Refactor engine and rendering system: move SDL2 logic to render.py, update entity/game structure, clean up unused files, and fix event handling. Major codebase reorganization for maintainability.
This commit is contained in:
+16
-16
@@ -28,10 +28,10 @@ class Marine(Entity):
|
||||
self.selected = True
|
||||
# Play a random voice response when selected
|
||||
sound_file = f"marine/tmawht0{random.randint(0, 3)}.wav"
|
||||
if not self.engine.cmd_sound_effects:
|
||||
if not self.game.cmd_sound_effects:
|
||||
self.graphics.play_sound(sound_file)
|
||||
self.engine.cmd_sound_effects = True
|
||||
|
||||
self.game.cmd_sound_effects = True
|
||||
|
||||
def move(self):
|
||||
# Aquisisci la posizione dell'unità
|
||||
self.iso_x, self.iso_y = self.graphics.iso_transform(self.x, self.y)
|
||||
@@ -98,23 +98,23 @@ class Marine(Entity):
|
||||
|
||||
# Verifica che le coordinate siano valide
|
||||
if not (0 <= y < map_height and 0 <= x < map_width):
|
||||
if not self.engine.cmd_sound_effects:
|
||||
self.engine.graphics.play_sound("sounds/perror.wav")
|
||||
self.engine.cmd_sound_effects = True
|
||||
if not self.game.cmd_sound_effects:
|
||||
self.graphics.play_sound("sounds/perror.wav")
|
||||
self.game.cmd_sound_effects = True
|
||||
return
|
||||
|
||||
# Ora puoi controllare il contenuto della cella in sicurezza
|
||||
if self.engine.map[y][x]["wall"]:
|
||||
if not self.engine.cmd_sound_effects:
|
||||
self.engine.graphics.play_sound("sounds/perror.wav")
|
||||
self.engine.cmd_sound_effects = True
|
||||
if not self.game.cmd_sound_effects:
|
||||
self.graphics.play_sound("sounds/perror.wav")
|
||||
self.game.cmd_sound_effects = True
|
||||
return
|
||||
|
||||
self.target_cell = target_cell
|
||||
if not self.engine.cmd_sound_effects:
|
||||
if not self.game.cmd_sound_effects:
|
||||
self.graphics.play_sound(f"marine/tmayes0{random.randint(0, 3)}.wav")
|
||||
self.engine.cmd_sound_effects = True
|
||||
|
||||
self.game.cmd_sound_effects = True
|
||||
|
||||
def cast_rays_to_distance(self, distance):
|
||||
# Cast rays to check for visibility
|
||||
done_cells = {}
|
||||
@@ -126,12 +126,12 @@ class Marine(Entity):
|
||||
v_x, v_y = self.graphics.inv_iso_transform(ray_x, ray_y)
|
||||
if v_x>= 0 and v_x < len(self.engine.map[0]) and v_y >= 0 and v_y < len(self.engine.map):
|
||||
if (v_x, v_y) not in done_cells.keys():
|
||||
done_cells.update({(v_x, v_y): self.engine.map_shadow[v_y][v_x]})
|
||||
done_cells.update({(v_x, v_y): self.game.map_shadow[v_y][v_x]})
|
||||
self.engine.map[v_y][v_x]["visited"] = True
|
||||
self.engine.map_shadow[v_y][v_x] = 0
|
||||
self.game.map_shadow[v_y][v_x] = 0
|
||||
if i == 1:
|
||||
|
||||
self.engine.map_shadow[v_y][v_x] = max(done_cells.get((v_x, v_y), 0)-0.5, 0)
|
||||
|
||||
self.game.map_shadow[v_y][v_x] = max(done_cells.get((v_x, v_y), 0)-0.5, 0)
|
||||
print(done_cells.get((v_x, v_y), 0))
|
||||
#self.graphics.draw_line((self.centered_position[0], self.centered_position[1], ray_x, ray_y), color=(0, 255, 0, 255))
|
||||
continue
|
||||
|
||||
+7
-6
@@ -1,8 +1,8 @@
|
||||
class Entity:
|
||||
def __init__(self, asset, x, y, action, direction, speed, engine):
|
||||
def __init__(self, asset, x, y, action, direction, speed, game):
|
||||
self.asset = asset
|
||||
|
||||
self.graphics = engine.graphics
|
||||
self.graphics = game.engine.graphics
|
||||
self.x = x
|
||||
self.y = y
|
||||
self.next_cell = (x, y)
|
||||
@@ -12,13 +12,14 @@ class Entity:
|
||||
self.direction = direction
|
||||
self.speed = speed
|
||||
self.frame = 0
|
||||
self.engine = engine
|
||||
self.game = game
|
||||
self.engine = game.engine
|
||||
self.selected = True
|
||||
self.movement = 0
|
||||
|
||||
def update(self):
|
||||
occlusion = self.graphics.get_distance((self.x, self.y), self.engine.cursor_pos) / 4
|
||||
|
||||
occlusion = self.graphics.get_distance((self.x, self.y), self.game.cursor_pos) / 4
|
||||
|
||||
# Set color based on selection status
|
||||
color = (0, 255, 0, 255)
|
||||
if self.selected:
|
||||
@@ -27,7 +28,7 @@ class Entity:
|
||||
# Draw target indicator if target is set
|
||||
|
||||
|
||||
occlusion = self.graphics.engine.map_shadow[self.y][self.x]
|
||||
occlusion = self.game.map_shadow[self.y][self.x]
|
||||
if occlusion >= 0.8:
|
||||
return
|
||||
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 79 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 929 KiB |
@@ -1,21 +0,0 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDdjCCAl6gAwIBAgIUO+7fPRqW/ZlLcjJc7abg7zY0dMswDQYJKoZIhvcNAQEL
|
||||
BQAwNTEOMAwGA1UECwwFV2F6dWgxDjAMBgNVBAoMBVdhenVoMRMwEQYDVQQHDApD
|
||||
YWxpZm9ybmlhMB4XDTI1MDQxOTE0NTQwM1oXDTM1MDQxNzE0NTQwM1owXDELMAkG
|
||||
A1UEBhMCVVMxEzARBgNVBAcMCkNhbGlmb3JuaWExDjAMBgNVBAoMBVdhenVoMQ4w
|
||||
DAYDVQQLDAVXYXp1aDEYMBYGA1UEAwwPd2F6dWguZGFzaGJvYXJkMIIBIjANBgkq
|
||||
hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvmIj4rPiA56NxFJDDjwMyE41wUzojw5X
|
||||
zfHOvvn22/G7I5pT7TKebFJcjMhLdj3oP2l3owYC/9SkwXD9S3nIkApLUMeg44LK
|
||||
LxuDdluneKa8hCm74zzZxP4D8lrSN4GBgCWB4D2UgOBEEBQXqD2bHp8Q/3JZHq44
|
||||
yRVEBYHRHNKNV8V+X/jwsRQX/AXxrZB5+88+E/qyWA20SFxHu+Ts4qBLbH5WN7sP
|
||||
i4ZeSYsWOjD4tarF2rCs+2BW08hinYh4gE+AzTlkhpz3AbwHpjx3W/LU1i3zr82T
|
||||
WvnDzfA89jmT3e+wYHk13b2JvAOFVW1TrEjo5B567Bq4WL3Ff7zoXwIDAQABo1cw
|
||||
VTAfBgNVHSMEGDAWgBTuFh2D9FW9b4yWpdSgKEgQi6ReHjAJBgNVHRMEAjAAMAsG
|
||||
A1UdDwQEAwIE8DAaBgNVHREEEzARgg93YXp1aC5kYXNoYm9hcmQwDQYJKoZIhvcN
|
||||
AQELBQADggEBAJyUnuD7Ss6hHtLlgugYLLKAGCiaTdlkSxzpzjRxka3hMqMVwSaQ
|
||||
XA+iUuxPZAFA3mMQX/jtgzD60CFJNK9lkHbh9n7uFCKqQwmQrFRwISdmoHI0M46B
|
||||
nJ6zUsarB7rovg1Mbdt1/1oFtRFq+AblnXlNh0IWrNL8U/kEzCeiR1f6DZZUqzTq
|
||||
UYmLLp3PVpL4U4TiUhExmpjSwrXrNt6Lus/tfP8ad0jVPBb728LhP0cbZlehRHH6
|
||||
8KjaSSwwgQ4p3yNC5puTbuSSFFgzbA7SawDkaH0KI4ZTSQHDPsmq2ZQpOXAeAJTC
|
||||
UXdyb7GGWuxsKjzzCcL2D90mZCsHlK3kjgM=
|
||||
-----END CERTIFICATE-----
|
||||
-21
@@ -1,21 +0,0 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDdjCCAl6gAwIBAgIUO+7fPRqW/ZlLcjJc7abg7zY0dMswDQYJKoZIhvcNAQEL
|
||||
BQAwNTEOMAwGA1UECwwFV2F6dWgxDjAMBgNVBAoMBVdhenVoMRMwEQYDVQQHDApD
|
||||
YWxpZm9ybmlhMB4XDTI1MDQxOTE0NTQwM1oXDTM1MDQxNzE0NTQwM1owXDELMAkG
|
||||
A1UEBhMCVVMxEzARBgNVBAcMCkNhbGlmb3JuaWExDjAMBgNVBAoMBVdhenVoMQ4w
|
||||
DAYDVQQLDAVXYXp1aDEYMBYGA1UEAwwPd2F6dWguZGFzaGJvYXJkMIIBIjANBgkq
|
||||
hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvmIj4rPiA56NxFJDDjwMyE41wUzojw5X
|
||||
zfHOvvn22/G7I5pT7TKebFJcjMhLdj3oP2l3owYC/9SkwXD9S3nIkApLUMeg44LK
|
||||
LxuDdluneKa8hCm74zzZxP4D8lrSN4GBgCWB4D2UgOBEEBQXqD2bHp8Q/3JZHq44
|
||||
yRVEBYHRHNKNV8V+X/jwsRQX/AXxrZB5+88+E/qyWA20SFxHu+Ts4qBLbH5WN7sP
|
||||
i4ZeSYsWOjD4tarF2rCs+2BW08hinYh4gE+AzTlkhpz3AbwHpjx3W/LU1i3zr82T
|
||||
WvnDzfA89jmT3e+wYHk13b2JvAOFVW1TrEjo5B567Bq4WL3Ff7zoXwIDAQABo1cw
|
||||
VTAfBgNVHSMEGDAWgBTuFh2D9FW9b4yWpdSgKEgQi6ReHjAJBgNVHRMEAjAAMAsG
|
||||
A1UdDwQEAwIE8DAaBgNVHREEEzARgg93YXp1aC5kYXNoYm9hcmQwDQYJKoZIhvcN
|
||||
AQELBQADggEBAJyUnuD7Ss6hHtLlgugYLLKAGCiaTdlkSxzpzjRxka3hMqMVwSaQ
|
||||
XA+iUuxPZAFA3mMQX/jtgzD60CFJNK9lkHbh9n7uFCKqQwmQrFRwISdmoHI0M46B
|
||||
nJ6zUsarB7rovg1Mbdt1/1oFtRFq+AblnXlNh0IWrNL8U/kEzCeiR1f6DZZUqzTq
|
||||
UYmLLp3PVpL4U4TiUhExmpjSwrXrNt6Lus/tfP8ad0jVPBb728LhP0cbZlehRHH6
|
||||
8KjaSSwwgQ4p3yNC5puTbuSSFFgzbA7SawDkaH0KI4ZTSQHDPsmq2ZQpOXAeAJTC
|
||||
UXdyb7GGWuxsKjzzCcL2D90mZCsHlK3kjgM=
|
||||
-----END CERTIFICATE-----
|
||||
@@ -16,7 +16,7 @@ class UserControls:
|
||||
def handle_events(self, mapping, event):
|
||||
if event.startswith("MOUSEMOTION"):
|
||||
x, y = event.split(":")[1:]
|
||||
self.set_cursor(int(x), int(y))
|
||||
self.game.set_cursor(int(x), int(y))
|
||||
if method := self.configs[mapping].get(event):
|
||||
getattr(self, method)()
|
||||
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
from enne2engine.render import SDL2Renderer
|
||||
from enne2engine.controls import UserControls
|
||||
import sys
|
||||
import os
|
||||
import json
|
||||
|
||||
|
||||
|
||||
class GameEngine(UserControls):
|
||||
def __init__(self, map, game):
|
||||
super().__init__()
|
||||
self.map = map
|
||||
self.game = game
|
||||
self.graphics = SDL2Renderer(self)
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
import pyglet
|
||||
from .tilemanager import TileManager
|
||||
|
||||
class PygletWrapper:
|
||||
def __init__(self):
|
||||
self.window = pyglet.window.Window(800, 600, "My Game")
|
||||
self.window.push_handlers(self)
|
||||
self.running = True
|
||||
|
||||
def on_draw(self):
|
||||
self.window.clear()
|
||||
# Render your game here
|
||||
|
||||
def on_close(self):
|
||||
self.running = False
|
||||
|
||||
def handle_events(self):
|
||||
pyglet.clock.tick()
|
||||
self.window.dispatch_events()
|
||||
return not self.running
|
||||
|
||||
def clear_screen(self, color=(0, 0, 0, 255)):
|
||||
pyglet.gl.glClearColor(color[0] / 255.0, color[1] / 255.0, color[2] / 255.0, color[3] / 255.0)
|
||||
self.window.clear()
|
||||
|
||||
def present_renderer(self):
|
||||
self.window.flip()
|
||||
|
||||
def quit(self):
|
||||
pyglet.app.exit()
|
||||
|
||||
def load_spritesheet(self, name, path):
|
||||
image = pyglet.image.load(path)
|
||||
self.spritesheets[name] = image
|
||||
self.tile_managers[name] = TileManager(path.replace('.png', '.xml'))
|
||||
|
||||
def render_sprite(self, name, x, y):
|
||||
sprite = pyglet.sprite.Sprite(self.spritesheets[name], x, y)
|
||||
sprite.draw()
|
||||
|
||||
def render_tile(self, spritesheet_name, tile_name, x, y):
|
||||
tile_rect = self.tile_managers[spritesheet_name].get_tile_rect(tile_name)
|
||||
if tile_rect is not None:
|
||||
image = self.spritesheets[spritesheet_name].get_region(*tile_rect)
|
||||
sprite = pyglet.sprite.Sprite(image, x, y)
|
||||
sprite.draw()
|
||||
@@ -8,10 +8,10 @@ import sdl2.ext
|
||||
import sdl2.sdlmixer as sdlmixer
|
||||
from .tilemanager import TileManager
|
||||
from .spritemanager import SpriteManager
|
||||
from .isogeometry import IsometricGeometry
|
||||
from .sdl2_utils.isogeometry import IsometricGeometry
|
||||
from .sdl2_utils.gui import SDL2Gui
|
||||
|
||||
class SDL2Wrapper(IsometricGeometry, SDL2Gui):
|
||||
class SDL2Renderer(IsometricGeometry, SDL2Gui):
|
||||
def __init__(self, engine):
|
||||
self.engine = engine
|
||||
sdl2.ext.init()
|
||||
@@ -56,9 +56,8 @@ class SDL2Gui:
|
||||
sprite = self.factory.from_text(text, color=sdl2.ext.Color(0, 0, 0), fontmanager=font)
|
||||
text_width, text_height = sprite.size
|
||||
self.renderer.fill((3, 3, text_width + 10, text_height + 4), sdl2.ext.Color(255, 255, 255))
|
||||
self.draw_text(text, font, (8, 5), sdl2.ext.Color(0, 0, 0))
|
||||
|
||||
|
||||
self.renderer.copy(sprite, dstrect=(5, 5))
|
||||
|
||||
def start_dialog(self, **kwargs):
|
||||
self.dialog("Welcome to the Mice!", subtitle="A game by Matteo because was bored", **kwargs)
|
||||
center = self.get_view_center()
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 36 KiB |
@@ -1,26 +1,14 @@
|
||||
from enne2engine.sdl2_wrapper import SDL2Wrapper
|
||||
from enne2engine.controls import UserControls
|
||||
import json
|
||||
import sys
|
||||
import os
|
||||
import json
|
||||
|
||||
from enne2engine import engine
|
||||
from Entities.Units.marine import Marine
|
||||
|
||||
|
||||
class GameEngine(UserControls):
|
||||
class Game:
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
||||
# Load map from JSON file
|
||||
try:
|
||||
with open("assets/maps/map.json", "r") as map_file:
|
||||
self.map = json.load(map_file)
|
||||
except (FileNotFoundError, json.JSONDecodeError) as e:
|
||||
print(f"Error loading map file: {e}")
|
||||
print("Exiting program.")
|
||||
sys.exit(0)
|
||||
|
||||
self.graphics = SDL2Wrapper(self)
|
||||
|
||||
self.engine = engine.GameEngine(self.load_map(), self)
|
||||
|
||||
self.frame_time = 0
|
||||
self.cursor_pos = (0, 0)
|
||||
|
||||
@@ -31,29 +19,29 @@ class GameEngine(UserControls):
|
||||
def run(self):
|
||||
running = True
|
||||
# Set a custom scale if needed
|
||||
self.graphics.set_scaling_factor(1.0) # 50% scale
|
||||
self.engine.graphics.set_scaling_factor(1.0) # 50% scale
|
||||
|
||||
self.entities.append(Marine("knight", 0, 0, "idle", 1, 1, self))
|
||||
self.entities.append(Marine("knight", 5, 5, "idle", 1, 1, self))
|
||||
#5 more marines
|
||||
self.entities.append(Marine("knight", 0, 5, "idle", 1, 1, self))
|
||||
self.entities.append(Marine("knight", 5, 5, "idle", 1, 1, self))
|
||||
self.entities.append(Marine("knight", 1,1, "idle", 1, 1, self))
|
||||
self.entities.append(Marine("knight", 2,2, "idle", 1, 1, self))
|
||||
self.entities.append(Marine("knight", 3,3, "idle", 1, 1, self))
|
||||
# self.entities.append(Marine("knight", 5, 5, "idle", 1, 1, self))
|
||||
# #5 more marines
|
||||
# self.entities.append(Marine("knight", 0, 5, "idle", 1, 1, self))
|
||||
# self.entities.append(Marine("knight", 5, 5, "idle", 1, 1, self))
|
||||
# self.entities.append(Marine("knight", 1,1, "idle", 1, 1, self))
|
||||
# self.entities.append(Marine("knight", 2,2, "idle", 1, 1, self))
|
||||
# self.entities.append(Marine("knight", 3,3, "idle", 1, 1, self))
|
||||
while running:
|
||||
self.cmd_sound_effects = False
|
||||
# Start the frame timer
|
||||
perf_counter = self.graphics.get_perf_counter()
|
||||
perf_counter = self.engine.graphics.get_perf_counter()
|
||||
# Initialize the map shadow and entities positions
|
||||
self.map_shadow = [ [1 for _ in range(len(self.map[0]))] for _ in range(len(self.map)) ]
|
||||
self.map_shadow = [ [1 for _ in range(len(self.engine.map[0]))] for _ in range(len(self.engine.map)) ]
|
||||
self.entities_positions.clear()
|
||||
for entity in self.entities:
|
||||
self.entities_positions[entity.next_cell] = entity
|
||||
self.entities_positions[(entity.x, entity.y)] = entity
|
||||
|
||||
# Handle events
|
||||
event = self.graphics.handle_events()
|
||||
event = self.engine.graphics.handle_events()
|
||||
if event:
|
||||
#print(f"Event detected: {event}")
|
||||
if event.startswith("MOUSEDOWN"):
|
||||
@@ -71,36 +59,36 @@ class GameEngine(UserControls):
|
||||
if event[-1] == "1":
|
||||
|
||||
self.select_entity_at_cursor()
|
||||
self.handle_events("keymap_game", event)
|
||||
self.engine.handle_events("keymap_game", event)
|
||||
|
||||
running = False if event == "QUIT" else True
|
||||
|
||||
self.graphics.clear_screen()
|
||||
self.engine.graphics.clear_screen()
|
||||
|
||||
for entity in self.entities:
|
||||
entity.update()
|
||||
# Create the map background texture with tiles
|
||||
self.graphics.create_background(self.map, "tiles", self.map_shadow)
|
||||
self.cursor_pos = self.graphics.draw_cursor()
|
||||
self.engine.graphics.create_background(self.engine.map, "tiles", self.map_shadow)
|
||||
self.cursor_pos = self.engine.graphics.draw_cursor()
|
||||
|
||||
self.graphics.render_background()
|
||||
self.graphics.render_sprites()
|
||||
self.graphics.draw_selection_rectangle()
|
||||
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()
|
||||
self.engine.graphics.render_background()
|
||||
self.engine.graphics.render_sprites()
|
||||
self.engine.graphics.draw_selection_rectangle()
|
||||
self.engine.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.engine.graphics.present_renderer()
|
||||
self.frame_time = self.engine.graphics.get_frame_time(perf_counter)
|
||||
self.engine.graphics.delay_frame(self.frame_time,50)
|
||||
self.engine.graphics.quit()
|
||||
|
||||
def set_cursor(self, x, y):
|
||||
self.graphics.cursor = (x, y)
|
||||
self.engine.graphics.cursor = (x, y)
|
||||
|
||||
def load_assets(self):
|
||||
self.graphics.load_tilesheet("tiles", "assets/tiles/landscapeTiles_sheet.png")
|
||||
self.engine.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}")
|
||||
self.engine.graphics.load_spritesheet(file[:-5].lower(), f"assets/KnightBasic/{dir}/{file}")
|
||||
|
||||
def select_entity_at_cursor(self):
|
||||
cursor_x, cursor_y = self.cursor_pos
|
||||
@@ -136,13 +124,23 @@ class GameEngine(UserControls):
|
||||
# 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)
|
||||
screen_x, screen_y = self.engine.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}")
|
||||
|
||||
def load_map(self):
|
||||
# Load map from JSON file
|
||||
try:
|
||||
with open("assets/maps/map.json", "r") as map_file:
|
||||
return json.load(map_file)
|
||||
except (FileNotFoundError, json.JSONDecodeError) as e:
|
||||
print(f"Error loading map file: {e}")
|
||||
print("Exiting program.")
|
||||
sys.exit(0)
|
||||
|
||||
if __name__ == "__main__":
|
||||
engine = GameEngine()
|
||||
engine.run()
|
||||
game = Game()
|
||||
game.run()
|
||||
@@ -0,0 +1,2 @@
|
||||
pysdl2
|
||||
Pillow
|
||||
@@ -1,62 +0,0 @@
|
||||
from PIL import ImageOps, Image, ImageFilter
|
||||
|
||||
FG_IMG_PATH = "fg.png"
|
||||
|
||||
BG_IMG_PATH = "bg.jpeg"
|
||||
|
||||
def load_image(path):
|
||||
|
||||
"""Load an image using PIL."""
|
||||
|
||||
return Image.open(path)
|
||||
|
||||
def extract_alpha(image):
|
||||
|
||||
"""Extract the alpha channel from an image."""
|
||||
|
||||
return image.split()[-1]
|
||||
|
||||
def create_shadow_from_alpha(alpha, blur_radius):
|
||||
|
||||
"""Create a shadow based on a blurred version of the alpha channel."""
|
||||
|
||||
alpha_blur = alpha.filter(ImageFilter.BoxBlur(blur_radius))
|
||||
|
||||
shadow = Image.new(mode="RGB", size=alpha_blur.size)
|
||||
|
||||
shadow.putalpha(alpha_blur)
|
||||
|
||||
return shadow
|
||||
|
||||
def composite_images(fg, shadow):
|
||||
|
||||
"""Composite the shadow and foreground onto the background."""
|
||||
|
||||
shadow.paste(fg, (-5, 4), fg)
|
||||
|
||||
return shadow
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
|
||||
# Load the images
|
||||
|
||||
fg = load_image(FG_IMG_PATH)
|
||||
|
||||
# Create the shadow based on the alpha channel of the foreground
|
||||
|
||||
alpha = extract_alpha(fg)
|
||||
|
||||
shadow = create_shadow_from_alpha(alpha, blur_radius=1)
|
||||
|
||||
# Composite the shadow and foreground onto the background
|
||||
|
||||
final_image = composite_images(fg, shadow)
|
||||
|
||||
# Display the final image (optional)
|
||||
|
||||
final_image.show()
|
||||
|
||||
# Save the final image
|
||||
|
||||
final_image.save(f"final_image.png")
|
||||
@@ -1,35 +0,0 @@
|
||||
import sdl2
|
||||
import sdl2.ext
|
||||
|
||||
def run():
|
||||
sdl2.ext.init()
|
||||
window = sdl2.ext.Window("SDL2 Texture Example", size=(640, 480))
|
||||
renderer = sdl2.ext.Renderer(window)
|
||||
target_surface = sdl2.SDL_CreateRGBSurface(0, 640, 480, 32, 0, 0, 0, 0)
|
||||
# Crea texture target usando il metodo del renderer
|
||||
target_tex = sdl2.ext.Texture(renderer, surface=target_surface)
|
||||
|
||||
# Disegna sulla texture
|
||||
sdl2.SDL_SetRenderTarget(renderer.renderer, target_tex.tx)
|
||||
renderer.clear()
|
||||
square_rect = sdl2.SDL_Rect(270, 190, 100, 100)
|
||||
renderer.draw_rect([square_rect], sdl2.ext.Color(255, 0, 0))
|
||||
renderer.present()
|
||||
sdl2.SDL_SetRenderTarget(renderer.renderer, None)
|
||||
# Main loop
|
||||
running = True
|
||||
while running:
|
||||
for event in sdl2.ext.get_events():
|
||||
if event.type == sdl2.SDL_QUIT:
|
||||
running = False
|
||||
break
|
||||
|
||||
renderer.clear()
|
||||
renderer.copy(target_tex) # Ora usa l'oggetto Texture corretto
|
||||
renderer.present()
|
||||
sdl2.SDL_Delay(10)
|
||||
|
||||
sdl2.ext.quit()
|
||||
|
||||
if __name__ == "__main__":
|
||||
run()
|
||||
Reference in New Issue
Block a user