Page 1 of 1

Particle Fun with Pygame

Posted: Thu Nov 12, 2009 11:58 pm
by Big Grizzle
Here is a small python script that creates a couple thousand particles and lets you throw them around. The particles all have a different rates of acceleration, top speeds and sizes. It has a rough approximation of gravity and friction. It took about 15 mins to write, but has a hypnotic effect on people who have used it!

## Controls ##
Arrow Keys - move particles
A - Turn Gravity on
Z - Turn Gravity off
X - Give each particle a random velocity
S - Stop particles
SPACE - Stop particles and give them a random new location
F - Give particles a random colour
R - Turn particles various shades of red.
G - Turn particles various shades of green.
B - Turn particles various shades of blue.
C - Turn particles various shades of red, green or blue.
K - Give background a random colour.
L - Reset background colour to black.

Code: Select all

import pygame, os, random
from pygame.locals import *

r = random
os.environ["SDL_VIDEO_WINDOW_POS"] = "150,50"

class Box(pygame.sprite.Sprite):
    def __init__(self, size=(32,32), pos=(100,100), colour=(r.randint(0,255),r.randint(0,255),r.randint(0,255)),acc=1,top=32):
        pygame.sprite.Sprite.__init__(self)
        self.screen = pygame.display.get_surface().get_rect()
        self.rect = pygame.Rect(pos,size)
        self.image = pygame.Surface(size)
        self.image.fill(colour)
        self.acc = acc
        self.top = top
        self.velocity = [0,0]
        self.gravity = 0.980665
        self.friction = 0.80999

    def update(self,velocity):
        self.key_input()
        self.rect = self.rect.move(velocity)

        if self.rect.x < 0 and self.velocity[0] < 0:
            self.rect.x = 0
            self.velocity[0] = (self.velocity[0]*0.8)
            self.velocity[0] *= -1

        if self.rect.right > self.screen.width and self.velocity[0] > 0:
            self.rect.x = (self.screen.width-self.rect.width)
            self.velocity[0] = (self.velocity[0]*0.8)
            self.velocity[0] *= -1

        if self.rect.y < 0  and self.velocity[1] < 0:
            self.rect.y = 0
            self.velocity[1] = (self.velocity[1]*0.8)
            self.velocity[1] *= -1

        if self.rect.bottom > self.screen.bottom:
            self.rect.y = self.screen.bottom - self.rect.height
            self.velocity[1] = (self.velocity[1]*0.8)
            self.velocity[1] *= -1

        
        if self.rect.bottom >= (self.screen.bottom):
            self.rect.y = self.screen.height - (self.rect.height*3)
            if self.velocity[1] > -3:
                self.velocity[1] = 0;
            self.velocity[0] *= self.friction
            
        self.velocity[1] += self.gravity
                            
    def key_input(self):
        keystate = pygame.key.get_pressed()
        if keystate[pygame.K_UP]:
            self.accelerate("up")
        if keystate[pygame.K_DOWN]:
            self.accelerate("down")
        if keystate[pygame.K_LEFT]:
            self.accelerate("left")
        if keystate[pygame.K_RIGHT]:
            self.accelerate("right")
        if keystate[pygame.K_q]:
            pygame.quit()

    def accelerate(self,direction):
        start_acc = 0
        if direction == "down":
            self.velocity[1] += self.acc
            if self.velocity[1] > self.top:
                self.velocity[1] = self.top

        elif direction == "up":
            self.velocity[1] -= (self.acc*4)
            if self.velocity[1] < -self.top:
                self.velocity[1] = -self.top

        if direction == "left":
            self.velocity[0] -= self.acc
            if self.velocity[0] > -3:
                start_acc = 4
                self.velocity[0] -= start_acc
            if self.velocity[0] < -self.top:
                self.velocity[0] = -self.top

        elif direction == "right":
            self.velocity[0] += self.acc
            if self.velocity[0] < 3:
                start_acc = 4
                self.velocity[0] += start_acc
            if self.velocity[0] > self.top:
                self.velocity[0] = self.top

