chingu 0.9rc7 → 0.9rc8

Sign up to get free protection for your applications and to get access to all the features.
@@ -30,7 +30,7 @@ class Stuff < GameState
30
30
  end
31
31
 
32
32
  def stop
33
- stop_timer(:name => :blink)
33
+ stop_timer(:blink)
34
34
  end
35
35
 
36
36
  def fast
@@ -9,11 +9,25 @@ include Chingu
9
9
  # GFXHelpers example - demonstrating Chingus GFX
10
10
  #
11
11
  class Game < Chingu::Window
12
+ @@number_of_game_states = 7
12
13
  def initialize
13
14
  super(640,400)
14
15
  self.input = {:space => :next_effect, :esc => :exit}
15
16
  self.caption = "Example of Chingus GFX Helpers"
16
-
17
+ load_game_states
18
+ end
19
+
20
+ def next_effect
21
+ @@number_of_game_states -= 1
22
+ if @@number_of_game_states == 0
23
+ load_game_states
24
+ @@number_of_game_states = 7
25
+ else
26
+ pop_game_state
27
+ end
28
+ end
29
+
30
+ def load_game_states
17
31
  push_game_state(Fill)
18
32
  push_game_state(FillRect)
19
33
  push_game_state(FillGradient)
@@ -22,15 +36,13 @@ class Game < Chingu::Window
22
36
  push_game_state(DrawCircle)
23
37
  push_game_state(Particles)
24
38
  end
25
-
26
- def next_effect
27
- pop_game_state
28
- end
29
39
  end
30
40
 
41
+
42
+
31
43
  class DrawCircle < Chingu::GameState
32
44
  def draw
33
- $window.caption = "circles and arcs (space to continue)"
45
+ $window.caption = "circles and arcs (press space to continue)"
34
46
  draw_circle(0, 0, 300, Color::RED)
35
47
  fill_circle($window.width, $window.height, 200, Color::RED)
36
48
 
@@ -44,14 +56,14 @@ end
44
56
 
45
57
  class Fill < Chingu::GameState
46
58
  def draw
47
- $window.caption = "fill (space to continue)"
59
+ $window.caption = "fill (press space to continue)"
48
60
  fill(Color::RED)
49
61
  end
50
62
  end
51
63
 
52
64
  class FillRect < Chingu::GameState
53
65
  def draw
54
- $window.caption = "fill_rect (space to continue)"
66
+ $window.caption = "fill_rect (press space to continue)"
55
67
  fill_rect([10,10,100,100], Color::WHITE)
56
68
  end
57
69
  end
@@ -63,7 +75,7 @@ class FillGradient < Chingu::GameState
63
75
  end
64
76
 
65
77
  def draw
66
- $window.caption = "fill_gradient (space to continue)"
78
+ $window.caption = "fill_gradient (press space to continue)"
67
79
  fill_gradient(:from => @pinkish, :to => @blueish, :orientation => :vertical)
68
80
  end
69
81
  end
@@ -74,7 +86,7 @@ class FillGradientMultipleColors < Chingu::GameState
74
86
  end
75
87
 
76
88
  def draw
77
- $window.caption = "fill_gradient with more than two colors (space to continue)"
89
+ $window.caption = "fill_gradient with more than two colors (press space to continue)"
78
90
  fill_gradient(:colors => @colors, :orientation => :horizontal)
79
91
  end
80
92
  end
@@ -86,7 +98,7 @@ class FillGradientRect < Chingu::GameState
86
98
  end
87
99
 
88
100
  def draw
89
- $window.caption = "fill_gradient with :rect-option (space to continue)"
101
+ $window.caption = "fill_gradient with :rect-option (press space to continue)"
90
102
  fill_gradient(:from => @color1, :to => @color2, :rect => [100,100,200,200], :orientation => :horizontal)
91
103
  end
92
104
  end
