Commits

Don Spaulding committed 9db1667

The compo version.

Comments (0)

Files changed (12)

+Use the arrow keys to move the grinch through the houses of whoville. Steal the presents and the escape out the chimny 
+(you will not be able to leave unless you have all the presents, mind you). Each present you get will slow you down, so be carefull. 
+Small who children may be awake in certain parts of the house, and if the touch you, the may cause your heart to grow two or 
+three sizes.
+
+Required:
+-Python (3.2.3 tested)
+-pyglet (1.2 alpha tested)
+-Avbin
+
+execute "run_game.py" in what ever manner works for your system to start the game.

data/levels/level_1

+18,18
+2,5,5,5,5,5,5,5,5,5,5,5,2,5,5,5,5,2,4,21,24,24,24,24,24,24,24,24,24,27,2,21,24,24,27,0,4,22,1,1,1,1,1,1,1,1,1,28,2,22,1,1,28,0,4,22,1,1,1,1,1,1,1,1,1,28,2,22,1,1,28,0,4,22,1,1,1,1,1,1,1,1,1,32,24,38,1,1,28,0,4,22,1,1,1,1,1,1,1,1,1,30,26,36,1,1,28,0,4,22,1,1,1,1,1,1,1,1,1,28,2,22,1,1,28,0,4,22,1,1,1,1,1,1,1,1,1,28,2,22,1,1,28,0,4,22,1,1,1,1,1,1,1,1,1,28,2,22,1,1,28,0,4,23,26,26,26,26,26,26,26,26,26,29,2,22,1,1,28,0,2,2,2,2,2,2,2,2,2,2,2,2,2,22,1,1,28,0,4,21,24,24,24,24,24,24,24,24,24,24,24,38,1,1,28,0,4,22,1,1,1,1,1,1,1,1,30,26,36,1,1,1,28,0,4,22,1,1,1,1,1,1,1,1,31,2,37,1,1,1,28,0,4,22,1,1,1,1,1,1,1,1,31,2,37,1,1,1,28,0,4,22,1,1,1,1,1,1,1,1,31,2,37,1,1,1,28,0,4,23,26,26,26,26,26,26,26,26,29,2,23,26,26,26,29,0,2,3,3,3,3,3,3,3,19,3,3,2,3,3,3,3,3,2,
+zombie,20,20
+present1,40,300
+present1,160,160
+present2,240,40
+end,340,160

data/levels/level_2

+24,22
+2,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,2,4,21,24,24,24,24,24,27,2,21,24,24,24,24,27,2,21,24,24,24,27,0,4,22,1,1,1,1,1,28,2,22,1,1,1,1,31,2,22,1,1,1,28,0,4,22,1,1,1,1,1,28,2,22,1,1,1,1,32,24,1,1,1,1,28,0,4,22,1,1,1,1,1,28,2,22,1,1,1,1,30,26,36,1,1,1,28,0,4,22,1,1,1,1,1,28,2,22,1,1,1,1,31,2,22,1,1,1,28,0,4,37,30,26,26,26,26,29,2,23,26,36,30,26,29,2,23,26,26,26,29,0,4,37,28,2,2,2,2,2,2,2,2,22,28,2,2,2,2,2,2,2,2,0,4,37,32,24,24,24,24,24,24,24,24,38,32,24,24,24,24,24,24,24,24,0,4,37,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,4,23,26,26,26,26,26,26,36,30,26,26,26,26,26,26,26,26,26,26,26,0,2,2,2,2,2,2,2,2,22,28,2,2,2,2,2,2,2,2,2,2,2,0,4,21,24,24,27,2,21,24,38,32,24,24,27,2,21,24,24,24,24,24,27,0,4,22,1,1,28,2,22,1,1,1,1,1,28,2,22,1,1,1,1,1,28,0,4,22,1,1,32,24,38,1,1,1,1,1,31,2,22,1,1,1,1,1,28,18,4,22,1,1,30,26,36,1,1,1,1,1,31,2,22,1,1,1,1,1,28,0,4,22,1,1,28,2,22,1,1,1,1,1,31,2,22,1,1,1,1,1,28,0,4,22,1,1,31,2,22,1,1,1,1,1,28,2,22,1,1,1,1,1,28,0,4,22,1,1,31,2,22,1,1,1,1,1,32,24,38,1,1,1,1,1,28,0,4,22,1,1,31,2,22,1,1,1,1,1,1,1,1,1,1,1,1,1,28,0,4,22,1,1,31,2,22,1,1,1,1,1,30,26,36,1,1,1,1,1,28,0,4,22,1,1,31,2,22,1,1,1,1,1,28,2,22,1,1,1,1,1,28,0,4,23,26,26,29,2,23,26,26,26,26,26,29,2,23,26,26,26,26,26,29,0,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,
+zombie,40,400
+end,280,420
+present1,120,320
+present2,20,180
+present3,440,40
+present4,240,240
+present5,420,380
+hero,40,60

data/levels/level_3

