-
Notifications
You must be signed in to change notification settings - Fork 13
/
Engine.py
142 lines (122 loc) · 4.56 KB
/
Engine.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
import sys
import xml.etree.ElementTree as ET
from Input import *
from World import *
from Graphics import *
from Sound import *
from GameActorController import *
from Actors import *
class Engine:
def __init__(self, screen_size, fps):
self._tmx_root = None # Will be used to store the currently loaded tmx-file:
self._fps = fps # Save fps
self._CLOCK = pygame.time.Clock() # Create pygame.Clock for fps-control
self._draw_tile_ids = False # DEBUG: Draw all ids:
# Create instance of Graphics-Engine:
self.graphics = Graphics(self,screen_size)
# Create instance of World:
self.world = World(self)
# Create instance of input-engine
self.input = Input(self)
# Create actors-controller
self.actors = GameActorController(self)
# Create sound-controller (not jet programmed...)
self.sound = Sound(self)
# Finally, first map (temporary):
self._load_tmx("Forest_N1_1.tmx")
# Var changed by self.load_new_level. If not false, in the next update cycle, the level gets loaded.
self._load_new_level = False
def update(self):
"""
Updates everything. Should be called once per frame.
"""
# Check if new level should be loaded:
if self._load_new_level:
self._load_tmx(self._load_new_level)
self._load_new_level = False
# Handle events:
self._handle_events()
# Update input:
self.input.update()
# Update world:
self.world.update()
# Update Game-Actors:
self.actors.update()
# Update screen:
self.graphics.update()
# Make sure engine doesn't run faster than 60 fps:
self._CLOCK.tick(self._fps)
def _load_tmx(self, filepath):
"""
Loads the tmx-file 'filepath' and parses it.
TODO: Maybe it would be better to move the part that parses tile-csv to the world-class....
"""
# Empty self.actors:
self.actors = GameActorController(self)
# TODO: Find a way to empty self.world
self.world = World(self)
# Open and parse the tmx-file
self._tmx_root = ET.parse(filepath).getroot()
# Get grid-size (in tiles)
grid_size = (int(self._tmx_root.attrib["width"]), int(self._tmx_root.attrib["height"]))
# Set the grid-size in the world:
self.world.set_gid_size(grid_size)
# Get tile-size (in pixels)
tile_size = (int(self._tmx_root.attrib["tilewidth"]), int(self._tmx_root.attrib["tileheight"]))
# Set the tile-size in the world:
self.world.set_tile_size(tile_size)
######
# Next, process the tilesets:
# For tileset..
for tileset in self._tmx_root.findall("tileset"):
# If tileset is "world":
if tileset.attrib["name"] == "world":
# Dor tile in this tileset:
for tile in tileset.findall("tile"):
# For property in tile:
for property in tile.find("properties").findall("property"):
# Update tile-property
self.world.set_tile_property(int(tile.attrib["id"]), property.attrib["name"], property.attrib["value"])
######
# Next, process the layers: Where is what tile?
# For every layer...
all_layers = self._tmx_root.findall("layer")
for layer in range(len(all_layers)):
# Get and save the raw csv data which contains information about where which tile is:
csv_data = all_layers[layer].find("data").text
# First, split the csv in rows:
splitted_data = csv_data.split("\n")
# For row in csv_data:
for row in range(len(splitted_data)):
# Make sure the row isn't empty:
if not splitted_data[row] == "":
splitted_row = splitted_data[row].split(",")
# For column in csv_data (= for tile)
for column in range(len(splitted_row)):
# Make sure the tile isn't empty:
if not splitted_row[column] == "":
# Calculate the position of the tile:
position = list(map(lambda x, y: x*y, (column, row-1), tile_size))
# Finally create the tile:
self.world.create_tile(layer, position, tile_size, int(splitted_row[column])-1)
#####
# Next, process object-group-layers:
# For object-group-layer...
for objectgroup in self._tmx_root.findall("objectgroup"):
# If layer-name == "main"...
if objectgroup.attrib["name"] == "game_actors":
# For every object in that layer...
for object in objectgroup.findall("object"):
# Get the name of that object (=GameActor):
actor_name = object.attrib["name"]
# Get the position of that object
position = (float(object.attrib["x"]), float(object.attrib["y"])-float(object.attrib["height"]))
# Spawn a game-actor with that name:
self.actors.spawn_game_actor(actor_name, position)
def _handle_events(self):
for event in self.input.events:
if event.type == QUIT:
pygame.quit()
sys.exit()
def load_new_level(self, filename):
self._load_new_level = filename