This repository was archived by the owner on Feb 17, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathscene.py
144 lines (127 loc) · 5.02 KB
/
scene.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
import random
from typing import Dict, List
from src.common.point import Point
from src.objects.agent import Agent
from src.objects.floor import Floor
from src.objects.portal import Portal
from src.objects.object import Object
from src.objects.npcs.enemies.training_dummy import TrainingDummy
import json
from PIL import Image
PATH_TO_CONFIG = "./src/init_files/config.json"
class Scene:
"""
Object representing one level in the game.
It is responsible for storing all instances of `Object` class.
"""
agent_locals: Dict
objects_count: int
runtime: 'Runtime'
_objects_position_map: Dict[Point, List[Object]] # fields
_objects_id_map: Dict[int, Object]
__player: Agent
def __init__(self, runtime) -> None:
self.objects_count = 0
self._objects_position_map = {}
self._objects_id_map = {}
self.agent_locals = {}
self.runtime = runtime
self._generate_scene()
self.__player = None
def _generate_scene_small(self):
"""
Small scene for tests
"""
points = [Point(0, 0), Point(0, 1), Point(1, 0), Point(1, 1), Point(0, 2), Point(1, 2)]
for point in points:
Floor(self, point)
#Portal(self, random.choice(points))
#TrainingDummy(self, Point(1, 0))
def _generate_scene(self):
"""
For now it'll generate scene layout
Subject to be changed
"""
with open(PATH_TO_CONFIG) as json_file:
config = json.load(json_file)
floor_colour = config["floor_colour"]
colour_to_function_dict = {}
for dict_row in config["functions"]:
colour_to_function_dict.update(dict_row)
map = Image.open("./src/maps/map1.bmp")
image_width, image_height = map.size
for width in range(image_width):
for height in range(image_height):
pixel_colour = str(map.getpixel((width, height)))
if pixel_colour in colour_to_function_dict or pixel_colour == floor_colour:
Floor(self, Point(width, height))
if pixel_colour != floor_colour:
eval(colour_to_function_dict[pixel_colour])(self, Point(width, height))
map.close()
def run(self):
"""
TODO
"""
max_spins: int = 8
spins: int = 0
while spins < max_spins:
spins += 1
for scene_object in list(self._objects_id_map.values()):
scene_object.tick()
def get_player(self):
"""
Returns reference to a players agent.
We cannot use just the field `__player`
because the reference itself my change
during runtime and could become outdated.
Think of actions like `move` which need
agent that is in the game now, not a
reference to agent in a previous scene
"""
return self.__player
def get_objects_by_position(self, position):
return self._objects_position_map[position]
def get_objects_by_id(self, id):
return self._objects_id_map[id]
def move_object(self, moved_object: Object, new_position: Point) -> bool:
"""
Returns True on successful `move` operation
"""
# Check if the destination is a `field` in the scene, and if it is -
# - it must be walkable
if not self.is_walkable_field(new_position):
return False
previous_position = moved_object.properties.position
moved_object.free_field(previous_position)
if moved_object.occupy_field(new_position):
moved_object.properties.position = new_position
else:
moved_object.occupy_field(previous_position)
return False
return True
def is_walkable_field(self, position: Point) -> bool:
return self._objects_position_map.get(position) and self._objects_position_map[position][0].walkable
def check_collisions(self, entering_object: Object) -> None:
"""
Call `on_collision` callback of every Object in the same
field as `entering_object`.
"""
for collision_object in self._objects_position_map[entering_object.properties.position]:
if collision_object != entering_object:
collision_object.on_collision(entering_object)
def add_object_to_position_map(self, new_object: Object, position: Point) -> None:
"""
Add object to per scene storage indexed by objects position.
The storage can store multiple objects and for now, object at
index `0` is a `field`(`floor`).
"""
if self._objects_position_map.get(position) is None:
self._objects_position_map[position] = []
new_object.occupy_field(position)
def add_object_to_id_map(self, new_object: Object) -> None:
"""
Add object to per scene storage indexed by objects `id`.
"""
self._objects_id_map[new_object.properties.id] = new_object
def _init_agent(self, _, points):
self.__player = Agent(self, points)