+22,22
+2,5,5,5,5,5,5,5,5,5,5,5,5,2,5,5,5,5,5,5,5,2,4,21,24,24,24,24,24,24,24,24,24,24,27,2,21,24,24,24,24,24,27,0,4,22,1,1,1,1,1,1,1,1,1,1,28,2,22,1,26,36,1,1,28,0,4,22,1,1,1,1,1,1,30,26,26,26,29,2,22,28,2,22,1,1,28,0,4,22,1,1,1,1,1,1,28,2,2,2,2,2,22,28,2,22,1,1,28,0,4,22,1,1,1,1,1,1,32,24,24,24,27,2,22,28,2,22,1,1,28,0,4,22,1,1,1,1,1,1,1,1,1,1,28,2,22,28,2,22,1,1,28,0,4,22,1,1,1,1,1,1,1,1,1,1,32,24,38,28,2,22,1,1,28,0,4,22,30,26,26,26,26,26,26,26,26,26,26,26,26,29,2,23,26,36,28,0,4,22,28,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,22,28,0,4,22,32,24,27,2,21,24,24,24,24,24,27,2,21,24,24,24,24,38,28,0,4,22,1,1,28,2,22,1,1,1,1,1,28,2,22,30,26,26,26,36,28,0,4,22,1,1,28,2,22,1,1,1,1,1,32,24,38,28,2,2,2,22,28,0,4,22,1,1,28,2,22,1,1,1,1,1,30,26,36,28,2,21,24,38,28,0,4,22,1,1,28,2,23,26,26,26,26,26,29,2,22,28,2,22,1,1,28,0,4,22,1,1,28,2,2,2,2,2,2,2,2,2,22,28,2,22,1,1,28,0,4,22,1,1,28,2,21,24,24,24,24,24,27,2,22,28,2,22,1,1,28,0,4,22,1,1,28,2,22,1,1,1,1,1,32,24,38,28,2,22,1,1,28,0,4,22,1,1,28,2,22,1,1,1,1,1,30,26,36,28,2,22,1,1,28,0,4,22,1,1,28,2,22,1,1,1,1,1,28,2,22,28,2,22,1,1,28,0,4,23,26,26,29,2,23,26,26,26,26,26,29,2,23,29,2,23,26,26,29,0,2,3,19,3,3,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,
+hero,40,220
+present6,80,60
+present1,220,120
+present2,360,360
+present3,40,380
+present4,280,60
+zombie,380,140
+end,420,40

data/levels/level_4

+22,22
+2,5,5,5,5,5,5,5,5,5,5,2,5,5,5,5,5,5,5,5,5,2,4,21,24,24,24,24,24,24,24,24,27,2,21,24,24,24,24,24,24,24,27,0,4,22,1,1,1,1,1,1,1,1,28,2,22,1,1,1,30,26,36,1,28,0,4,22,1,1,30,26,36,1,1,1,28,2,22,1,1,1,28,2,22,1,28,0,4,22,1,1,28,2,22,1,1,1,28,2,22,1,1,1,28,2,22,1,28,0,4,23,26,26,29,2,23,26,36,1,29,2,23,36,30,26,29,2,23,26,29,0,2,2,2,2,2,2,2,2,22,28,2,2,2,22,28,2,2,2,2,2,2,2,4,21,24,24,24,24,24,24,38,32,24,24,24,38,32,24,24,24,24,24,27,0,4,23,36,30,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,36,28,0,2,2,22,28,2,2,2,2,2,15,2,2,2,2,2,2,2,2,2,22,28,0,4,21,38,32,24,27,2,21,24,24,24,24,27,2,21,24,24,24,24,38,28,0,4,22,1,1,1,28,2,23,26,26,26,36,28,2,22,30,26,26,26,26,29,0,4,22,1,1,1,28,2,2,2,2,2,22,28,2,22,28,2,2,2,2,2,2,4,22,1,1,1,28,2,21,24,27,2,22,28,2,22,28,2,21,24,24,27,0,4,22,1,1,1,28,2,22,1,28,2,22,28,2,22,28,2,22,1,1,28,0,4,22,1,1,1,28,2,22,1,28,2,22,28,2,22,28,2,22,1,1,28,0,4,22,1,1,1,28,2,22,1,28,2,22,28,2,22,28,2,22,1,1,28,0,4,22,1,1,1,28,2,22,16,28,2,22,28,2,22,28,2,23,26,36,28,0,4,22,1,1,1,28,2,22,1,28,2,22,28,2,22,28,2,2,2,22,28,0,4,22,1,1,1,32,24,38,16,32,24,38,28,2,22,32,24,24,24,38,28,0,4,23,26,26,26,26,26,26,26,26,26,26,29,2,23,26,26,26,26,26,29,0,2,3,3,3,3,3,3,3,3,3,3,3,3,2,3,3,3,3,3,3,3,2,
+zombie,300,280
+end,180,180
+present1,360,400
+hero,260,360
+hero,100,400
+present2,360,40
+present4,20,360
+present5,220,280
+hero,100,20
+hero,280,140
+present3,20,120
+hero,280,180

data/levels/level_5

+32,24
+2,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,2,5,5,5,5,5,2,4,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,27,2,21,24,24,24,27,0,4,1,1,1,1,1,1,1,30,26,36,1,1,1,1,1,28,2,22,1,1,1,28,0,4,1,30,26,26,26,26,26,29,2,22,1,1,1,1,1,32,24,38,1,1,1,28,0,4,1,28,2,2,2,2,2,2,2,22,1,1,1,1,1,30,26,36,1,1,1,28,0,4,1,28,2,21,24,24,24,27,2,23,26,26,26,26,26,29,2,23,26,36,30,29,0,4,1,28,2,22,1,1,1,28,2,2,2,2,2,2,2,2,2,2,2,22,28,2,2,4,1,28,2,22,1,1,1,28,2,21,24,24,24,24,24,24,24,24,24,38,32,27,0,4,1,32,24,38,1,1,1,28,2,22,1,1,1,1,1,1,1,1,1,1,1,28,0,4,26,26,26,26,26,26,26,29,2,23,36,30,26,26,26,26,26,26,26,26,26,29,0,2,2,2,2,2,2,2,2,2,2,2,22,28,2,2,2,2,2,2,2,2,2,2,2,4,21,24,24,24,24,24,24,24,24,24,38,32,24,24,24,24,24,24,24,24,24,27,0,4,22,1,1,1,1,1,1,16,16,16,16,16,16,16,16,16,1,1,1,1,1,28,0,4,23,36,1,1,1,1,1,16,16,16,16,1,1,1,1,16,1,1,1,1,30,29,0,4,2,37,1,1,1,1,16,16,16,16,1,1,1,1,1,16,1,1,1,1,28,2,2,4,21,38,1,1,1,1,1,16,16,16,16,1,16,16,1,16,1,1,1,1,32,27,0,4,22,1,1,1,1,1,16,16,16,16,16,1,16,1,16,1,16,1,1,1,1,28,0,4,22,1,1,1,1,1,16,16,16,16,1,1,16,1,16,16,1,1,1,1,1,28,0,4,22,1,1,1,1,1,16,16,16,16,16,1,1,16,1,1,1,1,1,1,1,28,0,4,23,26,26,36,1,16,16,16,16,16,16,16,16,16,16,1,1,1,30,26,26,29,0,2,2,2,2,37,1,1,16,16,1,16,16,16,1,1,1,1,1,1,28,2,2,2,2,4,21,24,24,38,1,1,1,16,16,1,1,1,1,1,1,1,1,1,32,24,24,27,0,4,22,1,1,1,1,1,1,16,1,16,1,1,1,1,1,1,1,1,1,1,1,28,0,4,22,1,1,1,1,1,1,1,16,1,1,1,1,1,1,1,1,1,1,1,1,28,0,4,23,26,26,26,26,26,26,26,26,36,1,30,33,26,26,26,26,26,26,26,26,29,0,2,2,2,2,2,2,2,2,2,2,22,1,28,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,22,1,28,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,22,1,28,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,22,1,28,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,22,1,28,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,23,26,29,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,19,3,2,2,2,2,2,2,2,2,2,2,2,
+hero,240,420
+hero,320,420
+hero,440,40
+hero,480,20
+hero,320,20
+hero,360,40
+hero,240,40
+hero,360,420
+hero,440,420
+hero,480,420
+present3,20,420
+present6,560,220
+zombie,120,140
+end,620,220
+present2,380,220
+present4,440,240
+present5,500,200
+present1,40,20
+present2,540,220
+32,24
+2,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,2,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,4,1,1,1,1,1,1,1,1,1,16,16,1,1,1,1,1,1,1,1,1,1,1,0,4,1,1,1,1,1,1,1,1,1,1,16,16,1,1,1,1,1,1,1,1,1,1,0,4,1,1,1,1,1,1,1,16,16,16,16,16,16,16,16,16,1,1,1,1,1,1,0,4,1,1,1,1,1,1,1,16,16,16,16,1,1,1,1,16,1,1,1,1,1,1,0,4,1,1,1,1,1,1,16,16,16,16,1,1,1,1,1,16,1,1,1,1,1,1,0,4,1,1,1,1,1,1,1,16,16,16,16,1,16,16,1,16,1,1,1,1,1,1,0,4,1,1,1,1,1,1,16,16,16,16,16,1,16,1,16,1,16,1,1,1,1,1,0,4,1,1,1,1,1,1,16,16,16,16,1,1,16,1,16,16,1,1,1,1,1,1,0,4,1,1,1,1,1,1,16,16,16,16,16,1,1,16,1,1,1,1,1,1,1,1,0,4,1,1,1,1,1,16,16,16,16,16,16,16,16,16,16,1,1,1,1,1,1,1,0,4,1,1,1,1,1,1,16,16,1,16,16,16,1,1,1,1,1,1,1,1,1,1,0,4,1,1,1,1,1,1,1,16,16,1,1,1,1,1,1,1,1,1,1,1,1,1,0,4,1,1,1,1,1,1,1,16,1,16,1,1,1,1,1,1,1,1,1,1,1,1,0,4,1,1,1,1,1,1,1,1,16,1,1,1,1,1,1,1,1,1,1,1,1,1,0,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,

lib/actors/grinch.py

 from .basics import *
 from .items import StealableItem, UseableItem
 
-BASE_SPEED = 100
-MAX_SPRINT_FACTOR = 1.5
+BASE_SPEED = 150
+MAX_SPRINT_FACTOR = 1
 
 def load_sprite(imgfile):
 	img = pyglet.image.load(imgfile)
 class Grinch(GameObject):
 	def __init__(self, x, y, **kwargs):
 		super(Grinch,self).__init__(x,y, **kwargs)
