-
-
Save anonymous/b2739c37b139f9b057b7 to your computer and use it in GitHub Desktop.
a_walk
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
#example of animated frames for a character walk. | |
#downloads a soldier sprite sheet, cuts out frames for the walk cycles in 4 directions | |
# and animates the character walking in the direction controlled by gravity. | |
from scene import * | |
from PIL import Image | |
import urllib, os | |
from random import randint | |
#start = Point(2, 1) #the sheet has 8 sets of characters in a 4x2 grid. | |
#startMons = Point(1, 1) | |
ssize = Size(96, 128) | |
speed = 0.15 | |
speedMonsters = .15 | |
boost = 3 | |
frames = [0, 1, 2, 1] #4 frames per walk cycle | |
dirs = [0, 3, 9, 6] #start frame for direction | |
moveamt = 32 | |
mov = [(0, -moveamt), (-moveamt, 0), (0, moveamt), (moveamt, 0)] | |
keycolor = (0, 255, 0, 255) | |
gravsense = 0.06 | |
north = 0 | |
south = 2 | |
east = 1 | |
west = 3 | |
hitRange=10 | |
class collision (object): | |
def __init__(self, location, size, type): | |
self.location = location | |
self.size = size | |
self.type=type | |
class monster (object): | |
def __init__(self, location, size, type): | |
self.location = location | |
self.size = size | |
self.type=type | |
self.dir=0 | |
self.start = 0 | |
self.delay = speedMonsters | |
self.movlen = 0 #how long until randomly changes dir | |
#format: xy locations, xy size, type | |
#types: 0=safe spawn site, 1=mons spawn site, 2=wall, 3=pushable | |
levels=[[collision(Point(200,500),Point(100,200),2), | |
collision(Point(200,600),Point(300,100),2), | |
collision(Point(400,300),Point(100,400),2), | |
collision(Point(50,300),Point(450,100),2), | |
collision(Point(50,300),Point(50,500),2), | |
collision(Point(50,750),Point(600,50),2), | |
collision(Point(600,0),Point(50,800),2), | |
collision(Point(650,700),Point(200,100),3), | |
collision(Point(0,300),Point(50,100),3)], | |
#this level is a stress test and too large | |
[collision(Point(0,0),Point(100,100),2), | |
collision(Point(0,200),Point(100,100),2), | |
collision(Point(0,400),Point(100,100),2), | |
collision(Point(0,600),Point(100,100),2), | |
collision(Point(0,800),Point(100,100),2), | |
collision(Point(100,100),Point(100,100),3), | |
collision(Point(100,300),Point(100,100),3), | |
collision(Point(100,500),Point(100,100),3), | |
collision(Point(100,700),Point(100,100),3), | |
collision(Point(100,900),Point(100,100),2), | |
collision(Point(200,0),Point(100,100),2), | |
collision(Point(200,200),Point(100,100),3), | |
collision(Point(200,400),Point(100,100),3), | |
collision(Point(200,600),Point(100,100),3), | |
collision(Point(200,800),Point(100,100),3), | |
collision(Point(300,100),Point(100,100),3), | |
collision(Point(300,300),Point(100,100),3), | |
collision(Point(300,500),Point(100,100),3), | |
collision(Point(300,700),Point(100,100),3), | |
collision(Point(300,900),Point(100,100),2), | |
collision(Point(400,0),Point(100,100),2), | |
collision(Point(400,200),Point(100,100),3), | |
collision(Point(400,400),Point(100,100),3), | |
collision(Point(400,600),Point(100,100),3), | |
collision(Point(400,800),Point(100,100),3), | |
collision(Point(500,100),Point(100,100),3), | |
collision(Point(500,300),Point(100,100),3), | |
collision(Point(500,500),Point(100,100),3), | |
collision(Point(500,700),Point(100,100),3), | |
collision(Point(500,900),Point(100,100),2), | |
collision(Point(600,0),Point(100,100),2), | |
collision(Point(600,200),Point(100,100),3), | |
collision(Point(600,400),Point(100,100),3), | |
collision(Point(600,600),Point(100,100),3), | |
collision(Point(600,800),Point(100,100),3), | |
collision(Point(700,100),Point(100,100),2), | |
collision(Point(700,300),Point(100,100),2), | |
collision(Point(700,500),Point(100,100),2), | |
collision(Point(700,700),Point(100,100),2), | |
collision(Point(700,900),Point(100,100),2)], | |
[collision(Point(10,20),Point(100,100),1), | |
collision(Point(100,400),Point(50,200),1), | |
collision(Point(330,300),Point(10,100),2)], | |
[collision(Point(100,200),Point(100,100),0), | |
collision(Point(100,400),Point(50,200),1), | |
collision(Point(330,300),Point(1000,100),0)]] | |
#spawns xy, sorted by level. Will use later to respawn units | |
mvm=moveamt/2 | |
monsSpawn=[Point(300,400),Point(50,550),Point(300,500),Point(100,100)] | |
selfSpawn=[Point(700,32),Point(650,150),Point(400,500),Point(400,100)] | |
for i in range(len(levels)): | |
selfSpawn[i].x-=mvm | |
selfSpawn[i].y-=mvm | |
monsSpawn[i].x-=mvm | |
monsSpawn[i].y-=mvm | |
levels[i].append(collision(selfSpawn[i],Point(32,32),0)) | |
levels[i].append(collision(monsSpawn[i],Point(32,32),1)) | |
#like before, it's xy loc, xy size, then type | |
#Need at least three of type 0 to complete lvl | |
levelsMonsters=[[monster(Point(300,100),Point(32,32),2), | |
monster(Point(300,100),Point(32,32),2), | |
monster(Point(300,100),Point(32,32),2), | |
monster(Point(300,100),Point(32,32),2), | |
monster(Point(500,500),Point(32,32),0), | |
monster(Point(532,500),Point(32,32),0), | |
monster(Point(564,500),Point(32,32),0)], | |
[monster(Point(250-mvm,550-mvm),Point(32,32),0), | |
monster(Point(50-mvm,750-mvm),Point(32,32),0), | |
monster(Point(50-mvm,350-mvm),Point(32,32),0), | |
monster(Point(50-mvm,550-mvm),Point(32,32),2)], | |
[monster(Point(300,100),Point(32,32),1), | |
monster(Point(300,100),Point(32,32),1)], | |
[monster(Point(300,100),Point(32,32),1), | |
monster(Point(300,100),Point(32,32),1)]] | |
def score(self): | |
tint(0,1,1,1) | |
s='Score: '+str(self.score)+' Lives: '+str(self.lives) | |
text(s, 'Futura', 40, *self.bounds.center().as_tuple()) | |
tint(1,1,1,1) | |
#Reacts to a hit and returns a modified loc1 and loc2 for | |
#the two objects being tested | |
def hitReact(loc1,loc2,type,hit,speed,mons=False): | |
#if type==0: | |
#loc1.y+=speed | |
#loc1.y-=speed | |
if type==0 and mons==True or type==1 and mons==False or type==2: | |
if hit==1: loc1.x-=speed#z.location.x+=10 | |
elif hit==2: loc1.x+=speed#z.location.x-=10 | |
elif hit==3: loc1.y-=speed#z.location.y+=10 | |
elif hit==4: loc1.y+=speed#z.location.y-=10 | |
elif type==3: | |
if hit==1: loc2.x+=10 | |
elif hit==2: loc2.x-=10 | |
elif hit==3: loc2.y+=10 | |
elif hit==4: loc2.y-=10 | |
return [loc1,loc2] | |
def hitCorner(loc1,loc2,size2): | |
if loc1.x>loc2.x and loc1.x<loc2.x+size2.x: | |
if loc1.y>loc2.y and loc1.y<loc2.y+size2.y: | |
return True | |
def hitTest2(loc1,size1,loc2,size2,output=0): | |
if loc1.x+size1.x>=loc2.x and loc1.x<=loc2.x+size2.x: | |
if loc1.y+size1.y>=loc2.y and loc1.y<=loc2.y+size2.y: | |
output=1 | |
if output: | |
#Rectangle alert | |
if size1.x!=size1.y or size2.x!=size2.y: | |
c1=hitCorner(loc1,loc2,size2) | |
c2=hitCorner(Point(loc1.x,loc1.y+size1.y),loc2,size2) | |
c3=hitCorner(Point(loc1.x+size1.x,loc1.y+size1.y),loc2,size2) | |
c4=hitCorner(Point(loc1.x+size1.x,loc1.y),loc2,size2) | |
if c1 and c2: return 2#l | |
elif c2 and c3: return 3#t | |
elif c3 and c4: return 1#r | |
elif c4 and c1: return 4#b | |
#Difference between origins to locate the direction | |
difx=(loc1.x+size1.x/2)-(loc2.x+size2.x/2) | |
dify=(loc1.y+size1.y/2)-(loc2.y+size2.y/2) | |
if difx<=0: output1=1#hit from r | |
else: output1=2#hit from l | |
if dify<=0: output2=1#hit from t | |
else: output2=2#hit from b | |
if dify<0:dify*=-1#check which is most important | |
if difx<0:difx*=-1 | |
if difx>dify: output=output1 | |
else: output=output2+2 | |
return output | |
def loadImage(folderPath,imgPath,urlPath): | |
if not os.path.exists(folderPath): os.mkdir(folderPath) | |
if not os.path.exists(folderPath+"/"+imgPath): | |
url = urllib.urlopen(urlPath) | |
with open(folderPath+"/"+imgPath, "wb") as output: | |
output.write(url.read()) | |
img = Image.open(folderPath+"/"+imgPath).convert('RGBA') | |
return img | |
def replaceImage(folderPath,imgPath,urlPath): | |
url = urllib.urlopen(urlPath) | |
with open(folderPath+"/"+imgPath, "wb") as output: | |
output.write(url.read()) | |
def cropImage(img,start): | |
strt = Point(start.x * ssize.w, start.y * ssize.h) | |
img = img.crop((strt.x,strt.y,strt.x+ssize.w-1,strt.y+ssize.h-1)) | |
d = img.load() | |
keycolor = d[0,0] #1st pixel is used as keycolor. | |
for x in range(img.size[0]): | |
for y in range(img.size[1]): | |
p = d[x, y] | |
if p == keycolor: #if keycolor set alpha to 0. | |
d[x, y] = (p[0], p[1], p[2], 0) | |
return img | |
def wrap(v, ext): | |
if v < 0: | |
return ext + v | |
elif v >= ext: | |
return v - ext | |
return v | |
def reverseDir(dir): | |
if dir==0: dir=2 | |
elif dir==1: dir=3 | |
elif dir==2: dir=0 | |
else: dir=1 | |
return dir | |
def touchdirections(dir,source): | |
dx=dir.x-source.x | |
dy=dir.y-source.y | |
if dx<0:dx*=-1 | |
if dy<0:dy*=-1 | |
if dx>dy: | |
if dir.x > source.x: output=3 | |
else: output=1 | |
else: | |
if dir.y>source.y: output=2 | |
else: output=0 | |
return output | |
class MyScene (Scene): | |
def setup(self): | |
# Load sprites | |
img=loadImage('Images','soldier2.png', | |
'http://i766.photobucket.com/albums/xx303/TurtleSoupguild/iPadGame_Sprites2-1.png') | |
bg=loadImage('Images','gameBG.png','http://i766.photobucket.com/albums/xx303/TurtleSoupguild/iPadGame_BG-1.png') | |
#0,0=kingdra 0,1=big 1,0=bug 1,1=zubat 2,0=ekans 2,1=espeon 3,0=char | |
img1=cropImage(img,Point(0, 1))#the sheet has 8 sets in a 4x2 grid. | |
img2=cropImage(img,Point(1, 0)) | |
img3=cropImage(img,Point(3, 1)) | |
img4=cropImage(img,Point(0, 0)) | |
img4.show() | |
#img3.show() | |
def getframe(x, y, image): | |
nim = image.crop((x * 32, y * 32, (x+1) * 32, (y+1) * 32)) | |
return load_pil_image(nim) | |
self.images=[getframe(x,y,img1) for y in xrange(4) for x in xrange(3)] | |
self.imagesMons=[getframe(x,y,img2) for y in xrange(4) for x in xrange(3)] | |
self.imagesTarget=[getframe(x,y,img3) for y in xrange(4) for x in xrange(3)] | |
self.imagesKingdra=[getframe(x,y,img4) for y in xrange(4) for x in xrange(3)] | |
self.bg=load_pil_image(bg) | |
#self.bg=[getframe(x,y,bg) for y in xrange(4) for x in xrange(3)] | |
self.start = 0 | |
self.base = 0 | |
self.dir = 0 | |
self.score=0 | |
self.lives=3 | |
self.level=0 | |
self.delay = speed | |
self.x = selfSpawn[self.level].x | |
self.y = selfSpawn[self.level].y | |
self.target=Point(self.x,self.y) | |
self.collisions=set() #set up collision objects like walls | |
for box in levels[self.level]: self.collisions.add(box) | |
self.monsters=set() #set up monsters | |
for mons in levelsMonsters[self.level]: self.monsters.add(mons) | |
#mons=monster(Point(300,400),Point(32,32),1) | |
def touch_moved(self, touch): | |
self.dir = touchdirections(touch.location,self) | |
#global speed | |
#speed = .25 | |
d = self.dir | |
def touch_ended(self, touch): | |
self.dir = touchdirections(touch.location,self) | |
global speed | |
speed = .25 | |
x=touch.location.x-mvm | |
y=touch.location.y-mvm | |
if x<=0:x=0 | |
if y<=0:y=0 | |
self.target.x=x | |
self.target.y=y | |
def draw(self): | |
# This will be called for every frame (typically 60 times per second). | |
image(self.bg, 0, 0, 768, 1064) | |
#global speed | |
#background(1, 1, 1) | |
score(self) | |
mv = mov[self.dir] | |
if self.target.x>self.x+hitRange or self.target.x<self.x-hitRange: | |
#speed=.2 | |
if self.target.x>self.x+hitRange:self.dir=3 | |
else:self.dir=1 | |
self.x += mv[0] *boost* self.dt | |
self.x = wrap(self.x, self.size.w) | |
elif self.target.y>self.y+hitRange or self.target.y<self.y-hitRange: | |
#speed=.2 | |
self.dir=touchdirections(self.target,self) | |
self.y += mv[1] *boost* self.dt | |
self.y = wrap(self.y, self.size.h) | |
else: pass#speed=.4 | |
self.delay -= self.dt | |
if self.delay <= 0: | |
self.delay += speed | |
self.start += 1 | |
if self.start >= len(frames): self.start = 0 | |
dead=set() | |
#blend_mode(BLEND_MULTIPLY) | |
blend_mode(BLEND_ADD) | |
for z in self.collisions: | |
if z.type==0: fill(0,0,1) | |
elif z.type==1: fill(1,0,0) | |
elif z.type==2: fill(1,1,0) | |
else: fill(0,1,0) | |
rect(z.location.x,z.location.y,z.size.x,z.size.y) | |
hitz=hitTest2(Point((self.x+moveamt/3), | |
(self.y+moveamt/3)), | |
Point(hitRange,hitRange),z.location,z.size) | |
if hitz!=0: | |
r=hitReact(Point(self.x,self.y),z.location,z.type,hitz,boost) | |
z.location=r[1] | |
r=r[0] | |
self.x=r.x | |
self.y=r.y | |
if z.type==2 or z.type==3: | |
self.target.x=self.x | |
self.target.y=self.y | |
for m in self.monsters: | |
hitz=hitTest2(m.location,m.size,z.location,z.size) | |
if hitz!=0: | |
r=hitReact(m.location,z.location,z.type,hitz,1,True) | |
m.location=r[0] | |
z.location=r[1] | |
if z.type!=1: | |
r=randint(0,3) | |
while r==m.dir:r=randint(0,3) | |
m.dir=r#reverseDir(m.dir) | |
blend_mode(BLEND_NORMAL) | |
for m in self.monsters: | |
if m.type==1 or m.type==2:#Only moving monsters | |
m.movlen+=1 | |
if m.movlen>100: | |
m.movlen=0 | |
m.dir=randint(0,3) | |
mvm=mov[m.dir] | |
m.location.x += mvm[0] *(1-speedMonsters)* self.dt | |
m.location.x = wrap(m.location.x, self.size.w) | |
m.location.y += mvm[1] *(1-speedMonsters)* self.dt | |
m.location.y = wrap(m.location.y, self.size.h) | |
m.delay -= self.dt | |
if m.delay <= 0: | |
m.delay += speedMonsters | |
m.start += 1 | |
if m.start >= len(frames): m.start = 0 | |
if m.type!=2: img=self.imagesMons[dirs[m.dir]+frames[m.start]] | |
else: | |
#m.dir=randint(0,3) | |
m.location.x += mvm[0] *(1-speedMonsters)*boost* self.dt | |
m.location.x = wrap(m.location.x, self.size.w) | |
m.location.y += mvm[1] *(1-speedMonsters)*boost* self.dt | |
m.location.y = wrap(m.location.y, self.size.h) | |
img=self.imagesKingdra[dirs[m.dir]+frames[m.start]] | |
else: | |
m.dir=0 | |
img=self.imagesTarget[dirs[m.dir]+frames[m.start]] | |
image(img, m.location.x, m.location.y, 32, 32) | |
hit=hitTest2(Point(self.x+moveamt/3,self.y+moveamt/3),Point(hitRange,hitRange),m.location,m.size) | |
hitSet=set() | |
if hit!=0: | |
if m.type==1 or m.type==2: | |
hitSet.add(m) | |
#self.lives-=1 | |
#self.score+=1 | |
self.x=selfSpawn[self.level].x | |
self.target.x=self.x | |
self.y=selfSpawn[self.level].y | |
self.target.y=self.y | |
else: | |
self.score+=1 | |
dead.add(m) | |
#if hitSet: self.score+=1#self.score+=len(hitSet) | |
self.lives-=len(hitSet) | |
self.monsters-=dead | |
#if self.score!=0:print self.score | |
if self.score>=3: # new level | |
self.score=0 | |
if self.level<len(levels)-1: self.level+=1 | |
else: self.level=0 | |
self.monsters=set() | |
self.collisions=set() | |
self.collisions=levels[self.level] | |
for i in levelsMonsters[self.level]: self.monsters.add(i) | |
if len(self.monsters)<10: | |
l=monsSpawn[self.level] | |
l=Point(l.x,l.y) | |
self.monsters.add(monster(l,Point(32,32),1)) | |
image(self.images[dirs[self.dir] + frames[self.start]], self.x, self.y, 32, 32) | |
run(MyScene(), PORTRAIT) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment