feat: add game loop with logging
This commit is contained in:
@@ -8,3 +8,5 @@ wheels/
|
|||||||
|
|
||||||
# Virtual environments
|
# Virtual environments
|
||||||
.venv
|
.venv
|
||||||
|
|
||||||
|
game_state.jsonl
|
||||||
|
|||||||
@@ -0,0 +1,151 @@
|
|||||||
|
import inspect
|
||||||
|
import json
|
||||||
|
import math
|
||||||
|
from datetime import datetime
|
||||||
|
from typing import NotRequired, TypedDict
|
||||||
|
|
||||||
|
|
||||||
|
class SpriteInfo(TypedDict):
|
||||||
|
type: str
|
||||||
|
pos: NotRequired[list[float]]
|
||||||
|
vel: NotRequired[list[float]]
|
||||||
|
rad: NotRequired[float]
|
||||||
|
rot: NotRequired[float]
|
||||||
|
|
||||||
|
|
||||||
|
class GroupInfo(TypedDict):
|
||||||
|
count: int
|
||||||
|
sprites: list[SpriteInfo]
|
||||||
|
|
||||||
|
|
||||||
|
__all__ = ["log_state", "log_event"]
|
||||||
|
|
||||||
|
_FPS = 60
|
||||||
|
_MAX_SECONDS = 16
|
||||||
|
_SPRITE_SAMPLE_LIMIT = 10
|
||||||
|
|
||||||
|
_frame_count = 0
|
||||||
|
_state_log_initialized = False
|
||||||
|
_event_log_initialized = False
|
||||||
|
_start_time = datetime.now()
|
||||||
|
|
||||||
|
|
||||||
|
def log_state() -> None:
|
||||||
|
global _frame_count, _state_log_initialized
|
||||||
|
|
||||||
|
if _frame_count > _FPS * _MAX_SECONDS:
|
||||||
|
return
|
||||||
|
|
||||||
|
_frame_count += 1
|
||||||
|
if _frame_count % _FPS != 0:
|
||||||
|
return
|
||||||
|
|
||||||
|
now = datetime.now()
|
||||||
|
|
||||||
|
frame = inspect.currentframe()
|
||||||
|
if frame is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
frame_back = frame.f_back
|
||||||
|
if frame_back is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
local_vars = frame_back.f_locals.copy()
|
||||||
|
|
||||||
|
screen_size: list[int] = []
|
||||||
|
game_state: dict[str, object] = {}
|
||||||
|
sprite_info: SpriteInfo
|
||||||
|
|
||||||
|
for key, value in local_vars.items():
|
||||||
|
if "pygame" in str(type(value)) and hasattr(value, "get_size"):
|
||||||
|
screen_size = list(value.get_size())
|
||||||
|
|
||||||
|
if hasattr(value, "__class__") and "Group" in value.__class__.__name__:
|
||||||
|
sprites_data: list[SpriteInfo] = []
|
||||||
|
|
||||||
|
for i, sprite in enumerate(value):
|
||||||
|
if i >= _SPRITE_SAMPLE_LIMIT:
|
||||||
|
break
|
||||||
|
|
||||||
|
sprite_info = {"type": sprite.__class__.__name__}
|
||||||
|
|
||||||
|
if hasattr(sprite, "position"):
|
||||||
|
sprite_info["pos"] = [
|
||||||
|
round(sprite.position.x, 2),
|
||||||
|
round(sprite.position.y, 2),
|
||||||
|
]
|
||||||
|
|
||||||
|
if hasattr(sprite, "velocity"):
|
||||||
|
sprite_info["vel"] = [
|
||||||
|
round(sprite.velocity.x, 2),
|
||||||
|
round(sprite.velocity.y, 2),
|
||||||
|
]
|
||||||
|
|
||||||
|
if hasattr(sprite, "radius"):
|
||||||
|
sprite_info["rad"] = sprite.radius
|
||||||
|
|
||||||
|
if hasattr(sprite, "rotation"):
|
||||||
|
sprite_info["rot"] = round(sprite.rotation, 2)
|
||||||
|
|
||||||
|
sprites_data.append(sprite_info)
|
||||||
|
|
||||||
|
group_info: GroupInfo = {"count": len(value), "sprites": sprites_data}
|
||||||
|
|
||||||
|
game_state[key] = group_info
|
||||||
|
|
||||||
|
if len(game_state) == 0 and hasattr(value, "position"):
|
||||||
|
sprite_info = {"type": value.__class__.__name__}
|
||||||
|
|
||||||
|
sprite_info["pos"] = [
|
||||||
|
round(value.position.x, 2),
|
||||||
|
round(value.position.y, 2),
|
||||||
|
]
|
||||||
|
|
||||||
|
if hasattr(value, "velocity"):
|
||||||
|
sprite_info["vel"] = [
|
||||||
|
round(value.velocity.x, 2),
|
||||||
|
round(value.velocity.y, 2),
|
||||||
|
]
|
||||||
|
|
||||||
|
if hasattr(value, "radius"):
|
||||||
|
sprite_info["rad"] = value.radius
|
||||||
|
|
||||||
|
if hasattr(value, "rotation"):
|
||||||
|
sprite_info["rot"] = round(value.rotation, 2)
|
||||||
|
|
||||||
|
game_state[key] = sprite_info
|
||||||
|
|
||||||
|
entry: dict[str, object] = {
|
||||||
|
"timestamp": now.strftime("%H:%M:%S.%f")[:-3],
|
||||||
|
"elapsed_s": math.floor((now - _start_time).total_seconds()),
|
||||||
|
"frame": _frame_count,
|
||||||
|
"screen_size": screen_size,
|
||||||
|
**game_state,
|
||||||
|
}
|
||||||
|
|
||||||
|
mode = "w" if not _state_log_initialized else "a"
|
||||||
|
|
||||||
|
with open("game_state.jsonl", mode) as f:
|
||||||
|
f.write(json.dumps(entry) + "\n")
|
||||||
|
|
||||||
|
_state_log_initialized = True
|
||||||
|
|
||||||
|
|
||||||
|
def log_event(event_type: str, **details: object) -> None:
|
||||||
|
global _event_log_initialized
|
||||||
|
|
||||||
|
now = datetime.now()
|
||||||
|
|
||||||
|
event: dict[str, object] = {
|
||||||
|
"timestamp": now.strftime("%H:%M:%S.%f")[:-3],
|
||||||
|
"elapsed_s": math.floor((now - _start_time).total_seconds()),
|
||||||
|
"frame": _frame_count,
|
||||||
|
"type": event_type,
|
||||||
|
**details,
|
||||||
|
}
|
||||||
|
|
||||||
|
mode = "w" if not _event_log_initialized else "a"
|
||||||
|
with open("game_events.jsonl", mode) as f:
|
||||||
|
f.write(json.dumps(event) + "\n")
|
||||||
|
|
||||||
|
_event_log_initialized = True
|
||||||
@@ -3,12 +3,25 @@
|
|||||||
import pygame
|
import pygame
|
||||||
|
|
||||||
from constants import SCREEN_HEIGHT, SCREEN_WIDTH
|
from constants import SCREEN_HEIGHT, SCREEN_WIDTH
|
||||||
|
from logger import log_state
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
"""Main method for asteroids game"""
|
"""Main method for asteroids game"""
|
||||||
print(f"Starting Asteroids with pygame version: {pygame.version.ver}")
|
print(f"Starting Asteroids with pygame version: {pygame.version.ver}")
|
||||||
print(f"Screen width: {SCREEN_WIDTH}")
|
print(f"Screen width: {SCREEN_WIDTH}")
|
||||||
print(f"Screen height: {SCREEN_HEIGHT}")
|
print(f"Screen height: {SCREEN_HEIGHT}")
|
||||||
|
pygame.init()
|
||||||
|
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
|
||||||
|
|
||||||
|
while True:
|
||||||
|
log_state()
|
||||||
|
|
||||||
|
for event in pygame.event.get():
|
||||||
|
if event.type == pygame.QUIT:
|
||||||
|
return
|
||||||
|
|
||||||
|
screen.fill("black")
|
||||||
|
pygame.display.flip()
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
|||||||
Reference in New Issue
Block a user