-		self.aimer_image = pyglet.image.load("data/aimer.png")
+		#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.aimer_angle = 0
+		#self.aimer_sprite = pyglet.sprite.Sprite(self.aimer_image, self.mx,self.my)
 		self.sprites = list(map(load_sprite, [
 			"data/grinch2.png",
 			"data/grinch1.png",
 		self.useable_items = set()
 		self._base_speed = BASE_SPEED
 		self.current_frame = 0
+		self.collected_presents = 0
+		self.used_items = []
+		self.angle = 0
+
+		self.health = 0
 
 	def register_input_handlers(self, window):
 		from pyglet.window import key
 	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)
+		#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)
 		new_pos = self.pos + self.dir.safe_normalised() * self.speed * dt * self.sprint_factor
 		new_x, new_y = new_pos.x, new_pos.y
 		if (self.pos - new_pos).length:
+			self.angle = v(-self.dir.x, self.dir.y).angle + 180
 			self.current_frame += 4 * dt
 			if self.current_frame > 3:
 				self.current_frame = 0
 
 	def on_collision(self, other):
 		if isinstance(other, StealableItem):
-			self.sack_weight += other.weight
-			other.on_die()
+			if id(other) not in self.used_items:
+				self.sack_weight += other.weight
+				self.collected_presents += 1
+				self.used_items.append(id(other))
+				other.on_die()
 		elif isinstance(other, UseableItem):
 			self.useable_items.add(other)
 			other.on_die()
 		self.remove = True
 
 	def draw(self):
-		self.aimer_sprite.draw()
+		#self.aimer_sprite.draw()
 		sprite = self.sprites[round(self.current_frame)]
 		sprite.position = self.x + sprite.width // 2, self.y + sprite.height // 2
-		sprite.rotation = v(-self.dir.x, self.dir.y).angle + 180
+		sprite.rotation = self.angle
 		sprite.draw()
 
 	@property

lib/actors/items.py

 from .basics import *
 
 class StealableItem(GameObject):
-	def __init__(self, *args, weight=10, **kwargs):
+	def __init__(self, name, *args, weight=10, **kwargs):
 		super(StealableItem, self).__init__(*args, **kwargs)
 		self.weight = weight
 
+		self.image = None
+		self.name =name
+
+		if name == "present1":
+			self.image = pyglet.image.load("data/present1.png")
+		elif name == "present2":
+			self.image = pyglet.image.load("data/present2.png")
+		elif name == "present3":
+			self.image = pyglet.image.load("data/present3.png")
+		elif name == "present4":
+			self.image = pyglet.image.load("data/present4.png")
+		elif name == "present5":
+			self.image = pyglet.image.load("data/present5.png")
+		elif name == "present6":
+			self.image = pyglet.image.load("data/tree.png")
+
+
 	def on_die(self):
 		self.remove = True
 
 class UseableItem(GameObject):
 	def __init__(self, *args, **kwargs):
 		super(StealableItem, self).__init__(*args, **kwargs)
-		self.weight = weight
+		self.weight = 10
 
 	def on_use(self, grinch):
 		print("Item Used!")

lib/level_editor.py

 import pyglet
 import random
+import os
 
 class Tile(object):
 	def __init__(self, x,y, tile_type):
 		elif name == "present6":
 			self.image = pyglet.image.load("data/tree.png")
 
-		print(name)
-
 	def draw(self):
 		self.image.blit(self.x,self.y)
 
 
 	def load(self,filename):
 		self.filename = filename
-		f = open(self.filename, "r")
-		lines = f.readlines()
-		atribs = lines[0]
-		tile_list = lines[1]
-		objs = lines[2:]
+		if os.path.exists(filename):
+			f = open(self.filename, "r")
+			lines = f.readlines()
+			atribs = lines[0]
 
-		#load attributes
-		atribs = atribs.replace("\n", "")
-		props = atribs.split(",")
-		self.num_columns = int(props[0])
-		self.num_rows = int(props[1])
 
-		tiles = tile_list.split(",")
+			#load attributes
+			atribs = atribs.replace("\n", "")
+			props = atribs.split(",")
+			self.num_columns = int(props[0])
+			self.num_rows = int(props[1])
 
-		self.tiles = []
+			tile_list = ""
 
-		i = 0
-		for x in range(self.num_columns):
-			for y in range(self.num_rows):
-				self.tiles.append(Tile((x*self.tile_w),(y*self.tile_h),int(tiles[i])))
-				i += 1
-		for i in objs:
-			i.replace("\n", "")
-			l = i.split(",")
-			name = l[0]
+			if len(lines) > 1:
+				tile_list = lines[1]
+			if tile_list in ("", "\n"):
+				for x in range(self.num_columns):
+					for y in range(self.num_rows):
+						self.tiles.append(Tile(x*self.tile_w, y*self.tile_h, 1))
+				return
 
-			x = int(l[1])
-			y = int(l[2])
-			self.objects.append(GameObject(x,y,name))
+			tiles = tile_list.split(",")
+
+			self.tiles = []
+
+			i = 0
+			for x in range(self.num_columns):
+				for y in range(self.num_rows):
+					self.tiles.append(Tile((x*self.tile_w),(y*self.tile_h),int(tiles[i])))
+					i += 1
+
+			objs = lines[2:]
+			for i in objs:
+				i.replace("\n", "")
+				l = i.split(",")
+				name = l[0]
+
+				x = int(l[1])
+				y = int(l[2])
+				self.objects.append(GameObject(x,y,name))
+		else:
+			for x in range(self.num_columns):
+				for y in range(self.num_rows):
+					self.tiles.append(Tile(x*self.tile_w, y*self.tile_h, 1))
 
 	def PickTile(self,mx,my):
 		start_x = 660
 
 	def place_objects(self, x,y,name):
 
-		x = int((x/640)*self.num_columns)
-		y = int((y/480)*self.num_rows)
+		tx = int((x*self.num_columns)/(20*self.num_columns))
+		ty = int((y*self.num_rows)/(20*self.num_rows))
 
-		self.objects.append(GameObject(x*self.tile_w,y*self.tile_h,name))
+		self.objects.append(GameObject(tx*self.tile_w,ty*self.tile_h,name))
 	def remove_objects(self, x,y):
 
-		x = int((x/640)*self.num_columns)
-		y = int((y/480)*self.num_rows)
+		tx = int((x*self.num_columns)/(20*self.num_columns))
+		ty = int((y*self.num_rows)/(20*self.num_rows))
 
 		for i in self.objects:
-			if x == int(i.x/20) and y == int(i.y/20):
+			if tx == int(i.x/20) and ty == int(i.y/20):
 				self.objects.remove(i)
 
 
 
 
 class GameWindow(pyglet.window.Window):
-	def __init__(self):
+	def __init__(self,level_name):
 		super(GameWindow, self).__init__(740,480)
 		glEnable(GL_BLEND)
 		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
+		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
+		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
+		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP)
+		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP)
 		#make the update function run every sixtyth of a second
 		pyglet.clock.schedule_interval(self.update, 1.0/60.0)
 
 		self.objects = []
