#!/usr/bin/python import Image import ImageFont import math from ImageDraw import Draw import ps3 from ps3 import screen from ps3 import Blittable ############################################################################# # # style params tilesacross = 8 tilesup = 4 spaceup = 6 left = screen.width*7/100 top = screen.height*6/100 borderwidth = 5 # this determines how much screen space is lost due to overscan, etc #left = screen.xoff #top = screen.yoff tilewidth = (screen.width-2*left)/tilesacross tileheight = (screen.height-2*top)/(tilesup+spaceup+1) playwidth = tilewidth*tilesacross playheight = tileheight*tilesup fullheight = (tilesup+spaceup)*tileheight ############################################################################# # # construct graphics functions font = ImageFont.truetype("Vera.ttf", int(tileheight*1.8)) star = Image.open("star.png") def getText(font, colour, text): size = font.getsize(text) im = Image.new("RGBA", size, (0,0,0,0) ) draw = Draw(im) draw.text( (0,0), text, font=font, fill=colour) #mash to 16:9 by having horizontal size and taking half*3/4 of vertical im=im.resize( (size[0]*.5,size[1]*.375), Image.ANTIALIAS) #return Blittable(image=im) return Blittable(size=im.size, data=im.getdata()) def createBlock(width, height, colour, r=8): size = (width, height) im = Image.new("RGBA", size, (0,0,0,0) ) draw = Draw(im) draw.rectangle( ((r*2,r*2),(width-r*2,height-r*2)), fill=(colour[0],colour[1],colour[2],255) ) # inner = colour # colour = (colour[0]/2+128, colour[1]/2+128, colour[2]/2+128) colour = (colour[0]*3/4, colour[1]*3/4, colour[2]*3/4) inner = (colour[0], colour[1], colour[2], 192) for i in xrange(r): # c = (inner[0]*r/8,inner[1]*r/8,inner[2]*r/8,255) )` # draw.line( ((r+i,r+i), (width-1-r-i,r+i)), c) draw.rectangle( ((r+i,r+i),(width-1-r-i,height-1-r-i)), fill=(inner[0]*i/r+colour[0]*(r-i)/r,inner[1]*i/r+colour[1]*(r-i)/r,inner[2]*i/r+colour[2]*(r-i)/r,inner[3]*i/r+255*(r-i)/r) ) for i in xrange(r): c = (colour[0],colour[1],colour[2],i*256/r) #top lines draw.line( ((r,i),(width-1-r,i)), fill=c) draw.line( ((r,height-1-i),(width-1-r,height-1-i)), fill=c) #side lines draw.line( ((i,r),(i,height-1-r)), fill=c) draw.line( ((width-1-i,r),(width-1-i,height-1-r)), fill=c) #corner for j in xrange(r): c = (colour[0],colour[1],colour[2],i*j*256/r/r) draw.point( (i,j), fill=c) draw.point( (width-1-i,j), fill=c) draw.point( (i,height-1-j), fill=c) draw.point( (width-1-i,height-1-j), fill=c) return Blittable(im) def createBall(radius, colour): size = (radius*2,radius*2) im = Image.new("RGBA", size, (0,0,0,0) ) draw = Draw(im) for r in xrange(8): draw.ellipse( ((9*r,9*r),(2*radius-1-9*r,2*radius-1-9*r)), fill=(colour[0],colour[1],colour[2],255*8/(1+r)) ) return Blittable(im) def createBackground(w,h,pl,pt,pw,ph): im = Image.new("RGB", (w,h), (0,0,0,255)) draw = Draw(im) for x in xrange(pl,pl+pw,star.size[0]): for y in xrange(pt,h,star.size[1]): star2 = star xe=x+star.size[0] ye=y+star.size[1] if xe>pl+pw: xe=pl+pw if ye>h: ye=h star2 = star.crop( (0,0,xe-x,ye-y)) im.paste(star2, (x,y,xe,ye) ) # im = im.convert("RGB") b = Blittable(im) # b.transparency = 0 return b def getTile(x,y): return (int(math.floor(x/tilewidth)), int(math.floor(y/tileheight)), int(math.floor((x+ball.width-1)/tilewidth)), int(math.floor((y+ball.height-1)/tileheight))) ############################################################################# # # build images #bat = Blittable(Image.new("RGB",(tilewidth*3/2,tileheight/2),(255,255,255))) bat = createBlock(tilewidth*2,tileheight/2,(255,255,255), 4) ball = createBall(tileheight/4, (255,255,0)) red = createBlock(tilewidth,tileheight,(255,0,0)) green = createBlock(tilewidth,tileheight,(32,192,32)) blue = createBlock(tilewidth,tileheight,(48,48,255)) yellow = createBlock(tilewidth,tileheight,(255,255,0)) cyan = createBlock(tilewidth,tileheight,(0,255,255)) purple = createBlock(tilewidth,tileheight,(192,48,192)) bordertop = Blittable(Image.new("RGB",(playwidth+borderwidth*2,borderwidth),(255,255,255))) bordersides = Blittable(Image.new("RGB",(borderwidth,screen.height-top),(255,255,255))) background = createBackground(screen.width, screen.height, left, top, playwidth, fullheight) blocksRemaining = getText(font, (128,255,96), "Blocks remaining: ") livesRemaining = getText(font, (96,128,255), "Lives: ") numbers = [] for i in xrange(10): numbers.append(getText(font, (255,255,96), str(i))) ############################################################################ # # initial conditions paddlex = (tilesacross*tilewidth-bat.width)/2 paddley = fullheight ballx = (bat.width-ball.width)/2 + paddlex bally = paddley - ball.height + 1 resting = True balldx = 0 balldy = 0 controller = None def sign(x): if x<0: return -1 else: return 1 speed = tilewidth*tileheight/256 lives = 5 tiles = [] blocksleft = 0 for y in xrange(tilesup): row = [] for x in xrange(tilesacross): col = int(x+y*3.5) % 6 if (col == 0): tile = red elif (col == 1): tile = green elif (col == 2): tile = yellow elif (col == 3): tile = cyan elif (col == 4): tile = purple elif (col == 5): tile = blue else: tile = None if tile != None: blocksleft+=1 row.append(tile) tiles.append(row) ############################################################################ # # game loop while blocksleft>0 and lives>0: screen.clear() screen.blit(background, (0,0)) screen.blit(bordertop, (left-bordersides.width,top-bordertop.height) ) screen.blit(bordersides, (left-bordersides.width,top) ) screen.blit(bordersides, (left+bordertop.width-2*bordersides.width,top) ) for y in xrange(tilesup): row = tiles[y] for x in xrange(tilesacross): tile = row[x] if tile != None: screen.blit(tile, (left+x*tilewidth,top+y*tileheight)) joyspeed = 0 if controller == None: for c in ps3.controllers: if c.buttons[0] or (len(c.buttons)>13 and c.buttons[13]): controller = c joy = c.axes[0] paddlex += (joy * tilewidth / 32768 / 5) if resting: if controller != None and (controller.buttons[0] or (len(controller.buttons)>13 and controller.buttons[13])): resting = False balldx = int(math.sqrt(speed*speed/2)) balldy = -balldx if controller != None: joy = controller.axes[0] joyspeed = (joy * tilewidth / 32768 / 5) paddlex += joyspeed if paddlex < 0: paddlex = 0 elif paddlex >= playwidth-bat.width: paddlex = playwidth-bat.width if resting: bally = paddley - ball.height ballx = (bat.width-ball.width)/2 + paddlex balldx = 0 balldy = 0 screen.blit(ball, (left+ballx,top+bally) ) screen.blit(bat, (left+paddlex,top+paddley) ) oldpos = getTile(ballx,bally) ballx += balldx bally += balldy if ballx < 0: ballx = -ballx balldx = -balldx elif ballx > playwidth-ball.width: # r - (x-r) ballx = 2*(playwidth-ball.width) - ballx balldx = -balldx if bally < 0: bally = -bally balldy = -balldy elif bally >= screen.height-top-ball.height*2: resting = True lives -= 1 elif bally >= paddley+bat.height-ball.height: pass elif bally >= paddley-ball.height: bx1 = ballx+ball.width*.25 bx2 = ballx+ball.width*.75 px1 = paddlex px2 = paddlex+bat.width if (bx1 >= px1 and bx1 <= px2) or (bx2 >= px1 and bx2 <= px2): bally = 2*(paddley-ball.height) - bally fudge = joyspeed/8 fudge = (ballx+ball.height/2) - (paddlex+bat.width/2) fudge = fudge * 10 / bat.width oldsp = balldx*balldx + balldy*balldy balldx += fudge if abs(balldx)>0.75*speed: balldx = int(0.75*speed*sign(balldx)) oldsp = speed*speed - balldx*balldx if oldsp >= 1: balldy = -int(math.sqrt(oldsp)) else: balldy = -1 else: # paddle level, but missed pass try: pos = getTile(ballx,bally) if oldpos[1] < tilesup: if balldx < 0 and tiles[oldpos[1]][pos[0]] != None: tiles[oldpos[1]][pos[0]] = None balldx = -balldx blocksleft -= 1 elif balldx > 0 and tiles[oldpos[1]][pos[2]] != None: tiles[oldpos[1]][pos[2]] = None balldx = -balldx blocksleft -= 1 oballdy = balldy if pos[1] < tilesup and balldy < 0: if tiles[pos[1]][oldpos[0]] != None: tiles[pos[1]][oldpos[0]] = None balldy = -oballdy blocksleft -= 1 if tiles[pos[1]][oldpos[2]] != None: tiles[pos[1]][oldpos[2]] = None balldy = -oballdy blocksleft -= 1 if pos[3] < tilesup and balldy > 0: if tiles[pos[1]][oldpos[0]] != None: tiles[pos[1]][oldpos[0]] = None balldy = -oballdy blocksleft -= 1 if tiles[pos[1]][oldpos[2]] != None: tiles[pos[1]][oldpos[2]] = None balldy = -oballdy blocksleft -= 1 except: print "collision test broken, d=(",balldx,",",balldy,") oldpos=",oldpos," pos=",pos," ball at ",(ballx,bally) drawx = left + borderwidth drawy = top+paddley+bat.height screen.blit(blocksRemaining, (left,drawy)) drawx = drawx + blocksRemaining.width if blocksleft > 9: num = numbers[blocksleft/10] screen.blit(num, (drawx,drawy)) drawx += num.width num = numbers[blocksleft%10] screen.blit(num, (drawx,drawy)) drawx = left+playwidth - borderwidth num = numbers[lives] drawx -= num.width screen.blit(num, (drawx,drawy)) drawx -= livesRemaining.width screen.blit(livesRemaining, (drawx,drawy)) screen.flip() screen.wait() ############################################################################ # # end game miglu = Blittable(Image.open("miglu.jpg")) screen.clear() screen.blit(miglu, ((screen.width-miglu.width)/2,(screen.height-miglu.height)/2)) drawy = (screen.height+miglu.height)/2 + 40 if lives >0: text = "Well done!" else: text = "You kept missing... :(" message = getText(font, (64,64,192), text); screen.blit(message, ((screen.width-message.width)/2,drawy)) screen.flip() for i in xrange(120): screen.wait()