chingu 0.5.9.4 → 0.6
Sign up to get free protection for your applications and to get access to all the features.
- data.tar.gz.sig +0 -0
- data/History.txt +25 -21
- data/Manifest.txt +3 -0
- data/README.rdoc +27 -3
- data/chingu.gemspec +3 -3
- data/examples/example11.rb +15 -14
- data/examples/example13.rb +1 -1
- data/examples/example14.rb +124 -0
- data/examples/example2.rb +10 -6
- data/examples/example9.rb +4 -14
- data/examples/game1.rb +87 -76
- data/examples/high_score_list.yml +2 -2
- data/lib/chingu.rb +4 -1
- data/lib/chingu/basic_game_object.rb +34 -23
- data/lib/chingu/game_state.rb +24 -8
- data/lib/chingu/helpers/gfx.rb +13 -1
- data/lib/chingu/helpers/input_client.rb +39 -2
- data/lib/chingu/helpers/rotation_center.rb +7 -1
- data/lib/chingu/input.rb +14 -9
- data/lib/chingu/traits/bounding_box.rb +63 -0
- data/lib/chingu/traits/collision_detection.rb +8 -39
- data/lib/chingu/traits/effect.rb +3 -8
- data/lib/chingu/traits/radius.rb +55 -0
- data/lib/chingu/traits/retrofy.rb +9 -11
- data/lib/chingu/traits/timer.rb +3 -4
- data/lib/chingu/traits/velocity.rb +3 -12
- metadata +5 -2
- metadata.gz.sig +0 -0
data/lib/chingu.rb
CHANGED
@@ -8,22 +8,38 @@ module Chingu
|
|
8
8
|
class BasicGameObject
|
9
9
|
attr_reader :options, :paused, :visible
|
10
10
|
attr_accessor :parent
|
11
|
-
|
11
|
+
|
12
|
+
def self.trait_options; @trait_options; end
|
13
|
+
def trait_options; self.class.trait_options; end
|
14
|
+
|
12
15
|
#
|
13
16
|
# Adds a trait or traits to a certain game class
|
14
17
|
# Executes a standard ruby "include" the specified module
|
15
18
|
#
|
16
|
-
def self.has_trait(
|
17
|
-
|
19
|
+
def self.has_trait(trait, options = {})
|
20
|
+
@trait_options ||= Hash.new
|
21
|
+
if trait.is_a?(::Symbol) || trait.is_a?(::String)
|
22
|
+
begin
|
23
|
+
# Convert user-given symbol (eg. :timer) to a Module (eg. Chingu::Traits::Timer)
|
24
|
+
mod = Chingu::Traits.const_get(Chingu::Inflector.camelize(trait))
|
25
|
+
|
26
|
+
# Include the module, which will add the containing methods as instance methods
|
27
|
+
include mod
|
28
|
+
|
29
|
+
# Add possible classmethods defined in sub-module ClassMethods (eg: Chingu::Traits::Timer::ClassMethods)
|
30
|
+
mod2 = mod.const_get("ClassMethods")
|
31
|
+
extend mod2
|
32
|
+
|
33
|
+
# If the newly included trait has a initialize_trait method...
|
34
|
+
# ... call it with the options provided with the has_trait-call
|
35
|
+
initialize_trait(options) if mod2.method_defined?(:initialize_trait)
|
36
|
+
rescue
|
37
|
+
end
|
38
|
+
end
|
18
39
|
end
|
19
40
|
|
20
|
-
# See #has_trait
|
21
41
|
def self.has_traits(*traits)
|
22
|
-
Array(traits).each
|
23
|
-
if trait.is_a?(::Symbol) || trait.is_a?(::String)
|
24
|
-
include Chingu::Traits.const_get(Chingu::Inflector.camelize(trait))
|
25
|
-
end
|
26
|
-
end
|
42
|
+
Array(traits).each { |trait| has_trait trait }
|
27
43
|
end
|
28
44
|
|
29
45
|
#
|
@@ -122,20 +138,15 @@ module Chingu
|
|
122
138
|
@visible == true
|
123
139
|
end
|
124
140
|
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
def
|
129
|
-
|
130
|
-
|
131
|
-
def draw_trait
|
132
|
-
end
|
133
|
-
|
134
|
-
def update
|
135
|
-
end
|
136
|
-
|
137
|
-
def draw
|
138
|
-
end
|
141
|
+
#
|
142
|
+
# Empty placeholders to be overridden
|
143
|
+
#
|
144
|
+
def self.initialize_trait(options); end
|
145
|
+
def setup_trait(options); end
|
146
|
+
def update_trait; end
|
147
|
+
def draw_trait; end
|
148
|
+
def update; end
|
149
|
+
def draw; end
|
139
150
|
|
140
151
|
|
141
152
|
#
|
data/lib/chingu/game_state.rb
CHANGED
@@ -58,21 +58,37 @@ module Chingu
|
|
58
58
|
attr_reader :options
|
59
59
|
attr_accessor :game_state_manager, :game_objects
|
60
60
|
|
61
|
+
def self.trait_options; @trait_options; end
|
62
|
+
def trait_options; self.class.trait_options; end
|
63
|
+
|
61
64
|
#
|
62
65
|
# Adds a trait or traits to a certain game class
|
63
66
|
# Executes a standard ruby "include" the specified module
|
64
67
|
#
|
65
|
-
def self.has_trait(
|
66
|
-
|
68
|
+
def self.has_trait(trait, options = {})
|
69
|
+
@trait_options ||= Hash.new
|
70
|
+
if trait.is_a?(::Symbol) || trait.is_a?(::String)
|
71
|
+
begin
|
72
|
+
# Convert user-given symbol (eg. :timer) to a Module (eg. Chingu::Traits::Timer)
|
73
|
+
mod = Chingu::Traits.const_get(Chingu::Inflector.camelize(trait))
|
74
|
+
|
75
|
+
# Include the module, which will add the containing methods as instance methods
|
76
|
+
include mod
|
77
|
+
|
78
|
+
# Add possible classmethods defined in sub-module ClassMethods (eg: Chingu::Traits::Timer::ClassMethods)
|
79
|
+
mod2 = mod.const_get("ClassMethods")
|
80
|
+
extend mod2
|
81
|
+
|
82
|
+
# If the newly included trait has a initialize_trait method...
|
83
|
+
# ... call it with the options provided with the has_trait-call
|
84
|
+
initialize_trait(options) if mod2.method_defined?(:initialize_trait)
|
85
|
+
rescue
|
86
|
+
end
|
87
|
+
end
|
67
88
|
end
|
68
89
|
|
69
|
-
# See #has_trait
|
70
90
|
def self.has_traits(*traits)
|
71
|
-
Array(traits).each
|
72
|
-
if trait.is_a?(::Symbol) || trait.is_a?(::String)
|
73
|
-
include Chingu::Traits.const_get(Chingu::Inflector.camelize(trait))
|
74
|
-
end
|
75
|
-
end
|
91
|
+
Array(traits).each { |trait| has_trait trait }
|
76
92
|
end
|
77
93
|
|
78
94
|
|
data/lib/chingu/helpers/gfx.rb
CHANGED
@@ -98,7 +98,7 @@ module Chingu
|
|
98
98
|
end
|
99
99
|
|
100
100
|
#
|
101
|
-
# Draws
|
101
|
+
# Draws an unfilled rect in given color
|
102
102
|
#
|
103
103
|
def draw_rect(rect, color, zorder)
|
104
104
|
$window.draw_line(rect.x, rect.y, color, rect.right, rect.y, color, zorder)
|
@@ -107,6 +107,18 @@ module Chingu
|
|
107
107
|
$window.draw_line(rect.x, rect.bottom, color, rect.x, rect.y, color, zorder)
|
108
108
|
end
|
109
109
|
|
110
|
+
|
111
|
+
#
|
112
|
+
# Draws an unfilled circle, thanks shawn24!
|
113
|
+
#
|
114
|
+
CIRCLE_STEP = 10
|
115
|
+
def draw_circle(cx,cy,r,color)
|
116
|
+
0.step(360, CIRCLE_STEP) do |a1|
|
117
|
+
a2 = a1 + CIRCLE_STEP
|
118
|
+
$window.draw_line cx + offset_x(a1, r), cy + offset_y(a1, r), color, cx + offset_x(a2, r), cy + offset_y(a2, r), color, 9999
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
110
122
|
#
|
111
123
|
# Fills a given Rect 'rect' with Color 'color', drawing with zorder 'zorder'
|
112
124
|
#
|
@@ -29,11 +29,48 @@ module Chingu
|
|
29
29
|
# 1) Initialized an inputmap
|
30
30
|
# 2) notifies the parent (could be main Window or a GameState) that the object wants input
|
31
31
|
#
|
32
|
-
# In Chingu this is mixed into Window, GameState and GameObject
|
32
|
+
# In Chingu this is mixed into Window, GameState and GameObject.
|
33
|
+
#
|
34
|
+
# You can specify input in 3 different natural formats, the bellow 3 lines does the same thing:
|
35
|
+
#
|
36
|
+
# The normal way, this makes left_arrow key call method "left", and the same thing for right.
|
37
|
+
# self.input = {:left => :left, :right => :right}
|
38
|
+
#
|
39
|
+
# The shortened way, does exaclty as the above.
|
40
|
+
# self.input = [:left, :right]
|
41
|
+
#
|
42
|
+
# The multi-way, adds :a as trigger for method left, and :d as trigger for method :right
|
43
|
+
# self.input = {[:a, :left] => :left, [:right, :d] => :right}
|
44
|
+
#
|
33
45
|
#
|
34
46
|
module InputClient
|
35
47
|
def input=(input_map)
|
36
|
-
@input
|
48
|
+
@input ||= Hash.new
|
49
|
+
#@input = input_map
|
50
|
+
|
51
|
+
if input_map.is_a? Array
|
52
|
+
#
|
53
|
+
# Un-nest input_map [:left, :right, :space]
|
54
|
+
# Into: { :left => :left, :right => :right, :space => :space}
|
55
|
+
#
|
56
|
+
input_map.each do |symbol|
|
57
|
+
@input[symbol] = symbol
|
58
|
+
end
|
59
|
+
elsif input_map.is_a? Hash
|
60
|
+
#
|
61
|
+
# Un-nest input: { [:pad_left, :arrow_left, :a] => :move_left }
|
62
|
+
# Into: { :pad_left => :move_left, :arrow_left => :move_left, :a => :move_left }
|
63
|
+
#
|
64
|
+
input_map.each_pair do |possible_array, action|
|
65
|
+
if possible_array.is_a? Array
|
66
|
+
possible_array.each do |symbol|
|
67
|
+
@input[symbol] = action
|
68
|
+
end
|
69
|
+
elsif possible_array.is_a? Symbol
|
70
|
+
@input[possible_array] = action
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
37
74
|
|
38
75
|
if @parent
|
39
76
|
if (@input == nil || @input == {})
|
@@ -74,10 +74,16 @@ module Chingu
|
|
74
74
|
# They're also available (hey, hashlookups are speedy) with "middle" instead of "center" since
|
75
75
|
# those 2 words basicly have the same meaning and are both understandable.
|
76
76
|
#
|
77
|
-
def rotation_center(alignment)
|
77
|
+
def rotation_center(alignment = nil)
|
78
|
+
#return @rotation_center unless alignment
|
79
|
+
#@rotation_center = alignment
|
78
80
|
@center_x, @center_y = @@rotation_centers[alignment.to_sym]
|
79
81
|
end
|
80
82
|
|
83
|
+
def rotation_center=(alignment)
|
84
|
+
rotation_center(alignment)
|
85
|
+
end
|
86
|
+
|
81
87
|
end
|
82
88
|
end
|
83
89
|
end
|
data/lib/chingu/input.rb
CHANGED
@@ -20,13 +20,13 @@
|
|
20
20
|
#++
|
21
21
|
|
22
22
|
module Chingu
|
23
|
-
|
24
|
-
|
25
|
-
|
23
|
+
module Input
|
24
|
+
include Gosu::Button
|
25
|
+
|
26
26
|
#
|
27
27
|
# Ruby symbols describing http://www.libgosu.org/rdoc/classes/Gosu.html
|
28
28
|
#
|
29
|
-
|
29
|
+
CONSTANT_TO_SYMBOL = {
|
30
30
|
Kb0 => [:zero],
|
31
31
|
Kb1 => [:one],
|
32
32
|
Kb2 => [:two],
|
@@ -75,11 +75,11 @@ module Chingu
|
|
75
75
|
MsWheelDown => [:mouse_wheel_down, :wheel_down],
|
76
76
|
MsWheelUp => [:mouse_wheel_up, :wheel_up],
|
77
77
|
|
78
|
-
GpDown
|
79
|
-
GpLeft
|
80
|
-
GpRight
|
78
|
+
GpDown => [:gamepad_down, :gp_down, :pad_down],
|
79
|
+
GpLeft => [:gamepad_left, :gp_left, :pad_left],
|
80
|
+
GpRight => [:gamepad_right, :gp_right, :pad_right],
|
81
81
|
GpUp => [:gamepad_up, :gp_up, :pad_up]
|
82
|
-
|
82
|
+
}
|
83
83
|
|
84
84
|
# Letters, A-Z
|
85
85
|
("A".."Z").each do |letter|
|
@@ -99,11 +99,16 @@ module Chingu
|
|
99
99
|
#F-keys, F1-F12
|
100
100
|
(1..12).each do |number|
|
101
101
|
CONSTANT_TO_SYMBOL[eval("KbF#{number.to_s}")] = ["f#{number.to_s}".to_sym]
|
102
|
+
CONSTANT_TO_SYMBOL[eval("KbF#{number.to_s}")] = ["F#{number.to_s}".to_sym]
|
102
103
|
end
|
103
104
|
|
104
105
|
# Gamepad-buttons 0-15
|
105
106
|
(0..15).each do |number|
|
106
107
|
CONSTANT_TO_SYMBOL[eval("GpButton#{number.to_s}")] = ["gamepad_button_#{number.to_s}"]
|
108
|
+
CONSTANT_TO_SYMBOL[eval("GpButton#{number.to_s}")] = ["gamepad_#{number.to_s}"]
|
109
|
+
CONSTANT_TO_SYMBOL[eval("GpButton#{number.to_s}")] = ["pad_button_#{number.to_s}"]
|
110
|
+
CONSTANT_TO_SYMBOL[eval("GpButton#{number.to_s}")] = ["pad_#{number.to_s}"]
|
111
|
+
CONSTANT_TO_SYMBOL[eval("GpButton#{number.to_s}")] = ["gp_#{number.to_s}"]
|
107
112
|
end
|
108
113
|
|
109
114
|
#
|
@@ -117,5 +122,5 @@ module Chingu
|
|
117
122
|
end
|
118
123
|
end
|
119
124
|
|
120
|
-
|
125
|
+
end
|
121
126
|
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
#--
|
2
|
+
#
|
3
|
+
# Chingu -- OpenGL accelerated 2D game framework for Ruby
|
4
|
+
# Copyright (C) 2009 ippa / ippa@rubylicio.us
|
5
|
+
#
|
6
|
+
# This library is free software; you can redistribute it and/or
|
7
|
+
# modify it under the terms of the GNU Lesser General Public
|
8
|
+
# License as published by the Free Software Foundation; either
|
9
|
+
# version 2.1 of the License, or (at your option) any later version.
|
10
|
+
#
|
11
|
+
# This library is distributed in the hope that it will be useful,
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
14
|
+
# Lesser General Public License for more details.
|
15
|
+
#
|
16
|
+
# You should have received a copy of the GNU Lesser General Public
|
17
|
+
# License along with this library; if not, write to the Free Software
|
18
|
+
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
19
|
+
#
|
20
|
+
#++
|
21
|
+
|
22
|
+
module Chingu
|
23
|
+
module Traits
|
24
|
+
#
|
25
|
+
# Providing a bounding_box-method which generates a AABB on the fly from:
|
26
|
+
# x, y, factor_x, factor_y and rotation_center
|
27
|
+
#
|
28
|
+
module BoundingBox
|
29
|
+
|
30
|
+
module ClassMethods
|
31
|
+
def initialize_trait(options = {})
|
32
|
+
## puts "bounding_box initialize_trait #{options}"
|
33
|
+
@trait_options[:bounding_box] = options
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def bounding_box
|
38
|
+
width = self.image.width * self.factor_x.abs
|
39
|
+
height = self.image.height * self.factor_y.abs
|
40
|
+
|
41
|
+
if trait_options[:bounding_box][:scale]
|
42
|
+
width = width * trait_options[:bounding_box][:scale]
|
43
|
+
height = height * trait_options[:bounding_box][:scale]
|
44
|
+
end
|
45
|
+
|
46
|
+
x = self.x - (width * self.center_x.abs)
|
47
|
+
y = self.y - (height * self.center_y.abs)
|
48
|
+
|
49
|
+
return Rect.new(x, y, width, height)
|
50
|
+
end
|
51
|
+
alias :bb :bounding_box
|
52
|
+
|
53
|
+
def draw_trait
|
54
|
+
if trait_options[:bounding_box][:debug]
|
55
|
+
$window.draw_rect(self.bounding_box, Chingu::DEBUG_COLOR, Chingu::DEBUG_ZORDER)
|
56
|
+
end
|
57
|
+
|
58
|
+
super
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -28,33 +28,16 @@ module Chingu
|
|
28
28
|
#
|
29
29
|
# SEE: http://www.shmup-dev.com/forum/index.php?board=65.0
|
30
30
|
#
|
31
|
-
# Makes use of
|
32
|
-
#
|
33
|
-
#
|
34
|
-
# @detect_collisions - [true|false], should object be checked for collisions with Object.each_collision
|
31
|
+
# Makes use of 2 attributes
|
32
|
+
# bounding_box - a Rect-instance, uses in bounding_box collisions
|
33
|
+
# radius - a number
|
35
34
|
#
|
36
35
|
module CollisionDetection
|
37
|
-
attr_accessor :bounding_box, :radius
|
38
|
-
## attr_accessor :detect_collisions # slowed down example9 with 3 fps
|
39
36
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
#
|
45
|
-
# Automaticly try to set a bounding_box and radius. Don't overwrite if they already exists.
|
46
|
-
#
|
47
|
-
def setup_trait(options)
|
48
|
-
if @x and @y and @image
|
49
|
-
@bounding_box ||= Rect.new(@x, @y, @image.width, @image.height)
|
50
|
-
end
|
51
|
-
|
52
|
-
if @image
|
53
|
-
@radius ||= (@image.height + @image.width) / 2 * 0.80
|
37
|
+
module ClassMethods
|
38
|
+
def initialize_trait(options = {})
|
39
|
+
@trait_options[:collision_detection] = options
|
54
40
|
end
|
55
|
-
|
56
|
-
## @detect_collisions = true
|
57
|
-
super
|
58
41
|
end
|
59
42
|
|
60
43
|
#
|
@@ -83,18 +66,6 @@ module Chingu
|
|
83
66
|
distance(self.x, self.y, object2.x, object2.y) < self.radius + object2.radius
|
84
67
|
end
|
85
68
|
|
86
|
-
#
|
87
|
-
# Have bounding box follow game objects x/y
|
88
|
-
#
|
89
|
-
def update_trait
|
90
|
-
if defined?(@bounding_box) && @bounding_box.is_a?(Rect)
|
91
|
-
@bounding_box.x = self.x
|
92
|
-
@bounding_box.y = self.y
|
93
|
-
end
|
94
|
-
|
95
|
-
super
|
96
|
-
end
|
97
|
-
|
98
69
|
#
|
99
70
|
# Collides self with all objects of given classes
|
100
71
|
# Yields self and the objects it collides with
|
@@ -114,12 +85,11 @@ module Chingu
|
|
114
85
|
def each_radius_collision(klasses = [])
|
115
86
|
Array(klasses).each do |klass|
|
116
87
|
klass.all.each do |object|
|
117
|
-
yield(self, object) if distance(
|
88
|
+
yield(self, object) if distance(self.x, self.y, object.x, object.y) < self.radius + object.radius
|
118
89
|
end
|
119
90
|
end
|
120
91
|
end
|
121
92
|
|
122
|
-
|
123
93
|
#
|
124
94
|
# Explicit bounding_box-collision
|
125
95
|
# Works like each_collision but with inline-code for speedups
|
@@ -127,14 +97,13 @@ module Chingu
|
|
127
97
|
def each_bounding_box_collision(klasses = [])
|
128
98
|
Array(klasses).each do |klass|
|
129
99
|
klass.all.each do |object|
|
130
|
-
yield(self, object) if
|
100
|
+
yield(self, object) if self.bounding_box.collide_rect?(object.bounding_box)
|
131
101
|
end
|
132
102
|
end
|
133
103
|
end
|
134
104
|
|
135
105
|
|
136
106
|
module ClassMethods
|
137
|
-
|
138
107
|
#
|
139
108
|
# Works like each_collision but with inline-code for speedups
|
140
109
|
#
|