Commits

Don Spaulding committed 13a84ff

Start of day 3.

Comments (0)

Files changed (11)

data/floor.png

Added
New image
+
+
+
+
 from math import sqrt
 import math
 import pyglet
 MAX_SPRINT_FACTOR = 1.5
 ROTATION_SPEED = 2
 
-class GameObject(object):
-	def __init__(self, x, y, image_file, health=100, size=20, tag=None):
-		self.image = pyglet.image.load(image_file)
-		self.remove = False
-		self.speed = self.right_rotation_speed = self.left_rotation_speed = 0
-		self.speed_vector = v(self.speed, self.speed)
-		self.direction = 90
-		self.pos = v(x,y)
-		self.sprint_factor = 1.0
-		self.health = health
-		self.size = size
-		self.tag = tag or ""
 
 
-		self.dir = v(0,0)
 
-	def draw(self):
-		self.image.blit(self.x, self.y)
 
-	def set_speed(self, speed):
-		self.speed = speed
-		self.speed_vector = v(speed, speed)
 
-	def set_rotation_speed(self, left=None, right=None):
-		if right is not None:
-			self.right_rotation_speed = right
-		if left is not None:
-			self.left_rotation_speed = left
+# class GrinchOld(GameObject):
+# 	def register_input_handlers(self, window):
+# 		from pyglet.window import key
+# 		window.register_input(key.COMMA, on_press=lambda: self.set_speed(BASE_SPEED), on_release=lambda:self.set_speed(0))
+# 		window.register_input(key.O, on_press=lambda: self.set_speed(-BASE_SPEED), on_release=lambda:self.set_speed(0))
+# 		window.register_input(key.RIGHT, on_press=lambda: self.set_rotation_speed(right=ROTATION_SPEED), on_release=lambda: self.set_rotation_speed(right=0))
+# 		window.register_input(key.LEFT, on_press=lambda: self.set_rotation_speed(left=-ROTATION_SPEED), on_release=lambda: self.set_rotation_speed(left=0))
+# 		# window.register_input(key.D, on_press=lambda: self.set_speed(x=BASE_SPEED), on_release=lambda:self.set_speed(x=0))
+# 		# window.register_input(key.LEFT, on_press=lambda: self.set_speed(x=-BASE_SPEED), on_release=lambda:self.set_speed(x=0))
+# 		window.register_input(key.LSHIFT, on_press=lambda: self.set_speed(sprint_factor=MAX_SPRINT_FACTOR), on_release=lambda:self.set_speed(sprint_factor=1.0))		
 
-	#dt = time inbetween each frame, others=all the other actors, level = level object, to interact with collision
-	def update(self, dt, others, level):
-		speed = self.speed * self.sprint_factor * dt
-		self.pos = self.pos + self.speed_vector.rotated(self.direction)
-		self.direction += self.right_rotation_speed + self.left_rotation_speed
+	# def update_position(self, dt):
+	# 	distance = self.speed * self.sprint_factor * dt
+	# 	self.direction += self.right_rotation_speed + self.left_rotation_speed
+	# 	self.pos = self.pos + v(distance, 0).rotated(self.direction)
 
-		# if level.check_collision((self.x,self.y,20,20)):
-		# 	self.x -= self.speed_x * self.sprint_factor * dt
-		# 	self.y -= self.speed_y * self.sprint_factor * dt
 
-		for other in others:
-			if hasattr(other, 'y') and other is not self:
-				if self.get_distance(other.x, other.y) < (self.size+other.size)/2:
-					self.on_collision(other)
+# 	def on_damage(self, other, damage):
+# 		self.health -= damage
 
