1 # This file is part of NIT ( http://www.nitlanguage.org ).
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
7 # http://www.apache.org/licenses/LICENSE-2.0
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
18 intrude import geometry
::points_and_lines
19 import mnit
::opengles1
27 # Addition of `self` and `other`
28 fun +(other
: Pos): Pos do return new Pos(other
.x
+ x
, other
.y
+ y
)
31 redef class PointerEvent
33 fun to_pos
: Pos do return new Pos(x
, y
)
37 # Pretty alias to `pow`
38 private fun ^
(other
: Float): Float do return self.pow
(other
)
43 # Time of creation since (appropriate) app lauch
44 var created_at
: Float = app
.clock
.total
.to_f
46 # Is this effect dead?
49 # Time to live of this effect, in seconds
50 var ttl
: Float = ttl_base
+ ttl_rand
.rand
is lazy
52 # Time to live base value
53 private var ttl_base
: Float
55 # Variation range to add to `ttl_base`
56 private var ttl_rand
: Float
58 private fun update_and_draw
(display
: Display, t
: Float) do end
77 # Reduction in alpha value per seconds
80 redef fun update_and_draw
(display
, t
)
82 var dt
= t
- created_at
89 native_flash
(r
, g
, b
, a
, display
.width
.to_f
, display
.height
.to_f
)
92 private fun native_flash
(r
, g
, b
, a
, w
, h
: Float) `{
110 glEnableClientState(GL_VERTEX_ARRAY);
111 glEnableClientState(GL_COLOR_ARRAY);
114 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
116 glDisable(GL_DEPTH_TEST);
117 glDisable(GL_TEXTURE_2D);
119 glVertexPointer(3, GL_FLOAT, 0, coords);
120 glColorPointer(4, GL_FLOAT, 0, colors);
121 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
123 glDisableClientState(GL_VERTEX_ARRAY);
124 glDisableClientState(GL_COLOR_ARRAY);
127 if ((mnit_opengles_error_code = glGetError()) != GL_NO_ERROR) {
128 fprintf(stderr, "Error drawing: %i\n", mnit_opengles_error_code);
134 abstract class Particle
141 # Particle moving along a cubic Bézier curve
142 class CubicBezierParticle
145 # Points on this curve, from the start to the end with the handles in the middle
147 # Require: `points.length == 4`
148 var points
: Array[Pos]
150 redef fun update_and_draw
(display
, t
)
152 assert points
.length
== 4
154 var dt
= t
- created_at
158 var bx
= i
*i
*i
* points
[0].x
+ 3.0*i
*i
*p
* points
[1].x
+
159 3.0*i
*p
*p
* points
[2].x
+ p
*p
*p
*points
[3].x
160 var by
= i
*i
*i
* points
[0].y
+ 3.0*i
*i
*p
* points
[1].y
+
161 3.0*i
*p
*p
* points
[2].y
+ p
*p
*p
*points
[3].y
163 img
.scale
= display_scale
164 if display
isa Opengles1Display then display
.color
(1.0, 1.0, 1.0, p
)
165 display
.blit_centered
(img
, bx
, by
)
166 if display
isa Opengles1Display then display
.reset_color
168 if dt
> ttl
then dead
= true
172 # Particle falling like a feather
173 class FeatheryParticle
179 # Randomized variation so this particle is unique
180 var ddt
: Float = pi
.rand
182 # Direction: `-1.0` for left, `1.0` for right
183 var dir
: Float = if 2.rand
== 0 then -1.0 else 1.0
185 # Randomized variation on X
186 var ddx
: Float = (4.0 - 8.0.rand
)^
2.0
188 # Randomized variation on Y
189 var ddy
: Float = (12.0 - 24.0.rand
)^
2.0
191 redef fun update_and_draw
(display
, t
)
193 var dt
= t
- created_at
195 var dx
= ddx
+ 30.0*(dt
+ddt
).sin
197 var dy
= ddy
+ 20.0*dt
+ 16.0*(dt
*2.0+ddt
*2.0).cos
198 var pos
= from
+ new Pos(dx
, dy
)
200 if display
isa Opengles1Display then display
.color
(1.0, 1.0, 1.0, 5.0-5.0*dt
/ttl
)
201 display
.blit_centered
(img
, pos
.x
, pos
.y
)
202 if display
isa Opengles1Display then display
.reset_color
204 if dt
> ttl
then dead
= true
208 # Particles that start small then grow bigger and fade out
209 private class BlowUpParticle
212 # Origin/center of effect
215 redef fun update_and_draw
(display
, t
)
217 var dt
= t
- created_at
220 if display
isa Opengles1Display then display
.color
(1.0, 1.0, 1.0, 2.0-p
*2.0)
222 img
.scale
= p
*4.0*display_scale
223 display
.blit_centered
(img
, from
.x
, from
.y
)
225 if display
isa Opengles1Display then display
.reset_color
227 if dt
> ttl
then dead
= true
232 private var particles
= new Array[Particle]
233 private var flashes
= new Array[Flash]
235 redef fun draw_hud
(display
)
237 var t
= app
.clock
.total
.to_f
240 for particle
in particles
do particle
.update_and_draw
(display
, t
)
241 for particle
in particles
.reverse_iterator
do if particle
.dead
then
242 particles
.remove particle
246 for flash
in flashes
do flash
.update_and_draw
(display
, t
)
247 for flash
in flashes
.reverse_iterator
do if flash
.dead
then
254 private var score_center
= new Pos(48.0*display_scale
, 32.0*display_scale
) is lazy
255 private var score_entry
= new Pos(48.0*display_scale
, 256.0*display_scale
) is lazy
257 private var score_history
= new List[Int]
258 private var score_history_max_length
= 60
260 redef fun draw_score
(display
, score
)
262 # Use an history to smooth the score
263 score_history
.add game
.points
264 if score_history
.length
> score_history_max_length
then score_history
.shift
266 for h
in score_history
do sum
+= h
267 var avg
= sum
.to_f
/score_history
.length
.to_f
268 var d
= game
.points
.to_f
- avg
270 # Color the score according to positive or negative changes
283 if display
isa Opengles1Display then display
.color
(r
, g
, b
, 1.0)
285 # Draw the score itself
286 super(display
, avg
.to_i
)
288 if display
isa Opengles1Display then display
.reset_color
292 redef class HoleContent
293 # Add a `CubicBezierParticle` from `event` to the score box with `img`
294 private fun bezier_to_score
(img
: Image, event
: PointerEvent)
296 app
.screen
.particles
.add
new CubicBezierParticle(2.0, 0.0, img
,
297 [event
.to_pos
, event
.to_pos
+ new Pos(0.0, -128.0),
298 app
.screen
.score_entry
, app
.screen
.score_center
])
304 # Number of hair particles
305 private var n_hair_on_hit
= 20
307 redef fun hit
(game
, hole
, event
)
311 app
.assets
.hair
.scale
= display_scale
312 for i
in n_hair_on_hit
.times
do
313 app
.screen
.particles
.add
new FeatheryParticle(2.0, 2.0, app
.assets
.hair
, event
.to_pos
)
316 bezier_to_score
(app
.assets
.point
, event
)
317 app
.screen
.particles
.add
new BlowUpParticle(0.5, 0.0, app
.assets
.point
, event
.to_pos
)
322 # Image for `CubicBezierParticle` effect towards the score board
323 protected fun penalty_img
: Image do return app
.assets
.penalty_ten
325 # `Flash` effects on hit
326 protected fun flashes
: Array[Flash] do
327 return [new Flash(0.5, 0.0, 1.0, 0.0, 0.0, 0.5, 2.0)]
330 redef fun hit
(game
, hole
, event
)
334 bezier_to_score
(penalty_img
, event
)
335 app
.screen
.particles
.add
new BlowUpParticle(0.5, 0.0, penalty_img
, event
.to_pos
)
337 app
.screen
.flashes
.add_all flashes