Refactor code structure for improved readability and maintainability
This commit is contained in:
+36
-2
@@ -1,2 +1,36 @@
|
||||
.venv
|
||||
__pycache__
|
||||
# Virtual Environment
|
||||
.venv/
|
||||
venv/
|
||||
ENV/
|
||||
|
||||
# Python cache files
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
.pytest_cache/
|
||||
|
||||
# Distribution / packaging
|
||||
dist/
|
||||
build/
|
||||
*.egg-info/
|
||||
*.egg
|
||||
|
||||
# IDE specific files
|
||||
.idea/
|
||||
.vscode/
|
||||
*.swp
|
||||
*.swo
|
||||
|
||||
# OS specific files
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
# Logs
|
||||
*.log
|
||||
logs/
|
||||
|
||||
# Local configuration
|
||||
.env
|
||||
.env.local
|
||||
*.local.py
|
||||
engine_demo
|
||||
@@ -0,0 +1,43 @@
|
||||
import random
|
||||
from Entities.entity import Entity
|
||||
|
||||
class Marine(Entity):
|
||||
|
||||
next_cell = (1,1)
|
||||
movement = 0
|
||||
|
||||
|
||||
def update(self):
|
||||
self.move()
|
||||
super().update()
|
||||
|
||||
def select_unit(self):
|
||||
self.selected = True
|
||||
# Play a random voice response when selected
|
||||
sound_file = f"marine/tmawht0{random.randint(0, 4)}.wav"
|
||||
print(f"Playing sound: {sound_file}")
|
||||
self.graphics.play_sound(sound_file)
|
||||
|
||||
def move(self):
|
||||
if (self.x, self.y) != self.next_cell:
|
||||
# Set walking animation and direction
|
||||
self.action = "walk"
|
||||
self.direction = self.graphics.get_direction((self.x, self.y), self.next_cell)
|
||||
self.moving = True
|
||||
|
||||
# Calculate target coordinates
|
||||
target_x, target_y = self.graphics.iso_transform(self.next_cell[0], self.next_cell[1])
|
||||
|
||||
# Increment movement counter
|
||||
self.movement += 0.01
|
||||
|
||||
# Calculate how far we've moved (0.0 to 1.0)
|
||||
move_progress = min(self.movement, 1.0)
|
||||
# Calculate new position based on progress between cells
|
||||
self.iso_x = self.iso_x + (target_x - self.iso_x) * move_progress
|
||||
self.iso_y = self.iso_y + (target_y - self.iso_y) * move_progress
|
||||
print(f"Moving to {self.iso_x}, {self.iso_y} with progress {move_progress}")
|
||||
if self.movement >= 1.0:
|
||||
# Reset movement and set to idle
|
||||
self.movement = 0
|
||||
self.iso_x, self.iso_y = self.graphics.iso_transform(self.x, self.y)
|
||||
@@ -2,21 +2,28 @@ class Entity:
|
||||
def __init__(self, asset, x, y, action, direction, speed, engine):
|
||||
self.asset = asset
|
||||
|
||||
self.graphics = engine.graphics
|
||||
self.x = x
|
||||
self.y = y
|
||||
self.iso_x, self.iso_y = self.graphics.iso_transform(self.x, self.y)
|
||||
self.action = action
|
||||
self.direction = direction
|
||||
self.speed = speed
|
||||
self.frame = 0
|
||||
self.graphics = engine.graphics
|
||||
self.engine = engine
|
||||
self.selected = True
|
||||
self.movement = 0
|
||||
|
||||
def update(self):
|
||||
x, y = self.graphics.iso_transform(self.x, self.y)
|
||||
occlusion = self.graphics.get_distance((self.x, self.y), self.engine.cursor_pos) / 4
|
||||
|
||||
# Set color based on selection status
|
||||
color = (255, 255, 0, 255) if self.selected else (0, 255, 0, 255)
|
||||
self.graphics.draw_square(self.x, self.y, color=color, margin=4)
|
||||
|
||||
if occlusion >= 0.8:
|
||||
return
|
||||
|
||||
self.frame = self.graphics.render_sprite(f"{self.asset}_{self.action}_dir{self.direction}", x,y, self.frame, occlusion)
|
||||
|
||||
|
||||
self.frame = self.graphics.render_sprite(f"{self.asset}_{self.action}_dir{self.direction}", self.iso_x, self.iso_y, self.frame, occlusion)
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+67
-27
@@ -3,8 +3,8 @@ from enne2engine.pyglet_wrapper import PygletWrapper
|
||||
from enne2engine.controls import UserControls
|
||||
import sys
|
||||
import os
|
||||
from Entities.Units.marine import Marine
|
||||
|
||||
from enne2engine.Entities.entity import Entity
|
||||
|
||||
class GameEngine(UserControls):
|
||||
def __init__(self):
|
||||
@@ -12,14 +12,14 @@ class GameEngine(UserControls):
|
||||
if "--pyglet" in sys.argv:
|
||||
self.graphics = PygletWrapper()
|
||||
else:
|
||||
self.graphics = SDL2Wrapper()
|
||||
self.graphics = SDL2Wrapper(self)
|
||||
self.map = [
|
||||
[{ 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }],
|
||||
[{ 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }],
|
||||
[{ 'wall': True, 'tile': "landscapeTiles_066" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': True, 'tile': "landscapeTiles_066" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }],
|
||||
[{ 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': True, 'tile': "landscapeTiles_066" }],
|
||||
[{ 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }],
|
||||
[{ 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }],
|
||||
[{ 'wall': False, 'tile': "landscapeTiles_001" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }],
|
||||
[{ 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }],
|
||||
[{ 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': True, 'tile': "landscapeTiles_066" }]
|
||||
]
|
||||
@@ -28,50 +28,51 @@ class GameEngine(UserControls):
|
||||
|
||||
self.load_assets()
|
||||
self.entities = []
|
||||
self.entities_positions = {}
|
||||
|
||||
def run(self):
|
||||
running = True
|
||||
self.entities.append(Entity("knight", 0, 0, "idle", 1, 1, self))
|
||||
self.graphics.create_background(self.map, "tiles")
|
||||
# Set a custom scale if needed
|
||||
self.graphics.set_scaling_factor(0.5) # 50% scale
|
||||
|
||||
self.entities.append(Marine("knight", 0, 0, "idle", 1, 1, self))
|
||||
self.graphics.create_background(self.map, "tiles")
|
||||
while running:
|
||||
perf_counter = self.graphics.get_perf_counter()
|
||||
for entity in self.entities:
|
||||
self.entities_positions[(entity.x, entity.y)] = entity
|
||||
self.graphics.create_background(self.map, "tiles")
|
||||
event = self.graphics.handle_events()
|
||||
if event:
|
||||
#print(f"Event detected: {event}")
|
||||
if event.startswith("MOUSEDOWN"):
|
||||
pass
|
||||
elif event.startswith("SELECTION"):
|
||||
# Handle multiple unit selection
|
||||
self.select_units_in_area(event)
|
||||
elif event.startswith("MOUSEUP"):
|
||||
self.select_entity_at_cursor()
|
||||
self.handle_events("keymap_game", event)
|
||||
running = False if event == "QUIT" else True
|
||||
self.graphics.clear_screen()
|
||||
self.render_background()
|
||||
self.graphics.render_background()
|
||||
#self.graphics.render_tile(spritesheet_name="tiles", tile="landscapeTiles_064", x=0, y=0)
|
||||
#self.graphics.draw_square(0,0)
|
||||
self.cursor_pos = self.graphics.draw_cursor()
|
||||
# Draw the selection rectangle if selecting
|
||||
if self.graphics.is_mouse_button_pressed(1):
|
||||
self.graphics.draw_selection_rectangle()
|
||||
for entity in self.entities:
|
||||
entity.update()
|
||||
self.graphics.render_sprites()
|
||||
self.graphics.update_status(f"Frame time: {round(self.frame_time)}ms - FPS: {round(1000/self.frame_time if self.frame_time != 0 else 1)}")
|
||||
self.graphics.present_renderer()
|
||||
self.frame_time = self.graphics.get_frame_time(perf_counter)
|
||||
self.graphics.delay_frame(self.frame_time,50)
|
||||
self.graphics.quit()
|
||||
def set_cursor(self, x, y):
|
||||
self.graphics.cursor = (x, y)
|
||||
|
||||
def render_background(self):
|
||||
for y, row in enumerate(self.map):
|
||||
for x, cell in enumerate(row):
|
||||
cell["occlusion"] = self.get_occlusion(x, y)
|
||||
if cell['occlusion']==1:
|
||||
continue
|
||||
self.graphics.render_tile("tiles", cell, x, y)
|
||||
|
||||
def get_occlusion(self, x, y):
|
||||
if (x, y) == self.cursor_pos:
|
||||
return 0
|
||||
distance = self.graphics.get_distance((x, y), self.cursor_pos)
|
||||
if distance <2:
|
||||
return 0.2
|
||||
elif distance < 3:
|
||||
return 0.5
|
||||
else:
|
||||
return 0.8
|
||||
|
||||
def set_cursor(self, x, y):
|
||||
self.graphics.cursor = (x, y)
|
||||
|
||||
def load_assets(self):
|
||||
self.graphics.load_tilesheet("tiles", "assets/tiles/landscapeTiles_sheet.png")
|
||||
@@ -80,7 +81,46 @@ class GameEngine(UserControls):
|
||||
if file.endswith(".json"):
|
||||
self.graphics.load_spritesheet(file[:-5].lower(), f"assets/KnightBasic/{dir}/{file}")
|
||||
|
||||
def select_entity_at_cursor(self):
|
||||
cursor_x, cursor_y = self.cursor_pos
|
||||
print(f"Cursor position: {cursor_x}, {cursor_y}")
|
||||
# First deselect all entities
|
||||
for entity in self.entities:
|
||||
entity.selected = False
|
||||
|
||||
# Then select the entity at cursor position, if any
|
||||
entity = self.entities_positions.get((cursor_x, cursor_y))
|
||||
if entity:
|
||||
entity.select_unit()
|
||||
print(f"Selected entity at cursor: {entity.asset} at position {entity.x}, {entity.y}")
|
||||
else:
|
||||
print("No entity selected at cursor position.")
|
||||
|
||||
def select_units_in_area(self, selection_event):
|
||||
"""Select all units within the specified selection area."""
|
||||
# Parse selection coordinates
|
||||
_, start_x, start_y, end_x, end_y = selection_event.split(":")
|
||||
start_x, start_y, end_x, end_y = int(start_x), int(start_y), int(end_x), int(end_y)
|
||||
|
||||
# Calculate selection rectangle in screen coordinates
|
||||
min_x = min(start_x, end_x)
|
||||
max_x = max(start_x, end_x)
|
||||
min_y = min(start_y, end_y)
|
||||
max_y = max(start_y, end_y)
|
||||
|
||||
# First deselect all entities
|
||||
for entity in self.entities:
|
||||
entity.selected = False
|
||||
|
||||
# Select entities within the rectangle
|
||||
for entity in self.entities:
|
||||
# Convert entity position to screen coordinates
|
||||
screen_x, screen_y = self.graphics.iso_transform(entity.x, entity.y)
|
||||
|
||||
# Check if entity is within selection rectangle
|
||||
if min_x <= screen_x <= max_x and min_y <= screen_y <= max_y:
|
||||
entity.select_unit()
|
||||
print(f"Selected entity in area: {entity.asset} at position {entity.x}, {entity.y}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
engine = GameEngine()
|
||||
|
||||
@@ -1,87 +0,0 @@
|
||||
from sdl2_wrapper import SDL2Wrapper
|
||||
from pyglet_wrapper import PygletWrapper
|
||||
from controls import UserControls
|
||||
import sys
|
||||
import os
|
||||
|
||||
from Entities.entity import Entity
|
||||
|
||||
class GameEngine(UserControls):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
if "--pyglet" in sys.argv:
|
||||
self.graphics = PygletWrapper()
|
||||
else:
|
||||
self.graphics = SDL2Wrapper()
|
||||
self.map = [
|
||||
[{ 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }],
|
||||
[{ 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }],
|
||||
[{ 'wall': True, 'tile': "landscapeTiles_066" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': True, 'tile': "landscapeTiles_066" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }],
|
||||
[{ 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': True, 'tile': "landscapeTiles_066" }],
|
||||
[{ 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }],
|
||||
[{ 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }],
|
||||
[{ 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }],
|
||||
[{ 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': False, 'tile': "landscapeTiles_067" }, { 'wall': True, 'tile': "landscapeTiles_066" }]
|
||||
]
|
||||
self.frame_time = 0
|
||||
self.cursor_pos = (0, 0)
|
||||
|
||||
self.load_assets()
|
||||
self.entities = []
|
||||
|
||||
def run(self):
|
||||
running = True
|
||||
self.graphics.create_background(self.map, "tiles")
|
||||
self.entities.append(Entity("knight", 0, 0, "idle", 1, 1, self))
|
||||
|
||||
while running:
|
||||
perf_counter = self.graphics.get_perf_counter()
|
||||
event = self.graphics.handle_events()
|
||||
if event:
|
||||
self.handle_events("keymap_game", event)
|
||||
running = False if event == "QUIT" else True
|
||||
self.graphics.clear_screen()
|
||||
self.graphics.render_background()
|
||||
self.cursor_pos = self.graphics.draw_cursor()
|
||||
for entity in self.entities:
|
||||
entity.update()
|
||||
self.graphics.update_status(f"Frame time: {round(self.frame_time)}ms - FPS: {round(1000/self.frame_time if self.frame_time != 0 else 1)}")
|
||||
self.graphics.present_renderer()
|
||||
self.frame_time = self.graphics.get_frame_time(perf_counter)
|
||||
self.graphics.delay_frame(self.frame_time,50)
|
||||
self.graphics.quit()
|
||||
def set_cursor(self, x, y):
|
||||
self.graphics.cursor = (x, y)
|
||||
|
||||
def render_background(self):
|
||||
for y, row in enumerate(self.map):
|
||||
for x, cell in enumerate(row):
|
||||
cell["occlusion"] = self.get_occlusion(x, y)
|
||||
if cell['occlusion']==1:
|
||||
continue
|
||||
self.graphics.render_tile("tiles", cell, x, y)
|
||||
|
||||
def get_occlusion(self, x, y):
|
||||
if (x, y) == self.cursor_pos:
|
||||
return 0
|
||||
distance = self.graphics.get_distance((x, y), self.cursor_pos)
|
||||
if distance <2:
|
||||
return 0.2
|
||||
elif distance < 3:
|
||||
return 0.5
|
||||
else:
|
||||
return 0.8
|
||||
|
||||
|
||||
def load_assets(self):
|
||||
self.graphics.load_tilesheet("tiles", "assets/tiles/landscapeTiles_sheet.png")
|
||||
for dir in os.listdir("assets/KnightBasic"):
|
||||
for file in os.listdir(f"assets/KnightBasic/{dir}"):
|
||||
if file.endswith(".json"):
|
||||
self.graphics.load_spritesheet(file[:-5].lower(), f"assets/KnightBasic/{dir}/{file}")
|
||||
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
engine = GameEngine()
|
||||
engine.run()
|
||||
@@ -83,8 +83,15 @@ class IsometricGeometry:
|
||||
return screen_x, screen_y
|
||||
|
||||
def inv_iso_transform(self, screen_x, screen_y):
|
||||
x = (2 * screen_y + screen_x - 2 * self.view_offset_x) // self.cell_size - 1
|
||||
y = (2 * screen_y - screen_x + 2 * self.view_offset_x) // self.cell_size
|
||||
# Adjust screen coordinates by removing view offsets
|
||||
adj_x = screen_x - self.view_offset_x
|
||||
adj_y = screen_y - self.view_offset_y
|
||||
|
||||
# Inverse isometric transformation formulas:
|
||||
# Convert adjusted screen coordinates back to grid/world coordinates
|
||||
x = (adj_x + 2 * adj_y) // self.cell_size
|
||||
y = (2 * adj_y - adj_x) // self.cell_size
|
||||
#print(f"adj_x: {adj_x}, adj_y: {adj_y}, x: {x}, y: {y}")
|
||||
return x, y
|
||||
|
||||
def get_distance(self, position1, position2):
|
||||
@@ -124,4 +131,4 @@ class IsometricGeometry:
|
||||
visited.add((nx, ny))
|
||||
steps += 1
|
||||
|
||||
return -1
|
||||
return -1
|
||||
+259
-69
@@ -1,22 +1,32 @@
|
||||
import random
|
||||
import math
|
||||
import os
|
||||
from math import sqrt
|
||||
import ctypes
|
||||
import sdl2
|
||||
import sdl2.ext
|
||||
import sdl2.sdlmixer as sdlmixer
|
||||
from .tilemanager import TileManager
|
||||
from .spritemanager import SpriteManager
|
||||
from .isogeometry import IsometricGeometry
|
||||
from .sdl2_utils.gui import SDL2Gui
|
||||
|
||||
class SDL2Wrapper(IsometricGeometry, SDL2Gui):
|
||||
def __init__(self):
|
||||
def __init__(self, engine):
|
||||
self.engine = engine
|
||||
sdl2.ext.init()
|
||||
# Initialize SDL2 mixer
|
||||
sdlmixer.Mix_Init(sdlmixer.MIX_INIT_OGG | sdlmixer.MIX_INIT_MP3)
|
||||
sdlmixer.Mix_OpenAudio(44100, sdlmixer.MIX_DEFAULT_FORMAT, 2, 1024)
|
||||
sdlmixer.Mix_AllocateChannels(16) # Allocate channels for multiple sounds
|
||||
|
||||
self.view_size = (800, 600)
|
||||
self.target_size = (800, 600)
|
||||
self.cell_size = 132
|
||||
self.view_offset_x = 400
|
||||
self.view_offset_y = 200
|
||||
self.base_cell_size = 132 # Original/base cell size
|
||||
self.scaling_factor = 0.5 # Default scaling factor (can be changed)
|
||||
self.cell_size = int(self.base_cell_size * self.scaling_factor) # Effective cell size
|
||||
self.view_offset_x = 0
|
||||
self.view_offset_y = 0
|
||||
self.surface_width = 0
|
||||
self.surface_height = 0
|
||||
self.window = sdl2.ext.Window("My Game", size=self.view_size)
|
||||
@@ -27,7 +37,21 @@ class SDL2Wrapper(IsometricGeometry, SDL2Gui):
|
||||
self.factory = sdl2.ext.SpriteFactory(renderer=self.renderer)
|
||||
self.fonts = self.generate_fonts("assets/decterm.ttf")
|
||||
self.cursor = (0, 0)
|
||||
|
||||
# Add selection rectangle tracking variables
|
||||
self.selection_start = None
|
||||
self.selection_current = None
|
||||
self.selecting = False
|
||||
self.tiles_texture = sdl2.SDL_CreateTexture(self.renderer.renderer,
|
||||
sdl2.SDL_PIXELFORMAT_RGBA8888,
|
||||
sdl2.SDL_TEXTUREACCESS_TARGET,
|
||||
self.view_size[0],
|
||||
self.view_size[1])
|
||||
self.sprite_texture = sdl2.SDL_CreateTexture(self.renderer.renderer,
|
||||
sdl2.SDL_PIXELFORMAT_RGBA8888,
|
||||
sdl2.SDL_TEXTUREACCESS_TARGET,
|
||||
self.view_size[0],
|
||||
self.view_size[1])
|
||||
sdl2.SDL_SetTextureBlendMode(self.sprite_texture, sdl2.SDL_BLENDMODE_BLEND)
|
||||
def get_perf_counter(self):
|
||||
return int(sdl2.SDL_GetPerformanceCounter())
|
||||
|
||||
@@ -43,10 +67,43 @@ class SDL2Wrapper(IsometricGeometry, SDL2Gui):
|
||||
return f"KEYDOWN:{key}".lower()
|
||||
elif event.type == sdl2.SDL_MOUSEMOTION:
|
||||
x, y = event.motion.x, event.motion.y
|
||||
# Update current selection point if dragging
|
||||
if self.selecting:
|
||||
self.selection_current = (x, y)
|
||||
return f"MOUSEMOTION:{x}:{y}"
|
||||
elif event.type == sdl2.SDL_MOUSEBUTTONDOWN:
|
||||
x, y = event.button.x, event.button.y
|
||||
# Left mouse button (button 1)
|
||||
if event.button.button == 1:
|
||||
self.selection_start = (x, y)
|
||||
self.selection_current = (x, y)
|
||||
self.selecting = True
|
||||
return f"MOUSEDOWN:{x}:{y}"
|
||||
elif event.type == sdl2.SDL_MOUSEBUTTONUP:
|
||||
x, y = event.button.x, event.button.y
|
||||
# Left mouse button (button 1)
|
||||
if event.button.button == 1:
|
||||
result = f"MOUSEUP:{x}:{y}"
|
||||
# Return the selection area if it's large enough and we were selecting
|
||||
if self.selecting and self.selection_start and self.get_selection_size() > 5:
|
||||
result = f"SELECTION:{self.selection_start[0]}:{self.selection_start[1]}:{x}:{y}"
|
||||
|
||||
# Always reset selection state on mouse up, regardless of selecting flag
|
||||
self.selecting = False
|
||||
self.selection_start = None
|
||||
self.selection_current = None
|
||||
return result
|
||||
return f"MOUSEUP:{x}:{y}"
|
||||
return False
|
||||
|
||||
def clear_screen(self, color=(0, 0, 0, 255)): # Aggiunto valore alfa di default
|
||||
sdl2.SDL_SetRenderDrawColor(self.renderer.sdlrenderer, *color)
|
||||
# Clear sprite texture with transparent color
|
||||
sdl2.SDL_SetRenderTarget(self.renderer.sdlrenderer, self.sprite_texture)
|
||||
sdl2.SDL_SetRenderDrawColor(self.renderer.sdlrenderer, 0, 0, 0, 0) # Transparent color (alpha=0)
|
||||
sdl2.SDL_RenderClear(self.renderer.sdlrenderer)
|
||||
sdl2.SDL_SetRenderTarget(self.renderer.sdlrenderer, None)
|
||||
# Return to main renderer with the specified color
|
||||
sdl2.SDL_SetRenderDrawColor(self.renderer.sdlrenderer, *color)
|
||||
sdl2.SDL_RenderClear(self.renderer.sdlrenderer)
|
||||
|
||||
@@ -54,12 +111,15 @@ class SDL2Wrapper(IsometricGeometry, SDL2Gui):
|
||||
sdl2.SDL_RenderPresent(self.renderer.sdlrenderer)
|
||||
|
||||
def quit(self):
|
||||
# Clean up mixer resources
|
||||
sdlmixer.Mix_CloseAudio()
|
||||
sdlmixer.Mix_Quit()
|
||||
sdl2.SDL_Quit()
|
||||
|
||||
def load_spritesheet(self, name, path):
|
||||
surface = sdl2.ext.load_image(path.replace('.json', '.png'))
|
||||
texture = sdl2.ext.Texture(self.renderer, surface)
|
||||
self.sprite_managers[name] = SpriteManager(path, surface, texture, self.cell_size)
|
||||
self.sprite_managers[name] = SpriteManager(path, surface, texture, self.base_cell_size)
|
||||
|
||||
def load_tilesheet(self, name, path):
|
||||
surface = sdl2.ext.load_image(path)
|
||||
@@ -72,81 +132,87 @@ class SDL2Wrapper(IsometricGeometry, SDL2Gui):
|
||||
|
||||
def render_sprite(self, name, x, y, frame, occlusion=0):
|
||||
srcrect, total_frames = self.sprite_managers[name].get_frame_rect(frame)
|
||||
x -= self.cell_size // 2
|
||||
y -= self.cell_size // 4
|
||||
if occlusion:
|
||||
original_color_mods_r_g_b_a = self.apply_texture_color_mdod(self.sprite_managers[name].spritesheet_texture, occlusion)
|
||||
sdl2.SDL_SetRenderTarget(self.renderer.sdlrenderer, self.sprite_texture)
|
||||
self.renderer.copy(self.sprite_managers[name].spritesheet_texture,
|
||||
dstrect=(x, y, self.cell_size, self.cell_size),
|
||||
srcrect=srcrect)
|
||||
if occlusion:
|
||||
sdl2.SDL_SetTextureColorMod(self.sprite_managers[name].spritesheet_texture.tx,
|
||||
*original_color_mods_r_g_b_a)
|
||||
return (frame + 1) % total_frames
|
||||
|
||||
def render_tile(self, spritesheet_name, cell, x, y):
|
||||
tile_name = cell.get('tile')
|
||||
occlusion = cell.get('occlusion', 0)
|
||||
texture = self.tile_managers[spritesheet_name].get_tilesheet_texture()
|
||||
tile_rect = self.tile_managers[spritesheet_name].get_tile_rect(tile_name)
|
||||
|
||||
if tile_rect is not None:
|
||||
iso_x, iso_y = self.iso_transform(x, y)
|
||||
y_offset = self.cell_size - tile_rect[3]
|
||||
dst_rect = (iso_x, iso_y + y_offset,
|
||||
tile_rect[2], tile_rect[3])
|
||||
|
||||
# Salva i valori originali dei moduli di colore
|
||||
original_color_mods_r_g_b_a = self.apply_texture_color_mdod(texture, occlusion)
|
||||
|
||||
# Copia la texture con il nuovo modulo di colore
|
||||
self.renderer.copy(self.tile_managers[spritesheet_name].get_tilesheet_texture(),
|
||||
sdl2.SDL_Rect(*tile_rect),
|
||||
sdl2.SDL_Rect(*dst_rect))
|
||||
|
||||
sdl2.SDL_SetTextureColorMod(texture.tx, *original_color_mods_r_g_b_a)
|
||||
|
||||
def render_tile_shadow(self, spritesheet_name, cell, x, y):
|
||||
tile_name = cell.get('tile')
|
||||
occlusion = cell.get('occlusion', 0)
|
||||
sdl2.SDL_SetRenderTarget(self.renderer.sdlrenderer, None)
|
||||
return (frame + 1) % total_frames
|
||||
|
||||
def create_background(self, map, spritesheet_name):
|
||||
self.surface_width = round(self.cell_size * len(map[0])*sqrt(2))
|
||||
self.surface_height = round(self.cell_size//2 * len(map)*sqrt(2))
|
||||
tilesheet_surface = self.tile_managers[spritesheet_name].get_tilesheet_surface()
|
||||
bg_surface = sdl2.SDL_CreateRGBSurface(0, self.surface_width, self.surface_height, 32, 0, 0, 0, 0)
|
||||
# Set page as render target and initialize it
|
||||
sdl2.SDL_SetRenderTarget(self.renderer.sdlrenderer, self.tiles_texture)
|
||||
sdl2.SDL_SetRenderDrawColor(self.renderer.sdlrenderer, 0, 0, 0, 255) # Green background
|
||||
sdl2.SDL_RenderClear(self.renderer.sdlrenderer)
|
||||
|
||||
tilesheet_texture = self.tile_managers[spritesheet_name].get_tilesheet_texture()
|
||||
|
||||
def get_shadow(x, y):
|
||||
if (x, y) == self.engine.cursor_pos:
|
||||
return 0
|
||||
distance = self.get_distance((x, y), self.engine.cursor_pos)
|
||||
if distance <2:
|
||||
self.engine.map[y][x]['visited'] = True
|
||||
return 0.2
|
||||
elif distance < 3:
|
||||
self.engine.map[y][x]['visited'] = True
|
||||
return 0.5
|
||||
else:
|
||||
if self.engine.map[y][x].get('visited', False):
|
||||
return 0.8
|
||||
else:
|
||||
return 1
|
||||
|
||||
def blit_tile(tile, x, y):
|
||||
tile_rect = self.tile_managers[spritesheet_name].get_tile_rect(tile)
|
||||
if tile_rect is not None:
|
||||
vertical_offset = self.cell_size - tile_rect[3]
|
||||
horizontal_offset = (self.cell_size - tile_rect[2])
|
||||
shadow = get_shadow(x, y)
|
||||
if shadow==1:
|
||||
return
|
||||
self.apply_texture_color_mdod(tilesheet_texture, shadow)
|
||||
|
||||
# Adjusted vertical offset calculation for half-sized cells
|
||||
vertical_offset = self.cell_size - tile_rect[3] // 2 - self.cell_size//4
|
||||
if vertical_offset < 0:
|
||||
vertical_offset = 0
|
||||
|
||||
# Adjusted horizontal offset calculation for half-sized cells
|
||||
horizontal_offset = (self.cell_size - tile_rect[2] // 2)
|
||||
|
||||
iso_x, iso_y = self.iso_transform(x, y)
|
||||
iso_y += vertical_offset
|
||||
iso_x += horizontal_offset
|
||||
iso_x += horizontal_offset - tile_rect[2] // 4 # Divided by 4 instead of 2
|
||||
|
||||
# Scale the actual tile rectangle based on the current scaling factor
|
||||
dst_rect = (iso_x, iso_y,
|
||||
tile_rect[2], tile_rect[3])
|
||||
sdl2.SDL_BlitSurface(tilesheet_surface,
|
||||
sdl2.SDL_Rect(*tile_rect),
|
||||
bg_surface,
|
||||
sdl2.SDL_Rect(*dst_rect))
|
||||
#sdl2.SDL_FillRect(bg_surface, sdl2.SDL_Rect(*dst_rect), sdl2.SDL_MapRGB(bg_surface.contents.format, 0, 0, 255))
|
||||
int(tile_rect[2] * self.scaling_factor),
|
||||
int(tile_rect[3] * self.scaling_factor))
|
||||
|
||||
sdl2.SDL_RenderCopy(self.renderer.sdlrenderer, tilesheet_texture.tx,
|
||||
sdl2.SDL_Rect(*tile_rect),
|
||||
sdl2.SDL_Rect(*dst_rect))
|
||||
|
||||
for y, row in enumerate(map):
|
||||
for x, cell in enumerate(row):
|
||||
tile_name = cell.get('tile')
|
||||
blit_tile(tile_name, x, y)
|
||||
|
||||
self.background_texture = self.factory.from_surface(bg_surface)
|
||||
self.apply_texture_color_mdod(self.background_texture, 0.8)
|
||||
# Reset render target to the default (window)
|
||||
sdl2.SDL_SetRenderTarget(self.renderer.sdlrenderer, None)
|
||||
|
||||
|
||||
def render_texture_to_texture(self, src_texture, dst_texture, srcrect, dstrect):
|
||||
self.renderer.copy(src_texture, srcrect, dstrect)
|
||||
|
||||
def render_background(self):
|
||||
self.renderer.copy(self.background_texture,
|
||||
dstrect=(0, 0, self.surface_width, self.surface_height),
|
||||
srcrect=(0,0, self.surface_width, self.surface_height))
|
||||
|
||||
sdl2.SDL_RenderCopy(self.renderer.sdlrenderer, self.tiles_texture, None, None)
|
||||
|
||||
def render_sprites(self):
|
||||
sdl2.SDL_RenderCopy(self.renderer.sdlrenderer, self.sprite_texture, None, None)
|
||||
|
||||
def get_frame_time(self, perf_counter):
|
||||
return (sdl2.SDL_GetPerformanceCounter() - perf_counter) / sdl2.SDL_GetPerformanceFrequency() *1000
|
||||
|
||||
@@ -160,17 +226,39 @@ class SDL2Wrapper(IsometricGeometry, SDL2Gui):
|
||||
|
||||
def draw_cursor(self):
|
||||
x, y = self.cursor
|
||||
x += self.view_offset_x
|
||||
y -= self.view_offset_y
|
||||
c_x, c_y = self.inv_iso_transform(x, y)
|
||||
#print(f"Cursor: {c_x}, {c_y}")
|
||||
iso_x, iso_y = self.iso_transform(c_x, c_y)
|
||||
iso_y += self.cell_size // 2
|
||||
self.renderer.draw_line(points=[(iso_x, iso_y), (iso_x + self.cell_size//2, iso_y + self.cell_size//4)], color=(255, 0, 0, 255))
|
||||
self.renderer.draw_line(points=[(iso_x + self.cell_size//2, iso_y + self.cell_size//4), (iso_x + self.cell_size, iso_y)], color=(255, 0, 0, 255))
|
||||
self.renderer.draw_line(points=[(iso_x + self.cell_size, iso_y), (iso_x + self.cell_size//2, iso_y - self.cell_size//4)], color=(255, 0, 0, 255))
|
||||
self.renderer.draw_line(points=[(iso_x + self.cell_size//2, iso_y - self.cell_size//4), (iso_x, iso_y)], color=(255, 0, 0, 255))
|
||||
self.renderer.draw_line(points=[(iso_x, iso_y), (iso_x + self.cell_size//2, iso_y + self.cell_size//4)], color=(255
|
||||
, 0, 0, 255))
|
||||
self.renderer.draw_line(points=[(iso_x + self.cell_size//2, iso_y + self.cell_size//4), (iso_x, iso_y + self.cell_size//2)], color=(255, 0, 0, 255))
|
||||
self.renderer.draw_line(points=[(iso_x, iso_y + self.cell_size//2), (iso_x - self.cell_size//2, iso_y + self.cell_size//4)], color=(255, 0, 0, 255))
|
||||
self.renderer.draw_line(points=[(iso_x - self.cell_size//2, iso_y + self.cell_size//4), (iso_x, iso_y)], color=(255, 0, 0, 255))
|
||||
return c_x, c_y
|
||||
|
||||
def draw_square(self, x, y, color=(0, 255, 0, 255), margin=6):
|
||||
sdl2.SDL_SetRenderTarget(self.renderer.sdlrenderer, self.sprite_texture)
|
||||
iso_x, iso_y = self.iso_transform(x, y)
|
||||
|
||||
# Apply margin to reduce the size of the square
|
||||
adjusted_size = self.cell_size - margin*2
|
||||
|
||||
# Calculate half-sizes with margin applied
|
||||
half_width = adjusted_size // 2
|
||||
half_height = adjusted_size // 4
|
||||
|
||||
# Draw an isometric square with margin
|
||||
self.renderer.draw_line(points=[(iso_x, iso_y + margin),
|
||||
(iso_x + half_width-margin, iso_y + half_height +margin//2)], color=color)
|
||||
self.renderer.draw_line(points=[(iso_x + half_width-margin, iso_y + half_height +margin//2),
|
||||
(iso_x, iso_y + half_height*2+margin//4)], color=color)
|
||||
self.renderer.draw_line(points=[(iso_x, iso_y + half_height*2+margin//4),
|
||||
(iso_x - half_width+margin, iso_y + half_height +margin//2)], color=color)
|
||||
self.renderer.draw_line(points=[(iso_x - half_width+margin, iso_y + half_height +margin//2),
|
||||
(iso_x, iso_y + margin)], color=color)
|
||||
|
||||
sdl2.SDL_SetRenderTarget(self.renderer.sdlrenderer, None)
|
||||
|
||||
def apply_texture_color_mdod(self, texture, occlusion):
|
||||
color_mod_r = int(255 * (1 - occlusion))
|
||||
color_mod_g = int(255 * (1 - occlusion))
|
||||
@@ -193,9 +281,111 @@ class SDL2Wrapper(IsometricGeometry, SDL2Gui):
|
||||
color_mod_b)
|
||||
return original_color_mods_r_g_b_a
|
||||
|
||||
def render_tile_shadow(self, x, y, darkness=0):
|
||||
iso_x, iso_y = self.iso_transform(x, y)
|
||||
iso_y += self.cell_size // 2
|
||||
self.renderer.copy(self.shadow_texture,
|
||||
dstrect=(iso_x, iso_y, self.cell_size, self.cell_size),
|
||||
srcrect=(0, 0, self.cell_size, self.cell_size))
|
||||
def render_tile(self, spritesheet_name, x, y, tile):
|
||||
tile_rect = self.tile_managers[spritesheet_name].get_tile_rect(tile)
|
||||
if tile_rect is not None:
|
||||
vertical_offset = self.cell_size - tile_rect[3]
|
||||
horizontal_offset = (self.cell_size - tile_rect[2])
|
||||
iso_x, iso_y = self.iso_transform(x, y)
|
||||
iso_y += vertical_offset - tile_rect[3]//4
|
||||
iso_x += horizontal_offset - tile_rect[2] // 2
|
||||
dst_rect = (iso_x, iso_y,
|
||||
tile_rect[2], tile_rect[3])
|
||||
sdl2.SDL_RenderCopy(self.renderer.sdlrenderer, self.tile_managers[spritesheet_name].get_tilesheet_texture().tx,
|
||||
sdl2.SDL_Rect(*tile_rect),
|
||||
sdl2.SDL_Rect(*dst_rect))
|
||||
|
||||
def set_scaling_factor(self, factor):
|
||||
"""
|
||||
Set a new scaling factor and recalculate cell_size.
|
||||
|
||||
Args:
|
||||
factor (float): The scaling factor (0.5 = half size, 1.0 = original size, etc.)
|
||||
"""
|
||||
self.scaling_factor = factor
|
||||
self.cell_size = int(self.base_cell_size * self.scaling_factor)
|
||||
# Regenerate background if needed
|
||||
if hasattr(self.engine, 'map'):
|
||||
self.create_background(self.engine.map, "tiles")
|
||||
|
||||
def play_sound(self, sound_file):
|
||||
"""
|
||||
Play a sound file using SDL2 mixer.
|
||||
|
||||
Args:
|
||||
sound_file (str): Name of the sound file to play
|
||||
"""
|
||||
sound_path = os.path.join("assets", "Sounds", sound_file)
|
||||
if os.path.exists(sound_path):
|
||||
sound = sdlmixer.Mix_LoadWAV(sound_path.encode('utf-8'))
|
||||
if sound:
|
||||
channel = sdlmixer.Mix_PlayChannel(-1, sound, 0)
|
||||
if channel == -1:
|
||||
print(f"Error playing sound: {sdlmixer.Mix_GetError().decode('utf-8')}")
|
||||
# Free the sound when finished (after a delay or in a callback)
|
||||
# For simplicity, we're not handling this here, but in a real app you might want to
|
||||
else:
|
||||
print(f"Sound file not found: {sound_path}")
|
||||
|
||||
def draw_selection_rectangle(self):
|
||||
"""Draw the selection rectangle if currently selecting."""
|
||||
# Only draw if we're in a valid selection state
|
||||
if not self.selecting or not self.selection_start or not self.selection_current:
|
||||
return
|
||||
|
||||
# Get coordinates for the rectangle
|
||||
start_x, start_y = self.selection_start
|
||||
current_x, current_y = self.selection_current
|
||||
|
||||
# Calculate the rectangle dimensions
|
||||
x = min(start_x, current_x)
|
||||
y = min(start_y, current_y)
|
||||
width = abs(current_x - start_x)
|
||||
height = abs(current_y - start_y)
|
||||
|
||||
# Only draw if we have a meaningful selection area
|
||||
if width > 1 and height > 1:
|
||||
# Draw an empty rectangle in green
|
||||
self.draw_rectangle(x, y, width, height, "selection", outline=(0, 255, 0), filling=None)
|
||||
|
||||
def get_selection_size(self):
|
||||
"""Get the size (diagonal length) of the selection rectangle."""
|
||||
if not self.selection_start or not self.selection_current:
|
||||
return 0
|
||||
|
||||
start_x, start_y = self.selection_start
|
||||
current_x, current_y = self.selection_current
|
||||
|
||||
# Calculate diagonal length using Pythagorean theorem
|
||||
dx = current_x - start_x
|
||||
dy = current_y - start_y
|
||||
return int(math.sqrt(dx*dx + dy*dy))
|
||||
|
||||
def is_mouse_button_pressed(self, button=1):
|
||||
"""
|
||||
Check if a specific mouse button is currently pressed.
|
||||
|
||||
Args:
|
||||
button (int): Button number (1=left, 2=middle, 3=right)
|
||||
|
||||
Returns:
|
||||
bool: True if the button is pressed, False otherwise
|
||||
"""
|
||||
# Create ctypes variables to store the mouse position
|
||||
x = ctypes.c_int(0)
|
||||
y = ctypes.c_int(0)
|
||||
|
||||
# Get the current mouse state (returns a bitmask of buttons)
|
||||
button_state = sdl2.SDL_GetMouseState(ctypes.byref(x), ctypes.byref(y))
|
||||
|
||||
# Map button numbers to SDL constants
|
||||
button_masks = {
|
||||
1: sdl2.SDL_BUTTON_LMASK, # Left button
|
||||
2: sdl2.SDL_BUTTON_MMASK, # Middle button
|
||||
3: sdl2.SDL_BUTTON_RMASK, # Right button
|
||||
}
|
||||
|
||||
# Check if the requested button is pressed
|
||||
if button in button_masks:
|
||||
return bool(button_state & button_masks[button])
|
||||
return False
|
||||
Reference in New Issue
Block a user