commit:ffafe84871d82a090dd9867299891c311102514b
author:chip
committer:chip
date:Wed Nov 21 07:55:39 2007 +0000
parents:6d1cd20b7a27a5b99b7617445a6bf49b5bb93d98
Added surfaces and rudimentary platforming engine
diff --git a/Sprite.py b/Sprite.py
line changes: +49/-15
index d02a99e..31c2ef9
--- a/Sprite.py
+++ b/Sprite.py
@@ -15,20 +15,26 @@ TOP = 1
 
 class Sprite:
 	frames = None
-	framerate = 0.0
 	frameno = 0
 	animating = False
 	anim_t = 0
-	color = (1.0,1.0,1.0,1.0)
-	position = (0,0)
 	size = (0,0)
-	scale = 1.0
-	rotation = 0
-	gravity = (LEFT, BOTTOM)
 	uparrow = False
 	displaylists = None
 
-	def __init__(self, file, genlist=True):
+	def __init__(self, file, position=(0,0), scale=1.0, rotation=0,
+		     mirror=False, flip=False, color=(1.0,1.0,1.0,1.0),
+		     framerate=0.0, gravity=(LEFT,BOTTOM)):
+
+		self.position = position
+		self.scale = scale
+		self.rotation = rotation
+		self.mirror = mirror
+		self.flip = flip
+		self.color= color
+		self.setFramerate(framerate)
+		self.gravity = gravity
+
 		self.frames = []
 		d = None
 		if type(file) == type([]):
@@ -40,11 +46,10 @@ class Sprite:
 			d = TexMan.load(file)
 			self.frames.append(d['texture'])
 		self.size = d['size']
+		self.rect = pygame.Rect(self.position, self.size)
 		self.tsize = d['tsize']
-		print "size:",self.size
-		print "tsize:",self.tsize
-		if genlist:
-			self.gen_displaylist()
+
+		self.gen_displaylist()
 
 
 	def gen_displaylist(self):
@@ -62,14 +67,31 @@ class Sprite:
 			else:
 				print "Invalid gravity:",x
 				c[i] = 0
+		if self.mirror:
+			c[0] -= self.tsize[0] - self.size[0]
+		if self.flip:
+			c[1] -= self.tsize[1] - self.size[1]
 		vertexarray = array(
 			((c[0],c[1],0),(c[0]+self.tsize[0],c[1],0),
 			 (c[0]+self.tsize[0],c[1]+self.tsize[1],0),
 			 (c[0],c[1]+self.tsize[1],0))
 		,'f')
-		texcoordarray = array(
-			((1.0,0.0),(1.0,1.0),(0.0,1.0),(0.0,0.0))
-		,'f')
+		if self.flip and self.mirror:
+			texcoordarray = array(
+				((0.0,0.0),(0.0,1.0),(1.0,1.0),(1.0,0.0))
+			,'f')
+		elif self.flip:
+			texcoordarray = array(
+				((0.0,1.0),(0.0,0.0),(1.0,0.0),(1.0,1.0))
+			,'f')
+		elif self.mirror:
+			texcoordarray = array(
+				((1.0,1.0),(1.0,0.0),(0.0,0.0),(0.0,1.0))
+			,'f')
+		else:
+			texcoordarray = array(
+				((1.0,0.0),(1.0,1.0),(0.0,1.0),(0.0,0.0))
+			,'f')
 		index = array((0,1,2,3),'i')
 		for i in range(0,len(self.frames)):
 			glNewList(self.displaylists[i], GL_COMPILE)
@@ -81,10 +103,17 @@ class Sprite:
 			glDrawArrays(GL_QUADS, 0, 4)
 			glEndList()
 
+
+	def setPosition(self, x, y):
+		self.position = (x,y)
+		self.rect.move_ip(x,y)
+
+
 	def setColor(self, r, g, b, a = 1.0):
 		self.color = (r,g,b,a)
 		self.gen_displaylist()
 
+
 	def setScale(self, scale):
 		self.scale = scale
 	
@@ -107,6 +136,7 @@ class Sprite:
 
 	def reset(self):
 		self.anim_t = pygame.time.get_ticks()
+		self.frameno = 0
 
 
 	def play(self):
@@ -118,6 +148,10 @@ class Sprite:
 
 
 	def draw(self):
+		self.drawAt(self.position)
+
+
+	def drawAt(self,pos):
 		if self.animating:
 			now = pygame.time.get_ticks()
 			dt = now - self.anim_t
@@ -125,7 +159,7 @@ class Sprite:
 				self.frameno = (self.frameno + int(dt / self.anim_period)) % len(self.frames)
 				self.anim_t = now
 		glPushMatrix()