@@ -8,12 +8,20 @@ require 'rubygems' rescue nil
8
8
  $LOAD_PATH.unshift File.join(File.expand_path(__FILE__), "..", "..", "lib")
9
9
  require 'chingu'
10
10
  require 'texplay' # adds Image#get_pixel
11
+ require 'optparse'
11
12
 
12
13
  include Gosu
13
14
  include Chingu
14
15
 
16
+
15
17
  class Game < Chingu::Window
16
18
  def initialize
19
+ $debug = false
20
+ ARGV.each do |a|
21
+ if a == "-debug"
22
+ $debug = true
23
+ end
24
+ end
17
25
  super(1000,400,false)
18
26
  self.input = { :escape => :exit }
19
27
  retrofy
@@ -30,14 +38,18 @@ class Level < Chingu::GameState
30
38
 
31
39
  def initialize(options = {})
32
40
  super
33
-
34
- @parallax = Parallax.create(:rotation_center => :top_left, :zorder => 200)
35
- @parallax << { :image => "city2.png", :damping => 2, :zorder => 200}
36
- @parallax << { :image => "city1.png", :damping => 1, :zorder => 200}
37
- @player = Player.create(:x => 30, :y => 10)
41
+
42
+ @parallax = Parallax.create(:rotation_center => :top_left, :zorder => 0)
43
+ @parallax << { :image => "city2.png", :damping => 2, :zorder => 0}
44
+ @parallax << { :image => "city1.png", :damping => 1, :zorder => 1000}
45
+
46
+ @player = Player.create(:x => 30, :y => 10, :zorder=> 500)
38
47
 
39
48
  @bg1 = Color.new(0xFFCE28FF)
40
49
  @bg2 = Color.new(0xFF013E87)
50
+ @text = Text.create("Score:", :size => 20, :x => 30, :y => 370, :zorder => 1001) #initialize score string
51
+ @text1 = Text.create("0", :size => 20, :x => 90, :y => 370, :zorder => 1001) #initialize score value to 0
52
+
41
53
  end
42
54
 
43
55
  #
@@ -53,7 +65,7 @@ class Level < Chingu::GameState
53
65
  @player.y = 100
54
66
 
55
67
  @parallax.camera_x = 0
56
- @total_game_ticks = 100000
68
+ @total_game_ticks = 10000#100000
57
69
  @timer = 100
58
70
  @total_ticks = 0
59
71
  end
@@ -94,19 +106,183 @@ class Level < Chingu::GameState
94
106
  bullet.die
95
107
  if enemy.hit_by(bullet)
96
108
  @player.score += 20
109
+ @text1.destroy! #destroy old score
110
+ @text1 = Text.create(@player.score, :size => 20, :x => 90, :y => 370, :zorder => 1001 ) #update the new score
111
+
112
+ end
113
+ end
114
+
115
+ Bullet.each_bounding_circle_collision(EnemyPlane) do |bullet, enemy|
116
+ bullet.die
117
+ if enemy.hit_by(bullet)
118
+ @player.score += 20
119
+ @text1.destroy! #destroy old score
120
+ @text1 = Text.create(@player.score, :size => 20, :x => 90, :y => 370, :zorder => 1001 ) #update the new score
121
+
97
122
  end
98
123
  end
124
+
125
+ # clean up objects
126
+ game_objects.destroy_if { |object| object.outside_window? || object.color.alpha == 0 }
99
127
 
100
128
  @timer = @timer * 0.9999
101
129
  @total_ticks += 1
102
130
  if @total_ticks > @timer
103
- Enemy.create(:x => $window.width, :y => rand(300))
131
+ Enemy.create(:x => $window.width, :y => rand(300), :zorder => (rand(20) * 100))
104
132
  @total_ticks = 0
105
133
  end
106
-
107
- $window.caption = "City Battle! Player x/y: #{@player.x}/#{@player.y} - Score: #{@player.score} - FPS: #{$window.fps} - game objects: #{game_objects.size}"
134
+
135
+ if @player.score > 100
136
+ switch_game_state(Level2)
137
+ end
138
+
139
+ if($debug)
140
+ $window.caption = "City Battle! - Player x/y: #{@player.x}/#{@player.y} - Score: #{@player.score} - FPS: #{$window.fps} - game objects: #{game_objects.size}"
141
+ else
142
+ $window.caption = "City Battle! - Score: #{@player.score} - FPS: #{$window.fps} - game objects: #{game_objects.size}"
143
+ end
144
+ end
145
+ def draw
146
+ fill_gradient(:from => @bg2, :to => @bg1)
147
+ @parallax.draw
148
+ super
149
+ end
150
+ end
151
+
152
+
153
+ #
154
+ # GAME STATE: LEVEL
155
+ #
156
+ class Level2 < Chingu::GameState
157
+ has_trait :timer
158
+
159
+ def initialize(options = {})
160
+ super
161
+
162
+ @parallax = Parallax.create(:rotation_center => :top_left, :zorder => 0)
163
+ @parallax << { :image => "city1.png", :damping => 2, :zorder => 0}
164
+ @parallax << { :image => "city3.png", :damping => 1, :zorder => 1000}
165
+
166
+ @player = Player.create(:x => 30, :y => 10, :zorder=> 500)
167
+
168
+ @bg1 = Color.new(0xFFCE28FF)
169
+ @bg2 = Color.new(0xFF013E87)
170
+ @text = Text.create("Score:", :size => 20, :x => 30, :y => 370, :zorder => 1001) #initialize score string
171
+ @text1 = Text.create("0", :size => 20, :x => 90, :y => 370, :zorder => 1001) #initialize score value to 0
172
+
173
+
174
+ end
175
+
176
+ #
177
+ # This is called each time this GameState is switched/pushed/poped to.
178
+ #
179
+ def setup
180
+ # Remove all lingering game objects
181
+ Enemy.destroy_all
182
+ Bullet.destroy_all
183
+
184
+ @player.score = 0
185
+ @player.x = 10
186
+ @player.y = 100
187
+
188
+ @parallax.camera_x = 0
189
+ @total_game_ticks = 10000#100000
190
+ @timer = 100
191
+ @total_ticks = 0
192
+ end
193
+
194
+ #
195
+ # The foremost layer in our parallax scroller is the collidable terrain
196
+ #
197
+ def solid_pixel_at?(x, y)
198
+ begin
199
+ @parallax.layers.last.get_pixel(x, y)[3] != 0
200
+ rescue
201
+ puts "Error in get_pixel(#{x}, #{y})"
202
+ end
108
203
  end
109
204
 
