-
Notifications
You must be signed in to change notification settings - Fork 1
/
levels.py
161 lines (135 loc) · 5.82 KB
/
levels.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
# from xml.dom.pulldom import parseString
import pygame
import pytmx
from stgs import *
import enemies
import objects as objs
import os
class GameMap:
def __init__(self, game, index=0):
self.game = game
self.floors = [
Floor(game, "Floor1"),
Floor(game, "Floor2"),
]
self.index = index
self.floor = self.floors[self.index] # The floor loading will be based on an index within the floors list
def loadFloor(self, num=None):
"""Sets the map's floor and activates it"""
self.floor = self.floors[num if num else self.index]
self.floor.load()
def switchRoom(self, room, startObj):
for s in self.floor.room.sprites:
s.kill()
self.game.groups.killAll()
self.floor.enterRoom(room, startObj)
def getRoom(self):
return self.floor.room
def nextFloor(self):
self.index += 1
self.loadFloor()
# def update(self):
# """Update the map"""
# self.floor.update()
class Floor:
"""Represents a floor"""
def __init__(self, game, folder="Floor1"):
"""Basic initialization of props"""
self.game = game
self.folderPath = tAsset(folder)
# Finds the path of every room in the floor folder
self.roomPaths = []
for item in os.listdir(self.folderPath):
f = os.path.join(self.folderPath, item)
if os.path.isfile(f):
self.roomPaths.append(f)
# print(self.roomPaths)
# Generates room objects from path
self.rooms = [Room(self, i) for i in self.roomPaths]
# This stores the current room number or index within the rooms list
self.current = 0
def load(self):
"""Loads the floor (by default in the first room)"""
self.enterRoom("room5")
def getRoomByName(self, name):
for r in self.rooms:
if r.name == name:
return r
raise Exception(f"NO ROOM CORRESPONDING TO {name}")
def enterRoom(self, room, startObj="Entrance"):
self.room = self.getRoomByName(room)
self.room.load(startObj)
# def clear(self):
# pass
# def update(self):
# """Update the floor"""
# self.room.update(
class Room:
"""Represents a single room"""
def __init__(self, floor, filePath, **kwargs):
"""Initialize the room"""
self.floor = floor
self.game = floor.game
self.filePath = filePath
self.scale = 1
# Container for all the sprites corresponding to the room
self.sprites = pygame.sprite.Group()
# A way to track which sprite the player should go to when the room loads
self.startSprite = None
self.loaded = False
# Gets the name from the file name. Not in use yet
self.name = os.path.splitext(os.path.basename(self.filePath))[0]
for k, v in kwargs.items():
self.__dict__[k] = v
def load(self, start="Entrance"):
'''load the data for the room when the player enters it (replaces Ben's enter and load function)'''
self.clearSprites()
self.points = 0
self.loadTiled(start)
if self.startSprite:
self.game.player.setPos(self.startSprite.rect.center, True)
else:
print("There is no starting object")
self.game.player.setPos((self.width/2, self.height/2))
def loadTiled(self, start="Entrance"):
"""Load data from the tiled file"""
self.tiledData = pytmx.load_pygame(self.filePath, pixelAlpha = True)
self.width = self.tiledData.width * self.tiledData.tilewidth * self.scale
self.height = self.tiledData.height * self.tiledData.tileheight * self.scale
self.levelSize = (self.width, self.height)
self.rect = pygame.Rect(0, 0, self.width, self.height)
self.image = pygame.Surface(self.levelSize)
for layer in self.tiledData.visible_layers:
# Go through every layer to load the background images
if isinstance(layer, pytmx.TiledImageLayer):
l = layer.image
offset = (layer.offsetx*self.scale, layer.offsety*self.scale) if hasattr(layer, 'offsetx') else (0, 0)
print(offset)
self.image.blit(pygame.transform.scale(l, (l.get_width()*self.scale, l.get_height()*self.scale)), offset)
self.loadTiledObjects(start)
def loadTiledObjects(self, start="Entrance"):
for objT in self.tiledData.objects:
#print(objT.name)
objT.x, objT.y = objT.x * self.scale, objT.y * self.scale
objT.width, objT.height = objT.width * self.scale, objT.height * self.scale
try: # This is the auto registering system that allows the level to detect the name and type of Tiled Objects and generates Sprites out of them.
obj = objs.__dict__[objT.name]
if objT.name == start: # This is basically how we are going to start the player on the map. It looks for an object type that matches the start key and then uses it to place the player
self.startSprite = obj(self.game, objT)
self.sprites.add(self.startSprite)
else:
self.sprites.add(obj(self.game, objT))
except KeyError:
try:
enemy = enemies.__dict__[objT.name]
self.sprites.add(enemy(self.game, objT))
except KeyError:
print(f"Tiled Object {objT.name} is not defined")
def getObjById(self, id):
for obj in self.tiledData.objects:
if obj.id == id:
return obj
return False
def clearSprites(self):
for s in self.sprites:
s.kill()