-		if self.health < 0:
-			self.on_die()
-
-		#if this game object needs to be deleted
-		return self.remove
-
-	def get_distance(self, x, y):
-		return sqrt((self.x - x) ** 2 + (self.y - y) ** 2)
-
-	def register_input_handlers(self, window):
-		pass
-
-	def on_damage(self, other, damage):
-		pass
-
-	def on_collision(self, other):
-		pass
-
-	def on_damage(self, other, damage):
-		pass
-
-	# override this for each type of actor
-	def on_die(self):
-		pass
-
-	@property
-	def x(self):
-		return self.pos.x
-
-	@property
-	def y(self):
-		return self.pos.y
-
-class Human(GameObject):
-	def __init__(self, x,y, image_file, tag=""):
-		super(Human,self).__init__(x,y,image_file, tag="player")
-		self.aimer_image = pyglet.image.load("data/aimer.png")
-		self.mx = 0
-		self.my = 0
-		self.aimer_angle = 0
-		self.aimer_sprite = pyglet.sprite.Sprite(self.aimer_image, self.mx,self.my)
-	def register_input_handlers(self, window):
-		from pyglet.window import key
-		window.register_input(key.UP, on_press=lambda: self.ModDir(0,1), on_release=lambda:self.ModDir(0,-1))
-		window.register_input(key.DOWN, on_press=lambda: self.ModDir(0,-1), on_release=lambda:self.ModDir(0,1))
-		window.register_input(key.RIGHT, on_press=lambda: self.ModDir(1,0), on_release=lambda:self.ModDir(-1,0))
-		window.register_input(key.LEFT, on_press=lambda: self.ModDir(-1,0), on_release=lambda:self.ModDir(1,0))
-		# window.register_input(key.D, on_press=lambda: self.set_speed(x=BASE_SPEED), on_release=lambda:self.set_speed(x=0))
-		# window.register_input(key.LEFT, on_press=lambda: self.set_speed(x=-BASE_SPEED), on_release=lambda:self.set_speed(x=0))
-		window.register_input(key.LSHIFT, on_press=lambda: self.SetSprint(MAX_SPRINT_FACTOR), on_release=lambda:self.SetSprint(1.0))
-
-	def set_mouse_coords(self,x,y):
-		self.mx = x
-		self.my = y
-		self.aimer_angle = (self.pos-v(self.mx,self.my)).angle
-		self.aimer_sprite.rotation = -self.aimer_angle - 90
-		self.aimer_sprite.position = (self.mx-10,self.my-10)
-
-	def ModDir(self, x,y):
-		self.dir += v(x,y)
-
-	def SetSprint(self, factor):
-		self.sprint_factor = factor
-
-	def update(self, dt, others, level):
-		self.pos += self.dir.safe_normalised() * BASE_SPEED * dt * self.sprint_factor
-
-	def init(self):
-		pass
-
-	def on_damage(self, other, damage):
-		self.health -= damage
-
-	def on_die(self):
-		self.remove = True
-
-	def draw(self):
-		self.image.blit(self.x, self.y)
-		self.aimer_sprite.draw()
-
-
-class Zombie(GameObject):
-	def update(self, dt, others, level):
-		super(Zombie,self).update(dt,others,level)
-		for i in others:
-			if i.tag == "player":
-				if math.pow((self.x-i.x), 2) + math.pow((self.y-i.y), 2) < math.pow(100,2):
-					#insert vector code here
-					pass
-	def on_collision(self, other):
-		if isinstance(other, Human):
-			other.on_damage(self, 25)
-
-
-
-class HumanOld(GameObject):
-	def register_input_handlers(self, window):
-		from pyglet.window import key
-		window.register_input(key.W, on_press=lambda: self.set_speed(BASE_SPEED), on_release=lambda:self.set_speed(0))
-		window.register_input(key.S, on_press=lambda: self.set_speed(-BASE_SPEED), on_release=lambda:self.set_speed(0))
-		window.register_input(key.RIGHT, on_press=lambda: self.set_rotation_speed(right=ROTATION_SPEED), on_release=lambda: self.set_rotation_speed(right=0))
-		window.register_input(key.LEFT, on_press=lambda: self.set_rotation_speed(left=-ROTATION_SPEED), on_release=lambda: self.set_rotation_speed(left=0))
-		# window.register_input(key.D, on_press=lambda: self.set_speed(x=BASE_SPEED), on_release=lambda:self.set_speed(x=0))
-		# window.register_input(key.LEFT, on_press=lambda: self.set_speed(x=-BASE_SPEED), on_release=lambda:self.set_speed(x=0))
-		window.register_input(key.LSHIFT, on_press=lambda: self.set_speed(sprint_factor=MAX_SPRINT_FACTOR), on_release=lambda:self.set_speed(sprint_factor=1.0))		
-
-	def init(self):
-		pass
-
-	def on_damage(self, other, damage):
-		self.health -= damage
-
-	def on_die(self):
-		self.remove = True
+# 	def on_die(self):
+# 		self.remove = True

