-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathscene.py
More file actions
124 lines (108 loc) · 4.7 KB
/
scene.py
File metadata and controls
124 lines (108 loc) · 4.7 KB
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
import json
from engine.entity import Entity
from engine.components import Transform, Sprite, Physics
class Scene:
def __init__(self):
self.entities = []
def add_entity(self, e: Entity):
self.entities.append(e)
def update(self, dt):
for e in self.entities:
# if physics component exists and transform exists, update physics
phys = e.get("Physics")
trans = e.get("Transform")
if phys and hasattr(phys, "update"):
phys.update(dt, trans)
e.update(dt)
def draw(self, canvas, offset=(0, 0), scale=1.0):
offset_x, offset_y = offset
for e in self.entities:
trans = e.get("Transform")
sprite = e.get("Sprite")
if not trans or not sprite:
continue
x = (trans.x + offset_x) * scale
y = (trans.y + offset_y) * scale
w = sprite.w * scale
h = sprite.h * scale
color = sprite.color
if sprite.shape == "rect":
canvas.create_rectangle(x - w/2, y - h/2, x + w/2, y + h/2, fill=color, outline="")
else:
canvas.create_oval(x - w/2, y - h/2, x + w/2, y + h/2, fill=color, outline="")
def to_dict(self):
"""Serialize scene to dictionary format."""
return {"entities": [self._entity_to_dict(e) for e in self.entities]}
@staticmethod
def _entity_to_dict(entity):
"""Convert an entity and all its components to a dictionary."""
components = {}
for comp_name, comp_obj in entity.components.items():
if comp_obj is None:
continue
# Handle different component types
if isinstance(comp_obj, bool):
# For PlayerController and similar boolean flags
components[comp_name] = {"type": comp_name, "value": comp_obj}
elif hasattr(comp_obj, "to_dict") and callable(comp_obj.to_dict):
# For components with to_dict method
components[comp_name] = comp_obj.to_dict()
else:
# Fallback for other types
components[comp_name] = {"type": comp_name, "value": str(comp_obj)}
return {
"id": entity.id,
"name": entity.name,
"components": components
}
def save(self, path):
"""Save scene to JSON file."""
try:
with open(path, "w", encoding="utf-8") as f:
json.dump(self.to_dict(), f, indent=2)
except Exception as e:
raise Exception(f"Failed to save scene: {e}")
@staticmethod
def from_dict(d):
"""Deserialize scene from dictionary format."""
s = Scene()
for entity_data in d.get("entities", []):
entity = Scene._entity_from_dict(entity_data)
s.add_entity(entity)
return s
@staticmethod
def _entity_from_dict(entity_data):
"""Convert a dictionary to an entity with all its components."""
entity = Entity(entity_data.get("name", "Entity"))
entity.id = entity_data.get("id", entity.id)
components = entity_data.get("components", {})
for comp_name, comp_data in components.items():
if not isinstance(comp_data, dict):
continue
comp_type = comp_data.get("type", comp_name)
# Deserialize based on component type
if comp_type == "Transform":
component = Transform.from_dict(comp_data)
entity.add_component("Transform", component)
elif comp_type == "Sprite":
component = Sprite.from_dict(comp_data)
entity.add_component("Sprite", component)
elif comp_type == "Physics":
component = Physics.from_dict(comp_data)
entity.add_component("Physics", component)
elif comp_type == "PlayerController":
# Handle PlayerController as a boolean flag
entity.add_component("PlayerController", comp_data.get("value", False))
else:
# Handle unknown component types gracefully
entity.add_component(comp_name, comp_data.get("value"))
return entity
@staticmethod
def load(path):
"""Load scene from JSON file."""
try:
with open(path, "r", encoding="utf-8") as f:
data = json.load(f)
return Scene.from_dict(data)
except Exception as e:
raise Exception(f"Failed to load scene: {e}")