chingu 0.5.5.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (75) hide show
  1. data.tar.gz.sig +0 -0
  2. data/History.txt +21 -0
  3. data/LICENSE +504 -0
  4. data/Manifest.txt +72 -0
  5. data/README.rdoc +588 -0
  6. data/Rakefile +19 -0
  7. data/benchmarks/README.txt +1 -0
  8. data/benchmarks/benchmark.rb +6 -0
  9. data/benchmarks/benchmark3.rb +23 -0
  10. data/benchmarks/benchmark4.rb +71 -0
  11. data/benchmarks/benchmark5.rb +91 -0
  12. data/benchmarks/benchmark6.rb +23 -0
  13. data/benchmarks/meta_benchmark.rb +67 -0
  14. data/benchmarks/meta_benchmark2.rb +39 -0
  15. data/chingu.gemspec +34 -0
  16. data/examples/example1.rb +37 -0
  17. data/examples/example10.rb +75 -0
  18. data/examples/example11.rb +51 -0
  19. data/examples/example12.rb +67 -0
  20. data/examples/example2.rb +115 -0
  21. data/examples/example3.rb +40 -0
  22. data/examples/example4.rb +175 -0
  23. data/examples/example5.rb +107 -0
  24. data/examples/example6.rb +57 -0
  25. data/examples/example7.rb +133 -0
  26. data/examples/example8.rb +109 -0
  27. data/examples/example9.rb +106 -0
  28. data/examples/media/Parallax-scroll-example-layer-0.png +0 -0
  29. data/examples/media/Parallax-scroll-example-layer-1.png +0 -0
  30. data/examples/media/Parallax-scroll-example-layer-2.png +0 -0
  31. data/examples/media/Parallax-scroll-example-layer-3.png +0 -0
  32. data/examples/media/background1.png +0 -0
  33. data/examples/media/fire_bullet.png +0 -0
  34. data/examples/media/fireball.png +0 -0
  35. data/examples/media/particle.png +0 -0
  36. data/examples/media/ruby.png +0 -0
  37. data/examples/media/spaceship.png +0 -0
  38. data/examples/media/stickfigure.bmp +0 -0
  39. data/examples/media/stickfigure.png +0 -0
  40. data/examples/media/video_games.png +0 -0
  41. data/lib/chingu.rb +32 -0
  42. data/lib/chingu/actor.rb +17 -0
  43. data/lib/chingu/animation.rb +142 -0
  44. data/lib/chingu/assets.rb +64 -0
  45. data/lib/chingu/basic_game_object.rb +132 -0
  46. data/lib/chingu/core_extensions.rb +53 -0
  47. data/lib/chingu/effects.rb +36 -0
  48. data/lib/chingu/fpscounter.rb +62 -0
  49. data/lib/chingu/game_object.rb +127 -0
  50. data/lib/chingu/game_object_list.rb +91 -0
  51. data/lib/chingu/game_state.rb +137 -0
  52. data/lib/chingu/game_state_manager.rb +284 -0
  53. data/lib/chingu/game_states/debug.rb +65 -0
  54. data/lib/chingu/game_states/fade_to.rb +91 -0
  55. data/lib/chingu/game_states/pause.rb +57 -0
  56. data/lib/chingu/gfx_helpers.rb +89 -0
  57. data/lib/chingu/helpers.rb +166 -0
  58. data/lib/chingu/inflector.rb +34 -0
  59. data/lib/chingu/input.rb +100 -0
  60. data/lib/chingu/named_resource.rb +254 -0
  61. data/lib/chingu/parallax.rb +83 -0
  62. data/lib/chingu/particle.rb +21 -0
  63. data/lib/chingu/rect.rb +612 -0
  64. data/lib/chingu/require_all.rb +133 -0
  65. data/lib/chingu/text.rb +56 -0
  66. data/lib/chingu/traits/collision_detection.rb +172 -0
  67. data/lib/chingu/traits/effect.rb +113 -0
  68. data/lib/chingu/traits/input.rb +38 -0
  69. data/lib/chingu/traits/retrofy.rb +53 -0
  70. data/lib/chingu/traits/rotation_center.rb +84 -0
  71. data/lib/chingu/traits/timer.rb +90 -0
  72. data/lib/chingu/traits/velocity.rb +67 -0
  73. data/lib/chingu/window.rb +170 -0
  74. metadata +162 -0
  75. metadata.gz.sig +1 -0
