Compare commits

...

3 Commits
dev ... master

Author SHA1 Message Date
3e6796220d revert 6a0de3601989df8820bbdf9986aed8f04869b71e
There appears to be some differences between master and my local machines so this didn't work as expected.

revert Updated sim.py

updated sim.py with performance patch from the dev branch.
2024-12-29 12:25:21 -06:00
6a0de36019 Updated sim.py
updated sim.py with performance patch from the dev branch.
2024-12-29 12:14:32 -06:00
83ba8baba5 revert 3059e17622428b804e196941eb21719399a9208a
revert reorganizations.
2024-12-28 20:15:57 -06:00
15 changed files with 81 additions and 187 deletions

2
__init__.py Normal file
View File

@ -0,0 +1,2 @@
import os
import sys

View File

@ -17,7 +17,7 @@
"friction": 0.5,
"viscosity": 0,
"pressure": 0,
"melt": "molten-glass",
"melt": "molten-Glass",
"melt_temperature": 1700,
"conductive": false,
"liquid": false,

View File

@ -22,9 +22,8 @@ The `clear_screen` function is used to reset the simulation grid and clear the d
"""
from config.settings import pygame, random, particle_properties, engine_settings
from typing import List, Dict
import colorsys
from settings import pygame, random, particle_properties, engine_settings
class Rendering:

View File

@ -11,22 +11,19 @@ The main function to run the Sandpypi program.
This function initializes the Pygame environment, creates the simulation and rendering objects, and enters the main event loop.
It handles user input events such as mouse clicks, mouse wheel scrolling, and keyboard presses.
It also updates the simulation, draws the particles, buttons, and other UI elements, and manages the settings menu.
The main loop runs at a target frame rate of 60 FPS (this fps varies on my mood and the testing), with the actual frame rate displayed in the debug overlay.
The main loop runs at a target frame rate of 60 FPS, with the actual frame rate displayed in the debug overlay.
"""
# Import Require files for the Engine.
from config.settings import pygame, cProfile, pstats, engine_settings
from rendering.rendering import Rendering
from physics.sim import Simulation
import cProfile
import pstats
from settings import pygame, engine_settings
from rendering import Rendering
"""
This is for the future physics engine until i figure out a better method used for testing right now.
#import os
#import sys
#sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
"""
from sim import Simulation
def update_simulation(sim, dt, engine_settings):
"""Update simulation state"""
@ -181,7 +178,7 @@ def main():
screen.fill((0, 0, 0))
fps = clock.get_fps()
dt = clock.tick(60) / 1000
dt = clock.tick(1000) / 1000
keys = pygame.key.get_pressed()
mouse_pos = pygame.mouse.get_pos()
zoom_active = keys[pygame.K_z]

47
settings.py Normal file
View File

@ -0,0 +1,47 @@
"""
#File Name: settings.py
Global settings and imports for the project.
This module defines various settings for the game engine, such as enabling or disabling the cursor, glow effect, gas effect, debug mode, and FPS display. It also provides a function to load particle properties from a JSON file.
The `engine_settings` dictionary contains the configurable settings for the game engine. These settings can be used to customize the behavior of the game.
The `load_particle_properties()` function attempts to load particle properties from a 'particles.json' file. If the file is not found or the JSON data is invalid, it returns an empty dictionary.
The `particle_properties` variable is initialized by calling `load_particle_properties()` when the module is imported.
"""
import pygame
import json
import random
import time
import numpy as np
engine_settings = {
'pause_sim': True,
'enable_cursor': True,
'enable_glow': False,
'enable_gas_effect': True,
'enable_debug': False,
'enable_fps': True,
'enable_WVisuals': False,
'enable_PVisuals': False,
'enable_TempVisuals': False,
'outerwall': True,
# 'settings': True/False
}
# Load particle properties from JSON file
def load_particle_properties():
try:
with open('particles.json') as f:
return json.load(f)
except (FileNotFoundError, json.JSONDecodeError):
print("Error loading particles.json")
return {}
# Load particle properties once when module is imported
particle_properties = load_particle_properties()

View File

@ -10,19 +10,16 @@ Key Components:
1. Particle Class
- Handles individual particle properties and behaviors
- Supports multiple particle types (solid, liquid, gas)
- Manages temperature and state transitions
2. Simulation Class
- Core simulation engine
- Manages particle creation, movement and interactions
- Handles physics calculations and spatial partitioning
- Manages temperature and state transitions
"""
#Load the imports.
from config.settings import random, time, particle_properties
from dataclasses import dataclass
import math
#Load the imports. Pygame is what makes this even work and so simple may consider other engines for performance depends on learning curve.
from settings import random, time, particle_properties
# Load particle properties from json so we know what particles we got and how they should be simulated.
class Particle:
@ -100,7 +97,6 @@ class Simulation:
self.wind_zones = []
self.wind = [0.0, 0.0] # Global wind vector (x, y)
def reset_particle_count(self):
self.particle_count = 0
@ -127,20 +123,6 @@ class Simulation:
return cell_key
def _get_neighbors_from_grid(self, x, y):
"""Get neighbors using spatial grid"""
cell_key = self.get_cell_key(x, y)
neighbors = []
# Check current and adjacent cells
for dx in [-1, 0, 1]:
for dy in [-1, 0, 1]:
check_key = (cell_key[0] + dx, cell_key[1] + dy)
if check_key in self.spatial_grid:
neighbors.extend(self.spatial_grid[check_key])
return neighbors
def update_spatial_grid(self): # this is where we update the spatial grid.
"""Update spatial grid for optimized collision detection"""
if len(self.active_particles) > 100:
@ -155,7 +137,6 @@ class Simulation:
self.spatial_grid = {k: set(v) for k, v in cell_lists.items()}
def _check_dormant_state(self, x, y, particle):
key = (x, y)
if particle.particle_type == 'wall':
@ -178,7 +159,6 @@ class Simulation:
self.dormant_particles.discard(key)
return False
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
@ -207,7 +187,6 @@ class Simulation:
if new_type in self.particle_properties:
self.transform_particle(x, y, new_type)
def handle_particle_interactions(self, dt): # this is where we handle all the particle interactions.
"""Handle interactions between different particle types"""
for x, y in list(self.active_particles):
@ -281,7 +260,6 @@ class Simulation:
self.active_particles.add((new_x, new_y))
self.active_particles.discard((x, y))
def add_wind_zone(self, x, y):
# Instead of creating particles, store wind zone data
wind_zone = {
@ -321,9 +299,8 @@ class Simulation:
fy += drag * particle.velocity[1]
# Check neighboring particles
neighbors = self._get_neighbors_from_grid(x, y)
neighbors = self._get_quick_neighbors(x, y)
for nx, ny in neighbors:
if(nx, ny) != (x, y):
if 0 <= nx < self.width and 0 <= ny < self.height:
neighbor = self.particles[nx][ny]
if neighbor:
@ -331,8 +308,6 @@ class Simulation:
return fx, fy
def _process_particle_batch(self, batch, dt):
updates = []
new_active = set()
@ -381,19 +356,16 @@ class Simulation:
return new_active
def _get_quick_neighbors(self, x, y):
"""Quick neighbor lookup without full spatial grid"""
return [(x+dx, y+dy) for dx, dy in [(-1,0), (1,0), (0,-1), (0,1)]]
def _apply_neighbor_forces(self, particle, neighbor, fx, fy):
"""Optimized neighbor force calculation"""
if hasattr(neighbor, 'temperature') and hasattr(particle, 'temperature'):
temp_diff = neighbor.temperature - particle.temperature
fy += temp_diff * 0.05
def ignite_particle(self, particle): # this is where we ignite the particle.
"""Handle ignition and burning of flammable particles."""
if hasattr(particle, 'flamability') and particle.flamability > 0.5:
@ -533,7 +505,6 @@ class Simulation:
return particle.particle_type
return None
def apply_gravity(self, dt): # this is where we apply gravity.
"""Handle only gravity and basic particle movement"""
self.spatial_grid.clear()
@ -774,7 +745,6 @@ class Simulation:
self.dormant_particles.discard(key)
self.particle_movement_counter[key] = 0
def track_tps(self):
"""Track Ticks Per Second for simulation performance monitoring"""
if not hasattr(self, '_tps_counter'):
@ -796,17 +766,19 @@ class Simulation:
def simulate_step(self, dt, engine_settings):
"""Run simulation step with spatial grid updates"""
self.update_spatial_grid()
"""Run a single step of the simulation"""
active_list = list(self.active_particles)
batch_size = 1024
batch_size = 1000
for i in range(0, len(active_list), batch_size):
batch = active_list[i:i + batch_size]
self._process_particle_batch(batch, dt)
# Update spatial grid only when needed
if len(self.active_particles) > 100:
self.update_spatial_grid()
# Update particle positions and physics
self.apply_gravity(dt)
self.apply_physics(dt, engine_settings)

View File

View File

View File

@ -1,74 +0,0 @@
"""
#File Name: settings.py
Global settings and imports for the project.
This module defines various settings for the game engine, such as enabling or disabling the cursor, glow effect, gas effect, debug mode, and FPS display. It also provides a function to load particle properties from a JSON file.
The `engine_settings` dictionary contains the configurable settings for the game engine. These settings can be used to customize the behavior of the game.
The `load_particle_properties()` function attempts to load particle properties from a 'particles.json' file. If the file is not found or the JSON data is invalid, it returns an empty dictionary.
The `particle_properties` variable is initialized by calling `load_particle_properties()` when the module is imported.
"""
import cProfile
import pstats
import sys
import os
import pygame
import json
import random
import time
import numpy as np
engine_settings = {
'pause_sim': True,
'enable_cursor': True,
'enable_glow': False,
'enable_gas_effect': True,
'enable_debug': True,
'enable_fps': True,
'enable_WVisuals': False,
'enable_PVisuals': False,
'enable_TempVisuals': False,
'outerwall': False,
# 'settings': True/False
}
# For particles.json loading in settings.py:
particles_path = os.path.join(os.path.dirname(__file__), '..', 'part', 'particles.json')
# Load particle properties from JSON file
def load_particle_properties():
# Load core particles
particle_data = {}
print(f"Loading particles from {particles_path}")
# Core particles
try:
with open(particles_path, 'r') as f:
particle_data.update(json.load(f))
print(f"Loaded {len(particle_data)} core particles")
except (FileNotFoundError, json.JSONDecodeError) as e:
print(f"Error loading core particles: {e}")
# Load mods from mods directory
mods_path = os.path.join(os.path.dirname(__file__), '..', 'part', 'mods')
if os.path.exists(mods_path):
for filename in os.listdir(mods_path):
if filename.endswith('.json'):
mod_file = os.path.join(mods_path, filename)
try:
with open(mod_file, 'r') as f:
mod_data = json.load(f)
print(f"Loading mod: {filename}")
particle_data.update(mod_data)
print(f"Loaded {len(mod_data)} particles from {filename}")
except (FileNotFoundError, json.JSONDecodeError) as e:
print(f"Error loading mod {filename}: {e}")
return particle_data
# Load particle properties once when module is imported
particle_properties = load_particle_properties()
__all__ = ['pygame', 'np', 'random', 'time', 'engine_settings', 'particle_properties', 'cProfile', 'pstats', 'sys', 'os']

View File

View File

@ -1,49 +0,0 @@
{
"wsand": {
"name": "Wet Sand",
"size": 1,
"hardness": 0.5,
"color": [200, 200, 25, 255],
"velocity": 0.5,
"mass": 0.5,
"conductivity": 0,
"heat_capacity": 1,
"flamability": 0.8,
"temperature": 20,
"explosive": false,
"explosion_radius": 0,
"explosion_color": [0, 0, 0],
"friction": 0.5,
"viscosity": 0.3,
"pressure": 0,
"melt": "sand",
"melt_temperature": 100,
"conductive": false,
"liquid": false,
"solid": true,
"is_gas": false
},
"ultratanium": {
"name": "Ultra Tanium",
"size": 1,
"hardness": 1000,
"velocity": 0.1,
"conductivity": 1,
"heat_capacity": 1,
"color": [255, 200, 255, 255],
"pressure": 100,
"explosive": true,
"explosion_radius": 15,
"explosion_color": [
255,
0,
255
],
"temperature": 10000,
"conductive": true,
"liquid": true,
"solid": true,
"is_gas": true,
"special": true
}
}

View File