Browse Source

Enhance blood stain handling: combine existing and new blood surfaces for better accumulation and add surface management

master
Matteo Benedetto 4 months ago
parent
commit
a4b6703d12
  1. 21
      engine/graphics.py
  2. 93
      engine/sdl2.py

21
engine/graphics.py

@ -47,11 +47,24 @@ class Graphics():
if not hasattr(self, 'blood_stains'): if not hasattr(self, 'blood_stains'):
self.blood_stains = {} self.blood_stains = {}
# Generate blood surface # Generate new blood surface
blood_surface = self.render_engine.generate_blood_surface() new_blood_surface = self.render_engine.generate_blood_surface()
self.blood_stains[position] = blood_surface
# Regenerate background to include the new blood stain if position in self.blood_stains:
# If there's already a blood stain at this position, combine them
existing_surface = self.blood_stains[position]
combined_surface = self.render_engine.combine_blood_surfaces(existing_surface, new_blood_surface)
# Free the old surfaces
self.render_engine.free_surface(existing_surface)
self.render_engine.free_surface(new_blood_surface)
self.blood_stains[position] = combined_surface
else:
# First blood stain at this position
self.blood_stains[position] = new_blood_surface
# Regenerate background to include the updated blood stain
self.regenerate_background() self.regenerate_background()
def scroll_cursor(self, x=0, y=0): def scroll_cursor(self, x=0, y=0):

93
engine/sdl2.py

@ -304,13 +304,13 @@ class GameWindow:
pixels = cast(blood_surface.contents.pixels, POINTER(c_uint32)) pixels = cast(blood_surface.contents.pixels, POINTER(c_uint32))
pitch = blood_surface.contents.pitch // 4 # pitch in pixel (32-bit) pitch = blood_surface.contents.pitch // 4 # pitch in pixel (32-bit)
# Colori del sangue (variazioni di rosso) # Colori del sangue (variazioni di rosso in formato ABGR)
blood_colors = [ blood_colors = [
0xFF8B0000, # Rosso scuro 0xFF00008B, # Rosso scuro (A=FF, B=00, G=00, R=8B)
0xFFB22222, # Rosso mattone 0xFF002222, # Rosso mattone (A=FF, B=00, G=22, R=22)
0xFFDC143C, # Cremisi 0xFF003C14, # Cremisi (A=FF, B=00, G=3C, R=14)
0xFFFF0000, # Rosso puro 0xFF0000FF, # Rosso puro (A=FF, B=00, G=00, R=FF)
0xFF800000, # Marrone 0xFF000080, # Marrone rossastro (A=FF, B=00, G=00, R=80)
] ]
# Genera la macchia con un algoritmo di diffusione # Genera la macchia con un algoritmo di diffusione
@ -386,3 +386,84 @@ class GameWindow:
texture = self.factory.from_surface(temp_surface) texture = self.factory.from_surface(temp_surface)
sdl2.SDL_FreeSurface(temp_surface) sdl2.SDL_FreeSurface(temp_surface)
return texture return texture
def combine_blood_surfaces(self, existing_surface, new_surface):
"""Combine two blood surfaces by blending them together"""
# Create a new surface for the combined result
combined_surface = sdl2.SDL_CreateRGBSurface(
0, self.cell_size, self.cell_size, 32,
0x000000FF, # R mask
0x0000FF00, # G mask
0x00FF0000, # B mask
0xFF000000 # A mask
)
if combined_surface is None:
return existing_surface
# Lock both surfaces for pixel manipulation
sdl2.SDL_LockSurface(existing_surface)
sdl2.SDL_LockSurface(new_surface)
sdl2.SDL_LockSurface(combined_surface)
# Get pixel data
existing_pixels = cast(existing_surface.contents.pixels, POINTER(c_uint32))
new_pixels = cast(new_surface.contents.pixels, POINTER(c_uint32))
combined_pixels = cast(combined_surface.contents.pixels, POINTER(c_uint32))
pitch = combined_surface.contents.pitch // 4 # pitch in pixels (32-bit)
# Combine pixels manually for better blending
for y in range(self.cell_size):
for x in range(self.cell_size):
idx = y * pitch + x
existing_pixel = existing_pixels[idx]
new_pixel = new_pixels[idx]
# Extract RGBA components
existing_a = (existing_pixel >> 24) & 0xFF
existing_r = (existing_pixel >> 16) & 0xFF
existing_g = (existing_pixel >> 8) & 0xFF
existing_b = existing_pixel & 0xFF
new_a = (new_pixel >> 24) & 0xFF
new_r = (new_pixel >> 16) & 0xFF
new_g = (new_pixel >> 8) & 0xFF
new_b = new_pixel & 0xFF
# Blend the colors (additive blending for blood accumulation)
if new_a > 0: # If new pixel has color
if existing_a > 0: # If existing pixel has color
# Combine both colors, making it darker/more opaque
final_r = min(255, existing_r + (new_r // 2))
final_g = min(255, existing_g + (new_g // 2))
final_b = min(255, existing_b + (new_b // 2))
final_a = min(255, existing_a + (new_a // 2))
else:
# Use new pixel color
final_r = new_r
final_g = new_g
final_b = new_b
final_a = new_a
else:
# Use existing pixel color
final_r = existing_r
final_g = existing_g
final_b = existing_b
final_a = existing_a
# Pack the final pixel
combined_pixels[idx] = (final_a << 24) | (final_r << 16) | (final_g << 8) | final_b
# Unlock surfaces
sdl2.SDL_UnlockSurface(existing_surface)
sdl2.SDL_UnlockSurface(new_surface)
sdl2.SDL_UnlockSurface(combined_surface)
return combined_surface
def free_surface(self, surface):
"""Safely free an SDL surface"""
if surface is not None:
sdl2.SDL_FreeSurface(surface)
Loading…
Cancel
Save