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
+ }
0 commit comments