bathtub 0.5.2
Sign up to get free protection for your applications and to get access to all the features.
- data/SDL.dll +0 -0
- data/SDL_mixer.dll +0 -0
- data/SDL_ttf.dll +0 -0
- data/SGE.dll +0 -0
- data/VERSION +1 -0
- data/bathtub.exe +0 -0
- data/bathtub/character.rb +232 -0
- data/bathtub/game.rb +120 -0
- data/bathtub/graphic.rb +25 -0
- data/bathtub/main.rb +35 -0
- data/bathtub/misc.rb +83 -0
- data/bathtub/scene.rb +223 -0
- data/bathtub/score.rb +121 -0
- data/bathtub/task.rb +63 -0
- data/bin/bathtub +6 -0
- data/highscore.dat +0 -0
- data/image/back.bmp +0 -0
- data/image/bath.bmp +0 -0
- data/image/boxfont2.ttf +0 -0
- data/image/curving.ttf +0 -0
- data/image/hito.bmp +0 -0
- data/image/icon-16164.bmp +0 -0
- data/image/icon-16168.bmp +0 -0
- data/image/icon.bmp +0 -0
- data/image/logo.bmp +0 -0
- data/image/shibuki.bmp +0 -0
- data/image/staff.bmp +0 -0
- data/msvcr71.dll +0 -0
- data/readme.txt +38 -0
- data/sound/BB_Scratch_19.wav +0 -0
- data/sound/SplashA1@22.wav +0 -0
- data/sound/Stabs110.wav +0 -0
- data/sound/Stabs63.wav +0 -0
- data/sound/blacksamba.it +0 -0
- data/sound/bom08.wav +0 -0
- data/sound/clambient.it +0 -0
- data/sound/fall.wav +0 -0
- data/sound/get.wav +0 -0
- metadata +117 -0
data/SDL.dll
ADDED
Binary file
|
data/SDL_mixer.dll
ADDED
Binary file
|
data/SDL_ttf.dll
ADDED
Binary file
|
data/SGE.dll
ADDED
Binary file
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.5.2
|
data/bathtub.exe
ADDED
Binary file
|
@@ -0,0 +1,232 @@
|
|
1
|
+
#
|
2
|
+
# character.rb
|
3
|
+
#
|
4
|
+
|
5
|
+
class Combo
|
6
|
+
include Task
|
7
|
+
|
8
|
+
def self.load
|
9
|
+
@@font = SDL::TTF.open("image/curving.ttf", 20)
|
10
|
+
end
|
11
|
+
attr_accessor :x,:y,:value
|
12
|
+
|
13
|
+
def init
|
14
|
+
@step = 0
|
15
|
+
end
|
16
|
+
|
17
|
+
def act(dt,i)
|
18
|
+
@step += dt
|
19
|
+
@active = false if @step > 500
|
20
|
+
end
|
21
|
+
|
22
|
+
def draw(i)
|
23
|
+
@@font.drawBlendedUTF8(i.scr,"#{@value} COMBO", @x,@y-(@step/10) , 255,100,100)
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
class Bath
|
29
|
+
extend SingleTask
|
30
|
+
|
31
|
+
Shibuki = Struct.new(:x,:y,:step)
|
32
|
+
|
33
|
+
WAIT_STAFF_ANIM = 80
|
34
|
+
MOVE_WAIT = 3
|
35
|
+
|
36
|
+
STAFF_IMGS = 4
|
37
|
+
SHIBUKI_IMGS = 3
|
38
|
+
Y0 = 342
|
39
|
+
|
40
|
+
attr_reader :x,:y
|
41
|
+
|
42
|
+
def init
|
43
|
+
@img_bath = SDL::Surface.loadBMP("image/bath.bmp")
|
44
|
+
@img_bath.setColorKey(SDL::SRCCOLORKEY,[255,0,255])
|
45
|
+
@img_rstaff = Util.cut_image(56,67,STAFF_IMGS, SDL::Surface.loadBMP("image/staff.bmp"), 0,0, [255,0,255])
|
46
|
+
@img_lstaff = Util.cut_image(56,67,STAFF_IMGS, SDL::Surface.loadBMP("image/staff.bmp"), 0,67, [255,0,255])
|
47
|
+
@img_shibuki = Util.cut_image(94,105,SHIBUKI_IMGS, SDL::Surface.loadBMP("image/shibuki.bmp"),0,0,[255,255,255])
|
48
|
+
Sound.open(:scratch, "BB_Scratch_19.wav", 40)
|
49
|
+
@movetimer = Timer.new(MOVE_WAIT)
|
50
|
+
@staff_anim_timer = Timer.new(WAIT_STAFF_ANIM)
|
51
|
+
@shibuki_timer = Timer.new(80)
|
52
|
+
end
|
53
|
+
|
54
|
+
def enabled
|
55
|
+
@movestep = (GameMain.mode==:endless ? 3 : 2)
|
56
|
+
end
|
57
|
+
|
58
|
+
def reset
|
59
|
+
@staffimg = 0
|
60
|
+
@x = 320 #�o�X�^�u�̒��S���W
|
61
|
+
@y = Y0
|
62
|
+
@dir = 1 #1:right -1:left
|
63
|
+
@effects = []
|
64
|
+
end
|
65
|
+
|
66
|
+
def shibuki
|
67
|
+
@effects << Shibuki.new(0,0,0)
|
68
|
+
end
|
69
|
+
|
70
|
+
def act(dt,i)
|
71
|
+
act_move(dt,i) unless Gameover.active?
|
72
|
+
act_shibuki(dt)
|
73
|
+
end
|
74
|
+
|
75
|
+
def act_move(dt,i)
|
76
|
+
if i.key.right
|
77
|
+
newdir = 1
|
78
|
+
elsif i.key.left
|
79
|
+
newdir = -1
|
80
|
+
elsif i.keydown.button
|
81
|
+
newdir = -@dir
|
82
|
+
else
|
83
|
+
newdir = @dir
|
84
|
+
end
|
85
|
+
|
86
|
+
if newdir != @dir
|
87
|
+
#Sound.play(:scratch)
|
88
|
+
@dir = newdir
|
89
|
+
end
|
90
|
+
|
91
|
+
@staff_anim_timer.wait(dt){
|
92
|
+
@staffimg+=1
|
93
|
+
@staffimg=0 if @staffimg>=STAFF_IMGS
|
94
|
+
}
|
95
|
+
|
96
|
+
@movetimer.wait(dt){
|
97
|
+
@x += @dir * @movestep
|
98
|
+
@x = 0 if @x<0
|
99
|
+
@x = 639 if @x>639
|
100
|
+
}
|
101
|
+
end
|
102
|
+
|
103
|
+
def act_shibuki(dt)
|
104
|
+
@effects.each do |eff|
|
105
|
+
@shibuki_timer.wait(dt){
|
106
|
+
eff.step+=1
|
107
|
+
}
|
108
|
+
end
|
109
|
+
@effects.delete_if{|eff|
|
110
|
+
eff.step >= SHIBUKI_IMGS
|
111
|
+
}
|
112
|
+
end
|
113
|
+
|
114
|
+
def draw(i)
|
115
|
+
@effects.each{|eff| i.scr.put(@img_shibuki[eff.step], @x-55, @y-58)}
|
116
|
+
|
117
|
+
@x = 330 if NameEntry.active?
|
118
|
+
|
119
|
+
i.scr.put(@img_lstaff[@staffimg], @x-80, @y-14)
|
120
|
+
i.scr.put(@img_bath, @x-37, @y )
|
121
|
+
i.scr.put(@img_rstaff[@staffimg], @x+32, @y-14)
|
122
|
+
end
|
123
|
+
|
124
|
+
end
|
125
|
+
|
126
|
+
|
127
|
+
class Jumper
|
128
|
+
include Task
|
129
|
+
|
130
|
+
def self.load
|
131
|
+
@@img = SDL::Surface.loadBMP("image/hito.bmp")
|
132
|
+
@@img.setColorKey(SDL::SRCCOLORKEY,[255,0,255])
|
133
|
+
end
|
134
|
+
|
135
|
+
attr_accessor :x,:y
|
136
|
+
def init
|
137
|
+
case GameMain.mode
|
138
|
+
when :easy
|
139
|
+
speed = 11
|
140
|
+
when :normal
|
141
|
+
speed = 8
|
142
|
+
when :endless
|
143
|
+
speed = 7
|
144
|
+
end
|
145
|
+
|
146
|
+
@movetimer = Timer.new(speed)
|
147
|
+
@type = rand(2)
|
148
|
+
@missed = false
|
149
|
+
|
150
|
+
#���W�֘A
|
151
|
+
@t0=-20
|
152
|
+
@y0=260
|
153
|
+
@x=(@type==0 ? 0 : 640)
|
154
|
+
@y=0
|
155
|
+
@t=0
|
156
|
+
@vx=rand(6)+1
|
157
|
+
end
|
158
|
+
attr_accessor :missed
|
159
|
+
|
160
|
+
def act(dt,info)
|
161
|
+
@movetimer.wait(dt){
|
162
|
+
@t+=0.8
|
163
|
+
if @type==0
|
164
|
+
@x = @vx*@t
|
165
|
+
else # @type==1
|
166
|
+
@x = 640 - @vx*@t
|
167
|
+
end
|
168
|
+
|
169
|
+
@y = 480 - ( @y0 + 10*(@t-@t0) - 0.1*(@t-@t0)*(@t-@t0) )
|
170
|
+
}
|
171
|
+
|
172
|
+
if @x<0 || @x>=640 || @y>=480
|
173
|
+
@alive = false
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
def draw(i)
|
178
|
+
i.scr.put(@@img, @x - @@img.w/2, @y)
|
179
|
+
end
|
180
|
+
|
181
|
+
end
|
182
|
+
|
183
|
+
class Jumpers
|
184
|
+
extend SingleTask
|
185
|
+
|
186
|
+
def init
|
187
|
+
Sound.open(:zabun, "SplashA1@22.wav", 60)
|
188
|
+
Sound.open(:fall, "fall.wav", 60)
|
189
|
+
end
|
190
|
+
|
191
|
+
def reset
|
192
|
+
@items = []
|
193
|
+
@margin = (GameMain.mode==:easy ? 80 : 25)
|
194
|
+
end
|
195
|
+
|
196
|
+
def act(dt,i)
|
197
|
+
ret = 0 #0pts
|
198
|
+
|
199
|
+
#����
|
200
|
+
if @items.size<1 && !Gameover.active?
|
201
|
+
@items << Jumper.new
|
202
|
+
end
|
203
|
+
|
204
|
+
#����
|
205
|
+
@items.each do |item|
|
206
|
+
if item.y>=330 && item.alive && !item.missed
|
207
|
+
#����
|
208
|
+
if (Bath.instance.x-item.x).abs < @margin
|
209
|
+
#�����ρ[��
|
210
|
+
item.alive = false #����
|
211
|
+
i.score.incr #1 pts
|
212
|
+
Sound.play(:zabun)
|
213
|
+
Bath.instance.shibuki
|
214
|
+
if GameMain.mode==:endless && i.score.value > 0
|
215
|
+
c = Combo.new
|
216
|
+
c.x = Bath.instance.x; c.y = Bath.instance.y; c.value = i.score.value
|
217
|
+
end
|
218
|
+
elsif item.y>=360
|
219
|
+
#���ׂ�
|
220
|
+
Sound.play(:fall)
|
221
|
+
item.missed = true
|
222
|
+
i.score.miss #1miss
|
223
|
+
end
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
#�폜
|
228
|
+
@items.delete_if{|item| !item.alive}
|
229
|
+
end
|
230
|
+
|
231
|
+
end
|
232
|
+
|
data/bathtub/game.rb
ADDED
@@ -0,0 +1,120 @@
|
|
1
|
+
require 'singleton'
|
2
|
+
require 'bathtub/misc.rb'
|
3
|
+
require 'bathtub/task.rb'
|
4
|
+
require 'bathtub/score.rb'
|
5
|
+
require 'bathtub/scene.rb'
|
6
|
+
require 'bathtub/graphic.rb'
|
7
|
+
require 'bathtub/character.rb'
|
8
|
+
|
9
|
+
class NullJoystick
|
10
|
+
def axis(a); 0; end
|
11
|
+
def hat(i); 0; end
|
12
|
+
def numButtons; 0; end
|
13
|
+
end
|
14
|
+
|
15
|
+
class Game
|
16
|
+
|
17
|
+
Key = Struct.new(:left,:right,:button,:other,:ctrl,:esc)
|
18
|
+
class Key
|
19
|
+
def reset
|
20
|
+
self.size.times{|i| self[i]=nil}
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def initialize(screen)
|
25
|
+
@screen = screen
|
26
|
+
@joy = (SDL::Joystick.num > 0) ? SDL::Joystick.open(0) : NullJoystick.new
|
27
|
+
|
28
|
+
TaskManager.init
|
29
|
+
|
30
|
+
Background.new
|
31
|
+
Gameover.disable
|
32
|
+
Highscore.disable
|
33
|
+
ModeSelect.enable
|
34
|
+
GameMain.disable
|
35
|
+
@score = Score.instance
|
36
|
+
Jumper.load
|
37
|
+
Jumpers.disable
|
38
|
+
Bath.disable
|
39
|
+
Combo.load
|
40
|
+
NameEntry.disable
|
41
|
+
end
|
42
|
+
|
43
|
+
def run
|
44
|
+
TaskManager.reset
|
45
|
+
before = now = SDL.getTicks
|
46
|
+
info = Task::Info.new
|
47
|
+
info.scr = @screen
|
48
|
+
info.score = @score
|
49
|
+
info.key = Key.new
|
50
|
+
info.keydown = Key.new
|
51
|
+
|
52
|
+
while true
|
53
|
+
return if check_events(info.key, info.keydown)==nil
|
54
|
+
|
55
|
+
before=now; now=SDL.getTicks; dt=now-before
|
56
|
+
TaskManager.act(dt,info)
|
57
|
+
|
58
|
+
TaskManager.draw(info)
|
59
|
+
@screen.flip
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def check_events(key,kd)
|
64
|
+
key.reset
|
65
|
+
kd.reset
|
66
|
+
|
67
|
+
#check keys
|
68
|
+
while (event=SDL::Event2.poll)
|
69
|
+
case event
|
70
|
+
when SDL::Event2::Quit
|
71
|
+
return nil
|
72
|
+
when SDL::Event2::JoyButtonDown
|
73
|
+
kd.button = true
|
74
|
+
when SDL::Event2::JoyAxis
|
75
|
+
if event.value < -512
|
76
|
+
kd.left = true
|
77
|
+
elsif event.value > 512
|
78
|
+
kd.right = true
|
79
|
+
end
|
80
|
+
when SDL::Event2::KeyDown
|
81
|
+
kd.other ||= []
|
82
|
+
kd.other << event.sym
|
83
|
+
case event.sym
|
84
|
+
when SDL::Key::ESCAPE
|
85
|
+
if GameMain.mode==:endless && GameMain.active?
|
86
|
+
kd.esc = true
|
87
|
+
else
|
88
|
+
return nil
|
89
|
+
end
|
90
|
+
when SDL::Key::RETURN, SDL::Key::SPACE
|
91
|
+
kd.button = true
|
92
|
+
when SDL::Key::LEFT, SDL::Key::UP, SDL::Key::H, SDL::Key::K
|
93
|
+
kd.left = true
|
94
|
+
when SDL::Key::RIGHT, SDL::Key::DOWN, SDL::Key::L, SDL::Key::J
|
95
|
+
kd.right = true
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
SDL::Key.scan; SDL::Joystick.updateAll
|
101
|
+
key.left = true if @joy.axis(0) < -512 || @joy.axis(1) < -512 ||
|
102
|
+
@joy.hat(0) == SDL::Joystick::HAT_LEFT || @joy.hat(0) == SDL::Joystick::HAT_UP
|
103
|
+
key.right = true if @joy.axis(0) > 512 || @joy.axis(1) > 512 ||
|
104
|
+
@joy.hat(0) == SDL::Joystick::HAT_RIGHT || @joy.hat(0) == SDL::Joystick::HAT_DOWN
|
105
|
+
@joy.numButtons.times{|i| key.button = true if @joy.button(i)}
|
106
|
+
[SDL::Key::RETURN, SDL::Key::SPACE].each{|k| key.button=true if SDL::Key.press?(k)}
|
107
|
+
[SDL::Key::LEFT, SDL::Key::UP].each{|k| key.left=true if SDL::Key.press?(k)}
|
108
|
+
[SDL::Key::RIGHT, SDL::Key::DOWN].each{|k| key.right=true if SDL::Key.press?(k)}
|
109
|
+
unless NameEntry.active?
|
110
|
+
[SDL::Key::H, SDL::Key::K].each{|k| key.left=true if SDL::Key.press?(k)}
|
111
|
+
[SDL::Key::L, SDL::Key::J].each{|k| key.right=true if SDL::Key.press?(k)}
|
112
|
+
end
|
113
|
+
key.ctrl = true if SDL::Key.press?(SDL::Key::LCTRL)
|
114
|
+
|
115
|
+
return true
|
116
|
+
end
|
117
|
+
|
118
|
+
end
|
119
|
+
|
120
|
+
|
data/bathtub/graphic.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
#
|
2
|
+
# graphic.rb
|
3
|
+
#
|
4
|
+
|
5
|
+
class Background
|
6
|
+
include Task
|
7
|
+
|
8
|
+
def init
|
9
|
+
@img_back = SDL::Surface.loadBMP("image/back.bmp")
|
10
|
+
@img_logo = SDL::Surface.loadBMP("image/logo.bmp")
|
11
|
+
@img_logo.setColorKey(SDL::SRCCOLORKEY,[0,0,255])
|
12
|
+
@font = SDL::TTF.open("image/curving.ttf", 20)
|
13
|
+
end
|
14
|
+
|
15
|
+
def draw(i)
|
16
|
+
i.scr.fillRect(0,0,640,480,0)
|
17
|
+
i.scr.put(@img_back,0,0)
|
18
|
+
if GameMain.active?
|
19
|
+
i.scr.put(@img_logo,520,382)
|
20
|
+
@font.drawBlendedUTF8(i.scr, GameMain.mode.to_s.upcase, 550,455, 255,80,80)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
|
data/bathtub/main.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
# main.rb
|
2
|
+
|
3
|
+
require 'sdl'
|
4
|
+
require 'bathtub/game.rb'
|
5
|
+
|
6
|
+
class Main
|
7
|
+
|
8
|
+
TITLE = "�o�X�^�u�꒼��"
|
9
|
+
VERSION = "0.51"
|
10
|
+
|
11
|
+
def initialize(fullscreen=false)
|
12
|
+
SDL.init(SDL::INIT_VIDEO|SDL::INIT_AUDIO|SDL::INIT_JOYSTICK)
|
13
|
+
SDL::TTF.init
|
14
|
+
SDL::Mixer.open
|
15
|
+
|
16
|
+
SDL::WM.icon = SDL::Surface.loadBMP("image/icon-16168.bmp")
|
17
|
+
#screen
|
18
|
+
if fullscreen
|
19
|
+
screen = SDL::setVideoMode(640,480,16,SDL::SWSURFACE|SDL::FULLSCREEN) #|SDL::DOUBLEBUF
|
20
|
+
SDL::Mouse.hide
|
21
|
+
else
|
22
|
+
screen = SDL::setVideoMode(640,480,16,SDL::SWSURFACE) #|SDL::DOUBLEBUF)
|
23
|
+
end
|
24
|
+
#SDL::WM.setCaption(TITLE+" "+VERSION, TITLE)
|
25
|
+
|
26
|
+
#init game
|
27
|
+
@game = Game.new(screen)
|
28
|
+
end
|
29
|
+
|
30
|
+
def run
|
31
|
+
@game.run
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
data/bathtub/misc.rb
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
#
|
2
|
+
# misc.rb
|
3
|
+
#
|
4
|
+
|
5
|
+
class Consts
|
6
|
+
LIVES = 2
|
7
|
+
end
|
8
|
+
|
9
|
+
#----------------------------------------------------------------------------------
|
10
|
+
|
11
|
+
class Timer
|
12
|
+
def reset
|
13
|
+
@ct=0
|
14
|
+
end
|
15
|
+
|
16
|
+
def initialize(waittime)
|
17
|
+
set_wait(waittime)
|
18
|
+
reset
|
19
|
+
end
|
20
|
+
|
21
|
+
def wait(dt)
|
22
|
+
@ct+=dt
|
23
|
+
while @ct>=@waittime do
|
24
|
+
@ct-=@waittime
|
25
|
+
yield
|
26
|
+
@ct=0 if @ct<@waittime
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def set_wait(t)
|
31
|
+
raise ArgumentError,"waittime must be positive" if t<=0
|
32
|
+
@waittime = t
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
#----------------------------------------------------------------------------------
|
37
|
+
module Sound
|
38
|
+
|
39
|
+
class << Sound
|
40
|
+
def open(sym,fname,vol=nil)
|
41
|
+
if fname=~/\.wav\z/
|
42
|
+
@@waves ||= {}
|
43
|
+
@@waves[sym] = [SDL::Mixer::Wave.load("sound/"+fname), @@waves.size]
|
44
|
+
@@waves[sym][0].setVolume(vol) if vol
|
45
|
+
else
|
46
|
+
@@bgm ||= {}
|
47
|
+
#@@bgm[sym] = SDL::Mixer::Music.load("sound/"+fname)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def play(sym)
|
52
|
+
if @@waves.key? sym
|
53
|
+
SDL::Mixer.playChannel(@@waves[sym][1], #channel
|
54
|
+
@@waves[sym][0], #wave
|
55
|
+
0)
|
56
|
+
else
|
57
|
+
#SDL::Mixer.playMusic(@@bgm[sym],-1)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def stop_music
|
62
|
+
SDL::Mixer.haltMusic
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
|
68
|
+
#------------------------------------------------------------------------------
|
69
|
+
module Util
|
70
|
+
def self.cut_image(w,h,n,img, ofsx=0, ofsy=0, colkey=nil)
|
71
|
+
ret = []
|
72
|
+
n.times do |i|
|
73
|
+
surf = img.copyRect(i*w+ofsx,0+ofsy, w,h)
|
74
|
+
surf.setColorKey(SDL::SRCCOLORKEY, colkey) if colkey!=nil
|
75
|
+
ret << surf
|
76
|
+
end
|
77
|
+
ret
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
|
82
|
+
#----------------------------------------------------------------------------------
|
83
|
+
#----------------------------------------------------------------------------------
|
data/bathtub/scene.rb
ADDED
@@ -0,0 +1,223 @@
|
|
1
|
+
#
|
2
|
+
# scene.rb
|
3
|
+
#
|
4
|
+
|
5
|
+
class GameMain
|
6
|
+
extend SingleTask
|
7
|
+
|
8
|
+
def init
|
9
|
+
Sound.open(:bgm, "blacksamba.it")
|
10
|
+
Sound.open(:bgm2, "clambient.it")
|
11
|
+
@mode = nil
|
12
|
+
end
|
13
|
+
attr_accessor :mode
|
14
|
+
|
15
|
+
class << GameMain
|
16
|
+
def set_mode(mode); self.instance.mode = mode; end
|
17
|
+
def mode; self.instance.mode; end
|
18
|
+
end
|
19
|
+
|
20
|
+
def enabled
|
21
|
+
(@mode==:endless) ? Sound.play(:bgm2) : Sound.play(:bgm)
|
22
|
+
Bath.enable
|
23
|
+
Jumpers.enable
|
24
|
+
TaskManager.reset
|
25
|
+
end
|
26
|
+
|
27
|
+
def disabled
|
28
|
+
Sound.stop_music
|
29
|
+
Jumpers.disable
|
30
|
+
end
|
31
|
+
|
32
|
+
def act(dt,i)
|
33
|
+
if @mode==:endless && i.keydown.esc
|
34
|
+
GameMain.disable
|
35
|
+
Gameover.enable
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
class ModeSelect
|
42
|
+
extend SingleTask
|
43
|
+
|
44
|
+
MODES = [:easy, :normal, :endless]
|
45
|
+
HEIGHT = [180,220,260]
|
46
|
+
LEFT = 100
|
47
|
+
|
48
|
+
def init
|
49
|
+
@font=SDL::TTF.open("image/boxfont2.ttf", 40)
|
50
|
+
@movetimer = Timer.new(100)
|
51
|
+
@cur = 0
|
52
|
+
end
|
53
|
+
|
54
|
+
def enabled
|
55
|
+
Highscore.enable
|
56
|
+
Highscore.instance.show = MODES[@cur]
|
57
|
+
end
|
58
|
+
|
59
|
+
def act(dt,i)
|
60
|
+
if i.keydown.left
|
61
|
+
@cur-=1
|
62
|
+
@cur = MODES.size-1 if @cur<0
|
63
|
+
Highscore.instance.show = MODES[@cur]
|
64
|
+
elsif i.keydown.right
|
65
|
+
@cur+=1
|
66
|
+
@cur = 0 if @cur>MODES.size-1
|
67
|
+
Highscore.instance.show = MODES[@cur]
|
68
|
+
elsif i.keydown.button
|
69
|
+
self.disable
|
70
|
+
Highscore.disable
|
71
|
+
GameMain.set_mode(MODES[@cur])
|
72
|
+
GameMain.enable
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def draw(i)
|
77
|
+
@font.drawBlendedUTF8(i.scr, " EASY", LEFT,HEIGHT[0], 0,0,0)
|
78
|
+
@font.drawBlendedUTF8(i.scr, " NORMAL", LEFT,HEIGHT[1], 0,0,0)
|
79
|
+
@font.drawBlendedUTF8(i.scr, " ENDLESS", LEFT,HEIGHT[2], 0,0,0)
|
80
|
+
@font.drawBlendedUTF8(i.scr, "*", LEFT,HEIGHT[@cur], 0,0,0)
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
|
85
|
+
class Gameover
|
86
|
+
extend SingleTask
|
87
|
+
|
88
|
+
def init
|
89
|
+
@font = SDL::TTF.open("image/boxfont2.ttf", 48)
|
90
|
+
@flashtimer = Timer.new(700)
|
91
|
+
@draw = true
|
92
|
+
end
|
93
|
+
|
94
|
+
def act(dt,i)
|
95
|
+
@flashtimer.wait(dt){
|
96
|
+
@draw = (@draw ? false : true)
|
97
|
+
}
|
98
|
+
if i.keydown.button
|
99
|
+
i.keydown.reset
|
100
|
+
self.disable
|
101
|
+
Bath.disable
|
102
|
+
newscore = (GameMain.mode==:endless ? i.score.max : i.score.value)
|
103
|
+
if Highscore.instance.high?(newscore)
|
104
|
+
NameEntry.enable
|
105
|
+
else
|
106
|
+
ModeSelect.enable
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def draw(i)
|
112
|
+
@font.drawBlendedUTF8(i.scr,"HIT ENTER KEY", 160,220 , 0,0,0) if @draw
|
113
|
+
end
|
114
|
+
|
115
|
+
end
|
116
|
+
|
117
|
+
class NameEntry
|
118
|
+
extend SingleTask
|
119
|
+
|
120
|
+
CHARS = []
|
121
|
+
26.times{|i| CHARS << ?A+i}
|
122
|
+
10.times{|i| CHARS << ?0+i}
|
123
|
+
CHARS << -1 # 'BS'
|
124
|
+
CHARS << -2 # 'END'
|
125
|
+
|
126
|
+
R = 160
|
127
|
+
BASE = Math::PI / 2
|
128
|
+
RAD = Math::PI * 2 / CHARS.size
|
129
|
+
|
130
|
+
def init
|
131
|
+
@font_small = SDL::TTF.open("image/curving.ttf", 10)
|
132
|
+
@font = SDL::TTF.open("image/curving.ttf", 24)
|
133
|
+
@font_big = SDL::TTF.open("image/curving.ttf", 30)
|
134
|
+
@waittimer = Timer.new(100)
|
135
|
+
@name = ""
|
136
|
+
@cur = 0
|
137
|
+
end
|
138
|
+
|
139
|
+
def enabled
|
140
|
+
Bath.enable
|
141
|
+
Jumpers.disable
|
142
|
+
end
|
143
|
+
|
144
|
+
def act(dt,i)
|
145
|
+
if i.keydown.other
|
146
|
+
i.keydown.other.each do |sym|
|
147
|
+
case sym
|
148
|
+
when SDL::Key::BACKSPACE, SDL::Key::DELETE
|
149
|
+
@name.chop!
|
150
|
+
when (SDL::Key::A..SDL::Key::Z)
|
151
|
+
if sym==SDL::Key::H && i.key.ctrl
|
152
|
+
@name.chop!
|
153
|
+
else
|
154
|
+
@cur = sym - SDL::Key::A
|
155
|
+
@name << (?A + @cur).chr
|
156
|
+
end
|
157
|
+
when (SDL::Key::K0..SDL::Key::K9)
|
158
|
+
@cur = sym - SDL::Key::K0
|
159
|
+
@name << (?0 + @cur).chr
|
160
|
+
when (SDL::Key::KP0..SDL::Key::KP9)
|
161
|
+
@cur = sym - SDL::Key::KP0
|
162
|
+
@name << (?0 + @cur).chr
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
if i.keydown.button
|
168
|
+
case CHARS[@cur]
|
169
|
+
when -1 # BS
|
170
|
+
@name.chop!
|
171
|
+
when -2 # END
|
172
|
+
newscore = (GameMain.mode==:endless ? i.score.max : i.score.value)
|
173
|
+
Highscore.instance.add( newscore, @name.dup )
|
174
|
+
self.disable
|
175
|
+
Bath.disable
|
176
|
+
ModeSelect.enable
|
177
|
+
else
|
178
|
+
if i.keydown.other && i.keydown.other.include?(SDL::Key::RETURN)
|
179
|
+
@cur = CHARS.size-1
|
180
|
+
else
|
181
|
+
@name << CHARS[@cur].chr
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
@waittimer.wait(dt){
|
187
|
+
if i.key.left
|
188
|
+
@cur -= 1
|
189
|
+
@cur = CHARS.size-1 if @cur<0
|
190
|
+
elsif i.key.right
|
191
|
+
@cur += 1
|
192
|
+
@cur = 0 if @cur>CHARS.size-1
|
193
|
+
end
|
194
|
+
}
|
195
|
+
end
|
196
|
+
|
197
|
+
def draw(i)
|
198
|
+
CHARS.each_with_index do |c,n|
|
199
|
+
x = 320 + (R * Math.sin(RAD*(n-@cur)))
|
200
|
+
y = 200 + (R * Math.cos(RAD*(n-@cur)))
|
201
|
+
color = (n==@cur) ? [255,80,80] : [80,80,80]
|
202
|
+
|
203
|
+
if c==-1 # BS
|
204
|
+
@font_small.drawBlendedUTF8(i.scr, "D", x,y , *color)
|
205
|
+
@font_small.drawBlendedUTF8(i.scr, "E", x+5,y+5 , *color)
|
206
|
+
@font_small.drawBlendedUTF8(i.scr, "L", x+10,y+10 , *color)
|
207
|
+
elsif c==-2 # END
|
208
|
+
@font_small.drawBlendedUTF8(i.scr, "E", x,y , *color)
|
209
|
+
@font_small.drawBlendedUTF8(i.scr, "N", x+5,y+5 , *color)
|
210
|
+
@font_small.drawBlendedUTF8(i.scr, "D", x+10,y+10 , *color)
|
211
|
+
elsif n==@cur
|
212
|
+
@font_big.drawBlendedUTF8(i.scr, c.chr, x,y , *color)
|
213
|
+
else
|
214
|
+
@font.drawBlendedUTF8( i.scr, c.chr, x,y , *color)
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
x = 320 - @font_big.textSize(@name).first / 2
|
219
|
+
@font_big.drawBlendedUTF8(i.scr, @name, x,192 , 255,80,80)
|
220
|
+
end
|
221
|
+
|
222
|
+
end
|
223
|
+
|
data/bathtub/score.rb
ADDED
@@ -0,0 +1,121 @@
|
|
1
|
+
#
|
2
|
+
# score.rb
|
3
|
+
#
|
4
|
+
|
5
|
+
class Score
|
6
|
+
extend SingleTask
|
7
|
+
|
8
|
+
def init
|
9
|
+
@font=SDL::TTF.open("image/boxfont2.ttf", 40)
|
10
|
+
end
|
11
|
+
|
12
|
+
def reset
|
13
|
+
@life = Consts::LIVES
|
14
|
+
@score = 0
|
15
|
+
@max = 0
|
16
|
+
end
|
17
|
+
attr_accessor :score
|
18
|
+
attr_reader :max
|
19
|
+
|
20
|
+
def value
|
21
|
+
@score
|
22
|
+
end
|
23
|
+
|
24
|
+
def incr
|
25
|
+
@score+=1
|
26
|
+
@max = @score if @max < @score
|
27
|
+
end
|
28
|
+
|
29
|
+
def miss
|
30
|
+
if GameMain.mode==:endless
|
31
|
+
@max = @score if @max < @score
|
32
|
+
@score = 0
|
33
|
+
else
|
34
|
+
@life -= 1
|
35
|
+
if @life < 0
|
36
|
+
GameMain.disable
|
37
|
+
Gameover.enable
|
38
|
+
@life = 0
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def draw(i)
|
44
|
+
if GameMain.mode==:endless
|
45
|
+
@font.drawBlendedUTF8(i.scr," LIFE: .. MAXCOMBO:#{'%3d' % @max}", 0,0 , 0,0,0)
|
46
|
+
else
|
47
|
+
lifemeter = '*'*@life + ' '*(Consts::LIVES-@life)
|
48
|
+
@font.drawBlendedUTF8(i.scr," LIFE: #{lifemeter} SCORE:#{'%3d' % @score}", 0,0 , 0,0,0)
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
|
56
|
+
module Enumerable
|
57
|
+
def stable_sort
|
58
|
+
i = 0
|
59
|
+
self.sort_by{|v| [v, i += 1]}
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
|
64
|
+
class Highscore
|
65
|
+
extend SingleTask
|
66
|
+
|
67
|
+
N = 5
|
68
|
+
FILE = "highscore.dat"
|
69
|
+
|
70
|
+
def init
|
71
|
+
@font = SDL::TTF.open("image/boxfont2.ttf", 25)
|
72
|
+
@scores = read() || Hash.new
|
73
|
+
ModeSelect::MODES.each do |mode|
|
74
|
+
@scores[mode] ||= []
|
75
|
+
end
|
76
|
+
@show = nil
|
77
|
+
end
|
78
|
+
attr_reader :scores
|
79
|
+
attr_writer :show
|
80
|
+
|
81
|
+
def high?(score)
|
82
|
+
p score, @scores
|
83
|
+
return false if score==0
|
84
|
+
mode = GameMain.mode
|
85
|
+
@scores[mode].empty? || @scores[mode].size < N || @scores[mode].last[0] < score
|
86
|
+
end
|
87
|
+
|
88
|
+
def add(score,name)
|
89
|
+
return unless high?(score)
|
90
|
+
mode = GameMain.mode
|
91
|
+
@scores[mode] << [score, name]
|
92
|
+
@scores[mode] = @scores[mode].stable_sort.reverse[0,N]
|
93
|
+
write
|
94
|
+
end
|
95
|
+
|
96
|
+
def read
|
97
|
+
ret = nil
|
98
|
+
if File.exist?(FILE)
|
99
|
+
open(FILE,"rb") do |f|
|
100
|
+
ret = Marshal.load(f)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
ret
|
104
|
+
end
|
105
|
+
|
106
|
+
def write
|
107
|
+
open(FILE,"wb") do |f|
|
108
|
+
Marshal.dump(@scores,f)
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def draw(i)
|
113
|
+
@font.drawBlendedUTF8(i.scr, "* HighScore *", 380,38, 0,0,255)
|
114
|
+
@scores[@show].each_with_index do |item,n|
|
115
|
+
score,name = *item
|
116
|
+
@font.drawBlendedUTF8(i.scr, "#{n+1}. #{score} (#{name})", 380,65+(20*n), 0,0,255)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
end
|
121
|
+
|
data/bathtub/task.rb
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
#
|
2
|
+
# task.rb
|
3
|
+
#
|
4
|
+
|
5
|
+
class TaskManager
|
6
|
+
|
7
|
+
class << TaskManager
|
8
|
+
def init
|
9
|
+
@@task = []
|
10
|
+
end
|
11
|
+
|
12
|
+
def add_task(t)
|
13
|
+
@@task << t
|
14
|
+
end
|
15
|
+
|
16
|
+
def reset
|
17
|
+
@@task.each{|t| t.reset}
|
18
|
+
end
|
19
|
+
def draw(info)
|
20
|
+
@@task.each{|t| t.draw(info) if t.active?}
|
21
|
+
end
|
22
|
+
def act(dt,info)
|
23
|
+
@@task.each{|t| t.act(dt,info) if t.active?}
|
24
|
+
@@task.delete_if{|t| !t.alive}
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
module Task
|
31
|
+
Info = Struct.new(:key,:keydown,:scr,:score)
|
32
|
+
|
33
|
+
def initialize
|
34
|
+
@active = true
|
35
|
+
@alive = true
|
36
|
+
TaskManager.add_task(self)
|
37
|
+
init
|
38
|
+
end
|
39
|
+
attr_accessor :alive
|
40
|
+
|
41
|
+
def active?; @active; end
|
42
|
+
def enable; @active = true; enabled; end
|
43
|
+
def disable; @active = false; disabled; end
|
44
|
+
|
45
|
+
def enabled; end
|
46
|
+
def disabled; end
|
47
|
+
|
48
|
+
def init; end
|
49
|
+
def act(dt,info); end
|
50
|
+
def draw(info); end
|
51
|
+
def reset; end
|
52
|
+
end
|
53
|
+
|
54
|
+
module SingleTask
|
55
|
+
def self.extended(klass)
|
56
|
+
klass.__send__ :include, Singleton
|
57
|
+
klass.__send__ :include, Task
|
58
|
+
end
|
59
|
+
|
60
|
+
def active?; self.instance.active?; end
|
61
|
+
def enable; self.instance.enable; end
|
62
|
+
def disable; self.instance.disable; end
|
63
|
+
end
|
data/bin/bathtub
ADDED
data/highscore.dat
ADDED
Binary file
|
data/image/back.bmp
ADDED
Binary file
|
data/image/bath.bmp
ADDED
Binary file
|
data/image/boxfont2.ttf
ADDED
Binary file
|
data/image/curving.ttf
ADDED
Binary file
|
data/image/hito.bmp
ADDED
Binary file
|
Binary file
|
Binary file
|
data/image/icon.bmp
ADDED
Binary file
|
data/image/logo.bmp
ADDED
Binary file
|
data/image/shibuki.bmp
ADDED
Binary file
|
data/image/staff.bmp
ADDED
Binary file
|
data/msvcr71.dll
ADDED
Binary file
|
data/readme.txt
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
|
2
|
+
�o �X �^ �u �� �� ��
|
3
|
+
|
4
|
+
C67 �o�[�W����
|
5
|
+
|
6
|
+
�y�O����z
|
7
|
+
��N��C65�ɂ�EndEffector�́u���܂��v�Ƃ��Ď��^����Ă����o�X�^�u�꒼�����A
|
8
|
+
�P�N�̎����o�Ă����ɕ����I�i�������悤�Ȃ����ł��Ȃ��悤�ȕ��͋C�����y���݂��������B
|
9
|
+
|
10
|
+
�y�V�ѕ��z
|
11
|
+
��������`���Ĕ��ł���l�X���A�o�X�^�u�ŃL���b�`���Ă��������B
|
12
|
+
�R��~�X��ƃQ�[���I�[�o�[�ł��B
|
13
|
+
|
14
|
+
EASY: �ȒP�ł��B
|
15
|
+
NORMAL: �ӂ��ł��B
|
16
|
+
ENDLESS: �u�I��肪�Ȃ��v�Ə����ăG���h���X�ł��B�O������ESC�L�[�ŏI�����Ă��������B :-P
|
17
|
+
|
18
|
+
�y����z
|
19
|
+
���E�L�[�ňړ��B
|
20
|
+
�������́A�X�y�[�Xor�G���^�[�L�[�ŕ����]���B
|
21
|
+
|
22
|
+
�l�[���G���g���[�͍��E�ňړ��A�X�y�[�X�L�[�Ō���B�i���̓L�[�{�[�h���g���܂��j
|
23
|
+
|
24
|
+
�y�ӎ��z
|
25
|
+
�o�X�^�u�꒼����Ruby/SDL��p���Đ��삳��Aexerb��p���Ď��s�t�@�C����
|
26
|
+
���܂����B
|
27
|
+
- �I�u�W�F�N�g�w���X�N���v�g����Ruby: http://www.ruby-lang.org/ja/
|
28
|
+
- SDL(Simple DirectMedia Layer): http://www.libsdl.org/
|
29
|
+
- Ruby/SDL: http://www.kmc.gr.jp/~ohai/rubysdl.html
|
30
|
+
- exerb: http://exerb.sourceforge.jp/
|
31
|
+
|
32
|
+
�܂��o�X�^�u�ɔ�э��ތ��ʉ���WEB WAVE LIB�l�̂��̂��g�킹�Ă�����Ă܂��B
|
33
|
+
- WEB WAVE LIB: http://www.s-t-t.com/wwl/
|
34
|
+
|
35
|
+
----
|
36
|
+
yhara�i�� �I�j/ ����}�C�R���N���u
|
37
|
+
http://mono.kmc.gr.jp/~yhara/
|
38
|
+
mailto: yhara@kmc.gr.jp
|
Binary file
|
Binary file
|
data/sound/Stabs110.wav
ADDED
Binary file
|
data/sound/Stabs63.wav
ADDED
Binary file
|
data/sound/blacksamba.it
ADDED
Binary file
|
data/sound/bom08.wav
ADDED
Binary file
|
data/sound/clambient.it
ADDED
Binary file
|
data/sound/fall.wav
ADDED
Binary file
|
data/sound/get.wav
ADDED
Binary file
|
metadata
ADDED
@@ -0,0 +1,117 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: bathtub
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 15
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 5
|
9
|
+
- 2
|
10
|
+
version: 0.5.2
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Yutaka HARA
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2010-08-28 00:00:00 +09:00
|
19
|
+
default_executable: bathtub
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: rubysdl
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 3
|
30
|
+
segments:
|
31
|
+
- 0
|
32
|
+
version: "0"
|
33
|
+
type: :runtime
|
34
|
+
version_requirements: *id001
|
35
|
+
description: An action game written with Ruby/SDL
|
36
|
+
email: yutaka.hara/at/gmail.com
|
37
|
+
executables:
|
38
|
+
- bathtub
|
39
|
+
extensions: []
|
40
|
+
|
41
|
+
extra_rdoc_files: []
|
42
|
+
|
43
|
+
files:
|
44
|
+
- SDL.dll
|
45
|
+
- SDL_mixer.dll
|
46
|
+
- SDL_ttf.dll
|
47
|
+
- SGE.dll
|
48
|
+
- VERSION
|
49
|
+
- bathtub.exe
|
50
|
+
- bathtub/character.rb
|
51
|
+
- bathtub/game.rb
|
52
|
+
- bathtub/graphic.rb
|
53
|
+
- bathtub/main.rb
|
54
|
+
- bathtub/misc.rb
|
55
|
+
- bathtub/scene.rb
|
56
|
+
- bathtub/score.rb
|
57
|
+
- bathtub/task.rb
|
58
|
+
- bin/bathtub
|
59
|
+
- highscore.dat
|
60
|
+
- image/back.bmp
|
61
|
+
- image/bath.bmp
|
62
|
+
- image/boxfont2.ttf
|
63
|
+
- image/curving.ttf
|
64
|
+
- image/hito.bmp
|
65
|
+
- image/icon-16164.bmp
|
66
|
+
- image/icon-16168.bmp
|
67
|
+
- image/icon.bmp
|
68
|
+
- image/logo.bmp
|
69
|
+
- image/shibuki.bmp
|
70
|
+
- image/staff.bmp
|
71
|
+
- msvcr71.dll
|
72
|
+
- readme.txt
|
73
|
+
- sound/BB_Scratch_19.wav
|
74
|
+
- sound/SplashA1@22.wav
|
75
|
+
- sound/Stabs110.wav
|
76
|
+
- sound/Stabs63.wav
|
77
|
+
- sound/blacksamba.it
|
78
|
+
- sound/bom08.wav
|
79
|
+
- sound/clambient.it
|
80
|
+
- sound/fall.wav
|
81
|
+
- sound/get.wav
|
82
|
+
has_rdoc: true
|
83
|
+
homepage: http://github.com/yhara/bathtub
|
84
|
+
licenses: []
|
85
|
+
|
86
|
+
post_install_message:
|
87
|
+
rdoc_options:
|
88
|
+
- --charset=UTF-8
|
89
|
+
require_paths:
|
90
|
+
- lib
|
91
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
92
|
+
none: false
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
hash: 3
|
97
|
+
segments:
|
98
|
+
- 0
|
99
|
+
version: "0"
|
100
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
101
|
+
none: false
|
102
|
+
requirements:
|
103
|
+
- - ">="
|
104
|
+
- !ruby/object:Gem::Version
|
105
|
+
hash: 3
|
106
|
+
segments:
|
107
|
+
- 0
|
108
|
+
version: "0"
|
109
|
+
requirements: []
|
110
|
+
|
111
|
+
rubyforge_project:
|
112
|
+
rubygems_version: 1.3.7
|
113
|
+
signing_key:
|
114
|
+
specification_version: 3
|
115
|
+
summary: An action game written with Ruby/SDL
|
116
|
+
test_files: []
|
117
|
+
|