Skip to content

Commit 035aebc

Browse files
committed
experimenting with fxgl as lecture support
1 parent 10d30ca commit 035aebc

File tree

2 files changed

+298
-0
lines changed

2 files changed

+298
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,298 @@
1+
/*
2+
* The MIT License (MIT)
3+
*
4+
* FXGL - JavaFX Game Library
5+
*
6+
* Copyright (c) 2015-2017 AlmasB ([email protected])
7+
*
8+
* Permission is hereby granted, free of charge, to any person obtaining a copy
9+
* of this software and associated documentation files (the "Software"), to deal
10+
* in the Software without restriction, including without limitation the rights
11+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
* copies of the Software, and to permit persons to whom the Software is
13+
* furnished to do so, subject to the following conditions:
14+
*
15+
* The above copyright notice and this permission notice shall be included in
16+
* all copies or substantial portions of the Software.
17+
*
18+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24+
* SOFTWARE.
25+
*/
26+
27+
package sandbox
28+
29+
import com.almasb.fxgl.app.FXGL
30+
import com.almasb.fxgl.app.GameApplication
31+
import com.almasb.fxgl.asset.FXGLAssets
32+
import com.almasb.fxgl.input.UserAction
33+
import com.almasb.fxgl.settings.GameSettings
34+
import javafx.animation.ParallelTransition
35+
import javafx.animation.RotateTransition
36+
import javafx.animation.ScaleTransition
37+
import javafx.animation.TranslateTransition
38+
import javafx.application.Application
39+
import javafx.geometry.Insets
40+
import javafx.geometry.Pos
41+
import javafx.scene.Node
42+
import javafx.scene.Parent
43+
import javafx.scene.input.KeyCode
44+
import javafx.scene.layout.BorderPane
45+
import javafx.scene.layout.Pane
46+
import javafx.scene.layout.StackPane
47+
import javafx.scene.layout.VBox
48+
import javafx.scene.paint.Color
49+
import javafx.scene.shape.Line
50+
import javafx.scene.shape.Rectangle
51+
import javafx.scene.text.Font
52+
import javafx.scene.text.Text
53+
import javafx.util.Duration
54+
55+
/**
56+
*
57+
*
58+
* @author Almas Baimagambetov ([email protected])
59+
*/
60+
class LectureSample : GameApplication() {
61+
62+
override fun initSettings(settings: GameSettings) {
63+
with(settings) {
64+
width = 1920
65+
height = 1080
66+
isFullScreen = true
67+
isMenuEnabled = false
68+
isIntroEnabled = false
69+
isProfilingEnabled = false
70+
isCloseConfirmation = false
71+
}
72+
}
73+
74+
override fun initInput() {
75+
input.addAction(object : UserAction("Next") {
76+
override fun onActionBegin() {
77+
nextAction()
78+
}
79+
}, KeyCode.RIGHT)
80+
81+
input.addAction(object : UserAction("Prev") {
82+
override fun onActionBegin() {
83+
prevAction()
84+
}
85+
}, KeyCode.LEFT)
86+
87+
input.addAction(object : UserAction("Exit") {
88+
override fun onActionBegin() {
89+
pause()
90+
exit()
91+
}
92+
}, KeyCode.L)
93+
}
94+
95+
private val slides = arrayListOf<SlideView>()
96+
private var currentSlide = 0
97+
98+
override fun initGame() {
99+
addSlide("JavaFX Scene Graph", VBox())
100+
101+
addSlide("Outline", VBox(
102+
text("Scene Graph"),
103+
text("Key Terminology")
104+
))
105+
106+
addSlide("Scene Graph", VBox(
107+
sceneGraph()
108+
))
109+
110+
addSlide("Terminology", VBox(
111+
text("Translate"),
112+
text("Rotate"),
113+
text("Scale")
114+
))
115+
116+
addSlide("Translate", VBox(
117+
text("Translate along X, Y or Z axis by amount"),
118+
translateSlide()
119+
))
120+
121+
addSlide("Rotate", VBox(
122+
text("Rotate along X, Y or Z axis by angle"),
123+
rotateSlide()
124+
))
125+
126+
addSlide("Scale", VBox(
127+
text("Scale along X, Y or Z axis by amount"),
128+
scaleSlide()
129+
))
130+
131+
addSlide("Conclusion", VBox(
132+
text("Scene Graph"),
133+
text("Key Terminology")
134+
))
135+
136+
slides.forEachIndexed { i, slide ->
137+
if (i > 0)
138+
slide.translateX = width.toDouble()
139+
else
140+
gameScene.addUINode(slide)
141+
}
142+
}
143+
144+
private fun addSlide(title: String, content: Node) {
145+
slides.add(SlideView(title, content))
146+
}
147+
148+
private var animating = false
149+
150+
private fun nextAction() {
151+
if (animating)
152+
return
153+
154+
if (currentSlide < slides.size - 1) {
155+
val node = slides[currentSlide]
156+
val tt = TranslateTransition(Duration.seconds(0.5), node)
157+
tt.fromX = 0.0
158+
tt.toX = -width.toDouble()
159+
tt.setOnFinished { gameScene.removeUINode(node) }
160+
161+
currentSlide++
162+
163+
val tt2 = TranslateTransition(Duration.seconds(0.5), slides[currentSlide])
164+
tt2.fromX = width.toDouble()
165+
tt2.toX = 0.0
166+
167+
gameScene.addUINode(slides[currentSlide])
168+
169+
animating = true
170+
with(ParallelTransition(tt, tt2)) {
171+
setOnFinished { animating = false }
172+
play()
173+
}
174+
}
175+
}
176+
177+
private fun prevAction() {
178+
if (animating)
179+
return
180+
181+
if (currentSlide > 0) {
182+
val node = slides[currentSlide]
183+
val tt = TranslateTransition(Duration.seconds(0.5), slides[currentSlide])
184+
tt.fromX = 0.0
185+
tt.toX = width.toDouble()
186+
tt.setOnFinished { gameScene.removeUINode(node) }
187+
188+
currentSlide--
189+
190+
val tt2 = TranslateTransition(Duration.seconds(0.5), slides[currentSlide])
191+
tt2.fromX = -width.toDouble()
192+
tt2.toX = 0.0
193+
194+
gameScene.addUINode(slides[currentSlide])
195+
196+
animating = true
197+
with(ParallelTransition(tt, tt2)) {
198+
setOnFinished { animating = false }
199+
play()
200+
}
201+
}
202+
}
203+
204+
private fun translateSlide(): Node {
205+
val rect = Rectangle(120.0, 120.0, Color.BLUE)
206+
207+
val tt = TranslateTransition(Duration.seconds(3.5), rect)
208+
tt.toX = width / 3.0
209+
tt.isAutoReverse = true
210+
tt.cycleCount = Int.MAX_VALUE
211+
tt.play()
212+
213+
return rect
214+
}
215+
216+
private fun rotateSlide(): Node {
217+
val rect = Rectangle(120.0, 120.0, Color.BLUE)
218+
//rect.translateX = width / 2.0
219+
220+
val tt = RotateTransition(Duration.seconds(3.5), rect)
221+
tt.toAngle = 180.0
222+
tt.isAutoReverse = true
223+
tt.cycleCount = Int.MAX_VALUE
224+
tt.play()
225+
226+
return rect
227+
}
228+
229+
private fun scaleSlide(): Node {
230+
val rect = Rectangle(120.0, 120.0, Color.BLUE)
231+
//rect.translateX = width / 2.0
232+
233+
val tt = ScaleTransition(Duration.seconds(3.5), rect)
234+
tt.toX = 0.1
235+
tt.toY = 0.1
236+
tt.isAutoReverse = true
237+
tt.cycleCount = Int.MAX_VALUE
238+
tt.play()
239+
240+
return rect
241+
}
242+
243+
private fun sceneGraph(): Node {
244+
return assetLoader.loadTexture("scenegraph.jpg", 800.0, 800.0)
245+
// val pane = Pane()
246+
// pane.translateX = width / 2.0 - 350 / 2
247+
//
248+
// val node0 = GraphNode("Root (StackPane)")
249+
// val node1 = GraphNode("Branch (VBox)")
250+
// node1.translateY = 100.0
251+
//
252+
// pane.children.addAll(node0, Line(node0.translateX + 170, node0.translateY, node1.translateX + 170, node1.translateY), node1)
253+
//
254+
// return pane
255+
}
256+
}
257+
258+
class GraphNode(val nodeName: String) : StackPane() {
259+
init {
260+
val node = Rectangle(350.0, 50.0, null)
261+
node.arcWidth = 25.0
262+
node.arcHeight = 25.0
263+
node.stroke = Color.BLUE
264+
265+
val text = Text(nodeName)
266+
text.font = Font.font("Segoe UI", 36.0)
267+
268+
children.addAll(node, text)
269+
}
270+
}
271+
272+
// TODO: Slide data structure?
273+
// TODO: each view should have its own animation timeline
274+
// TODO: use scaling vs height hardcode?
275+
class SlideView(val title: String, val content: Node) : StackPane() {
276+
277+
init {
278+
setPrefSize(FXGL.getAppWidth().toDouble(), FXGL.getAppHeight().toDouble())
279+
280+
(content as VBox).alignment = Pos.CENTER
281+
282+
val root = VBox(prefHeight / 6, FXGL.getUIFactory().newText(title, Color.DARKBLUE, prefHeight / 12), content)
283+
root.alignment = Pos.CENTER
284+
root.padding = Insets(0.0, 10.0, 0.0, 10.0)
285+
286+
children.addAll(root)
287+
}
288+
}
289+
290+
fun text(content: String): Text {
291+
val text = FXGL.getUIFactory().newText(content, Color.BLACK, 42.0)
292+
text.font = Font.font("Segoe UI", FXGL.getAppHeight().toDouble() / 15.0)
293+
return text
294+
}
295+
296+
fun main(args: Array<String>) {
297+
Application.launch(LectureSample::class.java, *args)
298+
}
Loading

0 commit comments

Comments
 (0)