Skip to content

Commit f792104

Browse files
committed
went back to global variables for parts, fixed pause/power button issue, added place for settings menu, added theme toggle
1 parent 54dbe19 commit f792104

4 files changed

Lines changed: 173 additions & 33 deletions

File tree

src/main/kotlin/io/github/chip8k/Chip8.kt

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,18 @@ import java.io.InputStream
77

88

99
var running = false
10+
var paused = false
1011
lateinit var loadedRom: ByteArray
12+
val cpu = Cpu()
1113
val settings = Settings()
14+
val gpu = Gpu()
15+
val keyHandler = KeyHandler()
16+
1217

1318
class Chip8 : Application() {
14-
private val cpu = Cpu()
15-
private val gpu = Gpu()
16-
private val keyHandler = KeyHandler()
1719

18-
override fun start(stage: Stage) {
19-
cpu.gpu = gpu
20-
cpu.keyHandler = keyHandler
21-
gpu.cpu = cpu
2220

21+
override fun start(stage: Stage) {
2322
stage.title = "CHIP-8K"
2423
stage.scene = gpu.scene
2524
stage.show()
@@ -37,7 +36,7 @@ class Chip8 : Application() {
3736

3837
override fun handle(now: Long) {
3938
if (now - lastUpdateTime >= settings.delayInNs) {
40-
if (running) {
39+
if (running && !paused) {
4140
gpu.handleLogs()
4241
gpu.updateDisplay()
4342
cpu.runCycle()

src/main/kotlin/io/github/chip8k/Cpu.kt

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,6 @@ class Cpu {
3939
)
4040
var log = ""
4141

42-
lateinit var gpu: Gpu
43-
lateinit var keyHandler: KeyHandler
44-
4542
//loads font into memory
4643
init {
4744
font.copyInto(memory, 0x50)

src/main/kotlin/io/github/chip8k/Gpu.kt

Lines changed: 66 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,12 @@ import javafx.scene.Scene
66
import javafx.scene.canvas.Canvas
77
import javafx.scene.control.Button
88
import javafx.scene.control.TextArea
9+
import javafx.scene.layout.Background
10+
import javafx.scene.layout.BackgroundFill
911
import javafx.scene.layout.GridPane
12+
import javafx.scene.layout.StackPane
1013
import javafx.scene.layout.VBox
14+
import javafx.scene.paint.Color
1115
import javafx.stage.FileChooser
1216
import java.io.File
1317

@@ -24,30 +28,30 @@ class Gpu {
2428
//buttons (4x6 grid)
2529
val keypadScreen = GridPane()
2630
//power and load another rom buttons
27-
val loadRomScreen = VBox(10.0)
31+
val menuScreen = VBox(10.0)
2832

29-
val root = GridPane()
30-
val scene = Scene(root)
33+
var buttons = emptyArray<Button>()
3134

32-
lateinit var cpu: Cpu
35+
val mainScreen = GridPane()
36+
val root = StackPane(mainScreen, settings.popup)
37+
val scene = Scene(root)
3338

3439
init {
35-
//log of opcodes that are going through
36-
opcodeTextArea.isEditable = false
37-
3840
//buttons (4x4 grid) (need to change the order of the buttons)
3941
for (y in 0 until 4) {
4042
for (x in 0 until 4) {
4143
val button = Button ((y * 4 + x).toString(16))
44+
buttons += button
4245
button.onAction = EventHandler {
4346
cpu.log(0, "pressed button " + (y * 4 + x).toString(16))
4447
}
4548
keypadScreen.add(button, x, y)
4649
}
4750
}
4851
//buttons
49-
loadRomScreen.alignment = Pos.CENTER
52+
menuScreen.alignment = Pos.CENTER
5053
val powerButton = Button("power")
54+
buttons += powerButton
5155
powerButton.onAction = EventHandler {
5256
if (running) {
5357
cpu.log(0, "powering off")
@@ -63,18 +67,12 @@ class Gpu {
6367
}
6468

6569
val pauseButton = Button("toggle pause")
70+
buttons += pauseButton
6671
pauseButton.onAction = EventHandler {
67-
if (running) {
68-
cpu.log(0, "emulation paused")
69-
handleLogs()
70-
running = false
71-
}
72-
else {
73-
cpu.log(0, "emulation resumed")
74-
running = true
75-
}
72+
togglePause()
7673
}
7774
val loadRomButton = Button("load rom")
75+
buttons += loadRomButton
7876
loadRomButton.onAction = EventHandler {
7977
cpu.log(0, "loading another rom")
8078

@@ -93,15 +91,29 @@ class Gpu {
9391
}
9492

9593
val settingsButton = Button("settings")
94+
buttons += settingsButton
9695
settingsButton.onAction = EventHandler {
96+
settings.showPopup()
97+
}
9798

99+
val toggleThemeButton = Button("toggle theme")
100+
buttons += toggleThemeButton
101+
toggleThemeButton.onAction = EventHandler {
102+
if (settings.colours.first == Color.WHITE) {
103+
settings.colours = Pair(Color.BLACK, Color.WHITE)
104+
} else {
105+
settings.colours = Pair(Color.WHITE, Color.BLACK)
106+
}
107+
settings.flipStops()
108+
updateAllGraphics()
98109
}
99-
loadRomScreen.children.addAll(powerButton, loadRomButton, pauseButton, settingsButton)
110+
menuScreen.children.addAll(powerButton, loadRomButton, pauseButton, settingsButton, toggleThemeButton)
100111

101-
root.add(screen, 0, 0)
102-
root.add(opcodeTextArea, 0, 1)
103-
root.add(keypadScreen, 1, 0)
104-
root.add(loadRomScreen, 1, 1)
112+
updateAllGraphics()
113+
mainScreen.add(screen, 0, 0)
114+
mainScreen.add(opcodeTextArea, 0, 1)
115+
mainScreen.add(keypadScreen, 1, 0)
116+
mainScreen.add(menuScreen, 1, 1)
105117
}
106118
fun draw(x: Int, y: Int, height: Int) {
107119
cpu.v[0xF] = 0.toByte() //collision register defaults to off
@@ -144,4 +156,36 @@ class Gpu {
144156
opcodeTextArea.appendText(cpu.log + "\n")
145157
opcodeTextArea.scrollTop = scrollTop // Restore the previous vertical scroll position
146158
}
159+
160+
fun togglePause() {
161+
if (!paused) {
162+
cpu.log(0, "emulation paused")
163+
handleLogs()
164+
paused = true
165+
}
166+
else {
167+
cpu.log(0, "emulation resumed")
168+
paused = false
169+
}
170+
}
171+
172+
fun updateAllGraphics() {
173+
mainScreen.background = Background(BackgroundFill(settings.colours.second, null, null))
174+
opcodeTextArea.style = """
175+
-fx-control-inner-background: rgb(
176+
${settings.colours.second.red * 255},
177+
${settings.colours.second.green * 255},
178+
${settings.colours.second.blue * 255});
179+
180+
-fx-text-fill: rgb(
181+
${settings.colours.first.red * 255},
182+
${settings.colours.first.green * 255},
183+
${settings.colours.first.blue * 255});
184+
""".trimIndent()
185+
for (button in buttons) {
186+
button.background = Background(BackgroundFill(settings.gradient, null, null))
187+
button.textFill = settings.colours.second
188+
}
189+
updateDisplay()
190+
}
147191
}
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,119 @@
11
package io.github.chip8k
22

3+
import javafx.animation.TranslateTransition
4+
import javafx.event.EventHandler
5+
import javafx.geometry.Pos
6+
import javafx.scene.layout.Pane
7+
import javafx.scene.layout.VBox
38
import javafx.scene.paint.Color
9+
import javafx.scene.paint.RadialGradient
10+
import javafx.scene.paint.Stop
11+
import javafx.scene.control.Button
12+
import javafx.scene.layout.Background
13+
import javafx.scene.layout.BackgroundFill
14+
import javafx.scene.layout.GridPane
15+
import javafx.scene.shape.Rectangle
16+
import javafx.util.Duration
417

518
class Settings {
619
var scale = 10.0
720
var colours = Pair(Color.WHITE, Color.BLACK)
821
var fps = 60
922
var delayInNs = (1_000_000_000 / fps).toInt()
1023

24+
// Create a list of Stop objects for the gradient
25+
var stops = mutableListOf<Stop>(
26+
Stop(0.0, colours.first),
27+
Stop(0.5, colours.second)
28+
)
29+
30+
fun flipStops() {
31+
stops = mutableListOf<Stop>(
32+
Stop(0.0, colours.first),
33+
Stop(0.5, colours.second)
34+
)
35+
36+
gradient = RadialGradient(
37+
0.0, 0.0, // focusAngle, focusDistance
38+
0.5, 0.5, // centerX, centerY
39+
1.25, // radius
40+
true, // proportional
41+
null, // cycleMethod
42+
stops
43+
)
44+
}
45+
46+
// Create a RadialGradient
47+
var gradient = RadialGradient(
48+
0.0, 0.0, // focusAngle, focusDistance
49+
0.5, 0.5, // centerX, centerY
50+
1.25, // radius
51+
true, // proportional
52+
null, // cycleMethod
53+
stops
54+
)
55+
56+
var popup = createPopupPane()
57+
1158
fun reset() {
1259
scale = 10.0
1360
colours = Pair(Color.WHITE, Color.BLACK)
1461
fps = 60
1562
delayInNs = (1_000_000_000 / fps).toInt()
1663
}
1764

65+
private fun createPopupPane(): GridPane {
66+
val popupWidth = 200.0
67+
//val popupHeight = scene.height
68+
val popup = GridPane()
69+
popup.prefWidth = popupWidth
70+
//popup.prefHeight = popupHeight
71+
popup.background = Background(BackgroundFill(colours.second, null, null))
72+
73+
// Add some content to the popup
74+
val content = VBox(10.0)
75+
content.alignment = Pos.CENTER
76+
val rectangle = Rectangle(50.0, 50.0, Color.BLUE)
77+
val closeButton = Button("Close")
78+
closeButton.onAction = EventHandler {
79+
hidePopup()
80+
}
81+
val greyBackground = Pane()
82+
greyBackground.background = Background(BackgroundFill(Color.GRAY.deriveColor(0.0, 0.0, 0.0, 1.0), null, null))
83+
84+
content.children.addAll(rectangle, closeButton)
85+
86+
popup.add(content, 0, 0)
87+
popup.add(greyBackground, 1, 0)
88+
//popup.alignment = Pos.CENTER_LEFT
89+
slideOut(popup)
90+
return popup
91+
}
92+
93+
fun showPopup() {
94+
cpu.log(0, "settings opened, emulation paused")
95+
gpu.handleLogs()
96+
paused = true
97+
slideIn(popup)
98+
}
99+
100+
fun hidePopup() {
101+
cpu.log(0, "settings closed, emulation resumed")
102+
gpu.handleLogs()
103+
paused = false
104+
slideOut(popup)
105+
}
106+
107+
private fun slideIn(pane: Pane, targetX: Double = 0.0) {
108+
val transition = TranslateTransition(Duration.millis(500.0), pane)
109+
transition.toX = targetX
110+
transition.play()
111+
}
112+
113+
private fun slideOut(pane: Pane, targetX: Double = 1000.0) {
114+
val transition = TranslateTransition(Duration.millis(500.0), pane)
115+
transition.toX = targetX
116+
transition.play()
117+
}
18118

19119
}

0 commit comments

Comments
 (0)