Skip to content

Instantly share code, notes, and snippets.

/a_walk.py Secret

Created January 17, 2013 12:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save anonymous/b2739c37b139f9b057b7 to your computer and use it in GitHub Desktop.
Save anonymous/b2739c37b139f9b057b7 to your computer and use it in GitHub Desktop.
a_walk
#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