-		glTranslatef(self.position[0], self.position[1], 0)
+		glTranslatef(pos[0], pos[1], 0)
 		if self.rotation != 0:
 			glRotatef(self.rotation, 0, 0, -1)
 		if self.scale != 1.0:

diff --git a/Surface.py b/Surface.py
line changes: +139/-0
index 0000000..c85402e
--- /dev/null
+++ b/Surface.py
@@ -0,0 +1,139 @@
+import pygame
+from OpenGL.GL import *
+import math
+
+class Surface:
+	fuzz = 20
+	def __init__(self, p1, p2):
+		self.p1 = p1
+		self.p2 = p2
+		self.dx = p2[0] - p1[0]
+		self.dy = p2[1] - p1[1]
+		try:
+			self.m_x = float(self.dy) / float(self.dx)
+		except ZeroDivisionError:
+			self.m_x = 1e999
+		self.b_x = p1[1] - self.m_x * p1[0]
+		try:
+			self.m_y = float(self.dx) / float(self.dy)
+		except ZeroDivisionError:
+			self.m_y = 1e999
+		self.b_y = p1[0] - self.m_y * p1[1]
+
+		# A collision rect for fast collision culling. Only surfaces
+		# whose initial rect collision check passes will run the
+		# detailed check
+		self.rect = pygame.Rect(p1,(self.dx,self.dy))
+		self.rect.normalize()
+		self.rect.width += 1
+		self.rect.height += 1
+		# Expand the collision rect for nearly horizontal or vertical
+		# surfaces
+		if abs(self.m_x) < 0.2:		# 5:1 ratio or more
+			self.rect.height += 2*self.fuzz
+			self.rect.top -= self.fuzz
+		elif abs(self.m_y) < 0.2:	# 1:5 ratio or less
+			self.rect.width += 2*self.fuzz
+			self.rect.left -= self.fuzz
+
+
+	def collide(self, point):
+		if self.rect.collidepoint(point[0],point[1]):
+			if self.m_x > -1.0 and self.m_x < 1.0:
+				if self.dx > 0:
+					if point[1] < self.m_x * point[0] + self.b_x:
+						return True
+				else:
+					if point[1] > self.m_x * point[0] + self.b_x:
+						return True
+			else:
+				if self.dy > 0:
+					if point[0] > self.m_y * point[1] + self.b_y:
+						return True
+				else:
+					if point[0] < self.m_y * point[1] + self.b_y:
+						return True
+		return False
+
+
+	def draw(self):
+		angle = math.atan(self.m_x)
+		if self.dx < 0 or self.dy < 0:
+			arrow = (angle+3*math.pi/2) % (2*math.pi)
+		else:
+			arrow = (angle+math.pi/2) % (2*math.pi)
+		anglepoint = (math.cos(arrow) * 10, math.sin(arrow) * 10)
+		glPushMatrix()
+		glDisable(GL_TEXTURE_2D)
+		glColor3f(1.0,1.0,1.0)
+		glBegin(GL_LINES)
+		glVertex3f(self.p1[0],self.p1[1],0)
+		glVertex3f(self.p2[0],self.p2[1],0)
+		glVertex3f(self.rect.centerx, self.rect.centery, 0)
+		glVertex3f(self.rect.centerx + anglepoint[0], self.rect.centery + anglepoint[1], 0)
+		glEnd()
+		glPopMatrix()
+
+
+class Solid:
+	def __init__(self, p1, p2):
+		self.rect = pygame.Rect(p1,(p2[0]-p1[0],p2[1]-p1[1]))
+	
+
+	def collide(self, point):
+		return self.rect.collidepoint(point[0],point[1])
+
+
+class SurfaceSet:
+	surfaces = None
+
+	def __init__(self, file = None):
+		self.surfaces = []
+		if file is not None:
+			self.parse(file)
+	
+
+	def parse(self, file):
+		self.surfaces = []
+
+		mf = (1,1)
+		f = open(file,'r')
+		for line in f:
+			args = line.split()
+			if not args:
+				continue
+			cmd = args[0]
+			args = args[1:]
+			if cmd == 'tilesize':
+				mf = (int(args[0]),int(args[1]))
+			elif cmd == 'surface':
+				p1 = (int(args[0])*mf[0],int(args[1])*mf[1])
+				p2 = (int(args[2])*mf[0],int(args[3])*mf[1])
+				self.surfaces.append(Surface(p1,p2))
+			elif cmd == 'solid':
+				p1 = (int(args[0])*mf[0],int(args[1])*mf[1])
+				p2 = (int(args[2])*mf[0],int(args[3])*mf[1])
+				self.surfaces.append(Solid(p1,p2))
+		f.close()
+	
+
+	def collide(self,point):
+		colliders = filter(lambda x: x.rect.collidepoint(point), self.surfaces)
+		if not colliders:
+			return False
+		if filter(lambda x: not x, [c.collide(point) for c in colliders]):
+			return False
+		return True
+
+
+	def draw(self):
+		for s in self.surfaces:
+			s.draw()
+	
+
+	def append(self, s):
+		return self.surfaces.append(s)
+
+
+	def remove(self, s):
+		return self.surfaces.remove(s)

