Created Basic Engine
This project is kind of a dead end.
This commit is contained in:
parent
e8db72e3f9
commit
ae733d164a
0
core/__init__.py
Normal file
0
core/__init__.py
Normal file
BIN
core/__pycache__/__init__.cpython-311.pyc
Normal file
BIN
core/__pycache__/__init__.cpython-311.pyc
Normal file
Binary file not shown.
BIN
core/__pycache__/input_handler.cpython-311.pyc
Normal file
BIN
core/__pycache__/input_handler.cpython-311.pyc
Normal file
Binary file not shown.
BIN
core/__pycache__/lua_api.cpython-311.pyc
Normal file
BIN
core/__pycache__/lua_api.cpython-311.pyc
Normal file
Binary file not shown.
BIN
core/__pycache__/renderer.cpython-311.pyc
Normal file
BIN
core/__pycache__/renderer.cpython-311.pyc
Normal file
Binary file not shown.
15
core/input_handler.py
Normal file
15
core/input_handler.py
Normal file
@ -0,0 +1,15 @@
|
||||
# engine/input_handler.py
|
||||
import pygame
|
||||
|
||||
class InputHandler:
|
||||
def __init__(self):
|
||||
self.keys = {}
|
||||
|
||||
def process_event(self, event):
|
||||
if event.type == pygame.KEYDOWN:
|
||||
self.keys[event.key] = True
|
||||
elif event.type == pygame.KEYUP:
|
||||
self.keys[event.key] = False
|
||||
|
||||
def is_key_pressed(self, key):
|
||||
return self.keys.get(key, False)
|
64
core/lua_api.py
Normal file
64
core/lua_api.py
Normal file
@ -0,0 +1,64 @@
|
||||
# engine/lua_api.py
|
||||
import pygame
|
||||
|
||||
class LuaAPI:
|
||||
def __init__(self, renderer, input_handler):
|
||||
self.renderer = renderer
|
||||
self.input_handler = input_handler
|
||||
|
||||
def get_api(self, lua):
|
||||
# Expose functions to Lua
|
||||
lua.globals()['cls'] = self.cls
|
||||
lua.globals()['px'] = self.px
|
||||
lua.globals()['spr'] = self.spr
|
||||
lua.globals()['btn'] = self.btn
|
||||
|
||||
def cls(self, color=0):
|
||||
self.renderer.clear(color)
|
||||
|
||||
def px(self, x, y, color=1):
|
||||
self.renderer.draw_pixel(x, y, color)
|
||||
|
||||
def spr(self, x, y, sprite, color=1):
|
||||
"""
|
||||
Draws a sprite at position (x, y).
|
||||
|
||||
:param x: X-coordinate
|
||||
:param y: Y-coordinate
|
||||
:param sprite: 2D list representing the sprite
|
||||
:param color: Color index
|
||||
"""
|
||||
# Convert Lua table to Python list if necessary
|
||||
if hasattr(sprite, 'keys'):
|
||||
# If sprite is a Lua table, convert it to a Python list
|
||||
sprite = [sprite[i + 1] for i in range(len(sprite))]
|
||||
self.renderer.draw_sprite(x, y, sprite, color)
|
||||
|
||||
def btn(self, button):
|
||||
"""
|
||||
Checks if a specific button is pressed.
|
||||
|
||||
Button Mapping:
|
||||
0: Left Arrow
|
||||
1: Right Arrow
|
||||
2: Up Arrow
|
||||
3: Down Arrow
|
||||
4: Z (Button A)
|
||||
5: X (Button B)
|
||||
|
||||
:param button: Button index
|
||||
:return: Boolean indicating if the button is pressed
|
||||
"""
|
||||
# Map button indices to Pygame keys
|
||||
key_map = {
|
||||
0: pygame.K_LEFT,
|
||||
1: pygame.K_RIGHT,
|
||||
2: pygame.K_UP,
|
||||
3: pygame.K_DOWN,
|
||||
4: pygame.K_z, # Button A
|
||||
5: pygame.K_x, # Button B
|
||||
}
|
||||
key = key_map.get(button)
|
||||
if key:
|
||||
return self.input_handler.is_key_pressed(key)
|
||||
return False
|
50
core/renderer.py
Normal file
50
core/renderer.py
Normal file
@ -0,0 +1,50 @@
|
||||
# engine/renderer.py
|
||||
import pygame
|
||||
|
||||
class Renderer:
|
||||
def __init__(self, surface):
|
||||
self.surface = surface
|
||||
# Define a simple 8-bit palette (e.g., NES palette)
|
||||
self.palette = [
|
||||
(84, 84, 84), # Color 0
|
||||
(0, 30, 116), # Color 1
|
||||
(8, 16, 144), # Color 2
|
||||
(48, 0, 136), # Color 3
|
||||
(68, 0, 100), # Color 4
|
||||
(92, 0, 48), # Color 5
|
||||
(84, 4, 0), # Color 6
|
||||
(60, 24, 0), # Color 7
|
||||
(32, 42, 0), # Color 8
|
||||
(8, 58, 0), # Color 9
|
||||
(0, 64, 0), # Color 10
|
||||
(0, 60, 0), # Color 11
|
||||
(0, 50, 60), # Color 12
|
||||
(0, 0, 0), # Color 13
|
||||
(0, 0, 0), # Color 14
|
||||
(0, 0, 0), # Color 15
|
||||
]
|
||||
|
||||
def clear(self, color=0):
|
||||
if 0 <= color < len(self.palette):
|
||||
self.surface.fill(self.palette[color])
|
||||
else:
|
||||
self.surface.fill(self.palette[0]) # Default to background color
|
||||
|
||||
def draw_pixel(self, x, y, color_index):
|
||||
if 0 <= color_index < len(self.palette):
|
||||
if 0 <= x < self.surface.get_width() and 0 <= y < self.surface.get_height():
|
||||
self.surface.set_at((int(x), int(y)), self.palette[color_index])
|
||||
|
||||
def draw_sprite(self, x, y, sprite, color_index=1):
|
||||
"""
|
||||
Draws a sprite at position (x, y).
|
||||
|
||||
:param x: X-coordinate
|
||||
:param y: Y-coordinate
|
||||
:param sprite: 2D list representing the sprite
|
||||
:param color_index: Color index to use for the sprite
|
||||
"""
|
||||
for row_idx, row in enumerate(sprite):
|
||||
for col_idx, pixel in enumerate(row):
|
||||
if pixel:
|
||||
self.draw_pixel(x + col_idx, y + row_idx, color_index)
|
89
main.py
Normal file
89
main.py
Normal file
@ -0,0 +1,89 @@
|
||||
# main.py
|
||||
import pygame
|
||||
from core.lua_api import LuaAPI
|
||||
from core.renderer import Renderer
|
||||
from core.input_handler import InputHandler
|
||||
from lupa import LuaRuntime
|
||||
import os
|
||||
import sys
|
||||
|
||||
# Constants for 8-bit style
|
||||
SCREEN_WIDTH = 160
|
||||
SCREEN_HEIGHT = 144
|
||||
SCALE_FACTOR = 5 # Scale up for visibility
|
||||
FPS = 60
|
||||
|
||||
def main():
|
||||
pygame.init()
|
||||
pygame.display.set_caption("8-Bit Python Engine")
|
||||
window = pygame.display.set_mode((SCREEN_WIDTH * SCALE_FACTOR, SCREEN_HEIGHT * SCALE_FACTOR))
|
||||
clock = pygame.time.Clock()
|
||||
|
||||
# Create a surface for the 8-bit display
|
||||
display_surface = pygame.Surface((SCREEN_WIDTH, SCREEN_HEIGHT))
|
||||
|
||||
# Initialize components
|
||||
renderer = Renderer(display_surface)
|
||||
input_handler = InputHandler()
|
||||
lua = LuaRuntime(unpack_returned_tuples=True)
|
||||
api = LuaAPI(renderer, input_handler)
|
||||
api.get_api(lua) # Expose API to Lua
|
||||
|
||||
# Load Lua game script
|
||||
script_path = os.path.join("scripts", "game.lua")
|
||||
if not os.path.exists(script_path):
|
||||
print(f"Error: Lua script '{script_path}' not found.")
|
||||
pygame.quit()
|
||||
sys.exit(1)
|
||||
|
||||
with open(script_path, "r") as f:
|
||||
lua_script = f.read()
|
||||
|
||||
try:
|
||||
lua.execute(lua_script)
|
||||
except Exception as e:
|
||||
print(f"Error executing Lua script: {e}")
|
||||
pygame.quit()
|
||||
sys.exit(1)
|
||||
|
||||
# Retrieve update and draw functions from Lua
|
||||
lua_globals = lua.globals()
|
||||
if not hasattr(lua_globals, 'update') or not hasattr(lua_globals, 'draw'):
|
||||
print("Error: Lua script must define 'update' and 'draw' functions.")
|
||||
pygame.quit()
|
||||
sys.exit(1)
|
||||
|
||||
update = lua_globals.update
|
||||
draw = lua_globals.draw
|
||||
|
||||
running = True
|
||||
while running:
|
||||
delta_time = clock.tick(FPS) / 1000.0 # Seconds since last frame
|
||||
|
||||
for event in pygame.event.get():
|
||||
if event.type == pygame.QUIT:
|
||||
running = False
|
||||
input_handler.process_event(event)
|
||||
|
||||
try:
|
||||
# Update game logic via Lua
|
||||
update(delta_time)
|
||||
|
||||
# Clear the display
|
||||
renderer.clear()
|
||||
|
||||
# Draw game elements via Lua
|
||||
draw()
|
||||
except Exception as e:
|
||||
print(f"Error during Lua execution: {e}")
|
||||
running = False
|
||||
|
||||
# Scale and blit to the window
|
||||
scaled_surface = pygame.transform.scale(display_surface, (SCREEN_WIDTH * SCALE_FACTOR, SCREEN_HEIGHT * SCALE_FACTOR))
|
||||
window.blit(scaled_surface, (0, 0))
|
||||
pygame.display.flip()
|
||||
|
||||
pygame.quit()
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
70
scripts/game.lua
Normal file
70
scripts/game.lua
Normal file
@ -0,0 +1,70 @@
|
||||
-- scripts/game.lua
|
||||
|
||||
-- Define a simple sprite (e.g., 8x8 pixel player)
|
||||
player_sprite = {
|
||||
{0,1,1,0,0,1,1,0},
|
||||
{1,0,0,1,1,0,0,1},
|
||||
{1,0,0,1,1,0,0,1},
|
||||
{0,1,1,0,0,1,1,0},
|
||||
{0,1,1,0,0,1,1,0},
|
||||
{1,0,0,1,1,0,0,1},
|
||||
{1,0,0,1,1,0,0,1},
|
||||
{0,1,1,0,0,1,1,0},
|
||||
}
|
||||
|
||||
-- Define a simple enemy sprite
|
||||
enemy_sprite = {
|
||||
{2,2,2,2,2,2,2,2},
|
||||
{2,0,0,0,0,0,0,2},
|
||||
{2,0,2,2,2,2,0,2},
|
||||
{2,0,2,0,0,2,0,2},
|
||||
{2,0,2,2,2,2,0,2},
|
||||
{2,0,0,0,0,0,0,2},
|
||||
{2,2,2,2,2,2,2,2},
|
||||
{0,0,0,0,0,0,0,0},
|
||||
}
|
||||
|
||||
player_x = 72
|
||||
player_y = 68
|
||||
player_speed = 60 -- pixels per second
|
||||
|
||||
enemy_x = 40
|
||||
enemy_y = 40
|
||||
enemy_speed = 30 -- pixels per second
|
||||
|
||||
function update(dt)
|
||||
-- Player Movement
|
||||
if btn(0) then -- Left
|
||||
player_x = player_x - player_speed * dt
|
||||
end
|
||||
if btn(1) then -- Right
|
||||
player_x = player_x + player_speed * dt
|
||||
end
|
||||
if btn(2) then -- Up
|
||||
player_y = player_y - player_speed * dt
|
||||
end
|
||||
if btn(3) then -- Down
|
||||
player_y = player_y + player_speed * dt
|
||||
end
|
||||
|
||||
-- Enemy Movement: simple back and forth
|
||||
enemy_x = enemy_x + enemy_speed * dt
|
||||
if enemy_x > 120 then
|
||||
enemy_speed = -enemy_speed
|
||||
elseif enemy_x < 40 then
|
||||
enemy_speed = -enemy_speed
|
||||
end
|
||||
end
|
||||
|
||||
function draw()
|
||||
-- Draw Player
|
||||
spr(math.floor(player_x), math.floor(player_y), player_sprite, 11)
|
||||
|
||||
-- Draw Enemy
|
||||
spr(math.floor(enemy_x), math.floor(enemy_y), enemy_sprite, 9)
|
||||
|
||||
-- Draw some pixels as obstacles or decorations
|
||||
px(80, 72, 5)
|
||||
px(81, 72, 5)
|
||||
px(82, 72, 5)
|
||||
end
|
Loading…
Reference in New Issue
Block a user