chingu 0.8.0.5 → 0.8.1
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/benchmarks/array_vs_hash.rb +20 -0
- data/benchmarks/game_object_list_benchmark.rb +92 -0
- data/benchmarks/game_objects_benchmark.rb +48 -12
- data/benchmarks/lookup_benchmark.rb +9 -0
- data/benchmarks/trait_benchmark.rb +62 -0
- data/benchmarks/window_benchmark.rb +37 -0
- data/chingu.gemspec +10 -2
- data/examples/example17_gosu_tutorial.rb +3 -2
- data/examples/example21_sidescroller_with_edit.rb +6 -4
- data/examples/example23_chipmunk.rb +1 -0
- data/lib/chingu.rb +1 -1
- data/lib/chingu/animation.rb +2 -1
- data/lib/chingu/basic_game_object.rb +25 -9
- data/lib/chingu/game_object_list.rb +42 -26
- data/lib/chingu/game_object_map.rb +31 -8
- data/lib/chingu/helpers/game_object.rb +14 -0
- data/lib/chingu/traits/retrofy.rb +18 -10
- data/lib/chingu/traits/simple_sprite.rb +252 -0
- data/lib/chingu/traits/sprite.rb +22 -11
- data/spec/chingu/basic_game_object_spec.rb +27 -11
- data/spec/chingu/console_spec.rb +5 -1
- data/spec/chingu/game_object_list_spec.rb +19 -1
- data/spec/chingu/game_object_map_spec.rb +96 -0
- data/spec/chingu/game_object_spec.rb +2 -0
- metadata +11 -4
@@ -8,6 +8,8 @@ module Chingu
|
|
8
8
|
# It will also acts as a container for the trait-system of chingu.
|
9
9
|
#
|
10
10
|
class BasicGameObject
|
11
|
+
class << self; attr_accessor :instances; end
|
12
|
+
|
11
13
|
include Chingu::Helpers::ClassInheritableAccessor # adds classmethod class_inheritable_accessor
|
12
14
|
|
13
15
|
attr_reader :options, :paused
|
@@ -16,7 +18,7 @@ module Chingu
|
|
16
18
|
class_inheritable_accessor :trait_options
|
17
19
|
@trait_options = Hash.new
|
18
20
|
def trait_options; self.class.trait_options; end
|
19
|
-
|
21
|
+
|
20
22
|
#
|
21
23
|
# Adds a trait or traits to a certain game class
|
22
24
|
# Executes a standard ruby "include" the specified module
|
@@ -66,7 +68,10 @@ module Chingu
|
|
66
68
|
def initialize(options = {})
|
67
69
|
@options = options
|
68
70
|
@parent = options[:parent]
|
69
|
-
|
71
|
+
|
72
|
+
self.class.instances ||= Array.new
|
73
|
+
self.class.instances << self
|
74
|
+
|
70
75
|
#
|
71
76
|
# A GameObject either belong to a GameState or our mainwindow ($window)
|
72
77
|
#
|
@@ -79,7 +84,7 @@ module Chingu
|
|
79
84
|
# which then will pass it on to the next setup_trait() with a super-call.
|
80
85
|
setup_trait(options)
|
81
86
|
|
82
|
-
setup
|
87
|
+
setup
|
83
88
|
end
|
84
89
|
|
85
90
|
#
|
@@ -99,6 +104,12 @@ module Chingu
|
|
99
104
|
#
|
100
105
|
instance.parent.add_game_object(instance) if instance.parent
|
101
106
|
|
107
|
+
#
|
108
|
+
# Keep track of instances in class-variable
|
109
|
+
# Used for quick access to all isntances of a certain class, for example Enemy.all
|
110
|
+
#
|
111
|
+
#instances ||= Array.new
|
112
|
+
#instances << instance
|
102
113
|
|
103
114
|
return instance
|
104
115
|
end
|
@@ -107,6 +118,7 @@ module Chingu
|
|
107
118
|
# Disable automatic calling of update() and update_trait() each game loop
|
108
119
|
#
|
109
120
|
def pause!
|
121
|
+
@parent.game_objects.pause_game_object(self) if @parent && @paused == false
|
110
122
|
@paused = true
|
111
123
|
end
|
112
124
|
alias :pause :pause!
|
@@ -115,6 +127,7 @@ module Chingu
|
|
115
127
|
# Enable automatic calling of update() and update_trait() each game loop
|
116
128
|
#
|
117
129
|
def unpause!
|
130
|
+
@parent.game_objects.unpause_game_object(self) if @parent && @paused == true
|
118
131
|
@paused = false
|
119
132
|
end
|
120
133
|
alias :unpause :unpause!
|
@@ -153,8 +166,10 @@ module Chingu
|
|
153
166
|
# Bullet.all.each do {} # Iterate through all bullets in current game state
|
154
167
|
#
|
155
168
|
def self.all
|
156
|
-
|
157
|
-
|
169
|
+
instances ? instances.dup : []
|
170
|
+
# instances ? instances.keys : [] # for hash instance
|
171
|
+
# $window.current_scope.game_objects.of_class(self).dup # old school way
|
172
|
+
end
|
158
173
|
|
159
174
|
#
|
160
175
|
# As Array.each on the instances of the current class
|
@@ -177,12 +192,11 @@ module Chingu
|
|
177
192
|
all.select { |object| yield object }
|
178
193
|
end
|
179
194
|
|
180
|
-
|
181
195
|
#
|
182
196
|
# Returns the total amount of game objects based on this class
|
183
197
|
#
|
184
198
|
def self.size
|
185
|
-
|
199
|
+
all.size
|
186
200
|
end
|
187
201
|
|
188
202
|
#
|
@@ -200,7 +214,8 @@ module Chingu
|
|
200
214
|
# Bullet.destroy_all # Removes all Bullet objects from the game
|
201
215
|
#
|
202
216
|
def self.destroy_all
|
203
|
-
|
217
|
+
all.each { |game_object| game_object.parent.remove_game_object(game_object) }
|
218
|
+
instances.clear if instances
|
204
219
|
end
|
205
220
|
|
206
221
|
#
|
@@ -208,7 +223,8 @@ module Chingu
|
|
208
223
|
# If the object isn't being managed by Chingu (ie. you're doing manual update/draw calls) the object is only frozen, not removed from any updae cycle (because you are controlling that).
|
209
224
|
#
|
210
225
|
def destroy
|
211
|
-
@parent.remove_game_object(self)
|
226
|
+
@parent.remove_game_object(self) if @parent
|
227
|
+
self.class.instances.delete(self)
|
212
228
|
end
|
213
229
|
alias :destroy! :destroy
|
214
230
|
end
|
@@ -26,11 +26,16 @@ module Chingu
|
|
26
26
|
# An instance of GameObjectList is automaticly created as "game_objects" if using Chingu::Window
|
27
27
|
#
|
28
28
|
class GameObjectList
|
29
|
+
attr_reader :visible_game_objects, :unpaused_game_objects
|
29
30
|
|
30
31
|
def initialize(options = {})
|
31
32
|
@game_objects = options[:game_objects] || []
|
32
|
-
@
|
33
|
-
@
|
33
|
+
@visible_game_objects = []
|
34
|
+
@unpaused_game_objects = []
|
35
|
+
|
36
|
+
#@game_objects = {}
|
37
|
+
#@visible_game_objects = {}
|
38
|
+
#@unpaused_game_objects = {}
|
34
39
|
end
|
35
40
|
|
36
41
|
def to_s
|
@@ -42,23 +47,42 @@ module Chingu
|
|
42
47
|
end
|
43
48
|
|
44
49
|
def destroy_all
|
45
|
-
@game_objects.
|
50
|
+
@game_objects.each { |game_object| game_object.destroy }
|
46
51
|
end
|
47
52
|
alias :clear :destroy_all
|
48
53
|
alias :remove_all :destroy_all
|
49
54
|
|
55
|
+
def show_game_object(object)
|
56
|
+
@visible_game_objects.push(object)
|
57
|
+
end
|
58
|
+
def hide_game_object(object)
|
59
|
+
@visible_game_objects.delete(object)
|
60
|
+
end
|
61
|
+
def pause_game_object(object)
|
62
|
+
@unpaused_game_objects.delete(object)
|
63
|
+
end
|
64
|
+
def unpause_game_object(object)
|
65
|
+
@unpaused_game_objects.push(object)
|
66
|
+
end
|
67
|
+
|
50
68
|
def add_game_object(object)
|
51
69
|
@game_objects.push(object)
|
52
|
-
|
70
|
+
@visible_game_objects.push(object) if object.respond_to?(:visible) && object.visible
|
71
|
+
@unpaused_game_objects.push(object) if object.respond_to?(:paused) && !object.paused
|
72
|
+
|
73
|
+
#@game_objects[object] = true
|
74
|
+
#@visible_game_objects[object] = true if object.respond_to?(:visible) && object.visible
|
75
|
+
#@unpaused_game_objects[object] = true if object.respond_to?(:paused) && !object.paused
|
53
76
|
end
|
54
77
|
|
55
78
|
def remove_game_object(object)
|
56
79
|
@game_objects.delete(object)
|
57
|
-
|
80
|
+
@visible_game_objects.delete(object)
|
81
|
+
@unpaused_game_objects.delete(object)
|
58
82
|
end
|
59
83
|
|
60
84
|
def destroy_if
|
61
|
-
@game_objects.
|
85
|
+
@game_objects.select { |object| object.destroy if yield(object) }
|
62
86
|
end
|
63
87
|
|
64
88
|
def size
|
@@ -68,27 +92,28 @@ module Chingu
|
|
68
92
|
def empty?
|
69
93
|
@game_objects.empty?
|
70
94
|
end
|
95
|
+
|
96
|
+
def update
|
97
|
+
@unpaused_game_objects.each { |go| go.update_trait; go.update; }
|
98
|
+
end
|
99
|
+
def force_update
|
100
|
+
@game_objects.each { |go| go.update_trait; go.update; }
|
101
|
+
end
|
71
102
|
|
72
103
|
def draw
|
73
|
-
@
|
74
|
-
|
75
|
-
|
76
|
-
|
104
|
+
@visible_game_objects.each { |go| go.draw_trait; go.draw; }
|
105
|
+
end
|
106
|
+
def force_draw
|
107
|
+
@game_objects.each { |go| go.draw_trait; go.draw }
|
77
108
|
end
|
78
109
|
|
79
110
|
def draw_relative(x=0, y=0, zorder=0, angle=0, center_x=0, center_y=0, factor_x=0, factor_y=0)
|
80
|
-
@
|
111
|
+
@visible_game_objects.each do |object|
|
81
112
|
object.draw_trait
|
82
113
|
object.draw_relative(x, y, zorder, angle, center_x, center_y, factor_x, factor_y)
|
83
114
|
end
|
84
115
|
end
|
85
116
|
|
86
|
-
def update
|
87
|
-
@game_objects.select { |object| not object.paused }.each do |object|
|
88
|
-
object.update_trait
|
89
|
-
object.update
|
90
|
-
end
|
91
|
-
end
|
92
117
|
|
93
118
|
def each
|
94
119
|
@game_objects.dup.each { |object| yield object }
|
@@ -146,14 +171,5 @@ module Chingu
|
|
146
171
|
end
|
147
172
|
alias :show :show!
|
148
173
|
|
149
|
-
private
|
150
|
-
|
151
|
-
def sync
|
152
|
-
@game_objects += @add_game_objects
|
153
|
-
@add_game_objects.clear
|
154
|
-
|
155
|
-
@game_objects -= @remove_game_objects
|
156
|
-
@remove_game_objects.clear
|
157
|
-
end
|
158
174
|
end
|
159
175
|
end
|
@@ -23,14 +23,32 @@ module Chingu
|
|
23
23
|
#
|
24
24
|
# ** This class is under heavy development, API will most likely change! **
|
25
25
|
#
|
26
|
-
# GameObjectMap can
|
27
|
-
# You can
|
26
|
+
# GameObjectMap can map any set of game objects into a 2D-array for fast lookup.
|
27
|
+
# You can choose gridsize with the :grid-parameter, defaults to [32,32].
|
28
|
+
# The smaller the grid the more memory GameObjectMap will eat.
|
29
|
+
#
|
30
|
+
# The game objects sent to GameObjectMap must respond to #bb (as provided by trait :bounding_box)
|
31
|
+
# This is needed to calcuate what cells in the grid each game object covers.
|
28
32
|
#
|
29
33
|
# Basic usage:
|
30
34
|
# @map = GameObjectMap.new(:game_objects => TerrainObject.all, :grid => [32, 32])
|
31
35
|
# @map.at(100, 100) # returns one TerrainObject at x/y: 100/100
|
32
36
|
# @map.game_object(player) # returns one TerrainObject which collides with player.bounding_box
|
33
37
|
#
|
38
|
+
# A GameObjectMap is ment to be used for static non-moving objects, where a map can be calculated once and then used for fast lookups.
|
39
|
+
# This makes GameObjectMap very well suited for terrain for a player to walk on / collide with.
|
40
|
+
#
|
41
|
+
# One cell in the GameObjectMap can only be occupied by one game object.
|
42
|
+
# If you need many objects at the same cell, use 2 GameObjectMaps, something like:
|
43
|
+
#
|
44
|
+
# @terrain = GameObjectMap.new(:game_objects => Terrain.all)
|
45
|
+
# @mines = GameObjectMap.new(:game_objects => Mine.all)
|
46
|
+
#
|
47
|
+
# @player.stop_falling if @terrain.at(@player.x, @player)
|
48
|
+
# @player.die if @mine.at(@player.x, @player)
|
49
|
+
#
|
50
|
+
# Take note, since there can be only 1 game object per cell a huge game object could very well "cover out" another smaller game objects occupying the same cells.
|
51
|
+
#
|
34
52
|
# ** This class is under heavy development, API will most likely change! **
|
35
53
|
#
|
36
54
|
class GameObjectMap
|
@@ -52,7 +70,7 @@ module Chingu
|
|
52
70
|
@game_object_positions = {}
|
53
71
|
|
54
72
|
@game_objects.each do |game_object|
|
55
|
-
puts "#{game_object.class} @ #{game_object.x}
|
73
|
+
puts "#{game_object.class} @ #{game_object.x}/#{game_object.y} - #{game_object.bb}" if @debug
|
56
74
|
insert(game_object)
|
57
75
|
end
|
58
76
|
end
|
@@ -73,15 +91,17 @@ module Chingu
|
|
73
91
|
@map[x] ||= []
|
74
92
|
(start_y ... stop_y).each do |y|
|
75
93
|
@map[x][y] = game_object
|
94
|
+
puts "#{game_object.class} => map[#{x}][#{y}]" if @debug
|
76
95
|
end
|
77
96
|
end
|
78
97
|
end
|
79
98
|
|
80
99
|
#
|
81
|
-
# Removes a specific game object from the map
|
100
|
+
# Removes a specific game object from the map, replace the cell-value with nil
|
82
101
|
#
|
83
102
|
def delete(game_object)
|
84
103
|
range_x, range_y = @game_object_positions[game_object]
|
104
|
+
return unless range_x && range_y
|
85
105
|
|
86
106
|
range_x.each do |x|
|
87
107
|
range_y.each do |y|
|
@@ -92,7 +112,7 @@ module Chingu
|
|
92
112
|
alias :clear_game_object :delete
|
93
113
|
|
94
114
|
#
|
95
|
-
# Clear game object
|
115
|
+
# Clear the game object residing in the cell given by real world coordinates x/y
|
96
116
|
#
|
97
117
|
def clear_at(x, y)
|
98
118
|
lookup_x = (x / @grid[0]).to_i
|
@@ -101,14 +121,17 @@ module Chingu
|
|
101
121
|
end
|
102
122
|
|
103
123
|
#
|
104
|
-
# Gets
|
124
|
+
# Gets game object from map that resides on real world coordinates x/y
|
105
125
|
#
|
106
126
|
def at(x, y)
|
107
127
|
lookup_x = (x / @grid[0]).to_i
|
108
128
|
lookup_y = (y / @grid[1]).to_i
|
109
|
-
@map[lookup_x][lookup_y] rescue nil
|
129
|
+
@map[lookup_x][lookup_y] rescue nil # Benchmark this against @map[lookup_x] && @map[lookup_x][lookup_y] => prob faster
|
110
130
|
end
|
111
131
|
|
132
|
+
#
|
133
|
+
# Return the first game object occupying any of the cells that given 'game_object' covers
|
134
|
+
#
|
112
135
|
def from_game_object(game_object)
|
113
136
|
start_x = (game_object.bb.left / @grid[0]).to_i
|
114
137
|
stop_x = (game_object.bb.right / @grid[0]).to_i
|
@@ -126,7 +149,7 @@ module Chingu
|
|
126
149
|
end
|
127
150
|
|
128
151
|
#
|
129
|
-
# Yields
|
152
|
+
# Yields all game objects occupying any of the cells that given 'game_object' covers
|
130
153
|
#
|
131
154
|
def each_collision(game_object)
|
132
155
|
start_x = (game_object.bb.left / @grid[0]).to_i
|
@@ -40,6 +40,20 @@ module Chingu
|
|
40
40
|
@game_objects
|
41
41
|
end
|
42
42
|
|
43
|
+
def show_game_object(object)
|
44
|
+
@game_objects.show_game_object(object)
|
45
|
+
end
|
46
|
+
def hide_game_object(object)
|
47
|
+
@game_objects.hide_game_object(object)
|
48
|
+
end
|
49
|
+
def pause_game_object(object)
|
50
|
+
@game_objects.pause_game_object(object)
|
51
|
+
end
|
52
|
+
def unpause_game_object(object)
|
53
|
+
@game_objects.unpause_game_object(object)
|
54
|
+
end
|
55
|
+
|
56
|
+
|
43
57
|
#
|
44
58
|
# Fetch game objects of a certain type/class
|
45
59
|
#
|
@@ -29,24 +29,32 @@ module Chingu
|
|
29
29
|
#
|
30
30
|
module Retrofy
|
31
31
|
|
32
|
-
def setup_trait(options)
|
33
|
-
|
34
|
-
|
32
|
+
#def setup_trait(options)
|
33
|
+
# @retrofy_options = {:debug => false}.merge(options)
|
34
|
+
# super
|
35
|
+
#end
|
36
|
+
|
37
|
+
def retrofied_x=(x)
|
38
|
+
self.x = x / self.factor
|
35
39
|
end
|
36
|
-
|
37
|
-
def
|
38
|
-
|
40
|
+
|
41
|
+
def retrofied_y=(y)
|
42
|
+
self.y = y / self.factor
|
43
|
+
end
|
44
|
+
|
45
|
+
def real_x
|
46
|
+
(self.x / self.factor).to_i
|
39
47
|
end
|
40
48
|
|
41
|
-
def
|
42
|
-
(self.
|
49
|
+
def real_y
|
50
|
+
(self.y / self.factor).to_i
|
43
51
|
end
|
44
52
|
|
45
|
-
def
|
53
|
+
def retrofied_x
|
46
54
|
(self.x * self.factor).to_i
|
47
55
|
end
|
48
56
|
|
49
|
-
def
|
57
|
+
def retrofied_y
|
50
58
|
(self.y * self.factor).to_i
|
51
59
|
end
|
52
60
|
|
@@ -0,0 +1,252 @@
|
|
1
|
+
#--
|
2
|
+
# Part of Chingu -- OpenGL accelerated 2D game framework for Ruby
|
3
|
+
# Copyright (C) 2009 ippa / ippa@rubylicio.us
|
4
|
+
#
|
5
|
+
# Written/Refactored by Jakub Hozak - jakub.hozak@gmail.com
|
6
|
+
#
|
7
|
+
#++
|
8
|
+
|
9
|
+
module Chingu
|
10
|
+
module Traits
|
11
|
+
|
12
|
+
#
|
13
|
+
# A Chingu trait providing ability to be drawn as an image.
|
14
|
+
#
|
15
|
+
# Example:
|
16
|
+
#
|
17
|
+
# class Rocket < BasicGameObject
|
18
|
+
# trait :simple_sprite
|
19
|
+
# end
|
20
|
+
#
|
21
|
+
# Rocket.create(:x => 100, :y => 200)
|
22
|
+
#
|
23
|
+
# Options:
|
24
|
+
# :image - actual sprite to draw
|
25
|
+
# - see #image= for details as this method is used to set this option
|
26
|
+
#
|
27
|
+
# Introducing Variables:
|
28
|
+
# :x, :y, :zorder, :factor_x, :factor_y, :mode, :color, :visible
|
29
|
+
#
|
30
|
+
module SimpleSprite
|
31
|
+
module ClassMethods
|
32
|
+
def initialize_trait(options = {})
|
33
|
+
trait_options[:sprite] = options
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
attr_accessor :x, :y, :angle, :factor_x, :factor_y, :zorder, :mode, :color
|
38
|
+
attr_reader :factor, :center, :height, :width, :image
|
39
|
+
attr_accessor :visible # kill this? force use of setter
|
40
|
+
|
41
|
+
def setup_trait(object_options = {})
|
42
|
+
@visible = true unless options[:visible] == false
|
43
|
+
self.image = options[:image] if options[:image]
|
44
|
+
self.color = options[:color] || ::Gosu::Color::WHITE.dup
|
45
|
+
self.alpha = options[:alpha] if options[:alpha]
|
46
|
+
self.mode = options[:mode] || :default
|
47
|
+
self.x = options[:x] || 0
|
48
|
+
self.y = options[:y] || 0
|
49
|
+
self.zorder = options[:zorder] || 100
|
50
|
+
|
51
|
+
self.factor = options[:factor] || options[:scale] || $window.factor || 1.0
|
52
|
+
self.factor_x = options[:factor_x].to_f if options[:factor_x]
|
53
|
+
self.factor_y = options[:factor_y].to_f if options[:factor_y]
|
54
|
+
|
55
|
+
if self.image
|
56
|
+
self.width = options[:width] if options[:width]
|
57
|
+
self.height = options[:height] if options[:height]
|
58
|
+
self.size = options[:size] if options[:size]
|
59
|
+
end
|
60
|
+
|
61
|
+
super
|
62
|
+
end
|
63
|
+
|
64
|
+
#
|
65
|
+
# Let's have some useful information in to_s()
|
66
|
+
#
|
67
|
+
def to_s
|
68
|
+
"#{self.class.to_s} @ #{x.to_i} / #{y.to_i} " <<
|
69
|
+
"(#{width.to_i} x #{height.to_i}) - " <<
|
70
|
+
" ratio: #{sprintf("%.2f",width/height)} scale: #{sprintf("%.2f", factor_x)}/#{sprintf("%.2f", factor_y)} angle: #{angle.to_i} zorder: #{zorder} alpha: #{alpha}"
|
71
|
+
end
|
72
|
+
|
73
|
+
def color=(color)
|
74
|
+
@color = color.is_a?(Gosu::Color) ? color : Gosu::Color.new(color || 0xFFFFFFFF)
|
75
|
+
end
|
76
|
+
|
77
|
+
#
|
78
|
+
# Accepts String, callable object or any-other non-nil capable
|
79
|
+
# of drawing itself on screen.
|
80
|
+
#
|
81
|
+
# Examples:
|
82
|
+
# image = 'rocket.png'
|
83
|
+
# image = Gosu::Image.new($window, 'rocket.png')
|
84
|
+
#
|
85
|
+
# image = lambda do
|
86
|
+
# # TexPlay is library for Gosu image generation
|
87
|
+
# TexPlay.create_image($window,10,10).paint { circle(5,5,5, :color => :red) }
|
88
|
+
# end
|
89
|
+
#
|
90
|
+
def image=(image)
|
91
|
+
raise ArgumentError.new("No image set") if image.nil?
|
92
|
+
|
93
|
+
@image = if String === image
|
94
|
+
# 1) Try loading the image the normal way
|
95
|
+
# 2) Try looking up the picture using Chingus Image-cache
|
96
|
+
Gosu::Image.new($window, image,false) rescue Gosu::Image[image]
|
97
|
+
elsif image.respond_to? :call
|
98
|
+
image.call
|
99
|
+
else
|
100
|
+
image
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
#
|
105
|
+
# Get all settings from a game object in one array.
|
106
|
+
# Complemented by the GameObject#attributes= setter.
|
107
|
+
# Makes it easy to clone a objects x,y,angle etc.
|
108
|
+
#
|
109
|
+
def attributes
|
110
|
+
[@x, @y, @angle, @factor_x, @factor_y, @color, @mode, @zorder]
|
111
|
+
end
|
112
|
+
|
113
|
+
#
|
114
|
+
# Set all attributes on 1 line
|
115
|
+
# Mainly used in combination with game_object1.attributes = game_object2.attributes
|
116
|
+
#
|
117
|
+
def attributes=(attributes)
|
118
|
+
self.x, self.y, self.angle, self.factor_x, self.factor_y, self.color, self.mode, self.zorder = *attributes
|
119
|
+
end
|
120
|
+
|
121
|
+
#
|
122
|
+
# Set an effective width for the object on screen.
|
123
|
+
# Chingu does this by setting factor_x depending on imge.width and width given.
|
124
|
+
# Usually better to have a large image and make it smaller then the other way around.
|
125
|
+
#
|
126
|
+
def width=(width)
|
127
|
+
@factor_x = width.to_f / @image.width.to_f if @image
|
128
|
+
end
|
129
|
+
|
130
|
+
#
|
131
|
+
# Get effective width by calculating it from image-width and factor_x
|
132
|
+
#
|
133
|
+
def width
|
134
|
+
(@image.width * @factor_x).abs if @image
|
135
|
+
end
|
136
|
+
|
137
|
+
#
|
138
|
+
# Set an effective height for the object on screen.
|
139
|
+
# Chingu does this by setting factor_x depending on imge.width and width given.
|
140
|
+
# Usually better to have a large image and make it smaller then the other way around.
|
141
|
+
#
|
142
|
+
def height=(height)
|
143
|
+
@factor_y = height.to_f / @image.height.to_f if @image
|
144
|
+
end
|
145
|
+
|
146
|
+
#
|
147
|
+
# Get effective height by calculating it from image-width and factor
|
148
|
+
#
|
149
|
+
def height
|
150
|
+
(@image.height.to_f * @factor_y).abs if @image
|
151
|
+
end
|
152
|
+
|
153
|
+
# Set width and height in one swoop
|
154
|
+
def size=(size)
|
155
|
+
self.width, self.height = *size
|
156
|
+
end
|
157
|
+
|
158
|
+
# Get objects width and height in an array
|
159
|
+
def size
|
160
|
+
[self.width, self.height]
|
161
|
+
end
|
162
|
+
|
163
|
+
# Quick way of setting both factor_x and factor_y
|
164
|
+
def factor=(factor)
|
165
|
+
@factor = @factor_x = @factor_y = factor
|
166
|
+
end
|
167
|
+
alias scale= factor=
|
168
|
+
alias scale factor
|
169
|
+
|
170
|
+
|
171
|
+
# Get objects alpha-value (internally stored in @color.alpha)
|
172
|
+
def alpha
|
173
|
+
@color.alpha
|
174
|
+
end
|
175
|
+
|
176
|
+
# Set objects alpha-value (internally stored in @color.alpha)
|
177
|
+
# If out of range, set to closest working value. this makes fading simpler.
|
178
|
+
def alpha=(value)
|
179
|
+
value = 0 if value < 0
|
180
|
+
value = 255 if value > 255
|
181
|
+
@color.alpha = value
|
182
|
+
end
|
183
|
+
|
184
|
+
#
|
185
|
+
# Sets angle, normalize it to between 0..360
|
186
|
+
#
|
187
|
+
def angle=(value)
|
188
|
+
if value < 0
|
189
|
+
value = 360+value
|
190
|
+
elsif value > 360
|
191
|
+
value = value-360
|
192
|
+
end
|
193
|
+
@angle = value
|
194
|
+
end
|
195
|
+
|
196
|
+
#
|
197
|
+
# Disable automatic calling of draw and draw_trait each game loop
|
198
|
+
#
|
199
|
+
def hide!
|
200
|
+
@parent.game_objects.hide_game_object(self) if @parent && @visible == true
|
201
|
+
@visible = false
|
202
|
+
end
|
203
|
+
|
204
|
+
#
|
205
|
+
# Enable automatic calling of draw and draw_trait each game loop
|
206
|
+
#
|
207
|
+
def show!
|
208
|
+
@parent.game_objects.show_game_object(self) if @parent && @visible == false
|
209
|
+
@visible = true
|
210
|
+
end
|
211
|
+
|
212
|
+
#
|
213
|
+
# Returns true if visible (not hidden)
|
214
|
+
#
|
215
|
+
def visible?
|
216
|
+
@visible == true
|
217
|
+
end
|
218
|
+
|
219
|
+
|
220
|
+
# Returns true if object is inside the game window, false if outside
|
221
|
+
def inside_window?(x = @x, y = @y)
|
222
|
+
x >= 0 && x <= $window.width && y >= 0 && y <= $window.height
|
223
|
+
end
|
224
|
+
|
225
|
+
# Returns true object is outside the game window
|
226
|
+
def outside_window?(x = @x, y = @y)
|
227
|
+
not inside_window?(x,y)
|
228
|
+
end
|
229
|
+
|
230
|
+
#
|
231
|
+
# Our encapsulation of GOSU's image.draw_rot, uses the objects variables to draw it on screen if @visible is true
|
232
|
+
#
|
233
|
+
def draw
|
234
|
+
@image.draw(@x, @y, @zorder, @factor_x, @factor_y, @color, @mode) if @image
|
235
|
+
end
|
236
|
+
|
237
|
+
#
|
238
|
+
# Works as #draw() but takes offsets for all draw_rot()-arguments. Used among others by the viewport-trait.
|
239
|
+
#
|
240
|
+
def draw_relative(x=0, y=0, zorder=0, factor_x=0, factor_y=0)
|
241
|
+
@image.draw(@x+x, @y+y, @zorder+zorder, @factor_x+factor_x, @factor_y+factor_y, @color, @mode) if @image
|
242
|
+
end
|
243
|
+
|
244
|
+
#
|
245
|
+
# Works as #draw() but takes x/y arguments. Used among others by the edit-game state.
|
246
|
+
#
|
247
|
+
def draw_at(x, y)
|
248
|
+
draw_relative(x,y)
|
249
|
+
end
|
250
|
+
end
|
251
|
+
end
|
252
|
+
end
|