205
+ def update
206
+ super
207
+
208
+ # Move the level forward by increasing the parallax-scrollers camera x-coordinate
209
+ @parallax.camera_x += 1.5
210
+
211
+ # Remove all objects outside screen
212
+ game_objects.destroy_if { |game_object| game_object.respond_to?("outside_window?") && game_object.outside_window? }
213
+
214
+ # Collide bullets with terrain
215
+ Bullet.select { |o| solid_pixel_at?(o.x, o.y)}.each { |o| o.die }
216
+
217
+ # Collide player with terrain
218
+ push_game_state(GameOver) if solid_pixel_at?(@player.x, @player.y)
219
+
220
+ # Collide player with enemies and enemy bullets
221
+ @player.each_bounding_circle_collision(Enemy) do |player, enemy|
222
+ enemy.die
223
+ push_game_state(GameOver)
224
+ end
225
+
226
+ # Collide player with enemies and enemy bullets
227
+ @player.each_bounding_circle_collision(EnemyPlane) do |player, enemy|
228
+ enemy.die
229
+ push_game_state(GameOver)
230
+ end
231
+
232
+ Bullet.each_bounding_circle_collision(Enemy) do |bullet, enemy|
233
+ bullet.die
234
+ if enemy.hit_by(bullet)
235
+ @player.score += 20
236
+ @text1.destroy! #destroy old score
237
+ @text1 = Text.create(@player.score, :size => 20, :x => 90, :y => 370, :zorder => 1001 ) #update the new score
238
+ end
239
+ end
240
+
241
+ Bullet.each_bounding_circle_collision(EnemyPlane) do |bullet, enemy|
242
+ bullet.die
243
+ if enemy.hit_by(bullet)
244
+ @player.score += 20
245
+ @text1.destroy! #destroy old score
246
+ @text1 = Text.create(@player.score, :size => 20, :x => 90, :y => 370, :zorder => 1001 ) #update the new score
247
+ end
248
+ end
249
+
250
+ Bullet.each_bounding_circle_collision(EnemyPlane) do |bullet, enemy|
251
+ bullet.die
252
+ if enemy.hit_by(bullet)
253
+ @player.score += 20
254
+ @text1.destroy! #destroy old score
255
+ @text1 = Text.create(@player.score, :size => 20, :x => 90, :y => 370, :zorder => 1001 ) #update the new score
256
+
257
+ end
258
+ end
259
+
260
+
261
+ @timer = @timer * 0.9999
262
+ @total_ticks += 1
263
+ if @total_ticks > @timer
264
+ @select=rand(2)
265
+ if @select==1
266
+ Enemy.create(:x => $window.width, :y => rand(300), :zorder => (rand(20) * 100))
267
+ else
268
+ EnemyPlane.create(:x => $window.width, :y => rand(300), :zorder => (rand(20) * 100))
269
+ end
270
+ @total_ticks = 0
271
+ end
272
+
273
+ if @player.score > 100
274
+ switch_game_state(Done)
275
+ end
276
+
277
+ # clean up objects
278
+ game_objects.destroy_if { |object| object.outside_window? || object.color.alpha == 0 }
279
+
280
+ if($debug)
281
+ $window.caption = "City Battle! - Player x/y: #{@player.x}/#{@player.y} - Score: #{@player.score} - FPS: #{$window.fps} - game objects: #{game_objects.size}"
282
+ else
283
+ $window.caption = "City Battle! - Score: #{@player.score} - FPS: #{$window.fps} - game objects: #{game_objects.size}"
284
+ end
285
+ end
110
286
  def draw
111
287
  fill_gradient(:from => @bg2, :to => @bg1)
112
288
  @parallax.draw
@@ -280,6 +456,8 @@ class Enemy < GameObject
280
456
  @black = Color.new(0xFF000000)
281
457
  @status == :default
282
458
 
459
+ @fireball_animation = Chingu::Animation.new(:file => media_path("fireball.png"), :size => [32,32])
460
+
283
461
  #
284
462
  # Cache explosion and shrapnel images (created with texplay, not recomended doing over and over each time)
285
463
  #
@@ -323,7 +501,19 @@ class Enemy < GameObject
323
501
  # Create some shrapnel-objects
324
502
  #
325
503
  Sound["explosion.wav"].play(0.3)
326
- Explosion.create(:x => @x, :y => @y, :image => @@explosion_image )
504
+
505
+ #Explosion.create(:x => @x, :y => @y, :image => @@explosion_image )
506
+ 5.times{ Chingu::Particle.create( :x => @x,
507
+ :y => @y,
508
+ :animation => @fireball_animation,
509
+ :scale_rate => +0.05,
510
+ :fade_rate => -10,
511
+ :rotation_rate => +1,
512
+ :mode => :default
513
+ )
514
+ @x -= @velocity
515
+ }
516
+
327
517
  5.times { Shrapnel.create(:x => @x, :y => @y, :image => @@shrapnel_image)}
328
518
 
329
519
  #
@@ -343,6 +533,103 @@ class Enemy < GameObject
343
533
  end
344
534
 
345
535
 