-		self.level = MapEdit("test_level")
+		self.level = MapEdit(level_name)
 		self.tile_type = 0
 		self.num_tiles = 2
 		self.object_sel = 0
 		self.mx = 0
 		self.my = 0
 		self.dark = 250
-		self.light_im = pyglet.sprite.Sprite(pyglet.image.load("data/light_huge.png"))
+		self.light_im = pyglet.sprite.Sprite(pyglet.image.load("data/light.png"))
 		self.light_im.opacity = self.dark
 
+		self.hold_shift = False
+		self.hold_click = False
+
 	def draw_quad(self,x1,y1,x2,y2):
 		pyglet.graphics.draw(4, pyglet.gl.GL_QUADS, ("v2f", [x1, y1, x2, y1, x2, y2, x1, y2]),('c4B', [0, 0, 0, self.dark] * 4))
 
 
 	def on_draw(self):
 		self.clear()
+
 		self.level.draw()
 
+		if self.hold_shift == True:
+			self.DrawLight(self.mx,self.my)	
+
 		self.object_images[self.object_sel].blit(680,120)	
-		#self.DrawLight(self.mx,self.my)	
 
 	def update(self,dt):
-		pass
+		if self.hold_click == True:
+			self.level.SetTileAt(self.mx,self.my, self.tile_type)
 	def on_key_press(self, key, modifiers):
 		if key == pyglet.window.key.TAB:
 			#this only works if there are only two tiles
 			self.level.save()
 		if key == pyglet.window.key.LCTRL:
 			self.is_removing = True
+		if key == pyglet.window.key.LSHIFT:
+			self.hold_shift = True
 	def on_key_release(self, key, modifiers):
 		if key == pyglet.window.key.LCTRL:
 			self.is_removing = False
+		if key == pyglet.window.key.LSHIFT:
+			self.hold_shift = False
 
 	def on_mouse_press(self,x, y, button, modifiers):
 		if pyglet.window.mouse.LEFT == button:
 				if r != -1:
 					self.tile_type = r
 			else:
-				self.level.SetTileAt(x,y, self.tile_type)
+				self.hold_click = True
+				self.mx = x
+				self.my = y
 		if pyglet.window.mouse.RIGHT == button:
 			if self.is_removing is False:
 				self.level.place_objects(x,y,self.object_types[self.object_sel])
 			else:
 				self.level.remove_objects(x,y)
+	def on_mouse_release(self,x,y,button,modifiers):
+		if pyglet.window.mouse.LEFT == button:
+			self.hold_click = False
+
 	def on_mouse_motion(self,x,y,dx,dy):
 		self.mx = x
 		self.my = y
+	def on_mouse_drag(self,x,y,dx,dy,buttons, modifiers):
+		self.mx = x
+		self.my = y
 
 
 
 def Run():
-	window = GameWindow()
+	import sys
+	if len(sys.argv) > 1:
+		window = GameWindow(sys.argv[1])
+	else:
+		window = GameWindow()
 	pyglet.app.run()
 
 
+import sys
 import pyglet
 from pyglet.window import key
 from . import level
 
 from pyglet.gl import *
 
