Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 293 lines (246 sloc) 8.049 kB
4499560 @jlnr The latest version I have, not sure if the SHA1 interface bug has bee…
authored
1 require 'background'
2 require 'particle'
3 require 'map'
4 require 'itemdrawer'
5 require 'totd'
6 require 'gameover'
7
8 class Game < SubApp
9 attr_reader :main, :map, :mouse_x, :mouse_y, :images, :item_drawer, :ticks, :objects
10 def initialize(main, num)
11 super(main)
12 @first_password = true
13 reinitialize(main, num)
14 end
15
16 def reinitialize(main, num)
17 @main = main
18 @num = num
19
20 @images = Hash.new do |hash, key|
21 filename, tile_width, tile_height, hard_borders = *key
22 hard_borders = false if hard_borders == nil
23 tile_width ||= -1
24 tile_height ||= -1
25 result = Image.load_tiles(main, File.join("media", filename), tile_width, tile_height, hard_borders)
26 hash[key] = (result.size <= 1 && tile_width == -1 && tile_height == -1) ? result.first : result
27 end
28 def @images.[](*args)
29 super(args)
30 end
31
32 @ticks = 0
33 @background = Background.new(self)
34 @objects = []
35 @item_drawer = ItemDrawer.new(self, LevelItems[num - 1])
36 @map = Map.new(self, num)
37 @center_x = @view_x = [(@objects.grep(Player).first.x rescue @map.width / 2) - @main.height / 2, 0].max
38 @center_y = @view_y = [(@objects.grep(Player).first.y rescue @map.height / 2) - @main.width / 2, 0].max
39 @scroll_border_size = @main.width / 10.0
40 @scrolling = 0.96
41 @mouse_gfx = @images["cursor.png", 40, 40, false]
42 @paused_gfx = @images["paused.png"]
43 @paused = false
44 @password_gfx = @images["items.png", ItemDrawer::ItemWidth, ItemDrawer::ItemHeight]
45 @zzz_gfx = @images["zzz.png"]
46 @restart_gfx = @images["restart.png"]
47 # just in case.
48 @mouse_x = @mouse_y = 0
49 @mouse_dir = 1.0
50 @seen_password = @seen_totd = false
51 @zzz_level = 1
52 end
53
54 def restart_level()
55 reinitialize(@main, @num)
56 @seen_password = true
57 end
58
59 def do_restart()
60 GameOver.new(self, true).show
61 end
62
63 def activate()
64 unless @seen_password
65 @seen_password = true
66 if @first_password then
67 @first_password = false
68 else
69 Password.new(@main, lambda { self }, nil, @num).show
70 return
71 end
72 end
73
74 unless @seen_totd
75 @seen_totd = true
76 Totd.new(@main, lambda {self}, LevelTips[@num - 1]).show
77 return
78 end
79 end
80
81 def button_up(button_id)
82 if @paused then
83 case button_id
84 when @main.char_to_button_id("p"), *Buttons[:Escape] then
85 @paused = false
86 end
87 else
88 case button_id
89 when *Buttons[:Escape] then
90 close
91 when Button::MsLeft, *Buttons[:Fire] then
92 click(@main.mouse_x, @main.mouse_y)
93 when Button::MsRight
94 @item_drawer.unset_active_item
95 when @main.char_to_button_id("p") then
96 @paused = true
97 when @main.char_to_button_id("r") then
98 do_restart
99 end
100 end
101 end
102
103 def add_object(obj)
104 @objects << obj
105 end
106
107 def zzz_x()
108 @main.width - @zzz_gfx.width / 2 - 10
109 end
110
111 def zzz_y()
112 @main.height - @zzz_gfx.height / 2 - 10
113 end
114
115 def zzz_scale()
116 [@zzz_level, 0.6].max
117 end
118
119 def restart_x()
120 @restart_gfx.width / 2 + 10
121 end
122
123 def restart_y()
124 @main.height - @restart_gfx.height / 2 - 10
125 end
126
127 def click_restart(x, y)
128 return if Gosu.distance(x, y, restart_x, restart_y) > (1 * @restart_gfx.width) / 2
129
130 do_restart
131 end
132
133 def click(mouse_x, mouse_y)
134 return if @item_drawer.click(mouse_x, mouse_y)
135 return if click_restart(mouse_x, mouse_y)
136 return if @objects.grep(Player).any? do |player|
137 player.click(mouse_x + @view_x, mouse_y + @view_y)
138 end
139 end
140
141 def draw()
142 @item_drawer.draw(@view_x, @view_y)
143
144 active_img = @item_drawer.active_item_image
145 mouse_off = active_img ? 2 : 0
146
147 @zzz_level = @objects.grep(Player).inject(1) { |res, player| player.update_zzz_level; res * player.zzz_level }
148 scale = zzz_scale
149 @zzz_gfx.draw_rot(zzz_x, zzz_y, ZOrder::GUIFront,
150 0, 0.5, 0.5, scale, scale, Color.new((@zzz_level * 255).to_i, 255, 255, 255))
151
152 @restart_gfx.draw_rot(restart_x, restart_y, ZOrder::GUIFront, 0)
153
154 @mouse_gfx[mouse_off + milliseconds / 200 % 2].draw(@main.mouse_x - 15 * @mouse_dir, @main.mouse_y - 20, ZOrder::Mouse,
155 @mouse_dir, 1.0)
156 active_img.draw(@main.mouse_x - 7, @main.mouse_y - 10, ZOrder::MouseItem, 0.2, 0.2) if active_img
157 @map.draw(@view_x, @view_y)
158 @objects.each { |obj| obj.draw(@view_x, @view_y) }
159 @main.draw_quad(0, 0, 0x801070B0, 800, 0, 0x801070B0,
160 0, 600, 0x801070B0, 800, 600, 0x801070B0, ZOrder::Background)
161 @background.draw(@view_x, @view_y)
162
163 if @paused then
164 c = 0xAAFFFFFF
165 @main.draw_quad(0,0,c, @main.width,0,c, 0,@main.height,c, @main.width,@main.height,c, ZOrder::MenuBack)
166 @paused_gfx.draw((@main.width - @paused_gfx.width) / 2, (@main.height - @paused_gfx.height) / 2,
167 ZOrder::MenuFront)
168 end
169 end
170
171 def play_sound(name, x, y, speed = 1.0)
172 if (x - @view_x - 400).abs > 800 or (y - @view_y - 300).abs > 400 then
173 return
174 end
175
176 @samples ||= Hash.new
177 @samples[name] ||= Gosu::Sample.new(main, "sounds/#{name}")
178 pan = [[(x - @view_x - 400) / 400.0, -1].max, 1].min
179 dist = (x - @view_x - 400).abs
180 if dist < 400 then
181 vol = 1
182 else
183 vol = (800 - dist) / 400.0
184 end
185 @samples[name].play_pan(pan, vol, speed)
186 end
187
188 def update()
189 catch(:next_level) do
190 return false if @paused
191 @ticks += 1
192 handle_map_scrolling()
193
194 set_view(@center_x, @center_y)
195
196 old_x = @mouse_x
197
198 @mouse_x = @main.mouse_x.round + @view_x
199 @mouse_y = @main.mouse_y.round + @view_y
200
201 if @mouse_x < old_x then
202 @mouse_dir = +1
203 elsif @mouse_x > old_x
204 @mouse_dir = -1
205 end
206
207 Particle.new(self, @mouse_x, @mouse_y, 1 - rand(3), 1 - rand(3), 0, 5, Color.new(255, 255, 255, 255), 20, 0)
208
209 @item_drawer.update
210
211 zzz_level_target = @objects.grep(Player).inject(1) { |res, player| res * player.zzz_level_target }
212 if zzz_level_target == 0 then
213 play_sound("lose.ogg", @view_x + @main.width / 2, @view_y + @main.height / 2, 1.0)
214 GameOver.new(self).show
215 end
216
217 cur = 0
218 max = @objects.size
219 while cur < max do
220 if @objects[cur].update then
221 cur += 1
222 else
223 @objects.delete_at(cur)
224 max -= 1
225 end
226 end
227 end
228 end
229
230 def next_level
231 reinitialize(@main, @num + 1)
232 activate()
233 throw(:next_level)
234 end
235
236 def handle_map_scrolling()
237 mx = @main.mouse_x
238 my = @main.mouse_y
239 mw = @main.width
240 mh = @main.height
241
242 return if mx < 0 or my < 0 or mx > mw or my > mh
243
244 sf = 3
245
246 if mx < @scroll_border_size then
247 @center_x += (mx - @scroll_border_size) / sf
248 elsif mx > mw - @scroll_border_size then
249 @center_x += (@scroll_border_size - (mw - mx)) / sf
250 end
251
252 if my < @scroll_border_size then
253 @center_y += (my - @scroll_border_size) / sf
254 elsif my > mh - @scroll_border_size then
255 @center_y += (@scroll_border_size - (mh - my)) / sf
256 end
257
258 bf = 18
259 {
260 [Button::GpLeft, Button::KbLeft] => [-bf, 0],
261 [Button::GpRight, Button::KbRight] => [+bf, 0],
262 [Button::GpUp, Button::KbUp] => [0, -bf],
263 [Button::GpDown, Button::KbDown] => [0, +bf]
264 }.each do |buttons, (off_x, off_y)|
265 if buttons.any? do |button|
266 @main.button_down?(button)
267 end then
268 @center_x += off_x
269 @center_y += off_y
270 end
271 end
272
273 if @map.width < @main.width
274 @center_x = (@map.width - @main.width) / 2
275 else
276 @center_x = [[@center_x, 0].max, @map.width - @main.width].min
277 end
278
279 if @map.height < @main.height
280 @center_y = (@map.height - @main.height) / 2
281 else
282 @center_y = [[@center_y, 0].max, @map.height - @main.height].min
283 end
284
285 end
286
287 def set_view(x, y)
288 of, nf = @scrolling, 1.0 - @scrolling
289 @view_x = (@view_x * of + x * nf).round
290 @view_y = (@view_y * of + y * nf).round
291 end
292 end
Something went wrong with that request. Please try again.