sokoban.rb 0.0.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/.README.swp +0 -0
- data/.gitignore +5 -0
- data/.rvmrc +3 -0
- data/Gemfile +4 -0
- data/README +39 -0
- data/Rakefile +1 -0
- data/bin/.gears3.rb.swp +0 -0
- data/bin/.opengl_sokoban.rb.swp +0 -0
- data/bin/.sokoban.swp +0 -0
- data/bin/ignore_me_unix_term_sokoban.rb +266 -0
- data/bin/original_opengl_sokoban.rb +236 -0
- data/bin/run +11 -0
- data/bin/sokoban +485 -0
- data/lib/sokoban/config.rb +22 -0
- data/lib/sokoban/game_engine.rb +215 -0
- data/lib/sokoban/render.rb +401 -0
- data/lib/sokoban/sokoban_levels.txt +760 -0
- data/lib/sokoban/sokoban_saved_game.yaml +1821 -0
- data/lib/sokoban.rb +10 -0
- data/sokoban.gemspec +33 -0
- data/spec/sokoban/board_spec.rb +477 -0
- data/spec/spec_helper.rb +10 -0
- data/test/sokoban/board_test.rb +38 -0
- data/test/sokoban/tc_moveable.rb +41 -0
- data/test/test_helper.rb +28 -0
- metadata +108 -0
data/.README.swp
ADDED
Binary file
|
data/.gitignore
ADDED
data/.rvmrc
ADDED
data/Gemfile
ADDED
data/README
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
|
2
|
+
about using opengl with different versions of Ruby:
|
3
|
+
#######################################
|
4
|
+
#ruby 1.9.1 :
|
5
|
+
#gem : ruby-opengl
|
6
|
+
#
|
7
|
+
#if working with ruby 1.9.1-p376 + gem: ruby-opengl :
|
8
|
+
#read: http://rubygamedev.wordpress.com/2010/04/16/ruby-opengl-on-ruby-1-9/
|
9
|
+
#
|
10
|
+
# ruby 1.9.2 :
|
11
|
+
# gem: ffi-opengl
|
12
|
+
########################################
|
13
|
+
|
14
|
+
|
15
|
+
|
16
|
+
|
17
|
+
1.to play: run bin/sokoban
|
18
|
+
2.
|
19
|
+
keys:
|
20
|
+
----
|
21
|
+
as arrows:
|
22
|
+
##u##
|
23
|
+
#hjk#
|
24
|
+
|
25
|
+
quit : press esc or q
|
26
|
+
|
27
|
+
|
28
|
+
next to implement:
|
29
|
+
-----------------
|
30
|
+
1.console game
|
31
|
+
2.console game with colors
|
32
|
+
3.testing
|
33
|
+
4.using ruby 1.9.2 with gosu opengl
|
34
|
+
5.add optional prespective - user camera (fps view)
|
35
|
+
6.moving project to mvc stracture
|
36
|
+
7.draw only require cells
|
37
|
+
|
38
|
+
done:
|
39
|
+
use displaylist for faster drawing
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'bundler/gem_tasks'
|
data/bin/.gears3.rb.swp
ADDED
Binary file
|
Binary file
|
data/bin/.sokoban.swp
ADDED
Binary file
|
@@ -0,0 +1,266 @@
|
|
1
|
+
|
2
|
+
#require "sokoban"
|
3
|
+
|
4
|
+
def draw( g )
|
5
|
+
screen = "Level #{g.level} - #{g.moves} moves\n\n" + g.display
|
6
|
+
screen.gsub("\n", "\r\n")
|
7
|
+
end
|
8
|
+
|
9
|
+
system "stty raw -echo"
|
10
|
+
|
11
|
+
game = Sokoban.new
|
12
|
+
|
13
|
+
loop do
|
14
|
+
system "clear"
|
15
|
+
puts draw(game)
|
16
|
+
|
17
|
+
if game.level_solved?
|
18
|
+
puts "\r\nLevel solved. Nice Work!\r\n"
|
19
|
+
sleep 3
|
20
|
+
game.load_level
|
21
|
+
|
22
|
+
break if game.over?
|
23
|
+
end
|
24
|
+
|
25
|
+
case STDIN.getc
|
26
|
+
when ?Q, ?\C-c
|
27
|
+
break
|
28
|
+
when ?S
|
29
|
+
game.save
|
30
|
+
when ?L
|
31
|
+
game = Sokoban.load if test ?e, "sokoban_saved_game.yaml"
|
32
|
+
when ?R
|
33
|
+
game.restart_level
|
34
|
+
when ?U
|
35
|
+
game.undo
|
36
|
+
when ?j, ?j
|
37
|
+
game.move_left
|
38
|
+
when ?k, ?K
|
39
|
+
game.move_right
|
40
|
+
when ?m, ?m
|
41
|
+
game.move_down
|
42
|
+
when ?i, ?I
|
43
|
+
game.move_up
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
if game.over?
|
48
|
+
system "clear"
|
49
|
+
puts "\r\nYou've solved all the levels Puzzle Master!!!\r\n\r\n"
|
50
|
+
end
|
51
|
+
|
52
|
+
END { system "stty -raw echo" }
|
53
|
+
|
54
|
+
#!/usr/bin/env ruby
|
55
|
+
|
56
|
+
require "yaml"
|
57
|
+
|
58
|
+
class Sokoban
|
59
|
+
WALL = "#"
|
60
|
+
OPEN_FLOOR = " "
|
61
|
+
|
62
|
+
MAN = "@"
|
63
|
+
CRATE = "o"
|
64
|
+
|
65
|
+
STORAGE = "."
|
66
|
+
MAN_ON_STORAGE = "+"
|
67
|
+
CRATE_ON_STORAGE = "*"
|
68
|
+
|
69
|
+
MAX_UNDO = 10
|
70
|
+
|
71
|
+
PATH = File.expand_path(File.dirname(__FILE__))
|
72
|
+
|
73
|
+
attr_reader :level, :moves
|
74
|
+
|
75
|
+
def self.load( file = File.join(PATH, "sokoban_saved_game.yaml") )
|
76
|
+
game = nil
|
77
|
+
|
78
|
+
File.open file do |f|
|
79
|
+
game = YAML.load(f)
|
80
|
+
end
|
81
|
+
|
82
|
+
game ||= Sokoban.new
|
83
|
+
game
|
84
|
+
end
|
85
|
+
|
86
|
+
def initialize( file = File.join(PATH, "sokoban_levels.txt") )
|
87
|
+
@level_file = file
|
88
|
+
|
89
|
+
@board = [ ]
|
90
|
+
@level = 0
|
91
|
+
@over = false
|
92
|
+
|
93
|
+
@undos = [ ]
|
94
|
+
@moves = 0
|
95
|
+
|
96
|
+
load_level
|
97
|
+
end
|
98
|
+
|
99
|
+
def can_move_down?( ) can_move? :down end
|
100
|
+
def can_move_left?( ) can_move? :left end
|
101
|
+
def can_move_right?( ) can_move? :right end
|
102
|
+
def can_move_up?( ) can_move? :up end
|
103
|
+
|
104
|
+
def display
|
105
|
+
@board.inject("") { |dis, row| dis + row.join + "\n" }
|
106
|
+
end
|
107
|
+
|
108
|
+
def level_solved?
|
109
|
+
@board.each_with_index do |row, y|
|
110
|
+
row.each_with_index do |cell, x|
|
111
|
+
return false if cell == CRATE
|
112
|
+
end
|
113
|
+
end
|
114
|
+
true
|
115
|
+
end
|
116
|
+
|
117
|
+
def load_level( level = @level += 1, file = @level_file )
|
118
|
+
loaded = false
|
119
|
+
|
120
|
+
File.open file do |f|
|
121
|
+
count = 0
|
122
|
+
while lvl = f.gets("")
|
123
|
+
count += 1
|
124
|
+
if count == level
|
125
|
+
@board = [ ]
|
126
|
+
lvl.chomp!
|
127
|
+
lvl.each_line { |e| @board << e.chomp.split("") }
|
128
|
+
loaded = true
|
129
|
+
break
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
if loaded
|
135
|
+
@undos = [ ]
|
136
|
+
@moves = 0
|
137
|
+
else
|
138
|
+
@over = true
|
139
|
+
end
|
140
|
+
|
141
|
+
loaded
|
142
|
+
end
|
143
|
+
|
144
|
+
def move_down( ) move :down end
|
145
|
+
def move_left( ) move :left end
|
146
|
+
def move_right( ) move :right end
|
147
|
+
def move_up( ) move :up end
|
148
|
+
|
149
|
+
def over?
|
150
|
+
@over
|
151
|
+
end
|
152
|
+
|
153
|
+
def restart_level
|
154
|
+
load_level @level
|
155
|
+
end
|
156
|
+
|
157
|
+
def save( file = File.join(PATH, "sokoban_saved_game.yaml") )
|
158
|
+
File.open(file, "w") do |f|
|
159
|
+
f << YAML.dump(self)
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
def undo
|
164
|
+
if @undos.size > 0
|
165
|
+
@board = @undos.pop
|
166
|
+
@moves -= 1
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
private
|
171
|
+
|
172
|
+
def can_move?( dir )
|
173
|
+
x, y = where_am_i
|
174
|
+
case dir
|
175
|
+
when :down
|
176
|
+
first = @board[y + 1][x]
|
177
|
+
second = y < @board.size - 2 ? @board[y + 2][x] : nil
|
178
|
+
when :left
|
179
|
+
first = @board[y][x - 1]
|
180
|
+
second = x >= 2 ? @board[y][x - 2] : nil
|
181
|
+
when :right
|
182
|
+
first = @board[y][x + 1]
|
183
|
+
second = x < @board[y].size - 2 ? @board[y][x + 2] : nil
|
184
|
+
when :up
|
185
|
+
first = @board[y - 1][x]
|
186
|
+
second = y >= 2 ? @board[y - 2][x] : nil
|
187
|
+
end
|
188
|
+
|
189
|
+
if first == OPEN_FLOOR or first == STORAGE
|
190
|
+
true
|
191
|
+
elsif not second.nil? and
|
192
|
+
(first == CRATE or first == CRATE_ON_STORAGE) and
|
193
|
+
(second == OPEN_FLOOR or second == STORAGE)
|
194
|
+
true
|
195
|
+
else
|
196
|
+
false
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
def move( dir )
|
201
|
+
return false unless can_move? dir
|
202
|
+
|
203
|
+
@undos << Marshal.load(Marshal.dump(@board))
|
204
|
+
@undos.shift if @undos.size > MAX_UNDO
|
205
|
+
@moves += 1
|
206
|
+
|
207
|
+
x, y = where_am_i
|
208
|
+
case dir
|
209
|
+
when :down
|
210
|
+
if @board[y + 1][x] == CRATE or @board[y + 1][x] == CRATE_ON_STORAGE
|
211
|
+
move_crate x, y + 1, x, y + 2
|
212
|
+
end
|
213
|
+
move_man x, y, x, y + 1
|
214
|
+
when :left
|
215
|
+
if @board[y][x - 1] == CRATE or @board[y][x - 1] == CRATE_ON_STORAGE
|
216
|
+
move_crate x - 1, y, x - 2, y
|
217
|
+
end
|
218
|
+
move_man x, y, x - 1, y
|
219
|
+
when :right
|
220
|
+
if @board[y][x + 1] == CRATE or @board[y][x + 1] == CRATE_ON_STORAGE
|
221
|
+
move_crate x + 1, y, x + 2, y
|
222
|
+
end
|
223
|
+
move_man x, y, x + 1, y
|
224
|
+
when :up
|
225
|
+
if @board[y - 1][x] == CRATE or @board[y - 1][x] == CRATE_ON_STORAGE
|
226
|
+
move_crate x, y - 1, x, y - 2
|
227
|
+
end
|
228
|
+
move_man x, y, x, y - 1
|
229
|
+
end
|
230
|
+
true
|
231
|
+
end
|
232
|
+
|
233
|
+
def move_crate( from_x, from_y, to_x, to_y )
|
234
|
+
if @board[to_y][to_x] == STORAGE
|
235
|
+
@board[to_y][to_x] = CRATE_ON_STORAGE
|
236
|
+
else
|
237
|
+
@board[to_y][to_x] = CRATE
|
238
|
+
end
|
239
|
+
if @board[from_y][from_x] == CRATE_ON_STORAGE
|
240
|
+
@board[from_y][from_x] = STORAGE
|
241
|
+
else
|
242
|
+
@board[from_y][from_x] = OPEN_FLOOR
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
def move_man( from_x, from_y, to_x, to_y )
|
247
|
+
if @board[to_y][to_x] == STORAGE
|
248
|
+
@board[to_y][to_x] = MAN_ON_STORAGE
|
249
|
+
else
|
250
|
+
@board[to_y][to_x] = MAN
|
251
|
+
end
|
252
|
+
if @board[from_y][from_x] == MAN_ON_STORAGE
|
253
|
+
@board[from_y][from_x] = STORAGE
|
254
|
+
else
|
255
|
+
@board[from_y][from_x] = OPEN_FLOOR
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
259
|
+
def where_am_i
|
260
|
+
@board.each_with_index do |row, y|
|
261
|
+
row.each_with_index do |cell, x|
|
262
|
+
return x, y if cell == MAN or cell == MAN_ON_STORAGE
|
263
|
+
end
|
264
|
+
end
|
265
|
+
end
|
266
|
+
end
|
@@ -0,0 +1,236 @@
|
|
1
|
+
|
2
|
+
require "opengl"
|
3
|
+
require "glut"
|
4
|
+
|
5
|
+
#require "sokoban"
|
6
|
+
require File.dirname(__FILE__) + '/../lib/sokoban'
|
7
|
+
|
8
|
+
PATH = File.expand_path(File.dirname(__FILE__))
|
9
|
+
|
10
|
+
def init
|
11
|
+
GL.Light GL::LIGHT0, GL::AMBIENT, [0.0, 0.0, 0.0, 1.0]
|
12
|
+
GL.Light GL::LIGHT0, GL::DIFFUSE, [1.0, 1.0, 1.0, 1.0]
|
13
|
+
GL.Light GL::LIGHT0, GL::POSITION, [0.0, 3.0, 3.0, 0.0]
|
14
|
+
GL.LightModel GL::LIGHT_MODEL_AMBIENT, [0.2, 0.2, 0.2, 1.0]
|
15
|
+
GL.LightModel GL::LIGHT_MODEL_LOCAL_VIEWER, [0.0]
|
16
|
+
|
17
|
+
GL.FrontFace GL::CW
|
18
|
+
GL.Enable GL::LIGHTING
|
19
|
+
GL.Enable GL::LIGHT0
|
20
|
+
GL.Enable GL::AUTO_NORMAL
|
21
|
+
GL.Enable GL::NORMALIZE
|
22
|
+
GL.Enable GL::DEPTH_TEST
|
23
|
+
GL.DepthFunc GL::LESS
|
24
|
+
end
|
25
|
+
|
26
|
+
def render_man
|
27
|
+
GL.Material GL::FRONT, GL::AMBIENT, [0.0, 0.0, 0.0, 1.0]
|
28
|
+
GL.Material GL::FRONT, GL::DIFFUSE, [0.5, 0.0, 0.0, 1.0]
|
29
|
+
GL.Material GL::FRONT, GL::SPECULAR, [0.7, 0.6, 0.6, 1.0]
|
30
|
+
GL.Material GL::FRONT, GL::SHININESS, 0.25 * 128.0
|
31
|
+
|
32
|
+
GLUT.SolidSphere 0.5, 16, 16
|
33
|
+
end
|
34
|
+
|
35
|
+
def render_crate
|
36
|
+
GL.Material GL::FRONT, GL::AMBIENT, [0.19125, 0.0735, 0.0225, 1.0]
|
37
|
+
GL.Material GL::FRONT, GL::DIFFUSE, [0.7038, 0.27048, 0.0828, 1.0]
|
38
|
+
GL.Material GL::FRONT, GL::SPECULAR, [0.256777, 0.137622, 0.086014, 1.0]
|
39
|
+
GL.Material GL::FRONT, GL::SHININESS, 0.1 * 128.0
|
40
|
+
|
41
|
+
GL.PushMatrix
|
42
|
+
GL.Scale 0.9, 0.9, 0.9
|
43
|
+
GL.Translate 0.0, 0.0, 0.45
|
44
|
+
|
45
|
+
GLUT.SolidCube 1.0
|
46
|
+
GL.PopMatrix
|
47
|
+
end
|
48
|
+
|
49
|
+
def render_stored_crate
|
50
|
+
GL.Material GL::FRONT, GL::AMBIENT, [0.25, 0.20725, 0.20725, 1.0]
|
51
|
+
GL.Material GL::FRONT, GL::DIFFUSE, [1.0, 0.829, 0.829, 1.0]
|
52
|
+
GL.Material GL::FRONT, GL::SPECULAR, [0.296648, 0.296648, 0.296648, 1.0]
|
53
|
+
GL.Material GL::FRONT, GL::SHININESS, 0.088 * 128.0
|
54
|
+
|
55
|
+
GL.PushMatrix
|
56
|
+
GL.Scale 0.9, 0.9, 0.9
|
57
|
+
GL.Translate 0.0, 0.0, 0.45
|
58
|
+
|
59
|
+
GLUT.SolidCube 1.0
|
60
|
+
GL.PopMatrix
|
61
|
+
end
|
62
|
+
|
63
|
+
def render_open_floor
|
64
|
+
GL.Material GL::FRONT, GL::AMBIENT, [0.05, 0.05, 0.05, 1.0]
|
65
|
+
GL.Material GL::FRONT, GL::DIFFUSE, [0.5, 0.5, 0.5, 1.0]
|
66
|
+
GL.Material GL::FRONT, GL::SPECULAR, [0.7, 0.7, 0.7, 1.0]
|
67
|
+
GL.Material GL::FRONT, GL::SHININESS, 0.078125 * 128.0
|
68
|
+
|
69
|
+
GL.PushMatrix
|
70
|
+
GL.Scale 0.9, 0.9, 0.1
|
71
|
+
GL.Translate 0.0, 0.0, -0.05
|
72
|
+
|
73
|
+
GLUT.SolidCube 1.0
|
74
|
+
GL.PopMatrix
|
75
|
+
|
76
|
+
GL.Material GL::FRONT, GL::AMBIENT, [0.05375, 0.05, 0.06625, 1.0]
|
77
|
+
GL.Material GL::FRONT, GL::DIFFUSE, [0.18275, 0.17, 0.22525, 1.0]
|
78
|
+
GL.Material GL::FRONT, GL::SPECULAR, [0.332741, 0.328634, 0.346435, 1.0]
|
79
|
+
GL.Material GL::FRONT, GL::SHININESS, 0.3 * 128.0
|
80
|
+
|
81
|
+
GL.PushMatrix
|
82
|
+
GL.Scale 1.0, 1.0, 0.1
|
83
|
+
GL.Translate 0.0, 0.0, -0.1
|
84
|
+
|
85
|
+
GLUT.SolidCube 1.0
|
86
|
+
GL.PopMatrix
|
87
|
+
end
|
88
|
+
|
89
|
+
def render_storage
|
90
|
+
GL.Material GL::FRONT, GL::AMBIENT, [0.05, 0.05, 0.0, 1.0]
|
91
|
+
GL.Material GL::FRONT, GL::DIFFUSE, [0.5, 0.5, 0.4, 1.0]
|
92
|
+
GL.Material GL::FRONT, GL::SPECULAR, [0.7, 0.7, 0.04, 1.0]
|
93
|
+
GL.Material GL::FRONT, GL::SHININESS, 0.078125 * 128.0
|
94
|
+
|
95
|
+
GL.PushMatrix
|
96
|
+
GL.Scale 0.9, 0.9, 0.1
|
97
|
+
GL.Translate 0.0, 0.0, -0.05
|
98
|
+
|
99
|
+
GLUT.SolidCube 1.0
|
100
|
+
GL.PopMatrix
|
101
|
+
|
102
|
+
GL.Material GL::FRONT, GL::AMBIENT, [0.05375, 0.05, 0.06625, 1.0]
|
103
|
+
GL.Material GL::FRONT, GL::DIFFUSE, [0.18275, 0.17, 0.22525, 1.0]
|
104
|
+
GL.Material GL::FRONT, GL::SPECULAR, [0.332741, 0.328634, 0.346435, 1.0]
|
105
|
+
GL.Material GL::FRONT, GL::SHININESS, 0.3 * 128.0
|
106
|
+
|
107
|
+
GL.PushMatrix
|
108
|
+
GL.Scale 1.0, 1.0, 0.1
|
109
|
+
GL.Translate 0.0, 0.0, -0.1
|
110
|
+
|
111
|
+
GLUT.SolidCube 1.0
|
112
|
+
GL.PopMatrix
|
113
|
+
end
|
114
|
+
|
115
|
+
def solid_cylinder(radius, height, slices, stacks)
|
116
|
+
GL.PushAttrib GL::POLYGON_BIT
|
117
|
+
GL.PolygonMode GL::FRONT_AND_BACK, GL::FILL
|
118
|
+
obj = GLU.NewQuadric
|
119
|
+
GLU.Cylinder obj, radius, radius, height, slices, stacks
|
120
|
+
GL.PushMatrix
|
121
|
+
GL.Translate 0.0, 0.0, height
|
122
|
+
GLU.Disk obj, 0.0, radius, slices, stacks
|
123
|
+
GL.PopMatrix
|
124
|
+
GLU.DeleteQuadric obj
|
125
|
+
GL.PopAttrib
|
126
|
+
end
|
127
|
+
|
128
|
+
def render_wall
|
129
|
+
GL.Material GL::FRONT, GL::AMBIENT, [0.0, 0.0, 0.0, 1.0]
|
130
|
+
GL.Material GL::FRONT, GL::DIFFUSE, [0.1, 0.35, 0.1, 1.0]
|
131
|
+
GL.Material GL::FRONT, GL::SPECULAR, [0.45, 0.55, 0.45, 1.0]
|
132
|
+
GL.Material GL::FRONT, GL::SHININESS, 0.25 * 128.0
|
133
|
+
|
134
|
+
GL.PushMatrix
|
135
|
+
GL.Translate 0.0, 0.0, 0.5
|
136
|
+
|
137
|
+
solid_cylinder 0.45, 1.0, 16, 4
|
138
|
+
GL.PopMatrix
|
139
|
+
end
|
140
|
+
|
141
|
+
game = Sokoban.new
|
142
|
+
|
143
|
+
display = lambda do
|
144
|
+
GL.Clear GL::COLOR_BUFFER_BIT | GL::DEPTH_BUFFER_BIT
|
145
|
+
|
146
|
+
screen = game.display
|
147
|
+
puts screen.class
|
148
|
+
screen = screen.split("\n")
|
149
|
+
puts screen.class
|
150
|
+
|
151
|
+
screen.each_with_index do |row, y|
|
152
|
+
row.chomp!
|
153
|
+
first = row =~ /^(\s+)/ ? $1.length : 0
|
154
|
+
(first...row.length).each do |x|
|
155
|
+
GL.PushMatrix
|
156
|
+
GL.Translate 1.0 + x, 17.5 - y, 0.0
|
157
|
+
|
158
|
+
if row[x, 1] == "." or row[x, 1] == "*" or row[x, 1] == "+"
|
159
|
+
render_storage
|
160
|
+
else
|
161
|
+
render_open_floor
|
162
|
+
end
|
163
|
+
if row[x, 1] == "@" or row[x, 1] == "+"
|
164
|
+
render_man
|
165
|
+
elsif row[x, 1] == "o"
|
166
|
+
render_crate
|
167
|
+
elsif row[x, 1] == "*"
|
168
|
+
render_stored_crate
|
169
|
+
elsif row[x, 1] == "#"
|
170
|
+
render_wall
|
171
|
+
end
|
172
|
+
GL.PopMatrix
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
GL.Flush
|
177
|
+
end
|
178
|
+
|
179
|
+
reshape = lambda do |w, h|
|
180
|
+
puts w
|
181
|
+
puts h
|
182
|
+
|
183
|
+
GL.Viewport 0, 0, w, h
|
184
|
+
GL.MatrixMode GL::PROJECTION
|
185
|
+
GL.LoadIdentity
|
186
|
+
GL.Frustum(-1.0, 1.0, -1.0, 1.0, 1.5, 20.0)
|
187
|
+
GL.MatrixMode GL::MODELVIEW
|
188
|
+
GLU.LookAt 10.0, 10.0, 17.5, 10.0, 10.0, 0.0, 0.0, 1.0, 0.0
|
189
|
+
end
|
190
|
+
|
191
|
+
keyboard = lambda do |key, x, y|
|
192
|
+
case key
|
193
|
+
when ?Q, ?\C-c
|
194
|
+
exit 0
|
195
|
+
when ?S
|
196
|
+
game.save
|
197
|
+
when ?L
|
198
|
+
if test ?e, File.join(PATH, "sokoban_saved_game.yaml")
|
199
|
+
game = Sokoban.load
|
200
|
+
end
|
201
|
+
when ?R
|
202
|
+
game.restart_level
|
203
|
+
when ?N
|
204
|
+
game.load_level
|
205
|
+
when ?U
|
206
|
+
game.undo
|
207
|
+
when ?j, ?j
|
208
|
+
game.move_left
|
209
|
+
when ?k, ?K
|
210
|
+
game.move_right
|
211
|
+
when ?m, ?m
|
212
|
+
game.move_down
|
213
|
+
when ?i, ?I
|
214
|
+
game.move_up
|
215
|
+
end
|
216
|
+
|
217
|
+
if game.level_solved?
|
218
|
+
game.load_level
|
219
|
+
|
220
|
+
exit 0 if game.over?
|
221
|
+
end
|
222
|
+
|
223
|
+
GLUT.PostRedisplay
|
224
|
+
end
|
225
|
+
|
226
|
+
GLUT.Init
|
227
|
+
GLUT.InitDisplayMode GLUT::SINGLE | GLUT::RGB | GLUT::DEPTH
|
228
|
+
GLUT.CreateWindow "Sokoban"
|
229
|
+
|
230
|
+
init
|
231
|
+
|
232
|
+
GLUT.KeyboardFunc keyboard
|
233
|
+
GLUT.ReshapeFunc reshape
|
234
|
+
GLUT.DisplayFunc display
|
235
|
+
|
236
|
+
GLUT.MainLoop
|
data/bin/run
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require File.dirname(__FILE__) + '/../lib/sokoban'
|
3
|
+
|
4
|
+
#RubyWarrior::UI.out_stream = STDOUT
|
5
|
+
#RubyWarrior::UI.in_stream = STDIN
|
6
|
+
#RubyWarrior::UI.delay = 0.8 # TODO allow customization
|
7
|
+
|
8
|
+
|
9
|
+
game = Sokoban::Game.new # TODO pass options into game when initializing
|
10
|
+
game.start
|
11
|
+
|