-class GameWindow(pyglet.window.Window):
-	def __init__(self):
-		super(GameWindow, self).__init__()
-		glEnable(GL_BLEND)
-		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
-		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
-		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
-		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP)
-		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP)
+class BaseScene:
+	def __init__(self, window, *args, **kwargs):
+		self.window = window
+		self.init(*args, **kwargs)
 
+	def draw(self):
+		pass
+
+	def update(self, dt):
+		pass
+
+	def register_input(self, key, mods=None, on_press=None, on_release=None):
+		pass
+
+	def handle_input(self, symbol, mods, handler_list):
+		pass
+
+	def on_key_press(self, pressed, mods):
+		pass
+
+	def on_key_release(self, released, mods):
+		pass
+
+	def on_mouse_motion(self, x, y, dx, dy):
+		pass
+
+class RetryScene(BaseScene):
+	def init(self,level):
+		self.level = level
+		self.title_label = pyglet.text.Label(
+			'Fail!',
+			font_size=72,
+			x=320, y=400,
+			anchor_x='center', anchor_y='center', color=(255,0,0,255)
+		)
+		self.title2_label = pyglet.text.Label(
+			'Your Heart Grew Three Sizes!',
+			font_size=24,
+			x=320, y=300,
+			anchor_x='center', anchor_y='center', color=(255,0,0,255)
+		)
+		self.start_label = pyglet.text.Label(
+			"Press <Enter> To Restart The Level",
+			font_size=24,
+			x=320, y=200,
+			anchor_x='center', anchor_y='center', color=(255,0,0,255)
+		)
+		self.exit_label = pyglet.text.Label(
+			"Press <Escape> To Exit",
+			font_size=24,
+			x=320, y=100,
+			anchor_x='center', anchor_y='center', color=(255,0,0,190)
+		)
+
+	def draw(self):
+		self.title_label.draw()
+		self.title2_label.draw()
+		self.start_label.draw()
+		self.exit_label.draw()
+
+	def on_key_press(self, pressed, mods):
+		from pyglet.window import key
+		if pressed == key.ENTER:
+			self.window.scene = LevelScene(self.window, level_id=self.level)
+		elif pressed == key.ESCAPE:
+			self.window.show_main_menu()
+
+
+class LevelScene(BaseScene):
+	def init(self, level_id=None):
+		
 		self.mx = 0
 		self.my = 0
+		#the exit position
+		self.exit_pos = (0,0)		
+		self.actors = set()
+		self.presents_required = 0
 
-
-		#make the update function run every sixtyth of a second
-		pyglet.clock.schedule_interval(self.update, 1.0/60.0)
-
-		self.actors = set()
 		self.health_label = pyglet.text.Label('health',
                   font_size=24,
                   x=500, y=20,
                   anchor_x='center', anchor_y='center', color=(255,0,0,255))
-		self.key_press_handlers = [
-			(key.ESCAPE, [], lambda: self.on_close())
-		]
+		self.key_press_handlers = [(key.ESCAPE, [], lambda: self.window.show_main_menu())]
 		self.key_release_handlers = []
-
-		#the exit position
-		self.exit_pos = (0,0)
-
 		#load level objects
-		self.level = level.Map("test_level")
-		f = open("test_level", "r")
+		if level_id is None:
+			level_id = 1
+		self.level_id = level_id
+		level_name = "data/levels/level_%s" % self.level_id
+		self.level = level.Map(level_name)
+		f = open(level_name, "r")
 		lines = f.readlines()
 		objs = lines[2:]
 		for i in objs:
 				self.actors.add(actors.Grinch(x, y, size=30, tag="player"))
 			elif name == "hero":
 				self.actors.add(actors.Who(x, y, "data/hero.png"))
+			elif name.startswith("present"):
+				self.actors.add(actors.StealableItem(name, x, y))
+				self.presents_required += 1
 			elif name == "end":
 				self.exit_pos = (x, y)
 				print(self.exit_pos)
 
+
 		#flash light effect variables
 		self.dark = 250
 		self.light_im = pyglet.sprite.Sprite(pyglet.image.load("data/light.png"))
 
 		#healthbar vars
 		self.heart_size = 1
-
+		for actor in self.actors:
+			actor.register_input_handlers(self)
 
 	def draw_quad(self,x1,y1,x2,y2):
 		pyglet.graphics.draw(4, pyglet.gl.GL_QUADS, ("v2f", [x1, y1, x2, y1, x2, y2, x1, y2]),('c4B', [0, 0, 0, self.dark] * 4))
 
+
 	def DrawLight(self,x,y):
 		x = int(x)
 		y = int(y)
 		self.light_im.y = y-(self.light_im.image.width/2)
 		self.light_im.draw()
 
-	def on_draw(self):
-		self.clear()
+	def draw(self):
 		self.level.draw()
 		x = 0
 		y = 0
 
 		self.health_label.draw()
 
-	def update(self,dt):
-		#run all the actors update functions
+	def update(self, dt):
+		# run all the actors' update functions
 		removable_actors = set()
 		for actor in self.actors:
 			if actor.tag == "player":
 				actor.set_mouse_coords(self.mx,self.my)
 				self.heart_size = 3-actor.health
