|
|
|
|
@ -54,6 +54,18 @@ class GameWindow:
|
|
|
|
|
self.running = True |
|
|
|
|
self.delay = 30 |
|
|
|
|
self.performance = 0 |
|
|
|
|
self.last_status_text = "" |
|
|
|
|
self.stats_sprite = None |
|
|
|
|
self.mean_fps = 0 |
|
|
|
|
self.fpss = [] |
|
|
|
|
self.text_width = 0 |
|
|
|
|
self.text_height = 0 |
|
|
|
|
self.ammo_text = "" |
|
|
|
|
|
|
|
|
|
# White flash effect state |
|
|
|
|
self.white_flash_active = False |
|
|
|
|
self.white_flash_start_time = 0 |
|
|
|
|
self.white_flash_opacity = 255 |
|
|
|
|
|
|
|
|
|
# Input handling |
|
|
|
|
self.key_down, self.key_up, self.axis_scroll = key_callback |
|
|
|
|
@ -151,7 +163,7 @@ class GameWindow:
|
|
|
|
|
"""Draw background texture with current view offset""" |
|
|
|
|
self.renderer.copy(bg_texture, dstrect=sdl2.SDL_Rect(self.w_offset, self.h_offset, self.width, self.height)) |
|
|
|
|
|
|
|
|
|
def draw_image(self, x, y, sprite, tag, anchor="nw"): |
|
|
|
|
def draw_image(self, x, y, sprite, tag=None, anchor="nw"): |
|
|
|
|
"""Draw an image sprite at specified coordinates""" |
|
|
|
|
if not self.is_in_visible_area(x, y): |
|
|
|
|
return |
|
|
|
|
@ -225,20 +237,50 @@ class GameWindow:
|
|
|
|
|
# TODO: Fix outline parameter usage |
|
|
|
|
color = (0, 0, 255) if self.button_cursor == list(coords) else (0, 0, 0) |
|
|
|
|
self.draw_rectangle(x, y, width, height, "button", outline=color) |
|
|
|
|
self.draw_text(text, self.fonts[20], (x + 10, y + 10), (0, 0, 0)) |
|
|
|
|
#self.draw_text(text, self.fonts[20], (x + 10, y + 10), (0, 0, 0)) |
|
|
|
|
|
|
|
|
|
def update_status(self, text): |
|
|
|
|
"""Update and display the status bar with FPS information""" |
|
|
|
|
fps = int(1000 / self.performance) if self.performance != 0 else 0 |
|
|
|
|
status_text = f"FPS: {fps} - {text}" |
|
|
|
|
font = self.fonts[20] |
|
|
|
|
sprite = self.factory.from_text(status_text, color=sdl2.ext.Color(0, 0, 0), fontmanager=font) |
|
|
|
|
text_width, text_height = sprite.size |
|
|
|
|
|
|
|
|
|
# Draw background for status text |
|
|
|
|
self.renderer.fill((3, 3, text_width + 10, text_height + 4), sdl2.ext.Color(255, 255, 255)) |
|
|
|
|
self.draw_text(status_text, font, (8, 5), sdl2.ext.Color(0, 0, 0)) |
|
|
|
|
|
|
|
|
|
# at 10% of probability print fps |
|
|
|
|
if len(self.fpss) > 20: |
|
|
|
|
self.mean_fps = round(sum(self.fpss) / len(self.fpss)) if self.fpss else fps |
|
|
|
|
#print(f"FPS: {self.mean_fps}") |
|
|
|
|
self.fpss.clear() |
|
|
|
|
else: |
|
|
|
|
self.fpss.append(fps) |
|
|
|
|
|
|
|
|
|
status_text = f"FPS: {self.mean_fps} - {text}" |
|
|
|
|
if status_text != self.last_status_text: |
|
|
|
|
self.last_status_text = status_text |
|
|
|
|
font = self.fonts[20] |
|
|
|
|
self.stats_sprite = self.factory.from_text(status_text, color=sdl2.ext.Color(0, 0, 0), fontmanager=font) |
|
|
|
|
if self.text_width != self.stats_sprite.size[0] or self.text_height != self.stats_sprite.size[1]: |
|
|
|
|
self.text_width, self.text_height = self.stats_sprite.size |
|
|
|
|
# create a background for the status text using texture |
|
|
|
|
self.stats_background = self.factory.from_color(sdl2.ext.Color(255, 255, 255), (self.text_width + 10, self.text_height + 4)) |
|
|
|
|
|
|
|
|
|
# self.renderer.fill((3, 3, self.text_width + 10, self.text_height + 4), sdl2.ext.Color(255, 255, 255)) |
|
|
|
|
self.renderer.copy(self.stats_background, dstrect=sdl2.SDL_Rect(3, 3, self.text_width + 10, self.text_height + 4)) |
|
|
|
|
self.renderer.copy(self.stats_sprite, dstrect=sdl2.SDL_Rect(8, 5, self.text_width, self.text_height)) |
|
|
|
|
|
|
|
|
|
def update_ammo(self, ammo, assets): |
|
|
|
|
"""Update and display the ammo count""" |
|
|
|
|
ammo_text = f"{ammo['bomb']['count']}/{ammo['bomb']['max']} {ammo['mine']['count']}/{ammo['mine']['max']} {ammo['nuclear']['count']}/{ammo['nuclear']['max']} " |
|
|
|
|
if self.ammo_text != ammo_text: |
|
|
|
|
self.ammo_text = ammo_text |
|
|
|
|
font = self.fonts[20] |
|
|
|
|
self.ammo_sprite = self.factory.from_text(ammo_text, color=sdl2.ext.Color(0, 0, 0), fontmanager=font) |
|
|
|
|
text_width, text_height = self.ammo_sprite.size |
|
|
|
|
self.ammo_background = self.factory.from_color(sdl2.ext.Color(255, 255, 255), (text_width + 10, text_height + 4)) |
|
|
|
|
text_width, text_height = self.ammo_sprite.size |
|
|
|
|
position = (self.target_size[0] - text_width - 10, self.target_size[1] - text_height - 5) |
|
|
|
|
#self.renderer.fill((position[0] - 5, position[1] - 2, text_width + 10, text_height + 4), sdl2.ext.Color(255, 255, 255)) |
|
|
|
|
self.renderer.copy(self.ammo_background, dstrect=sdl2.SDL_Rect(position[0] - 5, position[1] - 2, text_width + 10, text_height + 4)) |
|
|
|
|
self.renderer.copy(self.ammo_sprite, dstrect=sdl2.SDL_Rect(position[0], position[1], text_width, text_height)) |
|
|
|
|
self.renderer.copy(assets["BMP_BOMB0"], dstrect=sdl2.SDL_Rect(position[0]+25, position[1], 20, 20)) |
|
|
|
|
self.renderer.copy(assets["mine"], dstrect=sdl2.SDL_Rect(position[0]+80, position[1], 20, 20)) |
|
|
|
|
self.renderer.copy(assets["BMP_NUCLEAR"], dstrect=sdl2.SDL_Rect(position[0]+130, position[1], 20, 20)) |
|
|
|
|
# ====================== |
|
|
|
|
# VIEW & NAVIGATION |
|
|
|
|
# ====================== |
|
|
|
|
@ -328,6 +370,10 @@ class GameWindow:
|
|
|
|
|
# Execute main update |
|
|
|
|
kwargs["update"]() |
|
|
|
|
|
|
|
|
|
# Update and draw white flash effect |
|
|
|
|
if self.update_white_flash(): |
|
|
|
|
self.draw_white_flash() |
|
|
|
|
|
|
|
|
|
# Handle SDL events |
|
|
|
|
events = sdl2.ext.get_events() |
|
|
|
|
for event in events: |
|
|
|
|
@ -335,7 +381,11 @@ class GameWindow:
|
|
|
|
|
self.running = False |
|
|
|
|
elif event.type == sdl2.SDL_KEYDOWN and self.key_down: |
|
|
|
|
key = sdl2.SDL_GetKeyName(event.key.keysym.sym).decode('utf-8') |
|
|
|
|
self.key_down(key) |
|
|
|
|
# Check for Right Ctrl key to trigger white flash |
|
|
|
|
if event.key.keysym.sym == sdl2.SDLK_RCTRL: |
|
|
|
|
self.trigger_white_flash() |
|
|
|
|
else: |
|
|
|
|
self.key_down(key) |
|
|
|
|
elif event.type == sdl2.SDL_KEYUP and self.key_up: |
|
|
|
|
key = sdl2.SDL_GetKeyName(event.key.keysym.sym).decode('utf-8') |
|
|
|
|
self.key_up(key) |
|
|
|
|
@ -362,6 +412,64 @@ class GameWindow:
|
|
|
|
|
# SPECIAL EFFECTS |
|
|
|
|
# ====================== |
|
|
|
|
|
|
|
|
|
def trigger_white_flash(self): |
|
|
|
|
"""Trigger the white flash effect""" |
|
|
|
|
self.white_flash_active = True |
|
|
|
|
self.white_flash_start_time = sdl2.SDL_GetTicks() |
|
|
|
|
self.white_flash_opacity = 255 |
|
|
|
|
|
|
|
|
|
def update_white_flash(self): |
|
|
|
|
"""Update the white flash effect and return True if it should be drawn""" |
|
|
|
|
if not self.white_flash_active: |
|
|
|
|
return False |
|
|
|
|
|
|
|
|
|
current_time = sdl2.SDL_GetTicks() |
|
|
|
|
elapsed_time = current_time - self.white_flash_start_time |
|
|
|
|
|
|
|
|
|
if elapsed_time < 1000: # First 1 second : full white |
|
|
|
|
self.white_flash_opacity = 255 |
|
|
|
|
return True |
|
|
|
|
elif elapsed_time < 3000: # Next 2 seconds: fade out |
|
|
|
|
# Calculate fade based on remaining time (2000ms fade duration) |
|
|
|
|
fade_progress = (elapsed_time - 1000) / 2000.0 # 0.0 to 1.0 |
|
|
|
|
self.white_flash_opacity = int(255 * (1.0 - fade_progress)) |
|
|
|
|
return True |
|
|
|
|
else: # Effect is complete |
|
|
|
|
self.white_flash_active = False |
|
|
|
|
self.white_flash_opacity = 0 |
|
|
|
|
return False |
|
|
|
|
|
|
|
|
|
def draw_white_flash(self): |
|
|
|
|
"""Draw the white flash overlay""" |
|
|
|
|
if self.white_flash_opacity > 0: |
|
|
|
|
# Create a white surface with the current opacity |
|
|
|
|
white_surface = sdl2.SDL_CreateRGBSurface( |
|
|
|
|
0, self.target_size[0], self.target_size[1], 32, |
|
|
|
|
0x000000FF, # R mask |
|
|
|
|
0x0000FF00, # G mask |
|
|
|
|
0x00FF0000, # B mask |
|
|
|
|
0xFF000000 # A mask |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
if white_surface: |
|
|
|
|
# Fill surface with white |
|
|
|
|
sdl2.SDL_FillRect(white_surface, None, |
|
|
|
|
sdl2.SDL_MapRGBA(white_surface.contents.format, |
|
|
|
|
255, 255, 255, self.white_flash_opacity)) |
|
|
|
|
|
|
|
|
|
# Convert to texture and draw |
|
|
|
|
white_texture = self.factory.from_surface(white_surface) |
|
|
|
|
white_texture.position = (0, 0) |
|
|
|
|
|
|
|
|
|
# Enable alpha blending for the texture |
|
|
|
|
sdl2.SDL_SetTextureBlendMode(white_texture.texture, sdl2.SDL_BLENDMODE_BLEND) |
|
|
|
|
|
|
|
|
|
# Draw the white overlay |
|
|
|
|
self.renderer.copy(white_texture, dstrect=sdl2.SDL_Rect(0, 0, self.target_size[0], self.target_size[1])) |
|
|
|
|
|
|
|
|
|
# Clean up |
|
|
|
|
sdl2.SDL_FreeSurface(white_surface) |
|
|
|
|
|
|
|
|
|
# ====================== |
|
|
|
|
# UTILITY METHODS |
|
|
|
|
# ====================== |
|
|
|
|
|