forked from ippa/chingu
-
Notifications
You must be signed in to change notification settings - Fork 1
/
example21_sidescroller_with_edit.rb
295 lines (241 loc) · 6.46 KB
/
example21_sidescroller_with_edit.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
#!/usr/bin/env ruby
require 'rubygems' rescue nil
$LOAD_PATH.unshift File.join(File.expand_path(__FILE__), "..", "..", "lib")
require 'chingu'
include Gosu
include Chingu
#
# Press 'E' when demo is running to edit the playfield!
#
class Game < Chingu::Window
def initialize
super(1000,700)
#super(1024,768, true)
end
def setup
retrofy
switch_game_state(Example21)
end
end
#
# The Game
#
class Example21 < GameState
traits :viewport, :timer
def initialize(options = {})
super
self.input = { :escape => :exit, :e => :edit }
self.viewport.game_area = [0, 0, 3500, 2000]
load_game_objects
@droid = Droid.create(:x => 100, :y => 400)
# Reverse the cog wheels in relation to eachother
CogWheel.each_collision(CogWheel) do |cog_wheel, cog_wheel_2|
cog_wheel_2.angle_velocity = -cog_wheel.angle_velocity
end
@saved_x, @saved_y = [100, 300]
every(5000) { save_player_position }
end
def edit
push_game_state(GameStates::Edit.new(:grid => [32,32], :classes => [Droid, Tube, CogWheel, Block, Saw, Battery]))
end
def restore_player_position
@droid.x, @droid.y = @saved_x, @saved_y
end
def save_player_position
@saved_x, @saved_y = @droid.x, @droid.y if @droid.collidable && !@jumping
end
def update
super
# Makes all saw pendle up and down between Y-coordinate 1000 - 1500
# TODO: Not a very flexible sollution, how about setting out circle,rects,lines in editor..
# .. when then can be used for this kind of stuff?
Saw.select {|saw| saw.y < 1300 || saw.y > 1550 }.each do |saw|
saw.velocity_y = -saw.velocity_y
saw.y += saw.velocity_y * saw.factor_y
end
@droid.each_collision(FireBall, Saw) do |player, evil_object|
player.die
end
@droid.each_collision(Battery) do |player, battery|
battery.die
end
self.viewport.center_around(@droid)
$window.caption = "Haunted Factory. 'E' toggles Edit. x/y: #{@droid.x.to_i}/#{@droid.y.to_i} - viewport x/y: #{self.viewport.x.to_i}/#{self.viewport.y.to_i} - FPS: #{$window.fps}"
end
end
#
# DROID
#
class Droid < Chingu::GameObject
trait :bounding_box, :scale => 0.80
traits :timer, :collision_detection , :timer, :velocity
attr_reader :jumping
def setup
self.input = { [:holding_left, :holding_a] => :holding_left,
[:holding_right, :holding_d] => :holding_right,
[:up, :w] => :jump,
}
# Load the full animation from tile-file media/droid.bmp
@animations = Chingu::Animation.new(:file => "droid_11x15.bmp")
@animations.frame_names = { :scan => 0..5, :up => 6..7, :down => 8..9, :left => 10..11, :right => 12..13 }
@animation = @animations[:scan]
@speed = 3
@jumping = false
self.zorder = 300
self.factor = 3
self.acceleration_y = 0.5
self.max_velocity = 10
self.rotation_center = :bottom_center
update
cache_bounding_box
end
def die
self.collidable = false
@color = Color::RED.dup
between(1,600) { self.velocity_y = 0; self.scale += 0.2; self.alpha -= 5; }.then { resurrect }
end
def resurrect
self.alpha = 255
self.factor = 3
self.collidable = true
@color = Color::WHITE.dup
game_state.restore_player_position
end
def holding_left
move(-@speed, 0)
@animation = @animations[:left]
end
def holding_right
move(@speed, 0)
@animation = @animations[:right]
end
def jump
return if @jumping
@jumping = true
self.velocity_y = -10
@animation = @animations[:up]
end
def move(x,y)
self.x += x
self.each_collision(Block) do |me, stone_wall|
self.x = previous_x
break
end
self.y += y
end
def update
@image = @animation.next
self.each_collision(Block) do |me, stone_wall|
if self.velocity_y < 0 # Hitting the ceiling
me.y = stone_wall.bb.bottom + me.image.height * self.factor_y
self.velocity_y = 0
else # Land on ground
@jumping = false
me.y = stone_wall.bb.top-1
end
end
@animation = @animations[:scan] unless moved?
end
end
#
# TUBE
#
class Tube < GameObject
traits :bounding_box, :timer
def setup
@image = Image["tube.png"]
every(3000) { fire }
cache_bounding_box
end
def fire
return if game_state.viewport.outside?(self.bb.centerx, self.bb.bottom)
FireBall.create(:x => self.bb.centerx - rand(10), :y => self.bb.bottom - rand(10))
end
end
#
# BATTERY
#
class Battery < GameObject
traits :timer, :effect
trait :bounding_box, :debug => false
def setup
@image = Image["battery.png"]
cache_bounding_box
end
def die
self.collidable = false # Stops further collisions in each_collsiion() etc.
self.rotation_rate = 5
self.scale_rate = 0.005
self.fade_rate = -5
after(2000) { destroy }
end
end
#
# A FIREBALL
#
class FireBall < GameObject
traits :velocity, :collision_detection, :timer
trait :bounding_circle, :scale => 0.7
def setup
@animation = Animation.new(:file => "fireball.png", :size => [32,32], :delay => 20)
@image = @animation.first
self.mode = :additive
self.factor = 3
self.velocity_y = 1
self.zorder = 200
self.rotation_center = :center
after(3000) { self.destroy }
end
def update
@image = @animation.next
@angle += 2
end
end
#
# COG WHEEL
#
class CogWheel < GameObject
traits :bounding_circle, :collision_detection, :timer
attr_accessor :angle_velocity
def setup
@image = Image["cog_wheel.png"]
@angle_velocity = 1 / self.factor_x
end
def update
self.angle += @angle_velocity
end
end
#
# SAW
#
class Saw < GameObject
traits :bounding_circle, :collision_detection, :timer, :velocity
attr_accessor :angle_velocity
def setup
@image = Image["saw.png"]
@angle_velocity = 3.0 / self.factor_x.to_f
self.velocity_y = 1.0 / self.factor_x.to_f
end
def update
self.angle += @angle_velocity
end
end
#
# BLOCK, our basic level building block
#
class Block < GameObject
trait :bounding_box, :debug => false
trait :collision_detection
def self.solid
all.select { |block| block.alpha == 255 }
end
def self.inside_viewport
all.select { |block| block.game_state.viewport.inside?(block) }
end
def setup
@image = Image["black_block.png"]
@color = Color.new(0xff808080)
cache_bounding_box
end
end
Game.new.show