chingu 0.7.6.6 → 0.7.6.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. data/chingu.gemspec +9 -2
  2. data/examples/example11_animation.rb +2 -5
  3. data/examples/example17_gosu_tutorial.rb +2 -2
  4. data/examples/example18_animation_trait.rb +2 -2
  5. data/examples/example19_edit_viewport.rb +6 -3
  6. data/examples/example21.yml +283 -291
  7. data/examples/example21_sidescroller_with_edit.rb +22 -16
  8. data/examples/example22_text.rb +5 -1
  9. data/examples/example23_chipmunk.rb +25 -0
  10. data/examples/example3_parallax.rb +1 -0
  11. data/examples/example4_gamestates.rb +20 -5
  12. data/examples/game1.rb +13 -40
  13. data/lib/chingu.rb +2 -1
  14. data/lib/chingu/assets.rb +2 -2
  15. data/lib/chingu/basic_game_object.rb +1 -23
  16. data/lib/chingu/game_object.rb +21 -0
  17. data/lib/chingu/game_object_map.rb +96 -0
  18. data/lib/chingu/game_states/debug.rb +60 -14
  19. data/lib/chingu/game_states/edit.rb +5 -1
  20. data/lib/chingu/game_states/fade_to.rb +1 -1
  21. data/lib/chingu/helpers/input_client.rb +13 -5
  22. data/lib/chingu/helpers/input_dispatcher.rb +13 -8
  23. data/lib/chingu/helpers/options_setter.rb +33 -0
  24. data/lib/chingu/input.rb +5 -5
  25. data/lib/chingu/rect.rb +2 -0
  26. data/lib/chingu/text.rb +7 -9
  27. data/lib/chingu/traits/animation.rb +1 -0
  28. data/lib/chingu/traits/bounding_box.rb +1 -5
  29. data/lib/chingu/traits/bounding_circle.rb +1 -6
  30. data/lib/chingu/traits/effect.rb +4 -4
  31. data/lib/chingu/traits/retrofy.rb +1 -1
  32. data/lib/chingu/traits/sprite.rb +234 -0
  33. data/lib/chingu/traits/velocity.rb +22 -11
  34. data/lib/chingu/traits/viewport.rb +2 -2
  35. data/lib/chingu/viewport.rb +32 -21
  36. data/lib/chingu/window.rb +6 -5
  37. data/spec/chingu/helpers/options_setter_spec.rb +39 -0
  38. data/spec/spec_helper.rb +3 -0
  39. metadata +12 -5
@@ -26,11 +26,10 @@ class Example21 < GameState
26
26
 
27
27
  def setup
28
28
  self.input = { :escape => :exit, :e => :edit }
29
- self.viewport.game_area = [0, 0, 3000, 1000]
29
+ self.viewport.game_area = [0, 0, 3500, 2000]
30
30
 
31
- @droid = Droid.create(:x => 100, :y => 300)
32
- #@droid = Droid.create(:x => 2500, :y => 1200)
33
- #@droid = Droid.create(:x => 500, :y => 1500)
31
+ @droid = Droid.create(:x => 100, :y => 400)
32
+ #@droid = Droid.create(:x => 400, :y => 1300)
34
33
 
35
34
  load_game_objects
36
35
 
@@ -58,11 +57,14 @@ class Example21 < GameState
58
57
  def update
59
58
  super
60
59
 
61
- visible_blocks = Block.inside_viewport
60
+ visible_blocks = Block
62
61
 
63
- FireBall.each_collision(visible_blocks) do |fire_ball, block|
64
- fire_ball.destroy
65
- end
62
+ #
63
+ # Eating a lot of CPU cause our crude collision detection, just kill fireballs after 3 secs instead.
64
+ #
65
+ # FireBall.each_collision(visible_blocks) do |fire_ball, block|
66
+ # fire_ball.destroy
67
+ # end
66
68
 
67
69
  # Makes all saw pendle up and down between Y-coordinate 1000 - 1500
68
70
  # TODO: Not a very flexible sollution, how about setting out circle,rects,lines in editor..
@@ -78,9 +80,7 @@ class Example21 < GameState
78
80
 
79
81
  @droid.each_collision(Battery) do |player, battery|
80
82
  battery.die
81
- #after(3000) { push_game_state(GameFinished) }
82
83
  end
83
-
84
84
 
85
85
  self.viewport.center_around(@droid)
86
86
 
@@ -153,15 +153,19 @@ class Droid < Chingu::GameObject
153
153
  end
154
154
 
155
155
  def move(x,y)