+				if actor.collected_presents >= self.presents_required and actor.get_distance(*self.exit_pos) < 35:
+					if self.level_id == 5:
+						self.window.scene = GameOverScene(self.window)
+					else:
+						self.window.scene = LevelCompletedScene(self.window, self.level_id + 1)
 			should_remove = actor.update(dt, self.actors, self.level)
 			if should_remove:
 				if actor.tag == "player":
-					self.on_close()
+					self.window.scene = RetryScene(self.window, self.level_id)
 				removable_actors.add(actor)
 		self.actors = self.actors - removable_actors
 
 	def on_key_release(self, released, mods):
 		self.handle_input(released, mods, self.key_release_handlers)
 
-	def on_mouse_motion(self, x,y, dx,dy):
+	def on_mouse_motion(self, x, y, dx, dy):
 		self.mx = x
 		self.my = y
 
+
+class GameOverScene(BaseScene):
+	def init(self):
+		self.main_label = pyglet.text.Label(
+			'YOU DID IT!',
+			font_size=72,
+			x=320, y=400,
+			anchor_x='center', anchor_y='center', color=(255,0,0,255)
+		)
+		self.congrats_label = pyglet.text.Label(
+			'Congratulations on completing Grinched!',
+			font_size=20,
+			x=320, y=200,
+			anchor_x='center', anchor_y='center', color=(255,0,0,255)
+		)
+		self.exit_label = pyglet.text.Label(
+			'Press <Escape> to Exit.',
+			font_size=12,
+			x=320, y=100,
+			anchor_x='center', anchor_y='center', color=(255,0,0,255)
+		)
+
+	def draw(self):
+		self.main_label.draw()
+		self.congrats_label.draw()
+		self.exit_label.draw()
+
+	def on_key_press(self, pressed, symbols):
+		if pressed == key.ESCAPE:
+			self.window.on_close()
+
+class MenuScene(BaseScene):
+	def init(self):
+		self.title_label = pyglet.text.Label(
+			'Grinched',
+			font_size=72,
+			x=320, y=400,
+			anchor_x='center', anchor_y='center', color=(255,0,0,255)
+		)
+		self.start_label = pyglet.text.Label(
+			"Press <Enter> To Start",
+			font_size=36,
+			x=320, y=200,
+			anchor_x='center', anchor_y='center', color=(255,0,0,255)
+		)
+		self.exit_label = pyglet.text.Label(
+			"Press <Escape> To Exit",
+			font_size=24,
+			x=320, y=100,
+			anchor_x='center', anchor_y='center', color=(255,0,0,190)
+		)
+
+	def draw(self):
+		self.title_label.draw()
+		self.start_label.draw()
+		self.exit_label.draw()
+
+	def on_key_press(self, pressed, mods):
+		from pyglet.window import key
+		if pressed == key.ENTER:
+			self.window.scene = LevelScene(self.window, level_id=1)
+		elif pressed == key.ESCAPE:
+			self.window.on_close()
+
+
+class LevelCompletedScene(BaseScene):
+	def init(self,next_level):
+		self.next_level = next_level
+		self.title_label = pyglet.text.Label(
+			'House Complete!',
+			font_size=48,
+			x=320, y=400,
+			anchor_x='center', anchor_y='center', color=(255,0,0,255)
+		)
+		self.start_label = pyglet.text.Label(
+			"Press <Enter> To Start Next Level",
+			font_size=24,
+			x=320, y=200,
+			anchor_x='center', anchor_y='center', color=(255,0,0,255)
+		)
+		self.exit_label = pyglet.text.Label(
+			"Press <Escape> To Exit",
+			font_size=24,
+			x=320, y=100,
+			anchor_x='center', anchor_y='center', color=(255,0,0,190)
+		)
+
+	def draw(self):
+		self.title_label.draw()
+		self.start_label.draw()
+		self.exit_label.draw()
+
+	def on_key_press(self, pressed, mods):
+		from pyglet.window import key
+		if pressed == key.ENTER:
+			self.window.scene = LevelScene(self.window, level_id=self.next_level)
+		elif pressed == key.ESCAPE:
+			self.window.show_main_menu()
+
+
+class GameWindow(pyglet.window.Window):
+	def __init__(self, level_name="test_level"):
+		super(GameWindow, self).__init__()
+		glEnable(GL_BLEND)
+		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
+		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
+		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
+		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP)
+		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP)
+
+		#make the update function run every sixtyth of a second
+		pyglet.clock.schedule_interval(self.update, 1.0/60.0)
+		self.show_main_menu()
+
+	def show_main_menu(self):
+		self.scene = MenuScene(self)
+
+	def on_draw(self):
+		self.clear()
+		self.scene.draw()
+
+	def update(self, dt):
+		self.scene.update(dt)
+
+	def on_key_press(self, pressed, mods):
+		self.scene.on_key_press(pressed, mods)
+
+	def on_key_release(self, released, mods):
+		self.scene.on_key_release(released, mods)
+
+	def on_mouse_motion(self, x, y, dx, dy):
+		self.scene.on_mouse_motion(x, y, dx, dy)
+
 def Run():
 	window = GameWindow()
