Implement multiple dungeon levels
parent
0be0efeb7f
commit
6c0124ac6c
Binary file not shown.
After Width: | Height: | Size: 1.7 KiB |
Binary file not shown.
After Width: | Height: | Size: 2.2 KiB |
15
src/game.py
15
src/game.py
|
@ -27,7 +27,7 @@ for filename in os.listdir(os.path.join(os.path.dirname(os.path.realpath(sys.arg
|
|||
# Map
|
||||
map = Map(METER)
|
||||
# map.load("map.json")
|
||||
map.generate()
|
||||
map.generate(0)
|
||||
|
||||
# Player
|
||||
player = Player()
|
||||
|
@ -35,8 +35,7 @@ player.sprite.texture = spritesheet.SpriteSheet(assets.get("character.png"), 32,
|
|||
player.sprite.set_rect((8, 32, 16, 16))
|
||||
# TODO: Use asset loader for spritesheets
|
||||
player.sprite.texture.set_animation(0, 0, 0)
|
||||
player.set_pos(1.1, 1.1)
|
||||
player.set_pos(map.generator.rooms[0].x + 2, map.generator.rooms[0].y + 2)
|
||||
player.set_pos(map.generators[0].rooms[0].x + 2, map.generators[0].rooms[0].y + 2)
|
||||
|
||||
CENTER = [winsize[0] / 2, winsize[1] / 2]
|
||||
BGCOLOR = pygame.Color("#3e1202")
|
||||
|
@ -67,7 +66,8 @@ while 1:
|
|||
|
||||
player_rendered = False
|
||||
|
||||
for z in range(len(map.map)):
|
||||
for z in range(player.z - 1, player.z + 1):
|
||||
if z < len(map.map):
|
||||
for y in range(len(map.map[z])):
|
||||
for x in range(len(map.map[z][y])):
|
||||
tile = map.get_tile(x, y, z)
|
||||
|
@ -94,11 +94,7 @@ while 1:
|
|||
tile.on_step(dtime, map, player)
|
||||
screen.blit(pygame.transform.scale(texture, [round(scaledsize[0]) + 1, round(scaledsize[1]) + 1]), pos)
|
||||
|
||||
# DEBUG
|
||||
# text = arial.render(str(int(x)) + ", " + str(int(y)), False, (255, 255, 255))
|
||||
# screen.blit(text, [x * 64 - (player.pos.x * round(SCALE * METER)) + camera[0], y * 64 - (player.pos.y * round(SCALE * METER)) + camera[1]])
|
||||
|
||||
if not player_rendered and z == 1 and y == math.ceil(player.pos.y + 1 + player.sprite.get_rect()[3] / METER):
|
||||
if not player_rendered and z == player.z and y == math.ceil(player.pos.y + 1 + player.sprite.get_rect()[3] / METER):
|
||||
# Draw player
|
||||
screen.blit(pygame.transform.scale(player.sprite.texture.frame, [round(SCALE * player.sprite.texture.width), round(SCALE * player.sprite.texture.height)]), camera)
|
||||
player_rendered = True
|
||||
|
@ -106,4 +102,3 @@ while 1:
|
|||
player.hud.render(screen, SCALE)
|
||||
|
||||
pygame.display.update()
|
||||
# pygame.display.flip()
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
from .rand import rand
|
||||
import math
|
||||
|
||||
def populate(map, generator, z):
|
||||
# Place stairways
|
||||
if z != 0:
|
||||
mroom = generator.rooms[int(math.ceil(len(generator.rooms) / 2))] # Middle room
|
||||
enterx = mroom.x + rand(2, mroom.width - 2)
|
||||
entery = mroom.y + rand(2, mroom.height - 3)
|
||||
map.set_tile(enterx, entery, z + 1, "map:stair_up")
|
||||
generator.enterance = (enterx, entery)
|
||||
|
||||
lroom = generator.rooms[0]#len(generator.rooms) - 1] # Last room
|
||||
exitx = lroom.x + rand(2, lroom.width - 2)
|
||||
exity = lroom.y + rand(2, lroom.height - 3)
|
||||
map.set_tile(exitx, exity, z + 1, "map:stair_down")
|
||||
generator.exit = (exitx, exity)
|
||||
|
||||
# Place loot
|
||||
loot = [
|
||||
["loot:coins", 10],
|
||||
["loot:pile", 50],
|
||||
]
|
||||
|
||||
for room in generator.rooms:
|
||||
if rand(0, 2) != 0: # 1 in 3 chance of no loot
|
||||
for y in range(1, room.height - 2):
|
||||
for x in range(1, room.width - 1):
|
||||
if map.get_tile(x, y, z) == None:
|
||||
placed = False
|
||||
for l in loot:
|
||||
if not placed and rand(1, l[1]) == 1: # 1 in n chance of placing
|
||||
map.set_tile(room.x + x, room.y + y, z + 1, l[0])
|
||||
placed = True
|
||||
|
||||
|
18
src/loot.py
18
src/loot.py
|
@ -1,18 +0,0 @@
|
|||
from .rand import rand
|
||||
|
||||
def place_loot(map, z):
|
||||
loot = [
|
||||
["loot:coins", 10],
|
||||
["loot:pile", 50],
|
||||
]
|
||||
|
||||
for room in map.generator.rooms:
|
||||
if rand(0, 2) != 0: # 1 in 3 chance of no loot
|
||||
for y in range(1, room.height - 2):
|
||||
for x in range(1, room.width - 1):
|
||||
placed = False
|
||||
for l in loot:
|
||||
if not placed and rand(1, l[1]) == 1: # 1 in n chance of placing
|
||||
map.set_tile(room.x + x, room.y + y, 1, l[0])
|
||||
placed = True
|
||||
|
20
src/map.py
20
src/map.py
|
@ -1,11 +1,12 @@
|
|||
import pygame
|
||||
import json, math
|
||||
from . import assets, dungeon, loot, tiles
|
||||
from . import assets, dungeon, level, tiles
|
||||
from .tiles import Tile
|
||||
from .vector import Vector
|
||||
|
||||
class Map:
|
||||
map = []
|
||||
generators = {}
|
||||
|
||||
def __init__(self, meter):
|
||||
self.METER = meter # Pixels per 1 meter
|
||||
|
@ -14,12 +15,14 @@ class Map:
|
|||
# with open(filename) as file:
|
||||
# self.map = json.load(file)
|
||||
|
||||
def generate(self):
|
||||
self.generator = dungeon.Generator(80)
|
||||
self.generator.generate(self, 0)
|
||||
loot.place_loot(self, 0)
|
||||
def generate(self, z):
|
||||
generator = dungeon.Generator(80)
|
||||
generator.generate(self, z)
|
||||
self.generators[z] = generator
|
||||
|
||||
def collides(self, pos, rect):
|
||||
level.populate(self, generator, z)
|
||||
|
||||
def collides(self, pos, z, rect):
|
||||
# Player position handling really needs to be reworked ...
|
||||
METER = self.METER
|
||||
cx = pos.x + (rect[0] / METER)
|
||||
|
@ -30,11 +33,12 @@ class Map:
|
|||
ch = cy + (rect[3] / METER)
|
||||
for y in range(py - 1, py + 1 + math.ceil(rect[3] / METER)):
|
||||
for x in range(px - 1, px + 2):
|
||||
if y >= 0 and y < len(self.map[1]) and x >= 0 and x < len(self.map[1][y]):
|
||||
tile = self.map[1][y][x]
|
||||
if y >= 0 and y < len(self.map[z]) and x >= 0 and x < len(self.map[z][y]):
|
||||
tile = self.map[z][y][x]
|
||||
if tile and tile.is_solid():
|
||||
if cw >= x and cx <= (x + 1) and ch >= y and cy <= (y + 1):
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def set_tile(self, x, y, z, name):
|
||||
|
|
|
@ -7,6 +7,8 @@ from .sprite import Sprite
|
|||
|
||||
class Player:
|
||||
pos = Vector(0, 0)
|
||||
z = 1
|
||||
last_level_change = 0
|
||||
|
||||
hp = 100
|
||||
coins = 0
|
||||
|
@ -59,13 +61,13 @@ class Player:
|
|||
oldx = self.pos.x
|
||||
self.set_pos(self.pos.x + self.vel.x * self.speed * dtime, self.pos.y)
|
||||
|
||||
if map.collides(self.pos, self.sprite.rect):
|
||||
if map.collides(self.pos, self.z, self.sprite.rect):
|
||||
self.set_pos(oldx, self.pos.y)
|
||||
|
||||
oldy = self.pos.y
|
||||
self.set_pos(self.pos.x, self.pos.y + self.vel.y * self.speed * dtime)
|
||||
|
||||
if map.collides(self.pos, self.sprite.rect):
|
||||
if map.collides(self.pos, self.z, self.sprite.rect):
|
||||
self.set_pos(self.pos.x, oldy)
|
||||
|
||||
if controller.is_down("up") or controller.is_down("down") or \
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
import math
|
||||
import random
|
||||
from . import tiles
|
||||
import time
|
||||
from . import controller, tiles
|
||||
from .vector import Vector
|
||||
|
||||
# Structure tiles
|
||||
tiles.register_tile("map:floor", {
|
||||
"textures": ["floor.png"],
|
||||
})
|
||||
|
@ -33,7 +36,45 @@ tiles.register_tile("map:wall_corner_outer", {
|
|||
],
|
||||
})
|
||||
|
||||
def pick_up(self, dtime, map, player):
|
||||
# Stairs
|
||||
def prev_level(self, _, map, player):
|
||||
# Lazy distance check
|
||||
if math.hypot(player.pos.x - self.pos[0], player.pos.y + 1 - self.pos[1]) <= 2 \
|
||||
and player.pos.y + 0.5 > self.pos[1] and controller.is_down("shift") \
|
||||
and time.time() - player.last_level_change > 0.5: # Prevent multiple shifts
|
||||
player.z = max(1, player.z - 2)
|
||||
generator = map.generators[player.z - 1]
|
||||
|
||||
player.set_pos(generator.exit[0], generator.exit[1] - 1)
|
||||
player.dir = 2
|
||||
player.last_level_change = time.time()
|
||||
|
||||
tiles.register_tile("map:stair_up", {
|
||||
"textures": ["stair_up.png"],
|
||||
"solid": True,
|
||||
"on_step": prev_level,
|
||||
})
|
||||
|
||||
def next_level(self, _, map, player):
|
||||
if math.hypot(player.pos.x - self.pos[0], player.pos.y + 1 - self.pos[1]) <= 1 \
|
||||
and controller.is_down("shift") and time.time() - player.last_level_change > 0.5:
|
||||
player.z += 2
|
||||
if not player.z - 1 in map.generators:
|
||||
map.generate(player.z - 1)
|
||||
generator = map.generators[player.z - 1]
|
||||
|
||||
player.set_pos(generator.enterance[0], generator.enterance[1] + 0.1)
|
||||
player.dir = 0
|
||||
player.last_level_change = time.time()
|
||||
|
||||
tiles.register_tile("map:stair_down", {
|
||||
"textures": ["stair_down.png"],
|
||||
"solid": False,
|
||||
"on_step": next_level,
|
||||
})
|
||||
|
||||
# Loot
|
||||
def pick_up(self, _, map, player):
|
||||
METER = map.METER
|
||||
rect = player.sprite.get_rect()
|
||||
cx = player.pos.x + (rect[0] / METER)
|
||||
|
|
Loading…
Reference in New Issue