lib/actors/__init__.py

+from .grinch import Grinch
+from .items import UseableItem, StealableItem
+from .who import Who

lib/actors/basics.py

+import pyglet
+from ..vector import v
+
+# from math import sqrt
+# import math
+# import pyglet
+# from .vector import v
+
+# BASE_SPEED = 100
+# MAX_SPRINT_FACTOR = 1.5
+# ROTATION_SPEED = 2
+
+
+
+
+class GameObject(object):
+	def __init__(self, x, y, image_file, health=100, size=20, tag=None):
+		self.image = pyglet.image.load(image_file)
+		self.remove = False
+		self.pos = v(x,y)
+		self.sprint_factor = 1.0
+		self.health = health
+		self.size = size
+		self.tag = tag or ""
+		self.dir = v(0,0)
+
+	def draw(self):
+		self.image.blit(self.x, self.y)
+
+	def set_rotation_speed(self, left=None, right=None):
+		if right is not None:
+			self.right_rotation_speed = right
+		if left is not None:
+			self.left_rotation_speed = left
+
+	#dt = time inbetween each frame, others=all the other actors, level = level object, to interact with collision
+	def update(self, dt, others, level):
+		self.update_position(dt)
+
+		# if level.check_collision((self.x,self.y,20,20)):
+		# 	self.x -= self.speed_x * self.sprint_factor * dt
+		# 	self.y -= self.speed_y * self.sprint_factor * dt
+
+		for other in others:
+			if hasattr(other, 'y') and other is not self:
+				if self.get_distance(other.x, other.y) < (self.size + other.size) / 2:
+					self.on_collision(other)
+
+		if self.health < 0:
+			self.on_die()
+
+		#if this game object needs to be deleted
+		return self.remove
+
+	def update_position(self, dt):
+		pass
+
+	def get_distance(self, x, y):
+		return sqrt((self.x - x) ** 2 + (self.y - y) ** 2)
+
+	def register_input_handlers(self, window):
+		pass
+
+	def on_damage(self, other, damage):
+		pass
+
+	def on_collision(self, other):
+		pass
+
+	def on_damage(self, other, damage):
+		pass
+
+	# override this for each type of actor
+	def on_die(self):
+		pass
+
+	@property
+	def x(self):
+		return self.pos.x
+
+	@property
+	def y(self):
+		return self.pos.y
+
+	@property
+	def direction(self):
+		return self._direction
+
+	@direction.setter
+	def direction(self, val):
+		self._direction = val % 360

lib/actors/grinch.py

+from .basics import *
+
+class Grinch(GameObject):
+	def __init__(self, x,y, image_file, tag=""):
+		super(Grinch,self).__init__(x,y,image_file, tag="player")
+		self.aimer_image = pyglet.image.load("data/aimer.png")
+		self.mx = 0
+		self.my = 0
+		self.aimer_angle = 0
+		self.aimer_sprite = pyglet.sprite.Sprite(self.aimer_image, self.mx,self.my)
+		self.sack_weight = 1
+		self.useable_items = set()
+		self._base_speed = BASE_SPEED
+
+	def register_input_handlers(self, window):
+		from pyglet.window import key
+		window.register_input(key.UP, on_press=lambda: self.ModDir(0,1), on_release=lambda:self.ModDir(0,-1))
+		window.register_input(key.DOWN, on_press=lambda: self.ModDir(0,-1), on_release=lambda:self.ModDir(0,1))
+		window.register_input(key.RIGHT, on_press=lambda: self.ModDir(1,0), on_release=lambda:self.ModDir(-1,0))
+		window.register_input(key.LEFT, on_press=lambda: self.ModDir(-1,0), on_release=lambda:self.ModDir(1,0))
+		window.register_input(key.LSHIFT, on_press=lambda: self.SetSprint(MAX_SPRINT_FACTOR), on_release=lambda:self.SetSprint(1.0))
+		window.register_input(key.SPACE, on_press=lambda: self.use_item())
+
+	def set_mouse_coords(self,x,y):
+		self.mx = x
+		self.my = y
+		self.aimer_angle = (self.pos-v(self.mx,self.my)).angle
+		self.aimer_sprite.rotation = -self.aimer_angle - 90
+		self.aimer_sprite.position = (self.mx-10,self.my-10)
+
+	def ModDir(self, x,y):
+		self.dir += v(x,y)
+
+	def SetSprint(self, factor):
+		self.sprint_factor = factor
+
+	def update_position(self, dt):
+		self.pos += self.dir.safe_normalised() * self.speed * dt * self.sprint_factor
+
+	def on_collision(self, other):
+		if isinstance(other, StealableItem):
+			self.sack_weight += other.weight
+			other.on_die()
+		elif isinstance(other, UseableItem):
+			self.useable_items.add(other)
+			other.on_die()
+
+	def use_item(self, item=None):
+		if item is None:
+			item = self.useable_items.pop()
+		else:
+			self.useable_items.remove(item)
+		item.on_use()
+
+	def on_damage(self, other, damage):
+		self.health -= damage
+
+	def on_die(self):
+		self.remove = True
+
+	def draw(self):
+		self.image.blit(self.x, self.y)
+		self.aimer_sprite.draw()
+
+	@property
+	def speed(self):
+		return self._base_speed - self.sack_weight

