ippa-chingu 0.3.1 → 0.4.0
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.
- data/README.rdoc +81 -23
- data/chingu.gemspec +2 -2
- data/lib/chingu/assets.rb +43 -44
- data/lib/chingu/game_object.rb +34 -7
- data/lib/chingu/game_state.rb +12 -7
- data/lib/chingu/game_state_manager.rb +84 -43
- data/lib/chingu/helpers.rb +11 -7
- data/lib/chingu/text.rb +2 -2
- data/lib/chingu/window.rb +25 -29
- data/lib/chingu.rb +1 -1
- metadata +2 -2
data/README.rdoc
CHANGED
@@ -227,7 +227,11 @@ Another more complex example:
|
|
227
227
|
|
228
228
|
class Play < Chingu::GameState
|
229
229
|
def initialize
|
230
|
-
self.input = { :p => Pause,
|
230
|
+
self.input = { :p => Pause,
|
231
|
+
:escape => :close,
|
232
|
+
:holding_left => :move_left,
|
233
|
+
:holding_right => :move_right,
|
234
|
+
:released_space => :fire }
|
231
235
|
end
|
232
236
|
end
|
233
237
|
class Pause < Chingu::GameState
|
@@ -237,12 +241,13 @@ Another more complex example:
|
|
237
241
|
In Gosu the above code would include code in button_up(), button_down() and a check for button_down?() in update().
|
238
242
|
|
239
243
|
Every symbol can be prefixed by either "released_" or "holding_" while no prefix at all defaults to pressed once.
|
244
|
+
|
240
245
|
So, why not :up_space or :relase_space instead of :released_space?
|
241
|
-
|
246
|
+
+:up_space+ doesn't sound like english, :release_space sounds more like a command then an event.
|
242
247
|
|
243
|
-
:up_space doesn't sound like english, :release_space sounds more like a command then an event.
|
244
248
|
|
245
|
-
|
249
|
+
Or +:hold_left+ or :down_left instead of :holding_left?
|
250
|
+
:holding_left sounds like something that's happening over a period of time, not a single trigger, which corresponds well to how it works.
|
246
251
|
|
247
252
|
And with the default :space => :something youd imagine that :something is called once. You press :space once, :something get's executed once.
|
248
253
|
|
@@ -271,7 +276,7 @@ Game states aren't complicated. In Chingu a GameState is a class that behaves mo
|
|
271
276
|
@player.angle = 0 # point player upwards
|
272
277
|
end
|
273
278
|
|
274
|
-
# Called when we leave the
|
279
|
+
# Called when we leave the game state
|
275
280
|
def finalize
|
276
281
|
push_game_state(Menu) # switch to game state "Menu"
|
277
282
|
end
|
@@ -292,23 +297,56 @@ You can activate the above game state in 2 ways
|
|
292
297
|
|
293
298
|
#
|
294
299
|
# 2) This leaves the actual object-creation to the game state manager.
|
295
|
-
#
|
296
|
-
# The second time 'push_game_state(Intro)' is called, it will re-use the last one.
|
297
|
-
# This means code in Intro#initialize() is only called once, Intro#setup() is called everytime Intro is activated though.
|
300
|
+
# Intro#initialize() is called, then Intro#setup()
|
298
301
|
#
|
299
302
|
push_game_state(Intro)
|
300
303
|
end
|
301
304
|
end
|
305
|
+
|
306
|
+
Another example:
|
307
|
+
|
308
|
+
class Game < Chingu::Window
|
309
|
+
def initialize
|
310
|
+
#
|
311
|
+
# We start by pushing Menu to the game state stack, making it active as the only state on stack.
|
312
|
+
# :setup => :false which will skip setup() from beeing called (standard when switching to a new state)
|
313
|
+
#
|
314
|
+
push_game_state(Menu, :setup => false)
|
315
|
+
|
316
|
+
#
|
317
|
+
# We push another game state to the stack, Play. We now have 2 states, which active beeing first / active.
|
318
|
+
#
|
319
|
+
# :finalize => false will skip setup() from beeing called on game state
|
320
|
+
# that's beeing pushed down the stack, in this case Intro.setup().
|
321
|
+
#
|
322
|
+
push_game_state(Play, :finalize => false)
|
323
|
+
|
324
|
+
#
|
325
|
+
# This would remove Play state from the stack, going back to the Menu-state. But also:
|
326
|
+
# .. skipping the standard call to Menu#setup (the new game state)
|
327
|
+
# .. skipping the standard call to Play#finalize (the current game state)
|
328
|
+
#
|
329
|
+
# :setup => false can for example be useful when pop'ing a Pause game state. (see example4.rb)
|
330
|
+
#
|
331
|
+
pop_game_state(:setup => false, :finalize => :false)
|
332
|
+
|
333
|
+
#
|
334
|
+
# Replace the current game state with a new one.
|
335
|
+
# :setup and :finalize options are available here as well.
|
336
|
+
#
|
337
|
+
switch_game_state(Credits)
|
338
|
+
end
|
339
|
+
end
|
302
340
|
|
303
341
|
A GameState in Chingu is just a class with the following instance methods:
|
304
342
|
|
305
|
-
* initialize()
|
306
|
-
* setup()
|
343
|
+
* initialize() - called only once with push_game_state(Intro) but everytime with push_game_state(Intro.new)
|
344
|
+
* setup() - called each time the game state becomes active.
|
307
345
|
* button_down(id) - Called when a button is down
|
308
346
|
* button_up(id) - Called when a button is released
|
309
|
-
* update()
|
310
|
-
* draw()
|
311
|
-
* finalize()
|
347
|
+
* update() - just as in your normal game loop, put your game logic here.
|
348
|
+
* draw() - just as in your normal game loop, put your screen manipulation here.
|
349
|
+
* finalize() - called when a game state de-activated (for example by pushing a new one on top with push_game_state)
|
312
350
|
|
313
351
|
Chingu::Window automatically creates a @game_state_manager and makes it accessible in our game loop.
|
314
352
|
By default the game loop calls update() / draw() on the the current game state.
|
@@ -317,6 +355,7 @@ Chingu also has a couple of helpers-methods for handling the game states:
|
|
317
355
|
In a main loop or in a game state:
|
318
356
|
* push_game_state(state) - adds a new gamestate on top of the stack, which then becomes the active one
|
319
357
|
* pop_game_state - removes active gamestate and activates the previous one
|
358
|
+
* switch_game_state(state) - replaces current game state with a new one
|
320
359
|
* current_game_state - returns the current game state
|
321
360
|
* previous_game_state - returns the previous game state (useful for pausing and dialog boxes, see example4.rb)
|
322
361
|
* pop_until_game_state(state) - pop game states until given state is found
|
@@ -333,10 +372,10 @@ Or Chingus shortcut:
|
|
333
372
|
|
334
373
|
class Intro < Chingu::GameState
|
335
374
|
def setup
|
336
|
-
self.input = { :space => Menu }
|
375
|
+
self.input = { :space => Menu }
|
337
376
|
end
|
338
377
|
end
|
339
|
-
|
378
|
+
|
340
379
|
Chingus inputhandler will detect that Menu is a gamestate-class, create a new instance, cache it and activate it with push_game_state().
|
341
380
|
|
342
381
|
=== Assets / Paths
|
@@ -350,12 +389,23 @@ For a local development version this might not be important, you're likely to st
|
|
350
389
|
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 dont do it like that.
|
351
390
|
|
352
391
|
Chingu solves this problem behind the scenes for the most common assets. The 2 lines above can be replaced with:
|
353
|
-
Image["player.png"]
|
392
|
+
Image["player.png"]
|
393
|
+
|
394
|
+
You also have:
|
395
|
+
Sound["shot.png"]
|
396
|
+
Song["intromusic.ogg"]
|
397
|
+
|
398
|
+
By default Image, Sound and Sound searches the current directory and directory "media".
|
399
|
+
Add your own searchpaths like this:
|
400
|
+
Gosu::Image.autoload_dirs << File.join($window.root, "gfx")
|
401
|
+
Gosu::Sound.autoload_dirs << File.join($window.root, "samples")
|
354
402
|
|
355
|
-
|
403
|
+
This will add \path\to\your\game\gfx and \path\to\your\game\samples to Image and Sound.
|
404
|
+
|
405
|
+
Thanks to Jacious of rubygame-fame (http://rubygame.org/) for his named resource code powering this.
|
356
406
|
|
357
407
|
Tiles and fonts are trickier since they require extra parameters so you'll have to do those the ordinary way.
|
358
|
-
You
|
408
|
+
You have $window.root (equivalent to ROOT_PATH above) for free though which points to the dir containing the game.
|
359
409
|
|
360
410
|
=== Text
|
361
411
|
Text is a class to give the use of Gosu::Font more rubyish feel and fit it better into Chingu.
|
@@ -372,6 +422,13 @@ Text is a class to give the use of Gosu::Font more rubyish feel and fit it bette
|
|
372
422
|
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. Set a new x or angle or color and it will instantly update on screen.
|
373
423
|
|
374
424
|
|
425
|
+
== MISC / FAQ
|
426
|
+
How do I access my main-window easily?
|
427
|
+
|
428
|
+
Chingu keeps a global variable, $window, which contains the Chingu::Window instance.
|
429
|
+
Since Chingu::Window is just Gosu::Window + some cheese you can do your $window.button_down?, $window.draw_line() etc from anywhere.
|
430
|
+
See http://www.libgosu.org/rdoc/classes/Gosu/Window.html for a full set of methods.
|
431
|
+
|
375
432
|
== TODO:
|
376
433
|
* (done) Complete the input-definitions with all possible inputs (keyboard, gamepad, mouse)!
|
377
434
|
* (done) Complete input-stuff with released-states etc
|
@@ -380,21 +437,22 @@ It's not only that the second example is readable by ppl now even familiar with
|
|
380
437
|
* (done) Generate docs @ ippa.github.com- http://rdoc.info/projects/ippa/chingu !
|
381
438
|
* (done) A good scene-manager to manage welcome screens, levels and game flow- GameStateManager / GameState !
|
382
439
|
* More docs
|
383
|
-
* make a playable simple game in examples\ that really depends on game states
|
440
|
+
* (20% done) make a playable simple game in examples\ that really depends on game states
|
384
441
|
* (done) Make a gem- first gem made on github
|
385
|
-
* Automate gemgenning rake-task even more
|
442
|
+
* (done) Automate gemgenning rake-task even more
|
386
443
|
* More examples when effects are more complete
|
387
444
|
* class ChipmunkObject
|
388
445
|
* class Actor/MovingActor with maybe abit more logic then the basic GameObject. Would ppl find is useful?
|
389
|
-
* Spell check all docs, sloppy spelling turns ppl off.
|
446
|
+
* (40% done) Spell check all docs, sloppy spelling turns ppl off.
|
390
447
|
* Tests
|
391
448
|
* (done) Streamline fps / tick code
|
392
449
|
* (done) Encapsulate Font.new / draw_rot with a "class Text < GameObject"
|
393
450
|
* (10% done) Make it possible for ppl to use the parts of Chingu they like
|
451
|
+
* At least make GameStateManager really easy to use with pure Gosu / Document it!
|
394
452
|
* A more robust game state <-> game_object system to connect them together.
|
395
|
-
* Get better at styling rdocs
|
453
|
+
* (50% done) Get better at styling rdocs
|
396
454
|
* (done) all �gamestate� ? �game state� ? it's "game state"
|
397
|
-
* intergrate
|
455
|
+
* intergrate MovieMaker
|
398
456
|
* FIX example4: :p => Pause.new would Change the "inside_game_state" to Pause and make @player belong to Pause.
|
399
457
|
|
400
458
|
== WHY?
|
data/chingu.gemspec
CHANGED
@@ -2,11 +2,11 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = %q{chingu}
|
5
|
-
s.version = "0.
|
5
|
+
s.version = "0.4.0"
|
6
6
|
|
7
7
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
8
8
|
s.authors = ["ippa"]
|
9
|
-
s.date = %q{2009-08-
|
9
|
+
s.date = %q{2009-08-19}
|
10
10
|
s.description = %q{Game framework built on top of the OpenGL accelerated game lib Gosu. It adds simple yet powerfull game states, prettier inputhandling, deploymentsafe asset-handling, a basic re-usable game object and automation of common task.}
|
11
11
|
s.email = ["ippa@rubylicio.us"]
|
12
12
|
s.extra_rdoc_files = ["History.txt", "Manifest.txt"]
|
data/lib/chingu/assets.rb
CHANGED
@@ -4,55 +4,54 @@
|
|
4
4
|
# Quick 'n easy access to sprites, sounds and tiles!
|
5
5
|
#
|
6
6
|
module Chingu
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
include Chingu::NamedResource
|
7
|
+
def media_path(file)
|
8
|
+
File.join($window.root, "media", file)
|
9
|
+
end
|
10
|
+
|
11
|
+
def image_path(file)
|
12
|
+
File.join($window.root, "gfx", file)
|
13
|
+
end
|
14
|
+
|
15
|
+
class ImagePath
|
16
|
+
include Chingu::NamedResource
|
18
17
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
18
|
+
def self.autoload(name)
|
19
|
+
find_file(name)
|
20
|
+
end
|
21
|
+
end
|
23
22
|
end
|
24
23
|
|
25
24
|
module Gosu
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
25
|
+
class Image
|
26
|
+
include Chingu::NamedResource
|
27
|
+
|
28
|
+
def self.autoload(name)
|
29
|
+
(path = find_file(name)) ? Gosu::Image.new($window, path, true) : nil
|
30
|
+
end
|
31
|
+
end
|
33
32
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
33
|
+
class Song
|
34
|
+
include Chingu::NamedResource
|
35
|
+
|
36
|
+
def self.autoload(name)
|
37
|
+
(path = find_file(name)) ? Gosu::Song.new($window, path) : nil
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
class Sample
|
42
|
+
include Chingu::NamedResource
|
43
|
+
|
44
|
+
def self.autoload(name)
|
45
|
+
(path = find_file(name)) ? Gosu::Sample.new($window, path) : nil
|
46
|
+
end
|
47
|
+
end
|
48
|
+
Sound = Sample
|
50
49
|
|
51
|
-
|
52
|
-
|
50
|
+
class Tile
|
51
|
+
include Chingu::NamedResource
|
53
52
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
53
|
+
def self.autoload(name)
|
54
|
+
(path = find_file(name)) ? Gosu::Image.load_tiles($window, path, 32, 32, true) : nil
|
55
|
+
end
|
56
|
+
end
|
58
57
|
end
|
data/lib/chingu/game_object.rb
CHANGED
@@ -8,7 +8,7 @@ module Chingu
|
|
8
8
|
class GameObject
|
9
9
|
attr_accessor :image, :x, :y, :angle, :center_x, :center_y, :factor_x, :factor_y, :color, :mode
|
10
10
|
attr_accessor :update, :draw
|
11
|
-
attr_reader :options
|
11
|
+
attr_reader :options, :parent
|
12
12
|
|
13
13
|
include Chingu::InputClient
|
14
14
|
|
@@ -98,15 +98,42 @@ module Chingu
|
|
98
98
|
@parent.add_game_object(self) if @parent
|
99
99
|
end
|
100
100
|
|
101
|
+
#
|
102
|
+
# Quick way of setting both factor_x and factor_y
|
103
|
+
#
|
101
104
|
def factor=(factor)
|
102
|
-
@
|
103
|
-
@factor_x = @factor_y = @factor
|
105
|
+
@factor_x = @factor_y = factor
|
104
106
|
end
|
105
|
-
|
106
|
-
|
107
|
-
|
107
|
+
|
108
|
+
#
|
109
|
+
# Quick way of setting both center_x and center_y
|
110
|
+
#
|
111
|
+
def center=(factor)
|
112
|
+
@center_x = @center_y = factor
|
113
|
+
end
|
114
|
+
|
115
|
+
#
|
116
|
+
# Zoom - increase @factor_x and @factor_y at the same time.
|
117
|
+
#
|
118
|
+
def zoom(amount)
|
119
|
+
@factor_x += amount
|
120
|
+
@factor_y += amount
|
121
|
+
end
|
122
|
+
|
123
|
+
#
|
124
|
+
# Zoom Out - decrease @factor_x and @factor_y at the same time.
|
125
|
+
#
|
126
|
+
def zoom_out(amount)
|
127
|
+
@factor_x -= amount
|
128
|
+
@factor_y -= amount
|
129
|
+
end
|
130
|
+
|
131
|
+
#
|
132
|
+
# Rotate object 'amount' degrees
|
133
|
+
#
|
134
|
+
def rotate(amount)
|
135
|
+
@angle += amount
|
108
136
|
end
|
109
|
-
alias :zoom :factor
|
110
137
|
|
111
138
|
#
|
112
139
|
# Returns true if game object is inside the game window, false if outside
|
data/lib/chingu/game_state.rb
CHANGED
@@ -34,16 +34,17 @@ module Chingu
|
|
34
34
|
include Chingu::InputClient
|
35
35
|
|
36
36
|
attr_reader :options # so jlnr can access his :level-number
|
37
|
-
attr_reader :game_objects
|
37
|
+
attr_reader :game_objects
|
38
38
|
|
39
39
|
def initialize(options = {})
|
40
40
|
@options = options
|
41
|
-
@do_setup = options[:setup] || true
|
42
|
-
|
43
41
|
@game_objects = Set.new
|
44
|
-
@input_clients = Set.new
|
42
|
+
@input_clients = Set.new # Set is like a unique Array with Hash lookupspeed
|
45
43
|
|
46
|
-
|
44
|
+
# Game state mamanger can be run alone
|
45
|
+
if defined?($window) && $window.respond_to?(:game_state_manager)
|
46
|
+
$window.game_state_manager.inside_state = self
|
47
|
+
end
|
47
48
|
end
|
48
49
|
|
49
50
|
#
|
@@ -53,12 +54,16 @@ module Chingu
|
|
53
54
|
def to_sym
|
54
55
|
self.class.to_s.to_sym
|
55
56
|
end
|
56
|
-
|
57
|
+
|
58
|
+
def to_s
|
59
|
+
self.class.to_s
|
60
|
+
end
|
61
|
+
|
57
62
|
def add_game_object(object)
|
58
63
|
@game_objects << object
|
59
64
|
end
|
60
65
|
def remove_game_object(object)
|
61
|
-
@
|
66
|
+
@game_objects.delete(object)
|
62
67
|
end
|
63
68
|
|
64
69
|
def setup
|
@@ -2,103 +2,144 @@ module Chingu
|
|
2
2
|
#
|
3
3
|
# GameStateManger is responsible for keeping track of game states with a simple pop/push stack.
|
4
4
|
#
|
5
|
+
# Related blogpost: http://gamedevgeek.com/tutorials/managing-game-states-in-c/
|
6
|
+
#
|
5
7
|
# Chingu::Window automatically creates a @game_state_manager and makes it accessible in our game loop.
|
6
8
|
# By default the game loop calls update() / draw() on @game_state_manager
|
7
9
|
#
|
8
10
|
class GameStateManager
|
9
11
|
attr_accessor :inside_state
|
10
|
-
attr_reader :states, :created_states
|
11
12
|
|
12
13
|
def initialize
|
13
14
|
@inside_state = nil
|
14
|
-
@
|
15
|
-
@created_states = {}
|
15
|
+
@game_states = []
|
16
16
|
end
|
17
17
|
|
18
18
|
#
|
19
19
|
# Gets the currently active gamestate (top of stack)
|
20
20
|
#
|
21
|
-
def
|
22
|
-
@
|
21
|
+
def current_game_state
|
22
|
+
@game_states.last
|
23
23
|
end
|
24
|
+
alias :current current_game_state
|
24
25
|
|
25
26
|
#
|
26
|
-
#
|
27
|
+
# Returns all gamestates with top of stack first
|
27
28
|
#
|
28
|
-
def
|
29
|
-
|
29
|
+
def game_states
|
30
|
+
@game_states.reverse
|
31
|
+
end
|
32
|
+
|
33
|
+
#
|
34
|
+
# Switch to a given game state, _replacing_ the current active one.
|
35
|
+
#
|
36
|
+
def switch_game_state(state, options = {})
|
37
|
+
options = {:setup => true, :finalize => true}.merge(options)
|
30
38
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
#
|
37
|
-
# If state is a GameState-class, create/initialize it once (@created_states keeps track of this)
|
38
|
-
#
|
39
|
-
elsif state.superclass == Chingu::GameState
|
39
|
+
new_state = game_state_instance(state)
|
40
|
+
|
41
|
+
if new_state
|
42
|
+
# Give the soon-to-be-disabled state a chance to clean up by calling finalize() on it.
|
43
|
+
current_game_state.finalize if current_game_state.respond_to?(:finalize) && options[:finalize]
|
40
44
|
|
41
|
-
|
42
|
-
|
45
|
+
# Call setup
|
46
|
+
new_state.setup if new_state.respond_to?(:setup) && options[:setup]
|
47
|
+
|
48
|
+
|
49
|
+
if current_game_state.nil?
|
50
|
+
@game_states << new_state
|
43
51
|
else
|
44
|
-
|
45
|
-
@
|
52
|
+
# Replace last (active) state with new one
|
53
|
+
@game_states[-1] = new_state
|
46
54
|
end
|
47
55
|
end
|
56
|
+
end
|
57
|
+
alias :switch :switch_game_state
|
58
|
+
|
59
|
+
#
|
60
|
+
# Adds a state to the game state-stack and activates it
|
61
|
+
#
|
62
|
+
def push_game_state(state, options = {})
|
63
|
+
options = {:setup => true, :finalize => true}.merge(options)
|
48
64
|
|
49
|
-
|
50
|
-
|
51
|
-
#
|
65
|
+
new_state = game_state_instance(state)
|
66
|
+
|
52
67
|
if new_state
|
53
68
|
# Give the soon-to-be-disabled state a chance to clean up by calling finalize() on it.
|
54
|
-
|
69
|
+
current_game_state.finalize if current_game_state.respond_to?(:finalize) && options[:finalize]
|
55
70
|
|
56
71
|
# Call setup
|
57
|
-
new_state.setup
|
72
|
+
new_state.setup if new_state.respond_to?(:setup) && options[:setup]
|
58
73
|
|
59
74
|
# Push new state on top of stack and therefore making it active
|
60
|
-
@
|
75
|
+
@game_states.push(new_state)
|
61
76
|
end
|
62
77
|
end
|
78
|
+
alias :push :push_game_state
|
63
79
|
|
64
80
|
#
|
65
81
|
# Pops a state off the game state-stack, activating the previous one.
|
66
82
|
#
|
67
|
-
def
|
83
|
+
def pop_game_state(options = {})
|
84
|
+
options = {:setup => true, :finalize => true}.merge(options)
|
85
|
+
|
68
86
|
#
|
69
87
|
# Give the soon-to-be-disabled state a chance to clean up by calling finalize() on it.
|
70
88
|
#
|
71
|
-
|
89
|
+
current_game_state.finalize if current_game_state.respond_to?(:finalize) && options[:finalize]
|
72
90
|
|
73
91
|
#
|
74
92
|
# Activate the game state "bellow" current one with a simple Array.pop
|
75
93
|
#
|
76
|
-
@
|
94
|
+
@game_states.pop
|
77
95
|
|
78
96
|
# Call setup on the new current state
|
79
|
-
|
97
|
+
current_game_state.setup if current_game_state.respond_to?(:setup) && options[:setup]
|
80
98
|
end
|
81
|
-
|
99
|
+
alias :pop :pop_game_state
|
100
|
+
|
101
|
+
#
|
102
|
+
# Returns a GameState-instance from either a class or object
|
103
|
+
#
|
104
|
+
def game_state_instance(state)
|
105
|
+
new_state = nil
|
106
|
+
#
|
107
|
+
# If state is a GameState-instance, just queue it
|
108
|
+
#
|
109
|
+
if state.is_a? Chingu::GameState
|
110
|
+
new_state = state
|
111
|
+
#
|
112
|
+
# If state is a GameState-class, create it.
|
113
|
+
#
|
114
|
+
elsif state.superclass == Chingu::GameState
|
115
|
+
new_state = state.new({})
|
116
|
+
end
|
117
|
+
|
118
|
+
return new_state
|
119
|
+
end
|
120
|
+
|
121
|
+
|
82
122
|
#
|
83
123
|
# Returns the previous game state
|
84
124
|
#
|
85
|
-
def
|
86
|
-
@
|
125
|
+
def previous_game_state
|
126
|
+
@game_states[@game_states.index(current_game_state)-1]
|
87
127
|
end
|
88
|
-
alias :
|
128
|
+
alias :previous previous_game_state
|
89
129
|
|
90
130
|
#
|
91
131
|
# Remove all game states from stack
|
92
132
|
#
|
93
|
-
def
|
94
|
-
@
|
133
|
+
def clear_game_states
|
134
|
+
@game_states.clear
|
95
135
|
end
|
136
|
+
alias :clear :clear_game_states
|
96
137
|
|
97
138
|
#
|
98
139
|
# Pops through all game states until matching a given game state
|
99
140
|
#
|
100
141
|
def pop_until_game_state(new_state)
|
101
|
-
while (state = @
|
142
|
+
while (state = @game_states.pop)
|
102
143
|
break if state == new_state
|
103
144
|
end
|
104
145
|
end
|
@@ -114,27 +155,27 @@ module Chingu
|
|
114
155
|
# Called before #update when the user pressed a button while the window had the focus.
|
115
156
|
#
|
116
157
|
def button_down(id)
|
117
|
-
|
158
|
+
current_game_state.button_down(id) if current_game_state
|
118
159
|
end
|
119
160
|
|
120
161
|
#
|
121
162
|
# Called when the user released a button.
|
122
163
|
#
|
123
164
|
def button_up(id)
|
124
|
-
|
165
|
+
current_game_state.button_up(id) if current_game_state
|
125
166
|
end
|
126
167
|
|
127
168
|
#
|
128
169
|
# Calls #update on the current gamestate, if there is one.
|
129
170
|
#
|
130
|
-
def update(time =
|
131
|
-
|
171
|
+
def update(time = nil)
|
172
|
+
current_game_state.update(time) if current_game_state
|
132
173
|
end
|
133
174
|
#
|
134
175
|
# Calls draw() on the current gamestate, if there is one.
|
135
176
|
#
|
136
177
|
def draw
|
137
|
-
|
178
|
+
current_game_state.draw if current_game_state
|
138
179
|
end
|
139
180
|
end
|
140
181
|
end
|
data/lib/chingu/helpers.rb
CHANGED
@@ -21,7 +21,7 @@ module Chingu
|
|
21
21
|
end
|
22
22
|
|
23
23
|
def dispatch_button_down(id, object)
|
24
|
-
return if
|
24
|
+
return if(object.nil? || object.input.nil?)
|
25
25
|
|
26
26
|
object.input.each do |symbol, action|
|
27
27
|
if Input::SYMBOL_TO_CONSTANT[symbol] == id
|
@@ -95,23 +95,27 @@ module Chingu
|
|
95
95
|
#
|
96
96
|
module GameStateHelpers
|
97
97
|
def push_game_state(state, options = {})
|
98
|
-
$window.game_state_manager.
|
98
|
+
$window.game_state_manager.push_game_state(state, options)
|
99
99
|
end
|
100
100
|
|
101
101
|
def pop_game_state(options = {})
|
102
|
-
$window.game_state_manager.
|
102
|
+
$window.game_state_manager.pop_game_state(options)
|
103
|
+
end
|
104
|
+
|
105
|
+
def switch_game_state(state, options = {})
|
106
|
+
$window.game_state_manager.switch_game_state(state, options)
|
103
107
|
end
|
104
108
|
|
105
109
|
def current_game_state
|
106
|
-
$window.game_state_manager.
|
110
|
+
$window.game_state_manager.current_game_state
|
107
111
|
end
|
108
112
|
|
109
113
|
def previous_game_state
|
110
|
-
$window.game_state_manager.
|
114
|
+
$window.game_state_manager.previous_game_state
|
111
115
|
end
|
112
|
-
|
116
|
+
|
113
117
|
def clear_game_states
|
114
|
-
$window.game_state_manager.
|
118
|
+
$window.game_state_manager.clear_game_states
|
115
119
|
end
|
116
120
|
end
|
117
121
|
|
data/lib/chingu/text.rb
CHANGED
@@ -34,8 +34,8 @@ module Chingu
|
|
34
34
|
def initialize(options)
|
35
35
|
super(options)
|
36
36
|
@text = options[:text] || "-No text specified-"
|
37
|
-
@font = options[:font] || @@font ||
|
38
|
-
@height = options[:height] || options[:size] || @@size ||
|
37
|
+
@font = options[:font] || @@font || default_font_name()
|
38
|
+
@height = options[:height] || options[:size] || @@size || 15
|
39
39
|
|
40
40
|
@gosu_font = Gosu::Font.new($window, @font, @height)
|
41
41
|
end
|
data/lib/chingu/window.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
module Chingu
|
2
|
-
|
2
|
+
class Window < Gosu::Window
|
3
3
|
# adds push_game_state, pop_game_state, current_game_state and previous_game_state
|
4
4
|
include Chingu::GameStateHelpers
|
5
5
|
|
@@ -15,9 +15,8 @@ module Chingu
|
|
15
15
|
# input= and input
|
16
16
|
include Chingu::InputClient
|
17
17
|
|
18
|
-
|
19
|
-
|
20
|
-
|
18
|
+
attr_reader :root, :game_state_manager, :game_objects, :milliseconds_since_last_tick
|
19
|
+
|
21
20
|
#
|
22
21
|
# See http://www.libgosu.org/rdoc/classes/Gosu/Window.html
|
23
22
|
#
|
@@ -29,58 +28,56 @@ module Chingu
|
|
29
28
|
# - Assethandling with Image["picture.png"] and Sample["shot.wav"]
|
30
29
|
# - Default input mapping escape to close
|
31
30
|
#
|
32
|
-
|
33
|
-
|
34
|
-
|
31
|
+
def initialize(width = 640, height = 480)
|
32
|
+
full_screen = ARGV.include?("--fullscreen")
|
33
|
+
$window = super(width, height, full_screen)
|
35
34
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
35
|
+
@root = File.dirname(File.expand_path($0))
|
36
|
+
Gosu::Image.autoload_dirs = [".", File.join(@root, "gfx"), File.join(@root, "media")]
|
37
|
+
Gosu::Sample.autoload_dirs = [".", File.join(@root, "sound"), File.join(@root, "media")]
|
38
|
+
Gosu::Tile.autoload_dirs = [".", File.join(@root, "gfx"), File.join(@root, "media")]
|
40
39
|
Gosu::Song.autoload_dirs = [".", File.join(@root, "sfx"), File.join(@root, "media")]
|
41
40
|
|
42
41
|
@game_objects = Set.new
|
43
42
|
@input_clients = Set.new # Set is like a unique Array with Hash lookupspeed
|
44
43
|
|
45
44
|
@fps_counter = FPSCounter.new
|
46
|
-
|
47
|
-
|
48
|
-
self.input = { :escape => close }
|
49
|
-
end
|
45
|
+
@game_state_manager = GameStateManager.new
|
46
|
+
end
|
50
47
|
|
51
48
|
def add_game_object(object)
|
52
49
|
@game_objects << object
|
53
50
|
end
|
54
51
|
def remove_game_object(object)
|
55
|
-
@
|
52
|
+
@game_objects.delete(object)
|
56
53
|
end
|
57
54
|
|
58
55
|
#
|
59
|
-
# Frames per second
|
56
|
+
# Frames per second, access with $window.fps or $window.framerate
|
60
57
|
#
|
61
|
-
|
62
|
-
|
63
|
-
|
58
|
+
def fps
|
59
|
+
@fps_counter.fps
|
60
|
+
end
|
64
61
|
alias :framerate :fps
|
65
62
|
|
66
63
|
#
|
67
64
|
# Total amount of game iterations (ticks)
|
68
65
|
#
|
69
|
-
|
70
|
-
|
71
|
-
|
66
|
+
def ticks
|
67
|
+
@fps_counter.ticks
|
68
|
+
end
|
72
69
|
|
73
70
|
#
|
74
71
|
# Chingus core-logic / loop. Gosu will call this each game-iteration.
|
75
72
|
#
|
76
|
-
|
73
|
+
def update
|
77
74
|
#
|
78
75
|
# Register a tick with our rather standard tick/framerate counter.
|
79
76
|
# Returns the amount of milliseconds since last tick. This number is used in all update()-calls.
|
80
77
|
# Without this self.fps would return an incorrect value.
|
81
78
|
# If you override this in your Chingu::Window class, make sure to call super.
|
82
79
|
#
|
83
|
-
|
80
|
+
@milliseconds_since_last_tick = @fps_counter.register_tick
|
84
81
|
|
85
82
|
#
|
86
83
|
# Dispatch inputmap for main window
|
@@ -102,14 +99,14 @@ module Chingu
|
|
102
99
|
# Call update(milliseconds_since_last_tick) on all game objects belonging to the current game state.
|
103
100
|
#
|
104
101
|
update_game_state_manager
|
105
|
-
|
102
|
+
end
|
106
103
|
|
107
104
|
#
|
108
105
|
# Chingus main screen manupulation method.
|
109
106
|
# If you override this in your Chingu::Window class, make sure to call super.
|
110
107
|
# Gosu will call this each game-iteration just after #update
|
111
108
|
#
|
112
|
-
|
109
|
+
def draw
|
113
110
|
#
|
114
111
|
# Draw all game objects associated with the main window.
|
115
112
|
#
|
@@ -119,7 +116,7 @@ module Chingu
|
|
119
116
|
# Let the game state manager call draw on the active game state (if any)
|
120
117
|
#
|
121
118
|
@game_state_manager.draw
|
122
|
-
|
119
|
+
end
|
123
120
|
|
124
121
|
#
|
125
122
|
# Call update() on all game objects in main game window.
|
@@ -137,7 +134,6 @@ module Chingu
|
|
137
134
|
@game_state_manager.update(@milliseconds_since_last_tick)
|
138
135
|
end
|
139
136
|
|
140
|
-
|
141
137
|
#
|
142
138
|
# By default button_up sends the keyevent to the GameStateManager
|
143
139
|
# .. Which then is responsible to send it to the right GameState(s)
|
data/lib/chingu.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ippa-chingu
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- ippa
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-08-
|
12
|
+
date: 2009-08-19 00:00:00 -07:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|