210 lines
6.6 KiB
Python
210 lines
6.6 KiB
Python
import pygame
|
|
import sys
|
|
import random
|
|
import objects
|
|
import math
|
|
|
|
class Particle():
|
|
def __init__(self, x, y, size, color):
|
|
self.x = x
|
|
self.y = y
|
|
self.size = size
|
|
self.colour = color
|
|
self.thickness = 1
|
|
self.speed = 2
|
|
self.angle = math.pi
|
|
self.drag = 0.999
|
|
self.elasticity = 0.75
|
|
self.selected = False
|
|
|
|
def bounce(self, width, height):
|
|
left_border = 0
|
|
rightborder = width
|
|
top = 0
|
|
bottom = height
|
|
|
|
if self.x+self.size >= rightborder:
|
|
#self.speed = 0
|
|
self.x = 2 * (width - self.size) - self.x
|
|
self.angle = - self.angle
|
|
self.speed *= self.elasticity
|
|
|
|
if self.x-self.size <= left_border:
|
|
#self.speed = 0
|
|
self.x = 2 * self.size - self.x
|
|
self.angle = - self.angle
|
|
self.speed *= self.elasticity
|
|
|
|
if self.y+self.size >= bottom:
|
|
#self.speed = 0
|
|
self.y = 2 * (height - self.size) - self.y
|
|
self.angle = math.pi - self.angle
|
|
self.speed *= self.elasticity
|
|
|
|
if self.y-self.size <= top:
|
|
#self.speed = 0
|
|
self.y = 2 * self.size - self.y
|
|
self.angle = math.pi - self.angle
|
|
self.speed *= self.elasticity
|
|
|
|
|
|
|
|
def move(self):
|
|
self.x += math.sin(self.angle) * self.speed
|
|
self.y -= math.cos(self.angle) * self.speed
|
|
|
|
# Gravity
|
|
self.angle, self.speed = addVectors(self.angle, self.speed, math.pi, 0.02)
|
|
|
|
# Drag - if im understanding it ast the ball moves its losing 0.001 of its speed
|
|
drag = 0.999
|
|
self.speed *= drag
|
|
|
|
def display(self, surface):
|
|
pygame.draw.circle(surface, self.colour, (self.x, self.y), self.size)
|
|
|
|
class EntityObject():
|
|
def __init__(self, parent, x, y):
|
|
self.radius = 32
|
|
self.parent = parent
|
|
self.color = (255, 255, 255)
|
|
self.surface = pygame.Surface((64, 64), pygame.SRCALPHA, 32)
|
|
self.rect = pygame.draw.circle(self.surface, self.color, (self.radius, self.radius), self.radius)
|
|
|
|
self.position = objects.Vector(x, y)
|
|
|
|
def update(self):
|
|
pass
|
|
|
|
def show(self):
|
|
self.parent.blit(self.surface, (self.position.x, self.position.y))
|
|
|
|
|
|
def addVectors(angle1, length1, angle2, length2):
|
|
x = math.sin(angle1) * length1 + math.sin(angle2) * length2
|
|
y = math.cos(angle1) * length1 + math.cos(angle2) * length2
|
|
length = math.hypot(x, y)
|
|
angle = 0.5 * math.pi - math.atan2(y, x)
|
|
return (angle, length)
|
|
|
|
class Game():
|
|
def __init__(self):
|
|
super(Game, self).__init__()
|
|
self.height = 760
|
|
self.width = 1280
|
|
self.window = pygame.display.set_mode((self.width, self.height))
|
|
self.window_rect = self.window.get_rect()
|
|
self.clock = pygame.time.Clock()
|
|
self.window.set_colorkey((35, 35, 35))
|
|
self.debug_grid = True
|
|
self.background = (35, 35, 35)
|
|
|
|
self.particles = []
|
|
|
|
n_particles = 30
|
|
|
|
for _ in range(n_particles):
|
|
size = random.randint(20, 40)
|
|
red = random.randint(100, 255)
|
|
blue = random.randint(100, 255)
|
|
green = random.randint(100, 255)
|
|
x = random.randint(size, self.width-size)
|
|
y = random.randint(size, self.height-size)
|
|
particle = Particle(x, y, size, (red, blue, green))
|
|
particle.speed = random.random() + 2
|
|
particle.angle = random.uniform(0, math.pi*2)
|
|
self.particles.append(particle)
|
|
|
|
def main(self):
|
|
self.event_handler()
|
|
self.update()
|
|
self.blit()
|
|
|
|
def event_handler(self):
|
|
"""
|
|
This method handles mouse and keyboard events for the scene and passes
|
|
them on as is needed.
|
|
"""
|
|
for event in pygame.event.get():
|
|
if event.type == pygame.QUIT:
|
|
pygame.quit()
|
|
sys.exit(0)
|
|
if event.type == pygame.MOUSEBUTTONDOWN:
|
|
mouseX, mouseY = pygame.mouse.get_pos()
|
|
selected_particle = self.findParticle(mouseX, mouseY)
|
|
if selected_particle:
|
|
selected_particle.selected = True
|
|
if event.type == pygame.MOUSEBUTTONUP:
|
|
self.unselectParticles()
|
|
|
|
|
|
def update(self):
|
|
pass
|
|
|
|
def unselectParticles(self):
|
|
for particle in self.particles:
|
|
particle.selected = False
|
|
|
|
def findParticle(self, mouseX, mouseY):
|
|
for particle in self.particles:
|
|
if math.hypot(particle.x-mouseX, particle.y-mouseY) <= particle.size:
|
|
return particle
|
|
return None
|
|
|
|
def collide(self, p1, p2):
|
|
dx = p1.x - p2.x
|
|
dy = p1.y - p2.y
|
|
|
|
distance = math.hypot(dx, dy)
|
|
if distance < p1.size + p2.size:
|
|
print('Bang!')
|
|
tangent = math.atan2(dy, dx)
|
|
p1.angle = 2 * tangent - p1.angle
|
|
p2.angle = 2 * tangent - p2.angle
|
|
(p1.speed, p2.speed) = (p2.speed, p1.speed)
|
|
p1.speed *= p1.elasticity
|
|
p2.speed *= p2.elasticity
|
|
angle = 0.5 * math.pi + tangent
|
|
p1.x += math.sin(angle)
|
|
p1.y -= math.cos(angle)
|
|
p2.x -= math.sin(angle)
|
|
p2.y += math.cos(angle)
|
|
|
|
def blit(self):
|
|
self.window.fill(self.background)
|
|
if self.debug_grid:
|
|
for y in range(1, int(self.window_rect.height/32) + 1):
|
|
pygame.draw.line(self.window, (150, 150, 150), (0, y * 32), (self.window_rect.width, y * 32))
|
|
|
|
for x in range(1, int(self.window_rect.width/32) + 1):
|
|
pygame.draw.line(self.window, (150, 150, 150), (x * 32, 0), (x * 32, self.window_rect.height))
|
|
|
|
for i, particle in enumerate(self.particles):
|
|
if not particle.selected:
|
|
particle.move()
|
|
particle.bounce(self.width, self.height)
|
|
for particle2 in self.particles[i+1:]:
|
|
self.collide(particle, particle2)
|
|
else:
|
|
mouseX, mouseY = pygame.mouse.get_pos()
|
|
#particle.x = mouseX
|
|
#particle.y = mouseY
|
|
dx = mouseX - particle.x
|
|
dy = mouseY - particle.y
|
|
particle.angle = math.atan2(dy, dx) + 0.5 * math.pi
|
|
particle.speed = math.hypot(dx, dy) * 0.1
|
|
particle.display(self.window)
|
|
|
|
|
|
pygame.display.flip()
|
|
self.clock.tick(60)
|
|
|
|
|
|
pygame.display.set_caption('Physics galore!')
|
|
|
|
pygame.init()
|
|
pygame.font.init()
|
|
scene = Game()
|
|
|
|
while scene is not None:
|
|
scene.main() |