Browse Source

collision detection!

raylu 12 years ago
parent
commit
fe8e0249c1
3 changed files with 44 additions and 20 deletions
  1. 31 15
      character.py
  2. 11 3
      tileset.py
  3. 2 2
      troll

+ 31 - 15
character.py

@@ -3,12 +3,14 @@ import pygame
 from tileset import Tileset
 
 class Character(object):
+	SPEED = 2
 	movement = [0, 0]
 
-	def __init__(self, start_pos):
-		self.render_x, self.render_y = start_pos
-		self.render_x *= Tileset.TILESIZE
-		self.render_y *= Tileset.TILESIZE
+	def __init__(self, start_pos, collisions):
+		self.pos = list(start_pos)
+		self.render_x = self.pos[0] * Tileset.TILESIZE
+		self.render_y = self.pos[1] * Tileset.TILESIZE
+		self.collisions = collisions
 
 	def frame(self, keys):
 		# are we done moving?
@@ -17,27 +19,41 @@ class Character(object):
 		if self.render_y % Tileset.TILESIZE == 0:
 			self.movement[1] = 0
 
-		SPEED = 2
-		direction = None
 		# can we start moving?
+		direction = None
+		movement_x = movement_y = None
 		if self.movement[1] == 0:
-			if keys[pygame.K_DOWN] or keys[pygame.K_j]:
-				self.movement[1] = SPEED
+			if (keys[pygame.K_DOWN] or keys[pygame.K_j]):
+				movement_y = 1
 				direction = Tileset.DOWN
 			elif keys[pygame.K_UP] or keys[pygame.K_k]:
-				self.movement[1] = -SPEED
+				movement_y = -1
 				direction = Tileset.UP
+			# vertical collision detection
+			# each direction is checked separately because holding
+			# down+right on a right wall should still move you down
+			if movement_y and (self.pos[0], self.pos[1] + movement_y) in self.collisions:
+				movement_y = 0
 		if self.movement[0] == 0:
 			if keys[pygame.K_RIGHT] or keys[pygame.K_l]:
-				self.movement[0] = SPEED
-				if not self.movement[1]: # prefer up/down when moving diagonally
+				movement_x = 1
+				if self.movement[1] == 0 and movement_y is None: # prefer up/down when moving diagonally
 					direction = Tileset.RIGHT
 			elif keys[pygame.K_LEFT] or keys[pygame.K_h]:
-				self.movement[0] = -SPEED
-				if not self.movement[1]:
+				movement_x = -1
+				if self.movement[1] == 0 and movement_y is None:
 					direction = Tileset.LEFT
+			# horizontal collision detection
+			if movement_x and (self.pos[0] + movement_x, self.pos[1]) in self.collisions:
+				movement_x = 0
+		if movement_x:
+			self.movement[0] = movement_x
+			self.pos[0] += movement_x
+		if movement_y:
+			self.movement[1] = movement_y
+			self.pos[1] += movement_y
 
 		# move!
-		self.render_x += self.movement[0]
-		self.render_y += self.movement[1]
+		self.render_x += self.movement[0] * self.SPEED
+		self.render_y += self.movement[1] * self.SPEED
 		return direction

+ 11 - 3
tileset.py

@@ -5,6 +5,7 @@ import pygame
 
 class Tileset(object):
 	TILESIZE = 16
+	MAPSIZE = 50
 	RIGHT = 0
 	DOWN = 1
 	LEFT = 2
@@ -56,7 +57,14 @@ class Tileset(object):
 			# read as array of 4-byte ints
 			array = list(struct.unpack('<{}i'.format(len(data)/4), data))
 			loaded[name] = array
+
 		self.level_array = loaded['level']
+		collidables = frozenset([6, 7, 8, 22, 24, 38, 39, 40])
+		collisions = set()
+		for i, tile in enumerate(loaded['level']):
+			if tile in collidables:
+				y, x = divmod(i, self.MAPSIZE)
+				collisions.add((x, y))
 
 		units = {
 			self.ENEMY1: [],
@@ -64,15 +72,15 @@ class Tileset(object):
 		}
 		for i, tile in enumerate(loaded['units']):
 			if tile in units.iterkeys():
-				y, x = divmod(i, 50)
+				y, x = divmod(i, self.MAPSIZE)
 				units[tile].append((x, y))
 		if len(units[self.PLAYER]) != 1:
 			raise Exception('expected exactly 1 player tile in units layer, found ' + str(len(units[self.PLAYER])))
-		return units
+		return collisions, units
 
 	def render_level(self):
 		for i, tile in enumerate(self.level_array):
-			y, x = divmod(i, 50)
+			y, x = divmod(i, self.MAPSIZE)
 			x *= self.TILESIZE
 			y *= self.TILESIZE
 			tile_y, tile_x = divmod(tile - 1, self.TILESIZE) # those 1-indexing fuckers

+ 2 - 2
troll

@@ -8,8 +8,8 @@ from character import Character
 pygame.init()
 screen = pygame.display.set_mode((800, 800))
 tileset = Tileset(screen)
-units = tileset.load_level()
-character = Character(units[Tileset.PLAYER][0])
+collisions, units = tileset.load_level()
+character = Character(units[Tileset.PLAYER][0], collisions)
 clock = pygame.time.Clock()
 
 black = (0, 0, 0)