one-file-projects/colortest.py

248 lines
8.3 KiB
Python
Raw Normal View History

2013-10-03 05:36:40 +02:00
import pygame
from pygame.locals import *
from random import random,randint
from math import sqrt
screen = None
color = (128,128,128)
color_vel = (0,0,0)
running = True
class Vector(tuple):
2016-02-18 14:38:39 +01:00
def __add__(self,other):
if len(self) != len(other):
raise Exception("Can't add vectors of different size: %d %d" % (len(self), len(other)))
return Vector([ self[i]+other[i] for i in range(len(self)) ])
2013-10-03 05:36:40 +02:00
2016-02-18 14:38:39 +01:00
def __sub__(self,other):
if len(self) != len(other):
raise Exception("Can't subtract vectors of different size")
return Vector([ self[i]-other[i] for i in range(len(self)) ])
2013-10-03 05:36:40 +02:00
2016-02-18 14:38:39 +01:00
def __mul__(self,factor):
return Vector([ self[i]*factor for i in range(len(self)) ])
2013-10-03 05:36:40 +02:00
2016-02-18 14:38:39 +01:00
def __div__(self,factor):
return self.__mul__(1.0/factor)
2013-10-03 05:36:40 +02:00
2016-02-18 14:38:39 +01:00
def __truediv__(self,factor):
return self.__div__(factor)
2013-10-03 05:36:40 +02:00
2016-02-18 14:38:39 +01:00
def __rmul__(self,factor):
return self.__mul__(factor)
2013-10-03 05:36:40 +02:00
2016-02-18 14:38:39 +01:00
def __rdiv__(self,factor):
raise NotImplemented
2013-10-03 05:36:40 +02:00
2016-02-18 14:38:39 +01:00
def __iadd__(self,other):
return self.__add__(other)
2013-10-03 05:36:40 +02:00
2016-02-18 14:38:39 +01:00
def __isub__(self,other):
return self.__sub__(other)
2013-10-03 05:36:40 +02:00
2016-02-18 14:38:39 +01:00
def __neg__(self):
return self.__mul__(-1.0)
2013-10-03 05:36:40 +02:00
2016-02-18 14:38:39 +01:00
def __setitem__(self,k,v):
raise Exception("Not available") # immutable
2013-10-03 05:36:40 +02:00
2016-02-18 14:38:39 +01:00
def distance(self, other):
if len(self) != len(other):
raise Exception("Can't calculate distance between vectors of different size")
return sqrt(sum([ (self[i]-other[i])**2 for i in range(len(self)) ]))
def length(self):
return self.distance( Vector( (0,0) ) )
2013-10-03 05:36:40 +02:00
class Tick(object):
2016-02-18 14:38:39 +01:00
def __init__(self, tickrange):
self.tickrange = tickrange
self.m_tick = 0
2013-10-03 05:36:40 +02:00
2016-02-18 14:38:39 +01:00
def tick(self):
self.m_tick = (self.m_tick+1)%self.tickrange
return self.m_tick == 0
2013-10-03 05:36:40 +02:00
class Mode(object):
2016-02-18 14:38:39 +01:00
def __init__(self, screensize):
self.screensize = screensize
2013-10-03 05:36:40 +02:00
2016-02-18 14:38:39 +01:00
def update(self):
pass
2013-10-03 05:36:40 +02:00
2016-02-18 14:38:39 +01:00
def draw(self,screen):
pass
2013-10-03 05:36:40 +02:00
def minmax(vmin,vmax):
2016-02-18 14:38:39 +01:00
return lambda v: min(vmax,max(vmin,v))
2013-10-03 05:36:40 +02:00
class TransitionMode(Mode):
2016-02-18 14:38:39 +01:00
t = 0.3
a = 30
def __init__(self, screensize):
Mode.__init__(self,screensize)
self.color = Vector( (127,127,127) )
self.color_vel = Vector( 2*self.a*random()+self.a for i in range(3) )
self.utick = Tick(10)
def update(self):
if self.utick.tick():
randvec = Vector( (2*self.a*random()-self.a) for i in range(3) )
self.color_vel = (1-self.t)*self.color_vel+self.t*randvec
self.color = Vector( map(minmax(0,255), self.color+self.color_vel) )
def draw(self,screen):
screen.fill( self.color )
2013-10-03 05:36:40 +02:00
class LelMode(Mode):
2016-02-18 14:38:39 +01:00
color = [(255,0,0),(0,255,0)]
size = 10
def __init__(self,screensize):
Mode.__init__(self,screensize)
self.offset = 0
self.tick = 0
def update(self):
self.offset = (self.offset+1)%2
def draw(self,screen):
w,h = screen.get_size()
for x in range(w):
color = self.color[ (x//self.size + self.offset)%2]
pygame.draw.line(screen, color, (x,0), (x,h) )
2013-10-03 05:36:40 +02:00
class BallMode(Mode):
2016-02-18 14:38:39 +01:00
def __init__(self,screensize):
Mode.__init__(self,screensize)
self.ball = [200,200]
self.radius = 70
self.velocity = [10,10]
def update(self):
w, h = self.screensize
if self.ball[0] + self.radius >= w:
self.velocity[0] = -abs(self.velocity[0])
elif self.ball[0] - self.radius < 0:
self.velocity[0] = abs(self.velocity[0])
elif self.ball[1] + self.radius >= h:
self.velocity[1] = -abs(self.velocity[1])
elif self.ball[1] - self.radius < 0:
self.velocity[1] = abs(self.velocity[1])
for i in range(2):
self.ball[i] += self.velocity[i]
def draw(self,screen):
screen.fill( (0,0,0) )
pygame.draw.circle(screen, (255,0,0), tuple(self.ball), self.radius)
2013-10-03 05:36:40 +02:00
class Particle:
2016-02-18 14:38:39 +01:00
def __init__(self,color, pos, vel):
self.color = color
self.pos = Vector(pos)
self.vel = Vector(vel)
2013-10-03 05:36:40 +02:00
2016-02-18 14:38:39 +01:00
def updateVel(self,gravity,max_v=20):
gravity = Vector(gravity)
2013-10-03 05:36:40 +02:00
2016-02-18 14:38:39 +01:00
#Update velocity
self.vel = 0.95*self.vel+0.01*random()*(gravity-self.pos)+0.1*random()*Vector( randint(-70,70) for i in range(2) )
2013-10-03 05:36:40 +02:00
2016-02-18 14:38:39 +01:00
#Limit speed
l = self.vel.length()
self.vel *= max_v/l
2013-10-03 05:36:40 +02:00
2016-02-18 14:38:39 +01:00
def updatePos(self):
self.pos = self.pos + self.vel
2013-10-03 05:36:40 +02:00
2016-02-18 14:38:39 +01:00
def draw(self,screen):
w,h = 1280,800
if self.pos[0] > 0 and self.pos[0] < w and self.pos[1] > 0 and self.pos[1] < h:
pos = tuple(map(int,self.pos))
velpos = tuple(map(int,self.pos+self.vel))
pygame.draw.circle(screen, self.color, pos, 5)
pygame.draw.line(screen, (255,255,255), pos, velpos, 1 )
2013-10-03 05:36:40 +02:00
2016-02-18 14:38:39 +01:00
@staticmethod
def generate(xmax,ymax):
return Particle( tuple( randint(100,255) for i in range(3) ), ( randint(0,xmax), randint(0,ymax) ), tuple( randint(-50,50) for i in range(2) ) )
2013-10-03 05:36:40 +02:00
class SwarmMode(Mode):
2016-02-18 14:38:39 +01:00
swarmsize = 60
def __init__(self,screensize):
Mode.__init__(self,screensize)
self.particles = list( Particle.generate(1280,800) for i in range(self.swarmsize) )
self.generateGravity()
self.gtick = Tick(150)
self.utick = Tick(2)
2015-11-01 14:36:52 +01:00
2016-02-18 14:38:39 +01:00
def generateGravity(self):
#self.gravity = tuple( randint(0,m) for m in [1280,800] )
self.gravity = Vector( (1280,800) )/2
2013-10-03 05:36:40 +02:00
2016-02-18 14:38:39 +01:00
def update(self):
if self.gtick.tick():
self.generateGravity()
2013-10-03 05:36:40 +02:00
2016-02-18 14:38:39 +01:00
v = self.utick.tick()
2013-10-03 05:36:40 +02:00
2016-02-18 14:38:39 +01:00
#king = self.particles[0]
#if v: king.updateVel(self.gravity, max_v=3)
#king.updatePos()
2013-10-03 05:36:40 +02:00
2016-02-18 14:38:39 +01:00
for p in self.particles:
if v: p.updateVel(self.gravity)
p.updatePos()
2013-10-03 05:36:40 +02:00
2016-02-18 14:38:39 +01:00
def draw(self,screen):
screen.fill( (0,0,0) )
for p in self.particles:
p.draw(screen)
2013-10-03 05:36:40 +02:00
class Game(object):
2016-02-18 14:38:39 +01:00
def __init__(self, modes=[SwarmMode,TransitionMode,LelMode,BallMode]):
self.modes = modes
pygame.init()
self.screen = pygame.display.set_mode( (1280,800), pygame.HWSURFACE )
pygame.mouse.set_visible(False)
self.setmode(0)
self.running = True
def update(self):
self.mode.update()
def setmode(self,i):
self.modeindex = i
self.mode = self.modes[i%len(self.modes)](self.screen.get_size())
def nextmode(self):
self.setmode( self.modeindex+1 )
def draw(self):
self.mode.draw(self.screen)
pygame.display.flip()
def getevents(self):
for event in pygame.event.get():
if event.type == QUIT:
self.running = False
elif event.type == KEYDOWN:
if event.key == K_ESCAPE:
pygame.event.post(pygame.event.Event(QUIT))
elif event.key == K_SPACE:
self.nextmode()
def run(self):
clock = pygame.time.Clock()
while self.running:
clock.tick(30)
self.getevents()
self.update()
self.draw()
2013-10-03 05:36:40 +02:00
if __name__ == '__main__':
2016-02-18 14:38:39 +01:00
Game().run()