diff --git a/data/example1 b/data/example1
line changes: +14/-0
index 5a5e4c6..6e5646e
--- a/data/example1
+++ b/data/example1
@@ -11,6 +11,7 @@ tile 7 0
 tile 8 0
 tile 9 0
 
+tile 3 1
 tile 4 1
 tile 4 2
 tile 4 3
@@ -19,6 +20,19 @@ tile 4 4
 tile 6 1
 tile 6 2
 
+solid 0 2 1 3
+surface 0 1 2 1
+surface 2 1 4 2
+solid   2 0 4 1
+surface 4 2 4 5
+surface 4 5 5 5
+surface 5 5 5 1
+surface 5 1 6 1
+surface 6 1 6 3
+surface 6 3 7 3
+surface 7 3 7 1
+surface 7 1 10 1
+
 tilesize 1 1
 texture img/ByteIco.png
 tile 263 263

diff --git a/platformtest.py b/platformtest.py
line changes: +123/-0
index 0000000..dfc9669
--- /dev/null
+++ b/platformtest.py
@@ -0,0 +1,123 @@
+#!/usr/bin/env python
+
+import pygame
+from Sprite import *
+from Collage import *
+from Surface import *
+import Engine
+
+#resolution = (1280,1024)
+resolution = (640,480)
+#resolution = (320,240)
+
+Engine.init(resolution)
+
+pygame.display.set_caption("platformtest")
+
+ground = Collage('data/example1')
+ground.position = [0,0]
+surfaces = SurfaceSet('data/example1')
+stars = Collage('data/stars')
+stars.position = [0,0]
+candelabra = Sprite(['Sprites/candelabra_short/cand_s_1.png','Sprites/candelabra_short/cand_s_2.png','Sprites/candelabra_short/cand_s_3.png','Sprites/candelabra_short/cand_s_4.png'])
+candelabra.position = [64, 64]
+candelabra.setScale(2.0)
+candelabra.setGravity(CENTER, BOTTOM)
+candelabra.setFramerate(10.0)
+candelabra.play()
+
+player_l = Sprite(['img/richter%d.png' % n for n in range(0,8)],
+		framerate=10.0, scale=2.0, gravity=(CENTER,BOTTOM))
+player_r = Sprite(['img/richter%d.png' % n for n in range(0,8)], mirror=True,
+		framerate=10.0, scale=2.0, gravity=(CENTER,BOTTOM))
+
+
+def moveObject(pos, delta):
+	npos = list(pos)
+	npos[0] += delta[0]
+	npos[1] += delta[1]
+	if surfaces.collide(npos):
+		npos[1] += 1
+		if surfaces.collide(npos):
+			return pos
+		else:
+			return npos
+	else:   
+		return npos
+
+
+class gamestate:
+	face = 1
+	direction = [0,0]
+	vgravity = 0
+	position = [32,64]
+
+
+def input(e):
+	if e.type == pygame.KEYDOWN:
+		if e.key == pygame.K_LEFT:
+			gamestate.direction[0] = -1
+			gamestate.face = 0
+			player_l.play()
+		elif e.key == pygame.K_RIGHT:
+			gamestate.direction[0] = 1
+			gamestate.face = 1
+			player_r.play()
+		elif e.key == pygame.K_DOWN:
+			gamestate.direction[1] = -1
+		elif e.key == pygame.K_UP:
+			gamestate.direction[1] = 1
+	elif e.type == pygame.KEYUP:
+		if e.key == pygame.K_LEFT or e.key == pygame.K_RIGHT:
+			gamestate.direction[0] = 0
+			player_l.stop()
+			player_l.reset()
+			player_r.stop()
+			player_r.reset()
+		elif e.key == pygame.K_UP:
+			gamestate.direction[1] = 0
+			if gamestate.vgravity != 0.0:
+				gamestate.vgravity = 0.0
+		elif e.key == pygame.K_DOWN:
+			gamestate.direction[1] = 0
+
+
+def update():
+	if gamestate.direction[1] == 1 and gamestate.vgravity == 0:
+		gamestate.vgravity = 20.0
+	gamestate.vgravity -= 0.5
+	npos = [gamestate.position[0], gamestate.position[1] + gamestate.vgravity]
+	if surfaces.collide(npos):
+		npos[1] -= 1
+		if surfaces.collide(npos):
+			gamestate.vgravity = 0
+	else:
+		gamestate.position = npos
+	# Move two pixels in whatever direction we're going, only horizontal
+	gamestate.position = moveObject(gamestate.position,(gamestate.direction[0]*2,0))
+	#ground.position[0] = gamestate.position[0] - resolution[0]/2
+	#stars.position[0] = int(ground.position[0] / 5.0)
+	#candelabra.position[0] -= ground.position[0] + 64
+	if gamestate.position[1] < 0:
+		gamestate.position = [gamestate.position[0],480]
+
+def draw():
+	stars.draw()
+	ground.draw()
+	candelabra.draw()
+	if gamestate.face == 1:
+		player_r.drawAt(gamestate.position)
+	else:
+		player_l.drawAt(gamestate.position)
+
+n = 0
+def fpsthing():
+	global n
+	n += 1
+	if n == 100:
+		fps = "%0.1f FPS" % Engine.fpsman.get_fps()
+		pygame.display.set_caption("bouncetest [%s]" % fps)
+		print fps
+		n = 0
+
+Engine.engine([input],[update,fpsthing],[draw])

