sandpypi/rendering.py
2024-12-26 04:11:32 -06:00

213 lines
8.7 KiB
Python

#File Name: rendering.py
from imports import pygame, json, random
try:
with open('sandpypi/particles.json') as f:
particle_properties = json.load(f)
except (FileNotFoundError, json.JSONDecodeError):
print("Error loading particles.json")
particle_properties = {}
class Rendering:
def __init__(self, width, height):
self.screen = pygame.display.set_mode((width, height))
self.background = pygame.Surface((width, height))
self.background.fill((0, 0, 0))
self.width = width
self.height = height
self.particle_surface = pygame.Surface((width, height), pygame.SRCALPHA)
self.particle_colors = {}
self.button_width, self.button_height = 30, 30
self.particle_properties = particle_properties
self.buttons = {}
self.clear_screen_button = pygame.Rect(915, 10, 50, 30)
self.load_buttons() # Load buttons dynamically
self.particle_colors = {}
for name, properties in particle_properties.items():
if 'color' in properties:
self.particle_colors[name.lower()] = properties['color']
self.categories = {
'Solids': [],
'Liquids': [],
'Gases': [],
'Special': []
}
for particle_name, properties in self.particle_properties.items():
if properties.get('is_gas'):
self.categories['Gases'].append(particle_name)
elif properties.get('liquid'):
self.categories['Liquids'].append(particle_name)
elif properties.get('solid'):
self.categories['Solids'].append(particle_name)
else:
self.categories['Special'].append(particle_name)
self.current_category = 'Solids'
self.category_buttons = {}
self.setup_category_menu()
def setup_category_menu(self):
# Category buttons at the top
x_offset = self.width - 350
y_offset = 10
for category in self.categories:
button_rect = pygame.Rect(x_offset, y_offset, 80, 25)
self.category_buttons[category] = button_rect
x_offset += 90
def load_buttons(self):
x_offset = 10
y_offset = 10
for particle_type, properties in self.particle_properties.items():
if 'color' in properties:
button_rect = pygame.Rect(x_offset, y_offset, self.button_width, self.button_height)
self.buttons[particle_type.lower()] = button_rect
x_offset += self.button_width + 10 # Add spacing between buttons
def draw_particles(self, particles, active_particles, particle_size, particle_colors):
self.particle_surface = pygame.Surface((self.width, self.height), pygame.SRCALPHA)
self.particle_surface.fill((0, 0, 0, 0))
for x, y in active_particles:
particle = particles[x][y]
if not particle:
continue
base_color = particle_colors.get(particle.particle_type, (255, 255, 255))
color = list(base_color)
if particle.is_gas:
# Enhanced gas visibility
alpha = random.randint(128, 200)
color = list(color)
if len(color) < 4:
color.append(alpha)
else:
color[3] = alpha
# Add subtle movement effect
offset_x = random.randint(-1, 1)
offset_y = random.randint(-1, 1)
rect = (x * particle_size + offset_x, y * particle_size + offset_y,
particle_size, particle_size)
else:
rect = (x * particle_size, y * particle_size,
particle_size, particle_size)
pygame.draw.rect(self.particle_surface, color, rect)
self.screen.blit(self.background, (0, 0))
self.screen.blit(self.particle_surface, (0, 0))
def draw_debug_overlay(self, fps, particles):
# Get mouse position and convert to grid coordinates
mouse_x, mouse_y = pygame.mouse.get_pos()
grid_x = mouse_x // 3
grid_y = mouse_y // 3
# Get particle info under cursor
particle_info = "None"
if 0 <= grid_x < len(particles) and 0 <= grid_y < len(particles[0]):
particle = particles[grid_x][grid_y]
if particle:
# Include more detailed particle information
particle_info = f"Type: {particle.particle_type}"
if hasattr(particle, 'temperature'):
particle_info += f" | Temp: {particle.temperature}°C"
if hasattr(particle, 'liquid'):
particle_info += f" | Liquid: {particle.liquid}"
if hasattr(particle, 'is_gas'):
particle_info += f" | Gas: {particle.is_gas}"
if hasattr(particle, 'solid'):
particle_info += f" | Solid: {particle.solid}"
if hasattr(particle, 'mass'):
particle_info += f" | Mass: {particle.mass}"
if hasattr(particle, 'velocity'):
particle_info += f" | Velocity: {particle.velocity}"
if hasattr(particle, 'friction'):
particle_info += f" | Friction: {particle.friction}"
# Draw debug information
font = pygame.font.SysFont(None, 24)
debug_info = [
f"FPS: {int(fps)}",
f"Mouse: ({mouse_x}, {mouse_y})",
f"Grid: ({grid_x}, {grid_y})",
f"Particle: {particle_info}"
]
y_offset = 10
for info in debug_info:
debug_text = font.render(info, True, (255, 255, 255))
self.screen.blit(debug_text, (10, y_offset))
y_offset += 25
def draw_buttons(self):
self.buttons = {}
# Draw category buttons vertically on right
x_offset = self.width - 100
y_offset = 10
for category, button in self.category_buttons.items():
color = (200, 200, 200) if category == self.current_category else (150, 150, 150)
pygame.draw.rect(self.screen, color, button)
font = pygame.font.SysFont(None, 20)
label = font.render(category, True, (0, 0, 0))
self.screen.blit(label, (button.x + 5, button.y + 5))
# Draw particle buttons for current category
y_offset = 150 # Start particle buttons below categories
for particle_type in self.categories[self.current_category]:
if particle_type in self.particle_properties:
color = self.particle_properties[particle_type].get('color', (255, 255, 255))
button_rect = pygame.Rect(x_offset, y_offset, 80, 25)
self.buttons[particle_type] = button_rect
pygame.draw.rect(self.screen, color, button_rect)
pygame.draw.rect(self.screen, (0, 0, 0), button_rect, 2)
font = pygame.font.SysFont(None, 20)
label = font.render(particle_type, True, (0, 0, 0))
self.screen.blit(label, (x_offset + 5, y_offset + 5))
y_offset += 30 # Stack buttons vertically
# Draw clear screen button
self.clear_screen_button = pygame.Rect(x_offset, y_offset + 10, 80, 25)
pygame.draw.rect(self.screen, (255, 0, 0), self.clear_screen_button)
font = pygame.font.SysFont(None, 24)
label = font.render("Clear", True, (255, 255, 255))
self.screen.blit(label, (self.clear_screen_button.x + 5, self.clear_screen_button.y + 5))
def render_brush_curser(self, x, y, radius):
# Draw a circle cursor for brushsize
pygame.draw.circle(self.screen, (255, 255, 255), (x, y), radius)
def draw_brush_size_slider(self, brush_size):
# Draw the slider for brush size
pygame.draw.rect(self.screen, (255, 255, 255), (500, 10, 100, 20))
pygame.draw.rect(self.screen, (0, 0, 0), (500, 10, 100, 20), 2)
pygame.draw.rect(self.screen, (255, 0, 0), (500 + brush_size, 10, 100 - brush_size * 2, 20))
label = pygame.font.SysFont(None, 24).render(f"Brush Size: {brush_size}", True, (255, 255, 255))
self.screen.blit(label, (500, 10))
def clear_screen(self, sim):
# Store current particle type
current_type = sim.current_particle_type
# Reset simulation grid while preserving particle type
sim.particles = [[None for _ in range(sim.height)] for _ in range(sim.width)]
sim.active_particles.clear()
sim.current_particle_type = current_type
# Clear display surfaces
self.background.fill((0, 0, 0))
self.particle_surface.fill((0, 0, 0, 0))