156
- @x += x
157
- self.each_collision(Block.inside_viewport) do |me, stone_wall|
158
- me.x = previous_x
156
+ self.x += x
157
+ self.each_collision(Block) do |me, stone_wall|
158
+ self.x = previous_x
159
+ break
159
160
  end
161
+
162
+ self.y += y
160
163
  end
161
164
 
162
- def update
165
+ def update
163
166
  @image = @animation.next
164
- self.each_collision(Block.inside_viewport) do |me, stone_wall|
167
+
168
+ self.each_collision(Block) do |me, stone_wall|
165
169
  if self.velocity_y < 0 # Hitting the ceiling
166
170
  me.y = stone_wall.bb.bottom + me.image.height * self.factor_y
167
171
  self.velocity_y = 0
@@ -217,7 +221,7 @@ end
217
221
  # A FIREBALL
218
222
  #
219
223
  class FireBall < GameObject
220
- traits :velocity, :collision_detection
224
+ traits :velocity, :collision_detection, :timer
221
225
  trait :bounding_circle, :scale => 0.7
222
226
 
223
227
  def setup
@@ -228,6 +232,7 @@ class FireBall < GameObject
228
232
  self.velocity_y = 1
229
233
  self.zorder = 200
230
234
  self.rotation_center = :center
235
+ after(3000) { self.destroy }
231
236
  end
232
237
 
233
238
  def update
@@ -288,6 +293,7 @@ class Block < GameObject
288
293
 
289
294
  def setup
290
295
  @image = Image["black_block.png"]
296
+ @color = Color.new(0xff808080)
291
297
  end
292
298
  end
293
299
 
@@ -29,7 +29,11 @@ class Woff < GameState
29
29
 
30
30
  #
31
31
  # TODO: More text examples!
32
- #
32
+ #
33
+
34
+ t = Text.create("Scaletest", :x => 10, :y => 100)
35
+ t.factor_x = 2
36
+ t.factor_y = 1
33
37
  end
34
38
 
35
39
  def draw
@@ -0,0 +1,25 @@
1
+ #!/usr/bin/env ruby
2
+ require 'rubygems'
3
+ require File.join(File.dirname($0), "..", "lib", "chingu")
4
+ include Gosu
5
+ include Chingu
6
+
7
+
8
+ class Game < Chingu::Window
9
+ def initialize
10
+ super(640,480,false) # leave it blank and it will be 800,600,non fullscreen
11
+ self.input = { :escape => :exit } # exits example on Escape
12
+
13
+ Player.create(:x => 0, :y => 0, :rotation_center => :top_left)
14
+ end
15
+ end
16
+
17
+ class Player < BasicGameObject
18
+ trait :sprite, :image => "spaceship.png"
19
+
20
+ def setup
21
+ end
22
+ end
23
+
24
+
25
+ Game.new.show
@@ -16,6 +16,7 @@ class Game < Chingu::Window
16
16
  end
17
17
 
18
18
  class Scroller < Chingu::GameState
19
+
19
20
  def initialize(options)
20
21
  super
21
22
  @text_color = Color.new(0xFF000000)
@@ -114,12 +114,17 @@ class Level < Chingu::GameState
114
114
  super
115
115
  @title = Chingu::Text.create(:text=>"Level #{options[:level].to_s}. P: pause R:restart", :x=>20, :y=>10, :size=>30)
116
116
  @player = Player.create
117
- @player.input = { :holding_left => :move_left,
118
- :holding_right => :move_right,
119
- :holding_up => :move_up,
120
- :holding_down => :move_down,
121
- :space => :fire}
122
117
 
118
+ #
119
+ # The below code can mostly be replaced with the use of method "holding?" in Level#update
120
+ # Using holding? in update could be good if you need fine grained controll over when input is dispatched.
121
+ #
122
+ @player.input = { :holding_left => :move_left,
123
+ :holding_right => :move_right,
124
+ :holding_up => :move_up,
125
+ :holding_down => :move_down,
126
+ :space => :fire }
127
+
123
128
  #
124
129
  # The input-handler understands gamestates. P is pressed --> push_gamegate(Pause)
125
130
  # You can also give it Procs/Lambdas which it will execute when key is pressed.
@@ -129,6 +134,16 @@ class Level < Chingu::GameState
129
134
 
130
135
  def update
131
136
  super
137
+
138
+ #
139
+ # Another way of checking input
140
+ #
141
+ # @player.move_left if holding?(:left, :a)
142
+ # @player.move_right if holding?(:right, :d)
143
+ # @player.move_up if holding?(:up, :w)
144
+ # @player.move_down if holding?(:down, :s)
145
+ # @player.fire if holding?(:space)
146
+
132
147
  Bullet.destroy_if {|bullet| bullet.outside_window? }
