diff --git a/__pycache__/rendering.cpython-312.pyc b/__pycache__/rendering.cpython-312.pyc index e845e57..fc4b5ac 100644 Binary files a/__pycache__/rendering.cpython-312.pyc and b/__pycache__/rendering.cpython-312.pyc differ diff --git a/__pycache__/sim.cpython-312.pyc b/__pycache__/sim.cpython-312.pyc index 56ca267..d93ef72 100644 Binary files a/__pycache__/sim.cpython-312.pyc and b/__pycache__/sim.cpython-312.pyc differ diff --git a/rendering.py b/rendering.py index 6ed210a..1b89da8 100644 --- a/rendering.py +++ b/rendering.py @@ -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) diff --git a/setup.py b/setup.py index de381a5..f4712d1 100644 --- a/setup.py +++ b/setup.py @@ -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"), ) diff --git a/sim.py b/sim.py index 587fdc8..e9e529c 100644 --- a/sim.py +++ b/sim.py @@ -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() diff --git a/simulation_core.pyx b/simulation_core.pyx index 7d3d18e..74d689b 100644 --- a/simulation_core.pyx +++ b/simulation_core.pyx @@ -1,4 +1,5 @@ # simulation_core.pyx +# Cython code for simulating the physics of the system cimport cython from libc.math cimport sqrt