Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"python-envs.pythonProjects": [],
"python-envs.defaultEnvManager": "ms-python.python:system"
}
1 change: 0 additions & 1 deletion src/freegames/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
import os
import runpy


def game_file(name):
"""Return True if filename represents a game."""
return (
Expand Down
1 change: 0 additions & 1 deletion src/freegames/ant.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ def wrap(value):
"""Wrap value around -200 and 200."""
return value # TODO


def draw():
"""Move ant and draw screen."""
ant.move(aim)
Expand Down
98 changes: 98 additions & 0 deletions src/freegames/custom_file_format.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import struct
import pygame
import io
import sys

class DaychIO:
"""
A utility class for the .daych custom image format.
Designed for high-performance Pygame surface manipulation.
"""
HEADER_FORMAT = "!5sBHHB" # Sig(5), Ver(1), W(2), H(2), BPP(1)
HEADER_SIZE = struct.calcsize(HEADER_FORMAT)
SIGNATURE = b"DAYCH"

@staticmethod
def load_surface(source):
"""
Decodes .daych data from a file path or BytesIO buffer into a pygame.Surface.
"""
is_path = isinstance(source, (str, bytes))
f = open(source, 'rb') if is_path else source

try:
header_bytes = f.read(DaychIO.HEADER_SIZE)
if len(header_bytes) < DaychIO.HEADER_SIZE:
raise ValueError("Invalid Header: Data truncated.")

sig, ver, w, h, bpp = struct.unpack(DaychIO.HEADER_FORMAT, header_bytes)

if sig != DaychIO.SIGNATURE:
raise ValueError(f"Signature mismatch: Expected {DaychIO.SIGNATURE}, got {sig}")

pixel_data = f.read()
# Directly convert raw bytes to Surface (Efficient RAM usage)
return pygame.image.frombytes(pixel_data, (w, h), "RGB")

finally:
if is_path:
f.close()

@staticmethod
def save_surface(surface, filename):
"""
Encodes a pygame.Surface into a .daych file on disk.
"""
width, height = surface.get_size()
# Extract raw RGB data from the surface
pixel_data = pygame.image.tostring(surface, "RGB")

header = struct.pack(DaychIO.HEADER_FORMAT, DaychIO.SIGNATURE, 1, width, height, 24)

with open(filename, "wb") as f:
f.write(header + pixel_data)

@staticmethod
def to_buffer(surface):
"""
Encodes a pygame.Surface into a BytesIO buffer (RAM only).
"""
width, height = surface.get_size()
pixel_data = pygame.image.tostring(surface, "RGB")

buffer = io.BytesIO()
header = struct.pack(DaychIO.HEADER_FORMAT, DaychIO.SIGNATURE, 1, width, height, 24)
buffer.write(header + pixel_data)
buffer.seek(0)
return buffer

# --- Demo/Test Logic ---
def run_demo():
pygame.init()
screen = pygame.display.set_mode((400, 400))
pygame.display.set_caption("DAYCH Format Engine")

# 1. Create a surface manually (Simulating an Aseprite export or game icon)
test_surf = pygame.Surface((32, 32))
test_surf.fill((255, 100, 0)) # Orange pixel art base
pygame.draw.rect(test_surf, (255, 255, 255), (8, 8, 16, 16)) # White center

# 2. Save to RAM and reload (The "No SSD wear" method)
mem_file = DaychIO.to_buffer(test_surf)
loaded_surf = DaychIO.load_surface(mem_file)

# 3. Scale it up so we can see the pixels (Aseprite style!)
display_surf = pygame.transform.scale(loaded_surf, (128, 128))

while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()

screen.fill((20, 20, 25)) # Professional dark theme
screen.blit(display_surf, (136, 136))
pygame.display.flip()

if __name__ == "__main__":
run_demo()
40 changes: 40 additions & 0 deletions src/freegames/turtle_race.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
from turtle import *
from random import randint

def set_race():
"""Start from top left"""
setup(420, 420, 370, 0)
speed(0)
penup()
goto(-140, 140)

"""Draw finish line"""
for step in range(15):
write(step, align="center")
right(90)
forward(10)
pendown()
forward(150)
penup()
backward(160)
left(90)
forward(20)

"""Set the colors of the players"""
colors = ["green", "red", "blue", "orange"]
all_turtles = []

"""Assign the colors"""
for i in range(len(colors)):
new_turtle = Turtle(shape="turtle")
new_turtle.color(colors[i])
new_turtle.penup()
new_turtle.goto(-160, 100 - (i * 30))
all_turtles.append(new_turtle)

"""Race players one by one"""
for t in all_turtles:
t.forward(randint(1, 5))

set_race()
done()