133
148
  $window.caption = "FPS: #{$window.fps} - GameObjects: #{game_objects.size} - Bullets: #{Bullet.size}"
134
149
  end
@@ -1,27 +1,21 @@
1
1
  #!/usr/bin/env ruby
2
2
  #
3
3
  #
4
- # A "full" simple game in Chingu, using GameState, GameObject, Paralaxx, has_traits etc
4
+ # A simple game in Chingu, using GameState, GameObject, Paralaxx, has_traits etc
5
5
  #
6
- # TODO: clean up code as Chingu moves along :). Comments. Get it working ;).
7
- #
8
6
  #
9
7
  require 'rubygems'
10
8
  require File.join(File.dirname($0), "..", "lib", "chingu")
11
9
  require 'texplay' # adds Image#get_pixel
12
- #require 'opengl' # adds raw gl stuff so Image#retrofy works (in some setups this seems to be 'gl')
13
10
 
14
11
  include Gosu
15
12
  include Chingu
16
13
 
17
- class Game < Chingu::Window
18
- #attr_reader :factor
19
-
14
+ class Game < Chingu::Window
20
15
  def initialize
21
16
  super(1000,400,false)
22
17
  self.input = { :escape => :exit }
23
- self.factor = 1
24
- Gosu::enable_undocumented_retrofication
18
+ retrofy
25
19
  switch_game_state(Level)
26
20
  end
27
21
  end
@@ -37,12 +31,8 @@ class Level < Chingu::GameState
37
31
  super
38
32
 
39
33
  @parallax = Parallax.create(:rotation_center => :top_left)
40
- #@parallax = Parallax.create(:rotation_center => :center)
41
- @parallax << { :image => "city2.png", :damping => 2}#, :factor => $window.factor }
42
- @parallax << { :image => "city1.png", :damping => 1}#, :factor => $window.factor }
43
- #@parallax.x = $window.width / 2
44
- #@parallax.y = $window.height / 2
45
-
34
+ @parallax << { :image => "city2.png", :damping => 2}
35
+ @parallax << { :image => "city1.png", :damping => 1}
46
36
  @player = Player.create(:x => 30, :y => 10)
47
37
 
48
38
  @bg1 = Color.new(0xFFCE28FF)
@@ -71,13 +61,8 @@ class Level < Chingu::GameState
71
61
  # The foremost layer in our parallax scroller is the collidable terrain
72
62
  #
73
63
  def solid_pixel_at?(x, y)
74
- begin
75
- #pixel = @parallax.layers.last.get_pixel(x/$window.factor, y/$window.factor)
76
- #return false if pixel.nil?
77
- #return
78
-
79
- @parallax.layers.last.get_pixel(x * $window.factor, y * $window.factor)[3] != 0
80
- #@parallax.layers.last.get_pixel(x, y)[3] != 0
64
+ begin
65
+ @parallax.layers.last.get_pixel(x, y)[3] != 0
81
66
  rescue
82
67
  puts "Error in get_pixel(#{x}, #{y})"
83
68
  end
@@ -96,7 +81,7 @@ class Level < Chingu::GameState
96
81
  Bullet.all.select { |o| solid_pixel_at?(o.x, o.y)}.each { |o| o.die }
97
82
 
98
83
  # Collide player with terrain
99
- #push_game_state(GameOver) if solid_pixel_at?(@player.x, @player.y)
84
+ push_game_state(GameOver) if solid_pixel_at?(@player.x, @player.y)
100
85
 
101
86
  # Collide player with enemies and enemy bullets
102
87
  @player.each_bounding_circle_collision(Enemy) do |player, enemy|
@@ -117,9 +102,7 @@ class Level < Chingu::GameState
117
102
  Enemy.create(:x => $window.width, :y => rand(300))
118
103
  @total_ticks = 0
119
104
  end
120
-
121
- #push_game_state(Done.new(:score => @player.score)) if @game_steps == 1
122
-
105
+
123
106
  $window.caption = "City Battle! Player x/y: #{@player.x}/#{@player.y} - Score: #{@player.score} - FPS: #{$window.fps} - game objects: #{game_objects.size}"
124
107
  end
125
108
 
@@ -134,14 +117,13 @@ end
134
117
  #
135
118
  class Player < GameObject
136
119
  has_traits :velocity, :collision_detection, :timer
137
- has_trait :bounding_circle, :scale => 0.50, :debug => true
120
+ has_trait :bounding_circle, :scale => 0.50, :debug => false
138
121
  attr_accessor :score
139
122
 
140
123
  def setup
141
124
  @image = Image["plane.png"]
142
- #self.factor = $window.factor
143
125
 
144
- self.input = {
126
+ self.input = {
145
127
  :holding_left => :left,
146
128
  :holding_right => :right,
147
129
  :holding_up => :up,
@@ -179,8 +161,8 @@ class Player < GameObject
179
161
  self.velocity_y *= 0.6
180
162
  self.velocity_x *= 0.6
181
163
 
182
- @x = @last_x if @x < 0 || @x > $window.width#/$window.factor
183
- @y = @last_y if @y < 0 || @y > $window.height#/$window.factor
164
+ @x = @last_x if @x < 0 || @x > $window.width
165
+ @y = @last_y if @y < 0 || @y > $window.height
184
166
  @last_x, @last_y = @x, @y
185
167
  end
186
168
 
@@ -195,7 +177,6 @@ class Bullet < GameObject
195
177
 
196
178
  def setup
197
179
  @image = Image["bullet.png"]
198
- #self.factor = $window.factor
199
180
  self.velocity_x = 10
200
181
  @status = :default
201
182
  @radius = 3
@@ -208,10 +189,6 @@ class Bullet < GameObject
208
189
  during(50) { @factor_x += 1; @factor_y += 1; @x -= 1; }.then { self.destroy }
209
190
  end
210
191
 
211
- #def update
212
- #return if @status == :dying
213
- #@x += self.velocity_x
214
- #end
215
192
  end
216
193
 
217
194
  #
@@ -238,7 +215,6 @@ class Explosion < GameObject
238
215
  @image = @@image.dup if @image.nil?
239
216
 
240
217
  self.rotation_center = :center
241
- #self.factor = options[:factor] ? options[:factor] : $window.factor
242
218
  during(100) { self.alpha -= 30}.then { destroy }
243
219
  end
244
220
 
@@ -262,7 +238,6 @@ class Shrapnel < GameObject
262
238
  self.velocity_y = 4 - rand(10)
263
239
  self.acceleration_y = 0.2 # gravity = downards acceleration
264
240
  self.rotation_center = :center
265
- #self.factor = $window.factor
266
241
  @status = :default
267
242
  end
268
243
 
@@ -297,10 +272,8 @@ class Enemy < GameObject
297
272
  @health = options[:health] || 100
298
273
 
299
274
  @anim = Animation.new(:file => "media/saucer.png", :size => [32,13], :delay => 100)
300
- # @anim.retrofy
301
275
  @image = @anim.first
302
276
 
303
- #self.factor = $window.factor
304
277
  @radius = 5
305
278
  @black = Color.new(0xFF000000)
306
279
  @status == :default
@@ -33,8 +33,9 @@ require_all "#{CHINGU_ROOT}/chingu/traits"
33
33
  require_all "#{CHINGU_ROOT}/chingu"
34
34
 
35
35
  module Chingu
36
- VERSION = "0.7.6.6"
36
+ VERSION = "0.7.6.7"
37
37
 
38
38
  DEBUG_COLOR = Gosu::Color.new(0xFFFF0000)
39
39
  DEBUG_ZORDER = 9999
40
+ INFINITY = 1.0 / 0
40
41
  end
@@ -33,7 +33,7 @@ module Gosu
33
33
  include Chingu::NamedResource
34
34
 
35
35
  def self.autoload(name)
36
- ret = (path = find_file(name)) ? Gosu::Image.new($window, path, true) : nil
36
+ ret = (path = find_file(name)) ? Gosu::Image.new($window, path, false) : nil
37
37
  raise "Can't load image \"#{name}\"" if ret.nil?
38
38
  return ret
39
39
  end
@@ -55,4 +55,4 @@ module Gosu
55
55
  end
56
56
  end
57
57
  Sound = Sample # Gosu uses Sample, but Sound makes sense too.
58
- end
58
+ end
@@ -133,34 +133,13 @@ module Chingu
133
133
  @paused = false
134
134
  end
135
135
 
136
- #
137
- # Disable automatic calling of draw and draw_trait each game loop
138
- #
139
- def hide!
140
- @visible = false
141
- end
142
-
143
- #
144
- # Enable automatic calling of draw and draw_trait each game loop
145
- #
146
- def show!
147
- @visible = true
148
- end
149
-
150
136
  #
151
137
  # Returns true if paused
152
138
  #
153
139
  def paused?
154
140
  @paused == true
155
141
  end
156
-
157
- #
158
- # Returns true if visible (not hidden)
159
- #
160
- def visible?
161
- @visible == true
162
- end
163
-
142
+
164
143
  #
165
144
  # Empty placeholders to be overridden
166
145
  #
@@ -171,7 +150,6 @@ module Chingu
171
150
  def draw_trait; end
172
151
  def update; end
173
152
  def draw; end
174
-
175
153
 
176
154
  #
177
155
  # Returns an array with all objects of current class.
@@ -189,6 +189,27 @@ module Chingu
189
189
  @angle = value
190
190
  end
191
191
 
192
+ #
193
+ # Disable automatic calling of draw and draw_trait each game loop
194
+ #
195
+ def hide!
196
+ @visible = false
197
+ end
198
+
199
+ #
200
+ # Enable automatic calling of draw and draw_trait each game loop
201
+ #
202
+ def show!
203
+ @visible = true
204
+ end
205
+
206
+ #
207
+ # Returns true if visible (not hidden)
208
+ #
209
+ def visible?
210
+ @visible == true
211
+ end
212
+
192
213
 
193
214
  # Returns true if object is inside the game window, false if outside
194
215
  def inside_window?(x = @x, y = @y)
@@ -0,0 +1,96 @@
1
+ #--
2
+ #
3
+ # Chingu -- OpenGL accelerated 2D game framework for Ruby
4
+ # Copyright (C) 2009 ippa / ippa@rubylicio.us
5
+ #
6
+ # This library is free software; you can redistribute it and/or
7
+ # modify it under the terms of the GNU Lesser General Public
8
+ # License as published by the Free Software Foundation; either
9
+ # version 2.1 of the License, or (at your option) any later version.
10
+ #
11
+ # This library is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
+ # Lesser General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU Lesser General Public
17
+ # License along with this library; if not, write to the Free Software
18
+ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
+ #
20
+ #++
21
+
22
+ module Chingu
23
+ #
24
+ # ** This class is under heavy development, API will most likely change! **
25
+ #
26
+ # GameObjectMap can convert any set of game objects into a 2D-array for fast lookup
27
+ # You can set any gridsize with :grid, defaults to [32,32]. The smaller the grid the more memory it will eat.
28
+ #
29
+ # Basic usage:
30
+ # @map = GameObjectMap.new(:game_objects => TerrainObject.all, :grid => [32, 32])
31
+ # @map.at(100, 100) # returns one TerrainObject at x/y: 100/100
32
+ # @map.game_object(player) # returns one TerrainObject which collides with player.bounding_box
33
+ #
34
+ # ** This class is under heavy development, API will most likely change! **
35
+ #
36
+ class GameObjectMap
37
+ attr_reader :map
38
+
39
+ def initialize(options = {})
40
+ @game_objects = options[:game_objects]
41
+ @grid = options[:grid] || [32,32]
42
+ @debug = options[:debug]
43
+ create_map
44
+ end
45
+
46
+ #
47
+ # Creates a "tilemap" of game objects using @grid and @game_objects
48
+ # Useful for faster collision detection on a grid-based freeform map created with the Edit game state.
49
+ #
50
+ def create_map
51
+ @map = []
52
+ @game_objects.each do |game_object|
53
+ puts "#{game_object.class} @ #{game_object.x} / #{game_object.y}" if @debug
54
+
55
+ start_x = (game_object.bb.left / @grid[0]).to_i
56
+ stop_x = (game_object.bb.right / @grid[0]).to_i
57
+
58
+ (start_x .. stop_x).each do |x|
59
+ start_y = (game_object.bb.top / @grid[1]).to_i
60
+ stop_y = (game_object.bb.bottom / @grid[1]).to_i
61
+
62
+ @map[x] ||= []
63
+ (start_y .. stop_y).each do |y|
64
+ @map[x][y] = game_object
65
+ end
66
+ end
67
+ end
68
+ end
69
+
70
+ #
71
+ # Gets a game object from the array-map on a certain X/Y
72
+ #
73
+ def at(x, y)
74
+ lookup_x = (x / @grid[0]).to_i
75
+ lookup_y = (y / @grid[1]).to_i
76
+ @map[lookup_x][lookup_y] rescue nil
77
+ end
78
+
79
+ def from_game_object(game_object)
80
+ start_x = (game_object.bb.left / @grid[0]).to_i
81
+ stop_x = (game_object.bb.right / @grid[0]).to_i
82
+
83
+ (start_x .. stop_x).each do |x|
84
+ start_y = (game_object.bb.top / @grid[1]).to_i
85
+ stop_y = (game_object.bb.bottom / @grid[1]).to_i
86
+
87
+ (start_y .. stop_y).each do |y|
88
+ return @map[x][y] if @map[x] && @map[x][y]
89
+ end
90
+
91
+ end
92
+ return nil
93
+ end
94
+
95
+ end
96
+ end