[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

Re: [pygame] Rain Generator



I always forget to attach files - here are the rain and snow I just talked about  :P


import random
import pygame
import psyco
psyco.full()

screen = pygame.display.set_mode([320,240])
colmap = [[0 for x in range(320)] for y in range(240)]
col_width = len(colmap[0])
col_height = len(colmap)
lowestflake = [col_height]
windtunnel = [0,60,320,10]
windpower = [0,0]
buggy = [10,10,10,5]
def p_in_c(point):
    """Returns 1 if that coordinate is in the coordinate map"""
    return point[1]<col_height and point[1]>=0 and point[0]<col_width and point[0]>=0
def getc(point):
    """Returns 1 if that point is out of bounds or if that point contains a snowflake"""
    if p_in_c(point):
        if point[0]>=buggy[0] and point[0]<=buggy[0]+buggy[2] and point[1]>=buggy[1] and point[1]<=buggy[1]+buggy[3]:
            return 1
        return colmap[point[1]][point[0]]
    if point[1]<col_height:
        if point[1]>lowestflake[0]:
            return 1
        return 0
    return 1
def setc(point,val):
    if p_in_c(point):
        if point[1]<lowestflake[0]:
            lowestflake[0] = point[1]
        colmap[point[1]][point[0]] = val

img_flake = pygame.Surface([1,1])
img_flake.fill([255,255,255])
grav = 9.8/60.0
wind = [-20.0/60.0,-1.0/60.0]

class SnowFlake:
    def __init__(self,pos):
        self.lastpos = pos[:]
        self.pos = pos[:]
        #setc([int(x) for x in self.pos],1)
        self.vel = [0,0.2]
        self.lastsurf = pygame.Surface([1,1])
        self.deadtime = 3
        self.rolltime = 10
    def move(self):
        force = [0,grav]
        if self.pos[0]>=windtunnel[0] and self.pos[0]<=windtunnel[0]+windtunnel[2] and self.pos[1]>=windtunnel[1] and self.pos[1]<=windtunnel[1]+windtunnel[3]:
            force[0]+=windpower[0]
            force[1]+=windpower[1]
        self.lastpos = self.pos[:]
        self.pos[0]+=self.vel[0]+0.2*random.choice([-1,1])+wind[0]
        self.pos[1]+=self.vel[1]/20.0+wind[1]
        self.vel[0]+=force[0]
        self.vel[1]+=force[1]
        lp = [int(x) for x in self.lastpos]  #last pixel
        np = [int(x) for x in self.pos]  #Now pixel
        dx = np[0]-lp[0]  #x change in pixels
        dy = np[1]-lp[1]  #y change in pixels
        if dx:
            dx = dx/abs(dx)  #Get direction of change x
        if dy:
            dy = dy/abs(dy)  #Get directionof change y
        #Draw line from last pixel to current pixel, find walls
        lx,ly = lp[0],lp[1]  #lastx pixel and lasty pixel
        x,y=lp[0],lp[1]
        p=None  #p is a spot where we were blocked
        while x!=np[0] or y!=np[1]:
            lx,ly=x,y
            if x!=np[0]:
                x+=dx
            if y!=np[1]:
                y+=dy
            if getc([x,y]):
                p = [lx,ly]  #blocked
                break
        x,y = np[0],np[1]
        if getc([x,y]) and not p:
            p = [lx,ly]
        if p:
            x,y = p
            left = getc([x-1,y+1])
            right = getc([x+1,y+1])
            down = getc([x,y+1])
            canroll = self.rolltime>0
            if not down:
                self.pos = [x,y+1]
            elif left and not right:
                self.pos = [x+1,y+1]
            elif not left and right:
                self.pos = [x-1,y+1]
            elif not left and not right:
                self.pos = [random.choice([x-1,x+1]),y]
            else:
                self.pos = [x,y]
                np = [int(x) for x in self.pos]
                self.deadtime -= 1
                setc(np,1)
        #if self.pos[0]<0:
        #    print "x out of bounds"
        #    raise Error
        #if self.pos[1]>240:
        #    print "oops?",self.pos[1],p,lp,np
        #    raise Error
    def draw(self):
        np = [int(x) for x in self.pos]
        self.lastsurf.blit(screen,np)
        screen.blit(img_flake,np)
        if self.lastpos != self.pos:
            screen.blit(self.lastsurf,[int(x) for x in self.lastpos])
        

flakes = []
numflakes = 500
def addflake():
    y = random.randint(-500,10)
    x = random.randint(0,420)
    f = SnowFlake([x,y])
    f.vel[0] = random.choice([-1,1])*0.05
    f.vel[1] = (y+1000)*.02
    flakes.append(f)
[addflake() for i in range(numflakes)]


pygame.event.clear()
pygame.event.pump()
c = pygame.time.Clock()

pygame.draw.rect(screen,[255,0,0],[10,10,10,5])

while 1:
    c.tick(60)
    flakes = [f for f in flakes if f.deadtime>0]
    [f.draw() for f in flakes]
    pygame.display.update()
    [f.move() for f in flakes]
    pygame.event.pump()
    if pygame.event.get(pygame.KEYDOWN):
        break
    [addflake() for x in xrange(numflakes-len(flakes))]
#init stuff
import pygame
import pygame.locals as l
import random
screen = pygame.display.set_mode([640,480])

class drop:
	def __init__(self,posx,posy):
		self.pos = [posx,posy]
	def __getattr__(self,attr):
		if attr=="x":
			return self.pos[0]
		if attr=="y":
			return self.pos[1]
		return drop.__get__(self,attr)
	def __getitem__(self,it):
		return self.pos[it]


class splash(drop):
	def __init__(self,posx,posy,xdirection):
		self.pos = [posx,posy]
		self.xdir = xdirection
		self.ydir = -1
		self.bounces = 0

drops = []   #list of points where a drop is
splashes = []  #list of points/direction/time [x,y,dx,dy,t] where a splash is
lands = [[0,100,110],[233,400,300],[200,300,150]]  #list of lines (x1,x2,y) for land

maxdrops = 50
maxsplashes = 400

def addDrop(posx,posy):
	if len(drops)<maxdrops:
		drops.append(drop(posx,posy))
def addSplash(posx,posy,xdirection):
	if len(splashes)<maxsplashes:
		splashes.append(splash(posx,posy,xdirection))

#For cool fading, darken the background each frame
dark = screen.convert()
dark.fill([0,0,0])
dark.set_alpha(5)

#Faster than drawing lines
splashsurf = pygame.Surface([1,1])
splashsurf.fill([0,0,255])

rainsurf = pygame.Surface([1,20])
rainsurf.fill([0,0,255])

mousesurf = pygame.Surface([20,20])
mousesurf.fill([200,200,200])

meep = pygame.Surface([10,10])
meep.fill([200,20,30])
meepx = 0
meepy = screen.get_height()-10
meepdir = 1

#Keep track of the clock
c = pygame.time.Clock()

#main loop
die = 0
keys = pygame.key.get_pressed()
while not keys[l.K_ESCAPE] and not die:
	c.tick(60)
	pygame.event.pump()
	keys = pygame.key.get_pressed()
	
	#make current screen darker
	screen.blit(dark,[0,0])
	
	mx,my = pygame.mouse.get_pos()
	
	#Draw land
	for line in lands:
		pygame.draw.line(screen,[0,200,0],[line[0],line[2]],[line[1],line[2]],2)
	
	#draw meep
	screen.blit(meep,[meepx-5,meepy])
	#maybe meep changes direction?
	if random.randint(0,100)>80:
		meepdir = random.randint(-1,1)
		#he should head to the right
		if random.randint(0,100)>20:
			meepdir = 1
	#move meep
	if meepx>0 and meepdir == -1 or meepx<screen.get_width() and meepdir == 1:
		meepx += meepdir
	
	#draw all drops and update their position
	for d in drops:
		pos = d.pos
		d.pos[1]+=20
		dosplash = 0
		if abs(d.x-mx)<20 and abs(d.y-my)<20:
			d.pos[1] = my-20
			dosplash = 1
		else:
			for line in lands:
				if d.pos[0]>=line[0] and d.pos[0]<=line[1] and d.pos[1]>line[2]:
					d.pos[1] = line[2]
					dosplash = 1
		if not dosplash and d.y>=meepy and d.x>=meepx-5 and d.x<=meepx+5:
			die = 1
			dosplash = 1
		if not dosplash and d.y>screen.get_height():
			d.pos[1] = screen.get_height()
			dosplash = 1
		if dosplash:
			addSplash(d.x,d.y,random.choice([-1,1]))
			drops.remove(d)
		screen.blit(rainsurf,[pos[0],pos[1]-20])
			
	#Draw all splashes and update their position
	for s in splashes:
		screen.blit(splashsurf,s.pos)
		#pygame.draw.line(screen,[0,0,255],s.pos,s.pos,1)
		if s.y>screen.get_height():
			s.y = screen.get_height()
			s.ydir = -1
			s.bounces += 1
		if abs(s.x-mx)<20 and abs(s.y-my)<20:
			s.y = my-20
			s.ydir = -1
			s.bounces += 1
		if s.x<0 or s.x>screen.get_width() or s.bounces>10:
			splashes.remove(s)
		else:
			s.pos[0]+=s.xdir*3
			s.pos[1]+=s.ydir*3  #move in y direction
			s.ydir+=.1
		
	#make new drops
	for i in range(5):  
		x = random.randint(0,screen.get_width())
		#y = random.randint(0,screen.get_height())
		addDrop(x,0)
		
	#Update screen
	screen.blit(mousesurf,[mx-10,my-10])
	pygame.display.flip()
while not keys[l.K_ESCAPE]:
	pygame.event.pump()
	keys = pygame.key.get_pressed()