Created
October 17, 2012 03:17
-
-
Save admalledd/3903518 to your computer and use it in GitHub Desktop.
pygame joysticks and timedeltas
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import random | |
import itertools | |
import pygame | |
import pygame.gfxdraw | |
from pygame.locals import * | |
SIZE=(1024,768) | |
#generate colors: we have three tables: (x,0,0) (x,y,0), (x,y,z) where xyz locations are random | |
#meaning that we have primary colors, colors with two, and colors with all three | |
#for the "target" colors, we only allow 4 per primary (dark, dim, lit, bright) (64,128,192,255) | |
c_range=(192,255) | |
#first, ct1 | |
ct1=[] | |
for color in range(3): | |
for level in c_range: | |
tmp_color=[0,0,0] | |
tmp_color[color]=level | |
ct1.append(tuple(tmp_color)) | |
ct1=tuple(ct1) | |
#two randomish... | |
ct2=[] | |
for hold_this in range(3): | |
tmp_lists=[c_range,c_range,c_range] | |
tmp_lists[hold_this]=(0,0,0)#the one color we hold to 0 throughout | |
ct2.append(tuple(itertools.product(*tmp_lists))) | |
ct2=tuple(itertools.chain(*ct2)) | |
COLORS=(ct1,ct2) | |
ct3=tuple(itertools.product(c_range,repeat=3)) #all three colors | |
#COLORS=(ct1,ct2,ct3) | |
class joystick(object): | |
def __init__(self,pygamejoy): | |
self.joy = pygamejoy | |
self.right_stick = axi_pair('right',self.joy,2,3,(255,255,0),True) | |
self.left_stick = axi_pair('left',self.joy,2,3,(0,255,255),False) | |
def draw(self,screen,timedelta): | |
self.left_stick.draw(screen,timedelta) | |
self.right_stick.draw(screen,timedelta) | |
def reset(self): | |
self.left_stick.x_spd=0.0 | |
self.left_stick.y_spd=0.0 | |
self.left_stick.pos=(SIZE[0]/2,SIZE[1]/2) | |
self.right_stick.x_spd=0.0 | |
self.right_stick.y_spd=0.0 | |
self.right_stick.pos=(SIZE[0]/2,SIZE[1]/2) | |
class axi_pair(object): | |
def __init__(self,name,joy,x,y,color,invert): | |
self.name=name | |
self.invert=invert | |
self.x_axis=x | |
self.y_axis=y | |
self.joy=joy | |
self.x_spd=0.0 | |
self.y_spd=0.0 | |
self.pos=(SIZE[0]/2,SIZE[1]/2)#center of screen | |
self.color=list(color) | |
self.color_vector=[0,0,0] | |
self.new_color() | |
def update_vector(self,timedelta): | |
'''checks if it is time to update the vector speed yet. | |
uses two "times": time since last accel and time since last drag | |
TODO:: allow arbritrary frame rate by dividing the calculation by the time-per-frame | |
''' | |
#how much we speed up by | |
chgx = (self.joy.get_axis(self.x_axis)/500)*timedelta | |
chgy = (self.joy.get_axis(self.y_axis)/500)*timedelta | |
if self.invert: | |
chgx=-chgx | |
chgy=-chgy | |
self.x_spd+=chgx | |
self.y_spd+=chgy | |
#how much we slow down by | |
scale=1+((0.05/1000)*timedelta) | |
self.x_spd/=scale | |
self.y_spd/=scale | |
#print scale,timedelta | |
xs=self.x_spd if self.x_spd != 0.0 else float('inf') | |
ys=self.y_spd if self.y_spd != 0.0 else float('inf') | |
vdx = (scale/xs) - chgx | |
vdy = (scale/ys) - chgy | |
#print "%s vector = (%0.3f,%0.3f)<%0.3f,%0.3f> vd: {%0.3f,%0.3f}"%( | |
# self.name,chgx,chgy,self.x_spd,self.y_spd,vdx,vdy) | |
#check if we are below threshhold and set to 0 therefore (coast to stop, really) | |
#the and !=0 is so that we only print out the debug line once, if we move at all within the deadban it resets. | |
if 0.005 > self.x_spd > -0.005 and self.x_spd != 0.0: | |
self.x_spd = 0.0 | |
print "%s: haltx (%s)@<%s>"%(self.name,(self.x_spd,self.y_spd),self.pos) | |
if 0.005 > self.y_spd > -0.005 and self.y_spd != 0.0: | |
self.y_spd = 0.0 | |
print "%s: halty (%s)@<%s>"%(self.name,(self.x_spd,self.y_spd),self.pos) | |
return (self.x_spd,self.y_spd) | |
def new_color(self,color=None,time=2000): | |
'''get a new color and reset things for new vector calculations''' | |
if color is None: | |
color = list(random.choice(random.choice(COLORS))) | |
self.color_target=color | |
#print "%s new color: (%s)<%s>"%(self.name,color,self.color_target) | |
self.color_timestamp=0#current "time" since last self.new_color() | |
self.color_timetarget=time#how long it should take us to get to the new color | |
def update_color(self,timedelta): | |
'''change color only sligtly. | |
should take 2 seconds to fully transition no matter what, although the "vector" is chosen at the start. | |
''' | |
self.color_timestamp+=timedelta | |
#code to check "color distance" from target | |
if 7.5 > sum(self.color)-sum(self.color_target) > -7.5: | |
#we have made it to the target (ish) | |
#calculate new vector | |
self.new_color(None,2500) | |
for i in range(3): | |
#new vector | |
#color change remaining/time remaining == change per timestep | |
#change per timestep * timedelta == ammount we need to change for this many timesteps | |
color_delta=self.color_target[i]-self.color[i] | |
time_pressure=float(self.color_timetarget-self.color_timestamp) | |
#print "%s i:%s d = %0.3f tp = %s td = %s"%(self.name,i, color_delta,time_pressure,timedelta) | |
self.color_vector[i]=(color_delta/time_pressure)*timedelta | |
r,g,b=self.color | |
rv,gv,bv=self.color_vector | |
rt,gt,bt=self.color_target | |
#print "%s color change: k:%0.3f t:(%s,%s,%s) c:<%0.3f,%0.3f,%0.3f> v:{%0.3f,%0.3f,%0.3f}"%( | |
# self.name,sum(self.color)-sum(self.color_target),rt,gt,bt,r,g,b,rv,gv,bv) | |
for i in range(3): | |
#add vector | |
self.color[i]+=self.color_vector[i] | |
if self.color[i] > 255: self.color[i]=255.0 | |
elif self.color[i] < 0: self.color[i]=0.0 | |
def draw(self,screen,timedelta): | |
#move current pos to new coords by +- vector, but limit to size of screen. | |
x,y=self.pos | |
vec=self.update_vector(timedelta) | |
#invert joymotion here? | |
xx,yy=x+vec[0],y+vec[1] | |
#check screen limits, dont want to go outside those now... | |
rect=screen.get_rect() | |
#x | |
if xx > rect.right: | |
xx=rect.left #too far right | |
elif xx < rect.left: | |
xx=rect.right #too far left | |
#y | |
if yy > rect.bottom: | |
yy=rect.top #too far down | |
elif yy < rect.top: | |
yy=rect.bottom #too far up | |
#update color to semi-randomness... | |
self.update_color(timedelta) | |
##pygame.gfxdraw.pixel(screen,int(xx),int(yy),self.color) | |
pygame.draw.circle(screen,self.color,(int(xx),int(yy)),2,0) | |
self.pos=xx,yy | |
def main(): | |
pygame.init() | |
pygame.joystick.init() | |
screen = pygame.display.set_mode(SIZE,pygame.SRCALPHA) | |
clock=pygame.time.Clock() | |
j = pygame.joystick.Joystick(0) | |
j.init() | |
joy = joystick(j) | |
while True: | |
timedelta = clock.tick() | |
print "fps: %0.3f"%clock.get_fps() | |
events = pygame.event.get() | |
for event in events: | |
if event.type == QUIT: | |
pygame.quit() | |
return | |
elif event.type == MOUSEBUTTONDOWN and event.button==1: | |
print event.pos | |
elif event.type == KEYDOWN: | |
if event.key == K_ESCAPE: | |
pygame.quit() | |
return | |
elif event.key == K_SPACE: | |
#clear screen | |
screen.fill((0, 0, 0)) | |
joy.reset() | |
elif event.type == JOYBUTTONDOWN: | |
if event.button == 9: | |
#clear screen | |
screen.fill((0, 0, 0)) | |
joy.reset() | |
elif event.button == 10: | |
#left stick | |
joy.left_stick.pos=(SIZE[0]/2,SIZE[1]/2) | |
joy.left_stick.x_spd=0.0 | |
joy.left_stick.y_spd=0.0 | |
elif event.button == 11: | |
#right stick | |
joy.right_stick.pos=(SIZE[0]/2,SIZE[1]/2) | |
joy.right_stick.x_spd=0.0 | |
joy.right_stick.y_spd=0.0 | |
elif event.button == 6: | |
#left color | |
joy.left_stick.new_color() | |
elif event.button == 7: | |
#right color | |
joy.right_stick.new_color() | |
#no clearing of screen out of loop: keep all old points. | |
joy.draw(screen,timedelta) | |
pygame.display.flip() | |
if __name__ == '__main__': | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment