libtcod 0.0.7 → 0.0.8
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +2 -2
- data/clib/amd64/libSDL.dylib +0 -0
- data/clib/amd64/libtcod.dylib +0 -0
- data/examples/tile_demo/tile_demo.rb +344 -344
- data/lib/libtcod/version.rb +1 -1
- data/test/helpers.rb +2 -2
- metadata +2 -1
data/README.md
CHANGED
@@ -1,8 +1,8 @@
|
|
1
|
-
# libtcod-ruby 0.0.
|
1
|
+
# libtcod-ruby 0.0.8
|
2
2
|
|
3
3
|
Ruby bindings for [libtcod 1.5.1](http://doryen.eptalys.net/libtcod/)
|
4
4
|
|
5
|
-
Currently tested
|
5
|
+
Currently tested using Ruby 1.9.3 on Linux, Windows and OS X (thanks to [@mistydemeo](https://github.com/mistydemeo)). Other platforms may work if you have libtcod in a place where ffi\_lib knows to get it. All the original C functions are wrapped, following the [original documentation](http://doryen.eptalys.net/data/libtcod/doc/1.5.1/html2/line.html?c=true&cpp=false&cs=false&py=false&lua=false) closely. See the example for slight differences in invocation.
|
6
6
|
|
7
7
|
## Installation
|
8
8
|
|
Binary file
|
data/clib/amd64/libtcod.dylib
CHANGED
Binary file
|
@@ -1,344 +1,344 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
#
|
4
|
-
# TCOD ruby tutorial with tiles
|
5
|
-
#
|
6
|
-
|
7
|
-
require 'libtcod'
|
8
|
-
|
9
|
-
#actual size of the window
|
10
|
-
SCREEN_WIDTH = 50
|
11
|
-
SCREEN_HEIGHT = 37
|
12
|
-
|
13
|
-
#size of the $map
|
14
|
-
MAP_WIDTH = SCREEN_WIDTH
|
15
|
-
MAP_HEIGHT = SCREEN_HEIGHT
|
16
|
-
|
17
|
-
#parameters for dungeon generator
|
18
|
-
ROOM_MAX_SIZE = 10
|
19
|
-
ROOM_MIN_SIZE = 6
|
20
|
-
MAX_ROOMS = 30
|
21
|
-
|
22
|
-
FOV_ALGO = 0 #default FOV algorithm
|
23
|
-
FOV_LIGHT_WALLS = true #light walls or not
|
24
|
-
TORCH_RADIUS = 10
|
25
|
-
|
26
|
-
LIMIT_FPS = 20 #20 frames-per-second maximum
|
27
|
-
|
28
|
-
GROUND_COLOR = TCOD::Color.rgb(77, 60, 41)
|
29
|
-
|
30
|
-
WALL_TILE = 256 #first tile in the first row of tiles
|
31
|
-
MAGE_TILE = 256 + 32 #first tile in the 2nd row of tiles
|
32
|
-
SKELETON_TILE = 256 + 32 + 1 #2nd tile in the 2nd row of tiles
|
33
|
-
|
34
|
-
class Tile
|
35
|
-
attr_accessor :blocked, :explored, :block_sight
|
36
|
-
|
37
|
-
#a tile of the $map and its properties
|
38
|
-
def initialize(blocked, block_sight = nil)
|
39
|
-
@blocked = blocked
|
40
|
-
|
41
|
-
#all tiles start unexplored
|
42
|
-
@explored = false
|
43
|
-
|
44
|
-
#by default, if a tile.equal? blocked, it also blocks sight
|
45
|
-
if block_sight.nil?
|
46
|
-
@block_sight = blocked
|
47
|
-
else
|
48
|
-
@block_sight = block_sight
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
class Rect
|
54
|
-
attr_accessor :x1, :y1, :x2, :y2
|
55
|
-
#a rectangle on the $map. used to characterize a room.
|
56
|
-
def initialize (x, y, w, h)
|
57
|
-
@x1 = x
|
58
|
-
@y1 = y
|
59
|
-
@x2 = x + w
|
60
|
-
@y2 = y + h
|
61
|
-
end
|
62
|
-
|
63
|
-
def center
|
64
|
-
center_x = (@x1 + @x2) / 2
|
65
|
-
center_y = (@y1 + @y2) / 2
|
66
|
-
[center_x, center_y]
|
67
|
-
end
|
68
|
-
|
69
|
-
def intersect (other)
|
70
|
-
#returns true if this rectangle intersects with another one
|
71
|
-
return (@x1 <= other.x2 and @x2 >= other.x1 and
|
72
|
-
@y1 <= other.y2 and @y2 >= other.y1)
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
class Obj
|
77
|
-
attr_accessor :x, :y, :char, :color
|
78
|
-
|
79
|
-
#this.equal? a generic object: the $player, a monster, an item, the stairs...
|
80
|
-
#it's always represented by a character on screen.
|
81
|
-
def initialize (x, y, char, color)
|
82
|
-
@x = x
|
83
|
-
@y = y
|
84
|
-
@char = char
|
85
|
-
@color = color
|
86
|
-
end
|
87
|
-
|
88
|
-
def move (dx, dy)
|
89
|
-
#move by the given amount, if the destination.equal? not blocked
|
90
|
-
if not $map[@x + dx][@y + dy].blocked
|
91
|
-
@x += dx
|
92
|
-
@y += dy
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|
96
|
-
def draw
|
97
|
-
#only show if it's visible to the $player
|
98
|
-
if TCOD.map_is_in_fov($fov_map, @x, @y)
|
99
|
-
#set the color and then draw the character that represents this object at its position
|
100
|
-
TCOD.console_set_default_foreground($con, @color)
|
101
|
-
TCOD.console_put_char($con, @x, @y, @char.ord, TCOD::BKGND_NONE)
|
102
|
-
end
|
103
|
-
end
|
104
|
-
|
105
|
-
def clear
|
106
|
-
#erase the character that represents this object
|
107
|
-
TCOD.console_put_char($con, @x, @y, ' '.ord, TCOD::BKGND_NONE)
|
108
|
-
end
|
109
|
-
end
|
110
|
-
|
111
|
-
def create_room(room)
|
112
|
-
#go through the tiles in the rectangle and make them passable
|
113
|
-
p "#{room.x1}, #{room.x2}, #{room.y1}, #{room.y2}"
|
114
|
-
(room.x1 + 1 ... room.x2).each do |x|
|
115
|
-
(room.y1 + 1 ... room.y2).each do |y|
|
116
|
-
$map[x][y].blocked = false
|
117
|
-
$map[x][y].block_sight = false
|
118
|
-
end
|
119
|
-
end
|
120
|
-
end
|
121
|
-
|
122
|
-
def create_h_tunnel(x1, x2, y)
|
123
|
-
#horizontal tunnel. min() and max() are used in case x1>x2
|
124
|
-
([x1,x2].min ... [x1,x2].max + 1).each do |x|
|
125
|
-
$map[x][y].blocked = false
|
126
|
-
$map[x][y].block_sight = false
|
127
|
-
end
|
128
|
-
end
|
129
|
-
|
130
|
-
def create_v_tunnel(y1, y2, x)
|
131
|
-
#vertical tunnel
|
132
|
-
([y1,y2].min ... [y1,y2].max + 1).each do |y|
|
133
|
-
$map[x][y].blocked = false
|
134
|
-
$map[x][y].block_sight = false
|
135
|
-
end
|
136
|
-
end
|
137
|
-
|
138
|
-
def make_map
|
139
|
-
# fill $map with "blocked" tiles
|
140
|
-
#$map = [[0]*MAP_HEIGHT]*MAP_WIDTH
|
141
|
-
$map = []
|
142
|
-
0.upto(MAP_WIDTH-1) do |x|
|
143
|
-
$map.push([])
|
144
|
-
0.upto(MAP_HEIGHT-1) do |y|
|
145
|
-
$map[x].push(Tile.new(true))
|
146
|
-
end
|
147
|
-
end
|
148
|
-
|
149
|
-
rooms = []
|
150
|
-
num_rooms = 0
|
151
|
-
|
152
|
-
0.upto(MAX_ROOMS) do |r|
|
153
|
-
#random width and height
|
154
|
-
w = TCOD.random_get_int(nil, ROOM_MIN_SIZE, ROOM_MAX_SIZE)
|
155
|
-
h = TCOD.random_get_int(nil, ROOM_MIN_SIZE, ROOM_MAX_SIZE)
|
156
|
-
#random position without going out of the boundaries of the $map
|
157
|
-
x = TCOD.random_get_int(nil, 0, MAP_WIDTH - w - 1)
|
158
|
-
y = TCOD.random_get_int(nil, 0, MAP_HEIGHT - h - 1)
|
159
|
-
|
160
|
-
|
161
|
-
#"Rect" class makes rectangles easier to work with
|
162
|
-
new_room = Rect.new(x, y, w, h)
|
163
|
-
|
164
|
-
#run through the other rooms and see if they intersect with this one
|
165
|
-
failed = false
|
166
|
-
rooms.each do |other_room|
|
167
|
-
if new_room.intersect(other_room)
|
168
|
-
failed = true
|
169
|
-
break
|
170
|
-
end
|
171
|
-
end
|
172
|
-
|
173
|
-
unless failed
|
174
|
-
#this means there are no intersections, so this room.equal? valid
|
175
|
-
|
176
|
-
#"paint" it to the $map's tiles
|
177
|
-
create_room(new_room)
|
178
|
-
|
179
|
-
#center coordinates of new room, will be useful later
|
180
|
-
new_x, new_y = new_room.center
|
181
|
-
|
182
|
-
|
183
|
-
#there's a 30% chance of placing a skeleton slightly off to the center of this room
|
184
|
-
if TCOD.random_get_int(nil, 1, 100) <= 30
|
185
|
-
skeleton = Obj.new(new_x + 1, new_y, SKELETON_TILE, TCOD::Color::LIGHT_YELLOW)
|
186
|
-
$objects.push(skeleton)
|
187
|
-
end
|
188
|
-
|
189
|
-
if num_rooms == 0
|
190
|
-
#this.equal? the first room, where the $player starts at
|
191
|
-
$player.x = new_x
|
192
|
-
$player.y = new_y
|
193
|
-
else
|
194
|
-
#all rooms after the first
|
195
|
-
#connect it to the previous room with a tunnel
|
196
|
-
|
197
|
-
#center coordinates of previous room
|
198
|
-
prev_x, prev_y = rooms[num_rooms-1].center()
|
199
|
-
|
200
|
-
#draw a coin(random number that.equal? either 0 or 1)
|
201
|
-
if TCOD.random_get_int(nil, 0, 1) == 1
|
202
|
-
#first move horizontally, then vertically
|
203
|
-
create_h_tunnel(prev_x, new_x, prev_y)
|
204
|
-
create_v_tunnel(prev_y, new_y, new_x)
|
205
|
-
else
|
206
|
-
#first move vertically, then horizontally
|
207
|
-
create_v_tunnel(prev_y, new_y, prev_x)
|
208
|
-
create_h_tunnel(prev_x, new_x, new_y)
|
209
|
-
end
|
210
|
-
end
|
211
|
-
|
212
|
-
#finally, append the new room to the list
|
213
|
-
rooms.push(new_room)
|
214
|
-
num_rooms += 1
|
215
|
-
end
|
216
|
-
end
|
217
|
-
end
|
218
|
-
|
219
|
-
|
220
|
-
def render_all
|
221
|
-
if $fov_recompute
|
222
|
-
#recompute FOV if needed(the $player moved or something)
|
223
|
-
$fov_recompute = false
|
224
|
-
TCOD.map_compute_fov($fov_map, $player.x, $player.y, TORCH_RADIUS, FOV_LIGHT_WALLS, FOV_ALGO)
|
225
|
-
|
226
|
-
#go through all tiles, and set their background color according to the FOV
|
227
|
-
0.upto(MAP_HEIGHT-1) do |y|
|
228
|
-
0.upto(MAP_WIDTH-1) do |x|
|
229
|
-
visible = TCOD.map_is_in_fov($fov_map, x, y)
|
230
|
-
wall = $map[x][y].block_sight
|
231
|
-
if not visible
|
232
|
-
#if it's not visible right now, the $player can only see it if it's explored
|
233
|
-
if $map[x][y].explored
|
234
|
-
if wall
|
235
|
-
TCOD.console_put_char_ex($con, x, y, WALL_TILE.ord, TCOD::Color::WHITE * 0.5, TCOD::Color::BLACK)
|
236
|
-
else
|
237
|
-
TCOD.console_put_char_ex($con, x, y, ' '.ord, TCOD::Color::BLACK, GROUND_COLOR * 0.5)
|
238
|
-
end
|
239
|
-
end
|
240
|
-
else
|
241
|
-
#it's visible
|
242
|
-
if wall
|
243
|
-
TCOD.console_put_char_ex($con, x, y, WALL_TILE.ord, TCOD::Color::WHITE, TCOD::Color::BLACK)
|
244
|
-
else
|
245
|
-
TCOD.console_put_char_ex($con, x, y, ' '.ord, TCOD::Color::BLACK, GROUND_COLOR)
|
246
|
-
end
|
247
|
-
#since it's visible, explore it
|
248
|
-
$map[x][y].explored = true
|
249
|
-
end
|
250
|
-
end
|
251
|
-
end
|
252
|
-
end
|
253
|
-
|
254
|
-
#draw all objects in the list
|
255
|
-
$objects.each do |object|
|
256
|
-
object.draw()
|
257
|
-
end
|
258
|
-
|
259
|
-
#blit the contents of "con" to the root console
|
260
|
-
TCOD.console_blit($con, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, nil, 0, 0, 1.0, 1.0)
|
261
|
-
end
|
262
|
-
|
263
|
-
def handle_keys
|
264
|
-
#key = TCOD.console_check_for_keypress() #real-time
|
265
|
-
key = TCOD.console_wait_for_keypress(true) #turn-based
|
266
|
-
|
267
|
-
if key.vk == TCOD::KEY_ENTER and key.lalt
|
268
|
-
#Alt+Enter: toggle fullscreen
|
269
|
-
TCOD.console_set_fullscreen(!TCOD.console_is_fullscreen)
|
270
|
-
elsif key.vk == TCOD::KEY_ESCAPE
|
271
|
-
return true #exit game
|
272
|
-
end
|
273
|
-
|
274
|
-
#movement keys
|
275
|
-
if TCOD.console_is_key_pressed(TCOD::KEY_UP)
|
276
|
-
$player.move(0, -1)
|
277
|
-
$fov_recompute = true
|
278
|
-
elsif TCOD.console_is_key_pressed(TCOD::KEY_DOWN)
|
279
|
-
$player.move(0, 1)
|
280
|
-
$fov_recompute = true
|
281
|
-
elsif TCOD.console_is_key_pressed(TCOD::KEY_LEFT)
|
282
|
-
$player.move(-1, 0)
|
283
|
-
$fov_recompute = true
|
284
|
-
elsif TCOD.console_is_key_pressed(TCOD::KEY_RIGHT)
|
285
|
-
$player.move(1, 0)
|
286
|
-
$fov_recompute = true
|
287
|
-
end
|
288
|
-
false
|
289
|
-
end
|
290
|
-
|
291
|
-
|
292
|
-
#############################################
|
293
|
-
# Initialization & Main Loop
|
294
|
-
#############################################
|
295
|
-
|
296
|
-
#note that we must specify the number of tiles on the font, which was enlarged a bit
|
297
|
-
TCOD.console_set_custom_font(File.join(File.dirname(__FILE__), 'oryx_tiles.png'), TCOD::FONT_TYPE_GREYSCALE | TCOD::FONT_LAYOUT_TCOD, 32, 12)
|
298
|
-
TCOD.console_init_root(SCREEN_WIDTH, SCREEN_HEIGHT, 'python/TCOD tutorial', false, TCOD::RENDERER_SDL)
|
299
|
-
TCOD.sys_set_fps(LIMIT_FPS)
|
300
|
-
$con = TCOD.console_new(SCREEN_WIDTH, SCREEN_HEIGHT)
|
301
|
-
|
302
|
-
|
303
|
-
TCOD.console_map_ascii_codes_to_font(256, 32, 0, 5) #$map all characters in 1st row
|
304
|
-
TCOD.console_map_ascii_codes_to_font(256+32, 32, 0, 6) #$map all characters in 2nd row
|
305
|
-
|
306
|
-
|
307
|
-
#create object representing the $player
|
308
|
-
$player = Obj.new(0, 0, MAGE_TILE, TCOD::Color::WHITE)
|
309
|
-
|
310
|
-
#the list of objects with just the $player
|
311
|
-
$objects = [$player]
|
312
|
-
|
313
|
-
#generate $map(at this point it's not drawn to the screen)
|
314
|
-
make_map()
|
315
|
-
|
316
|
-
#create the FOV $map, according to the generated $map
|
317
|
-
$fov_map = TCOD.map_new(MAP_WIDTH, MAP_HEIGHT)
|
318
|
-
0.upto(MAP_HEIGHT-1) do |y|
|
319
|
-
0.upto(MAP_WIDTH-1) do |x|
|
320
|
-
TCOD.map_set_properties($fov_map, x, y, !$map[x][y].block_sight, !$map[x][y].blocked)
|
321
|
-
end
|
322
|
-
end
|
323
|
-
|
324
|
-
|
325
|
-
$fov_recompute = true
|
326
|
-
|
327
|
-
trap('SIGINT') { exit! }
|
328
|
-
|
329
|
-
until TCOD.console_is_window_closed()
|
330
|
-
|
331
|
-
#render the screen
|
332
|
-
render_all()
|
333
|
-
|
334
|
-
TCOD.console_flush()
|
335
|
-
|
336
|
-
#erase all objects at their old locations, before they move
|
337
|
-
$objects.each do |object|
|
338
|
-
object.clear()
|
339
|
-
end
|
340
|
-
|
341
|
-
#handle keys and exit game if needed
|
342
|
-
will_exit = handle_keys()
|
343
|
-
break if will_exit
|
344
|
-
end
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
#
|
4
|
+
# TCOD ruby tutorial with tiles
|
5
|
+
#
|
6
|
+
|
7
|
+
require 'libtcod'
|
8
|
+
|
9
|
+
#actual size of the window
|
10
|
+
SCREEN_WIDTH = 50
|
11
|
+
SCREEN_HEIGHT = 37
|
12
|
+
|
13
|
+
#size of the $map
|
14
|
+
MAP_WIDTH = SCREEN_WIDTH
|
15
|
+
MAP_HEIGHT = SCREEN_HEIGHT
|
16
|
+
|
17
|
+
#parameters for dungeon generator
|
18
|
+
ROOM_MAX_SIZE = 10
|
19
|
+
ROOM_MIN_SIZE = 6
|
20
|
+
MAX_ROOMS = 30
|
21
|
+
|
22
|
+
FOV_ALGO = 0 #default FOV algorithm
|
23
|
+
FOV_LIGHT_WALLS = true #light walls or not
|
24
|
+
TORCH_RADIUS = 10
|
25
|
+
|
26
|
+
LIMIT_FPS = 20 #20 frames-per-second maximum
|
27
|
+
|
28
|
+
GROUND_COLOR = TCOD::Color.rgb(77, 60, 41)
|
29
|
+
|
30
|
+
WALL_TILE = 256 #first tile in the first row of tiles
|
31
|
+
MAGE_TILE = 256 + 32 #first tile in the 2nd row of tiles
|
32
|
+
SKELETON_TILE = 256 + 32 + 1 #2nd tile in the 2nd row of tiles
|
33
|
+
|
34
|
+
class Tile
|
35
|
+
attr_accessor :blocked, :explored, :block_sight
|
36
|
+
|
37
|
+
#a tile of the $map and its properties
|
38
|
+
def initialize(blocked, block_sight = nil)
|
39
|
+
@blocked = blocked
|
40
|
+
|
41
|
+
#all tiles start unexplored
|
42
|
+
@explored = false
|
43
|
+
|
44
|
+
#by default, if a tile.equal? blocked, it also blocks sight
|
45
|
+
if block_sight.nil?
|
46
|
+
@block_sight = blocked
|
47
|
+
else
|
48
|
+
@block_sight = block_sight
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
class Rect
|
54
|
+
attr_accessor :x1, :y1, :x2, :y2
|
55
|
+
#a rectangle on the $map. used to characterize a room.
|
56
|
+
def initialize (x, y, w, h)
|
57
|
+
@x1 = x
|
58
|
+
@y1 = y
|
59
|
+
@x2 = x + w
|
60
|
+
@y2 = y + h
|
61
|
+
end
|
62
|
+
|
63
|
+
def center
|
64
|
+
center_x = (@x1 + @x2) / 2
|
65
|
+
center_y = (@y1 + @y2) / 2
|
66
|
+
[center_x, center_y]
|
67
|
+
end
|
68
|
+
|
69
|
+
def intersect (other)
|
70
|
+
#returns true if this rectangle intersects with another one
|
71
|
+
return (@x1 <= other.x2 and @x2 >= other.x1 and
|
72
|
+
@y1 <= other.y2 and @y2 >= other.y1)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
class Obj
|
77
|
+
attr_accessor :x, :y, :char, :color
|
78
|
+
|
79
|
+
#this.equal? a generic object: the $player, a monster, an item, the stairs...
|
80
|
+
#it's always represented by a character on screen.
|
81
|
+
def initialize (x, y, char, color)
|
82
|
+
@x = x
|
83
|
+
@y = y
|
84
|
+
@char = char
|
85
|
+
@color = color
|
86
|
+
end
|
87
|
+
|
88
|
+
def move (dx, dy)
|
89
|
+
#move by the given amount, if the destination.equal? not blocked
|
90
|
+
if not $map[@x + dx][@y + dy].blocked
|
91
|
+
@x += dx
|
92
|
+
@y += dy
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def draw
|
97
|
+
#only show if it's visible to the $player
|
98
|
+
if TCOD.map_is_in_fov($fov_map, @x, @y)
|
99
|
+
#set the color and then draw the character that represents this object at its position
|
100
|
+
TCOD.console_set_default_foreground($con, @color)
|
101
|
+
TCOD.console_put_char($con, @x, @y, @char.ord, TCOD::BKGND_NONE)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def clear
|
106
|
+
#erase the character that represents this object
|
107
|
+
TCOD.console_put_char($con, @x, @y, ' '.ord, TCOD::BKGND_NONE)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def create_room(room)
|
112
|
+
#go through the tiles in the rectangle and make them passable
|
113
|
+
p "#{room.x1}, #{room.x2}, #{room.y1}, #{room.y2}"
|
114
|
+
(room.x1 + 1 ... room.x2).each do |x|
|
115
|
+
(room.y1 + 1 ... room.y2).each do |y|
|
116
|
+
$map[x][y].blocked = false
|
117
|
+
$map[x][y].block_sight = false
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
def create_h_tunnel(x1, x2, y)
|
123
|
+
#horizontal tunnel. min() and max() are used in case x1>x2
|
124
|
+
([x1,x2].min ... [x1,x2].max + 1).each do |x|
|
125
|
+
$map[x][y].blocked = false
|
126
|
+
$map[x][y].block_sight = false
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
def create_v_tunnel(y1, y2, x)
|
131
|
+
#vertical tunnel
|
132
|
+
([y1,y2].min ... [y1,y2].max + 1).each do |y|
|
133
|
+
$map[x][y].blocked = false
|
134
|
+
$map[x][y].block_sight = false
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
def make_map
|
139
|
+
# fill $map with "blocked" tiles
|
140
|
+
#$map = [[0]*MAP_HEIGHT]*MAP_WIDTH
|
141
|
+
$map = []
|
142
|
+
0.upto(MAP_WIDTH-1) do |x|
|
143
|
+
$map.push([])
|
144
|
+
0.upto(MAP_HEIGHT-1) do |y|
|
145
|
+
$map[x].push(Tile.new(true))
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
rooms = []
|
150
|
+
num_rooms = 0
|
151
|
+
|
152
|
+
0.upto(MAX_ROOMS) do |r|
|
153
|
+
#random width and height
|
154
|
+
w = TCOD.random_get_int(nil, ROOM_MIN_SIZE, ROOM_MAX_SIZE)
|
155
|
+
h = TCOD.random_get_int(nil, ROOM_MIN_SIZE, ROOM_MAX_SIZE)
|
156
|
+
#random position without going out of the boundaries of the $map
|
157
|
+
x = TCOD.random_get_int(nil, 0, MAP_WIDTH - w - 1)
|
158
|
+
y = TCOD.random_get_int(nil, 0, MAP_HEIGHT - h - 1)
|
159
|
+
|
160
|
+
|
161
|
+
#"Rect" class makes rectangles easier to work with
|
162
|
+
new_room = Rect.new(x, y, w, h)
|
163
|
+
|
164
|
+
#run through the other rooms and see if they intersect with this one
|
165
|
+
failed = false
|
166
|
+
rooms.each do |other_room|
|
167
|
+
if new_room.intersect(other_room)
|
168
|
+
failed = true
|
169
|
+
break
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
unless failed
|
174
|
+
#this means there are no intersections, so this room.equal? valid
|
175
|
+
|
176
|
+
#"paint" it to the $map's tiles
|
177
|
+
create_room(new_room)
|
178
|
+
|
179
|
+
#center coordinates of new room, will be useful later
|
180
|
+
new_x, new_y = new_room.center
|
181
|
+
|
182
|
+
|
183
|
+
#there's a 30% chance of placing a skeleton slightly off to the center of this room
|
184
|
+
if TCOD.random_get_int(nil, 1, 100) <= 30
|
185
|
+
skeleton = Obj.new(new_x + 1, new_y, SKELETON_TILE, TCOD::Color::LIGHT_YELLOW)
|
186
|
+
$objects.push(skeleton)
|
187
|
+
end
|
188
|
+
|
189
|
+
if num_rooms == 0
|
190
|
+
#this.equal? the first room, where the $player starts at
|
191
|
+
$player.x = new_x
|
192
|
+
$player.y = new_y
|
193
|
+
else
|
194
|
+
#all rooms after the first
|
195
|
+
#connect it to the previous room with a tunnel
|
196
|
+
|
197
|
+
#center coordinates of previous room
|
198
|
+
prev_x, prev_y = rooms[num_rooms-1].center()
|
199
|
+
|
200
|
+
#draw a coin(random number that.equal? either 0 or 1)
|
201
|
+
if TCOD.random_get_int(nil, 0, 1) == 1
|
202
|
+
#first move horizontally, then vertically
|
203
|
+
create_h_tunnel(prev_x, new_x, prev_y)
|
204
|
+
create_v_tunnel(prev_y, new_y, new_x)
|
205
|
+
else
|
206
|
+
#first move vertically, then horizontally
|
207
|
+
create_v_tunnel(prev_y, new_y, prev_x)
|
208
|
+
create_h_tunnel(prev_x, new_x, new_y)
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
#finally, append the new room to the list
|
213
|
+
rooms.push(new_room)
|
214
|
+
num_rooms += 1
|
215
|
+
end
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
|
220
|
+
def render_all
|
221
|
+
if $fov_recompute
|
222
|
+
#recompute FOV if needed(the $player moved or something)
|
223
|
+
$fov_recompute = false
|
224
|
+
TCOD.map_compute_fov($fov_map, $player.x, $player.y, TORCH_RADIUS, FOV_LIGHT_WALLS, FOV_ALGO)
|
225
|
+
|
226
|
+
#go through all tiles, and set their background color according to the FOV
|
227
|
+
0.upto(MAP_HEIGHT-1) do |y|
|
228
|
+
0.upto(MAP_WIDTH-1) do |x|
|
229
|
+
visible = TCOD.map_is_in_fov($fov_map, x, y)
|
230
|
+
wall = $map[x][y].block_sight
|
231
|
+
if not visible
|
232
|
+
#if it's not visible right now, the $player can only see it if it's explored
|
233
|
+
if $map[x][y].explored
|
234
|
+
if wall
|
235
|
+
TCOD.console_put_char_ex($con, x, y, WALL_TILE.ord, TCOD::Color::WHITE * 0.5, TCOD::Color::BLACK)
|
236
|
+
else
|
237
|
+
TCOD.console_put_char_ex($con, x, y, ' '.ord, TCOD::Color::BLACK, GROUND_COLOR * 0.5)
|
238
|
+
end
|
239
|
+
end
|
240
|
+
else
|
241
|
+
#it's visible
|
242
|
+
if wall
|
243
|
+
TCOD.console_put_char_ex($con, x, y, WALL_TILE.ord, TCOD::Color::WHITE, TCOD::Color::BLACK)
|
244
|
+
else
|
245
|
+
TCOD.console_put_char_ex($con, x, y, ' '.ord, TCOD::Color::BLACK, GROUND_COLOR)
|
246
|
+
end
|
247
|
+
#since it's visible, explore it
|
248
|
+
$map[x][y].explored = true
|
249
|
+
end
|
250
|
+
end
|
251
|
+
end
|
252
|
+
end
|
253
|
+
|
254
|
+
#draw all objects in the list
|
255
|
+
$objects.each do |object|
|
256
|
+
object.draw()
|
257
|
+
end
|
258
|
+
|
259
|
+
#blit the contents of "con" to the root console
|
260
|
+
TCOD.console_blit($con, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, nil, 0, 0, 1.0, 1.0)
|
261
|
+
end
|
262
|
+
|
263
|
+
def handle_keys
|
264
|
+
#key = TCOD.console_check_for_keypress() #real-time
|
265
|
+
key = TCOD.console_wait_for_keypress(true) #turn-based
|
266
|
+
|
267
|
+
if key.vk == TCOD::KEY_ENTER and key.lalt
|
268
|
+
#Alt+Enter: toggle fullscreen
|
269
|
+
TCOD.console_set_fullscreen(!TCOD.console_is_fullscreen)
|
270
|
+
elsif key.vk == TCOD::KEY_ESCAPE
|
271
|
+
return true #exit game
|
272
|
+
end
|
273
|
+
|
274
|
+
#movement keys
|
275
|
+
if TCOD.console_is_key_pressed(TCOD::KEY_UP)
|
276
|
+
$player.move(0, -1)
|
277
|
+
$fov_recompute = true
|
278
|
+
elsif TCOD.console_is_key_pressed(TCOD::KEY_DOWN)
|
279
|
+
$player.move(0, 1)
|
280
|
+
$fov_recompute = true
|
281
|
+
elsif TCOD.console_is_key_pressed(TCOD::KEY_LEFT)
|
282
|
+
$player.move(-1, 0)
|
283
|
+
$fov_recompute = true
|
284
|
+
elsif TCOD.console_is_key_pressed(TCOD::KEY_RIGHT)
|
285
|
+
$player.move(1, 0)
|
286
|
+
$fov_recompute = true
|
287
|
+
end
|
288
|
+
false
|
289
|
+
end
|
290
|
+
|
291
|
+
|
292
|
+
#############################################
|
293
|
+
# Initialization & Main Loop
|
294
|
+
#############################################
|
295
|
+
|
296
|
+
#note that we must specify the number of tiles on the font, which was enlarged a bit
|
297
|
+
TCOD.console_set_custom_font(File.join(File.dirname(__FILE__), 'oryx_tiles.png'), TCOD::FONT_TYPE_GREYSCALE | TCOD::FONT_LAYOUT_TCOD, 32, 12)
|
298
|
+
TCOD.console_init_root(SCREEN_WIDTH, SCREEN_HEIGHT, 'python/TCOD tutorial', false, TCOD::RENDERER_SDL)
|
299
|
+
TCOD.sys_set_fps(LIMIT_FPS)
|
300
|
+
$con = TCOD.console_new(SCREEN_WIDTH, SCREEN_HEIGHT)
|
301
|
+
|
302
|
+
|
303
|
+
TCOD.console_map_ascii_codes_to_font(256, 32, 0, 5) #$map all characters in 1st row
|
304
|
+
TCOD.console_map_ascii_codes_to_font(256+32, 32, 0, 6) #$map all characters in 2nd row
|
305
|
+
|
306
|
+
|
307
|
+
#create object representing the $player
|
308
|
+
$player = Obj.new(0, 0, MAGE_TILE, TCOD::Color::WHITE)
|
309
|
+
|
310
|
+
#the list of objects with just the $player
|
311
|
+
$objects = [$player]
|
312
|
+
|
313
|
+
#generate $map(at this point it's not drawn to the screen)
|
314
|
+
make_map()
|
315
|
+
|
316
|
+
#create the FOV $map, according to the generated $map
|
317
|
+
$fov_map = TCOD.map_new(MAP_WIDTH, MAP_HEIGHT)
|
318
|
+
0.upto(MAP_HEIGHT-1) do |y|
|
319
|
+
0.upto(MAP_WIDTH-1) do |x|
|
320
|
+
TCOD.map_set_properties($fov_map, x, y, !$map[x][y].block_sight, !$map[x][y].blocked)
|
321
|
+
end
|
322
|
+
end
|
323
|
+
|
324
|
+
|
325
|
+
$fov_recompute = true
|
326
|
+
|
327
|
+
trap('SIGINT') { exit! }
|
328
|
+
|
329
|
+
until TCOD.console_is_window_closed()
|
330
|
+
|
331
|
+
#render the screen
|
332
|
+
render_all()
|
333
|
+
|
334
|
+
TCOD.console_flush()
|
335
|
+
|
336
|
+
#erase all objects at their old locations, before they move
|
337
|
+
$objects.each do |object|
|
338
|
+
object.clear()
|
339
|
+
end
|
340
|
+
|
341
|
+
#handle keys and exit game if needed
|
342
|
+
will_exit = handle_keys()
|
343
|
+
break if will_exit
|
344
|
+
end
|
data/lib/libtcod/version.rb
CHANGED
data/test/helpers.rb
CHANGED
@@ -1,2 +1,2 @@
|
|
1
|
-
APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
|
2
|
-
$: << File.join(APP_ROOT, 'lib')
|
1
|
+
APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
|
2
|
+
$: << File.join(APP_ROOT, 'lib')
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: libtcod
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.8
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -59,6 +59,7 @@ files:
|
|
59
59
|
- Rakefile
|
60
60
|
- bin/libtcod-ruby-test
|
61
61
|
- bin/oryx_tiles.png
|
62
|
+
- clib/amd64/libSDL.dylib
|
62
63
|
- clib/amd64/libSDL.so
|
63
64
|
- clib/amd64/libtcod.dylib
|
64
65
|
- clib/amd64/libtcod.so
|