made small updates to the spatial grid

rearranged some of the code for better readability
This commit is contained in:
Stan44 2024-12-26 14:22:19 -06:00
parent a03ba2b950
commit 05e37a0bd5
6 changed files with 71 additions and 66 deletions

Binary file not shown.

View File

@ -69,7 +69,7 @@ class Rendering:
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)

View File

@ -4,5 +4,5 @@ from setuptools import setup
from Cython.Build import cythonize
setup(
ext_modules=cythonize("sandpypi/simulation_core.pyx"),
ext_modules=cythonize("simulation_core.pyx"),
)

132
sim.py
View File

@ -76,6 +76,36 @@ class Simulation:
self.wind = [0.0, 0.0] # Global wind vector (x, y)
def get_cell_key(self, x, y): # this is where we get the cell key.
# Convert coordinates to grid cell
cell_x = x // self.cell_size
cell_y = y // self.cell_size
return (cell_x, cell_y)
def add_to_spatial_grid(self, particle, x, y): # this is where we add to the spatial grid.
cell_key = self.get_cell_key(x, y)
if cell_key not in self.spatial_grid:
self.spatial_grid[cell_key] = set()
self.spatial_grid[cell_key].add((x, y))
return cell_key
def remove_from_spatial_grid(self, x, y): # this is where we remove from the spatial grid.
cell_key = self.get_cell_key(x, y)
if cell_key in self.spatial_grid:
self.spatial_grid[cell_key].discard((x, y))
return cell_key
def update_spatial_grid(self): # this is where we update the spatial grid.
"""Update spatial grid for optimized collision detection"""
self.spatial_grid.clear()
for x, y in self.active_particles:
self.add_to_spatial_grid(self.particles[x][y], x, y)
def handle_phase_transitions(self, particle, x, y): # this is where we handle all the phase transitions.
"""Handle all phase transitions for a particle"""
# Check evaporation
@ -101,6 +131,7 @@ class Simulation:
def handle_particle_interactions(self, dt): # this is where we handle all the particle interactions.
"""Handle interactions between different particle types"""
self.update_spatial_grid()
for x, y in list(self.active_particles):
particle = self.particles[x][y]
if not particle:
@ -253,6 +284,33 @@ class Simulation:
self.ignite_particle(neighbor)
def handle_special_particles(self, particle, x, y): # this is where we handle special particles.
"""Handle special particle behaviors"""
if particle.particle_type in ['fire', 'flame', 'smoke']:
if random.random() < 0.6: # % chance
self.particles[x][y] = None
self.active_particles.discard((x, y))
if particle.particle_type in ['fire', 'flame', 'lava']:
# Create smoke above with proper physics
if random.random() < 0.65 and y > 0: # % chance for smoke
properties = self.particle_properties['smoke']
new_smoke = Particle.from_type((x, y-1), 'smoke', properties)
if self.particles[x][y-1] is None:
self.particles[x][y-1] = new_smoke
self.active_particles.add((x, y-1))
else:
# Handle collision with water
if particle.particle_type == 'water':
self.particles[x][y-1] = None
self.active_particles.discard((x, y-1))
self.particles[x][y] = None
self.active_particles.discard((x, y))
self.particles[x][y] = Particle.from_type((x, y), 'water', self.particle_properties['water'])
self.active_particles.add((x, y))
def handle_temperature(self, dt): # this is where we handle the temperature.
"""Handle temperature changes and state transitions"""
for x, y in list(self.active_particles):
@ -298,36 +356,7 @@ class Simulation:
if particle.temperature > 1000:
self.particles[x][y] = None
self.active_particles.remove((x, y))
self.spatial_grid.pop((x, y), None)
def get_cell_key(self, x, y): # this is where we get the cell key.
# Convert coordinates to grid cell
cell_x = x // self.cell_size
cell_y = y // self.cell_size
return (cell_x, cell_y)
def add_to_spatial_grid(self, particle, x, y): # this is where we add to the spatial grid.
cell_key = self.get_cell_key(x, y)
if cell_key not in self.spatial_grid:
self.spatial_grid[cell_key] = set()
self.spatial_grid[cell_key].add((x, y))
def remove_from_spatial_grid(self, x, y): # this is where we remove from the spatial grid.
cell_key = self.get_cell_key(x, y)
if cell_key in self.spatial_grid:
self.spatial_grid[cell_key].discard((x, y))
def create_particle_circle(self, center_x, center_y): # this is where we create the particle circle.
brush_size = int(self.brush_size)
for dx in range(-brush_size, brush_size + 1):
for dy in range(-brush_size, brush_size + 1):
if dx*dx + dy*dy <= brush_size*brush_size: # Circle check
self.create_particle(center_x + dx * self.particle_size,
center_y + dy * self.particle_size)
self.spatial_grid.pop((x, y), None)
def create_particle(self, x, y): # this is where we create the particle.
@ -351,13 +380,15 @@ class Simulation:
self.particles[grid_x][grid_y] = new_particle
self.active_particles.add((grid_x, grid_y))
def update_spatial_grid(self): # this is where we update the spatial grid.
"""Update spatial grid for optimized collision detection"""
self.spatial_grid.clear()
for x, y in self.active_particles:
self.add_to_spatial_grid(self.particles[x][y], x, y)
def create_particle_circle(self, center_x, center_y): # this is where we create the particle circle.
brush_size = int(self.brush_size)
for dx in range(-brush_size, brush_size + 1):
for dy in range(-brush_size, brush_size + 1):
if dx*dx + dy*dy <= brush_size*brush_size: # Circle check
self.create_particle(center_x + dx * self.particle_size,
center_y + dy * self.particle_size)
def apply_gravity(self, dt): # this is where we apply gravity.
"""Handle only gravity and basic particle movement"""
@ -419,33 +450,6 @@ class Simulation:
particle.position = (new_x, new_y)
def handle_special_particles(self, particle, x, y): # this is where we handle special particles.
"""Handle special particle behaviors"""
if particle.particle_type in ['fire', 'flame', 'smoke']:
if random.random() < 0.6: # % chance
self.particles[x][y] = None
self.active_particles.discard((x, y))
if particle.particle_type in ['fire', 'flame', 'lava']:
# Create smoke above with proper physics
if random.random() < 0.65 and y > 0: # % chance for smoke
properties = self.particle_properties['smoke']
new_smoke = Particle.from_type((x, y-1), 'smoke', properties)
if self.particles[x][y-1] is None:
self.particles[x][y-1] = new_smoke
self.active_particles.add((x, y-1))
else:
# Handle collision with water
if particle.particle_type == 'water':
self.particles[x][y-1] = None
self.active_particles.discard((x, y-1))
self.particles[x][y] = None
self.active_particles.discard((x, y))
self.particles[x][y] = Particle.from_type((x, y), 'water', self.particle_properties['water'])
self.active_particles.add((x, y))
def apply_physics(self, dt): # this is where we apply physics.
"""Handle all physics effects"""
new_active_particles = set()

View File

@ -1,4 +1,5 @@
# simulation_core.pyx
# Cython code for simulating the physics of the system
cimport cython
from libc.math cimport sqrt