diff --git a/scrolltest.py b/scrolltest.py
line changes: +3/-0
index 595a48f..d67591e
--- a/scrolltest.py
+++ b/scrolltest.py
@@ -24,6 +24,9 @@ candelabra.setGravity(CENTER, BOTTOM)
 candelabra.setFramerate(10.0)
 candelabra.play()
 
+#pygame.mixer.music.load('horizon.ogg')
+#pygame.mixer.music.play()
+
 def update():
 	ground.position[0] -= 5
 	if ground.position[0] < 0:

diff --git a/surfacetest.py b/surfacetest.py
line changes: +79/-0
index 0000000..6cc64f3
--- /dev/null
+++ b/surfacetest.py
@@ -0,0 +1,79 @@
+#!/usr/bin/env python
+
+import pygame
+from Sprite import *
+from Surface import *
+import Engine
+
+#resolution = (1280,1024)
+resolution = (640,480)
+#resolution = (320,240)
+
+Engine.init(resolution)
+
+pygame.display.set_caption("surfacetest")
+
+surfaces = SurfaceSet('data/example1')
+# Octagon
+#surfaces.append(Surface( (520,240),(461,98) ))
+#surfaces.append(Surface( (461,98),(319,40) ))
+#surfaces.append(Surface( (319,40),(178,98) ))
+#surfaces.append(Surface( (178,98),(120,240) ))
+#surfaces.append(Surface( (120,240),(178,381) ))
+#surfaces.append(Surface( (178,381),(320,440) ))
+#surfaces.append(Surface( (320,440),(461,381) ))
+#surfaces.append(Surface( (461,381),(520,240) ))
+
+# Concave
+#surfaces.append(Surface( (200,200), (200,400) ))
+#surfaces.append(Surface( (200,400), (300,300) ))
+#surfaces.append(Surface( (300,300), (400,300) ))
+#surfaces.append(Surface( (400,300), (500,400) ))
+#surfaces.append(Surface( (500,400), (500,200) ))
+#surfaces.append(Surface( (500,200), (200,200) ))
+
+player = Sprite('img/star.png')
+player.setGravity(CENTER, CENTER)
+player.position = [resolution[0]/2,resolution[1]/2]
+
+class gamestate:
+	direction = [0,0]
+	colliding = False
+
+def input(e):
+	if e.type == pygame.KEYDOWN:
+		if e.key == pygame.K_LEFT:
+			gamestate.direction[0] = -1
+		elif e.key == pygame.K_RIGHT:
+			gamestate.direction[0] = 1
+		elif e.key == pygame.K_DOWN:
+			gamestate.direction[1] = -1
+		elif e.key == pygame.K_UP:
+			gamestate.direction[1] = 1
+	elif e.type == pygame.KEYUP:
+		if e.key == pygame.K_LEFT or e.key == pygame.K_RIGHT:
+			gamestate.direction[0] = 0
+		elif e.key == pygame.K_UP or e.key == pygame.K_DOWN:
+			gamestate.direction[1] = 0
+
+
+def update():
+	player.position[0] += gamestate.direction[0]
+	player.position[1] += gamestate.direction[1]
+	if surfaces.collide(player.position):
+		if not gamestate.colliding:
+			player.setColor(1.0,0.2,0.2)
+			gamestate.colliding = True
+	else:
+		if gamestate.colliding:
+			player.setColor(1.0,1.0,1.0)
+			gamestate.colliding = False
+		
+
+
+def draw():
+	surfaces.draw()
+	player.draw()
+
+
+Engine.engine([input],[update],[draw])