ippa-chingu 0.2.0 → 0.3.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/History.txt +4 -1
- data/README.rdoc +120 -30
- data/chingu.gemspec +5 -5
- data/examples/example1.rb +7 -1
- data/examples/example2.rb +17 -8
- data/examples/example3.rb +1 -1
- data/examples/example4.rb +74 -26
- data/lib/chingu/assets.rb +8 -0
- data/lib/chingu/fpscounter.rb +21 -1
- data/lib/chingu/game_object.rb +53 -17
- data/lib/chingu/game_state.rb +90 -14
- data/lib/chingu/game_state_manager.rb +75 -19
- data/lib/chingu/helpers.rb +127 -19
- data/lib/chingu/input.rb +4 -4
- data/lib/chingu/parallax.rb +4 -1
- data/lib/chingu/text.rb +16 -6
- data/lib/chingu/window.rb +104 -104
- metadata +3 -3
data/lib/chingu/assets.rb
CHANGED
@@ -30,7 +30,15 @@ module Gosu
|
|
30
30
|
(path = find_file(name)) ? Gosu::Image.new($window, path, true) : nil
|
31
31
|
end
|
32
32
|
end
|
33
|
+
|
34
|
+
class Song
|
35
|
+
include Chingu::NamedResource
|
33
36
|
|
37
|
+
def self.autoload(name)
|
38
|
+
(path = find_file(name)) ? Gosu::Song.new($window, path) : nil
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
34
42
|
class Sample
|
35
43
|
include Chingu::NamedResource
|
36
44
|
|
data/lib/chingu/fpscounter.rb
CHANGED
@@ -1,21 +1,41 @@
|
|
1
1
|
module Chingu
|
2
|
+
#
|
3
|
+
# Calculates a fps and a tick-time for use in update-calls
|
4
|
+
# register_tick() must be called every game loop iteration
|
5
|
+
#
|
2
6
|
class FPSCounter
|
3
|
-
attr_reader :fps
|
7
|
+
attr_reader :fps, :milliseconds_since_last_tick, :ticks
|
4
8
|
|
5
9
|
def initialize
|
6
10
|
@current_second = Gosu::milliseconds / 1000
|
7
11
|
@accum_fps = 0
|
8
12
|
@fps = 0
|
13
|
+
@ticks = 0
|
14
|
+
|
15
|
+
@milliseconds_since_last_tick = 0
|
16
|
+
@last_value = Gosu::milliseconds
|
9
17
|
end
|
10
18
|
|
19
|
+
#
|
20
|
+
# This should be called once every game-iteration, preferable in update()
|
21
|
+
#
|
11
22
|
def register_tick
|
12
23
|
@accum_fps += 1
|
24
|
+
@ticks += 1
|
13
25
|
current_second = Gosu::milliseconds / 1000
|
14
26
|
if current_second != @current_second
|
15
27
|
@current_second = current_second
|
16
28
|
@fps = @accum_fps
|
17
29
|
@accum_fps = 0
|
18
30
|
end
|
31
|
+
|
32
|
+
#
|
33
|
+
# Calculate how many milliseconds passed since last game loop iteration.
|
34
|
+
# useful in update()-calls
|
35
|
+
#
|
36
|
+
@milliseconds_since_last_tick = Gosu::milliseconds - @last_value
|
37
|
+
@last_value = Gosu::milliseconds
|
38
|
+
return @milliseconds_since_last_tick
|
19
39
|
end
|
20
40
|
end
|
21
41
|
end
|
data/lib/chingu/game_object.rb
CHANGED
@@ -6,10 +6,12 @@ module Chingu
|
|
6
6
|
# All objects that inherits from this class will automaticly be updated and drawn.
|
7
7
|
#
|
8
8
|
class GameObject
|
9
|
-
attr_accessor :image, :x, :y, :angle, :center_x, :center_y, :factor_x, :factor_y, :mode
|
10
|
-
attr_accessor :update, :draw
|
9
|
+
attr_accessor :image, :x, :y, :angle, :center_x, :center_y, :factor_x, :factor_y, :color, :mode
|
10
|
+
attr_accessor :update, :draw
|
11
11
|
attr_reader :options
|
12
12
|
|
13
|
+
include Chingu::InputClient
|
14
|
+
|
13
15
|
#
|
14
16
|
# Class-level default values.
|
15
17
|
# This allows you to set default-values that affect all created GameObjects after that.
|
@@ -17,12 +19,20 @@ module Chingu
|
|
17
19
|
#
|
18
20
|
# in Gosu::Window#initialize: GameObject.center_x = GameObject.center_y = 0
|
19
21
|
#
|
22
|
+
@@x = nil
|
23
|
+
@@y = nil
|
20
24
|
@@zorder = 100
|
21
25
|
@@center_x = 0.5
|
22
26
|
@@center_y = 0.5
|
23
27
|
@@factor_x = 1.0
|
24
28
|
@@factor_y = 1.0
|
25
29
|
|
30
|
+
def self.x; @@x; end
|
31
|
+
def self.x=(value); @@x = value; end
|
32
|
+
|
33
|
+
def self.y; @@y; end
|
34
|
+
def self.y=(value); @@y = value; end
|
35
|
+
|
26
36
|
def self.zorder; @@zorder; end
|
27
37
|
def self.zorder=(value); @@zorder = value; end
|
28
38
|
|
@@ -41,18 +51,18 @@ module Chingu
|
|
41
51
|
#
|
42
52
|
# Create a new GameObject. Arguments are given in hash-format:
|
43
53
|
#
|
44
|
-
#
|
45
|
-
#
|
46
|
-
#
|
47
|
-
#
|
48
|
-
#
|
49
|
-
#
|
50
|
-
#
|
51
|
-
#
|
52
|
-
#
|
54
|
+
# :x screen x-coordinate (default 0, to the left)
|
55
|
+
# :y screen y-coordinate (default 0, top of screen)
|
56
|
+
# :angle angle of object, used in draw_rot, (default 0, no rotation)
|
57
|
+
# :zorder a gameclass "foo" with higher zorder then gameclass "bar" is drawn on top of "foo".
|
58
|
+
# :center_x relative horizontal position of the rotation center on the image.
|
59
|
+
# 0 is the left border, 1 is the right border, 0.5 is the center (default 0.5)
|
60
|
+
# :center_y see center_x. (default 0.5)
|
61
|
+
# :factor_x horizontal zoom-factor, use >1.0 to zoom in. (default 1.0, no zoom).
|
62
|
+
# :factor_y vertical zoom-factor, use >1.0 to zoom in. (default 1.0, no zoom).
|
53
63
|
#
|
54
|
-
#
|
55
|
-
#
|
64
|
+
# :update [true|false] Automaticly call #update on object each gameloop. Default +true+.
|
65
|
+
# :draw [true|false] Automaticly call #update on object each gameloop. Default +true+.
|
56
66
|
#
|
57
67
|
def initialize(options = {})
|
58
68
|
@options = options
|
@@ -61,8 +71,8 @@ module Chingu
|
|
61
71
|
@image = options[:image] if options[:image].is_a? Gosu::Image
|
62
72
|
@image = Image[options[:image]] if options[:image].is_a? String
|
63
73
|
|
64
|
-
@x = options[:x] || 0
|
65
|
-
@y = options[:y] || 0
|
74
|
+
@x = options[:x] || @@x || 0
|
75
|
+
@y = options[:y] || @@y || 0
|
66
76
|
@angle = options[:angle] || 0
|
67
77
|
@zorder = options[:zorder] || @@zorder
|
68
78
|
@center_x = options[:center_x] || options[:center] || @@center_x
|
@@ -72,6 +82,9 @@ module Chingu
|
|
72
82
|
@color = options[:color] || 0xFFFFFFFF
|
73
83
|
@mode = options[:mode] || :default # :additive is also available.
|
74
84
|
|
85
|
+
# Shortcuts for draw_rot arguments
|
86
|
+
@factor = 1
|
87
|
+
|
75
88
|
# gameloop/framework logic
|
76
89
|
@update = options[:update] || true
|
77
90
|
@draw = options[:draw] || true
|
@@ -85,9 +98,32 @@ module Chingu
|
|
85
98
|
@parent.add_game_object(self) if @parent
|
86
99
|
end
|
87
100
|
|
101
|
+
def factor=(factor)
|
102
|
+
@factor = factor
|
103
|
+
@factor_x = @factor_y = @factor
|
104
|
+
end
|
105
|
+
alias :zoom= :factor=
|
106
|
+
def factor
|
107
|
+
@factor
|
108
|
+
end
|
109
|
+
alias :zoom :factor
|
88
110
|
|
89
|
-
|
90
|
-
|
111
|
+
#
|
112
|
+
# Returns true if game object is inside the game window, false if outside
|
113
|
+
#
|
114
|
+
def inside_window?(x = @x, y = @y)
|
115
|
+
x >= 0 && x <= $window.width && y >= 0 && y <= $window.height
|
116
|
+
end
|
117
|
+
|
118
|
+
#
|
119
|
+
#
|
120
|
+
#
|
121
|
+
def outside_window?(x = @x, y = @y)
|
122
|
+
not inside_window?(x,y)
|
123
|
+
end
|
124
|
+
|
125
|
+
def update(time = 1)
|
126
|
+
# Objects gamelogic here, 'time' is the time passed between 2 iterations of the main game loop
|
91
127
|
end
|
92
128
|
|
93
129
|
#
|
data/lib/chingu/game_state.rb
CHANGED
@@ -1,39 +1,115 @@
|
|
1
1
|
module Chingu
|
2
|
+
#
|
3
|
+
# Chingu incorporates a basic push/pop game state system (as discussed here: http://www.gamedev.net/community/forums/topic.asp?topic_id=477320).
|
4
|
+
# Game states is a way of organizing your intros, menus, levels.
|
5
|
+
# 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.
|
6
|
+
#
|
7
|
+
# # A simple GameState-example
|
8
|
+
# class Intro < Chingu::GameState
|
9
|
+
# def update
|
10
|
+
# # game logic here
|
11
|
+
# end
|
12
|
+
#
|
13
|
+
# def draw
|
14
|
+
# # screen manipulation here
|
15
|
+
# end
|
16
|
+
#
|
17
|
+
# # Called when we enter the game state
|
18
|
+
# def setup
|
19
|
+
# @player.angle = 0 # point player upwards
|
20
|
+
# end
|
21
|
+
#
|
22
|
+
# # Called when we leave the current game state
|
23
|
+
# def finalize
|
24
|
+
# push_game_state(Menu) # switch to game state "Menu"
|
25
|
+
# end
|
26
|
+
# end
|
27
|
+
#
|
28
|
+
|
2
29
|
class GameState
|
3
|
-
include Chingu::GameStateHelpers
|
4
|
-
include Chingu::DrawHelpers
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
30
|
+
include Chingu::GameStateHelpers # Easy access to the global game state-queue
|
31
|
+
include Chingu::DrawHelpers # Adds fill(), fade() etc to each game state
|
32
|
+
include Chingu::GameObjectHelpers # adds game_objects_of_class etc ...
|
33
|
+
include Chingu::InputDispatcher # dispatch-helpers
|
34
|
+
include Chingu::InputClient
|
35
|
+
|
36
|
+
attr_reader :options # so jlnr can access his :level-number
|
37
|
+
attr_reader :game_objects, :do_setup
|
9
38
|
|
10
39
|
def initialize(options = {})
|
11
40
|
@options = options
|
12
|
-
@
|
13
|
-
|
41
|
+
@do_setup = options[:setup] || true
|
42
|
+
|
43
|
+
@game_objects = Set.new
|
44
|
+
@input_clients = Set.new # Set is like a unique Array with Hash lookupspeed
|
45
|
+
|
14
46
|
$window.game_state_manager.inside_state = self
|
15
|
-
setup
|
16
47
|
end
|
17
48
|
|
18
|
-
|
19
|
-
|
49
|
+
#
|
50
|
+
# An unique identifier for the GameState-class,
|
51
|
+
# Used in game state manager to keep track of created states.
|
52
|
+
#
|
53
|
+
def to_sym
|
54
|
+
self.class.to_s.to_sym
|
55
|
+
end
|
56
|
+
|
57
|
+
def add_game_object(object)
|
58
|
+
@game_objects << object
|
59
|
+
end
|
60
|
+
def remove_game_object(object)
|
61
|
+
@input_clients.delete(object)
|
20
62
|
end
|
21
63
|
|
22
64
|
def setup
|
65
|
+
# Your game state setup logic here.
|
23
66
|
end
|
24
67
|
|
68
|
+
#
|
69
|
+
# Called when a button is pressed and a game state is active
|
70
|
+
#
|
25
71
|
def button_down(id)
|
72
|
+
dispatch_button_down(id, self)
|
73
|
+
@input_clients.each { |object| dispatch_button_down(id, object) }
|
26
74
|
end
|
27
75
|
|
76
|
+
#
|
77
|
+
# Called when a button is released and a game state active
|
78
|
+
#
|
28
79
|
def button_up(id)
|
80
|
+
dispatch_button_up(id, self)
|
81
|
+
@input_clients.each { |object| dispatch_button_up(id, object) }
|
29
82
|
end
|
30
|
-
|
31
|
-
|
32
|
-
|
83
|
+
|
84
|
+
#
|
85
|
+
# Calls update on each game object that has current game state as parent (created inside that game state)
|
86
|
+
#
|
87
|
+
def update(time = 1)
|
88
|
+
dispatch_input_for(self)
|
89
|
+
@input_clients.each { |game_object| dispatch_input_for(game_object) }
|
90
|
+
|
91
|
+
@game_objects.each { |object| object.update(time) }
|
33
92
|
end
|
34
93
|
|
94
|
+
#
|
95
|
+
# Calls Draw on each game object that has current game state as parent (created inside that game state)
|
96
|
+
#
|
35
97
|
def draw
|
36
98
|
@game_objects.each { |object| object.draw }
|
37
99
|
end
|
100
|
+
|
101
|
+
#
|
102
|
+
# Closes game state by poping it off the stack (and activating the game state below)
|
103
|
+
#
|
104
|
+
def close
|
105
|
+
pop_game_state
|
106
|
+
end
|
107
|
+
|
108
|
+
#
|
109
|
+
# Closes main window and terminates the application
|
110
|
+
#
|
111
|
+
def close_game
|
112
|
+
$window.close
|
113
|
+
end
|
38
114
|
end
|
39
115
|
end
|
@@ -1,47 +1,103 @@
|
|
1
|
-
module Chingu
|
1
|
+
module Chingu
|
2
|
+
#
|
3
|
+
# GameStateManger is responsible for keeping track of game states with a simple pop/push stack.
|
4
|
+
#
|
5
|
+
# Chingu::Window automatically creates a @game_state_manager and makes it accessible in our game loop.
|
6
|
+
# By default the game loop calls update() / draw() on @game_state_manager
|
7
|
+
#
|
2
8
|
class GameStateManager
|
3
9
|
attr_accessor :inside_state
|
4
|
-
attr_reader :states
|
10
|
+
attr_reader :states, :created_states
|
5
11
|
|
6
12
|
def initialize
|
7
13
|
@inside_state = nil
|
8
14
|
@states = []
|
15
|
+
@created_states = {}
|
9
16
|
end
|
10
17
|
|
11
18
|
#
|
12
19
|
# Gets the currently active gamestate (top of stack)
|
13
20
|
#
|
14
|
-
def
|
21
|
+
def current_state
|
15
22
|
@states.last
|
16
23
|
end
|
17
24
|
|
18
25
|
#
|
19
|
-
# Adds a state to the
|
26
|
+
# Adds a state to the game state-stack and activates it
|
20
27
|
#
|
21
|
-
def push_state(state)
|
22
|
-
|
28
|
+
def push_state(state, options = {})
|
29
|
+
new_state = nil
|
30
|
+
|
31
|
+
#
|
32
|
+
# If state is a GameState-instance, just queue it
|
33
|
+
#
|
34
|
+
if state.is_a? Chingu::GameState
|
35
|
+
new_state = state
|
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
|
40
|
+
|
41
|
+
if @created_states[state.to_s]
|
42
|
+
new_state = @created_states[state.to_s]
|
43
|
+
else
|
44
|
+
new_state = state.new(options)
|
45
|
+
@created_states[state.class.to_s] = new_state
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
#
|
50
|
+
# If the new state is all good
|
51
|
+
#
|
52
|
+
if new_state
|
53
|
+
# Give the soon-to-be-disabled state a chance to clean up by calling finalize() on it.
|
54
|
+
current_state.finalize if current_state.respond_to? :finalize
|
55
|
+
|
56
|
+
# Call setup
|
57
|
+
new_state.setup if new_state.do_setup
|
58
|
+
|
59
|
+
# Push new state on top of stack and therefore making it active
|
60
|
+
@states.push(new_state)
|
61
|
+
end
|
23
62
|
end
|
24
63
|
|
25
64
|
#
|
26
|
-
# Pops a state off the
|
27
|
-
#
|
28
|
-
def pop_state
|
65
|
+
# Pops a state off the game state-stack, activating the previous one.
|
66
|
+
#
|
67
|
+
def pop_state(options = {})
|
68
|
+
#
|
69
|
+
# Give the soon-to-be-disabled state a chance to clean up by calling finalize() on it.
|
70
|
+
#
|
71
|
+
current_state.finalize if current_state.respond_to? :finalize
|
72
|
+
|
73
|
+
#
|
74
|
+
# Activate the game state "bellow" current one with a simple Array.pop
|
75
|
+
#
|
29
76
|
@states.pop
|
77
|
+
|
78
|
+
# Call setup on the new current state
|
79
|
+
current_state.setup unless options[:setup] == false
|
30
80
|
end
|
31
81
|
|
32
82
|
#
|
33
|
-
# Returns the previous
|
83
|
+
# Returns the previous game state
|
34
84
|
#
|
35
85
|
def previous_state
|
36
|
-
@states[@states.index(
|
86
|
+
@states[@states.index(current_state)-1]
|
37
87
|
end
|
38
|
-
|
39
88
|
alias :prev_state previous_state
|
40
89
|
|
41
90
|
#
|
42
|
-
#
|
91
|
+
# Remove all game states from stack
|
92
|
+
#
|
93
|
+
def clear_states
|
94
|
+
@states.clear
|
95
|
+
end
|
96
|
+
|
97
|
+
#
|
98
|
+
# Pops through all game states until matching a given game state
|
43
99
|
#
|
44
|
-
def
|
100
|
+
def pop_until_game_state(new_state)
|
45
101
|
while (state = @states.pop)
|
46
102
|
break if state == new_state
|
47
103
|
end
|
@@ -58,27 +114,27 @@ module Chingu
|
|
58
114
|
# Called before #update when the user pressed a button while the window had the focus.
|
59
115
|
#
|
60
116
|
def button_down(id)
|
61
|
-
|
117
|
+
current_state.button_down(id) if current_state
|
62
118
|
end
|
63
119
|
|
64
120
|
#
|
65
121
|
# Called when the user released a button.
|
66
122
|
#
|
67
123
|
def button_up(id)
|
68
|
-
|
124
|
+
current_state.button_up(id) if current_state
|
69
125
|
end
|
70
126
|
|
71
127
|
#
|
72
128
|
# Calls #update on the current gamestate, if there is one.
|
73
129
|
#
|
74
|
-
def update
|
75
|
-
|
130
|
+
def update(time = 1)
|
131
|
+
current_state.update(time) if current_state
|
76
132
|
end
|
77
133
|
#
|
78
134
|
# Calls draw() on the current gamestate, if there is one.
|
79
135
|
#
|
80
136
|
def draw
|
81
|
-
|
137
|
+
current_state.draw if current_state
|
82
138
|
end
|
83
139
|
end
|
84
140
|
end
|