libtcod 0.0.7 → 0.0.8
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.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
|