From 1697018d7b8754ce0858046c1eea2b918560345b Mon Sep 17 00:00:00 2001 From: kleph Date: Tue, 1 Mar 2016 13:01:00 +0100 Subject: [PATCH] random BSP partitioned map --- 01_dynamic_bsp_map.py | 163 ++++++++++++++++++++++++++++++++++++++++++ ground.png | Bin 0 -> 358 bytes tiles.txt | 3 + 3 files changed, 166 insertions(+) create mode 100644 01_dynamic_bsp_map.py create mode 100644 ground.png create mode 100644 tiles.txt diff --git a/01_dynamic_bsp_map.py b/01_dynamic_bsp_map.py new file mode 100644 index 0000000..51a94c2 --- /dev/null +++ b/01_dynamic_bsp_map.py @@ -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() diff --git a/ground.png b/ground.png new file mode 100644 index 0000000000000000000000000000000000000000..094c282220766209c83249661d48aa16f8b11b0c GIT binary patch literal 358 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!6#K6G#d|Jc;AcwQSBeIx*fm;}a85w5HkpK#^ zmw5WRvOi#w6*c1d!y$4IC?r|p8d2h$pPQSSSHj?2l$uzQnxasiS(2gP?&%v4-pD5o zRP?~p#W6(Vd~J|5*I@&m+QLnxFVZwvo4N09N_jO!^ZQ#yo}G@0)z&OLt&hBSG{;1i zdE8Gr`D?HG?q0s+el;tG{muuu`WGk!xYY>sU7Rh|WqwihbjFW{DH#_piZ=FC9t`PS zVt4sKZSKCOVXW(AR%mg2W|F_)(q8FVTdul^WAVZr)6y?UuqH@N`dsyX&AX~|W!B#! z?03vzcu?WNEAMX@)AfPzS=-NfH;q>InVvM2;$5@VEGg{t?WTCs)whqWvbpCP_`rE1 z-%n?iDQ6}usb$Ey7G^&&=3>2J*GUh?sdAn_xY<^u2AoYVE&=+L!PC{xWt~$(69CW@ BhoAre literal 0 HcmV?d00001 diff --git a/tiles.txt b/tiles.txt new file mode 100644 index 0000000..90d6aa3 --- /dev/null +++ b/tiles.txt @@ -0,0 +1,3 @@ +0: brick.png +1: road.png +2: ground.png