lib/actors/items.py

+from .basics import *
+
+class StealableItem(GameObject):
+	def __init__(self, *args, weight=10, **kwargs):
+		super(StealableItem, self).__init__(*args, **kwargs)
+		self.weight = weight
+
+	def on_die(self):
+		self.remove = True
+
+
+class UseableItem(GameObject):
+	def __init__(self, *args, **kwargs):
+		super(StealableItem, self).__init__(*args, **kwargs)
+		self.weight = weight
+
+	def on_use(self, grinch):
+		print("Item Used!")
+
+	def on_die(self):
+		self.remove = True

lib/actors/who.py

+import math
+from .basics import *
+from .grinch import Grinch
+
+class Who(GameObject):
+	def update(self, dt, others, level):
+		super(Who,self).update(dt,others,level)
+		for i in others:
+			if i.tag == "player":
+				if math.pow((self.x-i.x), 2) + math.pow((self.y-i.y), 2) < math.pow(100,2):
+					#insert vector code here
+					pass
+	def on_collision(self, other):
+		if isinstance(other, Grinch):
+			other.on_damage(self, 25)
+
+# BOIDS - last updated for NodeBox 1.9.3
+# Author: Tom De Smedt <tomdesmedt@organisms.be>
+# Copyright (c) 2007 by Tom De Smedt.
+# See LICENSE.txt for details.
+
+# For the original pseucode the algorithm is based on:
+# http://www.vergenet.net/~conrad/boids/pseudocode.html
+
+from nodebox.util import random
+
+class Boid:
+    
+    def __init__(self, boids, x, y, z):
+        
+        self.boids = boids
+        self.flock = boids
+    
+        self.x = 1.0 * x
+        self.y = 1.0 * y
+        self.z = 1.0 * z
+        
+        self.vx = 0
+        self.vy = 0
+        self.vz = 0
+        
+        self.is_perching = False
+        self._perch_t = 0
+                
+    def copy(self):
+        
+        b = Boid(self.boids, self.x, self.y, self.z)
+        b.vx = self.vx
+        b.vy = self.vy
+        b.vz = self.vz
+        b.is_perching = self.is_perching
+        b._perch_t = self._perch_t
+        
+        return b
+        
+    def cohesion(self, d=100):
+        
+        """ Boids move towards the flock's centre of mass.
+        
+        The centre of mass is the average position of all boids,
+        not including itself (the "perceived centre").
+        
+        """
+        
+        vx = vy = vz = 0
+        for b in self.boids:
+            if b != self:
+                vx, vy, vz = vx+b.x, vy+b.y, vz+b.z
+                
+        n = len(self.boids)-1
+        vx, vy, vz = vx/n, vy/n, vz/n
+        
+        return (vx-self.x)/d, (vy-self.y)/d, (vz-self.z)/d
+                
+    def separation(self, r=10):
+        
+        """ Boids keep a small distance from other boids.
+        
+        Ensures that boids don't collide into each other,
+        in a smoothly accelerated motion.
+        
+        """
+        
+        vx = vy = vz = 0
+        for b in self.boids:
+            if b != self:
+                if abs(self.x-b.x) < r: vx += (self.x-b.x)
+                if abs(self.y-b.y) < r: vy += (self.y-b.y)
+                if abs(self.z-b.z) < r: vz += (self.z-b.z)
+                
+        return vx, vy, vz
+        
+    def alignment(self, d=5):
+        
+        """ Boids match velocity with other boids.
+        """
+        
+        vx = vy = vz = 0
+        for b in self.boids:
+           if b != self:
+               vx, vy, vz = vx+b.vx, vy+b.vy, vz+b.vz
+        
+        n = len(self.boids)-1
+        vx, vy, vz = vx/n, vy/n, vz/n
+        
+        return (vx-self.vx)/d, (vy-self.vy)/d, (vz-self.vz)/d
+        
+    def limit(self, max=30):
+        
+        """ The speed limit for a boid.
+        
+        Boids can momentarily go very fast,
+        something that is impossible for real animals.
+        
+        """
+        
+        if abs(self.vx) > max: 
+            self.vx = self.vx/abs(self.vx)*max
+        if abs(self.vy) > max: 
+            self.vy = self.vy/abs(self.vy)*max
+        if abs(self.vz) > max: 
+            self.vz = self.vz/abs(self.vz)*max
+        
+    def _angle(self):
+        
+        """ Returns the angle towards which the boid is steering.
+        """
+        
+        from math import atan, pi, degrees
+        a = degrees(atan(self.vy/self.vx)) + 360
+        if self.vx < 0: a += 180
+
+        return a
+    
+    angle = property(_angle)
+        
+    def goal(self, x, y, z, d=50.0):
+        
+        """ Tendency towards a particular place.
+        """
+        
+        return (x-self.x)/d, (y-self.y)/d, (z-self.z)/d
+        
+class Boids(list):
+    
+    def __init__(self, n, x, y, w, h):
+        
+        for i in range(n):
+            dx = random(w)
+            dy = random(h)
+            z = random(200)
+            b = Boid(self, x+dx, y+dy, z)
+            self.append(b)
+            
+        self.x = x
+        self.y = y
+        self.w = w
+        self.h = h
+        
+        self.scattered = False
+        self._scatter = 0.005
+        self._scatter_t = 50
+        self._scatter_i = 0
+        
+        self._perch = 1.0 # Lower this number to simulate diving.
+        self._perch_y = _ctx.HEIGHT
+        self._perch_t = lambda:25+random(50)
+    
+        self.has_goal = False
+        self.flee = False
+        self._gx = 0
+        self._gy = 0
+        self._gz = 0
+    
+    # Backwards compatibility:
+    def _boids(self): return self
+    boids = property(_boids)
+    
+    def copy(self):
+        
+        boids = Boids(0, self.x, self.y, self.w, self.h)
+        
+        boids.scattered = self.scattered
+        boids._scatter = self._scatter
+        boids._scatter_t = self._scatter_t
+        boids._scatter_i = self._scatter_i
+        
+        boids._perch = self._perch
+        boids._perch_y = self._perch_y
+        boids._perch_t = self._perch_t
+        
+        boids.has_goal = self.has_goal
+        boids.flee = self.flee
+        boids._gx = self._gx
+        boids._gy = self._gy
+        boids._gz = self._gz
+        
+        for boid in self:
+            boids.append(boid.copy())
+            
+        return boids
+
+    def scatter(self, chance=0.005, frames=50):
+        
+        self._scatter = chance
+        self._scatter_t = frames
+    
+    def noscatter(self):
+        
+        self._scatter = 0.0
+    
+    def perch(self, ground=None, chance=1.0, frames=lambda:25+random(50)):
+        
+        if ground == None:
+            ground = _ctx.HEIGHT
+            
+        self._perch = chance
+        self._perch_y = ground
+        self._perch_t = frames
+    
+    def noperch(self):
+        
+        self._perch = 0.0
+    
+    def goal(self, x, y, z, flee=False):
+        
+        self.has_goal = True
+        self.flee = flee
+        self._gx = x
+        self._gy = y
+        self._gz = z
+        
+    def nogoal(self):
+        
+        self.has_goal = False
+        
+    def constrain(self):
+        
+        """ Cages the flock inside the x, y, w, h area.
+        
+        The actual cage is a bit larger,
+        so boids don't seem to bounce of invisible walls
+        (they are rather "encouraged" to stay in the area).
+        
+        If a boid touches the ground level,
+        it may decide to perch there for a while.
+        
+        """
+        
+        dx = self.w * 0.1
+        dy = self.h * 0.1 
+        
+        for b in self:
+            
+            if b.x < self.x-dx: b.vx += random(dx)
+            if b.y < self.y-dy: b.vy += random(dy)
+            if b.x > self.x+self.w+dx: b.vx -= random(dx)
+            if b.y > self.y+self.h+dy: b.vy -= random(dy)
+            if b.z < 0: b.vz += 10
+            if b.z > 100: b.vz -= 10
+            
+            if b.y > self._perch_y and random() < self._perch:
+                b.y = self._perch_y
+                b.vy = -abs(b.vy) * 0.2
+                b.is_perching = True
+                try:
+                    b._perch_t = self._perch_t()
+                except:
+                    b._perch_t = self._perch_t
+            
+    def update(self, 
+               shuffled=True, 
+               cohesion=100, 
+               separation=10, 
+               alignment=5, 
+               goal=20,
+               limit=30):
+        
+        """ Calculates the next motion frame for the flock.
+        """
+        
+        # Shuffling the list of boids ensures fluid movement.
+        # If you need the boids to retain their position in the list
+        # each update, set the shuffled parameter to False.
+        from random import shuffle
+        if shuffled: shuffle(self)
+        
+        m1 = 1.0 # cohesion
+        m2 = 1.0 # separation
+        m3 = 1.0 # alignment
+        m4 = 1.0 # goal
+        
+        # The flock scatters randomly with a Boids.scatter chance.
+        # This means their cohesion (m1) is reversed,
+        # and their joint alignment (m3) is dimished,
+        # causing boids to oscillate in confusion.
+        # Setting Boids.scatter(chance=0) ensures they never scatter.
+        if not self.scattered and random() < self._scatter:
+            self.scattered = True
+        if self.scattered:
+            m1 = -m1
+            m3 *= 0.25
+            self._scatter_i += 1
+        if self._scatter_i >= self._scatter_t:
+            self.scattered = False
+            self._scatter_i = 0
+
+        # A flock can have a goal defined with Boids.goal(x,y,z),
+        # a place of interest to flock around.
+        if not self.has_goal:
+            m4 = 0
+        if self.flee:
+            m4 = -m4
+        
+        for b in self:
+            
+            # A boid that is perching will continue to do so
+            # until Boid._perch_t reaches zero.
+            if b.is_perching:
+                if b._perch_t > 0:
+                    b._perch_t -= 1
+                    continue
+                else:
+                    b.is_perching = False
+            
+            vx1, vy1, vz1 = b.cohesion(cohesion)
+            vx2, vy2, vz2 = b.separation(separation)
+            vx3, vy3, vz3 = b.alignment(alignment)
+            vx4, vy4, vz4 = b.goal(self._gx, self._gy, self._gz, goal)
+            
+            b.vx += m1*vx1 + m2*vx2 + m3*vx3 + m4*vx4
+            b.vy += m1*vy1 + m2*vy2 + m3*vy3 + m4*vy4
+            b.vz += m1*vz1 + m2*vz2 + m3*vz3 + m4*vz4
+            
+            b.limit(limit)
+        
+            b.x += b.vx
+            b.y += b.vy
+            b.z += b.vz
+        
+        self.constrain()
+        
+def flock(n, x, y, w, h):
+    
+    return Boids(n, x, y, w, h)

