Refactor map handling/generation/rendering
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 3.4 KiB |
After Width: | Height: | Size: 3.3 KiB |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 1007 B |
Before Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.2 KiB |
|
@ -3,9 +3,14 @@ import pygame
|
||||||
global assets
|
global assets
|
||||||
assets = {}
|
assets = {}
|
||||||
|
|
||||||
|
none = pygame.image.load("none.png")
|
||||||
|
|
||||||
def load(filename):
|
def load(filename):
|
||||||
assets[filename] = pygame.image.load("assets/" + filename)
|
assets[filename] = pygame.image.load("assets/" + filename) #.convert()
|
||||||
return assets[filename]
|
return assets[filename]
|
||||||
|
|
||||||
def get(filename):
|
def get(filename):
|
||||||
return assets[filename]
|
try:
|
||||||
|
return assets[filename]
|
||||||
|
except:
|
||||||
|
return none
|
||||||
|
|
|
@ -0,0 +1,174 @@
|
||||||
|
"""
|
||||||
|
Dungeon Generator
|
||||||
|
Based on https://www.jamesbaum.co.uk/blether/procedural-level-generation-rust/
|
||||||
|
"""
|
||||||
|
|
||||||
|
import random
|
||||||
|
import time
|
||||||
|
import math
|
||||||
|
from .tiles import Tile
|
||||||
|
from .vector import Vector
|
||||||
|
|
||||||
|
# Helper functions
|
||||||
|
def rand(*args):
|
||||||
|
random.seed(time.clock())
|
||||||
|
return random.randint(*args)
|
||||||
|
|
||||||
|
# Room class for generation handling
|
||||||
|
class Room():
|
||||||
|
def __init__(self, x, y, width, height):
|
||||||
|
self.x = x
|
||||||
|
self.y = y
|
||||||
|
self.width = width
|
||||||
|
self.height = height
|
||||||
|
|
||||||
|
self.left = x
|
||||||
|
self.right = x + width
|
||||||
|
self.top = y
|
||||||
|
self.bottom = y + height
|
||||||
|
|
||||||
|
self.cx = math.floor(self.x + (width / 2))
|
||||||
|
self.cy = math.floor(self.y + (height / 2))
|
||||||
|
|
||||||
|
def intersects(self, other):
|
||||||
|
return self.left <= other.right and self.right >= other.left and self.top <= other.bottom and self.bottom >= other.top
|
||||||
|
|
||||||
|
# Generator class in case its used multiple times
|
||||||
|
class Generator():
|
||||||
|
rooms = [] # Stores room objects
|
||||||
|
board = [] # Map of zeros and ones
|
||||||
|
|
||||||
|
def __init__(self, width, height = None):
|
||||||
|
self.width = width
|
||||||
|
self.height = height or width
|
||||||
|
|
||||||
|
for y in range(self.height + 1):
|
||||||
|
self.board.append([])
|
||||||
|
for _ in range(self.width + 1):
|
||||||
|
self.board[y].append(0)
|
||||||
|
|
||||||
|
self.place_rooms()
|
||||||
|
self.place_corridors()
|
||||||
|
|
||||||
|
def place_rooms(self):
|
||||||
|
for _ in range(rand(10, 30)): # Amount of rooms
|
||||||
|
width = rand(4, 10) # Room size
|
||||||
|
height = rand(4, 10)
|
||||||
|
x = rand(0, self.width - width) # Room position
|
||||||
|
y = rand(0, self.height - height)
|
||||||
|
|
||||||
|
if x + width > self.width:
|
||||||
|
x = self.width - width
|
||||||
|
|
||||||
|
if y + height > self.height:
|
||||||
|
y = self.height - height
|
||||||
|
|
||||||
|
collides = False
|
||||||
|
room = Room(x, y, width, height)
|
||||||
|
|
||||||
|
# Make sure room doesn't collide
|
||||||
|
for other_room in self.rooms:
|
||||||
|
if room.intersects(other_room):
|
||||||
|
collides = True
|
||||||
|
break
|
||||||
|
|
||||||
|
# Add room if valid place
|
||||||
|
if not collides:
|
||||||
|
for row in range(room.height):
|
||||||
|
for col in range(room.width):
|
||||||
|
self.board[room.y + row][room.x + col] = 1
|
||||||
|
|
||||||
|
self.rooms.append(room)
|
||||||
|
|
||||||
|
# Connect rooms together
|
||||||
|
def place_corridors(self):
|
||||||
|
for i in range(len(self.rooms) - 1):
|
||||||
|
room1 = self.rooms[i]
|
||||||
|
room2 = self.rooms[i + 1]
|
||||||
|
|
||||||
|
if rand(0, 2) == 0:
|
||||||
|
if room1.cx <= room2.cx:
|
||||||
|
self.horiz_corridor(room1.cx, room2.cx, room1.cy)
|
||||||
|
else:
|
||||||
|
self.horiz_corridor(room2.cx, room1.cx, room1.cy)
|
||||||
|
if room1.cy <= room2.cy:
|
||||||
|
self.vert_corridor(room1.cy, room2.cy, room2.cx)
|
||||||
|
else:
|
||||||
|
self.vert_corridor(room2.cy, room1.cy, room2.cx)
|
||||||
|
else:
|
||||||
|
if room1.cy <= room2.cy:
|
||||||
|
self.vert_corridor(room1.cy, room2.cy, room2.cx)
|
||||||
|
else:
|
||||||
|
self.vert_corridor(room2.cy, room1.cy, room2.cx)
|
||||||
|
if room1.cx <= room2.cx:
|
||||||
|
self.horiz_corridor(room1.cx, room2.cx, room1.cy)
|
||||||
|
else:
|
||||||
|
self.horiz_corridor(room2.cx, room1.cx, room1.cy)
|
||||||
|
|
||||||
|
def horiz_corridor(self, x1, x2, y):
|
||||||
|
for row in range(y - 1, y + 2):
|
||||||
|
for col in range(x1 - 1, x2 + 2):
|
||||||
|
self.board[row][col] = 1
|
||||||
|
|
||||||
|
def vert_corridor(self, y1, y2, x):
|
||||||
|
for row in range(y1, y2 + 2):
|
||||||
|
for col in range(x - 1, x + 2):
|
||||||
|
self.board[row][col] = 1
|
||||||
|
|
||||||
|
def generate(self, map):
|
||||||
|
for y in range(self.height):
|
||||||
|
for x in range(self.width):
|
||||||
|
if self.board[y][x] == 1:
|
||||||
|
# Floor
|
||||||
|
map.set_tile(x, y, 0, "map:cobble")
|
||||||
|
|
||||||
|
if self.board[y][x] == 1:
|
||||||
|
# Adjacent sides (Corresponds with rotation map below)
|
||||||
|
asides = [
|
||||||
|
[1, 0],
|
||||||
|
[0, 1],
|
||||||
|
[-1, 0],
|
||||||
|
[0, -1]
|
||||||
|
]
|
||||||
|
|
||||||
|
adj = 0 # How many adjacent
|
||||||
|
arot = 0 # Last adjacent key
|
||||||
|
for key in range(len(asides)):
|
||||||
|
off = asides[key]
|
||||||
|
if self.board[y + off[1]][x + off[0]] == 0:
|
||||||
|
adj += 1
|
||||||
|
arot = key
|
||||||
|
|
||||||
|
# Diagonal sides (Corresponds with rotation map below)
|
||||||
|
dsides = [
|
||||||
|
[-1, 1],
|
||||||
|
[-1, -1],
|
||||||
|
[1, -1],
|
||||||
|
[1, 1]
|
||||||
|
]
|
||||||
|
|
||||||
|
dia = 0 # How many diagonal
|
||||||
|
drot = 0 # Last diagonal key
|
||||||
|
for key in range(len(dsides)):
|
||||||
|
off = dsides[key]
|
||||||
|
if self.board[y + off[1]][x + off[0]] == 0:
|
||||||
|
dia += 1
|
||||||
|
# Only set key if opposite tile is floor
|
||||||
|
if self.board[y - off[1]][x - off[0]] == 1:
|
||||||
|
drot = key
|
||||||
|
|
||||||
|
tile = ""
|
||||||
|
rmap = [2, 3, 0, 1] # Rotation map
|
||||||
|
if adj == 0 and dia == 1: # Need diagonals to prevent false positives with all-floor
|
||||||
|
tile = "map:wall_cobble_corner_outer"
|
||||||
|
rot = rmap[drot]
|
||||||
|
elif adj == 1:
|
||||||
|
tile = "map:wall_cobble"
|
||||||
|
rot = rmap[arot]
|
||||||
|
elif adj == 2:
|
||||||
|
tile = "map:wall_cobble_corner_inner"
|
||||||
|
rot = rmap[drot]
|
||||||
|
|
||||||
|
if tile != "":
|
||||||
|
map.set_tile(x, y, 1, tile)
|
||||||
|
map.get_tile(x, y, 1).set_rotation(rot)
|
74
src/game.py
|
@ -1,23 +1,24 @@
|
||||||
import pygame
|
import pygame
|
||||||
import os, sys
|
import os, sys
|
||||||
from . import assets, controller, spritesheet
|
|
||||||
from .map import Map
|
|
||||||
from .player import Player
|
|
||||||
|
|
||||||
# Constants
|
|
||||||
SCALE = 3
|
|
||||||
METER = 32
|
|
||||||
FPS = 60
|
|
||||||
|
|
||||||
# Init
|
# Init
|
||||||
pygame.init()
|
pygame.init()
|
||||||
pygame.font.init()
|
pygame.font.init()
|
||||||
|
|
||||||
# Screen Init (might implement a display module later to handle maximizing)
|
winsize = [800, 600]
|
||||||
|
screen = pygame.display.set_mode(winsize, pygame.RESIZABLE)
|
||||||
|
|
||||||
|
from . import assets, controller, register, spritesheet
|
||||||
|
from .map import Map
|
||||||
|
from .player import Player
|
||||||
|
|
||||||
pygame.display.set_caption("Zoria")
|
pygame.display.set_caption("Zoria")
|
||||||
pygame.display.set_icon(assets.load("icon.png"))
|
pygame.display.set_icon(assets.load("icon.png"))
|
||||||
winsize = [800, 600]
|
|
||||||
screen = pygame.display.set_mode(winsize) #, pygame.RESIZABLE)
|
# Constants
|
||||||
|
SCALE = 2
|
||||||
|
METER = 32
|
||||||
|
FPS = 60
|
||||||
|
|
||||||
# Load all assets
|
# Load all assets
|
||||||
for filename in os.listdir(os.path.join(os.path.dirname(os.path.realpath(sys.argv[0])), "assets")):
|
for filename in os.listdir(os.path.join(os.path.dirname(os.path.realpath(sys.argv[0])), "assets")):
|
||||||
|
@ -39,6 +40,8 @@ player.set_pos(map.generator.rooms[0].x + 2, map.generator.rooms[0].y + 2)
|
||||||
|
|
||||||
CENTER = [winsize[0] / 2, winsize[1] / 2]
|
CENTER = [winsize[0] / 2, winsize[1] / 2]
|
||||||
|
|
||||||
|
arial = pygame.font.SysFont("Arial", 10)
|
||||||
|
|
||||||
# Mainloop
|
# Mainloop
|
||||||
clock = pygame.time.Clock()
|
clock = pygame.time.Clock()
|
||||||
while 1:
|
while 1:
|
||||||
|
@ -46,6 +49,11 @@ while 1:
|
||||||
|
|
||||||
for event in pygame.event.get():
|
for event in pygame.event.get():
|
||||||
if event.type == pygame.QUIT: sys.exit()
|
if event.type == pygame.QUIT: sys.exit()
|
||||||
|
elif event.type == pygame.VIDEORESIZE:
|
||||||
|
winsize = event.size
|
||||||
|
SCALE = 2 * (winsize[0] / 800)
|
||||||
|
CENTER = [winsize[0] / 2, winsize[1] / 2]
|
||||||
|
screen = pygame.display.set_mode(winsize, pygame.RESIZABLE)
|
||||||
|
|
||||||
screen.fill((0, 0, 0))
|
screen.fill((0, 0, 0))
|
||||||
|
|
||||||
|
@ -56,19 +64,37 @@ while 1:
|
||||||
psize = player.sprite.rect.size
|
psize = player.sprite.rect.size
|
||||||
camera = [CENTER[0] - (psize[0] / 2 * SCALE), CENTER[1] - (psize[1] / 2 * SCALE)]
|
camera = [CENTER[0] - (psize[0] / 2 * SCALE), CENTER[1] - (psize[1] / 2 * SCALE)]
|
||||||
|
|
||||||
for layer in map.map["renderLayers"]:
|
for z in range(len(map.map)):
|
||||||
for row in range(len(layer)):
|
for y in range(len(map.map[z])):
|
||||||
for column in range(len(layer[row])):
|
for x in range(len(map.map[z][y])):
|
||||||
materialIndex = layer[row][column]
|
tile = map.get_tile(x, y, z)
|
||||||
if materialIndex != 0:
|
if tile:
|
||||||
texture = assets.get(map.map["tiles"][materialIndex - 1])
|
texture = assets.get(tile.texture)
|
||||||
tilesize = texture.get_rect().size[0]
|
|
||||||
screen.blit(pygame.transform.scale(texture, [SCALE * tilesize, SCALE * tilesize]), [
|
# Rotations are clockwise due to Y+ down rendering
|
||||||
column * SCALE * tilesize - (player.pos.x * SCALE * METER) + camera[0],
|
# NOTE: This will be obsolete once game is converted to 2.5D
|
||||||
row * SCALE * tilesize - (player.pos.y * SCALE * METER) + camera[1]
|
rotated = pygame.transform.rotate(texture, -90 * tile.rotation)
|
||||||
])
|
|
||||||
|
tilesize = texture.get_rect().size
|
||||||
|
|
||||||
|
tilex = (x * METER) - ((tilesize[0] / 2) - (METER / 2))
|
||||||
|
tiley = (y * METER) - (tilesize[1] - METER)
|
||||||
|
|
||||||
|
pos = [
|
||||||
|
camera[0] + round((tilex - (player.pos.x * METER)) * SCALE),
|
||||||
|
camera[1] + round((tiley - (player.pos.y * METER)) * SCALE)
|
||||||
|
]
|
||||||
|
|
||||||
|
# Only render tile if on-screen
|
||||||
|
if pos[0] + tilex >= 0 and pos[0] <= winsize[0] and \
|
||||||
|
pos[1] + tiley >= 0 and pos[1] <= winsize[1]:
|
||||||
|
screen.blit(pygame.transform.scale(rotated, [round(tilesize[0] * SCALE), round(tilesize[1] * SCALE)]), pos)
|
||||||
|
|
||||||
|
# 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]])
|
||||||
|
|
||||||
# Draw player based on camera position
|
# Draw player based on camera position
|
||||||
screen.blit(pygame.transform.scale(player.sprite.texture.frame, [SCALE * player.sprite.texture.width, SCALE * player.sprite.texture.height]), camera)
|
screen.blit(pygame.transform.scale(player.sprite.texture.frame, [round(SCALE * player.sprite.texture.width), round(SCALE * player.sprite.texture.height)]), camera)
|
||||||
|
|
||||||
pygame.display.flip()
|
pygame.display.update()
|
||||||
|
# pygame.display.flip()
|
||||||
|
|
206
src/generator.py
|
@ -1,206 +0,0 @@
|
||||||
import random
|
|
||||||
import time
|
|
||||||
import math
|
|
||||||
|
|
||||||
MSIZE = 80
|
|
||||||
|
|
||||||
def rand(*args):
|
|
||||||
random.seed(time.clock())
|
|
||||||
return random.randint(*args)
|
|
||||||
|
|
||||||
class Room():
|
|
||||||
def __init__(self, x, y, width, height):
|
|
||||||
self.x = x
|
|
||||||
self.y = y
|
|
||||||
self.width = width
|
|
||||||
self.height = height
|
|
||||||
|
|
||||||
self.left = x
|
|
||||||
self.right = x + width
|
|
||||||
self.top = y
|
|
||||||
self.bottom = y + height
|
|
||||||
|
|
||||||
self.cx = math.floor(self.x + (width / 2))
|
|
||||||
self.cy = math.floor(self.y + (height / 2))
|
|
||||||
|
|
||||||
def intersects(self, other):
|
|
||||||
return self.left <= other.right and self.right >= other.left and self.top <= other.bottom and self.bottom >= other.top
|
|
||||||
|
|
||||||
class Generator():
|
|
||||||
rooms = []
|
|
||||||
board = []
|
|
||||||
|
|
||||||
def __init__(self, width, height = None):
|
|
||||||
self.width = width
|
|
||||||
self.height = height or width
|
|
||||||
|
|
||||||
for y in range(self.height):
|
|
||||||
self.board.append([])
|
|
||||||
for _ in range(self.width):
|
|
||||||
self.board[y].append(0)
|
|
||||||
|
|
||||||
self.place_rooms()
|
|
||||||
self.place_corridors()
|
|
||||||
|
|
||||||
def place_rooms(self):
|
|
||||||
for _ in range(rand(10, 30)):
|
|
||||||
width = rand(4, 10)
|
|
||||||
height = rand(4, 10)
|
|
||||||
x = rand(0, 60)
|
|
||||||
y = rand(0, 60)
|
|
||||||
|
|
||||||
if x + width > self.width:
|
|
||||||
x = self.width - width
|
|
||||||
|
|
||||||
if y + height > self.height:
|
|
||||||
y = self.height - height
|
|
||||||
|
|
||||||
collides = False
|
|
||||||
room = Room(x, y, width, height)
|
|
||||||
|
|
||||||
for other_room in self.rooms:
|
|
||||||
if room.intersects(other_room):
|
|
||||||
collides = True
|
|
||||||
break
|
|
||||||
|
|
||||||
if not collides:
|
|
||||||
self.place_room(room)
|
|
||||||
|
|
||||||
def place_room(self, room):
|
|
||||||
for row in range(room.height):
|
|
||||||
for col in range(room.width):
|
|
||||||
y = room.y + row
|
|
||||||
x = room.x + col
|
|
||||||
|
|
||||||
self.board[y][x] = 1
|
|
||||||
|
|
||||||
self.rooms.append(room)
|
|
||||||
|
|
||||||
def place_corridors(self):
|
|
||||||
for i in range(0, len(self.rooms) - 1):
|
|
||||||
room1 = self.rooms[i]
|
|
||||||
room2 = self.rooms[i + 1]
|
|
||||||
|
|
||||||
if rand(0, 2) == 0:
|
|
||||||
if room1.cx <= room2.cx:
|
|
||||||
self.horiz_corridor(room1.cx, room2.cx, room1.cy)
|
|
||||||
else:
|
|
||||||
self.horiz_corridor(room2.cx, room1.cx, room1.cy)
|
|
||||||
if room1.cy <= room2.cy:
|
|
||||||
self.vert_corridor(room1.cy, room2.cy, room2.cx)
|
|
||||||
else:
|
|
||||||
self.vert_corridor(room2.cy, room1.cy, room2.cx)
|
|
||||||
else:
|
|
||||||
if room1.cy <= room2.cy:
|
|
||||||
self.vert_corridor(room1.cy, room2.cy, room2.cx)
|
|
||||||
else:
|
|
||||||
self.vert_corridor(room2.cy, room1.cy, room2.cx)
|
|
||||||
if room1.cx <= room2.cx:
|
|
||||||
self.horiz_corridor(room1.cx, room2.cx, room1.cy)
|
|
||||||
else:
|
|
||||||
self.horiz_corridor(room2.cx, room1.cx, room1.cy)
|
|
||||||
|
|
||||||
def horiz_corridor(self, x1, x2, y):
|
|
||||||
for row in range(y - 1, y + 2):
|
|
||||||
for col in range(x1 - 1, x2 + 2):
|
|
||||||
self.board[row][col] = 1
|
|
||||||
|
|
||||||
def vert_corridor(self, y1, y2, x):
|
|
||||||
for row in range(y1, y2 + 2):
|
|
||||||
for col in range(x - 1, x + 2):
|
|
||||||
self.board[row][col] = 1
|
|
||||||
|
|
||||||
def get_map(self):
|
|
||||||
# Map object
|
|
||||||
map = {
|
|
||||||
"tiles": [
|
|
||||||
"floor_cobble.png",
|
|
||||||
"wall_cobble_down.png",
|
|
||||||
"wall_cobble_right.png",
|
|
||||||
"wall_cobble_up.png",
|
|
||||||
"wall_cobble_left.png",
|
|
||||||
"wall_cobble_corner_nw_inner.png",
|
|
||||||
"wall_cobble_corner_ne_inner.png",
|
|
||||||
"wall_cobble_corner_se_inner.png",
|
|
||||||
"wall_cobble_corner_sw_inner.png",
|
|
||||||
"wall_cobble_corner_nw_outer.png",
|
|
||||||
"wall_cobble_corner_ne_outer.png",
|
|
||||||
"wall_cobble_corner_se_outer.png",
|
|
||||||
"wall_cobble_corner_sw_outer.png"
|
|
||||||
],
|
|
||||||
"renderLayers": []
|
|
||||||
}
|
|
||||||
|
|
||||||
# Generate walls
|
|
||||||
bounds = []
|
|
||||||
for y in range(self.height):
|
|
||||||
bounds.append([])
|
|
||||||
for x in range(self.width):
|
|
||||||
wall = 0
|
|
||||||
if self.board[y][x] > 0:
|
|
||||||
for x2 in range(x - 1, x + 2):
|
|
||||||
for y2 in range(y - 1, y + 2):
|
|
||||||
if self.board[y2][x2] == 0:
|
|
||||||
wall += 1
|
|
||||||
bounds[y].append(wall)
|
|
||||||
map["boundaries"] = bounds
|
|
||||||
|
|
||||||
# Floor layer
|
|
||||||
layer1 = self.board.copy()
|
|
||||||
map["renderLayers"].append(layer1)
|
|
||||||
|
|
||||||
# Wall layer
|
|
||||||
layer2 = []
|
|
||||||
for y in range(self.height):
|
|
||||||
layer2.append([])
|
|
||||||
for _ in range(self.width):
|
|
||||||
layer2[y].append(0)
|
|
||||||
|
|
||||||
for y in range(1, self.height - 1):
|
|
||||||
for x in range(1, self.width - 1):
|
|
||||||
if self.board[y][x] == 1:
|
|
||||||
tile = 0
|
|
||||||
if self.board[y][x - 1] == 1 and self.board[y][x + 1] == 1:
|
|
||||||
if self.board[y - 1][x] == 0:
|
|
||||||
tile = 2
|
|
||||||
elif self.board[y + 1][x] == 0:
|
|
||||||
tile = 4
|
|
||||||
|
|
||||||
if self.board[y - 1][x] == 1 and self.board[y + 1][x] == 1:
|
|
||||||
if self.board[y][x - 1] == 0:
|
|
||||||
tile = 3
|
|
||||||
elif self.board[y][x + 1] == 0:
|
|
||||||
tile = 5
|
|
||||||
|
|
||||||
layer2[y][x] = tile
|
|
||||||
|
|
||||||
for y in range(1, self.height - 1):
|
|
||||||
for x in range(1, self.width - 1):
|
|
||||||
if bounds[y][x] > 0 and layer2[y][x] == 0:
|
|
||||||
tile = 0
|
|
||||||
if bounds[y + 1][x] > 0 and bounds[y][x + 1] > 0:
|
|
||||||
if bounds[y][x] > 1:
|
|
||||||
tile = 6
|
|
||||||
else:
|
|
||||||
tile = 10
|
|
||||||
elif bounds[y + 1][x] > 0 and bounds[y][x - 1] > 0:
|
|
||||||
if bounds[y][x] > 1:
|
|
||||||
tile = 7
|
|
||||||
else:
|
|
||||||
tile = 11
|
|
||||||
elif bounds[y - 1][x] > 0 and bounds[y][x - 1] > 0:
|
|
||||||
if bounds[y][x] > 1:
|
|
||||||
tile = 8
|
|
||||||
else:
|
|
||||||
tile = 12
|
|
||||||
elif bounds[y - 1][x] > 0 and bounds[y][x + 1] > 0:
|
|
||||||
if bounds[y][x] > 1:
|
|
||||||
tile = 9
|
|
||||||
else:
|
|
||||||
tile = 13
|
|
||||||
|
|
||||||
layer2[y][x] = tile
|
|
||||||
|
|
||||||
map["renderLayers"].append(layer2)
|
|
||||||
|
|
||||||
return map
|
|
49
src/map.py
|
@ -1,7 +1,7 @@
|
||||||
import pygame
|
import pygame
|
||||||
import json, math
|
import json, math
|
||||||
from . import assets
|
from . import assets, dungeon, loot
|
||||||
from .generator import Generator
|
from .tiles import Tile
|
||||||
from .vector import Vector
|
from .vector import Vector
|
||||||
|
|
||||||
class Map:
|
class Map:
|
||||||
|
@ -10,21 +10,44 @@ class Map:
|
||||||
def __init__(self, meter):
|
def __init__(self, meter):
|
||||||
self.METER = meter # Pixels per 1 meter
|
self.METER = meter # Pixels per 1 meter
|
||||||
|
|
||||||
def load(self, filename):
|
# def load(self, filename):
|
||||||
with open(filename) as file:
|
# with open(filename) as file:
|
||||||
self.map = json.load(file)
|
# self.map = json.load(file)
|
||||||
|
|
||||||
def generate(self):
|
def generate(self):
|
||||||
self.generator = Generator(80)
|
self.generator = dungeon.Generator(80)
|
||||||
self.map = self.generator.get_map()
|
self.generator.generate(self)
|
||||||
|
# self.placer = loot.Placer()
|
||||||
|
# self.map = self.placer.populate(self.map)
|
||||||
|
|
||||||
def collides(self, pos, rect):
|
def collides(self, pos, rect):
|
||||||
for y in range(int(math.floor(pos.y)) - 1, int(math.floor(pos.y)) + 2):
|
px = int(math.floor(pos.x))
|
||||||
for x in range(int(math.floor(pos.x)) - 1, int(math.floor(pos.x)) + 2):
|
py = int(math.floor(pos.y))
|
||||||
if not (x == pos.x and y == pos.y):
|
for y in range(py - 1, py + 2):
|
||||||
if self.map["boundaries"][y][x] > 0:
|
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 tile and tile.is_solid():
|
||||||
if pos.x + (rect.width / self.METER) >= x and pos.x <= (x + 1) and \
|
if pos.x + (rect.width / self.METER) >= x and pos.x <= (x + 1) and \
|
||||||
pos.y + (rect.height / self.METER) >= y and pos.y <= (y + 1):
|
pos.y + (rect.height / self.METER) >= y and pos.y <= (y + 1):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def set_tile(self, x, y, z, name):
|
||||||
|
for _ in range(len(self.map), z + 1):
|
||||||
|
self.map.append([])
|
||||||
|
|
||||||
|
for _ in range(len(self.map[z]), y + 1):
|
||||||
|
self.map[z].append([])
|
||||||
|
|
||||||
|
for _ in range(len(self.map[z][y]), x + 1):
|
||||||
|
self.map[z][y].append(None)
|
||||||
|
|
||||||
|
if name != "":
|
||||||
|
self.map[z][y][x] = Tile(name)
|
||||||
|
|
||||||
|
def get_tile(self, x, y, z):
|
||||||
|
try:
|
||||||
|
return self.map[z][y][x]
|
||||||
|
except:
|
||||||
|
return None
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
from . import tiles
|
||||||
|
|
||||||
|
tiles.register_tile("map:cobble", {
|
||||||
|
"texture": "floor_cobble.png",
|
||||||
|
})
|
||||||
|
|
||||||
|
tiles.register_tile("map:wall_cobble", {
|
||||||
|
"texture": "wall_cobble.png",
|
||||||
|
})
|
||||||
|
|
||||||
|
tiles.register_tile("map:wall_cobble_corner_inner", {
|
||||||
|
"texture": "wall_cobble_corner_inner.png",
|
||||||
|
})
|
||||||
|
|
||||||
|
tiles.register_tile("map:wall_cobble_corner_outer", {
|
||||||
|
"texture": "wall_cobble_corner_outer.png",
|
||||||
|
})
|
||||||
|
|
||||||
|
tiles.register_tile("loot:coins", {
|
||||||
|
"texture": "loot_gold.png",
|
||||||
|
})
|
||||||
|
|
||||||
|
tiles.register_tile("loot:pile", {
|
||||||
|
"texture": "loot_pile.png",
|
||||||
|
})
|
|
@ -0,0 +1,49 @@
|
||||||
|
import pygame
|
||||||
|
|
||||||
|
global registered_tiles
|
||||||
|
registered_tiles = {}
|
||||||
|
|
||||||
|
content_ids = []
|
||||||
|
content_id_map = {}
|
||||||
|
|
||||||
|
def register_tile(name, definition):
|
||||||
|
registered_tiles[name] = definition
|
||||||
|
content_id_map[name] = len(content_ids)
|
||||||
|
content_ids.append(name)
|
||||||
|
|
||||||
|
def get_content_id(name):
|
||||||
|
try:
|
||||||
|
return content_id_map[name]
|
||||||
|
except:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def get_tile_from_content_id(id):
|
||||||
|
try:
|
||||||
|
return registered_tiles[content_ids[id]]
|
||||||
|
except:
|
||||||
|
return None
|
||||||
|
|
||||||
|
class Tile:
|
||||||
|
texture = "none.png"
|
||||||
|
solid = True
|
||||||
|
rotation = 0
|
||||||
|
|
||||||
|
def __init__(self, name):
|
||||||
|
self.name = name
|
||||||
|
for key in registered_tiles[name]:
|
||||||
|
self.__dict__[key] = registered_tiles[name][key]
|
||||||
|
|
||||||
|
def get(self, key):
|
||||||
|
try:
|
||||||
|
return getattr(self, key)
|
||||||
|
except:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def set_rotation(self, rot):
|
||||||
|
self.rotation = rot
|
||||||
|
|
||||||
|
def get_rotation(self, rot):
|
||||||
|
return self.rotation
|
||||||
|
|
||||||
|
def is_solid(self):
|
||||||
|
return self.get("solid") == True
|
|
@ -14,8 +14,13 @@ class Vector:
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "Vector {{x: {0}, y: {1}}}".format(self.x, self.y)
|
return "Vector {{x: {0}, y: {1}}}".format(self.x, self.y)
|
||||||
|
|
||||||
def apply(self, func):
|
def __eq__(self, b):
|
||||||
return Vector(func(self.x), func(self.y))
|
vec = vec_or_num(b)
|
||||||
|
return self.x == vec.x and self.y == vec.y
|
||||||
|
|
||||||
|
def __ne__(self, b):
|
||||||
|
vec = vec_or_num(b)
|
||||||
|
return self.x != vec.x or self.y != vec.y
|
||||||
|
|
||||||
def __add__(self, b):
|
def __add__(self, b):
|
||||||
vec = vec_or_num(b)
|
vec = vec_or_num(b)
|
||||||
|
@ -41,3 +46,6 @@ class Vector:
|
||||||
|
|
||||||
def __ceil__(self):
|
def __ceil__(self):
|
||||||
return Vector(ceil(self.x), ceil(self.y))
|
return Vector(ceil(self.x), ceil(self.y))
|
||||||
|
|
||||||
|
def apply(self, func):
|
||||||
|
return Vector(func(self.x), func(self.y))
|
||||||
|
|