pygame.init()
res = (400,300)
pos = (0,0)
screen = pygame.display.set_mode(res,NOFRAME)#, FULLSCREEN)
bg_rect = pygame.Rect(pos,res)
bg_image = pygame.Surface(res)
bg_image.fill((0,0,0))

p = []
p1 = []
p2 = []
p3 = []
for x in range(0,400):
    box = Box((r.randint(2,4),r.randint(2,4)),(r.randint(1,r.randint(1,res[0])),r.randint(1,r.randint(1,res[1]))),(r.randint(0,25),r.randint(0,25),r.randint(120,255)),r.randint(1,10),r.randint(20,32))
    box.image.set_alpha(100)
    p.append(box)
    p1.append(box)
    box = Box((r.randint(4,6),r.randint(4,6)),(r.randint(1,r.randint(1,res[0])),r.randint(1,r.randint(1,res[1]))),(r.randint(0,25),r.randint(0,25),r.randint(120,255)),r.randint(1,8),r.randint(20,32))
    p.append(box)
    p2.append(box)
    box = Box((r.randint(4,8),r.randint(4,8)),(r.randint(1,r.randint(1,res[0])),r.randint(1,r.randint(1,res[1]))),(r.randint(0,25),r.randint(0,25),r.randint(120,255)),r.randint(1,4),r.randint(20,32))
    box.image.set_alpha(80)
    p.append(box)
    p3.append(box)
screen.blit(bg_image,bg_rect)
for box in p:
    box.velocity = [r.randint(-32,32),r.randint(-32,32)]
    screen.blit(box.image,box.rect)

pygame.display.update()

clock = pygame.time.Clock()
started = False
while True:
    for event in pygame.event.get():
        if event.type == pygame.KEYDOWN:
            if event.type == pygame.QUIT:
                pygame.quit()
                if event.key == K_ESCAPE:
                    pygame.quit()
                    
    keystate = pygame.key.get_pressed()
    
    if keystate[pygame.K_SPACE]:
        for box in p:
            box.velocity = [0,0]
            box.rect.x = r.randint(1,res[0]-1)
            box.rect.y = r.randint(1,res[1]-1)
    
    if keystate[pygame.K_r]:
        for box in p:
            colour = (r.randint(120,255),r.randint(0,25),r.randint(0,25))
            box.image.fill(colour)
            
    if keystate[pygame.K_g]:
        for box in p:
            colour = (r.randint(0,25),r.randint(120,255),r.randint(0,25))
            box.image.fill(colour)

    if keystate[pygame.K_b]:
        for box in p:
            colour = (r.randint(0,25),r.randint(0,25),r.randint(120,225))
            box.image.fill(colour)
            
    if keystate[pygame.K_c]:
        for box in p:
            red = (r.randint(120,225),r.randint(0,25),r.randint(0,25))
            green = (r.randint(0,25),r.randint(120,225),r.randint(0,25))
            blue = (r.randint(0,25),r.randint(0,25),r.randint(120,225))
            colour = r.choice([red,green,blue])
            box.image.fill(colour)

    if keystate[pygame.K_x]:
        for box in p:
            box.velocity = [r.randint(-32,32),r.randint(-32,32)]

    if keystate[pygame.K_s]:
        for box in p:
            box.velocity = [0,0]

    if keystate[pygame.K_z]:
        for box in p:
            box.gravity = 0

    if keystate[pygame.K_a]:
        for box in p:
            box.gravity = 0.580665
    
    if keystate[pygame.K_f]:
	colour = (r.randint(0,255),r.randint(0,255),r.randint(0,255))
        for box in p:
            box.image.fill(colour)
            box.image.set_alpha(r.choice((80,120,81,121,255)))

			
    if keystate[pygame.K_l]:
        bg_image.fill((0,0,0))
		
    if keystate[pygame.K_k]:
        colour = (r.randint(0,100),r.randint(0,100),r.randint(0,100))
        bg_image.fill(colour)
		
    screen.blit(bg_image,bg_rect)
    for box in p:
        box.update(box.velocity)
        screen.blit(box.image,box.rect)
    pygame.display.flip()
    clock.tick(30)
    #print clock.get_fps()
It works on Python 2.5, Python 2.6 and requires the Pygame library.