| @@ -1,76 +1,57 @@ | |||
| # Import the pygame library and initialise the game engine | |||
| import pygame | |||
| import numpy as np | |||
| from verlet import Ball, Spring | |||
| pygame.init() | |||
| # Initialize Pygame | |||
| size = (800, 800) | |||
| CENTER = np.array(size) / 2 | |||
| SIZE = (800, 800) | |||
| WHITE = (255, 255, 255) | |||
| DAMPING = 0.99 | |||
| screen = pygame.display.set_mode(size) | |||
| screen = pygame.display.set_mode(SIZE) | |||
| pygame.display.set_caption("Patrick") | |||
| running = True | |||
| clock = pygame.time.Clock() | |||
| class Ball(object): | |||
| def __init__(self, x, y, radius=10, mass=1): | |||
| self.pos = np.array([x, y]) | |||
| self.last_pos = np.array([x, y]) | |||
| self.velocity = np.array([0, 0]) | |||
| self.radius = radius | |||
| self.mass = mass | |||
| def physics(): | |||
| for ball in balls: | |||
| ball.update() | |||
| def render(self, screen): | |||
| x, y = self.pos + CENTER | |||
| pygame.draw.circle(screen, WHITE, [int(x), int(y)], self.radius, 2) | |||
| for spring in springs: | |||
| spring.update() | |||
| def update(self): | |||
| self.pos[1] += .05 | |||
| if self.pos[1] > 400: | |||
| self.pos[1] = 400 | |||
| self.last_pos[1] = 400 | |||
| self.velocity[1] = -.5 * self.velocity[1] | |||
| def draw(): | |||
| for ball in balls: | |||
| ball.render(screen) | |||
| self.pos += self.velocity | |||
| for spring in springs: | |||
| spring.render(screen) | |||
| self.velocity = self.pos - self.last_pos | |||
| self.velocity *= DAMPING | |||
| self.last_pos = np.array(self.pos) | |||
| class Spring(object): | |||
| def __init__(self, a, b, length=None, k=0.3): | |||
| self.a = a | |||
| self.b = b | |||
| self.k = k | |||
| self.length = self.compute_length() if length is None else length | |||
| print(self.length) | |||
| def render(self, screen): | |||
| x1, y1 = self.a.pos + CENTER | |||
| x2, y2 = self.b.pos + CENTER | |||
| pygame.draw.line(screen, WHITE, [x1, y1], [x2, y2]) | |||
| def compute_length(self): | |||
| x1, y1 = self.a.pos + CENTER | |||
| x2, y2 = self.b.pos + CENTER | |||
| return np.sqrt((x2 - x1)**2 + (y2 - y1)**2) | |||
| def update(self): | |||
| current_length = self.compute_length() | |||
| delta = self.b.pos - self.a.pos | |||
| delta /= current_length | |||
| stretch = (current_length - self.length) / self.length | |||
| self.a.velocity += stretch * delta * self.k | |||
| self.b.velocity -= stretch * delta * self.k | |||
| def boost(): | |||
| vector = springs[0].b.pos - springs[0].a.pos | |||
| length = springs[0].compute_length() | |||
| vector /= length | |||
| norm = np.array([vector[1], -vector[0]]) | |||
| balls[1].velocity += norm * .5 | |||
| if __name__ == '__main__': | |||
| balls = [Ball(0., 0.), Ball(100., 100.)] | |||
| springs = [Spring(balls[0], balls[1], length=100)] | |||
| balls = [Ball(0., 0., fixed=True), | |||
| Ball(0., 100.), | |||
| Ball(20., 120.), | |||
| Ball(-20., 120.), | |||
| Ball(0., 80.)] | |||
| springs = [ | |||
| Spring(balls[0], balls[1], length=100, k=3), | |||
| Spring(balls[1], balls[2], k=5), | |||
| Spring(balls[1], balls[3], k=5), | |||
| Spring(balls[2], balls[3], k=5), | |||
| Spring(balls[1], balls[4], k=5), | |||
| Spring(balls[2], balls[4], k=5), | |||
| Spring(balls[3], balls[4], k=5) | |||
| ] | |||
| while running: | |||
| for event in pygame.event.get(): | |||
| @@ -78,20 +59,9 @@ if __name__ == '__main__': | |||
| running = False | |||
| screen.fill((0, 0, 0)) | |||
| # Update physics | |||
| for ball in balls: | |||
| ball.update() | |||
| for spring in springs: | |||
| spring.update() | |||
| # Draw | |||
| for ball in balls: | |||
| ball.render(screen) | |||
| for spring in springs: | |||
| spring.render(screen) | |||
| physics() | |||
| boost() | |||
| draw() | |||
| pygame.display.flip() | |||
| clock.tick(60) | |||