536
+ #
537
+ # OUR ENEMY Plane
538
+ #
539
+ class EnemyPlane < GameObject
540
+ has_traits :collision_detection, :timer
541
+ attr_reader :radius
542
+
543
+ def setup
544
+ @velocity = options[:velocity] || 2
545
+ @health = options[:health] || 100
546
+
547
+ @anim = Animation.new(:file => "media/enemy_plane.png", :size => [32,20], :delay => 100)
548
+ @image = @anim.first
549
+
550
+ @radius = 5
551
+ @black = Color.new(0xFF000000)
552
+ @status == :default
553
+
554
+ @fireball_animation = Chingu::Animation.new(:file => media_path("fireball.png"), :size => [32,32])
555
+
556
+ #
557
+ # Cache explosion and shrapnel images (created with texplay, not recomended doing over and over each time)
558
+ #
559
+ @@shrapnel_image ||= Shrapnel.create_image_for(self)
560
+ @@explosion_image ||= Explosion.create_image_for(self)
561
+ end
562
+
563
+ def hit_by(object)
564
+ return if @status == :dying
565
+
566
+ #
567
+ # During 20 millisecons, use Gosus :additive draw-mode, which here results in a white sprite
568
+ # Classic "hit by a bullet"-effect
569
+ #
570
+ during(20) { @mode = :additive; }.then { @mode = :default }
571
+
572
+ @health -= 20
573
+
574
+ if @health <= 0
575
+ die
576
+ return true
577
+ else
578
+ return false
579
+ end
580
+ end
581
+
582
+ def fire
583
+ EnemyBullet.create(:x => self.x, :y => self.y)
584
+ end
585
+
586
+ def die
587
+ #
588
+ # Make sure die() is only called once
589
+ #
590
+ return if @status == :dying
591
+ @status = :dying
592
+
593
+ #
594
+ # Play our explosion-sound file
595
+ # Create an explosion-object
596
+ # Create some shrapnel-objects
597
+ #
598
+ Sound["explosion.wav"].play(0.3)
599
+
600
+ #Explosion.create(:x => @x, :y => @y, :image => @@explosion_image )
601
+ 5.times{ Chingu::Particle.create( :x => @x,
602
+ :y => @y,
603
+ :animation => @fireball_animation,
604
+ :scale_rate => +0.05,
605
+ :fade_rate => -10,
606
+ :rotation_rate => +1,
607
+ :mode => :default
608
+ )
609
+ @x -= @velocity
610
+ }
611
+
612
+ 5.times { Shrapnel.create(:x => @x, :y => @y, :image => @@shrapnel_image)}
613
+
614
+ #
615
+ # During 200 ms, fade and scale image, then destroy it
616
+ #
617
+ @color = @black
618
+ @color.alpha = 50
619
+ during(200) { @factor_x += 0.5; @factor_y += 0.5; @x -= 1; @color.alpha -= 1}.then { self.destroy }
620
+ end
621
+
622
+ def update
623
+ return if @status == :dying
624
+
625
+ @image = @anim.next
626
+ @x -= @velocity
627
+ end
628
+ end
629
+
630
+
631
+
632
+
346
633
  #
347
634
  # GAME STATE: GAME OVER
348
635
  #
@@ -368,17 +655,14 @@ end
368
655
  # GAME STATE: GAME OVER
369
656
  #
370
657
  class Done < Chingu::GameState
371
- def initialize(options)
372
- @score = options[:score]
373
- end
374
-
658
+
375
659
  def setup
376
660
  @text = Text.create("You made it! Score #{@score} (ESC to quit, RETURN to try again!)", :size => 40, :x => 30, :y => 100)
377
661
  self.input = { :esc => :exit, :return => :try_again}
378
662
  end
379
663
 
380
664
  def try_again
381
- pop_game_state # pop back to our playing game state
665
+ switch_game_state(Level)
382
666
  end
383
667
  end
384
668