1 # This file is part of NIT (http://www.nitlanguage.org).
3 # Copyright 2012-2014 Alexis Laferrière <alexis.laf@xymus.net>
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
9 # http://www.apache.org/licenses/LICENSE-2.0
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
19 # This is a minimal practical example of the mnit framework.
21 app_version
(1, 0, git_revision
)
22 app_name
("Crazy Groundhogs")
30 # A hole with a possible mole, or a trap in it
34 # Horizontal center of the hole
37 # Vertical center of the hole
40 # Half width of the hit box
43 # Height of the hit box
46 # Content (and state) of this hole
47 var content
: nullable HoleContent = null
49 # Time at witch this hole can act again
50 var timeout_until
: Float = app
.clock
.total
.to_f
is lazy
52 # Timeout for 1/2 sec or less with a higher score
53 private fun reset_timeout
do
54 timeout_until
= app
.clock
.total
.to_f
+
55 0.5 - 0.4 * (game
.points
.to_f
/ 1000.0).min
(1.0)
60 if timeout_until
> app
.clock
.total
.to_f
then return
63 if content
!= null then
64 if content
== game
.down
then
65 if (20.0*game
.speed_modifier
).to_i
.rand
== 0 then
70 else if (80.0*game
.speed_modifier
).to_i
.rand
== 0 then
75 else if (100.0*game
.speed_modifier
).to_i
.rand
== 0 then
81 # Get next `HoleContent` to pop
82 fun to_pop
: HoleContent
84 # show traps only at 10 points and up
85 if game
.points
> 10 then
87 # After 50 points we have more and more traps until point 1000
88 var d
= 1250-(game
.points
- 50)
89 if d
< 200 then d
= 200
91 if d
.rand
< 100 then return game
.trap
97 # Does this hole intercepts `event`?
98 fun intercepts
(event
: PointerEvent): Bool
100 if content
== null then return false
102 var dx
= (dx
*display_scale
).to_i
103 var dy
= (dy
*display_scale
).to_i
104 var ex
= event
.x
.to_i
- display_offset_x
105 var ey
= event
.y
.to_i
- display_offset_y
106 return ex
> x
- dx
and ex
< x
+ dx
and
107 ey
> y
- dy
and ey
< y
110 # Draw this hole and content to `display`
111 fun draw
(display
: Display)
114 var img
= app
.assets
.empty
115 var dx
= 300.0*display_scale
116 var dy
= 256.0*display_scale
117 img
.scale
= display_scale
118 display
.blit
(img
, x-dx
.to_i
+display_offset_x
, y-dy
.to_i
+display_offset_y
)
120 # The mole in the hole, or other content
121 var content
= self.content
122 if content
!= null then
123 content
.draw
(display
, x
, y
)
128 # Content of a `Hole`
133 # Offset of the horizontal center of the hole
136 # Offset of the vertical center of the hole
139 # Hit this hole content
140 fun hit
(game
: Game, hole
: Hole, event
: PointerEvent) do end
142 # Draw this content to `display`
143 fun draw
(display
: Display, x
, y
: Int)
145 img
.scale
= display_scale
147 x-dx
.to_i
+display_offset_x
,
148 y-dy
.to_i
+display_offset_y
)
156 # Points value when hit
159 redef fun hit
(game
, hole
, event
)
162 hole
.content
= game
.down
166 # A trap held out of a hole
170 # Points penalty when hit
173 redef fun hit
(game
, hole
, event
)
175 game
.points
-= penalty
176 if game
.points
< 0 then game
.points
= 0
182 # All holes, filled or not
183 var holes
= new Array[Hole]
186 var modifier_half_life
= 1000.0
189 fun rows
: Int do return 4
192 fun columns
: Int do return 5
198 var speed_modifier
= 1.0
200 # Vertical offset between rows
201 var dist_between_rows
= 448
203 # Horizontal offset between columns
204 var dist_between_columns
= 600
206 # Global accumulation control, applied to `speed_modifier`
207 fun global_speed_modifier
: Float do return 2.0
210 var up
= new Mole(app
.assets
.up
, 212.0*display_scale
, 820.0*display_scale
, 1) is lazy
212 # A mole that was hit
213 var down
= new HoleContent(app
.assets
.hit
, 250.0*display_scale
, 512.0*display_scale
) is lazy
215 # A trap out of the hole
216 var trap
= new Trap(app
.assets
.trap
, 212.0*display_scale
, 830.0*display_scale
, 10) is lazy
220 var dx
= (dist_between_columns
.to_f
*display_scale
).to_i
221 var dy
= (dist_between_rows
.to_f
*display_scale
).to_i
222 for x
in [0 .. columns
[ do
223 for y
in [0 .. rows
[ do
224 holes
.add
(new Hole(self, x
*dx
, y
*dy
))
231 for hole
in holes
do hole
.do_turn
233 speed_modifier
= modifier_half_life
/ (modifier_half_life
+points
.to_f
) * global_speed_modifier
237 # Where all the UI stuff is done
240 var game
= new Game is lazy
242 fun do_frame
(display
: Display)
244 display
.clear
(0.0, 0.45, 0.0)
246 app
.assets
.sign_warning
.scale
= display_scale
247 display
.blit
(app
.assets
.sign_warning
, (380.0*display_scale
).to_i
, (256.0*display_scale
).to_i
)
249 app
.assets
.sign_cute
.scale
= display_scale
250 display
.blit
(app
.assets
.sign_cute
, (1024.0*display_scale
).to_i
, (64.0*display_scale
).to_i
)
252 for hole
in game
.holes
do
259 fun input
(event
: InputEvent): Bool
261 if event
isa PointerEvent then
262 for hole
in game
.holes
.reverse_iterator
do
263 if hole
.intercepts
(event
) then
264 var hole_content
= hole
.content
265 if hole_content
!= null then hole_content
.hit
(game
, hole
, event
)
274 # Draw the HUD as the topmost layer of the screen
275 fun draw_hud
(display
: Display)
277 var board
= app
.assets
.points_board
278 board
.scale
= display_scale
279 display
.blit
(board
, (32.0*display_scale
).to_i
, -10)
285 fun draw_score
(display
: Display, score
: nullable Int)
287 if score
== null then score
= game
.points
289 # Draw the score itself
290 for img
in app
.numbers
.imgs
do img
.scale
= display_scale
291 display
.blit_number
(app
.numbers
, score
,
292 (92.0*display_scale
).to_i
,
293 (172.0*display_scale
).to_i
)
300 var screen
= new Screen
302 # Image set generate by inkscape_tools
303 var assets
= new DrawingImages
305 # Numbers to display the score
306 var numbers
= new NumberImages(assets
.n
)
308 # Elapsed time since program launch
309 var clock
= new Clock
319 redef fun frame_core
(display
)
322 screen
.do_frame
(display
)
327 if ie
isa QuitEvent or
328 (ie
isa KeyEvent and ie
.to_c
== 'q') then
333 return screen
.input
(ie
)
338 fun display_scale
: Float do return 1.0
340 # Depends on the hole center in the uo image
341 fun display_offset_x
: Int do return (512.0*display_scale
).to_i
343 # Depends on the width of the holes
344 fun display_offset_y
: Int do return (1000.0*display_scale
).to_i