lib/level_editor.py

 		self.tiles = []
 		self.tile_images = []
 
-		im = pyglet.image.load("data/tiles.png")
-		self.tile_images.append(im.get_region(0,0,20,20))
-		self.tile_images.append(im.get_region(20,0,20,20))
+		im = pyglet.image.load("data/floor.png")
+		cols = 3
+		rows = 8
+		for y in range(rows):
+			for x in range(cols):
+				r = im.get_region(x*20,y*20,20,20)
+				self.tile_images.append(r)
+
 
 		self.batch = pyglet.graphics.Batch()
 		self.sprites = []
 			y = int(l[2])
 			self.objects.append(GameObject(x,y,name))
 
+	def PickTile(self,mx,my):
+		start_x = 660
+		x = start_x
+		y = 280
+		for i in range(len(self.tile_images)):
+			if mx > x and mx < x+20 and my > y and my < y+20:
+				return i
+			x += 21
+			if x >= start_x +(21*3):
+				x = start_x
+				y += 21
+		return -1
+
 
 	def draw(self):
 		self.batch.draw()
 		for i in self.objects:
 			i.draw()
+		start_x = 660
+		x = start_x
+		y = 280
+		for i in range(len(self.tile_images)):
+			self.tile_images[i].blit(x,y)
+			x += 21
+			if x >= start_x +(21*3):
+				x = start_x
+				y += 21
+
 	def GetTileAt(self,x,y):
 		pass
 	def SetTileAt(self,x,y,t):
 
 class GameWindow(pyglet.window.Window):
 	def __init__(self):
-		super(GameWindow, self).__init__(680,480)
+		super(GameWindow, self).__init__(740,480)
 		glEnable(GL_BLEND)
 		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
 		#make the update function run every sixtyth of a second
 
 	def on_mouse_press(self,x, y, button, modifiers):
 		if pyglet.window.mouse.LEFT == button:
-			self.level.SetTileAt(x,y, self.tile_type)
-		if pyglet.window.mouse.MIDDLE == button:
-			self.tile_type += 1
-			if self.tile_type >= self.num_tiles:
-				self.tile_type = 0
+			if x > 640:
+				r = self.level.PickTile(x,y)
+				if r != -1:
+					self.tile_type = r
+			else:
+				self.level.SetTileAt(x,y, self.tile_type)
 		if pyglet.window.mouse.RIGHT == button:
 			if self.is_removing is False:
 				self.level.place_objects(x,y,self.object_types[self.object_sel])
 import pyglet
 from pyglet.window import key
 from . import level
-from . import actor
+from . import actors
 
 from pyglet.gl import *
 
 			x = int(l[1])
 			y = int(l[2])
 			if name == "zombie":
-				self.actors.add(actor.Human(x, y, "data/zombie.png", tag="player"))
+				self.actors.add(actors.Grinch(x, y, "data/zombie.png", tag="player"))
 			elif name == "hero":
-				self.actors.add(actor.Zombie(x, y, "data/hero.png"))
+				self.actors.add(actors.Who(x, y, "data/hero.png"))
 
 
 
 32,24
-1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,1,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,1,1,0,0,1,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,1,1,0,0,1,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,1,1,0,0,1,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,1,1,0,0,1,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,1,1,0,0,1,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-end,620,60
-zombie,40,20
-hero,100,380
-hero,460,140
-hero,80,120
+2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,22,1,2,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,1,2,2,22,1,2,22,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,16,2,2,22,1,2,22,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,16,2,2,22,1,2,22,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,16,2,2,22,1,2,22,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,16,2,2,22,1,2,22,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,16,2,2,22,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,16,2,2,22,17,20,23,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,16,2,2,22,15,18,21,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,16,2,2,22,16,2,22,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,16,2,2,18,1,2,22,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,16,2,2,2,2,2,22,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,16,2,2,23,20,20,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,16,2,2,22,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,16,2,2,22,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,16,2,2,22,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,16,2,2,22,1,1,1,1,1,1,1,1,1,1,1,1,15,18,18,18,18,18,21,1,16,2,2,22,1,1,1,1,1,1,1,1,1,1,1,1,16,2,2,2,2,2,22,1,16,2,2,22,1,1,1,1,1,1,1,1,1,1,1,1,16,2,2,2,2,2,22,1,16,2,2,22,1,1,1,1,1,1,1,1,1,1,1,1,16,2,2,2,2,2,22,1,16,2,2,22,1,1,1,1,1,1,1,1,1,1,1,1,17,20,20,20,20,20,23,1,16,2,2,22,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,16,2,2,22,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,16,2,2,22,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,16,2,2,22,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,16,2,2,22,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,16,2,2,22,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,16,2,2,22,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,16,2,2,22,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,16,2,2,1,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
+hero,240,220
+zombie,180,120