-	for actor in window.actors:
-		actor.register_input_handlers(window)
+	# music = pyglet.resource.media('data/grinch.mp3')
+	# music.play()
 	pyglet.app.run()
 32,24
 2,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,2,4,21,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,27,0,4,22,25,25,25,25,1,1,1,1,1,1,1,1,1,1,1,1,1,25,25,25,28,0,4,22,25,25,25,25,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,25,28,0,4,22,25,25,25,25,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,25,28,0,4,22,25,25,25,25,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,25,28,0,4,22,25,25,25,25,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,25,28,18,4,22,25,25,25,25,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,25,28,0,4,22,25,25,25,25,1,1,1,1,1,1,1,1,1,1,1,30,33,36,1,25,28,0,4,22,25,25,25,25,1,1,1,1,1,1,1,1,1,1,1,28,2,37,1,25,28,0,4,22,16,25,25,25,1,1,1,1,1,1,1,1,1,1,1,28,2,37,1,25,28,0,4,22,25,25,25,25,1,1,1,1,1,1,1,1,1,1,1,28,2,37,1,1,28,0,4,22,25,25,25,25,1,1,1,1,1,1,1,1,1,1,1,28,2,37,1,1,28,0,4,22,25,25,25,25,1,1,1,1,1,1,1,1,1,1,1,28,2,37,1,1,28,0,4,22,25,25,25,25,1,1,1,1,1,1,1,1,1,1,1,28,2,37,1,1,28,0,4,22,25,25,25,25,1,1,1,1,1,1,1,1,1,1,1,28,2,37,1,1,28,0,4,22,25,25,25,25,1,1,1,1,1,1,1,1,1,1,1,28,2,37,1,1,28,0,4,22,25,25,25,25,1,1,1,1,1,30,26,26,26,26,26,29,2,37,25,1,28,0,4,22,25,25,25,25,1,1,1,1,1,28,2,2,2,2,2,2,2,37,25,1,28,0,4,22,25,25,25,25,1,1,1,1,1,28,2,21,35,35,35,35,35,38,25,1,28,0,4,22,25,25,25,25,1,1,1,1,1,28,2,23,26,26,26,26,26,36,25,1,28,0,4,22,25,25,25,25,1,1,1,1,1,28,2,2,2,2,2,2,2,37,25,1,28,0,4,22,25,1,1,1,1,1,1,1,1,32,24,24,24,24,24,27,2,37,1,1,28,0,4,22,25,1,1,1,1,1,1,1,1,1,1,1,1,1,1,31,2,37,1,1,28,0,4,22,25,1,1,1,1,1,1,1,1,1,1,1,1,1,1,31,2,37,1,1,28,0,4,22,25,1,1,1,1,1,1,1,1,1,1,1,1,1,1,32,24,38,1,1,28,0,4,22,25,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,28,0,4,22,25,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,28,0,4,22,25,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,28,0,4,22,25,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,28,0,4,23,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,26,29,0,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,2,
-hero,500,420
 end,120,460
 zombie,140,400
-hero,560,60
-hero,440,40
-hero,440,180
-hero,320,100
-hero,60,80
-hero,180,160
-hero,60,220
-hero,240,220
-hero,240,160
-hero,200,100
-hero,140,80
-hero,120,240
-hero,140,240
-hero,360,120
-hero,440,140
-hero,380,160
-hero,280,140
-hero,240,120
-hero,220,80
-hero,160,140
-hero,120,140
-hero,80,160
-hero,140,180
-hero,160,200
-hero,220,220
-hero,280,240
-hero,320,220
-hero,300,180
-hero,320,180
-hero,380,200
-hero,460,240
-hero,500,280
-hero,480,320
-hero,460,320
-hero,460,320
-hero,460,280
-hero,400,280
-hero,400,300
-hero,380,320
-hero,400,340
-hero,400,340
-hero,400,320
-hero,380,340
-hero,380,340
-hero,380,260
-hero,480,160
-hero,500,120
-hero,380,300
 hero,380,280
-hero,400,260
-hero,400,360
-hero,380,360
-hero,400,380
-hero,380,380
-hero,380,400
-hero,400,420
-hero,400,400
-hero,380,420
-hero,400,440
-hero,380,440
-hero,360,440
-hero,360,420
-hero,360,400
-hero,360,380
-hero,340,380
-hero,340,400
-hero,340,420
-hero,340,440
-hero,320,440
-hero,320,420
-hero,320,400
-hero,320,380
-hero,340,320
-hero,320,340
-hero,320,340
-hero,340,340
-hero,340,340
-hero,320,320
-hero,320,300
-hero,340,300
-hero,320,300
-hero,300,300
-hero,280,300
-hero,260,300
-hero,240,300
-hero,220,300
-hero,220,320
-hero,240,340
-hero,260,320
-hero,280,320
-hero,300,320
-hero,300,340
-hero,280,340
-hero,260,340
-hero,240,320
-hero,240,320
-hero,220,340
-hero,340,280
-hero,320,280
-hero,300,280
-hero,280,280
-hero,260,280
-hero,240,280
-hero,240,280
-hero,220,280
-hero,220,260
-hero,240,260
-hero,240,260
-hero,260,260
-hero,280,260
-hero,300,260
-hero,300,260
-hero,320,260
-hero,320,260
-hero,340,260
-hero,340,240
-hero,300,240
-hero,300,240
-hero,260,240
-hero,240,240
+hero,440,340