diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..9ebed2f --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,16 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Python: main file", + "type": "python", + "request": "launch", + "program": "main.py", + "console": "integratedTerminal", + "justMyCode": true + } + ] +} \ No newline at end of file diff --git a/gas_sim.py b/gas_sim.py index 5f1c567..aa28c0a 100644 --- a/gas_sim.py +++ b/gas_sim.py @@ -2,22 +2,39 @@ from math import hypot class GasSim: - def __init__(self, particle_radius, particle_compressibility, particle_friction, substeps): + def __init__(self, particle_radius, particle_compressibility, particle_friction, substeps, window_aspect): self.particle_radius = particle_radius self.particle_compressibility = particle_compressibility self.particle_friction = particle_friction self.substeps = substeps + self.window_aspect = window_aspect + self.particles = [] - self.walls = [] - def add_particle(self, pos, vel = (0, 0)): - self.particles.append([pos, vel]) + def add_particle(self, pos, vel = [0, 0]): + self.particles.append([list(pos).copy(), vel.copy()]) - def cursor_particle_collide_test(self, cursor_pos, cursor_radius): + def circle_particle_collide_test(self, pos, radius): for particle in self.particles: - if hypot(particle[0][0] - cursor_pos[0], particle[0][1] - cursor_pos[1]) <= cursor_radius + self.particle_radius: + if hypot(particle[0][0] - pos[0], particle[0][1] - pos[1]) <= radius + self.particle_radius: return True - - def add_wall(self, start, end): - self.walls.append((start, end)) \ No newline at end of file + + def circle_force(self, pos, radius, vector, dt): + for i, particle in enumerate(self.particles): + if hypot(particle[0][0] - pos[0], particle[0][1] - pos[1]) <= radius + self.particle_radius: + self.particles[i][1][0] += vector[0] * dt + self.particles[i][1][1] += vector[1] * dt + + def update(self, dt): + # substeps + for _ in range(self.substeps): + # update particles + for i, particle in enumerate(self.particles): + + # + + + # position + self.particles[i][0][0] += particle[1][0] * dt / self.substeps + self.particles[i][0][1] += particle[1][1] * dt / self.substeps \ No newline at end of file diff --git a/main.py b/main.py index 617eac1..158192f 100644 --- a/main.py +++ b/main.py @@ -2,6 +2,7 @@ import pygame import pygame.gfxdraw import gas_sim as gs import numpy as np +import random ##### CONFIG ##### window_size = (1280, 720) @@ -32,21 +33,13 @@ clock = pygame.time.Clock() # gas sim init -gas_sim = gs.GasSim(particle_radius_ws, particle_compressibility, particle_friction, substeps) - - -# add walls -gas_sim.add_wall((0, 0), (window_aspect, 0)) -gas_sim.add_wall((0, 1), (window_aspect, 1)) -gas_sim.add_wall((0, 0), (0, 1)) -gas_sim.add_wall((1, 0), (1, 1)) +gas_sim = gs.GasSim(particle_radius_ws, particle_compressibility, particle_friction, substeps, window_aspect) not_loaded_particles = True dt = target_fps / 1000 - # main loop while True: # events @@ -55,8 +48,31 @@ while True: pygame.quit() quit() + elif event.type == pygame.KEYDOWN: + # on s key press + if event.key == pygame.K_s: + # save particles to file + particles = tuple(pos for pos, _ in gas_sim.particles) + np.save("particles.npy", particles) - # on mouse down + print("Saved particles to file") + + # on l key press + elif event.key == pygame.K_l: + if not_loaded_particles: + # load particles from file + particles = np.load("particles.npy") + for particle in particles: + gas_sim.add_particle(particle) + + print("Loaded particles from file") + + not_loaded_particles = False + else: + print("Particles already loaded !!!") + + + # on left mouse down if pygame.mouse.get_pressed()[0]: mouse_pos_ss = pygame.mouse.get_pos() @@ -64,33 +80,20 @@ while True: mouse_pos_ws = (mouse_pos_ss[0] / window_size[1], mouse_pos_ss[1] / window_size[1]) # if not colliding with any particles - if not gas_sim.cursor_particle_collide_test(mouse_pos_ws, particle_radius_ws): + if not gas_sim.circle_particle_collide_test(mouse_pos_ws, particle_radius_ws): gas_sim.add_particle(mouse_pos_ws) - - # on s key press - if pygame.key.get_pressed()[pygame.K_s]: - # save particles to file - particles = tuple(pos for pos, _ in gas_sim.particles) - np.save("particles.npy", particles) - - print("Saved particles to file") - # on l key press - if not_loaded_particles and pygame.key.get_pressed()[pygame.K_l]: - # load particles from file - particles = np.load("particles.npy") - for particle in particles: - gas_sim.add_particle(particle) - - print("Loaded particles from file") - - not_loaded_particles = False + # on right mouse down + elif pygame.mouse.get_pressed()[2]: + # apply wind force + mouse_pos_ss = pygame.mouse.get_pos() + mouse_pos_ws = (mouse_pos_ss[0] / window_size[1], mouse_pos_ss[1] / window_size[1]) + gas_sim.circle_force(mouse_pos_ws, cursor_radius_ws, (0.2, random.uniform(-0.5, 0.5)), dt) # update particles - #gas_sim.update(dt) - + gas_sim.update(dt) diff --git a/particles.npy b/particles.npy index cf35a8f..5bb9c87 100644 Binary files a/particles.npy and b/particles.npy differ