Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/sprayplay.py
diff options
context:
space:
mode:
authorAlan Aguiar <alanjas@hotmail.com>2012-05-22 19:52:57 (GMT)
committer Alan Aguiar <alanjas@hotmail.com>2012-05-22 19:52:57 (GMT)
commita2d53bc60aa292a2a5d7f77173c95799ab4543aa (patch)
tree31b414d4e8b1d30e398a011ebbee1f9bb46af2fb /sprayplay.py
initial commit
Diffstat (limited to 'sprayplay.py')
-rw-r--r--sprayplay.py838
1 files changed, 838 insertions, 0 deletions
diff --git a/sprayplay.py b/sprayplay.py
new file mode 100644
index 0000000..6b43e6b
--- /dev/null
+++ b/sprayplay.py
@@ -0,0 +1,838 @@
+from __future__ import division
+from math import *
+import random
+
+import pygame
+
+from olpcgames import data_path
+from pygame import *
+from sprayconstants import *
+
+class StopGame(Exception):
+ pass
+
+def angleToDirection(angle):
+ return [cos(angle),sin(angle)]
+
+def lineNormal(la,lb):
+ "Returns normal vector to line"
+ lx = (lb[0]-la[0])/100.0 #for numerical reasons we divide down first, then normalize
+ ly = (lb[1]-la[1])/100.0
+ invnorml = 1.0/sqrt(lx*lx+ly*ly) #will blow up if two vertices are in same place!
+ nx = ly*invnorml
+ ny = -lx*invnorml
+ return [nx,ny]
+
+def consumeBullet(bullet,player):
+ "Consumes a bullet from the playing field, sending it either to player a or b's stash"
+ bullet.kill()
+ player.collectBall(bullet)
+
+
+def containBullet(bullet):
+ global players
+ if (bullet.y > CIRCLE_BORDER and bullet.y < SCREEN_HEIGHT-CIRCLE_BORDER and bullet.x > CIRCLE_BORDER+CIRCLE_RADIUS and bullet.x < SCREEN_WIDTH-CIRCLE_BORDER-CIRCLE_RADIUS):
+ return
+ xleft = (CIRCLE_BORDER+CIRCLE_RADIUS)
+ dxleft = bullet.x - xleft
+ xright = (SCREEN_WIDTH-CIRCLE_BORDER-CIRCLE_RADIUS)
+ dxright = bullet.x - xright
+ dyleft = bullet.y - (CIRCLE_BORDER+CIRCLE_RADIUS)
+ dyright = dyleft
+ dleftsqr = dxleft*dxleft+dyleft*dyleft
+ drightsqr = dxright*dxright+dyright*dyright
+ if dleftsqr < CIRCLE_RADIUS*CIRCLE_RADIUS or drightsqr < CIRCLE_RADIUS*CIRCLE_RADIUS:
+ return
+ if bullet.x < xleft:
+ if (bullet.y > SCREEN_HEIGHT/2 - COLLECTION_WIDTH/2 and bullet.y < SCREEN_HEIGHT/2 + COLLECTION_WIDTH/2):
+ vnorm = sqrt(bullet.vx*bullet.vx+bullet.vy*bullet.vy)
+ if vnorm < MAX_COLLECTION_VELOCITY:
+ consumeBullet(bullet,players[0])
+ dist = sqrt(dleftsqr)
+ direction = [ dxleft/(dist), dyleft/(dist) ]
+ bullet.x -= (dist+1-CIRCLE_RADIUS)*direction[0]
+ bullet.y -= (dist+1-CIRCLE_RADIUS)*direction[1]
+ bulldotdir = bullet.vx*direction[0]+bullet.vy*direction[1]
+ bullet.vx += -(1.0+WALL_DAMPING)*bulldotdir*direction[0]
+ bullet.vy += -(1.0+WALL_DAMPING)*bulldotdir*direction[1]
+ bullet.vx *= 1.0-WALL_FRICTION
+ bullet.vy *= 1.0-WALL_FRICTION
+ elif bullet.x > xright:
+ if (bullet.y > SCREEN_HEIGHT/2 - COLLECTION_WIDTH/2 and bullet.y < SCREEN_HEIGHT/2 + COLLECTION_WIDTH/2):
+ vnorm = sqrt(bullet.vx*bullet.vx+bullet.vy*bullet.vy)
+ if vnorm < MAX_COLLECTION_VELOCITY:
+ consumeBullet(bullet,players[1])
+ dist = sqrt(drightsqr)
+ direction = [dxright/(dist), dyright/(dist) ]
+ bullet.x -= (dist+1-CIRCLE_RADIUS)*direction[0]
+ bullet.y -= (dist+1-CIRCLE_RADIUS)*direction[1]
+ bulldotdir = bullet.vx*direction[0]+bullet.vy*direction[1]
+ bullet.vx += -(1.0+WALL_DAMPING)*bulldotdir*direction[0]
+ bullet.vy += -(1.0+WALL_DAMPING)*bulldotdir*direction[1]
+ bullet.vx *= 1.0-WALL_FRICTION
+ bullet.vy *= 1.0-WALL_FRICTION
+ elif bullet.y < CIRCLE_BORDER:
+ bullet.y = CIRCLE_BORDER+1
+ bullet.vy = abs(bullet.vy)*WALL_DAMPING
+ bullet.vx = (1.0-WALL_FRICTION)*bullet.vx
+ else:
+ bullet.y = SCREEN_HEIGHT - CIRCLE_BORDER-1
+ bullet.vy = -abs(bullet.vy)*WALL_DAMPING
+ bullet.vx = (1.0-WALL_FRICTION)*bullet.vx
+
+def applyGravity(bullet):
+ if bullet.x < GRAVITY_DIST:
+ bullet.vx -= GRAVITY_FORCE
+ elif bullet.x > SCREEN_WIDTH-GRAVITY_DIST:
+ bullet.vx += GRAVITY_FORCE
+ elif bullet.x < SCREEN_WIDTH/2.0:
+ bullet.vx -= GRAVITY_FORCE/5.0
+ else: bullet.vx += GRAVITY_FORCE/5.0
+
+
+def forceField(puck):
+ #print CIRCLE_RADIUS
+
+ if (puck[1] > CIRCLE_BORDER and puck[1] < SCREEN_HEIGHT-CIRCLE_BORDER and puck[0] > CIRCLE_BORDER+CIRCLE_RADIUS and puck[0] < SCREEN_WIDTH-CIRCLE_BORDER-CIRCLE_RADIUS):
+
+ return [0.0,0.0]
+ xleft = (CIRCLE_BORDER+CIRCLE_RADIUS)
+ dxleft = puck[0] - xleft
+ xright = (SCREEN_WIDTH-CIRCLE_BORDER-CIRCLE_RADIUS)
+ dxright = puck[0] - xright
+ dyleft = puck[1] - (CIRCLE_BORDER+CIRCLE_RADIUS)
+ dyright = dyleft
+ dleftsqr = dxleft*dxleft+dyleft*dyleft
+ drightsqr = dxright*dxright+dyright*dyright
+ if dleftsqr < CIRCLE_RADIUS*CIRCLE_RADIUS or drightsqr < CIRCLE_RADIUS*CIRCLE_RADIUS:
+ return [0.0,0.0]
+
+ #Now the puck is definitely outside of the arena.
+ #There are three different cases to deal with, left section, middle section, and right section.
+ dist = 0
+ direction = [0.0,0.0]
+ if puck[0] < xleft:
+ dist = sqrt(dleftsqr) - CIRCLE_RADIUS
+ direction = [ dxleft/(dist+CIRCLE_RADIUS), dyleft/(dist+CIRCLE_RADIUS) ]
+ elif puck[0] > xright:
+ dist = sqrt(drightsqr) - CIRCLE_RADIUS
+ direction = [dxright/(dist+CIRCLE_RADIUS), dyright/(dist+CIRCLE_RADIUS) ]
+
+ elif puck[1] < CIRCLE_BORDER:
+ dist = abs(CIRCLE_BORDER - puck[1])
+ direction = [0.0, -1.0]
+
+ else:
+ dist = abs(puck[1]-SCREEN_HEIGHT+CIRCLE_BORDER)
+ direction = [0.0,1.0]
+
+ factor = -.001*dist
+ return [direction[0]*factor,direction[1]*factor]
+
+
+class Background(pygame.sprite.Sprite):
+
+ group = pygame.sprite.Group()
+
+ def __init__(self):
+ super(Background, self).__init__(Background.group)
+ self.image = pygame.image.load(data_path('bg.png')).convert()
+ self.rect = self.image.get_rect()
+
+class Intro(pygame.sprite.Sprite):
+ def __init__(self,base,num_images,delay):
+ pygame.sprite.Sprite.__init__(self)
+
+ self.num_images = num_images
+ self.delay = delay
+ self.demos = [] # Array of demo images
+ for i in range(num_images):
+ img = pygame.image.load(data_path(base + str(i) + '.png')).convert_alpha()
+ self.demos.append(img)
+ self.image = self.demos[0]
+ self.rect = self.image.get_rect()
+ self.update(0)
+
+ def update(self,delta):
+ img_num = pygame.time.get_ticks()//(self.delay)%(self.num_images)
+ img = self.demos[img_num]
+ self.image = img
+ self.rect = img.get_rect()
+ self.rect.centery = SCREEN_HEIGHT / 2
+ self.rect.centerx = SCREEN_WIDTH / 2
+
+class Overlay(pygame.sprite.Sprite):
+
+ def __init__(self):
+ super(Overlay, self).__init__()
+ self.rect = pygame.Rect(0,0,SCREEN_WIDTH,SCREEN_HEIGHT)
+ self.image = pygame.Surface(self.rect.size).convert_alpha()
+ self.alpha = 150
+ self.image.fill((255,255,255,self.alpha))
+
+ self.dying = 0
+
+ def update(self,delta):
+ self.image.fill((255,255,255,self.alpha))
+ if self.dying:
+ self.alpha *= .9
+ if self.alpha < 10:
+ self.kill()
+
+class Bullet(pygame.sprite.Sprite):
+
+ group = pygame.sprite.Group()
+ orig_image = 0
+ color = (255,255,255)
+ speed = 0.2
+ radius = BULLET_RADIUS
+ mass = BULLET_MASS
+
+ def __init__(self, pos, direction):
+ super(Bullet, self).__init__( Bullet.group)
+# self.rect = pygame.Rect(0, 0, 2*self.radius, 2*self.radius)
+ self.image = pygame.transform.scale(Bullet.orig_image, (int(2*self.radius),int(2*self.radius)))
+ self.rect = self.image.get_rect()
+# self.image = pygame.Surface(self.rect.size).convert_alpha()
+# self.image.fill((0,0,0,0))
+# pygame.draw.circle(self.image, self.color,self.rect.center,int(self.radius))
+# pygame.draw.circle(self.image,(150,150,150),self.rect.center,int(self.radius-2))
+ self.rect.center = pos
+ self.direction = direction
+ self.vx = direction[0]*self.speed
+ self.vy = direction[1]*self.speed
+ self.x = pos[0]
+ self.y = pos[1]
+ self.lastx = self.x
+ self.lasty = self.y
+ self.noUpdate = 0
+
+ def update(self, delta):
+ if not self.noUpdate:
+ #self.rect.move_ip(delta*self.speed*self.direction[0], delta*self.speed*self.direction[1])
+ self.lastx = self.x
+ self.lasty = self.y
+ self.x += delta*self.vx#speed*self.direction[0]
+ self.y += delta*self.vy#speed*self.direction[1]
+ self.constrain()
+ applyGravity(self)
+ self.rect.center = self.x,self.y
+
+ def constrain(self):
+ containBullet(self)
+
+
+def crossing(pa, pb, ra, rb): #returns point of contact if lines p and r cross, 0 otherwise
+ x1 = pa[0]
+ y1 = pa[1]
+ x2 = pb[0]
+ y2 = pb[1]
+ x3 = ra[0]
+ y3 = ra[1]
+ x4 = rb[0]
+ y4 = rb[1]
+
+ ua = ( (x4-x3)*(y1-y3)-(y4-y3)*(x1-x3) )
+ ub = ( (x2-x1)*(y1-y3)-(y2-y1)*(x1-x3) )
+ denom = (y4-y3)*(x2-x1) - (x4-x3)*(y2-y1)
+ if (abs(denom) < .0001): return 0
+ ua /= denom
+ ub /= denom
+
+ if 0 < ua and ua < 1 and 0 < ub and ub < 1:
+ return [x1+ua*(x2-x1),y1+ua*(y2-y1)]
+ else:
+ return 0
+
+
+#declare puck vertices counterclockwise (i think)
+#also, these don't auto-close, so bear that in mind
+
+class Puck(pygame.sprite.Sprite):
+ group = pygame.sprite.Group()
+ massPerVertex = 1.0
+ color = [50,255,50]
+ edgeWidth = 4
+ bounceLoss = .3
+ bounceFriction = .4
+ fric = .02
+ rotFric = .02
+ puckTemplates = []
+
+ def __init__(self,pos, vertices,bearing_radius):
+ super(Puck,self).__init__(Puck.group)
+ self.vertices = vertices
+ minX = vertices[0][0]
+ maxX = minX
+ minY = vertices[0][1]
+ maxY = minY
+ sumX = 0
+ sumY = 0
+ for vertex in self.vertices:
+ sumX += vertex[0]
+ sumY += vertex[1]
+ if vertex[0] > maxX: maxX = vertex[0]
+ elif vertex[0] < minX: minX = vertex[0]
+ if vertex[1] > maxY: maxY = vertex[1]
+ elif vertex[1] < minY: minY = vertex[1]
+ sumX -= vertices[0][0] #since we have to manually close objects, remove dupe entry
+ sumY -= vertices[0][1]
+ self.cmx = sumX/float(len(vertices)-1)
+ self.cmy = sumY/float(len(vertices)-1)
+ self.vcmx = 0
+ self.vcmy = 0
+ self.moment = 0
+ self.width = maxX-minX
+ self.height = maxY-minY
+ for vertex in self.vertices:
+ vertex[0] -= self.cmx
+ vertex[1] -= self.cmy
+ self.moment += Puck.massPerVertex*(vertex[0]*vertex[0]+vertex[1]*vertex[1])
+ self.moment *= .3 #eh, why not, makes things more spinny
+ self.rect = pygame.Rect(-(maxX-minX),-(maxY-minY),2*(maxX-minX),2*(maxY-minY))
+ self.shape_rect = self.rect
+ self.image = pygame.Surface((SCREEN_WIDTH,SCREEN_HEIGHT)).convert_alpha()
+ self.bearing_radius = bearing_radius
+ self.bearing_image = pygame.transform.scale(Bullet.orig_image,(int(2*self.bearing_radius),int(2*self.bearing_radius))).convert_alpha()
+
+ self.theta = 0 #angle
+ self.omega = 0 #angular velocity
+ self.costheta = 1.0
+ self.sintheta = 0.0
+ self.mass = 6.0#self.massPerVertex*(len(self.vertices)-1)
+ self.cmx = pos[0]
+ self.cmy = pos[1]
+ self.drawnvertices = self.vertices[:]
+ self.expandEdges(BULLET_RADIUS*1.0)
+ self.update(0)
+
+ def update(self, delta):
+ #print self.rect.center
+ for obj in self.getVertices():
+ impulse = forceField(obj)
+ self.applyImpulse(impulse[0]*delta*.5, impulse[1]*delta*.5, obj[0], obj[1])
+ self.cmx += delta*self.vcmx
+ self.cmy += delta*self.vcmy
+ self.theta += delta*self.omega
+ self.costheta = cos(self.theta)
+ self.sintheta = sin(self.theta)
+ self.cosdtheta = cos(delta*self.omega)
+ self.sindtheta = sin(delta*self.omega)
+ self.omega *= 1.0-self.rotFric
+ self.vcmx *= 1.0-self.fric
+ self.vcmy *= 1.0-self.fric
+ self.image.fill((0,0,0,0))
+ self.image.get_rect().topleft = (0,0)
+ r = pygame.Rect(self.cmx-self.width,self.cmy-self.height,2*self.width,2*self.height)
+ pygame.draw.polygon(self.image,self.color+[200],self.getDrawnVertices()[:-1],0)
+ pygame.draw.polygon(self.image,(0,0,0,255),self.getDrawnVertices()[:-1],3)
+ self.image.blit(self.bearing_image,(r.centerx-self.bearing_radius,r.centery-self.bearing_radius))
+# pygame.draw.circle(self.image,self.color+[50],r.center,self.bearing_radius)
+# pygame.draw.circle(self.image,self.color+[255],r.center,self.bearing_radius,3)
+ self.rect = self.image.get_rect()
+ self.shape_rect = r
+
+
+ #def getRect(self):
+# return pygame.Rect(self.cmx-self.width,self.cmy-self.height,2*self.width,2*self.height)
+ #print self.rect
+
+ def expandEdges(self,rad):
+ #pushes out edges so that we can bypass "true" circle collision detection and still have it look pretty good
+ verticesa = []
+ for i in range(len(self.drawnvertices)-1):
+ normal = lineNormal(self.drawnvertices[i+1],self.drawnvertices[i])
+ normal[0] *= rad
+ normal[1] *= rad
+ verticesa.append( [self.drawnvertices[i ][0]+normal[0],self.drawnvertices[i ][1]+normal[1] ])
+ verticesa.append( verticesa[0] )
+ verticesb = []
+ normal = lineNormal(self.drawnvertices[0],self.drawnvertices[len(verticesa)-2])
+ normal[0] *= rad
+ normal[1] *= rad
+ verticesb.append( [self.drawnvertices[0][0]+normal[0],self.drawnvertices[0][1]+normal[1] ])
+ for i in range(1,len(self.drawnvertices)):
+ normal = lineNormal(self.drawnvertices[i],self.drawnvertices[i-1])
+ normal[0] *= rad
+ normal[1] *= rad
+ verticesb.append( [self.drawnvertices[i ][0]+normal[0],self.drawnvertices[i ][1]+normal[1] ])
+ self.vertices = []
+ for i in range(len(verticesa)):
+ self.vertices.append( verticesb[i] )#[ (verticesa[i][0]+verticesb[i][0])/2.0, (verticesa[i][1]+verticesb[i][1])/2.0 ] )
+ self.vertices.append( verticesa[i] )
+
+ def getVertices(self):
+ vlist = []
+ for vertex in self.vertices:
+ myX = self.cmx + self.costheta*vertex[0] + self.sintheta*vertex[1]
+ myY = self.cmy - self.sintheta*vertex[0] + self.costheta*vertex[1]
+ vlist.append( [myX,myY] )
+ return vlist
+
+ def getDrawnVertices(self):
+ vlist = []
+ for vertex in self.drawnvertices:
+ myX = self.cmx + self.costheta*vertex[0] + self.sintheta*vertex[1]
+ myY = self.cmy - self.sintheta*vertex[0] + self.costheta*vertex[1]
+ vlist.append( [myX,myY] )
+ return vlist
+ # myXdot = cmxdot + -thetadot sintheta vertex[0] + thetadot costheta vertex[1]
+
+ def handleCollision(self, bullet, delta):
+ if not 1:#(self.rect.collidepoint(bullet.x,bullet.y) or self.rect.collidepoint(bullet.lastx,bullet.lasty)):
+ #print self.rect
+ return 0
+ else:
+ vlist = self.getVertices()
+ for i in range(len(vlist)-1):
+ #First off we need the normal vector to surface
+ lx = (vlist[i+1][0]-vlist[i][0])/100.0 #for numerical reasons we divide down first, then normalize
+ ly = (vlist[i+1][1]-vlist[i][1])/100.0
+ invnorml = 1.0/sqrt(lx*lx+ly*ly) #will blow up if two vertices are in same place!
+ nx = ly*invnorml #maybe a sign error in these, check it out
+ ny = -lx*invnorml
+
+ #before the check, we've got to pre-alter the old velocity - note that we must fix this before we leave
+ preX = bullet.x
+ preY = bullet.y
+ difftocmx = preX - self.cmx
+ difftocmy = preY - self.cmy
+ afterrotx = self.cmx + self.cosdtheta*difftocmx - self.sindtheta*difftocmy
+ afterroty = self.cmy + self.sindtheta*difftocmx + self.cosdtheta*difftocmy
+ bullet.x = afterrotx - delta*self.vcmx
+ bullet.y = afterroty - delta*self.vcmy
+ contact = crossing(vlist[i],vlist[i+1],[bullet.x+nx,bullet.y+ny],[bullet.lastx,bullet.lasty])
+ bullet.x = preX
+ bullet.y = preY
+ #print contact
+ if contact:
+ #Gotta resolve this nasty collision...
+
+ #Find the distance from cm to contact point
+ dzx = (contact[0] - self.cmx)/10.0
+ dzy = (contact[1] - self.cmy)/10.0
+ dz = 100*sqrt( dzx*dzx+dzy*dzy )
+ #Use this to find the velocity of that point on the rigid body
+
+ vzx = self.vcmx+self.omega*(-self.sintheta*dzx+self.costheta*dzy)
+ vzy = self.vcmy+self.omega*(-self.costheta*dzx-self.sintheta*dzy)
+ #Now transform the bullet velocity into this frame
+ dyx = (bullet.x-bullet.lastx)/delta
+ dyy = (bullet.y-bullet.lasty)/delta
+ dyrx = dyx-vzx #relative components of velocity
+ dyry = dyy-vzy
+ #print nx,ny,lx,ly,dyrx,dyry
+ dyperp = dyrx*nx + dyry*ny
+ if dyperp > 0:
+ #we _actually_ have a collision, since the normal component is positive
+ #Set new bullet location to collision point
+ bullet.x = contact[0]
+ bullet.y = contact[1]
+ bullet.rect.center = bullet.x, bullet.y
+ #Find velocity changes
+ dynorm = sqrt(dyx*dyx+dyy*dyy)+.001
+ dyperpx = dyperp*nx
+ dyperpy = dyperp*ny
+ dyparx = dyx-dyperpx
+ dypary = dyy-dyperpy
+ deltayperpx = -(2.0-self.bounceLoss)*dyperpx
+ deltayperpy = -(2.0-self.bounceLoss)*dyperpy
+ deltayparx = -self.bounceFriction*dyparx
+ deltaypary = -self.bounceFriction*dypary
+ #pygame.draw.line(screen,(255,255,255),(contact[0],contact[1]),(contact[0]+deltayperpx,contact[1]+deltayperpy))
+ #Now apply these velocity changes
+ bullet.vx += deltayperpx+deltayparx
+ bullet.vy += deltayperpy+deltaypary
+
+ #And apply the resulting impulse to the rigid body...
+ self.applyImpulse(-(deltayperpx+deltayparx)*bullet.mass,-(deltayperpy+deltaypary)*bullet.mass,contact[0],contact[1])
+ #bullet.x += delta*bullet.vx #Eh, gotta get it out of there somehow, right?
+ #bullet.y += delta*bullet.vy #If I wasn't too lazy I'd figure out how far to actually move it, but .1 of a frame is a decent hack for now
+ #print contact[0],contact[1]
+
+ def applyImpulse(self, impx, impy, locx, locy):
+
+ self.vcmx += impx / self.mass
+ self.vcmy += impy / self.mass
+ rx = locx-self.cmx
+ ry = locy-self.cmy
+ torqueimp = impx*ry-impy*rx
+ self.omega += torqueimp / self.moment
+
+
+#CLASS CHANGED BY ERIC 12:30
+class Player(pygame.sprite.Sprite):
+
+ star = 0
+ group = pygame.sprite.Group()
+ player_filenames = ['player0.png','player1.png']
+
+
+ def __init__(self,pos,rot,player_num=1):
+ super(Player,self).__init__(Player.group)
+ self.orig_image = pygame.image.load(data_path(Player.player_filenames[player_num])).convert_alpha()
+
+ player_color = [255,0,0]
+
+ # Rotation and positioning of rect.
+ self.orig_rotate = rot # "baseline" CW rotation, in degrees
+ self.position = pos
+ self.image = pygame.transform.rotate(self.orig_image,-self.orig_rotate)
+ self.rect = self.image.get_rect()
+ self.rect.center = self.position
+
+ # Player variables.
+ self.theta = self.orig_rotate # *current* player rotation, in degrees CW
+ self.dtheta = 0
+ self.bulletSpeed = BULLET_SPEED
+ #self.ammo = AMMO_PER_PLAYER #added when bullets are populated
+ self.ammoList = pygame.sprite.Group()
+ self.storedBulletPositions = []
+ self.num_pucks = 0
+ self.trophyCase = 0
+ self.makeTrophyCase()
+ pygame.draw.rect(self.trophyCase, (0,100,0,255), self.trophyCase.get_rect(),5)
+
+ self.isHuman = 0
+
+ # Boolean keystate values.
+ self.turnRight = 0
+ self.turnLeft = 0
+ self.shootButton = 0
+ self.reloaded = 1
+ self.reloadTimer = 0
+ #self.ammoList = []
+ self.ammo = 0 #reset below...
+ self.generateStoredBulletPositions()
+
+ def makeTrophyCase(self):
+ self.trophyCase = pygame.Surface((200,60)).convert_alpha()
+ self.trophyPos = self.trophyCase.get_rect()
+ self.trophyPos.centerx = self.rect.centerx
+ self.trophyPos.top = 10
+ self.trophyCase.fill((0,0,0,0))
+ pygame.draw.rect(self.trophyCase, (0,100,0,255), self.trophyCase.get_rect(),5)
+
+
+ def reset(self):
+ self.theta = self.orig_rotate
+ self.dtheta = 0
+ self.ammoList = pygame.sprite.Group()
+ for i in range(AMMO_PER_PLAYER):
+ bullet = Bullet( [0.0,0.0], [0.0,0.0] )
+ consumeBullet(bullet, self)
+ #self.ammoList.add(bullet)
+
+ def update(self,delta):
+ self.theta = self.theta + self.dtheta
+ self.constrain()
+ self.image = pygame.transform.rotate(self.orig_image,-self.theta)
+ self.rect = self.image.get_rect()
+ self.rect.center = self.position
+ if not (self.turnRight or self.turnLeft):
+ self.dtheta = self.dtheta * ROTATION_DECAY
+ for i in range(len(self.ammoList.sprites())):
+ self.ammoList.sprites()[i].x = self.getStoredBulletPos(i)[0]
+ self.ammoList.sprites()[i].y = self.getStoredBulletPos(i)[1]
+
+ def generateStoredBulletPositions(self):
+ for i in range(2*AMMO_PER_PLAYER):
+ self.storedBulletPositions.append( self.genStoredBulletPos(i) )
+
+ def genStoredBulletPos(self,num):
+ rad = CIRCLE_RADIUS+2*BULLET_RADIUS
+ maxAngle = pi/2.0
+ ang = maxAngle*( (num)/(2.0*AMMO_PER_PLAYER) )
+ if num%2==0:
+ ang += maxAngle/(2.0*AMMO_PER_PLAYER)
+ ang *= -1
+ yC = SCREEN_HEIGHT/2.0 + rad*sin(ang)
+ if self.rect.center[0] < SCREEN_WIDTH/2:
+ xCenter = (CIRCLE_BORDER+CIRCLE_RADIUS)
+ xC = xCenter - rad*cos(ang)
+ else:
+ xCenter = (SCREEN_WIDTH-CIRCLE_BORDER-CIRCLE_RADIUS)
+ xC = xCenter + rad*cos(ang)
+ return [xC,yC]#self.rect.center[0]+diff, SCREEN_HEIGHT*( (num+.5)/(2.0*AMMO_PER_PLAYER+1) )]
+
+ def getStoredBulletPos(self, num):
+ return self.storedBulletPositions[num]
+
+ def constrain(self):
+ if (self.theta - self.orig_rotate) >= MAX_ROTATION:
+ self.theta = self.orig_rotate + MAX_ROTATION
+ if (self.theta - self.orig_rotate) <= -MAX_ROTATION:
+ self.theta = self.orig_rotate - MAX_ROTATION
+ if self.dtheta > ROTATION_SPEED:
+ self.dtheta = ROTATION_SPEED
+ if self.dtheta < -ROTATION_SPEED:
+ self.dtheta = -ROTATION_SPEED
+
+ def collectBall(self,bullet):
+ self.ammo += 1
+ bullet.noUpdate = 1
+ self.ammoList.add(bullet)
+
+
+ def hasAmmo(self):
+ if self.ammo > 0:
+ #print self.ammo, len(self.ammoList.sprites())
+ returnbullet = self.ammoList.sprites()[0]
+ returnbullet.kill()
+ return returnbullet#self.ammoList.sprites()[0]
+ else: return 0
+
+def genPucks(puckTemplates):
+ myBuf = []
+ for i in range(6+1):
+ leg = 15
+ if i%2==0: leg = 60
+ myBuf.append( [leg*sin(2*pi*i/6.0),leg*cos(2*pi*i/6.0)] )
+
+ puckTemplates.append(myBuf)
+
+ myBuf = []
+ for i in range(8+1):
+ leg = 15
+ if i%2==0: leg = 60
+ myBuf.append( [leg*sin(2*pi*i/8.0),leg*cos(2*pi*i/8.0)] )
+
+ puckTemplates.append(myBuf)
+
+ myBuf = []
+ for i in range(9+1):
+ leg = 45
+ if i%3==0: leg = 15
+ myBuf.append( [leg*sin(2*pi*i/9.0),leg*cos(2*pi*i/9.0)] )
+
+ puckTemplates.append(myBuf)
+
+ myBuf = []
+ for i in range(5+1):
+ leg = 60
+ myBuf.append( [leg*sin(2*pi*i/5.0),leg*cos(2*pi*i/5.0)] )
+
+ puckTemplates.append(myBuf)
+
+ myBuf = []
+ for i in range(3+1):
+ leg = 60
+ myBuf.append( [leg*sin(2*pi*i/3.0),leg*cos(2*pi*i/3.0)] )
+ puckTemplates.append(myBuf)
+
+
+GAME_WON = 0
+
+def newGame():
+ global GAME_WON
+ GAME_WON = 1
+ for player in Player.group:
+ player.makeTrophyCase()
+ player.num_pucks = 0
+
+def sendPuckToPlayer(puck,player):
+ dest = (player.num_pucks * 30 + 10,10)
+ scaled = pygame.transform.scale(player.star,(40,40))
+ player.trophyCase.blit(scaled,dest)
+
+ # Remove current puck from Puck.group
+ Puck.group.remove(puck)
+
+ player.num_pucks = player.num_pucks + 1
+ print player.num_pucks
+ newRound()
+
+def newRound():
+
+ for bullet in Bullet.group:
+ bullet.kill()
+ for player in Player.group:
+ player.reset()
+ if player.num_pucks == PUCKS_TO_WIN:
+ newGame()
+ # Add a new puck to the game.
+ whichPuck = int( len(Puck.puckTemplates)*random.random() )
+ Puck.group.add(Puck( pygame.display.get_surface().get_rect().center, Puck.puckTemplates[whichPuck],20 ))
+
+def applyAI(player):
+ #pick between turn left, turn right, shoot, and nothing
+ for puck in Puck.group:
+ cosx = cos((player.theta - 90)/180*pi)
+ sinx = sin((player.theta - 90)/180*pi)
+ bulletDir = [player.bulletSpeed * cosx,player.bulletSpeed * sinx]
+ slope = bulletDir[1]/bulletDir[0]
+ desiredSlope = (puck.cmy-player.rect.center[1])/(puck.cmx-player.rect.center[0])
+ #print desiredAngle, ang
+ #if player.rect.center[0]>SCREEN_WIDTH/2: desiredAngle -= pi
+ if slope>desiredSlope+random.random():
+ player.turnLeft = 1
+ player.turnRight = 0
+ elif slope<desiredSlope-random.random():
+ player.turnRight = 1
+ player.turnLeft = 0
+ if random.random()>.9:
+ player.shootButton = 1
+ else:
+ player.shootButton = 0
+
+players = []
+
+def main():
+ # Initialization
+ pygame.init()
+ screen = pygame.display.set_mode((SCREEN_WIDTH,SCREEN_HEIGHT))
+ background = Background()
+
+ # Initial game state.
+ overlay = Overlay()
+ #intro = Intro()
+ keyboard_intro = Intro('keyboard-',4,1000)
+ intro_group = pygame.sprite.Group(overlay,keyboard_intro)
+
+ clock = pygame.time.Clock()
+
+ # Bullet image.
+ Bullet.orig_image = pygame.image.load(data_path('ball.png')).convert_alpha()
+
+ # Star image.
+ Player.star = pygame.image.load(data_path('star.png')).convert_alpha()
+
+ # Players.
+ global players
+ a = Player((CIRCLE_BORDER + 80,SCREEN_HEIGHT//2),90,0)
+ b = Player((SCREEN_WIDTH-CIRCLE_BORDER - 80,SCREEN_HEIGHT//2),-90,1)
+ players = [a,b]
+
+ # Puck defs
+ genPucks(Puck.puckTemplates)
+
+ newRound()
+ try:
+ while True:
+ delta = clock.tick(25)
+
+ #delta = 1.0 / 25.0
+
+ for evt in pygame.event.get():
+ if evt.type == pygame.QUIT:
+ raise StopGame
+ elif evt.type == pygame.KEYDOWN:
+ if not overlay.dying:
+ overlay.dying = 1
+ keyboard_intro.kill()
+ if evt.key == pygame.K_F5:
+ newGame()
+ if evt.key == pygame.K_ESCAPE:
+ raise StopGame
+ if evt.key == pygame.K_RIGHT:
+ a.turnRight = 1
+ a.isHuman = 1
+ if evt.key == pygame.K_LEFT:
+ a.turnLeft = 1
+ a.isHuman = 1
+ if evt.key == pygame.K_RETURN:
+ a.shootButton = 1
+ a.isHuman = 1
+ overlay.kill()
+ if evt.key == pygame.K_d:
+ b.turnRight = 1
+ b.isHuman = 1
+ if evt.key == pygame.K_a:
+ b.turnLeft = 1
+ b.isHuman = 1
+ if evt.key == pygame.K_SPACE:
+ b.shootButton = 1
+ b.isHuman = 1
+ elif evt.type == pygame.KEYUP:
+ if evt.key == pygame.K_RIGHT:
+ a.turnRight = 0
+ a.isHuman = 1
+ if evt.key == pygame.K_LEFT:
+ a.turnLeft = 0
+ a.isHuman = 1
+ if evt.key == pygame.K_RETURN:
+ a.shootButton = 0
+ a.isHuman = 1
+ if evt.key == pygame.K_d:
+ b.turnRight = 0
+ b.isHuman = 1
+ if evt.key == pygame.K_a:
+ b.turnLeft = 0
+ b.isHuman = 1
+ if evt.key == pygame.K_SPACE:
+ b.shootButton = 0
+ b.isHuman = 1
+
+ if not a.isHuman:
+ applyAI(a)
+ if not b.isHuman:
+ applyAI(b)
+
+ # inject round-wining logic here.
+ for puck in Puck.group:
+ if puck.cmx > SCREEN_WIDTH - GRAVITY_DIST:
+ # Player 0 gets it.
+ sendPuckToPlayer(puck,players[0])
+ elif puck.cmx < GRAVITY_DIST:
+ # Player 1 gets it.
+ sendPuckToPlayer(puck,players[1])
+
+
+ # inject AI logic here.
+
+ for player in players:
+ if player.shootButton and player.reloaded:
+ bull = player.hasAmmo()
+ if bull:
+ bull.kill()
+ cosx = cos((player.theta - 90)/180*pi)
+ sinx = sin((player.theta - 90)/180*pi)
+ bulletDir = [player.bulletSpeed * cosx,player.bulletSpeed * sinx]
+ x = player.rect.center[0] + cosx * PLAYER_ARM_LENGTH
+ y = player.rect.center[1] + sinx * PLAYER_ARM_LENGTH
+ Bullet( (x,y),bulletDir )
+ player.ammo -= 1
+ player.reloaded = 0
+ player.reloadTimer = int((1.0 + RELOAD_RANDOM*2*(random.random()-.5))*RELOAD_DELAY)
+ if not player.reloaded:
+ player.reloadTimer -= 1
+ if player.reloadTimer == 0:
+ player.reloaded = 1
+ if player.turnRight:
+ player.dtheta = player.dtheta + ROTATION_SPEED / 15.0
+ if player.turnLeft:
+ player.dtheta = player.dtheta - ROTATION_SPEED / 15.0
+
+
+ # Update phase
+ Bullet.group.update(delta)
+ Player.group.update(delta)
+ Puck.group.update(delta)
+
+ #ADDED BY ERIC 12:30
+ for player in players:
+ player.ammoList.update(delta)
+
+ for bullet in Bullet.group:
+ for puck in Puck.group:
+ puck.handleCollision(bullet,delta)
+
+ # Draw phase
+ Background.group.draw(screen)
+ Bullet.group.draw(screen)
+ Player.group.draw(screen)
+ Puck.group.draw(screen)
+ #ADDED BY ERIC 12:30
+ for player in players:
+ player.ammoList.draw(screen)
+ screen.blit(player.trophyCase,player.trophyPos)
+ intro_group.update(delta)
+ intro_group.draw(screen)
+
+ pygame.display.flip()
+ except StopGame:
+ pass
+
+if __name__ == '__main__':
+ main()
+