data/Manifest.txt ADDED
@@ -0,0 +1,72 @@
1
+ History.txt
2
+ LICENSE
3
+ Manifest.txt
4
+ README.rdoc
5
+ Rakefile
6
+ benchmarks/README.txt
7
+ benchmarks/benchmark.rb
8
+ benchmarks/benchmark3.rb
9
+ benchmarks/benchmark4.rb
10
+ benchmarks/benchmark5.rb
11
+ benchmarks/benchmark6.rb
12
+ benchmarks/meta_benchmark.rb
13
+ benchmarks/meta_benchmark2.rb
14
+ chingu.gemspec
15
+ examples/example1.rb
16
+ examples/example10.rb
17
+ examples/example11.rb
18
+ examples/example12.rb
19
+ examples/example2.rb
20
+ examples/example3.rb
21
+ examples/example4.rb
22
+ examples/example5.rb
23
+ examples/example6.rb
24
+ examples/example7.rb
25
+ examples/example8.rb
26
+ examples/example9.rb
27
+ examples/media/Parallax-scroll-example-layer-0.png
28
+ examples/media/Parallax-scroll-example-layer-1.png
29
+ examples/media/Parallax-scroll-example-layer-2.png
30
+ examples/media/Parallax-scroll-example-layer-3.png
31
+ examples/media/background1.png
32
+ examples/media/fire_bullet.png
33
+ examples/media/fireball.png
34
+ examples/media/particle.png
35
+ examples/media/ruby.png
36
+ examples/media/spaceship.png
37
+ examples/media/stickfigure.bmp
38
+ examples/media/stickfigure.png
39
+ examples/media/video_games.png
40
+ lib/chingu.rb
41
+ lib/chingu/actor.rb
42
+ lib/chingu/animation.rb
43
+ lib/chingu/assets.rb
44
+ lib/chingu/basic_game_object.rb
45
+ lib/chingu/core_extensions.rb
46
+ lib/chingu/effects.rb
47
+ lib/chingu/fpscounter.rb
48
+ lib/chingu/game_object.rb
49
+ lib/chingu/game_object_list.rb
50
+ lib/chingu/game_state.rb
51
+ lib/chingu/game_state_manager.rb
52
+ lib/chingu/game_states/debug.rb
53
+ lib/chingu/game_states/fade_to.rb
54
+ lib/chingu/game_states/pause.rb
55
+ lib/chingu/gfx_helpers.rb
56
+ lib/chingu/helpers.rb
57
+ lib/chingu/inflector.rb
58
+ lib/chingu/input.rb
59
+ lib/chingu/named_resource.rb
60
+ lib/chingu/parallax.rb
61
+ lib/chingu/particle.rb
62
+ lib/chingu/rect.rb
63
+ lib/chingu/require_all.rb
64
+ lib/chingu/text.rb
65
+ lib/chingu/traits/collision_detection.rb
66
+ lib/chingu/traits/effect.rb
67
+ lib/chingu/traits/input.rb
68
+ lib/chingu/traits/retrofy.rb
69
+ lib/chingu/traits/rotation_center.rb
70
+ lib/chingu/traits/timer.rb
71
+ lib/chingu/traits/velocity.rb
72
+ lib/chingu/window.rb
data/README.rdoc ADDED
@@ -0,0 +1,588 @@
1
+ = CHINGU
2
+ http://github.com/ippa/chingu/tree/master
3
+
4
+ DOCUMENTATION: http://rdoc.info/projects/ippa/chingu
5
+
6
+ Ruby 1.9.1 is recommended. Also works with 1.8.7+.
7
+
8
+ This is still a rather young project, core classes and naming can still change.
9
+
10
+ == INSTALL
11
+ gem sources -a http://gems.github.com
12
+ sudo gem install ippa-chingu
13
+
14
+
15
+ == DESCRIPTION
16
+ Game framework built on top of the OpenGL accelerated game lib Gosu.
17
+ It adds simple yet powerful game states, prettier input handling, deployment safe asset-handling, a basic re-usable game object and automation of common task.
18
+
19
+
20
+ == THE STORY
21
+ The last years I've dabbled around a lot with game development.
22
+ I've developed games in both Rubygame and Gosu. I've looked at gamebox.
23
+ Rubygame is a very capable framework with a lot of functionality (collision detection, very good event system etc). Gosu is way more minimalistic but also faster with OpenGL -acceleration. Gosu isn't likely to get much more complex since it does what it should do very well and fast.
24
+
25
+ After 10+ game prototypes and some finished smaller games I started to see patterns each time I started a new game. Making classes with x/y/image/other-parameters that I called update/draw on in the main loop.
26
+ This became the basic Chingu::GameObject which encapsulates Gosus "Image.draw_rot" and enables automatic updating/drawing through "game_objects".
27
+
28
+ There was always a huge big chunk of checking keyboard-events in the main loop.
29
+ Borrowing ideas from Rubygame this has now become @player.keyboard(:left => :move_left, :space => :fire ... etc.
30
+
31
+
32
+ == CORE OVERVIEW
33
+ Chingu consists of the following core classes / concepts:
34
+
35
+ === Chingu::Window
36
+ The main window, use it at you use Gosu::Window now. Calcs the framerate, takes care of states,
37
+ handles chingu-formated input, updates and draws BasicGameObject / GameObjects automaticly.
38
+ Available thoughout your source as $window (Yes, that's the only global Chingu has).
39
+
40
+ === Chingu::GameObject
41
+ Use this for all your in game objects. The player, the enemies, the bullets, the powerups, the loot laying around.
42
+ It's very reusable and doesn't contain any game-logic (that's up to you!). Only stuff to put it on screen a certain way.
43
+ If you do GameObject.create() instead of new() Chingu will keep save the object in the "game_object"-list for automatic updates/draws.
44
+ GameObjects also have the nicer Chingu input-mapping: @player.input = { :left => :move_left, :right => :move_right, :space => :fire}
45
+ Has either Chingu::Window or a Chingu::GameState as "parent".
46
+
47
+ === Chingu::BasicGameObject
48
+ For those who think GameObject is a too little fat, there's BasicGameObject (GameObject inherits from BasicGameObject).
49
+ BasicGameObject is just an empty frame (no x,y,image accessors or draw-logic) for you to build on.
50
+ It _can_ be extended with Chingus trait-system though. The new() vs create() behaivor of GameObject comes from BasicGameObject.
51
+ BasicGameObject#parent points to either $window or a game state and is automaticly set on creation time.
52
+
53
+ === Chingu::GameStateManager
54
+ Keeps track of the game states. Implements a stack-based system with push_game_state and pop_game_state.
55
+
56
+ === Chingu::GameState
57
+ A "standalone game loop" that can be activated and deactivated to control game flow.
58
+ A game state is very much like a main gosu window. You define update() and draw() in a gamestate.
59
+ It comes with 2 extras that main window doesn't have. #setup (called when activated) and #finalize (called when deactivated)
60
+
61
+ If using game states, the flow of draw/update/button_up/button_down is:
62
+ Chingu::Window --> Chingu::GameStateManager --> Chingu::GameState.
63
+ For example, inside game state Menu you call push_game_state(Level). When Level exists, it will go back to Menu.
64
+
65
+ === Traits
66
+ Traits are extensions (or plugins if you so will) to BasicGameObjects.
67
+ The aim is so encapsulate common behaivor into modules for easy inclusion in your game classes.
68
+ Making a trait is easy, just an ordinary module with the methods setup_trait(), update_trait() and/or draw_trait().
69
+ It currently has to be namespaced to Chingu::Traits for "has_trait" to work inside GameObject-classes.
70
+
71
+ == OTHER CLASSES / HELPERS
72
+
73
+ === Chingu::Text
74
+ Makes use of Gosu::Font more rubyish and powerful.
75
+ In it's core, another Chingu::GameObject + Gosu::Font.
76
+
77
+ === Chingu::Animation
78
+ Load and interact with tile-based animations. loop, bounce and access invidual frame(s) easily.
79
+ An "@image = @animation.next!" in your Player#update is usually enough to get you started!
80
+
81
+ === Chingu::Parallax
82
+ A class for easy paralaxxscrolling. See example3.rb for more.
83
+
84
+ === Various Helpers
85
+ Both $window and game states gets some new graphical helpers, currently only 3, but quite useful:
86
+
87
+ fill() # Fills whole window with color 'color'.
88
+ fill_rect() # Fills a given Rect 'rect' with Color 'color'
89
+ fill_gradient() # Fills window or a given rect with a gradient between two colors.
90
+
91
+ If you base your models on GameObject (or BasicGameObject) you get:
92
+ Enemy.all # Returns an Array of all Enemy-instances
93
+ Enemy.size # Returns the amount of Enemy-instances
94
+ Enemy.destroy_all # Destroys all Enemy-instances
95
+ Enemy.destroy_if(&block) # Destroy all objects for which &block returns true
96
+
97
+
98
+ == BASICS / EXAMPLES
99
+
100
+ === Chingu::Window
101
+ With Gosu the main window inherits from Gosu::Window. In Chingu we use Chingu::Window. It's a basic Gosu::Window with extra cheese on top of it. keyboard handling, automatic update/draw calls to all gameobjects, fps counting etc.
102
+
103
+ You're probably familiar with this very common Gosu pattern:
104
+
105
+ ROOT_PATH = File.dirname(File.expand_path(__FILE__))
106
+ class Game < Gosu::Window
107
+ def initialize
108
+ @player = Player.new
109
+ end
110
+
111
+ def update
112
+ if button_down? Button::KbLeft
113
+ @player.left
114
+ elsif button_down? Button::KbRight
115
+ @player.right
116
+ end
117
+
118
+ @player.update
119
+ end
120
+
121
+ def draw
122
+ @player.draw
123
+ end
124
+ end
125
+
126
+ class Player
127
+ attr_accessor :x,:y,:image
128
+ def initialize(options)
129
+ @x = options[:x]
130
+ @y = options[:y]
131
+ @image = Image.new(File.join(ROOT_PATH, "media", "player.png"))
132
+ end
133
+
134
+ def move_left
135
+ @x -= 1
136
+ end
137
+
138
+ def move_right
139
+ @x += 1
140
+ end
141
+
142
+ def draw
143
+ @image.draw(@x,@y,100)
144
+ end
145
+ end
146
+
147
+ Game.new.show # Start the Game update/draw loop!
148
+
149
+
150
+ Chingu doesn't change any fundamental concept of Gosu, but it will make the above code cleaner:
151
+
152
+ #
153
+ # We use Chingu::Window instead of Gosu::Window
154
+ #
155
+ class Game < Chingu::Window
156
+ def initialize
157
+ super # This is always needed if you want to take advantage of what chingu offers
158
+ #
159
+ # Player will automaticly be updated and drawn since it's a Chingu::GameObject
160
+ # You'll need your own Game#update/#draw after a while, but just put #super there and Chingu can do its thing.
161
+ #
162
+ @player = Player.create
163
+ @player.input = {:left => :move_left, :right => :move_right}
164
+ end
165
+ end
166
+
167
+ #
168
+ # If we create classes from Chingu::GameObject we get stuff for free.
169
+ # The accessors: image,x,y,zorder,angle,factor_x,factor_y,center_x,center_y,mode,update,draw
170
+ # You might recognize those from #draw_rot - http://www.libgosu.org/rdoc/classes/Gosu/Image.html#M000023
171
+ # And in it's core, that's what Chingu::GameObject is, an encapsulation of draw_rot with some extra cheese.
172
+ # For example, we get automatic calls to draw/update with Chingu::GameObject, which usually is what you want.
173
+ # You could stop this by doing: @player = Player.new(:draw => false, :update => false)
174
+ #
175
+ class Player < Chingu::GameObject
176
+ def initialize(options)
177
+ super(options.merge(:image => Image["player.png"])
178
+ end
179
+
180
+ def move_left
181
+ @x -= 1
182
+ end
183
+
184
+ def move_right
185
+ @x += 1
186
+ end
187
+ end
188
+
189
+ Game.new.show # Start the Game update/draw loop!
190
+
191
+ Roughly 50 lines became 26 more powerful lines. (you can do @player.angle = 100 for example)
192
+
193
+ If you've worked with Gosu for a while you're probably tired of passing around the window-parameter.
194
+ Chingu solves this (as has many other developers) with a global variable $window. Yes, globals are bad, but in this case it kinda makes sense. It's used under the hood in various places.
195
+
196
+ === Chingu::GameObject
197
+ This is our basic "game unit"-class, meaning most in game objects (players, enemies, bullets etc) should be inherited from Chingu::GameObject.
198
+ The basic ideas behind it are:
199
+
200
+ * Encapsulate only the very common basics that Most in game objects need
201
+ * Keep naming close to Gosu, but add smart convenient methods / shortcuts and a more rubyish feeling
202
+ * No game logic allowed in GameObject, since that's not likely to be useful for others.
203
+
204
+ I've chose to base it around Image#draw_rot. So basically all the arguments that you pass to draw_rot can be passed to GameObject#new when creating a new object, an example using almost all arguments would be:
205
+
206
+ #
207
+ # You probably recognize the arguments from http://www.libgosu.org/rdoc/classes/Gosu/Image.html#M000023
208
+ #
209
+ @player = Player.new(:image => Image["player.png"], :x=>100, :y=>100, :zorder=>100, :angle=>45, :factor_x=>10, :factor_y=>10, :center_x=>0, :center_y=>0)
210
+
211
+ #
212
+ # A shortcut for the above line would be
213
+ #
214
+ @player = Player.new(:image => Image["player.png"], :x=>100, :y=>100, :zorder=>100, :angle=>45, :factor=>10, :center=>0)
215
+
216
+ #
217
+ # I've tried doing sensible defaults:
218
+ # x/y = [middle of the screen] for super quick display where it should be easy in sight)
219
+ # angle = 0 (no angle by default)
220
+ # center_x/center_y = 0.5 (basically the center of the image will be drawn at x/y)
221
+ # factor_x/factor_y = 1 (no zoom by default)
222
+ #
223
+ @player = Player.new
224
+
225
+ #
226
+ # By default Chingu::Window calls update & draw on all GameObjects in it's own update/draw.
227
+ # If this is not what you want, use :draw and :update
228
+ #
229
+ @player = Player.new(:draw => false, :update => false)
230
+
231
+ === Input
232
+ One of the core things I wanted a more natural way of inputhandling.
233
+ You can define input -> actions on Chingu::Window, Chingu::GameState and Chingu::GameObject.
234
+ Like this:
235
+
236
+ #
237
+ # When left arrow is pressed, call @player.turn_left ... and so on.
238
+ #
239
+ @player.input = { :left => :turn_left, :right => :turn_right, :left => :halt_left, :right => :halt_right }
240
+
241
+
242
+ #
243
+ # In Gosu the equivalent would be:
244
+ #
245
+ def button_down(id)
246
+ @player.turn_left if id == Button::KbLeft
247
+ @player.turn_right if id == Button::KbRight
248
+ end
249
+
250
+ def button_up(id)
251
+ @player.halt_left if id == Button::KbLeft
252
+ @player.halt_right if id == Button::KbRight
253
+ end
254
+
255
+
256
+ Another more complex example:
257
+
258
+ #
259
+ # So what happens here?
260
+ #
261
+ # Pressing P would create an game state out of class Pause, cache it and activate it.
262
+ # Pressing ESC would call Play#close
263
+ # Holding down LEFT would call Play#move_left on every game iteration
264
+ # Holding down RIGHT would call Play#move_right on every game iteration
265
+ # Releasing SPACE would call Play#fire
266
+ #
267
+
268
+ class Play < Chingu::GameState
269
+ def initialize
270
+ self.input = { :p => Pause,
271
+ :escape => :close,
272
+ :holding_left => :move_left,
273
+ :holding_right => :move_right,
274
+ :released_space => :fire }
275
+ end
276
+ end
277
+ class Pause < Chingu::GameState
278
+ # pause logic here
279
+ end
280
+
281
+ In Gosu the above code would include code in button_up(), button_down() and a check for button_down?() in update().
282
+
283
+ Every symbol can be prefixed by either "released_" or "holding_" while no prefix at all defaults to pressed once.
284
+
285
+ So, why not :up_space or :release_space instead of :released_space?
286
+ +:up_space+ doesn't sound like english, :release_space sounds more like a command then an event.
287
+
288
+
289
+ Or +:hold_left+ or :down_left instead of :holding_left?
290
+ :holding_left sounds like something that's happening over a period of time, not a single trigger, which corresponds well to how it works.
291
+
292
+ And with the default :space => :something you would imagine that :something is called once. You press :space once, :something is executed once.
293
+
294
+
295
+ === GameState / GameStateManager
296
+ Chingu incorporates a basic push/pop game state system (as discussed here: http://www.gamedev.net/community/forums/topic.asp?topic_id=477320).
297
+
298
+ Game states is a way of organizing your intros, menus, levels.
299
+
300
+ Game states aren't complicated. In Chingu a GameState is a class that behaves mostly like your default Gosu::Window (or in our case Chingu::Window) game loop.
301
+
302
+
303
+ # A simple GameState-example
304
+ class Intro < Chingu::GameState
305
+
306
+ def update
307
+ # game logic here
308
+ end
309
+
310
+ def draw
311
+ # screen manipulation here
312
+ end
313
+
314
+ # Called when we enter the game state
315
+ def setup
316
+ @player.angle = 0 # point player upwards
317
+ end
318
+
319
+ # Called when we leave the game state
320
+ def finalize
321
+ push_game_state(Menu) # switch to game state "Menu"
322
+ end
323
+
324
+ end
325
+
326
+ Looks familiar yet?
327
+ You can activate the above game state in 2 ways
328
+
329
+ class Game < Chingu::Window
330
+ def initialize
331
+ #
332
+ # 1) Create a new Intro-object and activate it (pushing to the top).
333
+ # This version makes more sense if you want to pass parameters to the gamestate, for example:
334
+ # push_game_state(Level.new(:level_nr => 10))
335
+ #
336
+ push_game_state(Intro.new)
337
+
338
+ #
339
+ # 2) This leaves the actual object-creation to the game state manager.
340
+ # Intro#initialize() is called, then Intro#setup()
341
+ #
342
+ push_game_state(Intro)
343
+ end
344
+ end
345
+
346
+ Another example:
347
+
348
+ class Game < Chingu::Window
349
+ def initialize
350
+ #
351
+ # We start by pushing Menu to the game state stack, making it active as the only state on stack.
352
+ # :setup => :false which will skip setup() from being called (standard when switching to a new state)
353
+ #
354
+ push_game_state(Menu, :setup => false)
355
+
356
+ #
357
+ # We push another game state to the stack, Play. We now have 2 states, which active being first / active.
358
+ #
359
+ # :finalize => false will skip setup() from being called on game state
360
+ # that's being pushed down the stack, in this case Intro.setup().
361
+ #
362
+ push_game_state(Play, :finalize => false)
363
+
364
+ #
365
+ # This would remove Play state from the stack, going back to the Menu-state. But also:
366
+ # .. skipping the standard call to Menu#setup (the new game state)
367
+ # .. skipping the standard call to Play#finalize (the current game state)
368
+ #
369
+ # :setup => false can for example be useful when pop'ing a Pause game state. (see example4.rb)
370
+ #
371
+ pop_game_state(:setup => false, :finalize => :false)
372
+
373
+ #
374
+ # Replace the current game state with a new one.
375
+ # :setup and :finalize options are available here as well.
376
+ #
377
+ switch_game_state(Credits)
378
+ end
379
+ end
380
+
381
+ A GameState in Chingu is just a class with the following instance methods:
382
+
383
+ * initialize() - called only once with push_game_state(Intro) but every time with push_game_state(Intro.new)
384
+ * setup() - called each time the game state becomes active.
385
+ * button_down(id) - Called when a button is down
386
+ * button_up(id) - Called when a button is released
387
+ * update() - just as in your normal game loop, put your game logic here.
388
+ * draw() - just as in your normal game loop, put your screen manipulation here.
389
+ * finalize() - called when a game state de-activated (for example by pushing a new one on top with push_game_state)
390
+
391
+ Chingu::Window automatically creates a @game_state_manager and makes it accessible in our game loop.
392
+ By default the game loop calls update() / draw() on the the current game state.
393
+
394
+ Chingu also has a couple of helpers-methods for handling the game states:
395
+ In a main loop or in a game state:
396
+ * push_game_state(state) - adds a new gamestate on top of the stack, which then becomes the active one
397
+ * pop_game_state - removes active gamestate and activates the previous one
398
+ * switch_game_state(state) - replaces current game state with a new one
399
+ * current_game_state - returns the current game state
400
+ * previous_game_state - returns the previous game state (useful for pausing and dialog boxes, see example4.rb)
401
+ * pop_until_game_state(state) - pop game states until given state is found
402
+ * clear_game_states - removes all game states from stack
403
+
404
+ To switch to a certain gamestate with a keypress use Chingus input handler:
405
+ class Intro < Chingu::GameState
406
+ def setup
407
+ self.input = { :space => lambda{push_gamestate(Menu.new)} }
408
+ end
409
+ end
410
+
411
+ Or Chingus shortcut:
412
+
413
+ class Intro < Chingu::GameState
414
+ def setup
415
+ self.input = { :space => Menu }
416
+ end
417
+ end
418
+
419
+ Chingus inputhandler will detect that Menu is a gamestate-class, create a new instance, cache it and activate it with push_game_state().
420
+
421
+ === Traits
422
+ Traits (often called behaivors) is a way of adding logic to any class inheriting from BasicGameObject / GameObject.
423
+ Chingus trait-implementation is just ordinary ruby modules with 3 special methods:
424
+ - setup_trait
425
+ - update_trait
426
+ - draw_trait
427
+ Each of those 3 methods must call "super" to continue the trait-chain.
428
+
429
+ The flow for a game object then becomes:
430
+
431
+ -- creating the object
432
+ 1) GameObject#initialize(options)
433
+ 2) GameObject#setup_trait(options)
434
+ -- each game iteration
435
+ 3) GameObject#draw_trait
436
+ 4) GameObject#draw
437
+ 5) GameObject#update_trait
438
+ 6) GameObject#update
439
+
440
+ There's a couple of traits included as default in Chingu:
441
+
442
+ ==== Trait "timer"
443
+ Adds timer functionallity to your game object
444
+ during(300) { @color = Color.new(0xFFFFFFFF) } # forces @color to white ever update for 300 ms
445
+ after(400) { self.destroy } # destroy object after 400 ms
446
+ between(1000,2000) { self.rotate(10) } # starting after 1 second, call rotate(10) every update during 1 second
447
+
448
+ ==== Trait "velocity"
449
+ Adds variables velocity_x, velocity_y, acceleration_x, acceleration_y, max_velocity to game object.
450
+ They modify x, y as you would expect. *speed / angle will come*
451
+
452
+
453
+ ==== (IN DEVELOPMENT) Trait "effect"
454
+ Adds ability to automaticly fade, rotate and scale game objects.
455
+ * API isn't stabilized yet! *
456
+
457
+ ==== (IN DEVELOPMENT) Trait "collision_detection"
458
+ Adds class and instance methods for basic collision detection.
459
+
460
+ # Class method example
461
+ # This will collide all Enemy-instances with all Bullet-instances using the attribute #radius from each object.
462
+ Enemy.each_radius_collision(Bullet) do |enemy, bullet|
463
+ end
464
+
465
+ # You can also use the instance methods. This will use the Rect bounding_box from @player and each EnemyRocket-object.
466
+ @player.each_bounding_box_collision(EnemyRocket) do |player, enemyrocket|
467
+ player.die!
468
+ end
469
+
470
+ * API isn't stabilized yet! *
471
+
472
+ ==== (IN DEVELOPMENT) Trait "retrofy"
473
+ Providing easier handling of the "retrofy" effect (non-blurry zoom)
474
+ Aims to help out when using zoom-factor to create a retrofeeling with big pixels.
475
+ Provides screen_x and screen_y which takes the zoom into account
476
+ Also provides new code for draw() which uses screen_x / screen_y instead of x / y
477
+
478
+
479
+ === Assets / Paths
480
+
481
+ You might wonder why this is necessary in the straight Gosu example:
482
+ ROOT_PATH = File.dirname(File.expand_path(__FILE__))
483
+ @image = Image.new(File.join(ROOT_PATH, "media", "player.png"))
484
+
485
+ It enables you to start your game from any directory and it will still find your assets (pictures, samples, fonts etc..) correctly.
486
+ For a local development version this might not be important, you're likely to start the game from the games root-dir.
487
+ But as soon as you try to deploy (for example to windows with OCRA - http://github.com/larsch/ocra/tree/master) you'll run into trouble of you don't do it like that.
488
+
489
+ Chingu solves this problem behind the scenes for the most common assets. The 2 lines above can be replaced with:
490
+ Image["player.png"]
491
+
492
+ You also have:
493
+ Sound["shot.png"]
494
+ Song["intromusic.ogg"]
495
+
496
+ By default Image, Sound and Sound searches the current directory and directory "media".
497
+ Add your own searchpaths like this:
498
+ Gosu::Image.autoload_dirs << File.join($window.root, "gfx")
499
+ Gosu::Sound.autoload_dirs << File.join($window.root, "samples")
500
+
501
+ This will add \path\to\your\game\gfx and \path\to\your\game\samples to Image and Sound.
502
+
503
+ Thanks to Jacious of rubygame-fame (http://rubygame.org/) for his named resource code powering this.
504
+
505
+ Tiles and fonts are trickier since they require extra parameters so you'll have to do those the ordinary way.
506
+ You have $window.root (equivalent to ROOT_PATH above) for free though which points to the dir containing the game.
507
+
508
+ === Text
509
+ Text is a class to give the use of Gosu::Font more rubyish feel and fit it better into Chingu.
510
+
511
+ # Pure Gosu
512
+ @font = Gosu::Font.new($window, "verdana", 30)
513
+ @font.draw("A Text", 200, 50, 55, 2.0)
514
+
515
+ # Chingu
516
+ @text = Chingu::Text.create(:text => "A Text", :x => 200, :y => 50, :zorder => 55, :factor_x => 2.0)
517
+ @text.draw
518
+
519
+ @text.draw is usually not needed as Text is a GameObject and therefore automaticly updated/drawn (it #create is used instead of #new)
520
+ It's not only that the second example is readable by ppl now even familiar with Gosu, @text comes with a number of changeable properties, x,y,zorder,angle,factor_x,color,mode etc.
521
+ Set a new x or angle or color and it will instantly update on screen.
522
+
523
+
524
+ == MISC / FAQ
525
+ === How do I access my main-window easily?
526
+ Chingu keeps a global variable, $window, which contains the Chingu::Window instance.
527
+ Since Chingu::Window is just Gosu::Window + some cheese you can do your $window.button_down?, $window.draw_line() etc from anywhere.
528
+ See http://www.libgosu.org/rdoc/classes/Gosu/Window.html for a full set of methods.
529
+
530
+ === How did you decide on naming of methods / classes?
531
+ There's 1 zillion ways of naming stuff. As a general guideline I've tried to follow Gosus naming.
532
+ If Gosu didn't have a good name for a certain thing/method I've checked Ruby itself and then Rails since alot
533
+ of Ruby-devs are familiar with Rails.
534
+
535
+ == TODO:
536
+ * add :padding and :align => :topleft etc to class Text
537
+ * (skip) rename Chingu::Window so 'include Chingu' and 'include Gosu' wont make Window collide
538
+ * (done) BasicObject vs GameObject vs ScreenObject => Became BasicGameObject and GameObject
539
+ * (50%) some kind of componentsystem for GameObject (which should be cleaned up)
540
+ * (done) scale <--> growth parameter. See trait "effect"
541
+ * (done) Enemy.all ... instead of game_objects_of_type(Enemy) ? could this be cool / understandable?
542
+ * (done) Don't call .update(time) with timeparameter, make time available thru other means when needed.
543
+ * (10% done) debug screen / game state.. check out shawn24's elite irb sollution :)
544
+ * (done) Complete the input-definitions with all possible inputs (keyboard, gamepad, mouse)!
545
+ * (done) Complete input-stuff with released-states etc
546
+ * (done) More gfx effects, for example: fade in/out to a specific color (black makes sense between levels).
547
+ * (posted request on forums) Summon good proven community gosu snippets into Chingu
548
+ * (done) Generate docs @ ippa.github.com- http://rdoc.info/projects/ippa/chingu !
549
+ * (done) A good scene-manager to manage welcome screens, levels and game flow- GameStateManager / GameState !
550
+ * (20% done) make a playable simple game in examples\ that really depends on game states
551
+ * (done) Make a gem- first gem made on github
552
+ * (done) Automate gemgenning rake-task even more
553
+ * (done) More examples when effects are more complete
554
+ * class ChipmunkObject
555
+ * (done) class Actor/MovingActor with maybe a bit more logic then the basic GameObject.
556
+ * (60% done) Spell check all docs, sloppy spelling turns ppl off. tnx jduff ;).
557
+ * Tests
558
+ * (done) Streamline fps / tick code
559
+ * (done) Encapsulate Font.new / draw_rot with a "class Text < GameObject"
560
+ * (10% done) Make it possible for ppl to use the parts of Chingu they like
561
+ * (done) At least make GameStateManager really easy to use with pure Gosu / Document it!
562
+ * (50% done) Get better at styling rdocs
563
+ * (done) all �gamestate� ? �game state� ? it's "game state"
564
+ * (skipping) intergrate MovieMaker - solve this with traits instead.
565
+ * A more robust game state <-> game_object system to connect them together.
566
+ * FIX example4: :p => Pause.new would Change the "inside_game_state" to Pause and make @player belong to Pause.
567
+
568
+ == WHY?
569
+ * Plain Gosu is very minimalistic, perfect to build some higher level logic on!
570
+ * Deployment and asset handling should be simple
571
+ * Managing game states/scenes (intros, menus, levels etc) should be simple
572
+ * There are patterns in game development
573
+
574
+ == OPINIONS
575
+ * Less code is usually better
576
+ * Hash arguments FTW. And it becomes even better in 1.9.
577
+ * Don't separate too much from Gosus core-naming
578
+
579
+ == CREDITS:
580
+ * Jacius of Rubygame (For doing cool stuff that's well documented as re-usable). So far rect.rb and named_resource.rb is taken from Rubygame.
581
+ * Jduff for input / commits.
582
+ * Jlnr,Philymore,Shawn24,JamesKilton for constructive feedback/discussions.
583
+ * Thanks to http://github.com/tarcieri for require_all code, good stuff
584
+
585
+ == REQUIREMENTS:
586
+ * Gosu latest version
587
+ * Ruby 1.8.7+ (Works with 1.9+ as well!)
588
+