chingu 0.5.5.3

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 (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
+