diff --git a/README.md b/README.md index 9e62a2b..6bead46 100644 --- a/README.md +++ b/README.md @@ -4,8 +4,8 @@ mostly a concept in python for falling sand simulation i guess the goal is to make a python version of the powder toy which is a falling sand sim the code is not finished yet, but i will update it as i go. -Main Features: -------------- +## Main Features + - Particle Physics - Gravity and wind effects - Temperature dynamics @@ -17,7 +17,7 @@ Main Features: - Heat transfer between particles - Special Effects - - Fire propagation + - Fire propagation sorta - Smoke generation - Liquid spreading @@ -25,9 +25,9 @@ Main Features: - Spatial partitioning grid - Dormant particle tracking - Batch processing - """ + - Static User Interface -## **Current Features** +### **Current Features** | **Working** | **Partial** | **Not Working/Implemented** | | ----------------- | ----------------------------- | --------------------------- | @@ -41,7 +41,7 @@ Main Features: | | Core Physics and Interactions | | | | Core Rendering System | | -### **Controls** +#### **Controls** | Key | Action | | ------------------- | ------------------------------ | diff --git a/particles.json b/particles.json index ae2a842..d1f82d7 100644 --- a/particles.json +++ b/particles.json @@ -459,6 +459,16 @@ "liquid": false, "solid": false, "is_gas": true + }, + "wind": { + "name": "Wind", + "color": [200, 200, 255, 128], + "mass": 0.01, + "is_wind": true, + "wind_strength": 2.0, + "wind_direction": [1, 0], + "radius": 50, + "special": true } } diff --git a/rendering.py b/rendering.py index 94c4bbb..088aadc 100644 --- a/rendering.py +++ b/rendering.py @@ -209,8 +209,74 @@ class Rendering: if hasattr(particle, attr)) return " | ".join(info) return "None" + + + def draw_wind_overlay(self, wind_zones): + wind_surface = pygame.Surface((self.width, self.height), pygame.SRCALPHA) + + for zone in wind_zones: + # Draw wind direction arrows + x, y = zone['x'], zone['y'] + radius = zone['radius'] + strength = zone['strength'] + direction = zone['direction'] + + # Draw wind field visualization + arrow_color = (0, 150, 255, 100) # Light blue, semi-transparent + arrow_length = strength * 20 + + # Draw main direction arrow + end_x = x + direction[0] * arrow_length + end_y = y + direction[1] * arrow_length + pygame.draw.line(wind_surface, arrow_color, (x, y), (end_x, end_y), 2) + + # Draw arrow head + pygame.draw.circle(wind_surface, arrow_color, (int(x), int(y)), 5) + + self.screen.blit(wind_surface, (0, 0)) + + def draw_pressure_overlay(self, particles, active_particles): + pressure_surface = pygame.Surface((self.width, self.height), pygame.SRCALPHA) + + # Create pressure map + for x, y in active_particles: + particle = particles[x][y] + if particle and hasattr(particle, 'pressure'): + # Color gradient based on pressure + pressure = particle.pressure + if pressure > 0: + color = (255, 0, 0, int(min(pressure * 50, 255))) # Red for high pressure + else: + color = (0, 0, 255, int(min(-pressure * 50, 255))) # Blue for low pressure + + pygame.draw.rect(pressure_surface, color, + (x * self.particle_size, y * self.particle_size, + self.particle_size, self.particle_size)) + + self.screen.blit(pressure_surface, (0, 0)) + def draw_temperature_overlay(self, particles, active_particles): + temperature_surface = pygame.Surface((self.width, self.height), pygame.SRCALPHA) + + # Create temperature map + for x, y in active_particles: + particle = particles[x][y] + if particle and hasattr(particle, 'temperature'): + # Color gradient based on temperature + temperature = particle.temperature + if temperature > 0: + color = (255, 0, 0, int(min(temperature * 50, 255))) # Red for high temperature + else: + color = (0, 0, 255, int(min(-temperature * 50, 255))) # Blue for low temperature + + pygame.draw.rect(temperature_surface, color, + (x * self.particle_size, y * self.particle_size, + self.particle_size, self.particle_size)) + + self.screen.blit(temperature_surface, (0, 0)) + + def draw_debug_overlay(self, fps, particles): # this is the function that draws the debug overlay if engine_settings ['enable_fps']: # Draw FPS diff --git a/sandpypi.py b/sandpypi.py index d59b215..935e051 100644 --- a/sandpypi.py +++ b/sandpypi.py @@ -105,7 +105,7 @@ def main(): # Main function to run the program if not over_button and not in_settings_area: mouse_down_left = True - + elif event.button == 3: # Right click mouse_down_right = True @@ -143,7 +143,12 @@ def main(): # Main function to run the program if mouse_down_left and not over_button: x, y = pygame.mouse.get_pos() - sim.create_particle_circle(x, y) + # Check if current particle type is wind or air + if sim.current_particle_type not in ['wind', 'air']: + sim.create_particle_circle(x, y) + else: + # Handle wind/air differently + sim.add_wind_zone(x, y) if mouse_down_right: x, y = pygame.mouse.get_pos() diff --git a/settings.py b/settings.py index 807d990..b3f2bb9 100644 --- a/settings.py +++ b/settings.py @@ -23,7 +23,10 @@ engine_settings = { 'enable_glow': False, 'enable_gas_effect': True, 'enable_debug': False, - 'enable_fps': True + 'enable_fps': True, + 'enable_WVisuals': False, + 'enable_PVisuals': False, + 'enable_TempVisuals': False, # 'settings': True/False } diff --git a/sim.py b/sim.py index 968e5e7..0dd3681 100644 --- a/sim.py +++ b/sim.py @@ -93,6 +93,7 @@ class Simulation: self.particle_properties = particle_properties self.current_particle_type = 'sand' self.gravity = 9.8 # m/s^2, adjustable based on the scale of simulation + self.wind_zones = [] self.wind = [0.0, 0.0] # Global wind vector (x, y) @@ -267,10 +268,31 @@ class Simulation: particle.is_gas = False + def add_wind_zone(self, x, y): + # Instead of creating particles, store wind zone data + wind_zone = { + 'x': x, + 'y': y, + 'radius': 50, + 'strength': 2.0, + 'direction': [1, 0] + } + self.wind_zones.append(wind_zone) + + def calculate_forces(self, particle, x, y): # this is where we calculate the forces. """Calculate net forces acting on a particle.""" fx, fy = 0.0, 0.0 # Initialize forces + # Check wind zones + for zone in self.wind_zones: + dx = x - zone['x'] + dy = y - zone['y'] + distance = (dx*dx + dy*dy) ** 0.5 + if distance <= zone['radius']: + fx += zone['direction'][0] * zone['strength'] * (1 - distance/zone['radius']) + fy += zone['direction'][1] * zone['strength'] * (1 - distance/zone['radius']) + # Apply wind force if particle.is_gas: fx += self.wind[0] * 0.5 @@ -680,8 +702,10 @@ class Simulation: # physics calculations fx, fy = self.calculate_forces(particle, x, y) - particle.velocity[0] += (fx / particle.mass) * dt - particle.velocity[1] += (fy / particle.mass) * dt + # Use max() to ensure mass is never zero + mass = max(particle.mass, 0.001) + particle.velocity[0] += (fx / mass) * dt + particle.velocity[1] += (fy / mass) * dt new_x = int(x + particle.velocity[0] * dt) new_y = int(y + particle.velocity[1] * dt)