random BSP partitioned map
This commit is contained in:
parent
1f6aec2a1a
commit
1697018d7b
3 changed files with 166 additions and 0 deletions
163
01_dynamic_bsp_map.py
Normal file
163
01_dynamic_bsp_map.py
Normal file
|
@ -0,0 +1,163 @@
|
||||||
|
import pyglet
|
||||||
|
from pyglet.window import key
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import re
|
||||||
|
|
||||||
|
import random
|
||||||
|
|
||||||
|
# constants
|
||||||
|
TILE_SIZE_X = 16
|
||||||
|
TILE_SIZE_Y = 16
|
||||||
|
|
||||||
|
MIN_LEAF_SIZE = 4
|
||||||
|
|
||||||
|
class Leaf:
|
||||||
|
""" Leaf of the BSP """
|
||||||
|
|
||||||
|
def __init__(self, x, y, w, h, id):
|
||||||
|
self.id = id
|
||||||
|
self.x = x
|
||||||
|
self.y = y
|
||||||
|
self.width = w
|
||||||
|
self.height = h
|
||||||
|
self.left_leaf = None
|
||||||
|
self.right_leaf = None
|
||||||
|
|
||||||
|
def print_leaf(self):
|
||||||
|
print(str(self.id) + ': (' + str(self.x) + '), (' + str(self.y) + ')' +
|
||||||
|
' - ' + str(self.width) + 'x' + str(self.height) )
|
||||||
|
|
||||||
|
def split(self):
|
||||||
|
"""
|
||||||
|
:return: True if the leaf has been split
|
||||||
|
"""
|
||||||
|
|
||||||
|
self.print_leaf()
|
||||||
|
# choose direction
|
||||||
|
# TODO: if leaf is not so square, split along the long side
|
||||||
|
# if width > XX% height (25, 33 ?) -> split vertical
|
||||||
|
if random.random() < 0.5:
|
||||||
|
# x
|
||||||
|
if self.width < MIN_LEAF_SIZE * 2: # leaf is too small
|
||||||
|
return False
|
||||||
|
split_point = random.randint(MIN_LEAF_SIZE, self.width - MIN_LEAF_SIZE)
|
||||||
|
self.left_leaf = Leaf(self.x, self.y, split_point, self.height, self.id+1)
|
||||||
|
self.right_leaf = Leaf(self.x + split_point-1, self.y, self.width - split_point+1, self.height, self.id+2)
|
||||||
|
|
||||||
|
else:
|
||||||
|
# y
|
||||||
|
if self.height < MIN_LEAF_SIZE * 2: # leaf is too small
|
||||||
|
return False
|
||||||
|
split_point = random.randint(MIN_LEAF_SIZE, self.height - MIN_LEAF_SIZE)
|
||||||
|
self.left_leaf = Leaf(self.x, self.y, self.width, split_point, self.id+1)
|
||||||
|
self.right_leaf = Leaf(self.x, self.y + split_point-1, self.width, self.height - split_point+1, self.id+2)
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
def draw(self, wall, ground):
|
||||||
|
# first wall
|
||||||
|
for x in range(0, self.width):
|
||||||
|
wall.blit((self.x+x)*TILE_SIZE_X, self.y*TILE_SIZE_Y)
|
||||||
|
# middle
|
||||||
|
for y in range(1, self.height-1):
|
||||||
|
wall.blit(self.x*TILE_SIZE_X, (self.y+y)*TILE_SIZE_Y)
|
||||||
|
for x in range(1, self.width - 1):
|
||||||
|
ground.blit((self.x + x)*TILE_SIZE_X, (self.y+y)*TILE_SIZE_Y)
|
||||||
|
wall.blit((self.x+self.width-1)*TILE_SIZE_X, (self.y+y)*TILE_SIZE_Y)
|
||||||
|
# end
|
||||||
|
for x in range(0, self.width):
|
||||||
|
wall.blit((self.x+x)*TILE_SIZE_X, (self.y + self.height-1)*TILE_SIZE_Y)
|
||||||
|
|
||||||
|
def generate_tree():
|
||||||
|
# init tree
|
||||||
|
tree = [Leaf(0, 0, 24, 24, 0)]
|
||||||
|
#tree = [Leaf(0, 0, 10, 10, 0)]
|
||||||
|
#tree = [Leaf(0, 0, 5, 5, 0)]
|
||||||
|
|
||||||
|
# split leaves until none succeed
|
||||||
|
split_done = True
|
||||||
|
while split_done:
|
||||||
|
split_done = False
|
||||||
|
for l in tree:
|
||||||
|
if l.left_leaf == None and l.right_leaf == None:
|
||||||
|
if (l.split()):
|
||||||
|
tree.append(l.left_leaf)
|
||||||
|
tree.append(l.right_leaf)
|
||||||
|
split_done = True
|
||||||
|
|
||||||
|
return tree
|
||||||
|
|
||||||
|
|
||||||
|
##
|
||||||
|
# main
|
||||||
|
##
|
||||||
|
|
||||||
|
# main window
|
||||||
|
window = pyglet.window.Window()
|
||||||
|
|
||||||
|
@window.event
|
||||||
|
def on_key_press(symbol, modifiers):
|
||||||
|
#TODO: ugly hack
|
||||||
|
global level_tree
|
||||||
|
|
||||||
|
if symbol == key.Q:
|
||||||
|
print('Will quit')
|
||||||
|
if symbol == key.R:
|
||||||
|
print('Regeneration')
|
||||||
|
level_tree = generate_tree()
|
||||||
|
window.invalid = True
|
||||||
|
elif symbol == key.LEFT:
|
||||||
|
print('Left arrow')
|
||||||
|
elif symbol == key.ENTER:
|
||||||
|
print('Enter !')
|
||||||
|
|
||||||
|
@window.event
|
||||||
|
def on_draw():
|
||||||
|
window.clear()
|
||||||
|
draw_tree(level_tree)
|
||||||
|
|
||||||
|
label.draw()
|
||||||
|
|
||||||
|
def draw_tree(t):
|
||||||
|
"""
|
||||||
|
:param t: each leave of t will be draw()
|
||||||
|
"""
|
||||||
|
for l in t:
|
||||||
|
# draw only last leaves
|
||||||
|
if l.left_leaf == None and l.right_leaf == None:
|
||||||
|
l.draw(tiles[TILE_WALL], tiles[TILE_GROUND])
|
||||||
|
|
||||||
|
|
||||||
|
# init random
|
||||||
|
#TODO add seed mode (how ?)
|
||||||
|
random.seed()
|
||||||
|
|
||||||
|
label = pyglet.text.Label('Plop World', x = window.width*3/4, y = window.height*3/4, anchor_x='center', anchor_y='center')
|
||||||
|
|
||||||
|
# load images
|
||||||
|
tiles = []
|
||||||
|
resource_file = open('tiles.txt')
|
||||||
|
line = resource_file.readline().strip()
|
||||||
|
while line:
|
||||||
|
tile_file = re.compile('\d: ').split(line)[1]
|
||||||
|
print('loading tile: ' + str(tile_file))
|
||||||
|
tiles.append(pyglet.resource.image(tile_file))
|
||||||
|
line = resource_file.readline().strip()
|
||||||
|
|
||||||
|
TILE_WALL = 0
|
||||||
|
TILE_GROUND = 2
|
||||||
|
|
||||||
|
level_tree = generate_tree()
|
||||||
|
|
||||||
|
# artificial tree to test drawing
|
||||||
|
# troot = Leaf(0, 0, 24, 24, 0)
|
||||||
|
# tll = Leaf(0, 0, 16, 24, 1)
|
||||||
|
# trl = Leaf(16, 0, 8, 24, 2)
|
||||||
|
# troot.left_leaf = tll
|
||||||
|
# troot.right_leaf = trl
|
||||||
|
# tllvl = Leaf(0, 0, 16, 4, 3)
|
||||||
|
# tllvr = Leaf(0, 4, 16, 20, 4)
|
||||||
|
# level_tree = [troot, tll, trl, tllvl, tllvr]
|
||||||
|
|
||||||
|
pyglet.app.run()
|
BIN
ground.png
Normal file
BIN
ground.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 358 B |
3
tiles.txt
Normal file
3
tiles.txt
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
0: brick.png
|
||||||
|
1: road.png
|
||||||
|
2: ground.png
|
Loading…
Reference in a new issue