ippa-chingu 0.3.1 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|