From 939bcaa258c4e1f69588db417ed5ec833aa22de0 Mon Sep 17 00:00:00 2001 From: "willem.thorbecke@students.olin.edu" Date: Sun, 6 Mar 2016 20:10:28 -0500 Subject: [PATCH 01/76] motherload with inifinite world generation to the left --- motherload.py | 207 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 207 insertions(+) create mode 100644 motherload.py diff --git a/motherload.py b/motherload.py new file mode 100644 index 0000000..c75c7cf --- /dev/null +++ b/motherload.py @@ -0,0 +1,207 @@ +import pygame +from pygame.locals import QUIT, KEYDOWN, MOUSEMOTION +import time +from random import choice + +class PygameBrickBreakerView(object): + """ Visualizes a brick breaker game in a pygame window """ + def __init__(self, model, screen): + """ Initialize the view with the specified model + and screen. """ + self.model = model + self.screen = screen + + + def draw(self): + """ Draw the game state to the screen """ + self.screen.fill(pygame.Color('black')) + # draw the bricks to the screen + for top in range(len(self.model.temp_world)): + for left in range(len(self.model.temp_world[top])): + + #pulls the appropriate brick model from the list + brick = self.model.temp_world[top][left] + + r = pygame.Rect(brick.left, brick.top, brick.width, brick.height) + pygame.draw.rect(self.screen, pygame.Color(brick.color), r) + + + r = pygame.Rect(40*8,40,40,40) #the mining vehicle + + pygame.draw.rect(self.screen, pygame.Color('white'), r) + + pygame.display.update() + + + + +class Brick(object): + """ Represents a brick in our brick breaker game """ + def __init__(self, left, top, width, height, first): + if first: + self.left = left*width - width*9 #renders 9 extra columns of blocks off screen to the left + self.top = top*height + height*2 #starts the world with a 2 block high sky + self.width = width + self.height = height + self.color = choice(["red", "green", "orange", "blue", "purple"]) + else: + self.left = left + self.top = top*height + height*2 #starts the world with a 2 block high sky + self.width = width + self.height = height + self.color = choice(["red", "green", "orange", "blue", "purple"]) + + +class Vehicle(object): + """ Represents the paddle in our brick breaker game """ + def __init__(self, left, top, width, height): + """ Initialize the paddle with the specified geometry """ + self.left = left*width + self.top = top*height + height*4 + self.width = width + self.height = height + +class BrickBreakerModel(object): + """ Stores the game state for our brick breaker game """ + def __init__(self): + #self.bricks = [][] + self.world = [] + self.MARGIN = 0 + self.BRICK_WIDTH = 40 + self.BRICK_HEIGHT = 40 + self.SCREEN_WIDTH = 640 + self.SCREEN_HEIGHT = 480 + self.FAR_LEFT = -200 + self.FAR_RIGHT = 800 + + + self.init_height_dist = 34 + self.init_width_dist = 34 + + #initialize world + for top in range(0,self.init_height_dist): + self.world.append([]) + for left in range(0,self.init_width_dist): + brick = Brick(left, top, self.BRICK_WIDTH, self.BRICK_HEIGHT, True) + self.world[top].append(brick) + self.temp_world = self.world + + + #self.vehicle = Vehicle(0,0, 40, 40) + + def world_enlarger(self, what_side): + + + if what_side == "left": + + for top in range (len(self.world)): + for left in range(0,5): + brick = Brick(self.FAR_LEFT - self.BRICK_WIDTH*(left+1), top, self.BRICK_WIDTH, self.BRICK_HEIGHT, False) + self.world[top].insert(0,brick) + + self.temp_world = self.world[:][0:34] + self.FAR_LEFT = self.world[0][4].left #makes the threshold for creating more leftward blocks at 5 blocks from the leftmost column of blocks + + + elif what_side == "right": + print "ohhh noooo tooo right!!!" + for top in range (len(self.world)): + for right in range(0,5): + brick = Brick(self.FAR_RIGHT + self.BRICK_WIDTH*(right+1), top, self.BRICK_WIDTH, self.BRICK_HEIGHT, False) + self.world[top].append(brick) + + start_right = len(self.world[0]) - 34 + + self.temp_world = self.world[:][start_right:-1] + self.FAR_RIGHT = self.world[0][-5].left #makes the threshold for creating more rightward blocks at 5 blocks from the rightmost column of blocks + print "new self.right ", self.FAR_RIGHT + + + + + +class PyGameKeyboardController(object): + def __init__(self, model): + self.model = model + + def handle_event(self, event): + """ Look for left and right keypresses to + modify the x position of the paddle """ + if event.type != KEYDOWN: + return + + if event.key == pygame.K_UP: + for top in range(len(self.model.temp_world)): + for left in range(len(self.model.temp_world[top])): + brick = self.model.temp_world[top][left] + brick.top += brick.height + # if self.model.bricks[0][0].top + + + + if event.key == pygame.K_DOWN: + for top in range(len(self.model.temp_world)): + for left in range(len(self.model.temp_world[top])): + brick = self.model.temp_world[top][left] + brick.top -= brick.height + # print self.model.bricks[0][0].top + + + + if event.key == pygame.K_LEFT: + + for top in range(len(self.model.temp_world)): + for left in range(len(self.model.temp_world[top])): + brick = self.model.temp_world[top][left] + brick.left += brick.width + + #if farthest block to left reachest threshold, add more blocks to left + if self.model.temp_world[0][0].left == self.model.FAR_LEFT: + self.model.world_enlarger("left") + + print "left, ", self.model.temp_world[0][0].left + print "right, ", self.model.temp_world[0][-1].left + + + + if event.key == pygame.K_RIGHT: + for top in range(len(self.model.temp_world)): + for left in range(len(self.model.temp_world[top])): + brick = self.model.temp_world[top][left] + brick.left -= brick.width + if self.model.world[0][-1].left == self.model.FAR_RIGHT: + self.model.world_enlarger("right") + + print "left, ", self.model.temp_world[0][0].left + print "right, ", self.model.temp_world[0][-1].left + + + +class PyGameMouseController(object): + def __init__(self, model): + self.model = model + + def handle_event(self, event): + """ Look for mouse movements and respond appropriately """ + if event.type != MOUSEMOTION: + return + self.model.paddle.left = event.pos[0] + +if __name__ == '__main__': + pygame.init() + size = (640, 480) + screen = pygame.display.set_mode(size) + + model = BrickBreakerModel() + view = PygameBrickBreakerView(model, screen) + controller = PyGameKeyboardController(model) + #controller = PyGameMouseController(model) + + running = True + while running: + for event in pygame.event.get(): + if event.type == QUIT: + running = False + controller.handle_event(event) + view.draw() + time.sleep(.001) From fb0a3cf6e671229a99de7bb9d2e8cde28723bb51 Mon Sep 17 00:00:00 2001 From: "willem.thorbecke@students.olin.edu" Date: Sun, 6 Mar 2016 21:28:23 -0500 Subject: [PATCH 02/76] finite map to left and right --- motherload.py | 75 ++++++++++++++++++++++++++++++++------------------- 1 file changed, 47 insertions(+), 28 deletions(-) diff --git a/motherload.py b/motherload.py index c75c7cf..87f803e 100644 --- a/motherload.py +++ b/motherload.py @@ -71,8 +71,9 @@ def __init__(self): self.BRICK_HEIGHT = 40 self.SCREEN_WIDTH = 640 self.SCREEN_HEIGHT = 480 - self.FAR_LEFT = -200 - self.FAR_RIGHT = 800 + self.FAR_LEFT = 320 + self.FAR_RIGHT = 320 + self.FAR_BOTTOM = -680 self.init_height_dist = 34 @@ -93,23 +94,37 @@ def world_enlarger(self, what_side): if what_side == "left": + pass - for top in range (len(self.world)): - for left in range(0,5): - brick = Brick(self.FAR_LEFT - self.BRICK_WIDTH*(left+1), top, self.BRICK_WIDTH, self.BRICK_HEIGHT, False) - self.world[top].insert(0,brick) + # for top in range (len(self.world)): + # for left in range(0,5): + # brick = Brick(self.FAR_LEFT - self.BRICK_WIDTH*(left+1), top, self.BRICK_WIDTH, self.BRICK_HEIGHT, False) + # self.world[top].insert(0,brick) - self.temp_world = self.world[:][0:34] - self.FAR_LEFT = self.world[0][4].left #makes the threshold for creating more leftward blocks at 5 blocks from the leftmost column of blocks + # self.temp_world = self.world[:][0:34] + # self.FAR_LEFT = self.world[0][4].left #makes the threshold for creating more leftward blocks at 5 blocks from the leftmost column of blocks elif what_side == "right": - print "ohhh noooo tooo right!!!" - for top in range (len(self.world)): - for right in range(0,5): + pass + + # for top in range (len(self.world)): + # for right in range(0,5): + # brick = Brick(self.FAR_RIGHT + self.BRICK_WIDTH*(right+1), top, self.BRICK_WIDTH, self.BRICK_HEIGHT, False) + # self.world[top].append(brick) + + # start_right = len(self.world[0]) - 34 + + # self.temp_world = self.world[:][start_right:-1] + # self.FAR_RIGHT = self.world[0][-5].left #makes the threshold for creating more rightward blocks at 5 blocks from the rightmost column of blocks + # print "new self.right ", self.FAR_RIGHT + + + elif what_side == "down": + for top in range (len(self.world)): + for right in range(0,5): brick = Brick(self.FAR_RIGHT + self.BRICK_WIDTH*(right+1), top, self.BRICK_WIDTH, self.BRICK_HEIGHT, False) self.world[top].append(brick) - start_right = len(self.world[0]) - 34 self.temp_world = self.world[:][start_right:-1] @@ -117,9 +132,6 @@ def world_enlarger(self, what_side): print "new self.right ", self.FAR_RIGHT - - - class PyGameKeyboardController(object): def __init__(self, model): self.model = model @@ -144,36 +156,43 @@ def handle_event(self, event): for left in range(len(self.model.temp_world[top])): brick = self.model.temp_world[top][left] brick.top -= brick.height - # print self.model.bricks[0][0].top + print self.model.temp_world[0][0].top if event.key == pygame.K_LEFT: + if self.model.temp_world[0][0].left != self.model.FAR_LEFT: + - for top in range(len(self.model.temp_world)): - for left in range(len(self.model.temp_world[top])): - brick = self.model.temp_world[top][left] - brick.left += brick.width + for top in range(len(self.model.temp_world)): + for left in range(len(self.model.temp_world[top])): + brick = self.model.temp_world[top][left] + brick.left += brick.width + else: + return #if farthest block to left reachest threshold, add more blocks to left if self.model.temp_world[0][0].left == self.model.FAR_LEFT: self.model.world_enlarger("left") - print "left, ", self.model.temp_world[0][0].left - print "right, ", self.model.temp_world[0][-1].left + # print "left, ", self.model.temp_world[0][0].left + # print "right, ", self.model.temp_world[0][-1].left if event.key == pygame.K_RIGHT: - for top in range(len(self.model.temp_world)): - for left in range(len(self.model.temp_world[top])): - brick = self.model.temp_world[top][left] - brick.left -= brick.width + if self.model.world[0][-1].left != self.model.FAR_RIGHT: + for top in range(len(self.model.temp_world)): + for left in range(len(self.model.temp_world[top])): + brick = self.model.temp_world[top][left] + brick.left -= brick.width + else: + return if self.model.world[0][-1].left == self.model.FAR_RIGHT: self.model.world_enlarger("right") - print "left, ", self.model.temp_world[0][0].left - print "right, ", self.model.temp_world[0][-1].left + # print "left, ", self.model.temp_world[0][0].left + # print "right, ", self.model.temp_world[0][-1].left From 8e80b001b9c1e337825f2a8c9f45aa95a8f70aa9 Mon Sep 17 00:00:00 2001 From: "willem.thorbecke@students.olin.edu" Date: Sun, 6 Mar 2016 22:06:12 -0500 Subject: [PATCH 03/76] collision detection works --- motherload.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/motherload.py b/motherload.py index 87f803e..4ee7f96 100644 --- a/motherload.py +++ b/motherload.py @@ -23,10 +23,15 @@ def draw(self): brick = self.model.temp_world[top][left] r = pygame.Rect(brick.left, brick.top, brick.width, brick.height) - pygame.draw.rect(self.screen, pygame.Color(brick.color), r) + if brick.left == self.model.vehicle.left and brick.top == self.model.vehicle.top: #checks if the vehicle overlaps a block, if so change block to black + brick.color = "black" + pygame.draw.rect(self.screen, pygame.Color(brick.color), r) + else: + pygame.draw.rect(self.screen, pygame.Color(brick.color), r) + - r = pygame.Rect(40*8,40,40,40) #the mining vehicle + r = pygame.Rect(self.model.vehicle.left,self.model.vehicle.top,self.model.vehicle.width,self.model.vehicle.height) #the mining vehicle pygame.draw.rect(self.screen, pygame.Color('white'), r) @@ -56,8 +61,8 @@ class Vehicle(object): """ Represents the paddle in our brick breaker game """ def __init__(self, left, top, width, height): """ Initialize the paddle with the specified geometry """ - self.left = left*width - self.top = top*height + height*4 + self.left = left + self.top = top self.width = width self.height = height @@ -88,7 +93,7 @@ def __init__(self): self.temp_world = self.world - #self.vehicle = Vehicle(0,0, 40, 40) + self.vehicle = Vehicle(40*8,40, 40, 40) def world_enlarger(self, what_side): From 4ceceb8e4dbdd1e4755a7b454e13e0bd8f6f41f1 Mon Sep 17 00:00:00 2001 From: Sung Park Date: Sun, 6 Mar 2016 23:19:44 -0500 Subject: [PATCH 04/76] Add different frequency for blocks --- motherload.py | 194 ++++++++++++++++++++++++++------------------------ 1 file changed, 102 insertions(+), 92 deletions(-) diff --git a/motherload.py b/motherload.py index 4ee7f96..7ca12aa 100644 --- a/motherload.py +++ b/motherload.py @@ -2,6 +2,7 @@ from pygame.locals import QUIT, KEYDOWN, MOUSEMOTION import time from random import choice +import random class PygameBrickBreakerView(object): """ Visualizes a brick breaker game in a pygame window """ @@ -17,19 +18,22 @@ def draw(self): self.screen.fill(pygame.Color('black')) # draw the bricks to the screen for top in range(len(self.model.temp_world)): - for left in range(len(self.model.temp_world[top])): + for left in range(len(self.model.temp_world[top])): - #pulls the appropriate brick model from the list - brick = self.model.temp_world[top][left] + #pulls the appropriate brick model from the list + brick = self.model.temp_world[top][left] - r = pygame.Rect(brick.left, brick.top, brick.width, brick.height) + r = pygame.Rect(brick.left, brick.top, brick.width, brick.height) - if brick.left == self.model.vehicle.left and brick.top == self.model.vehicle.top: #checks if the vehicle overlaps a block, if so change block to black - brick.color = "black" - pygame.draw.rect(self.screen, pygame.Color(brick.color), r) - else: - pygame.draw.rect(self.screen, pygame.Color(brick.color), r) - + if brick.left == self.model.vehicle.left and brick.top == self.model.vehicle.top: #checks if the vehicle overlaps a block, if so change block to black + if brick.color != "black" and brick.color != "brown": + print "I am eating ...", brick.color + brick.color = "black" + pygame.draw.rect(self.screen, pygame.Color(brick.color), r) + + else: + pygame.draw.rect(self.screen, pygame.Color(brick.color), r) + r = pygame.Rect(self.model.vehicle.left,self.model.vehicle.top,self.model.vehicle.width,self.model.vehicle.height) #the mining vehicle @@ -43,18 +47,24 @@ def draw(self): class Brick(object): """ Represents a brick in our brick breaker game """ def __init__(self, left, top, width, height, first): - if first: - self.left = left*width - width*9 #renders 9 extra columns of blocks off screen to the left - self.top = top*height + height*2 #starts the world with a 2 block high sky - self.width = width - self.height = height - self.color = choice(["red", "green", "orange", "blue", "purple"]) - else: - self.left = left - self.top = top*height + height*2 #starts the world with a 2 block high sky - self.width = width - self.height = height - self.color = choice(["red", "green", "orange", "blue", "purple"]) + if first: + self.left = left*width - width*9 #renders 9 extra columns of blocks off screen to the left + self.top = top*height + height*2 #starts the world with a 2 block high sky + self.width = width + self.height = height + random_seed = random.random() + if random_seed < 0.1: + self.color = "black" + elif random_seed <0.9: + self.color = "brown" + else: + self.color = choice(["red", "green", "orange", "blue", "purple"]) + else: + self.left = left + self.top = top*height + height*2 #starts the world with a 2 block high sky + self.width = width + self.height = height + self.color = choice(["red", "green", "orange", "blue", "purple"]) class Vehicle(object): @@ -70,7 +80,7 @@ class BrickBreakerModel(object): """ Stores the game state for our brick breaker game """ def __init__(self): #self.bricks = [][] - self.world = [] + self.world = [] self.MARGIN = 0 self.BRICK_WIDTH = 40 self.BRICK_HEIGHT = 40 @@ -86,55 +96,55 @@ def __init__(self): #initialize world for top in range(0,self.init_height_dist): - self.world.append([]) - for left in range(0,self.init_width_dist): - brick = Brick(left, top, self.BRICK_WIDTH, self.BRICK_HEIGHT, True) - self.world[top].append(brick) - self.temp_world = self.world + self.world.append([]) + for left in range(0,self.init_width_dist): + brick = Brick(left, top, self.BRICK_WIDTH, self.BRICK_HEIGHT, True) + self.world[top].append(brick) + self.temp_world = self.world self.vehicle = Vehicle(40*8,40, 40, 40) def world_enlarger(self, what_side): - + - if what_side == "left": - pass - - # for top in range (len(self.world)): - # for left in range(0,5): - # brick = Brick(self.FAR_LEFT - self.BRICK_WIDTH*(left+1), top, self.BRICK_WIDTH, self.BRICK_HEIGHT, False) - # self.world[top].insert(0,brick) + if what_side == "left": + pass + + # for top in range (len(self.world)): + # for left in range(0,5): + # brick = Brick(self.FAR_LEFT - self.BRICK_WIDTH*(left+1), top, self.BRICK_WIDTH, self.BRICK_HEIGHT, False) + # self.world[top].insert(0,brick) - # self.temp_world = self.world[:][0:34] - # self.FAR_LEFT = self.world[0][4].left #makes the threshold for creating more leftward blocks at 5 blocks from the leftmost column of blocks + # self.temp_world = self.world[:][0:34] + # self.FAR_LEFT = self.world[0][4].left #makes the threshold for creating more leftward blocks at 5 blocks from the leftmost column of blocks - elif what_side == "right": - pass - - # for top in range (len(self.world)): - # for right in range(0,5): - # brick = Brick(self.FAR_RIGHT + self.BRICK_WIDTH*(right+1), top, self.BRICK_WIDTH, self.BRICK_HEIGHT, False) - # self.world[top].append(brick) + elif what_side == "right": + pass + + # for top in range (len(self.world)): + # for right in range(0,5): + # brick = Brick(self.FAR_RIGHT + self.BRICK_WIDTH*(right+1), top, self.BRICK_WIDTH, self.BRICK_HEIGHT, False) + # self.world[top].append(brick) - # start_right = len(self.world[0]) - 34 + # start_right = len(self.world[0]) - 34 - # self.temp_world = self.world[:][start_right:-1] - # self.FAR_RIGHT = self.world[0][-5].left #makes the threshold for creating more rightward blocks at 5 blocks from the rightmost column of blocks - # print "new self.right ", self.FAR_RIGHT + # self.temp_world = self.world[:][start_right:-1] + # self.FAR_RIGHT = self.world[0][-5].left #makes the threshold for creating more rightward blocks at 5 blocks from the rightmost column of blocks + # print "new self.right ", self.FAR_RIGHT elif what_side == "down": - for top in range (len(self.world)): - for right in range(0,5): - brick = Brick(self.FAR_RIGHT + self.BRICK_WIDTH*(right+1), top, self.BRICK_WIDTH, self.BRICK_HEIGHT, False) - self.world[top].append(brick) - start_right = len(self.world[0]) - 34 + for top in range (len(self.world)): + for right in range(0,5): + brick = Brick(self.FAR_RIGHT + self.BRICK_WIDTH*(right+1), top, self.BRICK_WIDTH, self.BRICK_HEIGHT, False) + self.world[top].append(brick) + start_right = len(self.world[0]) - 34 - self.temp_world = self.world[:][start_right:-1] - self.FAR_RIGHT = self.world[0][-5].left #makes the threshold for creating more rightward blocks at 5 blocks from the rightmost column of blocks - print "new self.right ", self.FAR_RIGHT + self.temp_world = self.world[:][start_right:-1] + self.FAR_RIGHT = self.world[0][-5].left #makes the threshold for creating more rightward blocks at 5 blocks from the rightmost column of blocks + print "new self.right ", self.FAR_RIGHT class PyGameKeyboardController(object): @@ -148,56 +158,56 @@ def handle_event(self, event): return if event.key == pygame.K_UP: - for top in range(len(self.model.temp_world)): - for left in range(len(self.model.temp_world[top])): - brick = self.model.temp_world[top][left] - brick.top += brick.height - # if self.model.bricks[0][0].top + for top in range(len(self.model.temp_world)): + for left in range(len(self.model.temp_world[top])): + brick = self.model.temp_world[top][left] + brick.top += brick.height + # if self.model.bricks[0][0].top if event.key == pygame.K_DOWN: - for top in range(len(self.model.temp_world)): - for left in range(len(self.model.temp_world[top])): - brick = self.model.temp_world[top][left] - brick.top -= brick.height + for top in range(len(self.model.temp_world)): + for left in range(len(self.model.temp_world[top])): + brick = self.model.temp_world[top][left] + brick.top -= brick.height print self.model.temp_world[0][0].top if event.key == pygame.K_LEFT: - if self.model.temp_world[0][0].left != self.model.FAR_LEFT: - + if self.model.temp_world[0][0].left != self.model.FAR_LEFT: + - for top in range(len(self.model.temp_world)): - for left in range(len(self.model.temp_world[top])): - brick = self.model.temp_world[top][left] - brick.left += brick.width - else: - return + for top in range(len(self.model.temp_world)): + for left in range(len(self.model.temp_world[top])): + brick = self.model.temp_world[top][left] + brick.left += brick.width + else: + return - #if farthest block to left reachest threshold, add more blocks to left - if self.model.temp_world[0][0].left == self.model.FAR_LEFT: - self.model.world_enlarger("left") + #if farthest block to left reachest threshold, add more blocks to left + if self.model.temp_world[0][0].left == self.model.FAR_LEFT: + self.model.world_enlarger("left") - # print "left, ", self.model.temp_world[0][0].left - # print "right, ", self.model.temp_world[0][-1].left + # print "left, ", self.model.temp_world[0][0].left + # print "right, ", self.model.temp_world[0][-1].left - + if event.key == pygame.K_RIGHT: - if self.model.world[0][-1].left != self.model.FAR_RIGHT: - for top in range(len(self.model.temp_world)): - for left in range(len(self.model.temp_world[top])): - brick = self.model.temp_world[top][left] - brick.left -= brick.width - else: - return - if self.model.world[0][-1].left == self.model.FAR_RIGHT: - self.model.world_enlarger("right") - - # print "left, ", self.model.temp_world[0][0].left - # print "right, ", self.model.temp_world[0][-1].left + if self.model.world[0][-1].left != self.model.FAR_RIGHT: + for top in range(len(self.model.temp_world)): + for left in range(len(self.model.temp_world[top])): + brick = self.model.temp_world[top][left] + brick.left -= brick.width + else: + return + if self.model.world[0][-1].left == self.model.FAR_RIGHT: + self.model.world_enlarger("right") + + # print "left, ", self.model.temp_world[0][0].left + # print "right, ", self.model.temp_world[0][-1].left From 0ba296d1b54c6d07e772fbe7afacf13391ee9ebe Mon Sep 17 00:00:00 2001 From: Sung Park Date: Mon, 7 Mar 2016 00:48:12 -0500 Subject: [PATCH 05/76] Add timer --- motherload.py | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/motherload.py b/motherload.py index 7ca12aa..70aa4ca 100644 --- a/motherload.py +++ b/motherload.py @@ -15,6 +15,9 @@ def __init__(self, model, screen): def draw(self): """ Draw the game state to the screen """ + myFont = pygame.font.SysFont("monospace",15) + game_over_font = pygame.font.SysFont("monospace",100) + self.screen.fill(pygame.Color('black')) # draw the bricks to the screen for top in range(len(self.model.temp_world)): @@ -38,7 +41,13 @@ def draw(self): r = pygame.Rect(self.model.vehicle.left,self.model.vehicle.top,self.model.vehicle.width,self.model.vehicle.height) #the mining vehicle pygame.draw.rect(self.screen, pygame.Color('white'), r) - + + if 5*1000-self.model.get_elapsed_time() <= 0: + msg = game_over_font.render("GAME OVER",1,(255,255,0)) + screen.blit(msg, (0, 240)) + else: + timer = myFont.render(str(5-(self.model.get_elapsed_time()/1000)), 1, (255,255,0)) + screen.blit(timer, (20,20)) pygame.display.update() @@ -110,7 +119,8 @@ def world_enlarger(self, what_side): if what_side == "left": pass - + + # for top in range (len(self.world)): # for left in range(0,5): # brick = Brick(self.FAR_LEFT - self.BRICK_WIDTH*(left+1), top, self.BRICK_WIDTH, self.BRICK_HEIGHT, False) @@ -147,6 +157,9 @@ def world_enlarger(self, what_side): print "new self.right ", self.FAR_RIGHT + def get_elapsed_time(self): + return pygame.time.get_ticks() + class PyGameKeyboardController(object): def __init__(self, model): self.model = model From 4bd1d1cba7627db9d19bfc82d0c9b32b6b3289ef Mon Sep 17 00:00:00 2001 From: Sung Park Date: Mon, 7 Mar 2016 01:19:31 -0500 Subject: [PATCH 06/76] Add fuel station --- motherload.py | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/motherload.py b/motherload.py index 70aa4ca..e7fda11 100644 --- a/motherload.py +++ b/motherload.py @@ -41,7 +41,10 @@ def draw(self): r = pygame.Rect(self.model.vehicle.left,self.model.vehicle.top,self.model.vehicle.width,self.model.vehicle.height) #the mining vehicle pygame.draw.rect(self.screen, pygame.Color('white'), r) - + + r = pygame.Rect(self.model.fuel_station.left,self.model.fuel_station.top,self.model.fuel_station.width,self.model.fuel_station.height) + pygame.draw.rect(self.screen, pygame.Color('deep pink'),r) + if 5*1000-self.model.get_elapsed_time() <= 0: msg = game_over_font.render("GAME OVER",1,(255,255,0)) screen.blit(msg, (0, 240)) @@ -75,6 +78,13 @@ def __init__(self, left, top, width, height, first): self.height = height self.color = choice(["red", "green", "orange", "blue", "purple"]) +class FuelStation(object): + """ Represents a fuel station as a pink block at fixed point""" + def __init__(self): + self.left = 400 + self.top = 40 + self.width = 40 + self.height = 40 class Vehicle(object): """ Represents the paddle in our brick breaker game """ @@ -113,6 +123,7 @@ def __init__(self): self.vehicle = Vehicle(40*8,40, 40, 40) + self.fuel_station = FuelStation() def world_enlarger(self, what_side): @@ -176,7 +187,7 @@ def handle_event(self, event): brick = self.model.temp_world[top][left] brick.top += brick.height # if self.model.bricks[0][0].top - + self.model.fuel_station.top += self.model.BRICK_HEIGHT if event.key == pygame.K_DOWN: @@ -184,7 +195,8 @@ def handle_event(self, event): for left in range(len(self.model.temp_world[top])): brick = self.model.temp_world[top][left] brick.top -= brick.height - print self.model.temp_world[0][0].top + self.model.fuel_station.top -= self.model.BRICK_HEIGHT + #print self.model.temp_world[0][0].top @@ -196,6 +208,7 @@ def handle_event(self, event): for left in range(len(self.model.temp_world[top])): brick = self.model.temp_world[top][left] brick.left += brick.width + self.model.fuel_station.left += self.model.BRICK_HEIGHT else: return @@ -214,6 +227,7 @@ def handle_event(self, event): for left in range(len(self.model.temp_world[top])): brick = self.model.temp_world[top][left] brick.left -= brick.width + self.model.fuel_station.left -= self.model.BRICK_HEIGHT else: return if self.model.world[0][-1].left == self.model.FAR_RIGHT: From 3f24603c33ef31907dc140df62e5b3d6dfec981c Mon Sep 17 00:00:00 2001 From: Sung Park Date: Mon, 7 Mar 2016 17:21:21 -0500 Subject: [PATCH 07/76] Separate the game model to model.py --- model.py | 127 +++++++++++++++++++++++++++++++++++++++++++++++++ motherload.py | 129 ++++---------------------------------------------- 2 files changed, 136 insertions(+), 120 deletions(-) create mode 100644 model.py diff --git a/model.py b/model.py new file mode 100644 index 0000000..fe1a0f3 --- /dev/null +++ b/model.py @@ -0,0 +1,127 @@ +import random +from random import choice +import pygame +from pygame.locals import QUIT, KEYDOWN, MOUSEMOTION +import time +""" + Class containing game model and all its components +""" + +class Brick(object): + """ Represents a brick in our brick breaker game """ + def __init__(self, left, top, width, height, first): + if first: + self.left = left*width - width*9 #renders 9 extra columns of blocks off screen to the left + self.top = top*height + height*2 #starts the world with a 2 block high sky + self.width = width + self.height = height + random_seed = random.random() + if random_seed < 0.1: + self.color = "black" + elif random_seed <0.9: + self.color = "brown" + else: + self.color = choice(["red", "green", "orange", "blue", "purple"]) + else: + self.left = left + self.top = top*height + height*2 #starts the world with a 2 block high sky + self.width = width + self.height = height + self.color = choice(["red", "green", "orange", "blue", "purple"]) + +class FuelStation(object): + """ Represents a fuel station as a pink block at fixed point""" + def __init__(self): + self.left = 400 + self.top = 40 + self.width = 40 + self.height = 40 + +class Vehicle(object): + """ Represents the paddle in our brick breaker game """ + def __init__(self, left, top, width, height): + """ Initialize the paddle with the specified geometry """ + self.left = left + self.top = top + self.width = width + self.height = height + +class BrickBreakerModel(object): + """ Stores the game state for our brick breaker game """ + def __init__(self): + #self.bricks = [][] + self.world = [] + self.MARGIN = 0 + self.BRICK_WIDTH = 40 + self.BRICK_HEIGHT = 40 + self.SCREEN_WIDTH = 640 + self.SCREEN_HEIGHT = 480 + self.FAR_LEFT = 320 + self.FAR_RIGHT = 320 + self.FAR_BOTTOM = -680 + + + self.init_height_dist = 34 + self.init_width_dist = 34 + + #initialize world + for top in range(0,self.init_height_dist): + self.world.append([]) + for left in range(0,self.init_width_dist): + brick = Brick(left, top, self.BRICK_WIDTH, self.BRICK_HEIGHT, True) + self.world[top].append(brick) + self.temp_world = self.world + + self.fuel = 5 + self.max_fuel = 10 + + self.vehicle = Vehicle(40*8,40, 40, 40) + self.fuel_station = FuelStation() + + def world_enlarger(self, what_side): + + + if what_side == "left": + pass + + + # for top in range (len(self.world)): + # for left in range(0,5): + # brick = Brick(self.FAR_LEFT - self.BRICK_WIDTH*(left+1), top, self.BRICK_WIDTH, self.BRICK_HEIGHT, False) + # self.world[top].insert(0,brick) + + # self.temp_world = self.world[:][0:34] + # self.FAR_LEFT = self.world[0][4].left #makes the threshold for creating more leftward blocks at 5 blocks from the leftmost column of blocks + + + elif what_side == "right": + pass + + # for top in range (len(self.world)): + # for right in range(0,5): + # brick = Brick(self.FAR_RIGHT + self.BRICK_WIDTH*(right+1), top, self.BRICK_WIDTH, self.BRICK_HEIGHT, False) + # self.world[top].append(brick) + + # start_right = len(self.world[0]) - 34 + + # self.temp_world = self.world[:][start_right:-1] + # self.FAR_RIGHT = self.world[0][-5].left #makes the threshold for creating more rightward blocks at 5 blocks from the rightmost column of blocks + # print "new self.right ", self.FAR_RIGHT + + + elif what_side == "down": + for top in range (len(self.world)): + for right in range(0,5): + brick = Brick(self.FAR_RIGHT + self.BRICK_WIDTH*(right+1), top, self.BRICK_WIDTH, self.BRICK_HEIGHT, False) + self.world[top].append(brick) + start_right = len(self.world[0]) - 34 + + self.temp_world = self.world[:][start_right:-1] + self.FAR_RIGHT = self.world[0][-5].left #makes the threshold for creating more rightward blocks at 5 blocks from the rightmost column of blocks + print "new self.right ", self.FAR_RIGHT + + def get_fuel(self): + return self.fuel*1000 - pygame.time.get_ticks() + + def get_elapsed_time(self): + return pygame.time.get_ticks() diff --git a/motherload.py b/motherload.py index e7fda11..50934f6 100644 --- a/motherload.py +++ b/motherload.py @@ -3,6 +3,7 @@ import time from random import choice import random +import model class PygameBrickBreakerView(object): """ Visualizes a brick breaker game in a pygame window """ @@ -44,133 +45,21 @@ def draw(self): r = pygame.Rect(self.model.fuel_station.left,self.model.fuel_station.top,self.model.fuel_station.width,self.model.fuel_station.height) pygame.draw.rect(self.screen, pygame.Color('deep pink'),r) + + if self.model.fuel_station.left == self.model.vehicle.left and self.model.fuel_station.top == self.model.vehicle.top and self.model.get_fuel < self.model.max_fuel: + self.model.fuel += 5 - if 5*1000-self.model.get_elapsed_time() <= 0: + if self.model.get_fuel() <= 0: msg = game_over_font.render("GAME OVER",1,(255,255,0)) screen.blit(msg, (0, 240)) else: - timer = myFont.render(str(5-(self.model.get_elapsed_time()/1000)), 1, (255,255,0)) + timer = myFont.render(str(self.model.get_fuel()), 1, (255,255,0)) screen.blit(timer, (20,20)) pygame.display.update() -class Brick(object): - """ Represents a brick in our brick breaker game """ - def __init__(self, left, top, width, height, first): - if first: - self.left = left*width - width*9 #renders 9 extra columns of blocks off screen to the left - self.top = top*height + height*2 #starts the world with a 2 block high sky - self.width = width - self.height = height - random_seed = random.random() - if random_seed < 0.1: - self.color = "black" - elif random_seed <0.9: - self.color = "brown" - else: - self.color = choice(["red", "green", "orange", "blue", "purple"]) - else: - self.left = left - self.top = top*height + height*2 #starts the world with a 2 block high sky - self.width = width - self.height = height - self.color = choice(["red", "green", "orange", "blue", "purple"]) - -class FuelStation(object): - """ Represents a fuel station as a pink block at fixed point""" - def __init__(self): - self.left = 400 - self.top = 40 - self.width = 40 - self.height = 40 - -class Vehicle(object): - """ Represents the paddle in our brick breaker game """ - def __init__(self, left, top, width, height): - """ Initialize the paddle with the specified geometry """ - self.left = left - self.top = top - self.width = width - self.height = height - -class BrickBreakerModel(object): - """ Stores the game state for our brick breaker game """ - def __init__(self): - #self.bricks = [][] - self.world = [] - self.MARGIN = 0 - self.BRICK_WIDTH = 40 - self.BRICK_HEIGHT = 40 - self.SCREEN_WIDTH = 640 - self.SCREEN_HEIGHT = 480 - self.FAR_LEFT = 320 - self.FAR_RIGHT = 320 - self.FAR_BOTTOM = -680 - - - self.init_height_dist = 34 - self.init_width_dist = 34 - - #initialize world - for top in range(0,self.init_height_dist): - self.world.append([]) - for left in range(0,self.init_width_dist): - brick = Brick(left, top, self.BRICK_WIDTH, self.BRICK_HEIGHT, True) - self.world[top].append(brick) - self.temp_world = self.world - - - self.vehicle = Vehicle(40*8,40, 40, 40) - self.fuel_station = FuelStation() - - def world_enlarger(self, what_side): - - - if what_side == "left": - pass - - - # for top in range (len(self.world)): - # for left in range(0,5): - # brick = Brick(self.FAR_LEFT - self.BRICK_WIDTH*(left+1), top, self.BRICK_WIDTH, self.BRICK_HEIGHT, False) - # self.world[top].insert(0,brick) - - # self.temp_world = self.world[:][0:34] - # self.FAR_LEFT = self.world[0][4].left #makes the threshold for creating more leftward blocks at 5 blocks from the leftmost column of blocks - - - elif what_side == "right": - pass - - # for top in range (len(self.world)): - # for right in range(0,5): - # brick = Brick(self.FAR_RIGHT + self.BRICK_WIDTH*(right+1), top, self.BRICK_WIDTH, self.BRICK_HEIGHT, False) - # self.world[top].append(brick) - - # start_right = len(self.world[0]) - 34 - - # self.temp_world = self.world[:][start_right:-1] - # self.FAR_RIGHT = self.world[0][-5].left #makes the threshold for creating more rightward blocks at 5 blocks from the rightmost column of blocks - # print "new self.right ", self.FAR_RIGHT - - - elif what_side == "down": - for top in range (len(self.world)): - for right in range(0,5): - brick = Brick(self.FAR_RIGHT + self.BRICK_WIDTH*(right+1), top, self.BRICK_WIDTH, self.BRICK_HEIGHT, False) - self.world[top].append(brick) - start_right = len(self.world[0]) - 34 - - self.temp_world = self.world[:][start_right:-1] - self.FAR_RIGHT = self.world[0][-5].left #makes the threshold for creating more rightward blocks at 5 blocks from the rightmost column of blocks - print "new self.right ", self.FAR_RIGHT - - - def get_elapsed_time(self): - return pygame.time.get_ticks() - class PyGameKeyboardController(object): def __init__(self, model): self.model = model @@ -253,9 +142,9 @@ def handle_event(self, event): size = (640, 480) screen = pygame.display.set_mode(size) - model = BrickBreakerModel() - view = PygameBrickBreakerView(model, screen) - controller = PyGameKeyboardController(model) + game_model = model.BrickBreakerModel() + view = PygameBrickBreakerView(game_model, screen) + controller = PyGameKeyboardController(game_model) #controller = PyGameMouseController(model) running = True From d9b132b0e6106046091665590ae0eae2b320b27d Mon Sep 17 00:00:00 2001 From: Sung Park Date: Mon, 7 Mar 2016 17:24:06 -0500 Subject: [PATCH 08/76] Change the name of model.py to game_model.py --- model.py => game_model.py | 0 motherload.py | 8 ++++---- 2 files changed, 4 insertions(+), 4 deletions(-) rename model.py => game_model.py (100%) diff --git a/model.py b/game_model.py similarity index 100% rename from model.py rename to game_model.py diff --git a/motherload.py b/motherload.py index 50934f6..a0dd48c 100644 --- a/motherload.py +++ b/motherload.py @@ -3,7 +3,7 @@ import time from random import choice import random -import model +import game_model class PygameBrickBreakerView(object): """ Visualizes a brick breaker game in a pygame window """ @@ -142,9 +142,9 @@ def handle_event(self, event): size = (640, 480) screen = pygame.display.set_mode(size) - game_model = model.BrickBreakerModel() - view = PygameBrickBreakerView(game_model, screen) - controller = PyGameKeyboardController(game_model) + model = game_model.BrickBreakerModel() + view = PygameBrickBreakerView(model, screen) + controller = PyGameKeyboardController(model) #controller = PyGameMouseController(model) running = True From 9c3674d6de5bafd244c2b25456c748ba058555e8 Mon Sep 17 00:00:00 2001 From: "willem.thorbecke@students.olin.edu" Date: Mon, 7 Mar 2016 20:10:55 -0500 Subject: [PATCH 09/76] "minor changes to key class" --- game_model.py | 12 ++---------- motherload.py | 18 +++++++++++++----- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/game_model.py b/game_model.py index fe1a0f3..2209d5e 100644 --- a/game_model.py +++ b/game_model.py @@ -61,7 +61,7 @@ def __init__(self): self.FAR_BOTTOM = -680 - self.init_height_dist = 34 + self.init_height_dist = 32 self.init_width_dist = 34 #initialize world @@ -110,15 +110,7 @@ def world_enlarger(self, what_side): elif what_side == "down": - for top in range (len(self.world)): - for right in range(0,5): - brick = Brick(self.FAR_RIGHT + self.BRICK_WIDTH*(right+1), top, self.BRICK_WIDTH, self.BRICK_HEIGHT, False) - self.world[top].append(brick) - start_right = len(self.world[0]) - 34 - - self.temp_world = self.world[:][start_right:-1] - self.FAR_RIGHT = self.world[0][-5].left #makes the threshold for creating more rightward blocks at 5 blocks from the rightmost column of blocks - print "new self.right ", self.FAR_RIGHT + pass def get_fuel(self): return self.fuel*1000 - pygame.time.get_ticks() diff --git a/motherload.py b/motherload.py index a0dd48c..897e897 100644 --- a/motherload.py +++ b/motherload.py @@ -80,11 +80,19 @@ def handle_event(self, event): if event.key == pygame.K_DOWN: - for top in range(len(self.model.temp_world)): - for left in range(len(self.model.temp_world[top])): - brick = self.model.temp_world[top][left] - brick.top -= brick.height - self.model.fuel_station.top -= self.model.BRICK_HEIGHT + if self.model.temp_world[-1][0].top != self.model.FAR_BOTTOM: + for top in range(len(self.model.temp_world)): + for left in range(len(self.model.temp_world[top])): + brick = self.model.temp_world[top][left] + brick.top -= brick.height + self.model.fuel_station.top -= self.model.BRICK_HEIGHT + else: + self.model.fuel_station.top -= self.model.BRICK_HEIGHT + self.model.world_enlarger("down") + for top in range(len(self.model.temp_world)): + for left in range(len(self.model.temp_world[top])): + brick = self.model.temp_world[top][left] + brick.top -= brick.height #print self.model.temp_world[0][0].top From 7d710afc255d007346e46c6d1ab6174be6fa206f Mon Sep 17 00:00:00 2001 From: "willem.thorbecke@students.olin.edu" Date: Mon, 7 Mar 2016 20:32:22 -0500 Subject: [PATCH 10/76] "infinite downward works, but memory alocation may suck" --- game_model.py | 23 +++++++++++++++++------ motherload.py | 1 + 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/game_model.py b/game_model.py index 2209d5e..5b907a2 100644 --- a/game_model.py +++ b/game_model.py @@ -23,11 +23,17 @@ def __init__(self, left, top, width, height, first): else: self.color = choice(["red", "green", "orange", "blue", "purple"]) else: - self.left = left - self.top = top*height + height*2 #starts the world with a 2 block high sky + self.left = left*width - width*9 + self.top = top #starts the world with a 2 block high sky self.width = width self.height = height - self.color = choice(["red", "green", "orange", "blue", "purple"]) + random_seed = random.random() + if random_seed < 0.1: + self.color = "black" + elif random_seed <0.9: + self.color = "brown" + else: + self.color = choice(["red", "green", "orange", "blue", "purple"]) class FuelStation(object): """ Represents a fuel station as a pink block at fixed point""" @@ -58,11 +64,11 @@ def __init__(self): self.SCREEN_HEIGHT = 480 self.FAR_LEFT = 320 self.FAR_RIGHT = 320 - self.FAR_BOTTOM = -680 + self.FAR_BOTTOM = self.SCREEN_HEIGHT + self.BRICK_HEIGHT*4 #the threshold for adding more blocks is 5 blocks from the bottom of the screen - self.init_height_dist = 32 - self.init_width_dist = 34 + self.init_height_dist = 34 #number of rows of blocks + self.init_width_dist = 32 #number of columns of blocks #initialize world for top in range(0,self.init_height_dist): @@ -111,6 +117,11 @@ def world_enlarger(self, what_side): elif what_side == "down": pass + for top in range(0,5): # cycles through 5 blocks + self.world.append([])#creates a row (list) to be filled with bricks + for left in range(0,self.init_width_dist): + brick = Brick(left, self.SCREEN_HEIGHT+self.BRICK_HEIGHT*5 + top*self.BRICK_HEIGHT, self.BRICK_WIDTH, self.BRICK_HEIGHT, False) + self.world[-1].append(brick) def get_fuel(self): return self.fuel*1000 - pygame.time.get_ticks() diff --git a/motherload.py b/motherload.py index 897e897..ff692d6 100644 --- a/motherload.py +++ b/motherload.py @@ -80,6 +80,7 @@ def handle_event(self, event): if event.key == pygame.K_DOWN: + print self.model.temp_world[-1][0].top if self.model.temp_world[-1][0].top != self.model.FAR_BOTTOM: for top in range(len(self.model.temp_world)): for left in range(len(self.model.temp_world[top])): From b947bf28251eeac3bba5cf443789612fb75d3cbf Mon Sep 17 00:00:00 2001 From: "willem.thorbecke@students.olin.edu" Date: Mon, 7 Mar 2016 23:32:11 -0500 Subject: [PATCH 11/76] "bunch of stuff works, but terribly disorganized" --- game_model.py | 47 +++++++----------- motherload.py | 134 +++++++++++++++++++++++++++++++++++--------------- 2 files changed, 111 insertions(+), 70 deletions(-) diff --git a/game_model.py b/game_model.py index 5b907a2..2e00a09 100644 --- a/game_model.py +++ b/game_model.py @@ -12,7 +12,7 @@ class Brick(object): def __init__(self, left, top, width, height, first): if first: self.left = left*width - width*9 #renders 9 extra columns of blocks off screen to the left - self.top = top*height + height*2 #starts the world with a 2 block high sky + self.top = top*height + height*2 #starts the world with a 2 block high sky self.width = width self.height = height random_seed = random.random() @@ -45,17 +45,25 @@ def __init__(self): class Vehicle(object): """ Represents the paddle in our brick breaker game """ - def __init__(self, left, top, width, height): + def __init__(self, left, top, width, height, cheatcode): """ Initialize the paddle with the specified geometry """ self.left = left self.top = top self.width = width self.height = height + self.thruster = False + self.cheatcode = cheatcode + self.speed = 0 + self.gravity = .1 + self.thruster_veloc = -.1 + class BrickBreakerModel(object): """ Stores the game state for our brick breaker game """ def __init__(self): #self.bricks = [][] + self.enlarger_helper = None + self.can_move_down = False #checks if the blocks free to fall downward self.world = [] self.MARGIN = 0 self.BRICK_WIDTH = 40 @@ -80,47 +88,26 @@ def __init__(self): self.fuel = 5 self.max_fuel = 10 - - self.vehicle = Vehicle(40*8,40, 40, 40) + cheatcode = "dpapp" + self.vehicle = Vehicle(40*8,40, 40, 40, cheatcode) self.fuel_station = FuelStation() def world_enlarger(self, what_side): - if what_side == "left": pass - - - # for top in range (len(self.world)): - # for left in range(0,5): - # brick = Brick(self.FAR_LEFT - self.BRICK_WIDTH*(left+1), top, self.BRICK_WIDTH, self.BRICK_HEIGHT, False) - # self.world[top].insert(0,brick) - - # self.temp_world = self.world[:][0:34] - # self.FAR_LEFT = self.world[0][4].left #makes the threshold for creating more leftward blocks at 5 blocks from the leftmost column of blocks - elif what_side == "right": pass - - # for top in range (len(self.world)): - # for right in range(0,5): - # brick = Brick(self.FAR_RIGHT + self.BRICK_WIDTH*(right+1), top, self.BRICK_WIDTH, self.BRICK_HEIGHT, False) - # self.world[top].append(brick) - - # start_right = len(self.world[0]) - 34 - - # self.temp_world = self.world[:][start_right:-1] - # self.FAR_RIGHT = self.world[0][-5].left #makes the threshold for creating more rightward blocks at 5 blocks from the rightmost column of blocks - # print "new self.right ", self.FAR_RIGHT - elif what_side == "down": - pass + for top in range(0,5): # cycles through 5 blocks - self.world.append([])#creates a row (list) to be filled with bricks + self.world.append([]) #creates a row (list) to be filled with bricks for left in range(0,self.init_width_dist): - brick = Brick(left, self.SCREEN_HEIGHT+self.BRICK_HEIGHT*5 + top*self.BRICK_HEIGHT, self.BRICK_WIDTH, self.BRICK_HEIGHT, False) + + + brick = Brick(left, self.world[-2][0].top + self.BRICK_HEIGHT, self.BRICK_WIDTH, self.BRICK_HEIGHT, False) self.world[-1].append(brick) def get_fuel(self): diff --git a/motherload.py b/motherload.py index ff692d6..8a4bc53 100644 --- a/motherload.py +++ b/motherload.py @@ -28,10 +28,18 @@ def draw(self): brick = self.model.temp_world[top][left] r = pygame.Rect(brick.left, brick.top, brick.width, brick.height) - - if brick.left == self.model.vehicle.left and brick.top == self.model.vehicle.top: #checks if the vehicle overlaps a block, if so change block to black + + + if brick.left == self.model.vehicle.left and brick.top <= self.model.vehicle.top + brick.height and brick.top + brick.height > self.model.vehicle.top + brick.height: #checks if the vehicle overlaps a block, if so change block to black + if brick.color != "black": + model.can_move_down = False + else: + model.can_move_down = True + + if brick.left == self.model.vehicle.left and self.model.vehicle.top > brick.top and self.model.vehicle.top + brick.height < brick.top + brick.height*2: #checks if the vehicle overlaps a block, if so change block to black if brick.color != "black" and brick.color != "brown": print "I am eating ...", brick.color + brick.color = "black" pygame.draw.rect(self.screen, pygame.Color(brick.color), r) @@ -49,12 +57,12 @@ def draw(self): if self.model.fuel_station.left == self.model.vehicle.left and self.model.fuel_station.top == self.model.vehicle.top and self.model.get_fuel < self.model.max_fuel: self.model.fuel += 5 - if self.model.get_fuel() <= 0: - msg = game_over_font.render("GAME OVER",1,(255,255,0)) - screen.blit(msg, (0, 240)) - else: - timer = myFont.render(str(self.model.get_fuel()), 1, (255,255,0)) - screen.blit(timer, (20,20)) + # if self.model.get_fuel() <= 0: + # # msg = game_over_font.render("GAME OVER",1,(255,255,0)) + # #screen.blit(msg, (0, 240)) + # else: + # timer = myFont.render(str(self.model.get_fuel()), 1, (255,255,0)) + # screen.blit(timer, (20,20)) pygame.display.update() @@ -70,34 +78,37 @@ def handle_event(self, event): if event.type != KEYDOWN: return - if event.key == pygame.K_UP: - for top in range(len(self.model.temp_world)): - for left in range(len(self.model.temp_world[top])): - brick = self.model.temp_world[top][left] - brick.top += brick.height - # if self.model.bricks[0][0].top - self.model.fuel_station.top += self.model.BRICK_HEIGHT + # if event.key == pygame.K_UP: + # for top in range(len(self.model.temp_world)): + # for left in range(len(self.model.temp_world[top])): + # brick = self.model.temp_world[top][left] + # brick.top += brick.height*2 + # # if self.model.bricks[0][0].top + # self.model.fuel_station.top += self.model.BRICK_HEIGHT - if event.key == pygame.K_DOWN: - print self.model.temp_world[-1][0].top - if self.model.temp_world[-1][0].top != self.model.FAR_BOTTOM: - for top in range(len(self.model.temp_world)): - for left in range(len(self.model.temp_world[top])): - brick = self.model.temp_world[top][left] - brick.top -= brick.height - self.model.fuel_station.top -= self.model.BRICK_HEIGHT - else: - self.model.fuel_station.top -= self.model.BRICK_HEIGHT - self.model.world_enlarger("down") - for top in range(len(self.model.temp_world)): - for left in range(len(self.model.temp_world[top])): - brick = self.model.temp_world[top][left] - brick.top -= brick.height - #print self.model.temp_world[0][0].top + # if event.key == pygame.K_DOWN: + # print self.model.temp_world[-1][0].top + # if self.model.temp_world[-1][0].top != self.model.FAR_BOTTOM: + # for top in range(len(self.model.temp_world)): + # for left in range(len(self.model.temp_world[top])): + # brick = self.model.temp_world[top][left] + # brick.top -= brick.height + # self.model.fuel_station.top -= self.model.BRICK_HEIGHT + # else: + # self.model.fuel_station.top -= self.model.BRICK_HEIGHT + # self.model.world_enlarger("down") + # for top in range(len(self.model.temp_world)): + # for left in range(len(self.model.temp_world[top])): + # brick = self.model.temp_world[top][left] + # brick.top -= brick.height + # #print self.model.temp_world[0][0].top + #checking pressed keys + + if event.key == pygame.K_LEFT: if self.model.temp_world[0][0].left != self.model.FAR_LEFT: @@ -113,10 +124,6 @@ def handle_event(self, event): #if farthest block to left reachest threshold, add more blocks to left if self.model.temp_world[0][0].left == self.model.FAR_LEFT: self.model.world_enlarger("left") - - # print "left, ", self.model.temp_world[0][0].left - # print "right, ", self.model.temp_world[0][-1].left - if event.key == pygame.K_RIGHT: @@ -131,9 +138,6 @@ def handle_event(self, event): if self.model.world[0][-1].left == self.model.FAR_RIGHT: self.model.world_enlarger("right") - # print "left, ", self.model.temp_world[0][0].left - # print "right, ", self.model.temp_world[0][-1].left - class PyGameMouseController(object): @@ -146,11 +150,18 @@ def handle_event(self, event): return self.model.paddle.left = event.pos[0] +clock = pygame.time.Clock() + if __name__ == '__main__': + + + + speed = 0; + gravity = 0.1; + thruster = -0.1 pygame.init() size = (640, 480) screen = pygame.display.set_mode(size) - model = game_model.BrickBreakerModel() view = PygameBrickBreakerView(model, screen) controller = PyGameKeyboardController(model) @@ -162,5 +173,48 @@ def handle_event(self, event): if event.type == QUIT: running = False controller.handle_event(event) + + if model.temp_world[-1][0].top >= model.FAR_BOTTOM and model.temp_world[-1][0].top < model.FAR_BOTTOM + 40: + mistake = model.FAR_BOTTOM - model.temp_world[-1][0].top + print "enlarging world" + model.world_enlarger("down") + + + keys = pygame.key.get_pressed() + if keys[pygame.K_UP]: + for top in range(len(model.temp_world)): + for left in range(len(model.temp_world[top])): + brick = model.temp_world[top][left] + brick.top -= speed + model.fuel_station.top -= speed + + speed = speed + thruster; + + if speed > 1: + speed = 0 + + elif keys[pygame.K_DOWN] and not model.can_move_down: + # print "juss drilling" + speed = .7 + for top in range(len(model.temp_world)): + for left in range(len(model.temp_world[top])): + brick = model.temp_world[top][left] + brick.top -= speed + model.fuel_station.top -= speed + + elif model.can_move_down: + for top in range(len(model.temp_world)): + for left in range(len(model.temp_world[top])): + brick = model.temp_world[top][left] + brick.top -= speed + model.fuel_station.top -= speed + speed = speed + gravity + if speed > 5: + speed = 5 + if not model.can_move_down and event.type != KEYDOWN: + speed = 0 + + + view.draw() - time.sleep(.001) + # clock.tick(500000000) From f684f030f07b46e6c31e7bd8e56d76d0bc945527 Mon Sep 17 00:00:00 2001 From: "willem.thorbecke@students.olin.edu" Date: Tue, 8 Mar 2016 00:06:40 -0500 Subject: [PATCH 12/76] "a little more shiz works" --- motherload.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/motherload.py b/motherload.py index 8a4bc53..cd5df70 100644 --- a/motherload.py +++ b/motherload.py @@ -211,6 +211,23 @@ def handle_event(self, event): speed = speed + gravity if speed > 5: speed = 5 + + # elif not model.can_move_down and keys[pygame.K_RIGHT]: + # speed = .7 + # for top in range(len(model.temp_world)): + # for left in range(len(model.temp_world[top])): + # brick = model.temp_world[top][left] + # brick.left -= speed + # model.fuel_station.left -= speed + + # elif not model.can_move_down and keys[pygame.K_LEFT]: + # speed = .7 + # for top in range(len(model.temp_world)): + # for left in range(len(model.temp_world[top])): + # brick = model.temp_world[top][left] + # brick.left += speed + # model.fuel_station.left += speed + if not model.can_move_down and event.type != KEYDOWN: speed = 0 From ded3a121f39914a7b34d71e317c4b246bd3110ae Mon Sep 17 00:00:00 2001 From: Sung Park Date: Tue, 8 Mar 2016 14:53:58 -0500 Subject: [PATCH 13/76] Add functionality for fuel station --- game_model.py | 9 ++++++--- motherload.py | 22 +++++++++++++--------- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/game_model.py b/game_model.py index 2e00a09..c23bb0a 100644 --- a/game_model.py +++ b/game_model.py @@ -86,8 +86,8 @@ def __init__(self): self.world[top].append(brick) self.temp_world = self.world - self.fuel = 5 - self.max_fuel = 10 + self.fuel = 50000 + self.max_fuel = 100000 cheatcode = "dpapp" self.vehicle = Vehicle(40*8,40, 40, 40, cheatcode) self.fuel_station = FuelStation() @@ -111,7 +111,10 @@ def world_enlarger(self, what_side): self.world[-1].append(brick) def get_fuel(self): - return self.fuel*1000 - pygame.time.get_ticks() + return self.fuel + + def get_max_fuel(self): + return self.max_fuel def get_elapsed_time(self): return pygame.time.get_ticks() diff --git a/motherload.py b/motherload.py index 8a4bc53..f76f038 100644 --- a/motherload.py +++ b/motherload.py @@ -54,15 +54,19 @@ def draw(self): r = pygame.Rect(self.model.fuel_station.left,self.model.fuel_station.top,self.model.fuel_station.width,self.model.fuel_station.height) pygame.draw.rect(self.screen, pygame.Color('deep pink'),r) - if self.model.fuel_station.left == self.model.vehicle.left and self.model.fuel_station.top == self.model.vehicle.top and self.model.get_fuel < self.model.max_fuel: - self.model.fuel += 5 + #print "fuel_station top coord: ", self.model.fuel_station.top + #print "vehicle top coord: ", self.model.vehicle.top + + if self.model.fuel_station.left == self.model.vehicle.left and self.model.fuel_station.top == self.model.vehicle.top and self.model.get_fuel() < self.model.get_max_fuel(): + self.model.fuel = self.model.max_fuel + print "helloo" - # if self.model.get_fuel() <= 0: - # # msg = game_over_font.render("GAME OVER",1,(255,255,0)) - # #screen.blit(msg, (0, 240)) - # else: - # timer = myFont.render(str(self.model.get_fuel()), 1, (255,255,0)) - # screen.blit(timer, (20,20)) + if self.model.get_fuel() <= 0: + msg = game_over_font.render("GAME OVER",1,(255,255,0)) + screen.blit(msg, (0, 240)) + else: + timer = myFont.render(str(self.model.get_fuel()), 1, (255,255,0)) + screen.blit(timer, (20,20)) pygame.display.update() @@ -215,6 +219,6 @@ def handle_event(self, event): speed = 0 - + model.fuel -= 1 #decrease fuel value every frame view.draw() # clock.tick(500000000) From 82759dd218e20b74841d568eb0e50cb04b2979ec Mon Sep 17 00:00:00 2001 From: "willem.thorbecke@students.olin.edu" Date: Tue, 8 Mar 2016 14:58:04 -0500 Subject: [PATCH 14/76] random shiz --- game_model.py | 8 +++--- motherload.py | 74 ++++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 62 insertions(+), 20 deletions(-) diff --git a/game_model.py b/game_model.py index 2e00a09..d173c37 100644 --- a/game_model.py +++ b/game_model.py @@ -23,8 +23,8 @@ def __init__(self, left, top, width, height, first): else: self.color = choice(["red", "green", "orange", "blue", "purple"]) else: - self.left = left*width - width*9 - self.top = top #starts the world with a 2 block high sky + self.left = left + self.top = top self.width = width self.height = height random_seed = random.random() @@ -56,7 +56,7 @@ def __init__(self, left, top, width, height, cheatcode): self.speed = 0 self.gravity = .1 self.thruster_veloc = -.1 - + class BrickBreakerModel(object): """ Stores the game state for our brick breaker game """ @@ -107,7 +107,7 @@ def world_enlarger(self, what_side): for left in range(0,self.init_width_dist): - brick = Brick(left, self.world[-2][0].top + self.BRICK_HEIGHT, self.BRICK_WIDTH, self.BRICK_HEIGHT, False) + brick = Brick(self.world[0][0].left+left*self.BRICK_WIDTH, self.world[-2][0].top + self.BRICK_HEIGHT, self.BRICK_WIDTH, self.BRICK_HEIGHT, False) self.world[-1].append(brick) def get_fuel(self): diff --git a/motherload.py b/motherload.py index cd5df70..467f80d 100644 --- a/motherload.py +++ b/motherload.py @@ -32,9 +32,28 @@ def draw(self): if brick.left == self.model.vehicle.left and brick.top <= self.model.vehicle.top + brick.height and brick.top + brick.height > self.model.vehicle.top + brick.height: #checks if the vehicle overlaps a block, if so change block to black if brick.color != "black": - model.can_move_down = False + self.model.can_move_down = False + #print "can move down", model.can_move_down + + else: + self.model.can_move_down = True + #print "can move down", self.model.can_move_down + + if self.model.vehicle.left + float(brick.width)/2 < brick.left and brick.left + float(brick.width)/2 > self.model.vehicle.left and not (brick.left > self.model.vehicle.left + float(brick.width)*3/2) \ + and brick.top > self.model.vehicle.top - brick.width/2 and brick.top + brick.height < self.model.vehicle.top + float(brick.width)*3/2: #checks if the vehicle has a block to the right + if brick.color != "black" and not model.can_move_down: + self.model.can_drill_right = True + # print "can move right", self.model.can_drill_right else: - model.can_move_down = True + self.model.can_drill_right = False + # print "can move right", self.model.can_drill_right + # print "can move?", model.can_move_down + # print "vehicle left", self.model.vehicle.left + # print "brick left ", brick.left + # print "brick top", brick.top + # print "veh top", self.model.vehicle.top + # print "can drill right,", model.can_drill_right + if brick.left == self.model.vehicle.left and self.model.vehicle.top > brick.top and self.model.vehicle.top + brick.height < brick.top + brick.height*2: #checks if the vehicle overlaps a block, if so change block to black if brick.color != "black" and brick.color != "brown": @@ -157,8 +176,8 @@ def handle_event(self, event): speed = 0; - gravity = 0.1; - thruster = -0.1 + gravity = 0.5; + thruster = -0.05 pygame.init() size = (640, 480) screen = pygame.display.set_mode(size) @@ -173,6 +192,8 @@ def handle_event(self, event): if event.type == QUIT: running = False controller.handle_event(event) + model.can_drill_right = False + if model.temp_world[-1][0].top >= model.FAR_BOTTOM and model.temp_world[-1][0].top < model.FAR_BOTTOM + 40: mistake = model.FAR_BOTTOM - model.temp_world[-1][0].top @@ -181,17 +202,20 @@ def handle_event(self, event): keys = pygame.key.get_pressed() - if keys[pygame.K_UP]: - for top in range(len(model.temp_world)): - for left in range(len(model.temp_world[top])): - brick = model.temp_world[top][left] - brick.top -= speed - model.fuel_station.top -= speed + if keys[pygame.K_UP]: - speed = speed + thruster; + for top in range(len(model.temp_world)): + for left in range(len(model.temp_world[top])): + brick = model.temp_world[top][left] + brick.top -= speed + model.fuel_station.top -= speed - if speed > 1: - speed = 0 + speed = speed + thruster; + + if speed > 1: + speed = 0 + elif speed > 10: + speed = 10 elif keys[pygame.K_DOWN] and not model.can_move_down: # print "juss drilling" @@ -202,15 +226,32 @@ def handle_event(self, event): brick.top -= speed model.fuel_station.top -= speed - elif model.can_move_down: + elif model.can_move_down and not keys[pygame.K_UP]: for top in range(len(model.temp_world)): for left in range(len(model.temp_world[top])): brick = model.temp_world[top][left] brick.top -= speed model.fuel_station.top -= speed speed = speed + gravity - if speed > 5: - speed = 5 + if speed > 10: + speed = 10 + + elif keys[pygame.K_RIGHT]: + if not model.can_move_down: + speed = .7 + for top in range(len(model.temp_world)): + for left in range(len(model.temp_world[top])): + brick = model.temp_world[top][left] + brick.left -= speed + model.fuel_station.left -= speed + + else: + for top in range(len(model.temp_world)): + for left in range(len(model.temp_world[top])): + brick = model.temp_world[top][left] + brick.left -= speed + model.fuel_station.left -= speed + # elif not model.can_move_down and keys[pygame.K_RIGHT]: # speed = .7 @@ -234,4 +275,5 @@ def handle_event(self, event): view.draw() + #print "can move right??", model.can_drill_right # clock.tick(500000000) From 708732d8abadaaeda2a33684384b7db10e767b02 Mon Sep 17 00:00:00 2001 From: Sung Park Date: Tue, 8 Mar 2016 15:28:52 -0500 Subject: [PATCH 15/76] Add mineral counter --- game_model.py | 19 +++++++++++-------- motherload.py | 34 +++++++++++++++++++++++++++++----- 2 files changed, 40 insertions(+), 13 deletions(-) diff --git a/game_model.py b/game_model.py index c23bb0a..a0bbd0a 100644 --- a/game_model.py +++ b/game_model.py @@ -86,8 +86,17 @@ def __init__(self): self.world[top].append(brick) self.temp_world = self.world - self.fuel = 50000 - self.max_fuel = 100000 + self.fuel = 500 + self.max_fuel = 1000 + + #counter for minerals + self.red_block = 0 + self.green_block = 0 + self.orange_block = 0 + self.blue_block = 0 + self.purple_block = 0 + + cheatcode = "dpapp" self.vehicle = Vehicle(40*8,40, 40, 40, cheatcode) self.fuel_station = FuelStation() @@ -110,11 +119,5 @@ def world_enlarger(self, what_side): brick = Brick(left, self.world[-2][0].top + self.BRICK_HEIGHT, self.BRICK_WIDTH, self.BRICK_HEIGHT, False) self.world[-1].append(brick) - def get_fuel(self): - return self.fuel - - def get_max_fuel(self): - return self.max_fuel - def get_elapsed_time(self): return pygame.time.get_ticks() diff --git a/motherload.py b/motherload.py index f76f038..e13669e 100644 --- a/motherload.py +++ b/motherload.py @@ -39,7 +39,16 @@ def draw(self): if brick.left == self.model.vehicle.left and self.model.vehicle.top > brick.top and self.model.vehicle.top + brick.height < brick.top + brick.height*2: #checks if the vehicle overlaps a block, if so change block to black if brick.color != "black" and brick.color != "brown": print "I am eating ...", brick.color - + if brick.color == "red": + self.model.red_block += 1 + elif brick.color == "green": + self.model.green_block += 1 + elif brick.color == "orange": + self.model.orange_block += 1 + elif brick.color == "blue": + self.model.blue_block += 1 + elif brick.color == "purple": + self.model.purple_block += 1 brick.color = "black" pygame.draw.rect(self.screen, pygame.Color(brick.color), r) @@ -57,16 +66,31 @@ def draw(self): #print "fuel_station top coord: ", self.model.fuel_station.top #print "vehicle top coord: ", self.model.vehicle.top - if self.model.fuel_station.left == self.model.vehicle.left and self.model.fuel_station.top == self.model.vehicle.top and self.model.get_fuel() < self.model.get_max_fuel(): + if self.model.fuel_station.left == self.model.vehicle.left and self.model.fuel_station.top == self.model.vehicle.top and self.model.fuel < self.model.max_fuel: self.model.fuel = self.model.max_fuel - print "helloo" - if self.model.get_fuel() <= 0: + if self.model.fuel <= 0: msg = game_over_font.render("GAME OVER",1,(255,255,0)) screen.blit(msg, (0, 240)) else: - timer = myFont.render(str(self.model.get_fuel()), 1, (255,255,0)) + timer = myFont.render(str(self.model.fuel), 1, (255,255,0)) screen.blit(timer, (20,20)) + + red_counter = myFont.render("Red: " + str(self.model.red_block), 1, (255,255,0)) + screen.blit(red_counter,(550,20)) + + green_counter = myFont.render("Green: " + str(self.model.green_block), 1, (255,255,0)) + screen.blit(green_counter,(550,40)) + + orange_counter = myFont.render("Orange: " + str(self.model.orange_block), 1, (255,255,0)) + screen.blit(orange_counter,(550,60)) + + blue_counter = myFont.render("Blue: " + str(self.model.blue_block), 1, (255,255,0)) + screen.blit(blue_counter,(550,80)) + + purple_counter = myFont.render("Purplpe: " + str(self.model.purple_block), 1, (255,255,0)) + screen.blit(purple_counter,(550,100)) + pygame.display.update() From 4caeadf99543713ca6497fb3b799d42571495420 Mon Sep 17 00:00:00 2001 From: "willem.thorbecke@students.olin.edu" Date: Tue, 8 Mar 2016 15:29:54 -0500 Subject: [PATCH 16/76] sprite bricks working --- game_model.py | 61 ++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 55 insertions(+), 6 deletions(-) diff --git a/game_model.py b/game_model.py index dd441b1..0405a69 100644 --- a/game_model.py +++ b/game_model.py @@ -7,14 +7,58 @@ Class containing game model and all its components """ -class Brick(object): - """ Represents a brick in our brick breaker game """ +# class Brick(object): +# """ Represents a brick in our brick breaker game """ +# def __init__(self, left, top, width, height, first): +# if first: +# self.left = left*width - width*9 #renders 9 extra columns of blocks off screen to the left +# self.top = top*height + height*2 #starts the world with a 2 block high sky +# self.width = width +# self.height = height +# random_seed = random.random() +# if random_seed < 0.1: +# self.color = "black" +# elif random_seed <0.9: +# self.color = "brown" +# else: +# self.color = choice(["red", "green", "orange", "blue", "purple"]) +# else: +# self.left = left +# self.top = top +# self.width = width +# self.height = height +# random_seed = random.random() +# if random_seed < 0.1: +# self.color = "black" +# elif random_seed <0.9: +# self.color = "brown" +# else: +# self.color = choice(["red", "green", "orange", "blue", "purple"]) + +class Brick(pygame.sprite.Sprite): + + # Constructor. Pass in the color of the block, + # and its x and y position def __init__(self, left, top, width, height, first): + # Call the parent class (Sprite) constructor + pygame.sprite.Sprite.__init__(self) + + # Create an image of the block, and fill it with a color. + # This could also be an image loaded from the disk. + self.image = pygame.Surface([width, height]) + + + # Fetch the rectangle object that has the dimensions of the image + # Update the position of this object by setting the values of rect.x and rect.y + self.rect = self.image.get_rect() + if first: - self.left = left*width - width*9 #renders 9 extra columns of blocks off screen to the left - self.top = top*height + height*2 #starts the world with a 2 block high sky + self.rect.x = left*width - width*9 #renders 9 extra columns of blocks off screen to the left + self.rect.y = top*height + height*2 #starts the world with a 2 block high sky self.width = width self.height = height + self.top = left*width - width*9 + self.left = top*height + height*2 random_seed = random.random() if random_seed < 0.1: self.color = "black" @@ -22,9 +66,12 @@ def __init__(self, left, top, width, height, first): self.color = "brown" else: self.color = choice(["red", "green", "orange", "blue", "purple"]) + self.image.fill((0,220,255)) else: - self.left = left - self.top = top + self.rect.x = left + self.rext.y = top + self.top = left*width - width*9 + self.left = top*height + height*2 self.width = width self.height = height random_seed = random.random() @@ -34,6 +81,8 @@ def __init__(self, left, top, width, height, first): self.color = "brown" else: self.color = choice(["red", "green", "orange", "blue", "purple"]) + self.image.fill((0,220,255)) + class FuelStation(object): """ Represents a fuel station as a pink block at fixed point""" From f1a289183564660350b6dd81d08c62c480ef6dd9 Mon Sep 17 00:00:00 2001 From: "willem.thorbecke@students.olin.edu" Date: Tue, 8 Mar 2016 15:33:46 -0500 Subject: [PATCH 17/76] yo --- game_model.py | 4 ++-- motherload.py | 30 +++++++++++++++--------------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/game_model.py b/game_model.py index a3ccc30..02837c8 100644 --- a/game_model.py +++ b/game_model.py @@ -70,8 +70,8 @@ def __init__(self, left, top, width, height, first): else: self.rect.x = left self.rext.y = top - self.top = left*width - width*9 - self.left = top*height + height*2 + self.top = left + self.left = top self.width = width self.height = height random_seed = random.random() diff --git a/motherload.py b/motherload.py index b9601c7..b0a2308 100644 --- a/motherload.py +++ b/motherload.py @@ -264,21 +264,21 @@ def handle_event(self, event): if speed > 10: speed = 10 - elif keys[pygame.K_RIGHT]: - if not model.can_move_down: - speed = .7 - for top in range(len(model.temp_world)): - for left in range(len(model.temp_world[top])): - brick = model.temp_world[top][left] - brick.left -= speed - model.fuel_station.left -= speed - - else: - for top in range(len(model.temp_world)): - for left in range(len(model.temp_world[top])): - brick = model.temp_world[top][left] - brick.left -= speed - model.fuel_station.left -= speed + # elif keys[pygame.K_RIGHT]: + # if not model.can_move_down: + # speed = .7 + # for top in range(len(model.temp_world)): + # for left in range(len(model.temp_world[top])): + # brick = model.temp_world[top][left] + # brick.left -= speed + # model.fuel_station.left -= speed + + # else: + # for top in range(len(model.temp_world)): + # for left in range(len(model.temp_world[top])): + # brick = model.temp_world[top][left] + # brick.left -= speed + # model.fuel_station.left -= speed # elif not model.can_move_down and keys[pygame.K_RIGHT]: From a86fb97228d03ab39bd3cff97404a6d5b6b29808 Mon Sep 17 00:00:00 2001 From: "willem.thorbecke@students.olin.edu" Date: Tue, 8 Mar 2016 15:38:22 -0500 Subject: [PATCH 18/76] fixed location start --- game_model.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/game_model.py b/game_model.py index 02837c8..9cbb2f4 100644 --- a/game_model.py +++ b/game_model.py @@ -57,8 +57,8 @@ def __init__(self, left, top, width, height, first): self.rect.y = top*height + height*2 #starts the world with a 2 block high sky self.width = width self.height = height - self.top = left*width - width*9 - self.left = top*height + height*2 + self.top = top*height + height*2 + self.left = left*width - width*9 random_seed = random.random() if random_seed < 0.1: self.color = "black" From c844298115f6840e04a912e82c6d15feaca85977 Mon Sep 17 00:00:00 2001 From: Sung Park Date: Tue, 8 Mar 2016 15:39:51 -0500 Subject: [PATCH 19/76] Add shop --- game_model.py | 9 +++++++++ motherload.py | 6 +++--- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/game_model.py b/game_model.py index 02837c8..c2e85d4 100644 --- a/game_model.py +++ b/game_model.py @@ -92,6 +92,14 @@ def __init__(self): self.width = 40 self.height = 40 +class Shop(object): + """ Represents a shop where the vehicle can sell a mineral""" + def __init__(self): + self.left = 480 + self.top = 40 + self.width = 40 + self.height = 40 + class Vehicle(object): """ Represents the paddle in our brick breaker game """ def __init__(self, left, top, width, height, cheatcode): @@ -149,6 +157,7 @@ def __init__(self): cheatcode = "dpapp" self.vehicle = Vehicle(40*8,40, 40, 40, cheatcode) self.fuel_station = FuelStation() + self.shop = Shop() def world_enlarger(self, what_side): diff --git a/motherload.py b/motherload.py index b0a2308..8142dc7 100644 --- a/motherload.py +++ b/motherload.py @@ -82,9 +82,9 @@ def draw(self): r = pygame.Rect(self.model.fuel_station.left,self.model.fuel_station.top,self.model.fuel_station.width,self.model.fuel_station.height) pygame.draw.rect(self.screen, pygame.Color('deep pink'),r) - #print "fuel_station top coord: ", self.model.fuel_station.top - #print "vehicle top coord: ", self.model.vehicle.top - + r = pygame.Rect(self.model.shop.left,self.model.shop.top,self.model.shop.width,self.model.shop.height) + pygame.draw.rect(self.screen, pygame.Color('yellow'), r) + if self.model.fuel_station.left == self.model.vehicle.left and self.model.fuel_station.top == self.model.vehicle.top and self.model.fuel < self.model.max_fuel: self.model.fuel = self.model.max_fuel From fbc0aa74d129885b07e54fb931edf2bbd7cc8c7e Mon Sep 17 00:00:00 2001 From: Sung Park Date: Tue, 8 Mar 2016 15:48:38 -0500 Subject: [PATCH 20/76] Add money counter --- game_model.py | 3 ++- motherload.py | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/game_model.py b/game_model.py index 48dcde8..41d3700 100644 --- a/game_model.py +++ b/game_model.py @@ -152,7 +152,8 @@ def __init__(self): self.orange_block = 0 self.blue_block = 0 self.purple_block = 0 - + + self.money = 0 cheatcode = "dpapp" self.vehicle = Vehicle(40*8,40, 40, 40, cheatcode) diff --git a/motherload.py b/motherload.py index 8142dc7..4423b99 100644 --- a/motherload.py +++ b/motherload.py @@ -85,8 +85,10 @@ def draw(self): r = pygame.Rect(self.model.shop.left,self.model.shop.top,self.model.shop.width,self.model.shop.height) pygame.draw.rect(self.screen, pygame.Color('yellow'), r) + #Vehicle visiting fuel station if self.model.fuel_station.left == self.model.vehicle.left and self.model.fuel_station.top == self.model.vehicle.top and self.model.fuel < self.model.max_fuel: self.model.fuel = self.model.max_fuel + if self.model.fuel <= 0: msg = game_over_font.render("GAME OVER",1,(255,255,0)) @@ -110,6 +112,9 @@ def draw(self): purple_counter = myFont.render("Purplpe: " + str(self.model.purple_block), 1, (255,255,0)) screen.blit(purple_counter,(550,100)) + money_counter = myFont.render("Money: " + str(self.model.money), 1, (255,255, 0)) + screen.blit(money_counter, (550,120)) + pygame.display.update() From f8ab8260ae7453cce09c5f84701df946ad714aa6 Mon Sep 17 00:00:00 2001 From: "willem.thorbecke@students.olin.edu" Date: Tue, 8 Mar 2016 15:48:58 -0500 Subject: [PATCH 21/76] sprites --- game_model.py | 53 ++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 48 insertions(+), 5 deletions(-) diff --git a/game_model.py b/game_model.py index 9cbb2f4..7f0c0d3 100644 --- a/game_model.py +++ b/game_model.py @@ -84,18 +84,56 @@ def __init__(self, left, top, width, height, first): self.image.fill((0,220,255)) -class FuelStation(object): - """ Represents a fuel station as a pink block at fixed point""" +# class FuelStation(object): +# """ Represents a fuel station as a pink block at fixed point""" +# def __init__(self): +# self.left = 400 +# self.top = 40 +# self.width = 40 +# self.height = 40 + +class FuelStation(pygame.sprite.Sprite): + + # Constructor. Pass in the color of the block, + # and its x and y position def __init__(self): + # Call the parent class (Sprite) constructor + pygame.sprite.Sprite.__init__(self) + + # Create an image of the block, and fill it with a color. + # This could also be an image loaded from the disk. + self.image = pygame.Surface([40, 40]) + self.left = 400 self.top = 40 self.width = 40 self.height = 40 + self.image.fill((0,255,255)) + + # Fetch the rectangle object that has the dimensions of the image + # Update the position of this object by setting the values of rect.x and rect.y + self.rect = self.image.get_rect() + self.rect.x = 400 + self.rect.y = 404 + + +class Vehicle(pygame.sprite.Sprite): -class Vehicle(object): - """ Represents the paddle in our brick breaker game """ + # Constructor. Pass in the color of the block, + # and its x and y position def __init__(self, left, top, width, height, cheatcode): - """ Initialize the paddle with the specified geometry """ + # Call the parent class (Sprite) constructor + pygame.sprite.Sprite.__init__(self) + + # Create an image of the block, and fill it with a color. + # This could also be an image loaded from the disk. + self.image = pygame.Surface([width, height]) + + + # Fetch the rectangle object that has the dimensions of the image + # Update the position of this object by setting the values of rect.x and rect.y + self.rect = self.image.get_rect() + self.left = left self.top = top self.width = width @@ -103,8 +141,13 @@ def __init__(self, left, top, width, height, cheatcode): self.thruster = False self.cheatcode = cheatcode self.speed = 0 + self.gravity = .1 self.thruster_veloc = -.1 + + self.rect.x = left + self.rect.y = top + self.image.fill((0,220,255)) class BrickBreakerModel(object): From d9cfa21891df3fd889f385e2a43b369896889e29 Mon Sep 17 00:00:00 2001 From: Sung Park Date: Tue, 8 Mar 2016 15:55:36 -0500 Subject: [PATCH 22/76] Update movement behavior for shop --- motherload.py | 105 ++++++++++++++++++++++++++------------------------ 1 file changed, 55 insertions(+), 50 deletions(-) diff --git a/motherload.py b/motherload.py index 4423b99..2b3e46c 100644 --- a/motherload.py +++ b/motherload.py @@ -36,7 +36,7 @@ def draw(self): #print "can move down", model.can_move_down else: - self.model.can_move_down = True + self.model.can_move_down = True #print "can move down", self.model.can_move_down if self.model.vehicle.left + float(brick.width)/2 < brick.left and brick.left + float(brick.width)/2 > self.model.vehicle.left and not (brick.left > self.model.vehicle.left + float(brick.width)*3/2) \ @@ -140,20 +140,20 @@ def handle_event(self, event): # if event.key == pygame.K_DOWN: - # print self.model.temp_world[-1][0].top - # if self.model.temp_world[-1][0].top != self.model.FAR_BOTTOM: - # for top in range(len(self.model.temp_world)): - # for left in range(len(self.model.temp_world[top])): - # brick = self.model.temp_world[top][left] - # brick.top -= brick.height - # self.model.fuel_station.top -= self.model.BRICK_HEIGHT - # else: - # self.model.fuel_station.top -= self.model.BRICK_HEIGHT - # self.model.world_enlarger("down") - # for top in range(len(self.model.temp_world)): - # for left in range(len(self.model.temp_world[top])): - # brick = self.model.temp_world[top][left] - # brick.top -= brick.height + # print self.model.temp_world[-1][0].top + # if self.model.temp_world[-1][0].top != self.model.FAR_BOTTOM: + # for top in range(len(self.model.temp_world)): + # for left in range(len(self.model.temp_world[top])): + # brick = self.model.temp_world[top][left] + # brick.top -= brick.height + # self.model.fuel_station.top -= self.model.BRICK_HEIGHT + # else: + # self.model.fuel_station.top -= self.model.BRICK_HEIGHT + # self.model.world_enlarger("down") + # for top in range(len(self.model.temp_world)): + # for left in range(len(self.model.temp_world[top])): + # brick = self.model.temp_world[top][left] + # brick.top -= brick.height # #print self.model.temp_world[0][0].top @@ -170,6 +170,7 @@ def handle_event(self, event): brick = self.model.temp_world[top][left] brick.left += brick.width self.model.fuel_station.left += self.model.BRICK_HEIGHT + self.model.shop.left += self.model.BRICK_HEIGHT else: return @@ -185,6 +186,7 @@ def handle_event(self, event): brick = self.model.temp_world[top][left] brick.left -= brick.width self.model.fuel_station.left -= self.model.BRICK_HEIGHT + self.model.shop.left -= self.model.BRICK_HEIGHT else: return if self.model.world[0][-1].left == self.model.FAR_RIGHT: @@ -229,9 +231,9 @@ def handle_event(self, event): if model.temp_world[-1][0].top >= model.FAR_BOTTOM and model.temp_world[-1][0].top < model.FAR_BOTTOM + 40: - mistake = model.FAR_BOTTOM - model.temp_world[-1][0].top - print "enlarging world" - model.world_enlarger("down") + mistake = model.FAR_BOTTOM - model.temp_world[-1][0].top + print "enlarging world" + model.world_enlarger("down") keys = pygame.key.get_pressed() @@ -242,8 +244,9 @@ def handle_event(self, event): brick = model.temp_world[top][left] brick.top -= speed model.fuel_station.top -= speed + model.shop.top -= speed - speed = speed + thruster; + speed = speed + thruster; if speed > 1: speed = 0 @@ -251,23 +254,25 @@ def handle_event(self, event): speed = 10 elif keys[pygame.K_DOWN] and not model.can_move_down: - # print "juss drilling" - speed = .7 - for top in range(len(model.temp_world)): - for left in range(len(model.temp_world[top])): - brick = model.temp_world[top][left] - brick.top -= speed - model.fuel_station.top -= speed - - elif model.can_move_down and not keys[pygame.K_UP]: - for top in range(len(model.temp_world)): - for left in range(len(model.temp_world[top])): - brick = model.temp_world[top][left] - brick.top -= speed - model.fuel_station.top -= speed - speed = speed + gravity - if speed > 10: - speed = 10 + # print "juss drilling" + speed = .7 + for top in range(len(model.temp_world)): + for left in range(len(model.temp_world[top])): + brick = model.temp_world[top][left] + brick.top -= speed + model.fuel_station.top -= speed + model.shop.top -= speed + + elif model.can_move_down and not keys[pygame.K_UP]: + for top in range(len(model.temp_world)): + for left in range(len(model.temp_world[top])): + brick = model.temp_world[top][left] + brick.top -= speed + model.fuel_station.top -= speed + model.shop.top -= speed + speed = speed + gravity + if speed > 10: + speed = 10 # elif keys[pygame.K_RIGHT]: # if not model.can_move_down: @@ -287,25 +292,25 @@ def handle_event(self, event): # elif not model.can_move_down and keys[pygame.K_RIGHT]: - # speed = .7 - # for top in range(len(model.temp_world)): - # for left in range(len(model.temp_world[top])): - # brick = model.temp_world[top][left] - # brick.left -= speed - # model.fuel_station.left -= speed + # speed = .7 + # for top in range(len(model.temp_world)): + # for left in range(len(model.temp_world[top])): + # brick = model.temp_world[top][left] + # brick.left -= speed + # model.fuel_station.left -= speed # elif not model.can_move_down and keys[pygame.K_LEFT]: - # speed = .7 - # for top in range(len(model.temp_world)): - # for left in range(len(model.temp_world[top])): - # brick = model.temp_world[top][left] - # brick.left += speed - # model.fuel_station.left += speed + # speed = .7 + # for top in range(len(model.temp_world)): + # for left in range(len(model.temp_world[top])): + # brick = model.temp_world[top][left] + # brick.left += speed + # model.fuel_station.left += speed if not model.can_move_down and event.type != KEYDOWN: - speed = 0 + speed = 0 - + model.fuel -= 1 #decrease fuel value every frame view.draw() #print "can move right??", model.can_drill_right From 165ef2dfc354a70f47b14df9f30b150f3f8aa81f Mon Sep 17 00:00:00 2001 From: "willem.thorbecke@students.olin.edu" Date: Tue, 8 Mar 2016 15:58:14 -0500 Subject: [PATCH 23/76] fixed bug --- game_model.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/game_model.py b/game_model.py index 7480c4c..f1570cf 100644 --- a/game_model.py +++ b/game_model.py @@ -69,7 +69,7 @@ def __init__(self, left, top, width, height, first): self.image.fill((0,220,255)) else: self.rect.x = left - self.rext.y = top + self.rect.y = top self.top = left self.left = top self.width = width From ec183f7b93567e9a5d7b6ab1798b4240138fa87d Mon Sep 17 00:00:00 2001 From: "willem.thorbecke@students.olin.edu" Date: Tue, 8 Mar 2016 16:34:09 -0500 Subject: [PATCH 24/76] sprites working like a mofo --- game_model.py | 24 +++++++++++++++++++++--- motherload.py | 33 ++++++++++++++++++++++++++++----- 2 files changed, 49 insertions(+), 8 deletions(-) diff --git a/game_model.py b/game_model.py index f1570cf..cbbab2c 100644 --- a/game_model.py +++ b/game_model.py @@ -114,17 +114,35 @@ def __init__(self): # Update the position of this object by setting the values of rect.x and rect.y self.rect = self.image.get_rect() self.rect.x = 400 - self.rect.y = 404 + self.rect.y = 40 -class Shop(object): - """ Represents a shop where the vehicle can sell a mineral""" + + +class Shop(pygame.sprite.Sprite): + + # Constructor. Pass in the color of the block, + # and its x and y position def __init__(self): + # Call the parent class (Sprite) constructor + pygame.sprite.Sprite.__init__(self) + + # Create an image of the block, and fill it with a color. + # This could also be an image loaded from the disk. + self.image = pygame.Surface([40, 40]) + self.rect = self.image.get_rect() + self.left = 480 self.top = 40 self.width = 40 self.height = 40 + self.rect.x = 480 + self.rect.y = 40 + + # Fetch the rectangle object that has the dimensions of the image + # Update the position of this object by setting the values of rect.x and rect.y + class Vehicle(pygame.sprite.Sprite): diff --git a/motherload.py b/motherload.py index 2b3e46c..5f0acf1 100644 --- a/motherload.py +++ b/motherload.py @@ -1,9 +1,11 @@ -import pygame -from pygame.locals import QUIT, KEYDOWN, MOUSEMOTION +import pygame, os, sys +from pygame.locals import * import time from random import choice import random import game_model +import pygame, os, sys + class PygameBrickBreakerView(object): """ Visualizes a brick breaker game in a pygame window """ @@ -86,10 +88,10 @@ def draw(self): pygame.draw.rect(self.screen, pygame.Color('yellow'), r) #Vehicle visiting fuel station - if self.model.fuel_station.left == self.model.vehicle.left and self.model.fuel_station.top == self.model.vehicle.top and self.model.fuel < self.model.max_fuel: + if pygame.sprite.collide_rect(self.model.fuel_station, self.model.vehicle): self.model.fuel = self.model.max_fuel - + if self.model.fuel <= 0: msg = game_over_font.render("GAME OVER",1,(255,255,0)) screen.blit(msg, (0, 240)) @@ -169,8 +171,14 @@ def handle_event(self, event): for left in range(len(self.model.temp_world[top])): brick = self.model.temp_world[top][left] brick.left += brick.width + brick.rect.x += brick.width #sprites stuff self.model.fuel_station.left += self.model.BRICK_HEIGHT + self.model.fuel_station.rect.x += self.model.BRICK_HEIGHT self.model.shop.left += self.model.BRICK_HEIGHT + self.model.shop.rect.x += self.model.BRICK_HEIGHT + # print self.model.fuel_station.left + # print self.model.fuel_station.rect.x + else: return @@ -185,8 +193,13 @@ def handle_event(self, event): for left in range(len(self.model.temp_world[top])): brick = self.model.temp_world[top][left] brick.left -= brick.width + brick.rect.x -= brick.width self.model.fuel_station.left -= self.model.BRICK_HEIGHT - self.model.shop.left -= self.model.BRICK_HEIGHT + self.model.fuel_station.rect.x -= self.model.BRICK_HEIGHT + self.model.shop.left -= self.model.BRICK_HEIGHT + self.model.shop.rect.x -= self.model.BRICK_HEIGHT + # print self.model.fuel_station.left + # print self.model.fuel_station.rect.x else: return if self.model.world[0][-1].left == self.model.FAR_RIGHT: @@ -243,8 +256,11 @@ def handle_event(self, event): for left in range(len(model.temp_world[top])): brick = model.temp_world[top][left] brick.top -= speed + brick.rect.y -= speed model.fuel_station.top -= speed + model.fuel_station.rect.y -= speed model.shop.top -= speed + model.shop.rect.y -= speed speed = speed + thruster; @@ -260,16 +276,23 @@ def handle_event(self, event): for left in range(len(model.temp_world[top])): brick = model.temp_world[top][left] brick.top -= speed + brick.rect.y -= speed model.fuel_station.top -= speed + model.fuel_station.rect.y -= speed model.shop.top -= speed + model.shop.rect.y -= speed elif model.can_move_down and not keys[pygame.K_UP]: for top in range(len(model.temp_world)): for left in range(len(model.temp_world[top])): brick = model.temp_world[top][left] brick.top -= speed + brick.rect.y -= speed model.fuel_station.top -= speed + model.fuel_station.rect.y -= speed model.shop.top -= speed + model.shop.rect.y -= speed + speed = speed + gravity if speed > 10: speed = 10 From efe25d498be85beba2de9f9d2c0ecebb1e2351b9 Mon Sep 17 00:00:00 2001 From: Sung Park Date: Tue, 8 Mar 2016 16:46:00 -0500 Subject: [PATCH 25/76] Add functionality to sell minerals --- motherload.py | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/motherload.py b/motherload.py index 5f0acf1..8317f89 100644 --- a/motherload.py +++ b/motherload.py @@ -91,6 +91,19 @@ def draw(self): if pygame.sprite.collide_rect(self.model.fuel_station, self.model.vehicle): self.model.fuel = self.model.max_fuel + #vehicle visiting shop + if pygame.sprite.collide_rect(self.model.shop, self.model.vehicle): + self.model.money += 100 * self.model.red_block + self.model.money += 100 * self.model.green_block + self.model.money += 100 * self.model.orange_block + self.model.money += 100 * self.model.blue_block + self.model.money += 100 * self.model.purple_block + self.model.red_block = 0 + self.model.green_block = 0 + self.model.orange_block = 0 + self.model.blue_block = 0 + self.model.purple_block = 0 + if self.model.fuel <= 0: msg = game_over_font.render("GAME OVER",1,(255,255,0)) @@ -115,7 +128,7 @@ def draw(self): screen.blit(purple_counter,(550,100)) money_counter = myFont.render("Money: " + str(self.model.money), 1, (255,255, 0)) - screen.blit(money_counter, (550,120)) + screen.blit(money_counter, (500,120)) pygame.display.update() From 01e27812cffd46fd6948f9a04cfc1c8dadadd4c5 Mon Sep 17 00:00:00 2001 From: Sung Park Date: Tue, 8 Mar 2016 17:26:28 -0500 Subject: [PATCH 26/76] Add fuel station and shop image --- game_model.py | 10 +++++++--- motherload.py | 15 ++++++++------- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/game_model.py b/game_model.py index cbbab2c..460567d 100644 --- a/game_model.py +++ b/game_model.py @@ -102,13 +102,13 @@ def __init__(self): # Create an image of the block, and fill it with a color. # This could also be an image loaded from the disk. - self.image = pygame.Surface([40, 40]) + self.image = pygame.image.load('fuel_station.gif').convert() self.left = 400 self.top = 40 self.width = 40 self.height = 40 - self.image.fill((0,255,255)) + #self.image.fill((0,255,255)) # Fetch the rectangle object that has the dimensions of the image # Update the position of this object by setting the values of rect.x and rect.y @@ -130,7 +130,7 @@ def __init__(self): # Create an image of the block, and fill it with a color. # This could also be an image loaded from the disk. - self.image = pygame.Surface([40, 40]) + self.image = pygame.image.load('store.jpg').convert() self.rect = self.image.get_rect() self.left = 480 @@ -219,8 +219,12 @@ def __init__(self): cheatcode = "dpapp" self.vehicle = Vehicle(40*8,40, 40, 40, cheatcode) + + self.sprite_list = pygame.sprite.Group() #a list of sprites to be drawn self.fuel_station = FuelStation() + self.sprite_list.add(self.fuel_station) self.shop = Shop() + self.sprite_list.add(self.shop) def world_enlarger(self, what_side): diff --git a/motherload.py b/motherload.py index 8317f89..6cef1bf 100644 --- a/motherload.py +++ b/motherload.py @@ -83,9 +83,10 @@ def draw(self): r = pygame.Rect(self.model.fuel_station.left,self.model.fuel_station.top,self.model.fuel_station.width,self.model.fuel_station.height) pygame.draw.rect(self.screen, pygame.Color('deep pink'),r) + self.model.sprite_list.draw(self.screen) r = pygame.Rect(self.model.shop.left,self.model.shop.top,self.model.shop.width,self.model.shop.height) - pygame.draw.rect(self.screen, pygame.Color('yellow'), r) + #pygame.draw.rect(self.screen, pygame.Color('yellow'), r) #Vehicle visiting fuel station if pygame.sprite.collide_rect(self.model.fuel_station, self.model.vehicle): @@ -271,9 +272,9 @@ def handle_event(self, event): brick.top -= speed brick.rect.y -= speed model.fuel_station.top -= speed - model.fuel_station.rect.y -= speed + model.fuel_station.rect.y = model.fuel_station.top model.shop.top -= speed - model.shop.rect.y -= speed + model.shop.rect.y = model.shop.top speed = speed + thruster; @@ -291,9 +292,9 @@ def handle_event(self, event): brick.top -= speed brick.rect.y -= speed model.fuel_station.top -= speed - model.fuel_station.rect.y -= speed + model.fuel_station.rect.y = model.fuel_station.top model.shop.top -= speed - model.shop.rect.y -= speed + model.shop.rect.y = model.shop.top elif model.can_move_down and not keys[pygame.K_UP]: for top in range(len(model.temp_world)): @@ -302,9 +303,9 @@ def handle_event(self, event): brick.top -= speed brick.rect.y -= speed model.fuel_station.top -= speed - model.fuel_station.rect.y -= speed + model.fuel_station.rect.y = model.fuel_station.top model.shop.top -= speed - model.shop.rect.y -= speed + model.shop.rect.y = model.shop.top speed = speed + gravity if speed > 10: From c4bbe64116926efc0f70bb6608cfb83dc603a63e Mon Sep 17 00:00:00 2001 From: "willem.thorbecke@students.olin.edu" Date: Tue, 8 Mar 2016 17:26:55 -0500 Subject: [PATCH 27/76] fixed infinite terrain --- game_model.py | 8 ++++---- motherload.py | 17 +++++++++++++++-- 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/game_model.py b/game_model.py index cbbab2c..534c700 100644 --- a/game_model.py +++ b/game_model.py @@ -66,12 +66,12 @@ def __init__(self, left, top, width, height, first): self.color = "brown" else: self.color = choice(["red", "green", "orange", "blue", "purple"]) - self.image.fill((0,220,255)) + #self.image.fill((0,220,255)) else: self.rect.x = left self.rect.y = top - self.top = left - self.left = top + self.top = top + self.left = left self.width = width self.height = height random_seed = random.random() @@ -81,7 +81,7 @@ def __init__(self, left, top, width, height, first): self.color = "brown" else: self.color = choice(["red", "green", "orange", "blue", "purple"]) - self.image.fill((0,220,255)) + #self.image.fill((0,220,255)) # class FuelStation(object): diff --git a/motherload.py b/motherload.py index 5f0acf1..d0c5902 100644 --- a/motherload.py +++ b/motherload.py @@ -5,6 +5,7 @@ import random import game_model import pygame, os, sys +import math class PygameBrickBreakerView(object): @@ -27,18 +28,30 @@ def draw(self): for left in range(len(self.model.temp_world[top])): #pulls the appropriate brick model from the list + brick = self.model.temp_world[top][left] r = pygame.Rect(brick.left, brick.top, brick.width, brick.height) - - if brick.left == self.model.vehicle.left and brick.top <= self.model.vehicle.top + brick.height and brick.top + brick.height > self.model.vehicle.top + brick.height: #checks if the vehicle overlaps a block, if so change block to black + # if pygame.sprite.collide_rect(brick, self.model.vehicle) and brick.rect.y > self.model.vehicle.rect.y and math.fabs(brick.rect.x - self.model.vehicle.rect.x) < 2: + # print "absolute ", math.fabs(self.model.vehicle.rect.x - brick.rect.x) + # print "colliding" + # print "brick, x ", brick.rect.x + # print "brick, y ", brick.rect.y + # print "veh x, ", self.model.vehicle.rect.x + # print "veh y, ", self.model.vehicle.rect.y + + if brick.left == self.model.vehicle.left and brick.top <= self.model.vehicle.top + brick.height and brick.top + brick.height > self.model.vehicle.top + brick.height: + + #checks if the vehicle overlaps a block, if so change block to black if brick.color != "black": self.model.can_move_down = False + #print "can move down", model.can_move_down else: self.model.can_move_down = True + #print "can move down", self.model.can_move_down if self.model.vehicle.left + float(brick.width)/2 < brick.left and brick.left + float(brick.width)/2 > self.model.vehicle.left and not (brick.left > self.model.vehicle.left + float(brick.width)*3/2) \ From 6a92b4e31abac8f3272022043a35a77a05664a3a Mon Sep 17 00:00:00 2001 From: Sung Park Date: Tue, 8 Mar 2016 17:28:10 -0500 Subject: [PATCH 28/76] Add image to the repo --- fuel_station.gif | Bin 0 -> 941 bytes store.jpg | Bin 0 -> 1671 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 fuel_station.gif create mode 100644 store.jpg diff --git a/fuel_station.gif b/fuel_station.gif new file mode 100644 index 0000000000000000000000000000000000000000..82cf7904de68b6bbd955fa2133f54b6aa2e44704 GIT binary patch literal 941 zcmV;e15*4)Nk%w1VJHA70M$PL>-7Be`u-V+>vFd9k*?YcWXs9q`!{*Z5_Z`{oa-En z?_0e61536AP`d#&njVw$2VBIo-2Bt){Vt{dG^zVTs`;tc`ZV}gE1UHr zkLem}$`z3LN3Z+9;QL#v@#5?Cp~2@1k^D%b@G7DCK91lUnEfiL{s2L(Fq7&ARJ{NH z|NsC0A^8LW002J#EC2ui04M+`000L6z@Ko2;kAy)q;kpRVF1Et=~Wv|uGp-0%N^BJ z7N5{kn=H=gw0g}>do4e}?q|g8u|L_`u+Lt z68ypNwZNZ-aw-h+Gx+bFL2x(xsqm0M#fFO*Dw>94nN-vW>qBL!Ov0qn9>fL85Z1qtE`{uM*P$N_9I z_~7vu?FA45_6i6*IIaN!0%AnKEMR~S8xKN-&2hNi#TgF`CGUkyoIGZkT;XrBA zxGAgt<+?Rz9zHPOo?W{Dg5$_>?0y@=bcyD;i6TEv`v8RL$CWSlk>PlW?#LBmhj73; z2<+OIga1DLgOBm$A%K`q|H5|e^J!$DFWLux5ab=ug9ro?*xz;;hya3q1&V+`01b*j zo(Tg+Xdi+E(qKS?2SC`$U=IhF&_DqsmUy9hB)a!Oi8T07B8ec1_#%lX?v??GF3b=B z0Rv><0}V4aV1fw@%vity_uWY10Y3UL!vIDyFeC#IRB2_6s@-TM1TNUNrIk_=`6U6q z+&6=DU#1B`m^<{~rkez;BIld{2>9lmc`m|nVr15nTqX{MltYU!plL@}rXsHUpws;suUDgk0dF+&I>)N1Rk PxaO*Bts%@1MGycxaoE9W literal 0 HcmV?d00001 diff --git a/store.jpg b/store.jpg new file mode 100644 index 0000000000000000000000000000000000000000..c9f778adee35ae3b297d69dba3ff19f56764f7b7 GIT binary patch literal 1671 zcmb7wqFCb>yS!9Y-mj9LRx3=+T>NWp|WA`rC*A!W2ss2Z7SKoHOhLU=_n zGJ_Ksct9Ac1{5hOgjYa7gbMN~Q>rC^0|l`}lp%RUKfKkC-D{n_&VQYKe)}Btuj*&O z22ZvJ8vxg34O#<$dJJFzTAC5mxRyo;NaIKZ0z#mWDAdOVW6&rV1EWxAZ8Qd}(fSUj zjm2pO4dl~REhGdXu`mk$82MYKmH~J)U z)cPT10|06oAqW9|3V>P=0*Qk0fSv`~mZ`txAcksBFfdFFJuY6)n}7g_fc`>T{~}ro ziGej;w(Gs%I!p_xh5E$%h{FRY3s}#V%0%mLwF@O2++?`L)mtn`m8wSp90abv6~Y61 zfGXwC{*#9aFAxLl`A45rl(SQ+U!jRS<|eP+;X6ODIp_Dd0IF_i<>`^c=%nCFcWUNO zVEsc}C(0k0Varwf82zbNOB_feR}NPt&Nc5a*1^|&&Yg?#gdRDrZqJBJq{;sL(RP*7 zm>-+7xYkv=&(}`u6n5^X1QRb?KFjr6{9NIq=WR?YS3RFswcE8F|C3k4TJ2Xl>X>39 z>)giht&(N#>91pA=id*NM`y%!N;1jYk6@hJ$f0vN0*gbWYpP1 z=ns7NO_?`2SU;$z?58gfx);|x-RBLR<+2FslY;Q(`fMq^s4jH+Y<@~?nrby`=Gq~X z(x#V78AIhQKGj@FmWytIi_w=;eg^$%St6a9xp$*Vx=lQ9g!J8X37hfy`BOpNp6Ds_ z$uZiy!GdocZEE>lJ%WhV#f3-$Es#f`Z(x2vKvnefF#$`yg%Q5p+HJeQlx-eHa95jg z>SVy$y(UUBPx;xXyzOv$p*JJ+D!%IrQw&l5E~b*B916Z%+k8H&>Go^ayJGPlcX&S( zZ}MK`)*Cc>?cOGp7UZ_@N|G1Gf`m0=fsJaQnQ}hnrn^PJx#EMk;0bAm-IkjPc|tF0 zqNAhZ!Z%Acev+i*u!_rNDZS)g9|dQ$(?7?!WFS3$`b#4>=!PNX`KjRi&hc(PhT-)6;E4n^nt=vSq*ZCW1<1^M--@PI>^~`D3 z?uQ+uk@2OTK;!sKeWgRD&GAd_`gWk45maC{IqA=H8$urO;1X^-lXo5?QssgC2L>LU zG*%grJ9z-s`<;+&@|~zpKj$Ir6dLBU!4==I!oT%O`>q9wQg_?))r#r?-|O}qG&&bq))L4=5fe9rl72Phdt#+`eQPfuh7Fj`*Ze$Ys1D0 zE@l7b6BS~Gn{cXMN6ZM(Q3DBPOCF1@&u8l5UBvzo5wnAPaR%Iax>=FXZ;E}G7Au1+ zjaH9wPRZ}_lCVSPq=xrnk;aNbHWoJZFxOqGvarw_U~YXF8F6dwgHuiWiwl-@aky7| zbsZQ9M>#J{J612IsqF9T7awpI<$DCUINvdWtphoW<4lApbFe7KFPzWIE``0{WM@WM Wc$(7rdABUx?exnWGNi-mk^cdjy|J$V literal 0 HcmV?d00001 From 6e383bc0d34896cf2e17d4047255c0c45de4d126 Mon Sep 17 00:00:00 2001 From: Sung Park Date: Tue, 8 Mar 2016 18:04:34 -0500 Subject: [PATCH 29/76] Add ruby image --- game_model.py | 9 +++++++-- motherload.py | 9 ++++++--- ruby.png | Bin 0 -> 2387 bytes 3 files changed, 13 insertions(+), 5 deletions(-) create mode 100644 ruby.png diff --git a/game_model.py b/game_model.py index 460567d..42f0de2 100644 --- a/game_model.py +++ b/game_model.py @@ -66,7 +66,10 @@ def __init__(self, left, top, width, height, first): self.color = "brown" else: self.color = choice(["red", "green", "orange", "blue", "purple"]) - self.image.fill((0,220,255)) + + if self.color == "red": + self.image = pygame.image.load('ruby.png').convert() + #self.image.fill((0,220,255)) else: self.rect.x = left self.rect.y = top @@ -197,12 +200,15 @@ def __init__(self): self.init_height_dist = 34 #number of rows of blocks self.init_width_dist = 32 #number of columns of blocks + self.sprite_list = pygame.sprite.Group() #a list of sprites to be drawn #initialize world for top in range(0,self.init_height_dist): self.world.append([]) for left in range(0,self.init_width_dist): brick = Brick(left, top, self.BRICK_WIDTH, self.BRICK_HEIGHT, True) self.world[top].append(brick) + if brick.color == "red": + self.sprite_list.add(brick) self.temp_world = self.world self.fuel = 500 @@ -220,7 +226,6 @@ def __init__(self): cheatcode = "dpapp" self.vehicle = Vehicle(40*8,40, 40, 40, cheatcode) - self.sprite_list = pygame.sprite.Group() #a list of sprites to be drawn self.fuel_station = FuelStation() self.sprite_list.add(self.fuel_station) self.shop = Shop() diff --git a/motherload.py b/motherload.py index 6cef1bf..dc6a52b 100644 --- a/motherload.py +++ b/motherload.py @@ -62,6 +62,8 @@ def draw(self): print "I am eating ...", brick.color if brick.color == "red": self.model.red_block += 1 + brick.image.fill((0,0,0)) + brick.image.set_colorkey((0,0,0)) elif brick.color == "green": self.model.green_block += 1 elif brick.color == "orange": @@ -75,6 +77,7 @@ def draw(self): else: pygame.draw.rect(self.screen, pygame.Color(brick.color), r) + r = pygame.Rect(self.model.vehicle.left,self.model.vehicle.top,self.model.vehicle.width,self.model.vehicle.height) #the mining vehicle @@ -270,7 +273,7 @@ def handle_event(self, event): for left in range(len(model.temp_world[top])): brick = model.temp_world[top][left] brick.top -= speed - brick.rect.y -= speed + brick.rect.y = brick.top model.fuel_station.top -= speed model.fuel_station.rect.y = model.fuel_station.top model.shop.top -= speed @@ -290,7 +293,7 @@ def handle_event(self, event): for left in range(len(model.temp_world[top])): brick = model.temp_world[top][left] brick.top -= speed - brick.rect.y -= speed + brick.rect.y = brick.top model.fuel_station.top -= speed model.fuel_station.rect.y = model.fuel_station.top model.shop.top -= speed @@ -301,7 +304,7 @@ def handle_event(self, event): for left in range(len(model.temp_world[top])): brick = model.temp_world[top][left] brick.top -= speed - brick.rect.y -= speed + brick.rect.y = brick.top model.fuel_station.top -= speed model.fuel_station.rect.y = model.fuel_station.top model.shop.top -= speed diff --git a/ruby.png b/ruby.png new file mode 100644 index 0000000000000000000000000000000000000000..6d9b51596419b0b95939acfe19c4469783b7f7b4 GIT binary patch literal 2387 zcmV-Z39R;sP)2x~Nb~=<&`UtT!LdDjC zfd-7)PeeaJlqM1-5Q8BYK^_H(N-$zgKn(&Sril?lOiYXcO$(t|rBhlSl@{syF^|ss zao^|cvzH(4o$2j#pp&*nKCo|g&bl`@d;Ru*t+gLVRF#i&GyiXZv$anE&$sy(c)TXy zCfnO}o7dbD<@fFF$i2BE&h6Ua^1F7raG+n~Fm~lI&JCEjy^P6Q@t*1#DL(y(s+(>= zxd26CDuXB24{Uz+;qcH0SC!uG^x~f5_?}1e`mdH7Zv1+3bo(~R?e1j!-FJ%vrQ)EA z?Zrh51w2X^@V${p z4L8Qyzj4#isIO;?l?ht6-g0Z3kABvA_StG_GDdvgH0B4Uc;1@`$7;nFO);h!{i!XN1U@1}gIS zR7dBMgNu&*?&;3=Hhy=Wh7|+=1t(w>5O7+Zx)W?ERTKcM)U$#7lg2jzcUeRi_P7gohDKUUA0fmH#ap01sWDFW%cGi zIjt1TqU&!+C2=WVReY2H#Ygc_42snCq;)6^%}Bv;q;F;CZ=U)>sGzPkjoLGiDYL3m zF3~)j&prQwmfzfB;_(rZQFIw1W1>3CDu_@6lhg7QAXBjbgEIo`+Pd|*;?YAyQ{X-d z(xfwdcGIu4@Zu9<$3{?9aB5Nwss9uTr8N#Atl+g7b+)m`7G>!&}ExLiV=s{*Q`PDvvRTpiqm9f{xs(q%iL z9%hCLS}&cZrK1D7y8%8Fa>>mbSbqJN*>~sdXc$tzrcPR_OJigtMrJz^Vj!*+mna0M zufu0oQ1iLAhLxWQE4|$b0O{#QfWAVBVpxTod-;{Dd+g`9g9mu;t~+pXJRR7CEk?}# z2wfAyq=Krrz*7@@f=~4v88|(=g8iEw%rxD&;c&Ea)nyn1#vol?hzP~mtz7lJ2U&UZ zhS9elxX1Qxer67}LYxL{5;$ozD!FQSV+5yCPI@jSD0o83_Xs?r?UiWwtbpTN|C+6w zI5xlImoJdtvzyYP{o0Yr46a`B>EoGY%R?>Z7uf!;i}ybFe7@+cdeEOVn$L(VsvoZ& zIEh>oi;qKah)sw~Ol(fhgH+%Vcrv!GtoE#crDB*Z?%vg$-2U1dbFRE{cB;AQ(l|HL z=K2n{a;YtI4C=`tTdar4Sf=9NGlI_L|dS@a?UsZ&n$5)~PYk=6vRVhkCj z`iV^q(8w9#offd1uQU#oqBoDp0+|-Dn6ISz!g&6yICs(L z>#yXJ39nIY4A!F7g0+nHjK&*YQgmKDpq{!qO+F{=tW(}G3Mw2CWxlQ2{{Eh^{q33La_2yuGL{P`6MOTo3vY!3BEXIE^Ub< z`8X!XWTsW{48SN^+~SO!u)as+8?0{_42&rhB4Raes(RHsoRBa9K@i{qpMFp2H;zGx z875{NM?sW|03HOsA(`;WX49;{^b*>$S-M;}?d53NOVd+xXD!9!-?1?%6;MRy^ybHc zh7=LD*+0&FxA8%>S9vUo1 zFRa^fple2e0KZ)*EhRVWafRzuq%~c!?>3ZlacFE)Brzg@999!Q#+|7Bsp}G*S-~OlVWB-Qr6TtIr{{=Bu76H1ktGECF002ovPDHLk FV1mZNm@5DP literal 0 HcmV?d00001 From 29d2d830305af59d1559a032b1cc1d7aa1c27921 Mon Sep 17 00:00:00 2001 From: "willem.thorbecke@students.olin.edu" Date: Tue, 8 Mar 2016 18:04:55 -0500 Subject: [PATCH 30/76] fixed infinite terrain --- game_model.py | 6 +++--- motherload.py | 44 ++++++++++++++++---------------------------- 2 files changed, 19 insertions(+), 31 deletions(-) diff --git a/game_model.py b/game_model.py index 2d6db89..f700dca 100644 --- a/game_model.py +++ b/game_model.py @@ -54,10 +54,10 @@ def __init__(self, left, top, width, height, first): if first: self.rect.x = left*width - width*9 #renders 9 extra columns of blocks off screen to the left - self.rect.y = top*height + height*2 #starts the world with a 2 block high sky - self.width = width + self.rect.y = top*height + height*2 - 1 #starts the world with a 2 block high sky + self.width = width self.height = height - self.top = top*height + height*2 + self.top = top*height + height*2 -1 self.left = left*width - width*9 random_seed = random.random() if random_seed < 0.1: diff --git a/motherload.py b/motherload.py index 05537cd..65dec0c 100644 --- a/motherload.py +++ b/motherload.py @@ -33,15 +33,10 @@ def draw(self): r = pygame.Rect(brick.left, brick.top, brick.width, brick.height) - # if pygame.sprite.collide_rect(brick, self.model.vehicle) and brick.rect.y > self.model.vehicle.rect.y and math.fabs(brick.rect.x - self.model.vehicle.rect.x) < 2: - # print "absolute ", math.fabs(self.model.vehicle.rect.x - brick.rect.x) - # print "colliding" - # print "brick, x ", brick.rect.x - # print "brick, y ", brick.rect.y - # print "veh x, ", self.model.vehicle.rect.x - # print "veh y, ", self.model.vehicle.rect.y + if pygame.sprite.collide_rect(brick, self.model.vehicle) and brick.rect.y > self.model.vehicle.rect.y and math.fabs(brick.rect.x - self.model.vehicle.rect.x) < 2: + - if brick.left == self.model.vehicle.left and brick.top <= self.model.vehicle.top + brick.height and brick.top + brick.height > self.model.vehicle.top + brick.height: + # if brick.left == self.model.vehicle.left and brick.top <= self.model.vehicle.top + brick.height and brick.top + brick.height > self.model.vehicle.top + brick.height: #checks if the vehicle overlaps a block, if so change block to black if brick.color != "black": @@ -51,14 +46,17 @@ def draw(self): else: self.model.can_move_down = True + # elif not pygame.sprite.collide_rect(brick, self.model.vehicle): + # self.model.can_move_down = False #print "can move down", self.model.can_move_down + if self.model.vehicle.left + float(brick.width)/2 < brick.left and brick.left + float(brick.width)/2 > self.model.vehicle.left and not (brick.left > self.model.vehicle.left + float(brick.width)*3/2) \ and brick.top > self.model.vehicle.top - brick.width/2 and brick.top + brick.height < self.model.vehicle.top + float(brick.width)*3/2: #checks if the vehicle has a block to the right if brick.color != "black" and not model.can_move_down: self.model.can_drill_right = True - # print "can move right", self.model.can_drill_right + #print "can move right", self.model.can_drill_right else: self.model.can_drill_right = False # print "can move right", self.model.can_drill_right @@ -68,7 +66,7 @@ def draw(self): # print "brick top", brick.top # print "veh top", self.model.vehicle.top # print "can drill right,", model.can_drill_right - + # print self.model.can_drill_right if brick.left == self.model.vehicle.left and self.model.vehicle.top > brick.top and self.model.vehicle.top + brick.height < brick.top + brick.height*2: #checks if the vehicle overlaps a block, if so change block to black if brick.color != "black" and brick.color != "brown": @@ -96,28 +94,16 @@ def draw(self): r = pygame.Rect(self.model.fuel_station.left,self.model.fuel_station.top,self.model.fuel_station.width,self.model.fuel_station.height) pygame.draw.rect(self.screen, pygame.Color('deep pink'),r) + self.model.sprite_list.draw(self.screen) r = pygame.Rect(self.model.shop.left,self.model.shop.top,self.model.shop.width,self.model.shop.height) - #pygame.draw.rect(self.screen, pygame.Color('yellow'), r) + #subpygame.draw.rect(self.screen, pygame.Color('yellow'), r) #Vehicle visiting fuel station if pygame.sprite.collide_rect(self.model.fuel_station, self.model.vehicle): self.model.fuel = self.model.max_fuel - #vehicle visiting shop - if pygame.sprite.collide_rect(self.model.shop, self.model.vehicle): - self.model.money += 100 * self.model.red_block - self.model.money += 100 * self.model.green_block - self.model.money += 100 * self.model.orange_block - self.model.money += 100 * self.model.blue_block - self.model.money += 100 * self.model.purple_block - self.model.red_block = 0 - self.model.green_block = 0 - self.model.orange_block = 0 - self.model.blue_block = 0 - self.model.purple_block = 0 - if self.model.fuel <= 0: msg = game_over_font.render("GAME OVER",1,(255,255,0)) @@ -142,7 +128,7 @@ def draw(self): screen.blit(purple_counter,(550,100)) money_counter = myFont.render("Money: " + str(self.model.money), 1, (255,255, 0)) - screen.blit(money_counter, (500,120)) + screen.blit(money_counter, (550,120)) pygame.display.update() @@ -283,7 +269,7 @@ def handle_event(self, event): for left in range(len(model.temp_world[top])): brick = model.temp_world[top][left] brick.top -= speed - brick.rect.y -= speed + brick.rect.y = brick.top model.fuel_station.top -= speed model.fuel_station.rect.y = model.fuel_station.top model.shop.top -= speed @@ -303,7 +289,7 @@ def handle_event(self, event): for left in range(len(model.temp_world[top])): brick = model.temp_world[top][left] brick.top -= speed - brick.rect.y -= speed + brick.rect.y = brick.top model.fuel_station.top -= speed model.fuel_station.rect.y = model.fuel_station.top model.shop.top -= speed @@ -314,7 +300,9 @@ def handle_event(self, event): for left in range(len(model.temp_world[top])): brick = model.temp_world[top][left] brick.top -= speed - brick.rect.y -= speed + brick.rect.y = brick.top + + model.fuel_station.top -= speed model.fuel_station.rect.y = model.fuel_station.top model.shop.top -= speed From f46eb35bc7c6aab4e5f4343d57c004f46a447752 Mon Sep 17 00:00:00 2001 From: "willem.thorbecke@students.olin.edu" Date: Tue, 8 Mar 2016 18:08:38 -0500 Subject: [PATCH 31/76] fixed terrain gen --- game_model.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/game_model.py b/game_model.py index f700dca..625cec4 100644 --- a/game_model.py +++ b/game_model.py @@ -194,8 +194,8 @@ def __init__(self): self.FAR_BOTTOM = self.SCREEN_HEIGHT + self.BRICK_HEIGHT*4 #the threshold for adding more blocks is 5 blocks from the bottom of the screen - self.init_height_dist = 34 #number of rows of blocks - self.init_width_dist = 32 #number of columns of blocks + self.init_height_dist = 32 #number of rows of blocks + self.init_width_dist = 34 #number of columns of blocks #initialize world for top in range(0,self.init_height_dist): From bf56ce1c7a7364231a5440f64d373dfd5ed2f276 Mon Sep 17 00:00:00 2001 From: Sung Park Date: Tue, 8 Mar 2016 18:11:46 -0500 Subject: [PATCH 32/76] Fix merge conflict --- motherload.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/motherload.py b/motherload.py index d3605e2..6cacb94 100644 --- a/motherload.py +++ b/motherload.py @@ -304,11 +304,6 @@ def handle_event(self, event): brick = model.temp_world[top][left] brick.top -= speed brick.rect.y = brick.top -<<<<<<< HEAD - - -======= ->>>>>>> 6e383bc0d34896cf2e17d4047255c0c45de4d126 model.fuel_station.top -= speed model.fuel_station.rect.y = model.fuel_station.top model.shop.top -= speed From e1e45cb10efd529c6d82dcc495d1c2808c6f68ae Mon Sep 17 00:00:00 2001 From: Sung Park Date: Tue, 8 Mar 2016 18:16:42 -0500 Subject: [PATCH 33/76] Add shop functionality --- motherload.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/motherload.py b/motherload.py index 6cacb94..f91742f 100644 --- a/motherload.py +++ b/motherload.py @@ -107,6 +107,18 @@ def draw(self): if pygame.sprite.collide_rect(self.model.fuel_station, self.model.vehicle): self.model.fuel = self.model.max_fuel + #Vehicle visiting shop + if pygame.sprite.collide_rect(self.model.shop, self.model.vehicle): + self.model.money += 100 * self.model.red_block + self.model.money += 100 * self.model.green_block + self.model.money += 100 * self.model.orange_block + self.model.money += 100 * self.model.blue_block + self.model.money += 100 * self.model.purple_block + self.model.red_block = 0 + self.model.green_block = 0 + self.model.orange_block = 0 + self.model.blue_block = 0 + self.model.purple_block = 0 if self.model.fuel <= 0: msg = game_over_font.render("GAME OVER",1,(255,255,0)) From 7e5cd183ca73f74c645cca3e6bfda13596f1f7a9 Mon Sep 17 00:00:00 2001 From: "willem.thorbecke@students.olin.edu" Date: Tue, 8 Mar 2016 18:18:00 -0500 Subject: [PATCH 34/76] fixed gravity --- motherload.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/motherload.py b/motherload.py index d3605e2..fbcb78b 100644 --- a/motherload.py +++ b/motherload.py @@ -304,19 +304,15 @@ def handle_event(self, event): brick = model.temp_world[top][left] brick.top -= speed brick.rect.y = brick.top -<<<<<<< HEAD - -======= ->>>>>>> 6e383bc0d34896cf2e17d4047255c0c45de4d126 model.fuel_station.top -= speed model.fuel_station.rect.y = model.fuel_station.top model.shop.top -= speed model.shop.rect.y = model.shop.top speed = speed + gravity - if speed > 10: - speed = 10 + if speed > 12: + speed -=.5 # elif keys[pygame.K_RIGHT]: # if not model.can_move_down: From 05a25be224965afa1b49e33df14004a39d7d2b6c Mon Sep 17 00:00:00 2001 From: Sung Park Date: Tue, 8 Mar 2016 18:26:13 -0500 Subject: [PATCH 35/76] make ruby image transparent --- game_model.py | 1 + 1 file changed, 1 insertion(+) diff --git a/game_model.py b/game_model.py index f2bc010..68ec5b1 100644 --- a/game_model.py +++ b/game_model.py @@ -68,6 +68,7 @@ def __init__(self, left, top, width, height, first): self.color = choice(["red", "green", "orange", "blue", "purple"]) if self.color == "red": self.image = pygame.image.load('ruby.png').convert() + self.image.set_colorkey((255,255,255)) #self.image.fill((0,220,255)) else: From 9030b29cab568b3521ac00171a35f79cff24e49a Mon Sep 17 00:00:00 2001 From: Sung Park Date: Tue, 8 Mar 2016 18:27:10 -0500 Subject: [PATCH 36/76] Fix merge conflict --- motherload.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/motherload.py b/motherload.py index 982af92..2566044 100644 --- a/motherload.py +++ b/motherload.py @@ -316,10 +316,6 @@ def handle_event(self, event): brick = model.temp_world[top][left] brick.top -= speed brick.rect.y = brick.top -<<<<<<< HEAD - -======= ->>>>>>> e1e45cb10efd529c6d82dcc495d1c2808c6f68ae model.fuel_station.top -= speed model.fuel_station.rect.y = model.fuel_station.top model.shop.top -= speed From 9294edc9aaaa77d8fbe98fa05ba577a7d75865a0 Mon Sep 17 00:00:00 2001 From: Sung Park Date: Tue, 8 Mar 2016 18:57:29 -0500 Subject: [PATCH 37/76] Add transparent ruby image --- game_model.py | 22 ++++++++++++++-------- motherload.py | 15 ++++++++------- 2 files changed, 22 insertions(+), 15 deletions(-) diff --git a/game_model.py b/game_model.py index 68ec5b1..0563968 100644 --- a/game_model.py +++ b/game_model.py @@ -62,11 +62,14 @@ def __init__(self, left, top, width, height, first): random_seed = random.random() if random_seed < 0.1: self.color = "black" + self.brick_type = "sky" elif random_seed <0.9: - self.color = "brown" + self.color = "brown" + self.brick_type = "soil" else: - self.color = choice(["red", "green", "orange", "blue", "purple"]) - if self.color == "red": + self.color = "brown" + self.brick_type = choice(["ruby", "emerald", "amazonite", "sapphire", "watsonite"]) + if self.brick_type == "ruby": self.image = pygame.image.load('ruby.png').convert() self.image.set_colorkey((255,255,255)) @@ -81,13 +84,16 @@ def __init__(self, left, top, width, height, first): random_seed = random.random() if random_seed < 0.1: self.color = "black" + self.brick_type = "sky" elif random_seed <0.9: - self.color = "brown" + self.color = "blue" + self.brick_type = "soil" else: - self.color = choice(["red", "green", "orange", "blue", "purple"]) - if self.color == "red": + self.color = "brown" + self.brick_type = choice(["ruby", "emerald", "amazonite", "sapphire", "watsonite"]) + if self.brick_type == "ruby": self.image = pygame.image.load('ruby.png').convert() - + self.image.set_colorkey((255,255,255)) #self.image.fill((0,220,255)) @@ -211,7 +217,7 @@ def __init__(self): for left in range(0,self.init_width_dist): brick = Brick(left, top, self.BRICK_WIDTH, self.BRICK_HEIGHT, True) self.world[top].append(brick) - if brick.color == "red": + if brick.brick_type == "ruby": self.sprite_list.add(brick) self.temp_world = self.world diff --git a/motherload.py b/motherload.py index 2566044..b53326e 100644 --- a/motherload.py +++ b/motherload.py @@ -69,21 +69,22 @@ def draw(self): # print self.model.can_drill_right if brick.left == self.model.vehicle.left and self.model.vehicle.top > brick.top and self.model.vehicle.top + brick.height < brick.top + brick.height*2: #checks if the vehicle overlaps a block, if so change block to black - if brick.color != "black" and brick.color != "brown": - print "I am eating ...", brick.color - if brick.color == "red": + if brick.brick_type != "sky" and brick.brick_type != "soil": + print "I am eating ...", brick.brick_type + if brick.brick_type == "ruby": self.model.red_block += 1 brick.image.fill((0,0,0)) brick.image.set_colorkey((0,0,0)) - elif brick.color == "green": + elif brick.brick_type == "emerald": self.model.green_block += 1 - elif brick.color == "orange": + elif brick.brick_type == "amazonite": self.model.orange_block += 1 - elif brick.color == "blue": + elif brick.brick_type == "sapphire": self.model.blue_block += 1 - elif brick.color == "purple": + elif brick.brick_type == "watsonite": self.model.purple_block += 1 brick.color = "black" + brick.brick_type = "sky" pygame.draw.rect(self.screen, pygame.Color(brick.color), r) else: From 2592b78ae8a8272832d6bf0c037f975aa7a24da0 Mon Sep 17 00:00:00 2001 From: Sung Park Date: Tue, 8 Mar 2016 20:10:04 -0500 Subject: [PATCH 38/76] Add all minerals --- amazonite.png | Bin 0 -> 2535 bytes emerald.png | Bin 0 -> 1848 bytes game_model.py | 24 ++++++++++++++++++++++-- motherload.py | 8 ++++++++ sapphire.png | Bin 0 -> 4175 bytes watsonite.png | Bin 0 -> 1685 bytes 6 files changed, 30 insertions(+), 2 deletions(-) create mode 100644 amazonite.png create mode 100644 emerald.png create mode 100644 sapphire.png create mode 100644 watsonite.png diff --git a/amazonite.png b/amazonite.png new file mode 100644 index 0000000000000000000000000000000000000000..3c4b0c20886d47933d288ad2c2094702c13fc19b GIT binary patch literal 2535 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 literal 0 HcmV?d00001 diff --git a/emerald.png b/emerald.png new file mode 100644 index 0000000000000000000000000000000000000000..32ba4f29dc09eeca7c2e23125a9c8491e527e9c4 GIT binary patch literal 1848 zcmY+Fc|6-mAIE=5NYs6m7DZbcJdQX^ibft+)>%|3)-5Wob=94?T8dRPj&U2rQJ2zOmZQ>&@hC>Sc&xE)s4(Y>%p6x!m|d zS@r9nT#D)qmj|sfa29^FJghB$nKYq&nK(!2;R)2*x8lc8gG1B`qQsmxV)LyakyY|8l%#I_@G>FvB)WJ|J zQiMA)0?s(gF6+JTxb%-W*mK9mjGD>jwFiN_1qcgG$cn-U^@h%~cbK+Jg2G6&)6fwkSik(0m70yO@nHye_ou z>V3v7XKYnrbie)SsJOV~uWR|yL0uL*_Nl96_Vfxv4Y)UyeguOOWEaX|aW5q9;mJ>G z8jl1$;>dp%94ahyNcXh$xE~V7MUA*b9&@!QX@16e;mSX-X8jRUf4gBx^d_CBJKL~f z!wGV52ioZrR$OwCo?3aIwC#W5^eRkAQ9D&p7?3m3$s^Sj)ym^;+|A?KOkm5;trga| zu<*H!gG$Q-MFxweu(@-N4SpA2thEo?W^XJ>nJhlw(sz z;&yAKCj0D49VH|B3vAtb2ziy%<-8v+gjZojh%$;DcgW7|)C69#vXa2v3^hGP$tyL> znPKx(ofV@A|D{0L`Nt-pms)m3z4@Mh4DC~P);3S7o?5qsXmiYJ7qYGC7cEPRHt`() zQm=WH`y0Bk_ID{Z`4#|p8fhe>FRgBKFu`Q3xEcbSAn!>_WqUI3# zNG#DDV~Uo#c1@|=2+!lt;)tS7SGK$TJ)aHZp4T-~beb91ZMY{~80*!(KYxmD1?xJj zQcmCHpz>m#Y}F7>BdNX}9x^0tpRA6( z5=GHXIlEmmd;(pqo=>8Dr%i>YLDlLXz@Na@Ldg~O3Ewcc41HEKI^hBGYR?PiVuIJ+ zs0SAuQS$=fg8)pF$MQaVO>cPv1G!)b=nac3ph?44^xTZPV2*u(Mj(y z6+iPWW%DxZEZxj<8iJ$N~{O?PCx(R4O zU+~F8TK-V4byz?Ck{KYuh>an<@04J0j^}Gc_*r#X@0UBTcXgBnAL5B;p#Dr74W9BD z8|KF#9b#Y?;^7+NiF6P0WE!A?P*znys3|CG*(j?Z5jT;_8VU$?BmzyTtzka<@*& literal 0 HcmV?d00001 diff --git a/game_model.py b/game_model.py index 0563968..664fa37 100644 --- a/game_model.py +++ b/game_model.py @@ -72,7 +72,18 @@ def __init__(self, left, top, width, height, first): if self.brick_type == "ruby": self.image = pygame.image.load('ruby.png').convert() self.image.set_colorkey((255,255,255)) - + elif self.brick_type == "emerald": + self.image = pygame.image.load('emerald.png').convert() + self.image.set_colorkey((0,0,0)) + elif self.brick_type == "amazonite": + self.image = pygame.image.load('amazonite.png').convert() + self.image.set_colorkey((0,0,0)) + elif self.brick_type == "sapphire": + self.image = pygame.image.load('sapphire.png').convert() + self.image.set_colorkey((0,0,0)) + elif self.brick_type == "watsonite": + self.image = pygame.image.load('watsonite.png').convert() + self.image.set_colorkey((255,255,255)) #self.image.fill((0,220,255)) else: self.rect.x = left @@ -94,6 +105,15 @@ def __init__(self, left, top, width, height, first): if self.brick_type == "ruby": self.image = pygame.image.load('ruby.png').convert() self.image.set_colorkey((255,255,255)) + elif self.brick_type == "emerald": + self.image = pygame.image.load('emerald.png').convert() + self.image.set_colorkey((0,0,0)) + elif self.brick_type == "amazonite": + self.image = pygame.image.load('amazonite.png').convert() + self.image.set_colorkey((0,0,0)) + elif self.brick_type == "sapphire": + self.image = pygame.image.load('sapphire.png').convert() + self.image.set_colorkey((0,0,0)) #self.image.fill((0,220,255)) @@ -217,7 +237,7 @@ def __init__(self): for left in range(0,self.init_width_dist): brick = Brick(left, top, self.BRICK_WIDTH, self.BRICK_HEIGHT, True) self.world[top].append(brick) - if brick.brick_type == "ruby": + if brick.brick_type != "sky" and brick.brick_type != "soil": self.sprite_list.add(brick) self.temp_world = self.world diff --git a/motherload.py b/motherload.py index b53326e..8df7901 100644 --- a/motherload.py +++ b/motherload.py @@ -77,12 +77,20 @@ def draw(self): brick.image.set_colorkey((0,0,0)) elif brick.brick_type == "emerald": self.model.green_block += 1 + brick.image.fill((0,0,0)) + brick.image.set_colorkey((0,0,0)) elif brick.brick_type == "amazonite": self.model.orange_block += 1 + brick.image.fill((0,0,0)) + brick.image.set_colorkey((0,0,0)) elif brick.brick_type == "sapphire": self.model.blue_block += 1 + brick.image.fill((0,0,0)) + brick.image.set_colorkey((0,0,0)) elif brick.brick_type == "watsonite": self.model.purple_block += 1 + brick.image.fill((0,0,0)) + brick.image.set_colorkey((0,0,0)) brick.color = "black" brick.brick_type = "sky" pygame.draw.rect(self.screen, pygame.Color(brick.color), r) diff --git a/sapphire.png b/sapphire.png new file mode 100644 index 0000000000000000000000000000000000000000..c6c835bc49558a60d8798df5800cb27c4b1c4118 GIT binary patch literal 4175 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 Date: Tue, 8 Mar 2016 21:26:04 -0500 Subject: [PATCH 39/76] improved collision detection --- game_model.py | 29 +---- motherload.py | 307 ++++++++++++++++++++++++++------------------------ 2 files changed, 159 insertions(+), 177 deletions(-) diff --git a/game_model.py b/game_model.py index f2bc010..404d32e 100644 --- a/game_model.py +++ b/game_model.py @@ -7,33 +7,6 @@ Class containing game model and all its components """ -# class Brick(object): -# """ Represents a brick in our brick breaker game """ -# def __init__(self, left, top, width, height, first): -# if first: -# self.left = left*width - width*9 #renders 9 extra columns of blocks off screen to the left -# self.top = top*height + height*2 #starts the world with a 2 block high sky -# self.width = width -# self.height = height -# random_seed = random.random() -# if random_seed < 0.1: -# self.color = "black" -# elif random_seed <0.9: -# self.color = "brown" -# else: -# self.color = choice(["red", "green", "orange", "blue", "purple"]) -# else: -# self.left = left -# self.top = top -# self.width = width -# self.height = height -# random_seed = random.random() -# if random_seed < 0.1: -# self.color = "black" -# elif random_seed <0.9: -# self.color = "brown" -# else: -# self.color = choice(["red", "green", "orange", "blue", "purple"]) class Brick(pygame.sprite.Sprite): @@ -166,6 +139,8 @@ def __init__(self, left, top, width, height, cheatcode): # Fetch the rectangle object that has the dimensions of the image # Update the position of this object by setting the values of rect.x and rect.y self.rect = self.image.get_rect() + self.can_drill_left = False + self.can_drill_right = False self.left = left self.top = top diff --git a/motherload.py b/motherload.py index 982af92..1439160 100644 --- a/motherload.py +++ b/motherload.py @@ -32,43 +32,41 @@ def draw(self): brick = self.model.temp_world[top][left] r = pygame.Rect(brick.left, brick.top, brick.width, brick.height) - - if pygame.sprite.collide_rect(brick, self.model.vehicle) and brick.rect.y > self.model.vehicle.rect.y and math.fabs(brick.rect.x - self.model.vehicle.rect.x) < 2: - - - # if brick.left == self.model.vehicle.left and brick.top <= self.model.vehicle.top + brick.height and brick.top + brick.height > self.model.vehicle.top + brick.height: + #pygame.sprite.collide_rect(brick, self.model.vehicle) + if self.model.vehicle.top + brick.height + 9 >= brick.top and self.model.vehicle.top < brick.top and math.fabs(brick.rect.x - self.model.vehicle.rect.x) < 9: #checks if the vehicle overlaps a block, if so change block to black if brick.color != "black": self.model.can_move_down = False - #print "can move down", model.can_move_down else: self.model.can_move_down = True - # elif not pygame.sprite.collide_rect(brick, self.model.vehicle): - # self.model.can_move_down = False - - #print "can move down", self.model.can_move_down - - - if self.model.vehicle.left + float(brick.width)/2 < brick.left and brick.left + float(brick.width)/2 > self.model.vehicle.left and not (brick.left > self.model.vehicle.left + float(brick.width)*3/2) \ - and brick.top > self.model.vehicle.top - brick.width/2 and brick.top + brick.height < self.model.vehicle.top + float(brick.width)*3/2: #checks if the vehicle has a block to the right - if brick.color != "black" and not model.can_move_down: - self.model.can_drill_right = True - #print "can move right", self.model.can_drill_right - else: - self.model.can_drill_right = False - # print "can move right", self.model.can_drill_right - # print "can move?", model.can_move_down - # print "vehicle left", self.model.vehicle.left - # print "brick left ", brick.left - # print "brick top", brick.top - # print "veh top", self.model.vehicle.top - # print "can drill right,", model.can_drill_right - # print self.model.can_drill_right - - if brick.left == self.model.vehicle.left and self.model.vehicle.top > brick.top and self.model.vehicle.top + brick.height < brick.top + brick.height*2: #checks if the vehicle overlaps a block, if so change block to black + + if (not model.can_move_down) and (brick.left + brick.width >= self.model.vehicle.left) \ + and (brick.left < self.model.vehicle.left) and math.fabs(brick.top-self.model.vehicle.top) < 9: #checks if the vehicles can/should drill left + + if brick.color != "black": + + self.model.vehicle.can_drill_left = True + else: + + self.model.vehicle.can_drill_left = False + + + if (not model.can_move_down) and (self.model.vehicle.left + brick.width >= brick.left) \ + and (self.model.vehicle.left < brick.left) and math.fabs(brick.top-self.model.vehicle.top) < 9: #checks if the vehicles can/should drill right + + if brick.color != "black": + + self.model.vehicle.can_drill_right = True + else: + + self.model.vehicle.can_drill_right = False + + + + if math.fabs(brick.left - self.model.vehicle.left) < 9 and math.fabs(self.model.vehicle.top - brick.top)<9: #and self.model.vehicle.top + brick.height < brick.top + brick.height*2: #checks if the vehicle overlaps a block, if so change block to black if brick.color != "black" and brick.color != "brown": print "I am eating ...", brick.color if brick.color == "red": @@ -83,6 +81,7 @@ def draw(self): self.model.blue_block += 1 elif brick.color == "purple": self.model.purple_block += 1 + brick.color = "black" pygame.draw.rect(self.screen, pygame.Color(brick.color), r) @@ -160,78 +159,49 @@ def handle_event(self, event): if event.type != KEYDOWN: return - # if event.key == pygame.K_UP: - # for top in range(len(self.model.temp_world)): - # for left in range(len(self.model.temp_world[top])): - # brick = self.model.temp_world[top][left] - # brick.top += brick.height*2 - # # if self.model.bricks[0][0].top - # self.model.fuel_station.top += self.model.BRICK_HEIGHT - - - # if event.key == pygame.K_DOWN: - # print self.model.temp_world[-1][0].top - # if self.model.temp_world[-1][0].top != self.model.FAR_BOTTOM: - # for top in range(len(self.model.temp_world)): - # for left in range(len(self.model.temp_world[top])): - # brick = self.model.temp_world[top][left] - # brick.top -= brick.height - # self.model.fuel_station.top -= self.model.BRICK_HEIGHT - # else: - # self.model.fuel_station.top -= self.model.BRICK_HEIGHT - # self.model.world_enlarger("down") - # for top in range(len(self.model.temp_world)): - # for left in range(len(self.model.temp_world[top])): - # brick = self.model.temp_world[top][left] - # brick.top -= brick.height - # #print self.model.temp_world[0][0].top - - - - #checking pressed keys - if event.key == pygame.K_LEFT: - if self.model.temp_world[0][0].left != self.model.FAR_LEFT: + # if event.key == pygame.K_LEFT: + # if self.model.temp_world[0][0].left != self.model.FAR_LEFT: - for top in range(len(self.model.temp_world)): - for left in range(len(self.model.temp_world[top])): - brick = self.model.temp_world[top][left] - brick.left += brick.width - brick.rect.x += brick.width #sprites stuff - self.model.fuel_station.left += self.model.BRICK_HEIGHT - self.model.fuel_station.rect.x += self.model.BRICK_HEIGHT - self.model.shop.left += self.model.BRICK_HEIGHT - self.model.shop.rect.x += self.model.BRICK_HEIGHT - # print self.model.fuel_station.left - # print self.model.fuel_station.rect.x + # for top in range(len(self.model.temp_world)): + # for left in range(len(self.model.temp_world[top])): + # brick = self.model.temp_world[top][left] + # brick.left += brick.width + # brick.rect.x += brick.width #sprites stuff + # self.model.fuel_station.left += self.model.BRICK_HEIGHT + # self.model.fuel_station.rect.x += self.model.BRICK_HEIGHT + # self.model.shop.left += self.model.BRICK_HEIGHT + # self.model.shop.rect.x += self.model.BRICK_HEIGHT + # # print self.model.fuel_station.left + # # print self.model.fuel_station.rect.x - else: - return + # else: + # return - #if farthest block to left reachest threshold, add more blocks to left - if self.model.temp_world[0][0].left == self.model.FAR_LEFT: - self.model.world_enlarger("left") + # #if farthest block to left reachest threshold, add more blocks to left + # if self.model.temp_world[0][0].left == self.model.FAR_LEFT: + # self.model.world_enlarger("left") - if event.key == pygame.K_RIGHT: - if self.model.world[0][-1].left != self.model.FAR_RIGHT: - for top in range(len(self.model.temp_world)): - for left in range(len(self.model.temp_world[top])): - brick = self.model.temp_world[top][left] - brick.left -= brick.width - brick.rect.x -= brick.width - self.model.fuel_station.left -= self.model.BRICK_HEIGHT - self.model.fuel_station.rect.x -= self.model.BRICK_HEIGHT - self.model.shop.left -= self.model.BRICK_HEIGHT - self.model.shop.rect.x -= self.model.BRICK_HEIGHT - # print self.model.fuel_station.left - # print self.model.fuel_station.rect.x - else: - return - if self.model.world[0][-1].left == self.model.FAR_RIGHT: - self.model.world_enlarger("right") + # if event.key == pygame.K_RIGHT: + # if self.model.world[0][-1].left != self.model.FAR_RIGHT: + # for top in range(len(self.model.temp_world)): + # for left in range(len(self.model.temp_world[top])): + # brick = self.model.temp_world[top][left] + # brick.left -= brick.width + # brick.rect.x -= brick.width + # self.model.fuel_station.left -= self.model.BRICK_HEIGHT + # self.model.fuel_station.rect.x -= self.model.BRICK_HEIGHT + # self.model.shop.left -= self.model.BRICK_HEIGHT + # self.model.shop.rect.x -= self.model.BRICK_HEIGHT + # # print self.model.fuel_station.left + # # print self.model.fuel_station.rect.x + # else: + # return + # if self.model.world[0][-1].left == self.model.FAR_RIGHT: + # self.model.world_enlarger("right") @@ -251,9 +221,11 @@ def handle_event(self, event): - speed = 0; - gravity = 0.5; + speed_y = 0; + speed_x=0; + gravity = 0.25; thruster = -0.05 + thruster_x = .025 pygame.init() size = (640, 480) screen = pygame.display.set_mode(size) @@ -270,6 +242,9 @@ def handle_event(self, event): controller.handle_event(event) model.can_drill_right = False + # print " can drill right?", model.vehicle.can_drill_right + # print " can drill left?", model.vehicle.can_drill_left + if model.temp_world[-1][0].top >= model.FAR_BOTTOM and model.temp_world[-1][0].top < model.FAR_BOTTOM + 40: mistake = model.FAR_BOTTOM - model.temp_world[-1][0].top @@ -283,87 +258,119 @@ def handle_event(self, event): for top in range(len(model.temp_world)): for left in range(len(model.temp_world[top])): brick = model.temp_world[top][left] - brick.top -= speed + brick.top -= speed_y brick.rect.y = brick.top - model.fuel_station.top -= speed + model.fuel_station.top -= speed_y model.fuel_station.rect.y = model.fuel_station.top - model.shop.top -= speed + model.shop.top -= speed_y model.shop.rect.y = model.shop.top - speed = speed + thruster; + speed_y = speed_y + thruster; + + if speed_y > 1: + speed_y = 0 + elif speed_y > 10: + speed_y = 10 + + if keys[pygame.K_LEFT] and model.vehicle.can_drill_left: + #print "somethings working??" + speed_x = .7 + for top in range(len(model.temp_world)): + for left in range(len(model.temp_world[top])): + brick = model.temp_world[top][left] + brick.left += speed_x + brick.rect.x = brick.left + model.fuel_station.left += speed_x + model.fuel_station.rect.x = model.fuel_station.left + model.shop.left += speed_x + model.shop.rect.x = model.shop.left + + if keys[pygame.K_LEFT] and not model.vehicle.can_drill_left: + speed_x = 2 + for top in range(len(model.temp_world)): + for left in range(len(model.temp_world[top])): + brick = model.temp_world[top][left] + brick.left += speed_x + brick.rect.x = brick.left + model.fuel_station.left += speed_x + model.fuel_station.rect.x = model.fuel_station.left + model.shop.left += speed_x + model.shop.rect.x = model.shop.left + + speed_x = speed_x + thruster_x; + + if speed_x > 1: + speed_x = 0 + elif speed_x > 10: + speed_x = 10 + + if keys[pygame.K_RIGHT] and model.vehicle.can_drill_right: + #print "somethings working??" + speed_x = .7 + for top in range(len(model.temp_world)): + for left in range(len(model.temp_world[top])): + brick = model.temp_world[top][left] + brick.left -= speed_x + brick.rect.x = brick.left + model.fuel_station.left -= speed_x + model.fuel_station.rect.x = model.fuel_station.left + model.shop.left -= speed_x + model.shop.rect.x = model.shop.left + + if keys[pygame.K_RIGHT] and not model.vehicle.can_drill_right: + speed_x = 2 + for top in range(len(model.temp_world)): + for left in range(len(model.temp_world[top])): + brick = model.temp_world[top][left] + brick.left -= speed_x + brick.rect.x = brick.left + model.fuel_station.left -= speed_x + model.fuel_station.rect.x = model.fuel_station.left + model.shop.left -= speed_x + model.shop.rect.x = model.shop.left + speed_x = speed_x + thruster_x; + + if speed_x > 1: + speed_x = 0 + elif speed_x > 10: + speed_x = 10 - if speed > 1: - speed = 0 - elif speed > 10: - speed = 10 elif keys[pygame.K_DOWN] and not model.can_move_down: # print "juss drilling" - speed = .7 + speed_y = .7 for top in range(len(model.temp_world)): for left in range(len(model.temp_world[top])): brick = model.temp_world[top][left] - brick.top -= speed + brick.top -= speed_y brick.rect.y = brick.top - model.fuel_station.top -= speed + model.fuel_station.top -= speed_y model.fuel_station.rect.y = model.fuel_station.top - model.shop.top -= speed + model.shop.top -= speed_y model.shop.rect.y = model.shop.top elif model.can_move_down and not keys[pygame.K_UP]: for top in range(len(model.temp_world)): for left in range(len(model.temp_world[top])): brick = model.temp_world[top][left] - brick.top -= speed + brick.top -= speed_y brick.rect.y = brick.top -<<<<<<< HEAD -======= ->>>>>>> e1e45cb10efd529c6d82dcc495d1c2808c6f68ae - model.fuel_station.top -= speed + model.fuel_station.top -= speed_y model.fuel_station.rect.y = model.fuel_station.top - model.shop.top -= speed + model.shop.top -= speed_y model.shop.rect.y = model.shop.top - speed = speed + gravity - if speed > 12: - speed -=.5 - - # elif keys[pygame.K_RIGHT]: - # if not model.can_move_down: - # speed = .7 - # for top in range(len(model.temp_world)): - # for left in range(len(model.temp_world[top])): - # brick = model.temp_world[top][left] - # brick.left -= speed - # model.fuel_station.left -= speed - - # else: - # for top in range(len(model.temp_world)): - # for left in range(len(model.temp_world[top])): - # brick = model.temp_world[top][left] - # brick.left -= speed - # model.fuel_station.left -= speed - - - # elif not model.can_move_down and keys[pygame.K_RIGHT]: - # speed = .7 - # for top in range(len(model.temp_world)): - # for left in range(len(model.temp_world[top])): - # brick = model.temp_world[top][left] - # brick.left -= speed - # model.fuel_station.left -= speed - - # elif not model.can_move_down and keys[pygame.K_LEFT]: - # speed = .7 - # for top in range(len(model.temp_world)): - # for left in range(len(model.temp_world[top])): - # brick = model.temp_world[top][left] - # brick.left += speed - # model.fuel_station.left += speed + speed_y = speed_y + gravity + if speed_y > 12: + speed_y -=.5 + + if not model.can_move_down and event.type != KEYDOWN: - speed = 0 + speed_y = 0 + if not model.vehicle.can_drill_left and not model.vehicle.can_drill_right and event.type != KEYDOWN: + speed_x = 0 model.fuel -= 1 #decrease fuel value every frame From b65b4ae44014f47adbaffb63fdfe135385df1b7a Mon Sep 17 00:00:00 2001 From: Sung Park Date: Tue, 8 Mar 2016 21:34:10 -0500 Subject: [PATCH 40/76] Changed typo --- game_model.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/game_model.py b/game_model.py index 664fa37..41b2f28 100644 --- a/game_model.py +++ b/game_model.py @@ -97,7 +97,7 @@ def __init__(self, left, top, width, height, first): self.color = "black" self.brick_type = "sky" elif random_seed <0.9: - self.color = "blue" + self.color = "brown" self.brick_type = "soil" else: self.color = "brown" @@ -114,6 +114,9 @@ def __init__(self, left, top, width, height, first): elif self.brick_type == "sapphire": self.image = pygame.image.load('sapphire.png').convert() self.image.set_colorkey((0,0,0)) + elif self.brick_type == "watsonite": + self.image = pygame.image.load('watsonite.png').convert() + self.image.set_colorkey((255,255,255)) #self.image.fill((0,220,255)) From d644bd54cd545ec8129fcd67f97b2c8e302d58c9 Mon Sep 17 00:00:00 2001 From: "willem.thorbecke@students.olin.edu" Date: Tue, 8 Mar 2016 21:48:15 -0500 Subject: [PATCH 41/76] fixed full station --- motherload.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/motherload.py b/motherload.py index 6aa41e9..d114312 100644 --- a/motherload.py +++ b/motherload.py @@ -357,6 +357,7 @@ def handle_event(self, event): brick = model.temp_world[top][left] brick.left -= speed_x brick.rect.x = brick.left + model.fuel_station.left -= speed_x model.fuel_station.rect.x = model.fuel_station.left model.shop.left -= speed_x @@ -390,11 +391,10 @@ def handle_event(self, event): brick.rect.y = brick.top - model.fuel_station.top -= speed_y - model.fuel_station.top -= speed_y model.fuel_station.rect.y = model.fuel_station.top + model.shop.top -= speed_y model.shop.rect.y = model.shop.top From 8252b35eea02beffa9c6a052dc2369e995d15100 Mon Sep 17 00:00:00 2001 From: Sung Park Date: Tue, 8 Mar 2016 21:50:37 -0500 Subject: [PATCH 42/76] Fix a bug in which the enlarged world is blue --- game_model.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/game_model.py b/game_model.py index a235311..05d9f20 100644 --- a/game_model.py +++ b/game_model.py @@ -67,7 +67,7 @@ def __init__(self, left, top, width, height, first): self.height = height random_seed = random.random() if random_seed < 0.1: - self.color = "black" + self.color = "brown" self.brick_type = "sky" elif random_seed <0.9: self.color = "brown" @@ -90,6 +90,7 @@ def __init__(self, left, top, width, height, first): elif self.brick_type == "watsonite": self.image = pygame.image.load('watsonite.png').convert() self.image.set_colorkey((255,255,255)) + self.color = "brown" #self.image.fill((0,220,255)) @@ -256,6 +257,8 @@ def world_enlarger(self, what_side): brick = Brick(self.world[0][0].left+left*self.BRICK_WIDTH, self.world[-2][0].top + self.BRICK_HEIGHT, self.BRICK_WIDTH, self.BRICK_HEIGHT, False) self.world[-1].append(brick) + if brick.brick_type != "soil": + self.sprite_list.add(brick) def get_elapsed_time(self): return pygame.time.get_ticks() From ea173e1e8c3c6ed02126080a1721fe5f431e17a2 Mon Sep 17 00:00:00 2001 From: Sung Park Date: Tue, 8 Mar 2016 21:59:12 -0500 Subject: [PATCH 43/76] Fix a bug that makes empty holes to be not generated --- game_model.py | 9 ++++----- motherload.py | 4 ++-- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/game_model.py b/game_model.py index 05d9f20..a88f686 100644 --- a/game_model.py +++ b/game_model.py @@ -35,7 +35,7 @@ def __init__(self, left, top, width, height, first): random_seed = random.random() if random_seed < 0.1: self.color = "black" - self.brick_type = "sky" + self.brick_type = "empty" elif random_seed <0.9: self.color = "brown" self.brick_type = "soil" @@ -67,8 +67,8 @@ def __init__(self, left, top, width, height, first): self.height = height random_seed = random.random() if random_seed < 0.1: - self.color = "brown" - self.brick_type = "sky" + self.color = "black" + self.brick_type = "empty" elif random_seed <0.9: self.color = "brown" self.brick_type = "soil" @@ -90,7 +90,6 @@ def __init__(self, left, top, width, height, first): elif self.brick_type == "watsonite": self.image = pygame.image.load('watsonite.png').convert() self.image.set_colorkey((255,255,255)) - self.color = "brown" #self.image.fill((0,220,255)) @@ -257,7 +256,7 @@ def world_enlarger(self, what_side): brick = Brick(self.world[0][0].left+left*self.BRICK_WIDTH, self.world[-2][0].top + self.BRICK_HEIGHT, self.BRICK_WIDTH, self.BRICK_HEIGHT, False) self.world[-1].append(brick) - if brick.brick_type != "soil": + if brick.brick_type != "soil" and brick.brick_type != "empty": self.sprite_list.add(brick) def get_elapsed_time(self): diff --git a/motherload.py b/motherload.py index d114312..a714609 100644 --- a/motherload.py +++ b/motherload.py @@ -90,7 +90,7 @@ def draw(self): # print self.model.can_drill_right if math.fabs(brick.left - self.model.vehicle.left) < 9 and math.fabs(self.model.vehicle.top - brick.top)<9: #checks if the vehicle overlaps a block, if so change block to black - if brick.brick_type != "sky" and brick.brick_type != "soil": + if brick.brick_type != "empty" and brick.brick_type != "soil": print "I am eating ...", brick.brick_type if brick.brick_type == "ruby": self.model.red_block += 1 @@ -115,7 +115,7 @@ def draw(self): brick.image.set_colorkey((0,0,0)) brick.color = "black" - brick.brick_type = "sky" + brick.brick_type = "empty" pygame.draw.rect(self.screen, pygame.Color(brick.color), r) else: From c45a3ae43279b4c08134f85753706c419c057023 Mon Sep 17 00:00:00 2001 From: "willem.thorbecke@students.olin.edu" Date: Tue, 8 Mar 2016 23:05:42 -0500 Subject: [PATCH 44/76] idk what this is --- motherload.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/motherload.py b/motherload.py index d114312..1dd604f 100644 --- a/motherload.py +++ b/motherload.py @@ -33,9 +33,11 @@ def draw(self): r = pygame.Rect(brick.left, brick.top, brick.width, brick.height) #pygame.sprite.collide_rect(brick, self.model.vehicle) - if self.model.vehicle.top + brick.height + 9 >= brick.top and self.model.vehicle.top < brick.top and math.fabs(brick.rect.x - self.model.vehicle.rect.x) < 9: + #check for overlap in x direct: + #if self.model.vehicle.can_drill_right and (self.model.vehicle.left < brick.left) - #checks if the vehicle overlaps a block, if so change block to black + if self.model.vehicle.top + brick.height + 2 >= brick.top and self.model.vehicle.top < brick.top and math.fabs(brick.rect.x - self.model.vehicle.rect.x) < 9: #checks for collision underneath + if brick.color != "black": self.model.can_move_down = False @@ -357,7 +359,7 @@ def handle_event(self, event): brick = model.temp_world[top][left] brick.left -= speed_x brick.rect.x = brick.left - + model.fuel_station.left -= speed_x model.fuel_station.rect.x = model.fuel_station.left model.shop.left -= speed_x From 7c4b9bd924a703e7011996e0c4d85e4191ac5a78 Mon Sep 17 00:00:00 2001 From: Sung Park Date: Tue, 8 Mar 2016 23:09:00 -0500 Subject: [PATCH 45/76] Fix empty spot glitch --- game_model.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/game_model.py b/game_model.py index a88f686..e574dfd 100644 --- a/game_model.py +++ b/game_model.py @@ -215,7 +215,7 @@ def __init__(self): for left in range(0,self.init_width_dist): brick = Brick(left, top, self.BRICK_WIDTH, self.BRICK_HEIGHT, True) self.world[top].append(brick) - if brick.brick_type != "sky" and brick.brick_type != "soil": + if brick.brick_type != "empty" and brick.brick_type != "soil": self.sprite_list.add(brick) self.temp_world = self.world From 165ff63db74c1eb2a0d86b9abf860d6a16fdf0a7 Mon Sep 17 00:00:00 2001 From: "willem.thorbecke@students.olin.edu" Date: Wed, 9 Mar 2016 20:33:11 -0500 Subject: [PATCH 46/76] made vehicle smaller --- game_model.py | 2 +- motherload.py | 9 ++++----- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/game_model.py b/game_model.py index e574dfd..788d6f8 100644 --- a/game_model.py +++ b/game_model.py @@ -232,7 +232,7 @@ def __init__(self): self.money = 0 cheatcode = "dpapp" - self.vehicle = Vehicle(40*8,40, 40, 40, cheatcode) + self.vehicle = Vehicle(40*8,30, 30, 30, cheatcode) self.fuel_station = FuelStation() self.sprite_list.add(self.fuel_station) diff --git a/motherload.py b/motherload.py index 0851387..e3d92f7 100644 --- a/motherload.py +++ b/motherload.py @@ -32,12 +32,11 @@ def draw(self): brick = self.model.temp_world[top][left] r = pygame.Rect(brick.left, brick.top, brick.width, brick.height) - #pygame.sprite.collide_rect(brick, self.model.vehicle) - #check for overlap in x direct: - #if self.model.vehicle.can_drill_right and (self.model.vehicle.left < brick.left) + - if self.model.vehicle.top + brick.height + 2 >= brick.top and self.model.vehicle.top < brick.top and math.fabs(brick.rect.x - self.model.vehicle.rect.x) < 9: #checks for collision underneath - + #checks if the bottom of the vehicle + 6 is more than or equal to the top of a brick and the top of the vehicle is less than the top of that brick and if its the brick in the same column + if self.model.vehicle.top + self.model.vehicle.height + 6 >= brick.top and self.model.vehicle.top < brick.top and math.fabs(brick.rect.x - self.model.vehicle.rect.x) < 9: + #if that brick isn't black, then the vehicle cant move if brick.color != "black": self.model.can_move_down = False From 5b3ca2a64bf362ee2a2c97ad272698ee5276aaea Mon Sep 17 00:00:00 2001 From: "willem.thorbecke@students.olin.edu" Date: Wed, 9 Mar 2016 20:40:08 -0500 Subject: [PATCH 47/76] fixed gravity bug --- game_model.py | 2 +- motherload.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/game_model.py b/game_model.py index 788d6f8..c347d53 100644 --- a/game_model.py +++ b/game_model.py @@ -193,7 +193,7 @@ class BrickBreakerModel(object): def __init__(self): #self.bricks = [][] self.enlarger_helper = None - self.can_move_down = False #checks if the blocks free to fall downward + self.can_move_down = True #checks if the blocks free to fall downward self.world = [] self.MARGIN = 0 self.BRICK_WIDTH = 40 diff --git a/motherload.py b/motherload.py index e3d92f7..0ad3e4c 100644 --- a/motherload.py +++ b/motherload.py @@ -35,7 +35,7 @@ def draw(self): #checks if the bottom of the vehicle + 6 is more than or equal to the top of a brick and the top of the vehicle is less than the top of that brick and if its the brick in the same column - if self.model.vehicle.top + self.model.vehicle.height + 6 >= brick.top and self.model.vehicle.top < brick.top and math.fabs(brick.rect.x - self.model.vehicle.rect.x) < 9: + if self.model.vehicle.top + self.model.vehicle.height + 6 >= brick.top and self.model.vehicle.top < brick.top and brick.rect.x-self.model.vehicle.rect.x < 9: #if that brick isn't black, then the vehicle cant move if brick.color != "black": self.model.can_move_down = False From adc9e08691bf13df589e30c5dcea51c95e54f308 Mon Sep 17 00:00:00 2001 From: "willem.thorbecke@students.olin.edu" Date: Wed, 9 Mar 2016 20:42:37 -0500 Subject: [PATCH 48/76] digging a little better --- motherload.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/motherload.py b/motherload.py index 0ad3e4c..ee08292 100644 --- a/motherload.py +++ b/motherload.py @@ -90,7 +90,7 @@ def draw(self): # print "can drill right,", model.can_drill_right # print self.model.can_drill_right - if math.fabs(brick.left - self.model.vehicle.left) < 9 and math.fabs(self.model.vehicle.top - brick.top)<9: #checks if the vehicle overlaps a block, if so change block to black + if math.fabs(brick.left - self.model.vehicle.left) < 20 and math.fabs(self.model.vehicle.top - brick.top)<20: #checks if the vehicle overlaps a block, if so change block to black if brick.brick_type != "empty" and brick.brick_type != "soil": print "I am eating ...", brick.brick_type if brick.brick_type == "ruby": From c4f3a1d5dcc1cd182c847c5703632367a59780e5 Mon Sep 17 00:00:00 2001 From: Sung Park Date: Wed, 9 Mar 2016 20:55:59 -0500 Subject: [PATCH 49/76] Add workshop --- game_model.py | 16 ++++++++++++++++ motherload.py | 16 ++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/game_model.py b/game_model.py index c347d53..c48a5ec 100644 --- a/game_model.py +++ b/game_model.py @@ -126,7 +126,21 @@ def __init__(self): self.rect.y = 40 +class Workshop(pygame.sprite.Sprite): + """ + Workshop tile where the vehicle can upgrade its fuel tank + """ + def __init__(self): + pygame.sprite.Sprite.__init__(self) + self.image = pygame.image.load('workshop.png') + self.rect = self.image.get_rect() + self.left = 560 + self.top = 40 + self.width = 40 + self.height = 40 + self.rect.x = 560 + self.rect.y = 40 class Shop(pygame.sprite.Sprite): @@ -238,6 +252,8 @@ def __init__(self): self.sprite_list.add(self.fuel_station) self.shop = Shop() self.sprite_list.add(self.shop) + self.workshop = Workshop() + self.sprite_list.add(self.workshop) def world_enlarger(self, what_side): diff --git a/motherload.py b/motherload.py index 0ad3e4c..ccf1eee 100644 --- a/motherload.py +++ b/motherload.py @@ -298,6 +298,8 @@ def handle_event(self, event): model.fuel_station.rect.y = model.fuel_station.top model.shop.top -= speed_y model.shop.rect.y = model.shop.top + model.workshop.top -= speed_y + model.workshop.rect.y = model.workshop.top speed_y = speed_y + thruster; @@ -318,6 +320,8 @@ def handle_event(self, event): model.fuel_station.rect.x = model.fuel_station.left model.shop.left += speed_x model.shop.rect.x = model.shop.left + model.workshop.left += speed_x + model.workshop.rect.x = model.workshop.left if keys[pygame.K_LEFT] and not model.vehicle.can_drill_left: speed_x = 2 @@ -330,6 +334,8 @@ def handle_event(self, event): model.fuel_station.rect.x = model.fuel_station.left model.shop.left += speed_x model.shop.rect.x = model.shop.left + model.workshop.left += speed_x + model.workshop.rect.x = model.workshop.left speed_x = speed_x + thruster_x; @@ -350,6 +356,8 @@ def handle_event(self, event): model.fuel_station.rect.x = model.fuel_station.left model.shop.left -= speed_x model.shop.rect.x = model.shop.left + model.workshop.left -= speed_x + model.workshop.rect.x = model.workshop.left if keys[pygame.K_RIGHT] and not model.vehicle.can_drill_right: speed_x = 2 @@ -363,6 +371,9 @@ def handle_event(self, event): model.fuel_station.rect.x = model.fuel_station.left model.shop.left -= speed_x model.shop.rect.x = model.shop.left + model.workshop.left -= speed_x + model.workshop.rect.x = model.workshop.left + speed_x = speed_x + thruster_x; if speed_x > 1: @@ -383,6 +394,8 @@ def handle_event(self, event): model.fuel_station.rect.y = model.fuel_station.top model.shop.top -= speed_y model.shop.rect.y = model.shop.top + model.workshop.top -= speed_y + model.workshop.rect.y = model.workshop.top elif model.can_move_down and not keys[pygame.K_UP]: for top in range(len(model.temp_world)): @@ -399,6 +412,9 @@ def handle_event(self, event): model.shop.top -= speed_y model.shop.rect.y = model.shop.top + model.workshop.top -= speed_y + model.workshop.rect.y = model.workshop.top + speed_y = speed_y + gravity if speed_y > 12: speed_y -=.5 From 93c0e50703209b169098981ba06ee2dbc15bb7d6 Mon Sep 17 00:00:00 2001 From: "willem.thorbecke@students.olin.edu" Date: Wed, 9 Mar 2016 20:57:06 -0500 Subject: [PATCH 50/76] saving work --- game_model.py | 1 + motherload.py | 14 +++++++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/game_model.py b/game_model.py index c347d53..aa235e8 100644 --- a/game_model.py +++ b/game_model.py @@ -171,6 +171,7 @@ def __init__(self, left, top, width, height, cheatcode): self.rect = self.image.get_rect() self.can_drill_left = False self.can_drill_right = False + self.can_drill_down = False self.left = left self.top = top diff --git a/motherload.py b/motherload.py index ee08292..e7d2167 100644 --- a/motherload.py +++ b/motherload.py @@ -44,6 +44,17 @@ def draw(self): else: self.model.can_move_down = True + if self.model.vehicle.top + self.model.vehicle.height + 6 >= brick.top and self.model.vehicle.top < brick.top and brick.rect.x-self.model.vehicle.rect.x < 9: + print "x side of brick", brick.rect.x + print "x side of vehicle", self.model.vehicle.rect.x + print self.model.vehicle.can_drill_down + if brick.color != "black" and self.model.vehicle.rect.x - brick.rect.x < 9: + self.model.vehicle.can_drill_down = True + + else: + self.model.vehicle.can_drill_down = False + + if (not model.can_move_down) and (brick.left + brick.width >= self.model.vehicle.left) \ and (brick.left < self.model.vehicle.left) and math.fabs(brick.top-self.model.vehicle.top) < 9: #checks if the vehicles can/should drill left @@ -54,6 +65,7 @@ def draw(self): else: self.model.vehicle.can_drill_left = False + if (not model.can_move_down) and (self.model.vehicle.left + brick.width >= brick.left) \ @@ -278,7 +290,7 @@ def handle_event(self, event): # print " can drill right?", model.vehicle.can_drill_right # print " can drill left?", model.vehicle.can_drill_left - + print "can drill down? ", model.vehicle.can_drill_down if model.temp_world[-1][0].top >= model.FAR_BOTTOM and model.temp_world[-1][0].top < model.FAR_BOTTOM + 40: mistake = model.FAR_BOTTOM - model.temp_world[-1][0].top From 0654ce58ce581ea55c11e0e1cd3f84089b8be94a Mon Sep 17 00:00:00 2001 From: Sung Park Date: Wed, 9 Mar 2016 20:57:34 -0500 Subject: [PATCH 51/76] Add workshop image --- workshop.png | Bin 0 -> 1503 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 workshop.png diff --git a/workshop.png b/workshop.png new file mode 100644 index 0000000000000000000000000000000000000000..c508e2092df2e39d7e4cb2d304e7ae98b9d0e4f9 GIT binary patch literal 1503 zcmV<51t9u~P)vIV>o3qjX;w&lQv>XnV_Sk0!{{%R*F)gWg@;! zanlA7e1O6(%kJL2_nzBXmj(ouQTFaPcXoF7oO^!f`_BJ--#JiG6yU>T$yIZ`a&PI` z>e{A0J@hjsK5a1e0xB8w1-^0P^4yHVGgoYq3;|H+XYWwvV79q?j{&NHk*@}~TPUlr zAq062@EkPqpw=oSEZkLh>r!CBk&%Oov&M@ekxBDE91Ch~^62FJx?2?i47JxRmg5PF ze?SnT|7R#jFwBS#Y?u}r9vu*my*6;*(4tQg+)~Trw2X4oDvw>V+tpYVKrpqq*yl#X z7~K-|{-jgTvdYyv==YLCfdzYEZA^o~SEPoFLG)ua4G$&qu78s;9lBr9W| z>gN|&A;N;yMF~sxm6ZP6zWL&X!;@B&vdleyN(4oROHt8J`US4PU3t>t&})G?{pj)X zk~Y+Y)M5q$1n+rAknxO>p;&A33%sYeoG1t*MaO|DD}LL%zesZ1WyyK;uU{w?W5~3V z0R-~oQL%pRW2U0gO1CK$5Os@&^zBbi#(sN&!KmEg(6H3kw!(7D==n#`LxV>6o4H~K zgt%qkjU{DkHQ-#OaO#SaerXfoW_KY?qUhKC1(r)?Kp|bvTtd_Ju_?I~)e_Hkn!{RG zEd@G6i~(6bz2~xdGa=@?m@@4Rl~b1O{QH{7vqZV?H)&6s11)^nl(}>cVuHG|j}0Mx z3)h;Xdod2NgXmI#NHBfcNel$@TtP=~D@NFp2BSBt9FK@XX_V9v`#}=8Pz+yZ~q~fYaZy%t&1_U@>mA8 z-(by?cCjfFG%Hi*Lnc^-dfdv$?xMWpb^jQ70)6zL?6+RjtV*MP2i@-)-;WxmPkwFf zf+(v4`vl-`uLS`JJyfdcbYZniJ<_ zEsC%@Xqkk*{N8*($XLHwk?rb%@4{y!zPT>Bhuw*Mv5i`B<6hT?Yc~FKK6I%5Yv78!E2=!lJD z6)*LJS51rNF68uKEN9T_!-mJl%Z+CapZ6RgfM`WPErV>*)Y%)BLhVG>r-9; z5Vh_wfBGl}$r^@~Sp@aKcgLPOZj7EI^c=%$h(;UIrkOW{8niUmg8C*!T`&-3hSPX7 zW_2K^z3r{8uC~%sV-yh44XX^+8$u@xHwmIg;h8z5M6|XX5ykq$E(wi@;nh-g zi(RWa7B~AR1FyJ5{L)a}QggiC5MghuUh~b#;?n|M`z8UN*)m3buqUPDZ(IIF6+H^N zWja2+*2+#drom;g(%@vWQ^J#`%?kwBQ?_?}mzS1(nE*_$nb3Pwl@W&0`gi&zPMQfI z6BzJayIFIhVE?J3=Np^?;kD?AK}PfV_@2Gvy{-QVFaWZJa=9zkal8Nk002ovPDHLk FV1n?p@-YAa literal 0 HcmV?d00001 From d9602d4af1d28d83691094992117cb1754da6631 Mon Sep 17 00:00:00 2001 From: Sung Park Date: Wed, 9 Mar 2016 21:09:23 -0500 Subject: [PATCH 52/76] Add functionality for workshop --- game_model.py | 2 +- motherload.py | 10 ++++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/game_model.py b/game_model.py index c48a5ec..f9f1211 100644 --- a/game_model.py +++ b/game_model.py @@ -233,7 +233,7 @@ def __init__(self): self.sprite_list.add(brick) self.temp_world = self.world - self.fuel = 500 + self.fuel = 1000 self.max_fuel = 1000 #counter for minerals diff --git a/motherload.py b/motherload.py index a2882ce..0732854 100644 --- a/motherload.py +++ b/motherload.py @@ -152,7 +152,13 @@ def draw(self): self.model.orange_block = 0 self.model.blue_block = 0 self.model.purple_block = 0 - + + #Vehicle visiting workshop + if pygame.sprite.collide_rect(self.model.workshop, self.model.vehicle): + if self.model.money >= 500: + self.model.money -= 500 + self.model.max_fuel += 500 + if self.model.fuel <= 0: msg = game_over_font.render("GAME OVER",1,(255,255,0)) screen.blit(msg, (0, 240)) @@ -176,7 +182,7 @@ def draw(self): screen.blit(purple_counter,(550,100)) money_counter = myFont.render("Money: " + str(self.model.money), 1, (255,255, 0)) - screen.blit(money_counter, (550,120)) + screen.blit(money_counter, (540,120)) pygame.display.update() From 99e55ea46cf4cc997d0d24a98adc53534147d531 Mon Sep 17 00:00:00 2001 From: "willem.thorbecke@students.olin.edu" Date: Wed, 9 Mar 2016 21:10:51 -0500 Subject: [PATCH 53/76] broke gravity again --- motherload.py | 24 ++++-------------------- 1 file changed, 4 insertions(+), 20 deletions(-) diff --git a/motherload.py b/motherload.py index 4fe1d46..142457f 100644 --- a/motherload.py +++ b/motherload.py @@ -35,7 +35,7 @@ def draw(self): #checks if the bottom of the vehicle + 6 is more than or equal to the top of a brick and the top of the vehicle is less than the top of that brick and if its the brick in the same column - if self.model.vehicle.top + self.model.vehicle.height + 6 >= brick.top and self.model.vehicle.top < brick.top and brick.rect.x-self.model.vehicle.rect.x < 9: + if self.model.vehicle.top + self.model.vehicle.height + 6 >= brick.top and self.model.vehicle.top < brick.top and brick.rect.x < self.model.vehicle.rect.x and brick.rect.x + brick.width > self.model.vehicle.rect.x + self.model.vehicle.width: #if that brick isn't black, then the vehicle cant move if brick.color != "black": self.model.can_move_down = False @@ -44,11 +44,11 @@ def draw(self): else: self.model.can_move_down = True - if self.model.vehicle.top + self.model.vehicle.height + 6 >= brick.top and self.model.vehicle.top < brick.top and brick.rect.x-self.model.vehicle.rect.x < 9: + if self.model.vehicle.top + self.model.vehicle.height + 6 >= brick.top and self.model.vehicle.top < brick.top and brick.rect.x < self.model.vehicle.rect.x and brick.rect.x + brick.width > self.model.vehicle.rect.x + self.model.vehicle.width: print "x side of brick", brick.rect.x print "x side of vehicle", self.model.vehicle.rect.x - print self.model.vehicle.can_drill_down - if brick.color != "black" and self.model.vehicle.rect.x - brick.rect.x < 9: + #print self.model.vehicle.can_drill_down + if brick.color != "black": self.model.vehicle.can_drill_down = True else: @@ -310,8 +310,6 @@ def handle_event(self, event): model.fuel_station.rect.y = model.fuel_station.top model.shop.top -= speed_y model.shop.rect.y = model.shop.top - model.workshop.top -= speed_y - model.workshop.rect.y = model.workshop.top speed_y = speed_y + thruster; @@ -332,8 +330,6 @@ def handle_event(self, event): model.fuel_station.rect.x = model.fuel_station.left model.shop.left += speed_x model.shop.rect.x = model.shop.left - model.workshop.left += speed_x - model.workshop.rect.x = model.workshop.left if keys[pygame.K_LEFT] and not model.vehicle.can_drill_left: speed_x = 2 @@ -346,8 +342,6 @@ def handle_event(self, event): model.fuel_station.rect.x = model.fuel_station.left model.shop.left += speed_x model.shop.rect.x = model.shop.left - model.workshop.left += speed_x - model.workshop.rect.x = model.workshop.left speed_x = speed_x + thruster_x; @@ -368,8 +362,6 @@ def handle_event(self, event): model.fuel_station.rect.x = model.fuel_station.left model.shop.left -= speed_x model.shop.rect.x = model.shop.left - model.workshop.left -= speed_x - model.workshop.rect.x = model.workshop.left if keys[pygame.K_RIGHT] and not model.vehicle.can_drill_right: speed_x = 2 @@ -383,9 +375,6 @@ def handle_event(self, event): model.fuel_station.rect.x = model.fuel_station.left model.shop.left -= speed_x model.shop.rect.x = model.shop.left - model.workshop.left -= speed_x - model.workshop.rect.x = model.workshop.left - speed_x = speed_x + thruster_x; if speed_x > 1: @@ -406,8 +395,6 @@ def handle_event(self, event): model.fuel_station.rect.y = model.fuel_station.top model.shop.top -= speed_y model.shop.rect.y = model.shop.top - model.workshop.top -= speed_y - model.workshop.rect.y = model.workshop.top elif model.can_move_down and not keys[pygame.K_UP]: for top in range(len(model.temp_world)): @@ -424,9 +411,6 @@ def handle_event(self, event): model.shop.top -= speed_y model.shop.rect.y = model.shop.top - model.workshop.top -= speed_y - model.workshop.rect.y = model.workshop.top - speed_y = speed_y + gravity if speed_y > 12: speed_y -=.5 From ab8f91bf8e5e4c8267485838b95465bcfbb7b87b Mon Sep 17 00:00:00 2001 From: Sung Park Date: Wed, 9 Mar 2016 21:28:03 -0500 Subject: [PATCH 54/76] Fixed workshop positioning --- motherload.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/motherload.py b/motherload.py index 101b8d6..6f4f0b8 100644 --- a/motherload.py +++ b/motherload.py @@ -316,6 +316,8 @@ def handle_event(self, event): model.fuel_station.rect.y = model.fuel_station.top model.shop.top -= speed_y model.shop.rect.y = model.shop.top + model.workshop.top -= speed_y + model.workshop.rect.y = model.workshop.top speed_y = speed_y + thruster; @@ -336,6 +338,8 @@ def handle_event(self, event): model.fuel_station.rect.x = model.fuel_station.left model.shop.left += speed_x model.shop.rect.x = model.shop.left + model.workshop.left += speed_x + model.workshop.rect.x = model.workshop.left if keys[pygame.K_LEFT] and not model.vehicle.can_drill_left: speed_x = 2 @@ -348,6 +352,8 @@ def handle_event(self, event): model.fuel_station.rect.x = model.fuel_station.left model.shop.left += speed_x model.shop.rect.x = model.shop.left + model.workshop.left += speed_x + model.workshop.rect.x = model.workshop.left speed_x = speed_x + thruster_x; @@ -368,6 +374,8 @@ def handle_event(self, event): model.fuel_station.rect.x = model.fuel_station.left model.shop.left -= speed_x model.shop.rect.x = model.shop.left + model.workshop.left -= speed_x + model.workshop.rect.x = model.workshop.left if keys[pygame.K_RIGHT] and not model.vehicle.can_drill_right: speed_x = 2 @@ -381,6 +389,9 @@ def handle_event(self, event): model.fuel_station.rect.x = model.fuel_station.left model.shop.left -= speed_x model.shop.rect.x = model.shop.left + model.workshop.left -= speed_x + model.workshop.rect.x = model.workshop.left + speed_x = speed_x + thruster_x; if speed_x > 1: @@ -401,6 +412,8 @@ def handle_event(self, event): model.fuel_station.rect.y = model.fuel_station.top model.shop.top -= speed_y model.shop.rect.y = model.shop.top + model.workshop.top -= speed_y + model.workshop.rect.y = model.workshop.top elif model.can_move_down and not keys[pygame.K_UP]: for top in range(len(model.temp_world)): @@ -417,6 +430,9 @@ def handle_event(self, event): model.shop.top -= speed_y model.shop.rect.y = model.shop.top + model.workshop.top -= speed_y + model.workshop.rect.y = model.workshop.top + speed_y = speed_y + gravity if speed_y > 12: speed_y -=.5 From 0ca2ad7ace0afe2a5e7496bf4d32023d3abf7596 Mon Sep 17 00:00:00 2001 From: "willem.thorbecke@students.olin.edu" Date: Wed, 9 Mar 2016 21:28:36 -0500 Subject: [PATCH 55/76] better gravity --- motherload.py | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/motherload.py b/motherload.py index 101b8d6..7c7950c 100644 --- a/motherload.py +++ b/motherload.py @@ -32,23 +32,27 @@ def draw(self): brick = self.model.temp_world[top][left] r = pygame.Rect(brick.left, brick.top, brick.width, brick.height) - + #checks if the bottom of the vehicle + 6 is more than or equal to the top of a brick and the top of the vehicle is less than the top of that brick and if its the brick in the same column - if self.model.vehicle.top + self.model.vehicle.height + 6 >= brick.top and self.model.vehicle.top < brick.top and brick.rect.x < self.model.vehicle.rect.x and brick.rect.x + brick.width > self.model.vehicle.rect.x + self.model.vehicle.width: + if self.model.vehicle.top + self.model.vehicle.height + 6 >= brick.top and self.model.vehicle.top < brick.top and brick.rect.x - self.model.vehicle.rect.x < 9: #if that brick isn't black, then the vehicle cant move - if brick.color != "black": + if brick.color != "black" and brick.rect.x < self.model.vehicle.rect.x and brick.rect.x + brick.width > self.model.vehicle.rect.x + self.model.vehicle.width: self.model.can_move_down = False + print "does anything work" - else: + elif brick.rect.x < self.model.vehicle.rect.x and brick.rect.x + brick.width > self.model.vehicle.rect.x + self.model.vehicle.width: self.model.can_move_down = True + else: + self.model.can_move_down = False + if self.model.vehicle.top + self.model.vehicle.height + 6 >= brick.top and self.model.vehicle.top < brick.top and brick.rect.x < self.model.vehicle.rect.x and brick.rect.x + brick.width > self.model.vehicle.rect.x + self.model.vehicle.width: print "x side of brick", brick.rect.x print "x side of vehicle", self.model.vehicle.rect.x - #print self.model.vehicle.can_drill_down - if brick.color != "black": + print self.model.vehicle.can_drill_down + if brick.color != "black" and self.model.vehicle.rect.x - brick.rect.x < 9: self.model.vehicle.can_drill_down = True else: @@ -164,13 +168,7 @@ def draw(self): self.model.orange_block = 0 self.model.blue_block = 0 self.model.purple_block = 0 - - #Vehicle visiting workshop - if pygame.sprite.collide_rect(self.model.workshop, self.model.vehicle): - if self.model.money >= 500: - self.model.money -= 500 - self.model.max_fuel += 500 - + if self.model.fuel <= 0: msg = game_over_font.render("GAME OVER",1,(255,255,0)) screen.blit(msg, (0, 240)) @@ -194,7 +192,7 @@ def draw(self): screen.blit(purple_counter,(550,100)) money_counter = myFont.render("Money: " + str(self.model.money), 1, (255,255, 0)) - screen.blit(money_counter, (540,120)) + screen.blit(money_counter, (550,120)) pygame.display.update() From 357757d962a383440c63329b862ca2056b6ca46c Mon Sep 17 00:00:00 2001 From: Sung Park Date: Wed, 9 Mar 2016 21:39:00 -0500 Subject: [PATCH 56/76] Add score functionality --- game_model.py | 2 ++ motherload.py | 27 ++++++++++++++++++++------- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/game_model.py b/game_model.py index a5669b7..a6f853e 100644 --- a/game_model.py +++ b/game_model.py @@ -245,6 +245,8 @@ def __init__(self): self.purple_block = 0 self.money = 0 + + self.score = 0 cheatcode = "dpapp" self.vehicle = Vehicle(40*8,30, 30, 30, cheatcode) diff --git a/motherload.py b/motherload.py index 4a90877..e4e8108 100644 --- a/motherload.py +++ b/motherload.py @@ -111,23 +111,27 @@ def draw(self): print "I am eating ...", brick.brick_type if brick.brick_type == "ruby": self.model.red_block += 1 + self.model.score += 100 brick.image.fill((0,0,0)) brick.image.set_colorkey((0,0,0)) elif brick.brick_type == "emerald": self.model.green_block += 1 + self.model.score += 100 brick.image.fill((0,0,0)) brick.image.set_colorkey((0,0,0)) elif brick.brick_type == "amazonite": self.model.orange_block += 1 + self.model.score += 100 brick.image.fill((0,0,0)) brick.image.set_colorkey((0,0,0)) elif brick.brick_type == "sapphire": self.model.blue_block += 1 + self.model.score += 100 brick.image.fill((0,0,0)) brick.image.set_colorkey((0,0,0)) elif brick.brick_type == "watsonite": self.model.purple_block += 1 - + self.model.score += 100 brick.image.fill((0,0,0)) brick.image.set_colorkey((0,0,0)) @@ -169,6 +173,12 @@ def draw(self): self.model.blue_block = 0 self.model.purple_block = 0 + #Vehicle visiting workshop + if pygame.sprite.collide_rect(self.model.workshop, self.model.vehicle): + if self.model.money >= 500: + self.model.money -= 500 + self.model.max_fuel += 500 + if self.model.fuel <= 0: msg = game_over_font.render("GAME OVER",1,(255,255,0)) screen.blit(msg, (0, 240)) @@ -177,22 +187,25 @@ def draw(self): screen.blit(timer, (20,20)) red_counter = myFont.render("Red: " + str(self.model.red_block), 1, (255,255,0)) - screen.blit(red_counter,(550,20)) + screen.blit(red_counter,(540,20)) green_counter = myFont.render("Green: " + str(self.model.green_block), 1, (255,255,0)) - screen.blit(green_counter,(550,40)) + screen.blit(green_counter,(540,40)) orange_counter = myFont.render("Orange: " + str(self.model.orange_block), 1, (255,255,0)) - screen.blit(orange_counter,(550,60)) + screen.blit(orange_counter,(540,60)) blue_counter = myFont.render("Blue: " + str(self.model.blue_block), 1, (255,255,0)) - screen.blit(blue_counter,(550,80)) + screen.blit(blue_counter,(540,80)) purple_counter = myFont.render("Purplpe: " + str(self.model.purple_block), 1, (255,255,0)) - screen.blit(purple_counter,(550,100)) + screen.blit(purple_counter,(540,100)) money_counter = myFont.render("Money: " + str(self.model.money), 1, (255,255, 0)) - screen.blit(money_counter, (550,120)) + screen.blit(money_counter, (540,120)) + + score_counter = myFont.render("Score: " + str(self.model.score), 1, (255,255, 0)) + screen.blit(score_counter, (540,140)) pygame.display.update() From 805e6b02efe6adb5e3a7905f00a7ca1886375895 Mon Sep 17 00:00:00 2001 From: "willem.thorbecke@students.olin.edu" Date: Wed, 9 Mar 2016 21:39:39 -0500 Subject: [PATCH 57/76] idk --- game_model.py | 2 +- motherload.py | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/game_model.py b/game_model.py index a5669b7..48f718d 100644 --- a/game_model.py +++ b/game_model.py @@ -247,7 +247,7 @@ def __init__(self): self.money = 0 cheatcode = "dpapp" - self.vehicle = Vehicle(40*8,30, 30, 30, cheatcode) + self.vehicle = Vehicle(40*8,25, 25, 25, cheatcode) self.fuel_station = FuelStation() self.sprite_list.add(self.fuel_station) diff --git a/motherload.py b/motherload.py index 4a90877..3592e6c 100644 --- a/motherload.py +++ b/motherload.py @@ -33,6 +33,8 @@ def draw(self): r = pygame.Rect(brick.left, brick.top, brick.width, brick.height) + # if not pygame.sprite.collide_rect(self.model.vehicle, brick): + # self.model.can_move_down = True #checks if the bottom of the vehicle + 6 is more than or equal to the top of a brick and the top of the vehicle is less than the top of that brick and if its the brick in the same column if self.model.vehicle.top + self.model.vehicle.height + 6 >= brick.top and self.model.vehicle.top < brick.top and brick.rect.x - self.model.vehicle.rect.x < 9: @@ -445,5 +447,4 @@ def handle_event(self, event): model.fuel -= 1 #decrease fuel value every frame view.draw() - #print "can move right??", model.can_drill_right - # clock.tick(500000000) + \ No newline at end of file From 48feea9a946313df676a278882507badc129dd57 Mon Sep 17 00:00:00 2001 From: "willem.thorbecke@students.olin.edu" Date: Wed, 9 Mar 2016 21:57:43 -0500 Subject: [PATCH 58/76] cant drill up --- game_model.py | 1 + motherload.py | 29 +++++++++++++++++++++++------ 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/game_model.py b/game_model.py index 49965be..38c0eb6 100644 --- a/game_model.py +++ b/game_model.py @@ -186,6 +186,7 @@ def __init__(self, left, top, width, height, cheatcode): self.can_drill_left = False self.can_drill_right = False self.can_drill_down = False + self.can_move_up = True self.left = left self.top = top diff --git a/motherload.py b/motherload.py index bd6dd3f..cb5eee0 100644 --- a/motherload.py +++ b/motherload.py @@ -36,12 +36,27 @@ def draw(self): # if not pygame.sprite.collide_rect(self.model.vehicle, brick): # self.model.can_move_down = True + + if self.model.vehicle.top <= brick.top + brick.height and self.model.vehicle.top > brick.top and brick.rect.x - self.model.vehicle.rect.x < 9: + #if that brick isn't black, then the vehicle cant move + if brick.color != "black" and brick.rect.x < self.model.vehicle.rect.x and brick.rect.x + brick.width > self.model.vehicle.rect.x + self.model.vehicle.width: + self.model.vehicle.can_move_up = False + + + + elif brick.rect.x < self.model.vehicle.rect.x and brick.rect.x + brick.width > self.model.vehicle.rect.x + self.model.vehicle.width: + self.model.vehicle.can_move_up = True + + else: + self.model.vehicle.can_move_up = False + + #checks if the bottom of the vehicle + 6 is more than or equal to the top of a brick and the top of the vehicle is less than the top of that brick and if its the brick in the same column if self.model.vehicle.top + self.model.vehicle.height + 6 >= brick.top and self.model.vehicle.top < brick.top and brick.rect.x - self.model.vehicle.rect.x < 9: #if that brick isn't black, then the vehicle cant move if brick.color != "black" and brick.rect.x < self.model.vehicle.rect.x and brick.rect.x + brick.width > self.model.vehicle.rect.x + self.model.vehicle.width: self.model.can_move_down = False - print "does anything work" + elif brick.rect.x < self.model.vehicle.rect.x and brick.rect.x + brick.width > self.model.vehicle.rect.x + self.model.vehicle.width: @@ -51,9 +66,9 @@ def draw(self): if self.model.vehicle.top + self.model.vehicle.height + 6 >= brick.top and self.model.vehicle.top < brick.top and brick.rect.x < self.model.vehicle.rect.x and brick.rect.x + brick.width > self.model.vehicle.rect.x + self.model.vehicle.width: - print "x side of brick", brick.rect.x - print "x side of vehicle", self.model.vehicle.rect.x - print self.model.vehicle.can_drill_down + # print "x side of brick", brick.rect.x + # print "x side of vehicle", self.model.vehicle.rect.x + # print self.model.vehicle.can_drill_down if brick.color != "black" and self.model.vehicle.rect.x - brick.rect.x < 9: self.model.vehicle.can_drill_down = True @@ -309,7 +324,7 @@ def handle_event(self, event): # print " can drill right?", model.vehicle.can_drill_right # print " can drill left?", model.vehicle.can_drill_left - print "can drill down? ", model.vehicle.can_drill_down + print "can drill up? ", model.vehicle.can_move_up if model.temp_world[-1][0].top >= model.FAR_BOTTOM and model.temp_world[-1][0].top < model.FAR_BOTTOM + 40: mistake = model.FAR_BOTTOM - model.temp_world[-1][0].top @@ -318,7 +333,7 @@ def handle_event(self, event): keys = pygame.key.get_pressed() - if keys[pygame.K_UP]: + if keys[pygame.K_UP] and model.vehicle.can_move_up: for top in range(len(model.temp_world)): for left in range(len(model.temp_world[top])): @@ -338,6 +353,8 @@ def handle_event(self, event): speed_y = 0 elif speed_y > 10: speed_y = 10 + elif keys[pygame.K_UP] and not model.vehicle.can_move_up: + speed_y = 0 if keys[pygame.K_LEFT] and model.vehicle.can_drill_left: #print "somethings working??" From 41cb1a3bbce7c161d889d98f53480b1359cf2aed Mon Sep 17 00:00:00 2001 From: Sung Park Date: Wed, 9 Mar 2016 22:02:33 -0500 Subject: [PATCH 59/76] Add game-over --- motherload.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/motherload.py b/motherload.py index cb5eee0..df82771 100644 --- a/motherload.py +++ b/motherload.py @@ -322,6 +322,9 @@ def handle_event(self, event): controller.handle_event(event) model.can_drill_right = False + if model.fuel < 0: + running = False + # print " can drill right?", model.vehicle.can_drill_right # print " can drill left?", model.vehicle.can_drill_left print "can drill up? ", model.vehicle.can_move_up From a46235949847bf4ba900ed55c5363037cde46dcc Mon Sep 17 00:00:00 2001 From: "willem.thorbecke@students.olin.edu" Date: Thu, 10 Mar 2016 00:57:08 -0500 Subject: [PATCH 60/76] added different collision detect --- game_model.py | 15 +++++--- motherload.py | 98 ++++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 93 insertions(+), 20 deletions(-) diff --git a/game_model.py b/game_model.py index 38c0eb6..2e9cab5 100644 --- a/game_model.py +++ b/game_model.py @@ -27,11 +27,15 @@ def __init__(self, left, top, width, height, first): if first: self.rect.x = left*width - width*9 #renders 9 extra columns of blocks off screen to the left - self.rect.y = top*height + height*2 - 1 #starts the world with a 2 block high sky + self.rect.y = top*height #top*height + height*2 - 1 #starts the world with a 2 block high sky self.width = width self.height = height - self.top = top*height + height*2 -1 + self.top = top*height #+ height*2 -1 self.left = left*width - width*9 + + if top == 0 or top == 1: + self.color = "black" + return random_seed = random.random() if random_seed < 0.1: self.color = "black" @@ -226,13 +230,16 @@ def __init__(self): self.sprite_list = pygame.sprite.Group() #a list of sprites to be drawn #initialize world + + for top in range(0,self.init_height_dist): self.world.append([]) for left in range(0,self.init_width_dist): brick = Brick(left, top, self.BRICK_WIDTH, self.BRICK_HEIGHT, True) self.world[top].append(brick) - if brick.brick_type != "empty" and brick.brick_type != "soil": - self.sprite_list.add(brick) + if not (top ==1 or top ==0): + if brick.brick_type != "empty" and brick.brick_type != "soil": + self.sprite_list.add(brick) self.temp_world = self.world self.fuel = 1000 diff --git a/motherload.py b/motherload.py index cb5eee0..d7764c4 100644 --- a/motherload.py +++ b/motherload.py @@ -30,14 +30,68 @@ def draw(self): #pulls the appropriate brick model from the list brick = self.model.temp_world[top][left] + brick_left = self.model.temp_world[top][left-1] + brick_top_left = self.model.temp_world[top-1][left-1] + brick_top_right = self.model.temp_world[top-1][left+1] + brick_bottom_left = self.model.temp_world[top+1][left-1] + brick_bottom_right = self.model.temp_world[top+1][left+1] + brick_right = self.model.temp_world[top][left+1] + brick_bottom = self.model.temp_world[top+1][left] + brick_top = self.model.temp_world[top-1][left] r = pygame.Rect(brick.left, brick.top, brick.width, brick.height) - - # if not pygame.sprite.collide_rect(self.model.vehicle, brick): - # self.model.can_move_down = True - - - if self.model.vehicle.top <= brick.top + brick.height and self.model.vehicle.top > brick.top and brick.rect.x - self.model.vehicle.rect.x < 9: + + if pygame.sprite.collide_rect(brick,self.model.vehicle): + + if pygame.sprite.collide_rect(brick,brick_left): #checks collision with left + l = True + elif not pygame.sprite.collide_rect(brick,brick_left): + l = False + + elif pygame.sprite.collide_rect(brick,brick_right): #checks collision with right + r = True + elif not pygame.sprite.collide_rect(brick,brick_right): + r = False + + elif pygame.sprite.collide_rect(brick,brick_top): #checks collision with top + t = True + elif not pygame.sprite.collide_rect(brick,brick_top): + t = False + + elif pygame.sprite.collide_rect(brick,brick_bottom): #checks collision with bottom + b = True + elif not pygame.sprite.collide_rect(brick,brick_bottom): + b = False + + elif pygame.sprite.collide_rect(brick,brick_bottom_left): #checks collision with bottom left + bl = True + elif not pygame.sprite.collide_rect(brick,brick_bottom_left): + bl = False + + elif pygame.sprite.collide_rect(brick,brick_bottom_right): #checks collision with bottom right + br = True + elif not pygame.sprite.collide_rect(brick,brick_bottom_right): + br = False + + elif pygame.sprite.collide_rect(brick,brick_top_left): #checks collision with top left + tl = True + elif not pygame.sprite.collide_rect(brick,brick_top_left): + tl = False + + elif pygame.sprite.collide_rect(brick,brick_top_right): #checks collision with top right + tr = True + elif not pygame.sprite.collide_rect(brick,brick_top_right): + tr = False + + + + + + + + #checks if the + if self.model.vehicle.top <= brick.top + brick.height and self.model.vehicle.top - 30 > brick.top and self.model.vehicle.left - brick.left < 10 and brick.left + brick.width > self.model.vehicle.left + self.model.vehicle.width: + print "is this ever executed" #if that brick isn't black, then the vehicle cant move if brick.color != "black" and brick.rect.x < self.model.vehicle.rect.x and brick.rect.x + brick.width > self.model.vehicle.rect.x + self.model.vehicle.width: self.model.vehicle.can_move_up = False @@ -51,8 +105,8 @@ def draw(self): self.model.vehicle.can_move_up = False - #checks if the bottom of the vehicle + 6 is more than or equal to the top of a brick and the top of the vehicle is less than the top of that brick and if its the brick in the same column - if self.model.vehicle.top + self.model.vehicle.height + 6 >= brick.top and self.model.vehicle.top < brick.top and brick.rect.x - self.model.vehicle.rect.x < 9: + #checks if the bottom of the vehicle + 6 px is more than or equal to the top of a brick and the top of the vehicle is less than the top of that brick and if its the brick in the same column + if self.model.vehicle.top + self.model.vehicle.height + 3 >= brick.top and self.model.vehicle.top < brick.top and brick.rect.x - self.model.vehicle.rect.x < 9: #if that brick isn't black, then the vehicle cant move if brick.color != "black" and brick.rect.x < self.model.vehicle.rect.x and brick.rect.x + brick.width > self.model.vehicle.rect.x + self.model.vehicle.width: self.model.can_move_down = False @@ -65,15 +119,27 @@ def draw(self): self.model.can_move_down = False - if self.model.vehicle.top + self.model.vehicle.height + 6 >= brick.top and self.model.vehicle.top < brick.top and brick.rect.x < self.model.vehicle.rect.x and brick.rect.x + brick.width > self.model.vehicle.rect.x + self.model.vehicle.width: + if self.model.vehicle.top + self.model.vehicle.height + 3 >= brick.top and self.model.vehicle.top < brick.top and brick.rect.x < self.model.vehicle.rect.x and brick.rect.x + brick.width > self.model.vehicle.rect.x + self.model.vehicle.width: # print "x side of brick", brick.rect.x # print "x side of vehicle", self.model.vehicle.rect.x # print self.model.vehicle.can_drill_down - if brick.color != "black" and self.model.vehicle.rect.x - brick.rect.x < 9: - self.model.vehicle.can_drill_down = True + # if brick.color != "black" and self.model.vehicle.rect.x - brick.rect.x < 9: + # self.model.vehicle.can_drill_down = True + + # else: + # self.model.vehicle.can_drill_down = False + + if brick.color != "black" and brick.rect.x < self.model.vehicle.rect.x and brick.rect.x + brick.width > self.model.vehicle.rect.x + self.model.vehicle.width: + self.model.vehicle.can_drill_down = True + + + + elif brick.rect.x < self.model.vehicle.rect.x and brick.rect.x + brick.width > self.model.vehicle.rect.x + self.model.vehicle.width: + self.model.vehicle.can_drill_down = False + + else: + self.model.vehicle.can_drill_down = True - else: - self.model.vehicle.can_drill_down = False @@ -324,7 +390,7 @@ def handle_event(self, event): # print " can drill right?", model.vehicle.can_drill_right # print " can drill left?", model.vehicle.can_drill_left - print "can drill up? ", model.vehicle.can_move_up + print "can drill right? ", model.vehicle.can_drill_right if model.temp_world[-1][0].top >= model.FAR_BOTTOM and model.temp_world[-1][0].top < model.FAR_BOTTOM + 40: mistake = model.FAR_BOTTOM - model.temp_world[-1][0].top @@ -393,7 +459,7 @@ def handle_event(self, event): speed_x = 10 if keys[pygame.K_RIGHT] and model.vehicle.can_drill_right: - #print "somethings working??" + speed_x = .7 for top in range(len(model.temp_world)): for left in range(len(model.temp_world[top])): @@ -430,7 +496,7 @@ def handle_event(self, event): speed_x = 10 - elif keys[pygame.K_DOWN] and not model.can_move_down: + elif keys[pygame.K_DOWN] and not model.can_move_down and model.vehicle.can_drill_down: # print "juss drilling" speed_y = .7 for top in range(len(model.temp_world)): From d9dd89ced00c09ae378f364842c481e82b97e9a5 Mon Sep 17 00:00:00 2001 From: Sung Park Date: Thu, 10 Mar 2016 00:58:14 -0500 Subject: [PATCH 61/76] Fix collision stuff --- motherload.py | 42 ++++++++++++++++++++++++++---------------- 1 file changed, 26 insertions(+), 16 deletions(-) diff --git a/motherload.py b/motherload.py index df82771..c3e5993 100644 --- a/motherload.py +++ b/motherload.py @@ -39,31 +39,38 @@ def draw(self): if self.model.vehicle.top <= brick.top + brick.height and self.model.vehicle.top > brick.top and brick.rect.x - self.model.vehicle.rect.x < 9: #if that brick isn't black, then the vehicle cant move + + if brick.color != "black" and brick.rect.x < self.model.vehicle.rect.x and brick.rect.x + brick.width > self.model.vehicle.rect.x + self.model.vehicle.width: self.model.vehicle.can_move_up = False - elif brick.rect.x < self.model.vehicle.rect.x and brick.rect.x + brick.width > self.model.vehicle.rect.x + self.model.vehicle.width: self.model.vehicle.can_move_up = True - + elif brick.rect.y != 24: + self.model.vehicle.can_move_up = True + elif brick.rect.y == 24 and brick.color == "black": + self.model.vehicle.can_move_up = True else: self.model.vehicle.can_move_up = False - #checks if the bottom of the vehicle + 6 is more than or equal to the top of a brick and the top of the vehicle is less than the top of that brick and if its the brick in the same column if self.model.vehicle.top + self.model.vehicle.height + 6 >= brick.top and self.model.vehicle.top < brick.top and brick.rect.x - self.model.vehicle.rect.x < 9: - #if that brick isn't black, then the vehicle cant move + #if that brick isn't black, then the vehicle cant move + if brick.color != "black" and brick.rect.x < self.model.vehicle.rect.x and brick.rect.x + brick.width > self.model.vehicle.rect.x + self.model.vehicle.width: self.model.can_move_down = False - elif brick.rect.x < self.model.vehicle.rect.x and brick.rect.x + brick.width > self.model.vehicle.rect.x + self.model.vehicle.width: self.model.can_move_down = True + elif not (brick.rect.y < 55 and brick.rect.y > 50): + self.model.can_move_down = True + elif brick.rect.y < 55 and brick.rect.y > 50 and brick.color == "black": + self.model.can_move_down = True else: self.model.can_move_down = False - + if self.model.vehicle.top + self.model.vehicle.height + 6 >= brick.top and self.model.vehicle.top < brick.top and brick.rect.x < self.model.vehicle.rect.x and brick.rect.x + brick.width > self.model.vehicle.rect.x + self.model.vehicle.width: # print "x side of brick", brick.rect.x @@ -322,12 +329,12 @@ def handle_event(self, event): controller.handle_event(event) model.can_drill_right = False - if model.fuel < 0: - running = False +# if model.fuel < 0: +# running = False # print " can drill right?", model.vehicle.can_drill_right # print " can drill left?", model.vehicle.can_drill_left - print "can drill up? ", model.vehicle.can_move_up + # print "can move up? ", model.vehicle.can_move_up if model.temp_world[-1][0].top >= model.FAR_BOTTOM and model.temp_world[-1][0].top < model.FAR_BOTTOM + 40: mistake = model.FAR_BOTTOM - model.temp_world[-1][0].top @@ -357,10 +364,13 @@ def handle_event(self, event): elif speed_y > 10: speed_y = 10 elif keys[pygame.K_UP] and not model.vehicle.can_move_up: - speed_y = 0 + speed_y = 0 - if keys[pygame.K_LEFT] and model.vehicle.can_drill_left: - #print "somethings working??" + print "can_move_down????: ", model.can_move_down + + if keys[pygame.K_LEFT] and model.vehicle.can_drill_left and not model.can_move_down: + #print "somethings working??" + print "mining left" speed_x = .7 for top in range(len(model.temp_world)): for left in range(len(model.temp_world[top])): @@ -374,7 +384,7 @@ def handle_event(self, event): model.workshop.left += speed_x model.workshop.rect.x = model.workshop.left - if keys[pygame.K_LEFT] and not model.vehicle.can_drill_left: + if keys[pygame.K_LEFT] and not model.vehicle.can_drill_left and not model.can_move_down: speed_x = 2 for top in range(len(model.temp_world)): for left in range(len(model.temp_world[top])): @@ -395,9 +405,9 @@ def handle_event(self, event): elif speed_x > 10: speed_x = 10 - if keys[pygame.K_RIGHT] and model.vehicle.can_drill_right: + if keys[pygame.K_RIGHT] and model.vehicle.can_drill_right and not model.can_move_down: #print "somethings working??" - speed_x = .7 + speed_x = 0.7 for top in range(len(model.temp_world)): for left in range(len(model.temp_world[top])): brick = model.temp_world[top][left] @@ -410,7 +420,7 @@ def handle_event(self, event): model.workshop.left -= speed_x model.workshop.rect.x = model.workshop.left - if keys[pygame.K_RIGHT] and not model.vehicle.can_drill_right: + if keys[pygame.K_RIGHT] and not model.vehicle.can_drill_right and not model.can_move_down: speed_x = 2 for top in range(len(model.temp_world)): for left in range(len(model.temp_world[top])): From 23f3ade4dbcdb3c3b62fb63f928c9408064927e2 Mon Sep 17 00:00:00 2001 From: "willem.thorbecke@students.olin.edu" Date: Thu, 10 Mar 2016 01:03:51 -0500 Subject: [PATCH 62/76] motherload2 --- motherload2.py | 554 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 554 insertions(+) create mode 100644 motherload2.py diff --git a/motherload2.py b/motherload2.py new file mode 100644 index 0000000..072f0f2 --- /dev/null +++ b/motherload2.py @@ -0,0 +1,554 @@ +import pygame, os, sys +from pygame.locals import * +import time +from random import choice +import random +import game_model +import pygame, os, sys +import math + + +class PygameBrickBreakerView(object): + """ Visualizes a brick breaker game in a pygame window """ + def __init__(self, model, screen): + """ Initialize the view with the specified model + and screen. """ + self.model = model + self.screen = screen + + + def draw(self): + """ Draw the game state to the screen """ + myFont = pygame.font.SysFont("monospace",15) + game_over_font = pygame.font.SysFont("monospace",100) + + self.screen.fill(pygame.Color('black')) + # draw the bricks to the screen + for top in range(len(self.model.temp_world)): + for left in range(len(self.model.temp_world[top])): + + #pulls the appropriate brick model from the list + + + + brick = self.model.temp_world[top][left] + if not (left == 0 or top == 0 or top == len(self.model.temp_world) -1 or left == len(self.model.temp_world[0])-1): + + brick_left = self.model.temp_world[top][left-1] + brick_top_left = self.model.temp_world[top-1][left-1] + brick_top_right = self.model.temp_world[top-1][left+1] + brick_bottom_left = self.model.temp_world[top+1][left-1] + brick_bottom_right = self.model.temp_world[top+1][left+1] + brick_right = self.model.temp_world[top][left+1] + brick_bottom = self.model.temp_world[top+1][left] + brick_top = self.model.temp_world[top-1][left] + + if pygame.sprite.collide_rect(brick,self.model.vehicle): + + if pygame.sprite.collide_rect(brick,brick_left): #checks collision with left + l = True + elif not pygame.sprite.collide_rect(brick,brick_left): + l = False + + elif pygame.sprite.collide_rect(brick,brick_right): #checks collision with right + r = True + elif not pygame.sprite.collide_rect(brick,brick_right): + r = False + + elif pygame.sprite.collide_rect(brick,brick_top): #checks collision with top + t = True + elif not pygame.sprite.collide_rect(brick,brick_top): + t = False + + elif pygame.sprite.collide_rect(brick,brick_bottom): #checks collision with bottom + b = True + elif not pygame.sprite.collide_rect(brick,brick_bottom): + b = False + + elif pygame.sprite.collide_rect(brick,brick_bottom_left): #checks collision with bottom left + bl = True + elif not pygame.sprite.collide_rect(brick,brick_bottom_left): + bl = False + + elif pygame.sprite.collide_rect(brick,brick_bottom_right): #checks collision with bottom right + br = True + elif not pygame.sprite.collide_rect(brick,brick_bottom_right): + br = False + + elif pygame.sprite.collide_rect(brick,brick_top_left): #checks collision with top left + tl = True + elif not pygame.sprite.collide_rect(brick,brick_top_left): + tl = False + + elif pygame.sprite.collide_rect(brick,brick_top_right): #checks collision with top right + tr = True + elif not pygame.sprite.collide_rect(brick,brick_top_right): + tr = False + + if brick.color == "black" and brick_bottom.color == "black": + print "gravity is TRUE" + + + r = pygame.Rect(brick.left, brick.top, brick.width, brick.height) + + + + + + + + + + #checks if the vehicle can move up + if self.model.vehicle.top <= brick.top + brick.height and self.model.vehicle.top > brick.top and brick.rect.x - self.model.vehicle.rect.x < 9: + #if that brick isn't black, then the vehicle cant move + if brick.color != "black" and brick.rect.x < self.model.vehicle.rect.x and brick.rect.x + brick.width > self.model.vehicle.rect.x + self.model.vehicle.width: + self.model.vehicle.can_move_up = False + + + + elif brick.rect.x < self.model.vehicle.rect.x and brick.rect.x + brick.width > self.model.vehicle.rect.x + self.model.vehicle.width: + self.model.vehicle.can_move_up = True + + else: + self.model.vehicle.can_move_up = False + + #checks if the bottom of the vehicle + 6 px is more than or equal to the top of a brick and the top of the vehicle is less than the top of that brick and if its the brick in the same column + if self.model.vehicle.top + self.model.vehicle.height + 3 >= brick.top and self.model.vehicle.top < brick.top and brick.rect.x - self.model.vehicle.rect.x < 9: + #if that brick isn't black, then the vehicle cant move + if brick.color != "black" and brick.rect.x < self.model.vehicle.rect.x and brick.rect.x + brick.width > self.model.vehicle.rect.x + self.model.vehicle.width: + self.model.can_move_down = False + + + + elif brick.rect.x < self.model.vehicle.rect.x and brick.rect.x + brick.width > self.model.vehicle.rect.x + self.model.vehicle.width: + self.model.can_move_down = True + else: + self.model.can_move_down = False + + + if self.model.vehicle.top + self.model.vehicle.height + 3 >= brick.top and self.model.vehicle.top < brick.top and brick.rect.x < self.model.vehicle.rect.x and brick.rect.x + brick.width > self.model.vehicle.rect.x + self.model.vehicle.width: + # print "x side of brick", brick.rect.x + # print "x side of vehicle", self.model.vehicle.rect.x + # print self.model.vehicle.can_drill_down + # if brick.color != "black" and self.model.vehicle.rect.x - brick.rect.x < 9: + # self.model.vehicle.can_drill_down = True + + # else: + # self.model.vehicle.can_drill_down = False + + if brick.color != "black" and brick.rect.x < self.model.vehicle.rect.x and brick.rect.x + brick.width > self.model.vehicle.rect.x + self.model.vehicle.width: + self.model.vehicle.can_drill_down = True + + + + elif brick.rect.x < self.model.vehicle.rect.x and brick.rect.x + brick.width > self.model.vehicle.rect.x + self.model.vehicle.width: + self.model.vehicle.can_drill_down = False + + else: + self.model.vehicle.can_drill_down = True + + + + + if (not model.can_move_down) and (brick.left + brick.width >= self.model.vehicle.left) \ + and (brick.left < self.model.vehicle.left) and math.fabs(brick.top-self.model.vehicle.top) < 9: #checks if the vehicles can/should drill left + + if brick.color != "black": + + self.model.vehicle.can_drill_left = True + else: + + self.model.vehicle.can_drill_left = False + + + + if (not model.can_move_down) and (self.model.vehicle.left + brick.width >= brick.left) \ + and (self.model.vehicle.left < brick.left) and math.fabs(brick.top-self.model.vehicle.top) < 9: #checks if the vehicles can/should drill right + + if brick.color != "black": + + self.model.vehicle.can_drill_right = True + else: + + self.model.vehicle.can_drill_right = False + + + + # elif not pygame.sprite.collide_rect(brick, self.model.vehicle): + # self.model.can_move_down = False + + #print "can move down", self.model.can_move_down + + + if self.model.vehicle.left + float(brick.width)/2 < brick.left and brick.left + float(brick.width)/2 > self.model.vehicle.left and not (brick.left > self.model.vehicle.left + float(brick.width)*3/2) \ + and brick.top > self.model.vehicle.top - brick.width/2 and brick.top + brick.height < self.model.vehicle.top + float(brick.width)*3/2: #checks if the vehicle has a block to the right + if brick.color != "black" and not model.can_move_down: + self.model.can_drill_right = True + #print "can move right", self.model.can_drill_right + else: + self.model.can_drill_right = False + # print "can move right", self.model.can_drill_right + # print "can move?", model.can_move_down + # print "vehicle left", self.model.vehicle.left + # print "brick left ", brick.left + # print "brick top", brick.top + # print "veh top", self.model.vehicle.top + # print "can drill right,", model.can_drill_right + # print self.model.can_drill_right + if not (top == 0 or top ==1): + if math.fabs(brick.left - self.model.vehicle.left) < 20 and math.fabs(self.model.vehicle.top - brick.top)<20: #checks if the vehicle overlaps a block, if so change block to black + if brick.brick_type != "empty" and brick.brick_type != "soil": + print "I am eating ...", brick.brick_type + if brick.brick_type == "ruby": + self.model.red_block += 1 + self.model.score += 100 + brick.image.fill((0,0,0)) + brick.image.set_colorkey((0,0,0)) + elif brick.brick_type == "emerald": + self.model.green_block += 1 + self.model.score += 100 + brick.image.fill((0,0,0)) + brick.image.set_colorkey((0,0,0)) + elif brick.brick_type == "amazonite": + self.model.orange_block += 1 + self.model.score += 100 + brick.image.fill((0,0,0)) + brick.image.set_colorkey((0,0,0)) + elif brick.brick_type == "sapphire": + self.model.blue_block += 1 + self.model.score += 100 + brick.image.fill((0,0,0)) + brick.image.set_colorkey((0,0,0)) + elif brick.brick_type == "watsonite": + self.model.purple_block += 1 + self.model.score += 100 + brick.image.fill((0,0,0)) + brick.image.set_colorkey((0,0,0)) + + brick.color = "black" + brick.brick_type = "empty" + pygame.draw.rect(self.screen, pygame.Color(brick.color), r) + + else: + pygame.draw.rect(self.screen, pygame.Color(brick.color), r) + + + + r = pygame.Rect(self.model.vehicle.left,self.model.vehicle.top,self.model.vehicle.width,self.model.vehicle.height) #the mining vehicle + + pygame.draw.rect(self.screen, pygame.Color('white'), r) + + r = pygame.Rect(self.model.fuel_station.left,self.model.fuel_station.top,self.model.fuel_station.width,self.model.fuel_station.height) + pygame.draw.rect(self.screen, pygame.Color('deep pink'),r) + + self.model.sprite_list.draw(self.screen) + + r = pygame.Rect(self.model.shop.left,self.model.shop.top,self.model.shop.width,self.model.shop.height) + #subpygame.draw.rect(self.screen, pygame.Color('yellow'), r) + + #Vehicle visiting fuel station + if pygame.sprite.collide_rect(self.model.fuel_station, self.model.vehicle): + self.model.fuel = self.model.max_fuel + + #Vehicle visiting shop + if pygame.sprite.collide_rect(self.model.shop, self.model.vehicle): + self.model.money += 100 * self.model.red_block + self.model.money += 100 * self.model.green_block + self.model.money += 100 * self.model.orange_block + self.model.money += 100 * self.model.blue_block + self.model.money += 100 * self.model.purple_block + self.model.red_block = 0 + self.model.green_block = 0 + self.model.orange_block = 0 + self.model.blue_block = 0 + self.model.purple_block = 0 + + #Vehicle visiting workshop + if pygame.sprite.collide_rect(self.model.workshop, self.model.vehicle): + if self.model.money >= 500: + self.model.money -= 500 + self.model.max_fuel += 500 + + if self.model.fuel <= 0: + msg = game_over_font.render("GAME OVER",1,(255,255,0)) + screen.blit(msg, (0, 240)) + else: + timer = myFont.render(str(self.model.fuel), 1, (255,255,0)) + screen.blit(timer, (20,20)) + + red_counter = myFont.render("Red: " + str(self.model.red_block), 1, (255,255,0)) + screen.blit(red_counter,(540,20)) + + green_counter = myFont.render("Green: " + str(self.model.green_block), 1, (255,255,0)) + screen.blit(green_counter,(540,40)) + + orange_counter = myFont.render("Orange: " + str(self.model.orange_block), 1, (255,255,0)) + screen.blit(orange_counter,(540,60)) + + blue_counter = myFont.render("Blue: " + str(self.model.blue_block), 1, (255,255,0)) + screen.blit(blue_counter,(540,80)) + + purple_counter = myFont.render("Purplpe: " + str(self.model.purple_block), 1, (255,255,0)) + screen.blit(purple_counter,(540,100)) + + money_counter = myFont.render("Money: " + str(self.model.money), 1, (255,255, 0)) + screen.blit(money_counter, (540,120)) + + score_counter = myFont.render("Score: " + str(self.model.score), 1, (255,255, 0)) + screen.blit(score_counter, (540,140)) + + pygame.display.update() + + + + +class PyGameKeyboardController(object): + def __init__(self, model): + self.model = model + + def handle_event(self, event): + """ Look for left and right keypresses to + modify the x position of the paddle """ + if event.type != KEYDOWN: + return + + + + # if event.key == pygame.K_LEFT: + # if self.model.temp_world[0][0].left != self.model.FAR_LEFT: + + + # for top in range(len(self.model.temp_world)): + # for left in range(len(self.model.temp_world[top])): + # brick = self.model.temp_world[top][left] + # brick.left += brick.width + # brick.rect.x += brick.width #sprites stuff + # self.model.fuel_station.left += self.model.BRICK_HEIGHT + # self.model.fuel_station.rect.x += self.model.BRICK_HEIGHT + # self.model.shop.left += self.model.BRICK_HEIGHT + # self.model.shop.rect.x += self.model.BRICK_HEIGHT + # # print self.model.fuel_station.left + # # print self.model.fuel_station.rect.x + + # else: + # return + + # #if farthest block to left reachest threshold, add more blocks to left + # if self.model.temp_world[0][0].left == self.model.FAR_LEFT: + # self.model.world_enlarger("left") + + + # if event.key == pygame.K_RIGHT: + # if self.model.world[0][-1].left != self.model.FAR_RIGHT: + # for top in range(len(self.model.temp_world)): + # for left in range(len(self.model.temp_world[top])): + # brick = self.model.temp_world[top][left] + # brick.left -= brick.width + # brick.rect.x -= brick.width + # self.model.fuel_station.left -= self.model.BRICK_HEIGHT + # self.model.fuel_station.rect.x -= self.model.BRICK_HEIGHT + # self.model.shop.left -= self.model.BRICK_HEIGHT + # self.model.shop.rect.x -= self.model.BRICK_HEIGHT + # # print self.model.fuel_station.left + # # print self.model.fuel_station.rect.x + # else: + # return + # if self.model.world[0][-1].left == self.model.FAR_RIGHT: + # self.model.world_enlarger("right") + + + +class PyGameMouseController(object): + def __init__(self, model): + self.model = model + + def handle_event(self, event): + """ Look for mouse movements and respond appropriately """ + if event.type != MOUSEMOTION: + return + self.model.paddle.left = event.pos[0] + +clock = pygame.time.Clock() + +if __name__ == '__main__': + + + + speed_y = 0; + speed_x=0; + gravity = 0.25; + thruster = -0.05 + thruster_x = .025 + pygame.init() + size = (640, 480) + screen = pygame.display.set_mode(size) + model = game_model.BrickBreakerModel() + view = PygameBrickBreakerView(model, screen) + controller = PyGameKeyboardController(model) + #controller = PyGameMouseController(model) + + running = True + while running: + for event in pygame.event.get(): + if event.type == QUIT: + running = False + controller.handle_event(event) + model.can_drill_right = False + + # print " can drill right?", model.vehicle.can_drill_right + # print " can drill left?", model.vehicle.can_drill_left + print "can drill right? ", model.vehicle.can_drill_right + + if model.temp_world[-1][0].top >= model.FAR_BOTTOM and model.temp_world[-1][0].top < model.FAR_BOTTOM + 40: + mistake = model.FAR_BOTTOM - model.temp_world[-1][0].top + print "enlarging world" + model.world_enlarger("down") + + + keys = pygame.key.get_pressed() + if keys[pygame.K_UP] and model.vehicle.can_move_up: + + for top in range(len(model.temp_world)): + for left in range(len(model.temp_world[top])): + brick = model.temp_world[top][left] + brick.top -= speed_y + brick.rect.y = brick.top + model.fuel_station.top -= speed_y + model.fuel_station.rect.y = model.fuel_station.top + model.shop.top -= speed_y + model.shop.rect.y = model.shop.top + model.workshop.top -= speed_y + model.workshop.rect.y = model.workshop.top + + speed_y = speed_y + thruster; + + if speed_y > 1: + speed_y = 0 + elif speed_y > 10: + speed_y = 10 + elif keys[pygame.K_UP] and not model.vehicle.can_move_up: + speed_y = 0 + + if keys[pygame.K_LEFT] and model.vehicle.can_drill_left: + #print "somethings working??" + speed_x = .7 + for top in range(len(model.temp_world)): + for left in range(len(model.temp_world[top])): + brick = model.temp_world[top][left] + brick.left += speed_x + brick.rect.x = brick.left + model.fuel_station.left += speed_x + model.fuel_station.rect.x = model.fuel_station.left + model.shop.left += speed_x + model.shop.rect.x = model.shop.left + model.workshop.left += speed_x + model.workshop.rect.x = model.workshop.left + + if keys[pygame.K_LEFT] and not model.vehicle.can_drill_left: + speed_x = 2 + for top in range(len(model.temp_world)): + for left in range(len(model.temp_world[top])): + brick = model.temp_world[top][left] + brick.left += speed_x + brick.rect.x = brick.left + model.fuel_station.left += speed_x + model.fuel_station.rect.x = model.fuel_station.left + model.shop.left += speed_x + model.shop.rect.x = model.shop.left + model.workshop.left += speed_x + model.workshop.rect.x = model.workshop.left + + speed_x = speed_x + thruster_x; + + if speed_x > 1: + speed_x = 0 + elif speed_x > 10: + speed_x = 10 + + if keys[pygame.K_RIGHT] and model.vehicle.can_drill_right: + + speed_x = .7 + for top in range(len(model.temp_world)): + for left in range(len(model.temp_world[top])): + brick = model.temp_world[top][left] + brick.left -= speed_x + brick.rect.x = brick.left + model.fuel_station.left -= speed_x + model.fuel_station.rect.x = model.fuel_station.left + model.shop.left -= speed_x + model.shop.rect.x = model.shop.left + model.workshop.left -= speed_x + model.workshop.rect.x = model.workshop.left + + if keys[pygame.K_RIGHT] and not model.vehicle.can_drill_right: + speed_x = 2 + for top in range(len(model.temp_world)): + for left in range(len(model.temp_world[top])): + brick = model.temp_world[top][left] + brick.left -= speed_x + brick.rect.x = brick.left + + model.fuel_station.left -= speed_x + model.fuel_station.rect.x = model.fuel_station.left + model.shop.left -= speed_x + model.shop.rect.x = model.shop.left + model.workshop.left -= speed_x + model.workshop.rect.x = model.workshop.left + + speed_x = speed_x + thruster_x; + + if speed_x > 1: + speed_x = 0 + elif speed_x > 10: + speed_x = 10 + + + elif keys[pygame.K_DOWN] and not model.can_move_down and model.vehicle.can_drill_down: + # print "juss drilling" + speed_y = .7 + for top in range(len(model.temp_world)): + for left in range(len(model.temp_world[top])): + brick = model.temp_world[top][left] + brick.top -= speed_y + brick.rect.y = brick.top + model.fuel_station.top -= speed_y + model.fuel_station.rect.y = model.fuel_station.top + model.shop.top -= speed_y + model.shop.rect.y = model.shop.top + model.workshop.top -= speed_y + model.workshop.rect.y = model.workshop.top + + elif model.can_move_down and not keys[pygame.K_UP]: + for top in range(len(model.temp_world)): + for left in range(len(model.temp_world[top])): + brick = model.temp_world[top][left] + brick.top -= speed_y + brick.rect.y = brick.top + + + model.fuel_station.top -= speed_y + + model.fuel_station.rect.y = model.fuel_station.top + + model.shop.top -= speed_y + model.shop.rect.y = model.shop.top + + model.workshop.top -= speed_y + model.workshop.rect.y = model.workshop.top + + speed_y = speed_y + gravity + if speed_y > 12: + speed_y -=.5 + + + + if not model.can_move_down and event.type != KEYDOWN: + speed_y = 0 + if not model.vehicle.can_drill_left and not model.vehicle.can_drill_right and event.type != KEYDOWN: + speed_x = 0 + + + model.fuel -= 1 #decrease fuel value every frame + view.draw() + From ad072ccc6562691b71574de64a3b0a6c948c0381 Mon Sep 17 00:00:00 2001 From: Sung Park Date: Thu, 10 Mar 2016 01:47:32 -0500 Subject: [PATCH 63/76] Add collision detection for up movement --- motherload2.py | 264 +++++++++++++++++++++++++++---------------------- 1 file changed, 144 insertions(+), 120 deletions(-) diff --git a/motherload2.py b/motherload2.py index 072f0f2..0859069 100644 --- a/motherload2.py +++ b/motherload2.py @@ -32,63 +32,86 @@ def draw(self): brick = self.model.temp_world[top][left] - if not (left == 0 or top == 0 or top == len(self.model.temp_world) -1 or left == len(self.model.temp_world[0])-1): - - brick_left = self.model.temp_world[top][left-1] - brick_top_left = self.model.temp_world[top-1][left-1] - brick_top_right = self.model.temp_world[top-1][left+1] - brick_bottom_left = self.model.temp_world[top+1][left-1] - brick_bottom_right = self.model.temp_world[top+1][left+1] - brick_right = self.model.temp_world[top][left+1] - brick_bottom = self.model.temp_world[top+1][left] - brick_top = self.model.temp_world[top-1][left] - - if pygame.sprite.collide_rect(brick,self.model.vehicle): - - if pygame.sprite.collide_rect(brick,brick_left): #checks collision with left - l = True - elif not pygame.sprite.collide_rect(brick,brick_left): - l = False - - elif pygame.sprite.collide_rect(brick,brick_right): #checks collision with right - r = True - elif not pygame.sprite.collide_rect(brick,brick_right): - r = False - - elif pygame.sprite.collide_rect(brick,brick_top): #checks collision with top - t = True - elif not pygame.sprite.collide_rect(brick,brick_top): - t = False - - elif pygame.sprite.collide_rect(brick,brick_bottom): #checks collision with bottom - b = True - elif not pygame.sprite.collide_rect(brick,brick_bottom): - b = False - - elif pygame.sprite.collide_rect(brick,brick_bottom_left): #checks collision with bottom left - bl = True - elif not pygame.sprite.collide_rect(brick,brick_bottom_left): - bl = False - - elif pygame.sprite.collide_rect(brick,brick_bottom_right): #checks collision with bottom right - br = True - elif not pygame.sprite.collide_rect(brick,brick_bottom_right): - br = False - - elif pygame.sprite.collide_rect(brick,brick_top_left): #checks collision with top left - tl = True - elif not pygame.sprite.collide_rect(brick,brick_top_left): - tl = False - - elif pygame.sprite.collide_rect(brick,brick_top_right): #checks collision with top right - tr = True - elif not pygame.sprite.collide_rect(brick,brick_top_right): - tr = False - - if brick.color == "black" and brick_bottom.color == "black": - print "gravity is TRUE" - - + if not (left == 0 or top == 0 or top == len(self.model.temp_world) -1 or left == len(self.model.temp_world[0])-1) and pygame.sprite.collide_rect(brick,self.model.vehicle): + + brick_left = self.model.temp_world[top][left-1] + brick_top_left = self.model.temp_world[top-1][left-1] + brick_top_right = self.model.temp_world[top-1][left+1] + brick_bottom_left = self.model.temp_world[top+1][left-1] + brick_bottom_right = self.model.temp_world[top+1][left+1] + brick_right = self.model.temp_world[top][left+1] + brick_bottom = self.model.temp_world[top+1][left] + brick_top = self.model.temp_world[top-1][left] + + t = True + tl = True + tr = True + + if pygame.sprite.collide_rect(brick,self.model.vehicle): + + if pygame.sprite.collide_rect(self.model.vehicle,brick_left): #checks collision with left + l = True + elif not pygame.sprite.collide_rect(self.model.vehicle,brick_left): + l = False + + if pygame.sprite.collide_rect(self.model.vehicle,brick_right): #checks collision with right + r = True + elif not pygame.sprite.collide_rect(self.model.vehicle,brick_right): + r = False + + if pygame.sprite.collide_rect(self.model.vehicle,brick_top): #checks collision with top + t = True + elif not pygame.sprite.collide_rect(self.model.vehicle,brick_top): + t = False + + if pygame.sprite.collide_rect(self.model.vehicle,brick_bottom): #checks collision with bottom + b = True + elif not pygame.sprite.collide_rect(self.model.vehicle,brick_bottom): + b = False + + if pygame.sprite.collide_rect(self.model.vehicle,brick_bottom_left): #checks collision with bottom left + bl = True + elif not pygame.sprite.collide_rect(self.model.vehicle,brick_bottom_left): + bl = False + + if pygame.sprite.collide_rect(self.model.vehicle,brick_bottom_right): #checks collision with bottom right + br = True + elif not pygame.sprite.collide_rect(self.model.vehicle,brick_bottom_right): + br = False + + if pygame.sprite.collide_rect(self.model.vehicle,brick_top_left): #checks collision with top left + tl = True + elif not pygame.sprite.collide_rect(self.model.vehicle,brick_top_left): + tl = False + + if pygame.sprite.collide_rect(self.model.vehicle,brick_top_right): #checks collision with top right + tr = True + elif not pygame.sprite.collide_rect(self.model.vehicle,brick_top_right): + tr = False + + if brick.color == "black" and brick_bottom.color == "black": + print "gravity is TRUE" + + #Collision detection using sprite collision + print "tl",tl,"t: ",t, "tr", tr + if t and not tl and not tr: + if brick_top.color == "black": + self.model.vehicle.can_move_up = True + else: + self.model.vehicle.can_move_up = False + elif (tl and t): + if brick_top.color == "black" and brick_top_left.color == "black": + self.model.vehicle.can_move_up = True + else: + self.model.vehicle.can_move_up = False + elif (t and tr): + if brick_top.color == "black" and brick_top_right.color == "black": + self.model.vehicle.can_move_up = True + else: + self.model.vehicle.can_move_up = False + else: + self.model.vehicle.can_move_up = True + r = pygame.Rect(brick.left, brick.top, brick.width, brick.height) @@ -100,8 +123,8 @@ def draw(self): #checks if the vehicle can move up - if self.model.vehicle.top <= brick.top + brick.height and self.model.vehicle.top > brick.top and brick.rect.x - self.model.vehicle.rect.x < 9: - #if that brick isn't black, then the vehicle cant move + """if self.model.vehicle.top <= brick.top + brick.height and self.model.vehicle.top > brick.top and brick.rect.x - self.model.vehicle.rect.x < 9: + #if that brick isn't black, then the vehicle cant move if brick.color != "black" and brick.rect.x < self.model.vehicle.rect.x and brick.rect.x + brick.width > self.model.vehicle.rect.x + self.model.vehicle.width: self.model.vehicle.can_move_up = False @@ -111,11 +134,11 @@ def draw(self): self.model.vehicle.can_move_up = True else: - self.model.vehicle.can_move_up = False + self.model.vehicle.can_move_up = False""" #checks if the bottom of the vehicle + 6 px is more than or equal to the top of a brick and the top of the vehicle is less than the top of that brick and if its the brick in the same column if self.model.vehicle.top + self.model.vehicle.height + 3 >= brick.top and self.model.vehicle.top < brick.top and brick.rect.x - self.model.vehicle.rect.x < 9: - #if that brick isn't black, then the vehicle cant move + #if that brick isn't black, then the vehicle cant move if brick.color != "black" and brick.rect.x < self.model.vehicle.rect.x and brick.rect.x + brick.width > self.model.vehicle.rect.x + self.model.vehicle.width: self.model.can_move_down = False @@ -124,18 +147,18 @@ def draw(self): elif brick.rect.x < self.model.vehicle.rect.x and brick.rect.x + brick.width > self.model.vehicle.rect.x + self.model.vehicle.width: self.model.can_move_down = True else: - self.model.can_move_down = False + self.model.can_move_down = False if self.model.vehicle.top + self.model.vehicle.height + 3 >= brick.top and self.model.vehicle.top < brick.top and brick.rect.x < self.model.vehicle.rect.x and brick.rect.x + brick.width > self.model.vehicle.rect.x + self.model.vehicle.width: - # print "x side of brick", brick.rect.x - # print "x side of vehicle", self.model.vehicle.rect.x - # print self.model.vehicle.can_drill_down - # if brick.color != "black" and self.model.vehicle.rect.x - brick.rect.x < 9: - # self.model.vehicle.can_drill_down = True + # print "x side of brick", brick.rect.x + # print "x side of vehicle", self.model.vehicle.rect.x + # print self.model.vehicle.can_drill_down + # if brick.color != "black" and self.model.vehicle.rect.x - brick.rect.x < 9: + # self.model.vehicle.can_drill_down = True - # else: - # self.model.vehicle.can_drill_down = False + # else: + # self.model.vehicle.can_drill_down = False if brick.color != "black" and brick.rect.x < self.model.vehicle.rect.x and brick.rect.x + brick.width > self.model.vehicle.rect.x + self.model.vehicle.width: self.model.vehicle.can_drill_down = True @@ -146,32 +169,32 @@ def draw(self): self.model.vehicle.can_drill_down = False else: - self.model.vehicle.can_drill_down = True + self.model.vehicle.can_drill_down = True if (not model.can_move_down) and (brick.left + brick.width >= self.model.vehicle.left) \ and (brick.left < self.model.vehicle.left) and math.fabs(brick.top-self.model.vehicle.top) < 9: #checks if the vehicles can/should drill left - - if brick.color != "black": + + if brick.color != "black": - self.model.vehicle.can_drill_left = True - else: + self.model.vehicle.can_drill_left = True + else: - self.model.vehicle.can_drill_left = False - + self.model.vehicle.can_drill_left = False + if (not model.can_move_down) and (self.model.vehicle.left + brick.width >= brick.left) \ and (self.model.vehicle.left < brick.left) and math.fabs(brick.top-self.model.vehicle.top) < 9: #checks if the vehicles can/should drill right - if brick.color != "black": + if brick.color != "black": - self.model.vehicle.can_drill_right = True - else: + self.model.vehicle.can_drill_right = True + else: - self.model.vehicle.can_drill_right = False + self.model.vehicle.can_drill_right = False @@ -196,42 +219,42 @@ def draw(self): # print "veh top", self.model.vehicle.top # print "can drill right,", model.can_drill_right # print self.model.can_drill_right - if not (top == 0 or top ==1): - if math.fabs(brick.left - self.model.vehicle.left) < 20 and math.fabs(self.model.vehicle.top - brick.top)<20: #checks if the vehicle overlaps a block, if so change block to black - if brick.brick_type != "empty" and brick.brick_type != "soil": - print "I am eating ...", brick.brick_type - if brick.brick_type == "ruby": - self.model.red_block += 1 - self.model.score += 100 - brick.image.fill((0,0,0)) - brick.image.set_colorkey((0,0,0)) - elif brick.brick_type == "emerald": - self.model.green_block += 1 - self.model.score += 100 - brick.image.fill((0,0,0)) - brick.image.set_colorkey((0,0,0)) - elif brick.brick_type == "amazonite": - self.model.orange_block += 1 - self.model.score += 100 - brick.image.fill((0,0,0)) - brick.image.set_colorkey((0,0,0)) - elif brick.brick_type == "sapphire": - self.model.blue_block += 1 - self.model.score += 100 - brick.image.fill((0,0,0)) - brick.image.set_colorkey((0,0,0)) - elif brick.brick_type == "watsonite": - self.model.purple_block += 1 - self.model.score += 100 - brick.image.fill((0,0,0)) - brick.image.set_colorkey((0,0,0)) - - brick.color = "black" - brick.brick_type = "empty" - pygame.draw.rect(self.screen, pygame.Color(brick.color), r) - - else: - pygame.draw.rect(self.screen, pygame.Color(brick.color), r) + if not (top == 0 or top ==1): + if math.fabs(brick.left - self.model.vehicle.left) < 20 and math.fabs(self.model.vehicle.top - brick.top)<20: #checks if the vehicle overlaps a block, if so change block to black + if brick.brick_type != "empty" and brick.brick_type != "soil": + print "I am eating ...", brick.brick_type + if brick.brick_type == "ruby": + self.model.red_block += 1 + self.model.score += 100 + brick.image.fill((0,0,0)) + brick.image.set_colorkey((0,0,0)) + elif brick.brick_type == "emerald": + self.model.green_block += 1 + self.model.score += 100 + brick.image.fill((0,0,0)) + brick.image.set_colorkey((0,0,0)) + elif brick.brick_type == "amazonite": + self.model.orange_block += 1 + self.model.score += 100 + brick.image.fill((0,0,0)) + brick.image.set_colorkey((0,0,0)) + elif brick.brick_type == "sapphire": + self.model.blue_block += 1 + self.model.score += 100 + brick.image.fill((0,0,0)) + brick.image.set_colorkey((0,0,0)) + elif brick.brick_type == "watsonite": + self.model.purple_block += 1 + self.model.score += 100 + brick.image.fill((0,0,0)) + brick.image.set_colorkey((0,0,0)) + + brick.color = "black" + brick.brick_type = "empty" + pygame.draw.rect(self.screen, pygame.Color(brick.color), r) + + else: + pygame.draw.rect(self.screen, pygame.Color(brick.color), r) @@ -398,7 +421,7 @@ def handle_event(self, event): # print " can drill right?", model.vehicle.can_drill_right # print " can drill left?", model.vehicle.can_drill_left - print "can drill right? ", model.vehicle.can_drill_right +# print "can drill right? ", model.vehicle.can_drill_right if model.temp_world[-1][0].top >= model.FAR_BOTTOM and model.temp_world[-1][0].top < model.FAR_BOTTOM + 40: mistake = model.FAR_BOTTOM - model.temp_world[-1][0].top @@ -406,7 +429,8 @@ def handle_event(self, event): model.world_enlarger("down") - keys = pygame.key.get_pressed() + keys = pygame.key.get_pressed() + print "can_move_up: ",model.vehicle.can_move_up if keys[pygame.K_UP] and model.vehicle.can_move_up: for top in range(len(model.temp_world)): @@ -428,10 +452,10 @@ def handle_event(self, event): elif speed_y > 10: speed_y = 10 elif keys[pygame.K_UP] and not model.vehicle.can_move_up: - speed_y = 0 + speed_y = 0 if keys[pygame.K_LEFT] and model.vehicle.can_drill_left: - #print "somethings working??" + #print "somethings working??" speed_x = .7 for top in range(len(model.temp_world)): for left in range(len(model.temp_world[top])): From d5b8fac1783b9430f13145b542f01188c2ebebf3 Mon Sep 17 00:00:00 2001 From: Sung Park Date: Thu, 10 Mar 2016 03:28:16 -0500 Subject: [PATCH 64/76] Implement drill left and right --- game_model.py | 2 ++ motherload2.py | 88 +++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 75 insertions(+), 15 deletions(-) diff --git a/game_model.py b/game_model.py index 2e9cab5..1d66ae4 100644 --- a/game_model.py +++ b/game_model.py @@ -191,6 +191,8 @@ def __init__(self, left, top, width, height, cheatcode): self.can_drill_right = False self.can_drill_down = False self.can_move_up = True + self.can_move_left = True + self.can_move_right = True self.left = left self.top = top diff --git a/motherload2.py b/motherload2.py index 0859069..84082e9 100644 --- a/motherload2.py +++ b/motherload2.py @@ -47,6 +47,13 @@ def draw(self): tl = True tr = True + l = True + r = True + + bl = True + b = True + br = True + if pygame.sprite.collide_rect(brick,self.model.vehicle): if pygame.sprite.collide_rect(self.model.vehicle,brick_left): #checks collision with left @@ -89,12 +96,12 @@ def draw(self): elif not pygame.sprite.collide_rect(self.model.vehicle,brick_top_right): tr = False - if brick.color == "black" and brick_bottom.color == "black": - print "gravity is TRUE" + #if brick.color == "black" and brick_bottom.color == "black": + #print "gravity is TRUE" #Collision detection using sprite collision - print "tl",tl,"t: ",t, "tr", tr if t and not tl and not tr: + #print "tl",tl,"t: ",t, "tr", tr if brick_top.color == "black": self.model.vehicle.can_move_up = True else: @@ -111,7 +118,56 @@ def draw(self): self.model.vehicle.can_move_up = False else: self.model.vehicle.can_move_up = True - + + if b and not bl and not br: + if brick_bottom.color == "black": + self.model.can_move_down = True + else: + self.model.can_move_down = False + elif b and bl: + if brick_bottom.color == "black" and brick_bottom_left == "black": + self.model.can_move_down = True + else: + self.model.can_move_down = False + elif b and br: + if brick_bottom.color == "black" and brick_bottom_right.color == "black": + self.model.can_move_down = True + else: + self.model.can_move_down = False + elif brick.color == "black" and not b and not bl and not br: + self.model.can_move_down = True + + if l and bl: + if brick_left.color == "black": + self.model.vehicle.can_move_left = True + else: + self.model.vehicle.can_move_left = False + + if r and br: + if brick_right.color == "black": + self.model.vehicle.can_move_right = True + else: + self.model.vehicle.can_move_right = False + + #Checks for drilling availability + if l and b and not self.model.can_move_down: + if brick_left.color != "black" and brick_bottom.color != "black": + #print "CAN DRILL!!" + self.model.vehicle.can_drill_left = True + else: + self.model.vehicle.can_drill_left = False + + if r and b and not self.model.can_move_down: + if brick_right.color != "black" and brick_bottom.color != "black": + self.model.vehicle.can_drill_right = True + else: + self.model.vehicle.can_drill_right = False + + if b: + if brick_bottom.color != "black": + self.model.vehicle.can_drill_down = True + else: + self.model.vehicle.can_drill_down = False r = pygame.Rect(brick.left, brick.top, brick.width, brick.height) @@ -134,7 +190,7 @@ def draw(self): self.model.vehicle.can_move_up = True else: - self.model.vehicle.can_move_up = False""" + self.model.vehicle.can_move_up = False #checks if the bottom of the vehicle + 6 px is more than or equal to the top of a brick and the top of the vehicle is less than the top of that brick and if its the brick in the same column if self.model.vehicle.top + self.model.vehicle.height + 3 >= brick.top and self.model.vehicle.top < brick.top and brick.rect.x - self.model.vehicle.rect.x < 9: @@ -148,7 +204,7 @@ def draw(self): self.model.can_move_down = True else: self.model.can_move_down = False - +""" if self.model.vehicle.top + self.model.vehicle.height + 3 >= brick.top and self.model.vehicle.top < brick.top and brick.rect.x < self.model.vehicle.rect.x and brick.rect.x + brick.width > self.model.vehicle.rect.x + self.model.vehicle.width: # print "x side of brick", brick.rect.x @@ -174,7 +230,7 @@ def draw(self): - if (not model.can_move_down) and (brick.left + brick.width >= self.model.vehicle.left) \ + """if (not model.can_move_down) and (brick.left + brick.width >= self.model.vehicle.left) \ and (brick.left < self.model.vehicle.left) and math.fabs(brick.top-self.model.vehicle.top) < 9: #checks if the vehicles can/should drill left if brick.color != "black": @@ -182,8 +238,8 @@ def draw(self): self.model.vehicle.can_drill_left = True else: - self.model.vehicle.can_drill_left = False - + self.model.vehicle.can_drill_left = False""" + if (not model.can_move_down) and (self.model.vehicle.left + brick.width >= brick.left) \ @@ -425,12 +481,11 @@ def handle_event(self, event): if model.temp_world[-1][0].top >= model.FAR_BOTTOM and model.temp_world[-1][0].top < model.FAR_BOTTOM + 40: mistake = model.FAR_BOTTOM - model.temp_world[-1][0].top - print "enlarging world" + #print "enlarging world" model.world_enlarger("down") keys = pygame.key.get_pressed() - print "can_move_up: ",model.vehicle.can_move_up if keys[pygame.K_UP] and model.vehicle.can_move_up: for top in range(len(model.temp_world)): @@ -454,8 +509,10 @@ def handle_event(self, event): elif keys[pygame.K_UP] and not model.vehicle.can_move_up: speed_y = 0 - if keys[pygame.K_LEFT] and model.vehicle.can_drill_left: - #print "somethings working??" + if keys[pygame.K_LEFT] and not model.vehicle.can_drill_left and not model.vehicle.can_move_left: + pass + elif keys[pygame.K_LEFT] and model.vehicle.can_drill_left: + print "just drilling" speed_x = .7 for top in range(len(model.temp_world)): for left in range(len(model.temp_world[top])): @@ -469,7 +526,8 @@ def handle_event(self, event): model.workshop.left += speed_x model.workshop.rect.x = model.workshop.left - if keys[pygame.K_LEFT] and not model.vehicle.can_drill_left: + elif keys[pygame.K_LEFT] and model.vehicle.can_move_left: + print "just movin'" speed_x = 2 for top in range(len(model.temp_world)): for left in range(len(model.temp_world[top])): @@ -505,7 +563,7 @@ def handle_event(self, event): model.workshop.left -= speed_x model.workshop.rect.x = model.workshop.left - if keys[pygame.K_RIGHT] and not model.vehicle.can_drill_right: + elif keys[pygame.K_RIGHT] and model.vehicle.can_move_right: speed_x = 2 for top in range(len(model.temp_world)): for left in range(len(model.temp_world[top])): From 72ed9eaaa4e68a997b96f69826229560a9a9e754 Mon Sep 17 00:00:00 2001 From: Sung Park Date: Thu, 10 Mar 2016 03:41:09 -0500 Subject: [PATCH 65/76] cabbage --- motherload2.py | 168 +------------------------------------------------ 1 file changed, 2 insertions(+), 166 deletions(-) diff --git a/motherload2.py b/motherload2.py index 84082e9..f2f9619 100644 --- a/motherload2.py +++ b/motherload2.py @@ -172,113 +172,8 @@ def draw(self): - - - - - - - #checks if the vehicle can move up - """if self.model.vehicle.top <= brick.top + brick.height and self.model.vehicle.top > brick.top and brick.rect.x - self.model.vehicle.rect.x < 9: - #if that brick isn't black, then the vehicle cant move - if brick.color != "black" and brick.rect.x < self.model.vehicle.rect.x and brick.rect.x + brick.width > self.model.vehicle.rect.x + self.model.vehicle.width: - self.model.vehicle.can_move_up = False - - - - elif brick.rect.x < self.model.vehicle.rect.x and brick.rect.x + brick.width > self.model.vehicle.rect.x + self.model.vehicle.width: - self.model.vehicle.can_move_up = True - - else: - self.model.vehicle.can_move_up = False - - #checks if the bottom of the vehicle + 6 px is more than or equal to the top of a brick and the top of the vehicle is less than the top of that brick and if its the brick in the same column - if self.model.vehicle.top + self.model.vehicle.height + 3 >= brick.top and self.model.vehicle.top < brick.top and brick.rect.x - self.model.vehicle.rect.x < 9: - #if that brick isn't black, then the vehicle cant move - if brick.color != "black" and brick.rect.x < self.model.vehicle.rect.x and brick.rect.x + brick.width > self.model.vehicle.rect.x + self.model.vehicle.width: - self.model.can_move_down = False - - - - elif brick.rect.x < self.model.vehicle.rect.x and brick.rect.x + brick.width > self.model.vehicle.rect.x + self.model.vehicle.width: - self.model.can_move_down = True - else: - self.model.can_move_down = False -""" - - if self.model.vehicle.top + self.model.vehicle.height + 3 >= brick.top and self.model.vehicle.top < brick.top and brick.rect.x < self.model.vehicle.rect.x and brick.rect.x + brick.width > self.model.vehicle.rect.x + self.model.vehicle.width: - # print "x side of brick", brick.rect.x - # print "x side of vehicle", self.model.vehicle.rect.x - # print self.model.vehicle.can_drill_down - # if brick.color != "black" and self.model.vehicle.rect.x - brick.rect.x < 9: - # self.model.vehicle.can_drill_down = True - - # else: - # self.model.vehicle.can_drill_down = False - - if brick.color != "black" and brick.rect.x < self.model.vehicle.rect.x and brick.rect.x + brick.width > self.model.vehicle.rect.x + self.model.vehicle.width: - self.model.vehicle.can_drill_down = True - - - - elif brick.rect.x < self.model.vehicle.rect.x and brick.rect.x + brick.width > self.model.vehicle.rect.x + self.model.vehicle.width: - self.model.vehicle.can_drill_down = False - - else: - self.model.vehicle.can_drill_down = True - - - - - """if (not model.can_move_down) and (brick.left + brick.width >= self.model.vehicle.left) \ - and (brick.left < self.model.vehicle.left) and math.fabs(brick.top-self.model.vehicle.top) < 9: #checks if the vehicles can/should drill left - - if brick.color != "black": - - self.model.vehicle.can_drill_left = True - else: - - self.model.vehicle.can_drill_left = False""" - - - - if (not model.can_move_down) and (self.model.vehicle.left + brick.width >= brick.left) \ - and (self.model.vehicle.left < brick.left) and math.fabs(brick.top-self.model.vehicle.top) < 9: #checks if the vehicles can/should drill right - - if brick.color != "black": - - self.model.vehicle.can_drill_right = True - else: - - self.model.vehicle.can_drill_right = False - - - - # elif not pygame.sprite.collide_rect(brick, self.model.vehicle): - # self.model.can_move_down = False - - #print "can move down", self.model.can_move_down - - - if self.model.vehicle.left + float(brick.width)/2 < brick.left and brick.left + float(brick.width)/2 > self.model.vehicle.left and not (brick.left > self.model.vehicle.left + float(brick.width)*3/2) \ - and brick.top > self.model.vehicle.top - brick.width/2 and brick.top + brick.height < self.model.vehicle.top + float(brick.width)*3/2: #checks if the vehicle has a block to the right - if brick.color != "black" and not model.can_move_down: - self.model.can_drill_right = True - #print "can move right", self.model.can_drill_right - else: - self.model.can_drill_right = False - # print "can move right", self.model.can_drill_right - # print "can move?", model.can_move_down - # print "vehicle left", self.model.vehicle.left - # print "brick left ", brick.left - # print "brick top", brick.top - # print "veh top", self.model.vehicle.top - # print "can drill right,", model.can_drill_right - # print self.model.can_drill_right if not (top == 0 or top ==1): if math.fabs(brick.left - self.model.vehicle.left) < 20 and math.fabs(self.model.vehicle.top - brick.top)<20: #checks if the vehicle overlaps a block, if so change block to black - if brick.brick_type != "empty" and brick.brick_type != "soil": - print "I am eating ...", brick.brick_type if brick.brick_type == "ruby": self.model.red_block += 1 self.model.score += 100 @@ -324,7 +219,6 @@ def draw(self): self.model.sprite_list.draw(self.screen) r = pygame.Rect(self.model.shop.left,self.model.shop.top,self.model.shop.width,self.model.shop.height) - #subpygame.draw.rect(self.screen, pygame.Color('yellow'), r) #Vehicle visiting fuel station if pygame.sprite.collide_rect(self.model.fuel_station, self.model.vehicle): @@ -392,61 +286,9 @@ def handle_event(self, event): if event.type != KEYDOWN: return - - # if event.key == pygame.K_LEFT: - # if self.model.temp_world[0][0].left != self.model.FAR_LEFT: - - # for top in range(len(self.model.temp_world)): - # for left in range(len(self.model.temp_world[top])): - # brick = self.model.temp_world[top][left] - # brick.left += brick.width - # brick.rect.x += brick.width #sprites stuff - # self.model.fuel_station.left += self.model.BRICK_HEIGHT - # self.model.fuel_station.rect.x += self.model.BRICK_HEIGHT - # self.model.shop.left += self.model.BRICK_HEIGHT - # self.model.shop.rect.x += self.model.BRICK_HEIGHT - # # print self.model.fuel_station.left - # # print self.model.fuel_station.rect.x - - # else: - # return - - # #if farthest block to left reachest threshold, add more blocks to left - # if self.model.temp_world[0][0].left == self.model.FAR_LEFT: - # self.model.world_enlarger("left") - - - # if event.key == pygame.K_RIGHT: - # if self.model.world[0][-1].left != self.model.FAR_RIGHT: - # for top in range(len(self.model.temp_world)): - # for left in range(len(self.model.temp_world[top])): - # brick = self.model.temp_world[top][left] - # brick.left -= brick.width - # brick.rect.x -= brick.width - # self.model.fuel_station.left -= self.model.BRICK_HEIGHT - # self.model.fuel_station.rect.x -= self.model.BRICK_HEIGHT - # self.model.shop.left -= self.model.BRICK_HEIGHT - # self.model.shop.rect.x -= self.model.BRICK_HEIGHT - # # print self.model.fuel_station.left - # # print self.model.fuel_station.rect.x - # else: - # return - # if self.model.world[0][-1].left == self.model.FAR_RIGHT: - # self.model.world_enlarger("right") - - - -class PyGameMouseController(object): - def __init__(self, model): - self.model = model - def handle_event(self, event): - """ Look for mouse movements and respond appropriately """ - if event.type != MOUSEMOTION: - return - self.model.paddle.left = event.pos[0] clock = pygame.time.Clock() @@ -465,7 +307,6 @@ def handle_event(self, event): model = game_model.BrickBreakerModel() view = PygameBrickBreakerView(model, screen) controller = PyGameKeyboardController(model) - #controller = PyGameMouseController(model) running = True while running: @@ -475,13 +316,11 @@ def handle_event(self, event): controller.handle_event(event) model.can_drill_right = False - # print " can drill right?", model.vehicle.can_drill_right - # print " can drill left?", model.vehicle.can_drill_left -# print "can drill right? ", model.vehicle.can_drill_right + if model.fuel < 0: + running = False if model.temp_world[-1][0].top >= model.FAR_BOTTOM and model.temp_world[-1][0].top < model.FAR_BOTTOM + 40: mistake = model.FAR_BOTTOM - model.temp_world[-1][0].top - #print "enlarging world" model.world_enlarger("down") @@ -512,7 +351,6 @@ def handle_event(self, event): if keys[pygame.K_LEFT] and not model.vehicle.can_drill_left and not model.vehicle.can_move_left: pass elif keys[pygame.K_LEFT] and model.vehicle.can_drill_left: - print "just drilling" speed_x = .7 for top in range(len(model.temp_world)): for left in range(len(model.temp_world[top])): @@ -527,7 +365,6 @@ def handle_event(self, event): model.workshop.rect.x = model.workshop.left elif keys[pygame.K_LEFT] and model.vehicle.can_move_left: - print "just movin'" speed_x = 2 for top in range(len(model.temp_world)): for left in range(len(model.temp_world[top])): @@ -587,7 +424,6 @@ def handle_event(self, event): elif keys[pygame.K_DOWN] and not model.can_move_down and model.vehicle.can_drill_down: - # print "juss drilling" speed_y = .7 for top in range(len(model.temp_world)): for left in range(len(model.temp_world[top])): From 1c16dd0d94880f507a87a4b2a91469e987393dc8 Mon Sep 17 00:00:00 2001 From: Sung Park Date: Thu, 10 Mar 2016 03:46:01 -0500 Subject: [PATCH 66/76] Renamed the file --- motherload.py | 449 +++++++++++++++++++--------------------------- motherload2.py | 472 ------------------------------------------------- 2 files changed, 181 insertions(+), 740 deletions(-) delete mode 100644 motherload2.py diff --git a/motherload.py b/motherload.py index 27a6b45..f2f9619 100644 --- a/motherload.py +++ b/motherload.py @@ -29,208 +29,183 @@ def draw(self): #pulls the appropriate brick model from the list - brick = self.model.temp_world[top][left] - brick_left = self.model.temp_world[top][left-1] - brick_top_left = self.model.temp_world[top-1][left-1] - brick_top_right = self.model.temp_world[top-1][left+1] - brick_bottom_left = self.model.temp_world[top+1][left-1] - brick_bottom_right = self.model.temp_world[top+1][left+1] - brick_right = self.model.temp_world[top][left+1] - brick_bottom = self.model.temp_world[top+1][left] - brick_top = self.model.temp_world[top-1][left] - - r = pygame.Rect(brick.left, brick.top, brick.width, brick.height) - - if pygame.sprite.collide_rect(brick,self.model.vehicle): - - if pygame.sprite.collide_rect(brick,brick_left): #checks collision with left - l = True - elif not pygame.sprite.collide_rect(brick,brick_left): - l = False - - elif pygame.sprite.collide_rect(brick,brick_right): #checks collision with right - r = True - elif not pygame.sprite.collide_rect(brick,brick_right): - r = False - - elif pygame.sprite.collide_rect(brick,brick_top): #checks collision with top - t = True - elif not pygame.sprite.collide_rect(brick,brick_top): - t = False - - elif pygame.sprite.collide_rect(brick,brick_bottom): #checks collision with bottom - b = True - elif not pygame.sprite.collide_rect(brick,brick_bottom): - b = False - - elif pygame.sprite.collide_rect(brick,brick_bottom_left): #checks collision with bottom left - bl = True - elif not pygame.sprite.collide_rect(brick,brick_bottom_left): - bl = False - - elif pygame.sprite.collide_rect(brick,brick_bottom_right): #checks collision with bottom right - br = True - elif not pygame.sprite.collide_rect(brick,brick_bottom_right): - br = False - - elif pygame.sprite.collide_rect(brick,brick_top_left): #checks collision with top left - tl = True - elif not pygame.sprite.collide_rect(brick,brick_top_left): - tl = False - - elif pygame.sprite.collide_rect(brick,brick_top_right): #checks collision with top right - tr = True - elif not pygame.sprite.collide_rect(brick,brick_top_right): - tr = False - - - - - - - - #checks if the - if self.model.vehicle.top <= brick.top + brick.height and self.model.vehicle.top - 30 > brick.top and self.model.vehicle.left - brick.left < 10 and brick.left + brick.width > self.model.vehicle.left + self.model.vehicle.width: - print "is this ever executed" - #if that brick isn't black, then the vehicle cant move - - - if brick.color != "black" and brick.rect.x < self.model.vehicle.rect.x and brick.rect.x + brick.width > self.model.vehicle.rect.x + self.model.vehicle.width: - self.model.vehicle.can_move_up = False - - - elif brick.rect.x < self.model.vehicle.rect.x and brick.rect.x + brick.width > self.model.vehicle.rect.x + self.model.vehicle.width: - self.model.vehicle.can_move_up = True - elif brick.rect.y != 24: - self.model.vehicle.can_move_up = True - elif brick.rect.y == 24 and brick.color == "black": - self.model.vehicle.can_move_up = True - else: - self.model.vehicle.can_move_up = False - - #checks if the bottom of the vehicle + 6 px is more than or equal to the top of a brick and the top of the vehicle is less than the top of that brick and if its the brick in the same column - if self.model.vehicle.top + self.model.vehicle.height + 3 >= brick.top and self.model.vehicle.top < brick.top and brick.rect.x - self.model.vehicle.rect.x < 9: - #if that brick isn't black, then the vehicle cant move - if brick.color != "black" and brick.rect.x < self.model.vehicle.rect.x and brick.rect.x + brick.width > self.model.vehicle.rect.x + self.model.vehicle.width: - self.model.can_move_down = False - - elif brick.rect.x < self.model.vehicle.rect.x and brick.rect.x + brick.width > self.model.vehicle.rect.x + self.model.vehicle.width: - self.model.can_move_down = True - elif not (brick.rect.y < 55 and brick.rect.y > 50): - self.model.can_move_down = True - elif brick.rect.y < 55 and brick.rect.y > 50 and brick.color == "black": - self.model.can_move_down = True - else: - self.model.can_move_down = False - - - if self.model.vehicle.top + self.model.vehicle.height + 3 >= brick.top and self.model.vehicle.top < brick.top and brick.rect.x < self.model.vehicle.rect.x and brick.rect.x + brick.width > self.model.vehicle.rect.x + self.model.vehicle.width: - # print "x side of brick", brick.rect.x - # print "x side of vehicle", self.model.vehicle.rect.x - # print self.model.vehicle.can_drill_down - # if brick.color != "black" and self.model.vehicle.rect.x - brick.rect.x < 9: - # self.model.vehicle.can_drill_down = True - - # else: - # self.model.vehicle.can_drill_down = False - - if brick.color != "black" and brick.rect.x < self.model.vehicle.rect.x and brick.rect.x + brick.width > self.model.vehicle.rect.x + self.model.vehicle.width: - self.model.vehicle.can_drill_down = True - - - - elif brick.rect.x < self.model.vehicle.rect.x and brick.rect.x + brick.width > self.model.vehicle.rect.x + self.model.vehicle.width: - self.model.vehicle.can_drill_down = False + brick = self.model.temp_world[top][left] + if not (left == 0 or top == 0 or top == len(self.model.temp_world) -1 or left == len(self.model.temp_world[0])-1) and pygame.sprite.collide_rect(brick,self.model.vehicle): + + brick_left = self.model.temp_world[top][left-1] + brick_top_left = self.model.temp_world[top-1][left-1] + brick_top_right = self.model.temp_world[top-1][left+1] + brick_bottom_left = self.model.temp_world[top+1][left-1] + brick_bottom_right = self.model.temp_world[top+1][left+1] + brick_right = self.model.temp_world[top][left+1] + brick_bottom = self.model.temp_world[top+1][left] + brick_top = self.model.temp_world[top-1][left] - else: - self.model.vehicle.can_drill_down = True - - - - - if (not model.can_move_down) and (brick.left + brick.width >= self.model.vehicle.left) \ - and (brick.left < self.model.vehicle.left) and math.fabs(brick.top-self.model.vehicle.top) < 9: #checks if the vehicles can/should drill left - - if brick.color != "black": - - self.model.vehicle.can_drill_left = True - else: - - self.model.vehicle.can_drill_left = False - - - - if (not model.can_move_down) and (self.model.vehicle.left + brick.width >= brick.left) \ - and (self.model.vehicle.left < brick.left) and math.fabs(brick.top-self.model.vehicle.top) < 9: #checks if the vehicles can/should drill right - - if brick.color != "black": - - self.model.vehicle.can_drill_right = True - else: + t = True + tl = True + tr = True + + l = True + r = True + + bl = True + b = True + br = True + + if pygame.sprite.collide_rect(brick,self.model.vehicle): + + if pygame.sprite.collide_rect(self.model.vehicle,brick_left): #checks collision with left + l = True + elif not pygame.sprite.collide_rect(self.model.vehicle,brick_left): + l = False + + if pygame.sprite.collide_rect(self.model.vehicle,brick_right): #checks collision with right + r = True + elif not pygame.sprite.collide_rect(self.model.vehicle,brick_right): + r = False + + if pygame.sprite.collide_rect(self.model.vehicle,brick_top): #checks collision with top + t = True + elif not pygame.sprite.collide_rect(self.model.vehicle,brick_top): + t = False + + if pygame.sprite.collide_rect(self.model.vehicle,brick_bottom): #checks collision with bottom + b = True + elif not pygame.sprite.collide_rect(self.model.vehicle,brick_bottom): + b = False + + if pygame.sprite.collide_rect(self.model.vehicle,brick_bottom_left): #checks collision with bottom left + bl = True + elif not pygame.sprite.collide_rect(self.model.vehicle,brick_bottom_left): + bl = False + + if pygame.sprite.collide_rect(self.model.vehicle,brick_bottom_right): #checks collision with bottom right + br = True + elif not pygame.sprite.collide_rect(self.model.vehicle,brick_bottom_right): + br = False + + if pygame.sprite.collide_rect(self.model.vehicle,brick_top_left): #checks collision with top left + tl = True + elif not pygame.sprite.collide_rect(self.model.vehicle,brick_top_left): + tl = False + + if pygame.sprite.collide_rect(self.model.vehicle,brick_top_right): #checks collision with top right + tr = True + elif not pygame.sprite.collide_rect(self.model.vehicle,brick_top_right): + tr = False + + #if brick.color == "black" and brick_bottom.color == "black": + #print "gravity is TRUE" + + #Collision detection using sprite collision + if t and not tl and not tr: + #print "tl",tl,"t: ",t, "tr", tr + if brick_top.color == "black": + self.model.vehicle.can_move_up = True + else: + self.model.vehicle.can_move_up = False + elif (tl and t): + if brick_top.color == "black" and brick_top_left.color == "black": + self.model.vehicle.can_move_up = True + else: + self.model.vehicle.can_move_up = False + elif (t and tr): + if brick_top.color == "black" and brick_top_right.color == "black": + self.model.vehicle.can_move_up = True + else: + self.model.vehicle.can_move_up = False + else: + self.model.vehicle.can_move_up = True + + if b and not bl and not br: + if brick_bottom.color == "black": + self.model.can_move_down = True + else: + self.model.can_move_down = False + elif b and bl: + if brick_bottom.color == "black" and brick_bottom_left == "black": + self.model.can_move_down = True + else: + self.model.can_move_down = False + elif b and br: + if brick_bottom.color == "black" and brick_bottom_right.color == "black": + self.model.can_move_down = True + else: + self.model.can_move_down = False + elif brick.color == "black" and not b and not bl and not br: + self.model.can_move_down = True + + if l and bl: + if brick_left.color == "black": + self.model.vehicle.can_move_left = True + else: + self.model.vehicle.can_move_left = False + + if r and br: + if brick_right.color == "black": + self.model.vehicle.can_move_right = True + else: + self.model.vehicle.can_move_right = False + + #Checks for drilling availability + if l and b and not self.model.can_move_down: + if brick_left.color != "black" and brick_bottom.color != "black": + #print "CAN DRILL!!" + self.model.vehicle.can_drill_left = True + else: + self.model.vehicle.can_drill_left = False + + if r and b and not self.model.can_move_down: + if brick_right.color != "black" and brick_bottom.color != "black": + self.model.vehicle.can_drill_right = True + else: + self.model.vehicle.can_drill_right = False + + if b: + if brick_bottom.color != "black": + self.model.vehicle.can_drill_down = True + else: + self.model.vehicle.can_drill_down = False + r = pygame.Rect(brick.left, brick.top, brick.width, brick.height) - self.model.vehicle.can_drill_right = False - - - - # elif not pygame.sprite.collide_rect(brick, self.model.vehicle): - # self.model.can_move_down = False + - #print "can move down", self.model.can_move_down - + if not (top == 0 or top ==1): + if math.fabs(brick.left - self.model.vehicle.left) < 20 and math.fabs(self.model.vehicle.top - brick.top)<20: #checks if the vehicle overlaps a block, if so change block to black + if brick.brick_type == "ruby": + self.model.red_block += 1 + self.model.score += 100 + brick.image.fill((0,0,0)) + brick.image.set_colorkey((0,0,0)) + elif brick.brick_type == "emerald": + self.model.green_block += 1 + self.model.score += 100 + brick.image.fill((0,0,0)) + brick.image.set_colorkey((0,0,0)) + elif brick.brick_type == "amazonite": + self.model.orange_block += 1 + self.model.score += 100 + brick.image.fill((0,0,0)) + brick.image.set_colorkey((0,0,0)) + elif brick.brick_type == "sapphire": + self.model.blue_block += 1 + self.model.score += 100 + brick.image.fill((0,0,0)) + brick.image.set_colorkey((0,0,0)) + elif brick.brick_type == "watsonite": + self.model.purple_block += 1 + self.model.score += 100 + brick.image.fill((0,0,0)) + brick.image.set_colorkey((0,0,0)) + + brick.color = "black" + brick.brick_type = "empty" + pygame.draw.rect(self.screen, pygame.Color(brick.color), r) - if self.model.vehicle.left + float(brick.width)/2 < brick.left and brick.left + float(brick.width)/2 > self.model.vehicle.left and not (brick.left > self.model.vehicle.left + float(brick.width)*3/2) \ - and brick.top > self.model.vehicle.top - brick.width/2 and brick.top + brick.height < self.model.vehicle.top + float(brick.width)*3/2: #checks if the vehicle has a block to the right - if brick.color != "black" and not model.can_move_down: - self.model.can_drill_right = True - #print "can move right", self.model.can_drill_right else: - self.model.can_drill_right = False - # print "can move right", self.model.can_drill_right - # print "can move?", model.can_move_down - # print "vehicle left", self.model.vehicle.left - # print "brick left ", brick.left - # print "brick top", brick.top - # print "veh top", self.model.vehicle.top - # print "can drill right,", model.can_drill_right - # print self.model.can_drill_right - - if math.fabs(brick.left - self.model.vehicle.left) < 20 and math.fabs(self.model.vehicle.top - brick.top)<20: #checks if the vehicle overlaps a block, if so change block to black - if brick.brick_type != "empty" and brick.brick_type != "soil": - print "I am eating ...", brick.brick_type - if brick.brick_type == "ruby": - self.model.red_block += 1 - self.model.score += 100 - brick.image.fill((0,0,0)) - brick.image.set_colorkey((0,0,0)) - elif brick.brick_type == "emerald": - self.model.green_block += 1 - self.model.score += 100 - brick.image.fill((0,0,0)) - brick.image.set_colorkey((0,0,0)) - elif brick.brick_type == "amazonite": - self.model.orange_block += 1 - self.model.score += 100 - brick.image.fill((0,0,0)) - brick.image.set_colorkey((0,0,0)) - elif brick.brick_type == "sapphire": - self.model.blue_block += 1 - self.model.score += 100 - brick.image.fill((0,0,0)) - brick.image.set_colorkey((0,0,0)) - elif brick.brick_type == "watsonite": - self.model.purple_block += 1 - self.model.score += 100 - brick.image.fill((0,0,0)) - brick.image.set_colorkey((0,0,0)) - - brick.color = "black" - brick.brick_type = "empty" - pygame.draw.rect(self.screen, pygame.Color(brick.color), r) - - else: - pygame.draw.rect(self.screen, pygame.Color(brick.color), r) + pygame.draw.rect(self.screen, pygame.Color(brick.color), r) @@ -244,7 +219,6 @@ def draw(self): self.model.sprite_list.draw(self.screen) r = pygame.Rect(self.model.shop.left,self.model.shop.top,self.model.shop.width,self.model.shop.height) - #subpygame.draw.rect(self.screen, pygame.Color('yellow'), r) #Vehicle visiting fuel station if pygame.sprite.collide_rect(self.model.fuel_station, self.model.vehicle): @@ -312,61 +286,9 @@ def handle_event(self, event): if event.type != KEYDOWN: return - - # if event.key == pygame.K_LEFT: - # if self.model.temp_world[0][0].left != self.model.FAR_LEFT: - - # for top in range(len(self.model.temp_world)): - # for left in range(len(self.model.temp_world[top])): - # brick = self.model.temp_world[top][left] - # brick.left += brick.width - # brick.rect.x += brick.width #sprites stuff - # self.model.fuel_station.left += self.model.BRICK_HEIGHT - # self.model.fuel_station.rect.x += self.model.BRICK_HEIGHT - # self.model.shop.left += self.model.BRICK_HEIGHT - # self.model.shop.rect.x += self.model.BRICK_HEIGHT - # # print self.model.fuel_station.left - # # print self.model.fuel_station.rect.x - - # else: - # return - - # #if farthest block to left reachest threshold, add more blocks to left - # if self.model.temp_world[0][0].left == self.model.FAR_LEFT: - # self.model.world_enlarger("left") - - - # if event.key == pygame.K_RIGHT: - # if self.model.world[0][-1].left != self.model.FAR_RIGHT: - # for top in range(len(self.model.temp_world)): - # for left in range(len(self.model.temp_world[top])): - # brick = self.model.temp_world[top][left] - # brick.left -= brick.width - # brick.rect.x -= brick.width - # self.model.fuel_station.left -= self.model.BRICK_HEIGHT - # self.model.fuel_station.rect.x -= self.model.BRICK_HEIGHT - # self.model.shop.left -= self.model.BRICK_HEIGHT - # self.model.shop.rect.x -= self.model.BRICK_HEIGHT - # # print self.model.fuel_station.left - # # print self.model.fuel_station.rect.x - # else: - # return - # if self.model.world[0][-1].left == self.model.FAR_RIGHT: - # self.model.world_enlarger("right") - - - -class PyGameMouseController(object): - def __init__(self, model): - self.model = model - def handle_event(self, event): - """ Look for mouse movements and respond appropriately """ - if event.type != MOUSEMOTION: - return - self.model.paddle.left = event.pos[0] clock = pygame.time.Clock() @@ -385,7 +307,6 @@ def handle_event(self, event): model = game_model.BrickBreakerModel() view = PygameBrickBreakerView(model, screen) controller = PyGameKeyboardController(model) - #controller = PyGameMouseController(model) running = True while running: @@ -395,20 +316,15 @@ def handle_event(self, event): controller.handle_event(event) model.can_drill_right = False -# if model.fuel < 0: -# running = False - - # print " can drill right?", model.vehicle.can_drill_right - # print " can drill left?", model.vehicle.can_drill_left - print "can drill right? ", model.vehicle.can_drill_right + if model.fuel < 0: + running = False if model.temp_world[-1][0].top >= model.FAR_BOTTOM and model.temp_world[-1][0].top < model.FAR_BOTTOM + 40: mistake = model.FAR_BOTTOM - model.temp_world[-1][0].top - print "enlarging world" model.world_enlarger("down") - keys = pygame.key.get_pressed() + keys = pygame.key.get_pressed() if keys[pygame.K_UP] and model.vehicle.can_move_up: for top in range(len(model.temp_world)): @@ -432,11 +348,9 @@ def handle_event(self, event): elif keys[pygame.K_UP] and not model.vehicle.can_move_up: speed_y = 0 - print "can_move_down????: ", model.can_move_down - - if keys[pygame.K_LEFT] and model.vehicle.can_drill_left and not model.can_move_down: - #print "somethings working??" - print "mining left" + if keys[pygame.K_LEFT] and not model.vehicle.can_drill_left and not model.vehicle.can_move_left: + pass + elif keys[pygame.K_LEFT] and model.vehicle.can_drill_left: speed_x = .7 for top in range(len(model.temp_world)): for left in range(len(model.temp_world[top])): @@ -450,7 +364,7 @@ def handle_event(self, event): model.workshop.left += speed_x model.workshop.rect.x = model.workshop.left - if keys[pygame.K_LEFT] and not model.vehicle.can_drill_left and not model.can_move_down: + elif keys[pygame.K_LEFT] and model.vehicle.can_move_left: speed_x = 2 for top in range(len(model.temp_world)): for left in range(len(model.temp_world[top])): @@ -471,9 +385,9 @@ def handle_event(self, event): elif speed_x > 10: speed_x = 10 - if keys[pygame.K_RIGHT] and model.vehicle.can_drill_right and not model.can_move_down: - #print "somethings working??" - speed_x = 0.7 + if keys[pygame.K_RIGHT] and model.vehicle.can_drill_right: + + speed_x = .7 for top in range(len(model.temp_world)): for left in range(len(model.temp_world[top])): brick = model.temp_world[top][left] @@ -486,7 +400,7 @@ def handle_event(self, event): model.workshop.left -= speed_x model.workshop.rect.x = model.workshop.left - if keys[pygame.K_RIGHT] and not model.vehicle.can_drill_right and not model.can_move_down: + elif keys[pygame.K_RIGHT] and model.vehicle.can_move_right: speed_x = 2 for top in range(len(model.temp_world)): for left in range(len(model.temp_world[top])): @@ -510,7 +424,6 @@ def handle_event(self, event): elif keys[pygame.K_DOWN] and not model.can_move_down and model.vehicle.can_drill_down: - # print "juss drilling" speed_y = .7 for top in range(len(model.temp_world)): for left in range(len(model.temp_world[top])): diff --git a/motherload2.py b/motherload2.py deleted file mode 100644 index f2f9619..0000000 --- a/motherload2.py +++ /dev/null @@ -1,472 +0,0 @@ -import pygame, os, sys -from pygame.locals import * -import time -from random import choice -import random -import game_model -import pygame, os, sys -import math - - -class PygameBrickBreakerView(object): - """ Visualizes a brick breaker game in a pygame window """ - def __init__(self, model, screen): - """ Initialize the view with the specified model - and screen. """ - self.model = model - self.screen = screen - - - def draw(self): - """ Draw the game state to the screen """ - myFont = pygame.font.SysFont("monospace",15) - game_over_font = pygame.font.SysFont("monospace",100) - - self.screen.fill(pygame.Color('black')) - # draw the bricks to the screen - for top in range(len(self.model.temp_world)): - for left in range(len(self.model.temp_world[top])): - - #pulls the appropriate brick model from the list - - - - brick = self.model.temp_world[top][left] - if not (left == 0 or top == 0 or top == len(self.model.temp_world) -1 or left == len(self.model.temp_world[0])-1) and pygame.sprite.collide_rect(brick,self.model.vehicle): - - brick_left = self.model.temp_world[top][left-1] - brick_top_left = self.model.temp_world[top-1][left-1] - brick_top_right = self.model.temp_world[top-1][left+1] - brick_bottom_left = self.model.temp_world[top+1][left-1] - brick_bottom_right = self.model.temp_world[top+1][left+1] - brick_right = self.model.temp_world[top][left+1] - brick_bottom = self.model.temp_world[top+1][left] - brick_top = self.model.temp_world[top-1][left] - - t = True - tl = True - tr = True - - l = True - r = True - - bl = True - b = True - br = True - - if pygame.sprite.collide_rect(brick,self.model.vehicle): - - if pygame.sprite.collide_rect(self.model.vehicle,brick_left): #checks collision with left - l = True - elif not pygame.sprite.collide_rect(self.model.vehicle,brick_left): - l = False - - if pygame.sprite.collide_rect(self.model.vehicle,brick_right): #checks collision with right - r = True - elif not pygame.sprite.collide_rect(self.model.vehicle,brick_right): - r = False - - if pygame.sprite.collide_rect(self.model.vehicle,brick_top): #checks collision with top - t = True - elif not pygame.sprite.collide_rect(self.model.vehicle,brick_top): - t = False - - if pygame.sprite.collide_rect(self.model.vehicle,brick_bottom): #checks collision with bottom - b = True - elif not pygame.sprite.collide_rect(self.model.vehicle,brick_bottom): - b = False - - if pygame.sprite.collide_rect(self.model.vehicle,brick_bottom_left): #checks collision with bottom left - bl = True - elif not pygame.sprite.collide_rect(self.model.vehicle,brick_bottom_left): - bl = False - - if pygame.sprite.collide_rect(self.model.vehicle,brick_bottom_right): #checks collision with bottom right - br = True - elif not pygame.sprite.collide_rect(self.model.vehicle,brick_bottom_right): - br = False - - if pygame.sprite.collide_rect(self.model.vehicle,brick_top_left): #checks collision with top left - tl = True - elif not pygame.sprite.collide_rect(self.model.vehicle,brick_top_left): - tl = False - - if pygame.sprite.collide_rect(self.model.vehicle,brick_top_right): #checks collision with top right - tr = True - elif not pygame.sprite.collide_rect(self.model.vehicle,brick_top_right): - tr = False - - #if brick.color == "black" and brick_bottom.color == "black": - #print "gravity is TRUE" - - #Collision detection using sprite collision - if t and not tl and not tr: - #print "tl",tl,"t: ",t, "tr", tr - if brick_top.color == "black": - self.model.vehicle.can_move_up = True - else: - self.model.vehicle.can_move_up = False - elif (tl and t): - if brick_top.color == "black" and brick_top_left.color == "black": - self.model.vehicle.can_move_up = True - else: - self.model.vehicle.can_move_up = False - elif (t and tr): - if brick_top.color == "black" and brick_top_right.color == "black": - self.model.vehicle.can_move_up = True - else: - self.model.vehicle.can_move_up = False - else: - self.model.vehicle.can_move_up = True - - if b and not bl and not br: - if brick_bottom.color == "black": - self.model.can_move_down = True - else: - self.model.can_move_down = False - elif b and bl: - if brick_bottom.color == "black" and brick_bottom_left == "black": - self.model.can_move_down = True - else: - self.model.can_move_down = False - elif b and br: - if brick_bottom.color == "black" and brick_bottom_right.color == "black": - self.model.can_move_down = True - else: - self.model.can_move_down = False - elif brick.color == "black" and not b and not bl and not br: - self.model.can_move_down = True - - if l and bl: - if brick_left.color == "black": - self.model.vehicle.can_move_left = True - else: - self.model.vehicle.can_move_left = False - - if r and br: - if brick_right.color == "black": - self.model.vehicle.can_move_right = True - else: - self.model.vehicle.can_move_right = False - - #Checks for drilling availability - if l and b and not self.model.can_move_down: - if brick_left.color != "black" and brick_bottom.color != "black": - #print "CAN DRILL!!" - self.model.vehicle.can_drill_left = True - else: - self.model.vehicle.can_drill_left = False - - if r and b and not self.model.can_move_down: - if brick_right.color != "black" and brick_bottom.color != "black": - self.model.vehicle.can_drill_right = True - else: - self.model.vehicle.can_drill_right = False - - if b: - if brick_bottom.color != "black": - self.model.vehicle.can_drill_down = True - else: - self.model.vehicle.can_drill_down = False - r = pygame.Rect(brick.left, brick.top, brick.width, brick.height) - - - - if not (top == 0 or top ==1): - if math.fabs(brick.left - self.model.vehicle.left) < 20 and math.fabs(self.model.vehicle.top - brick.top)<20: #checks if the vehicle overlaps a block, if so change block to black - if brick.brick_type == "ruby": - self.model.red_block += 1 - self.model.score += 100 - brick.image.fill((0,0,0)) - brick.image.set_colorkey((0,0,0)) - elif brick.brick_type == "emerald": - self.model.green_block += 1 - self.model.score += 100 - brick.image.fill((0,0,0)) - brick.image.set_colorkey((0,0,0)) - elif brick.brick_type == "amazonite": - self.model.orange_block += 1 - self.model.score += 100 - brick.image.fill((0,0,0)) - brick.image.set_colorkey((0,0,0)) - elif brick.brick_type == "sapphire": - self.model.blue_block += 1 - self.model.score += 100 - brick.image.fill((0,0,0)) - brick.image.set_colorkey((0,0,0)) - elif brick.brick_type == "watsonite": - self.model.purple_block += 1 - self.model.score += 100 - brick.image.fill((0,0,0)) - brick.image.set_colorkey((0,0,0)) - - brick.color = "black" - brick.brick_type = "empty" - pygame.draw.rect(self.screen, pygame.Color(brick.color), r) - - else: - pygame.draw.rect(self.screen, pygame.Color(brick.color), r) - - - - r = pygame.Rect(self.model.vehicle.left,self.model.vehicle.top,self.model.vehicle.width,self.model.vehicle.height) #the mining vehicle - - pygame.draw.rect(self.screen, pygame.Color('white'), r) - - r = pygame.Rect(self.model.fuel_station.left,self.model.fuel_station.top,self.model.fuel_station.width,self.model.fuel_station.height) - pygame.draw.rect(self.screen, pygame.Color('deep pink'),r) - - self.model.sprite_list.draw(self.screen) - - r = pygame.Rect(self.model.shop.left,self.model.shop.top,self.model.shop.width,self.model.shop.height) - - #Vehicle visiting fuel station - if pygame.sprite.collide_rect(self.model.fuel_station, self.model.vehicle): - self.model.fuel = self.model.max_fuel - - #Vehicle visiting shop - if pygame.sprite.collide_rect(self.model.shop, self.model.vehicle): - self.model.money += 100 * self.model.red_block - self.model.money += 100 * self.model.green_block - self.model.money += 100 * self.model.orange_block - self.model.money += 100 * self.model.blue_block - self.model.money += 100 * self.model.purple_block - self.model.red_block = 0 - self.model.green_block = 0 - self.model.orange_block = 0 - self.model.blue_block = 0 - self.model.purple_block = 0 - - #Vehicle visiting workshop - if pygame.sprite.collide_rect(self.model.workshop, self.model.vehicle): - if self.model.money >= 500: - self.model.money -= 500 - self.model.max_fuel += 500 - - if self.model.fuel <= 0: - msg = game_over_font.render("GAME OVER",1,(255,255,0)) - screen.blit(msg, (0, 240)) - else: - timer = myFont.render(str(self.model.fuel), 1, (255,255,0)) - screen.blit(timer, (20,20)) - - red_counter = myFont.render("Red: " + str(self.model.red_block), 1, (255,255,0)) - screen.blit(red_counter,(540,20)) - - green_counter = myFont.render("Green: " + str(self.model.green_block), 1, (255,255,0)) - screen.blit(green_counter,(540,40)) - - orange_counter = myFont.render("Orange: " + str(self.model.orange_block), 1, (255,255,0)) - screen.blit(orange_counter,(540,60)) - - blue_counter = myFont.render("Blue: " + str(self.model.blue_block), 1, (255,255,0)) - screen.blit(blue_counter,(540,80)) - - purple_counter = myFont.render("Purplpe: " + str(self.model.purple_block), 1, (255,255,0)) - screen.blit(purple_counter,(540,100)) - - money_counter = myFont.render("Money: " + str(self.model.money), 1, (255,255, 0)) - screen.blit(money_counter, (540,120)) - - score_counter = myFont.render("Score: " + str(self.model.score), 1, (255,255, 0)) - screen.blit(score_counter, (540,140)) - - pygame.display.update() - - - - -class PyGameKeyboardController(object): - def __init__(self, model): - self.model = model - - def handle_event(self, event): - """ Look for left and right keypresses to - modify the x position of the paddle """ - if event.type != KEYDOWN: - return - - - - - -clock = pygame.time.Clock() - -if __name__ == '__main__': - - - - speed_y = 0; - speed_x=0; - gravity = 0.25; - thruster = -0.05 - thruster_x = .025 - pygame.init() - size = (640, 480) - screen = pygame.display.set_mode(size) - model = game_model.BrickBreakerModel() - view = PygameBrickBreakerView(model, screen) - controller = PyGameKeyboardController(model) - - running = True - while running: - for event in pygame.event.get(): - if event.type == QUIT: - running = False - controller.handle_event(event) - model.can_drill_right = False - - if model.fuel < 0: - running = False - - if model.temp_world[-1][0].top >= model.FAR_BOTTOM and model.temp_world[-1][0].top < model.FAR_BOTTOM + 40: - mistake = model.FAR_BOTTOM - model.temp_world[-1][0].top - model.world_enlarger("down") - - - keys = pygame.key.get_pressed() - if keys[pygame.K_UP] and model.vehicle.can_move_up: - - for top in range(len(model.temp_world)): - for left in range(len(model.temp_world[top])): - brick = model.temp_world[top][left] - brick.top -= speed_y - brick.rect.y = brick.top - model.fuel_station.top -= speed_y - model.fuel_station.rect.y = model.fuel_station.top - model.shop.top -= speed_y - model.shop.rect.y = model.shop.top - model.workshop.top -= speed_y - model.workshop.rect.y = model.workshop.top - - speed_y = speed_y + thruster; - - if speed_y > 1: - speed_y = 0 - elif speed_y > 10: - speed_y = 10 - elif keys[pygame.K_UP] and not model.vehicle.can_move_up: - speed_y = 0 - - if keys[pygame.K_LEFT] and not model.vehicle.can_drill_left and not model.vehicle.can_move_left: - pass - elif keys[pygame.K_LEFT] and model.vehicle.can_drill_left: - speed_x = .7 - for top in range(len(model.temp_world)): - for left in range(len(model.temp_world[top])): - brick = model.temp_world[top][left] - brick.left += speed_x - brick.rect.x = brick.left - model.fuel_station.left += speed_x - model.fuel_station.rect.x = model.fuel_station.left - model.shop.left += speed_x - model.shop.rect.x = model.shop.left - model.workshop.left += speed_x - model.workshop.rect.x = model.workshop.left - - elif keys[pygame.K_LEFT] and model.vehicle.can_move_left: - speed_x = 2 - for top in range(len(model.temp_world)): - for left in range(len(model.temp_world[top])): - brick = model.temp_world[top][left] - brick.left += speed_x - brick.rect.x = brick.left - model.fuel_station.left += speed_x - model.fuel_station.rect.x = model.fuel_station.left - model.shop.left += speed_x - model.shop.rect.x = model.shop.left - model.workshop.left += speed_x - model.workshop.rect.x = model.workshop.left - - speed_x = speed_x + thruster_x; - - if speed_x > 1: - speed_x = 0 - elif speed_x > 10: - speed_x = 10 - - if keys[pygame.K_RIGHT] and model.vehicle.can_drill_right: - - speed_x = .7 - for top in range(len(model.temp_world)): - for left in range(len(model.temp_world[top])): - brick = model.temp_world[top][left] - brick.left -= speed_x - brick.rect.x = brick.left - model.fuel_station.left -= speed_x - model.fuel_station.rect.x = model.fuel_station.left - model.shop.left -= speed_x - model.shop.rect.x = model.shop.left - model.workshop.left -= speed_x - model.workshop.rect.x = model.workshop.left - - elif keys[pygame.K_RIGHT] and model.vehicle.can_move_right: - speed_x = 2 - for top in range(len(model.temp_world)): - for left in range(len(model.temp_world[top])): - brick = model.temp_world[top][left] - brick.left -= speed_x - brick.rect.x = brick.left - - model.fuel_station.left -= speed_x - model.fuel_station.rect.x = model.fuel_station.left - model.shop.left -= speed_x - model.shop.rect.x = model.shop.left - model.workshop.left -= speed_x - model.workshop.rect.x = model.workshop.left - - speed_x = speed_x + thruster_x; - - if speed_x > 1: - speed_x = 0 - elif speed_x > 10: - speed_x = 10 - - - elif keys[pygame.K_DOWN] and not model.can_move_down and model.vehicle.can_drill_down: - speed_y = .7 - for top in range(len(model.temp_world)): - for left in range(len(model.temp_world[top])): - brick = model.temp_world[top][left] - brick.top -= speed_y - brick.rect.y = brick.top - model.fuel_station.top -= speed_y - model.fuel_station.rect.y = model.fuel_station.top - model.shop.top -= speed_y - model.shop.rect.y = model.shop.top - model.workshop.top -= speed_y - model.workshop.rect.y = model.workshop.top - - elif model.can_move_down and not keys[pygame.K_UP]: - for top in range(len(model.temp_world)): - for left in range(len(model.temp_world[top])): - brick = model.temp_world[top][left] - brick.top -= speed_y - brick.rect.y = brick.top - - - model.fuel_station.top -= speed_y - - model.fuel_station.rect.y = model.fuel_station.top - - model.shop.top -= speed_y - model.shop.rect.y = model.shop.top - - model.workshop.top -= speed_y - model.workshop.rect.y = model.workshop.top - - speed_y = speed_y + gravity - if speed_y > 12: - speed_y -=.5 - - - - if not model.can_move_down and event.type != KEYDOWN: - speed_y = 0 - if not model.vehicle.can_drill_left and not model.vehicle.can_drill_right and event.type != KEYDOWN: - speed_x = 0 - - - model.fuel -= 1 #decrease fuel value every frame - view.draw() - From 11c992f47aebb1e9c438663cefea3919ab3be35a Mon Sep 17 00:00:00 2001 From: "willem.thorbecke@students.olin.edu" Date: Thu, 10 Mar 2016 14:16:22 -0500 Subject: [PATCH 67/76] renamed a class --- game_model.py | 2 +- motherload.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/game_model.py b/game_model.py index 1d66ae4..dd339c1 100644 --- a/game_model.py +++ b/game_model.py @@ -210,7 +210,7 @@ def __init__(self, left, top, width, height, cheatcode): self.image.fill((0,220,255)) -class BrickBreakerModel(object): +class BrickModel(object): """ Stores the game state for our brick breaker game """ def __init__(self): #self.bricks = [][] diff --git a/motherload.py b/motherload.py index f2f9619..2b26dc8 100644 --- a/motherload.py +++ b/motherload.py @@ -304,7 +304,7 @@ def handle_event(self, event): pygame.init() size = (640, 480) screen = pygame.display.set_mode(size) - model = game_model.BrickBreakerModel() + model = game_model.BrickModel() view = PygameBrickBreakerView(model, screen) controller = PyGameKeyboardController(model) From 5a1d493075ed38456518b07a68ff947dc3f96d61 Mon Sep 17 00:00:00 2001 From: "willem.thorbecke@students.olin.edu" Date: Thu, 10 Mar 2016 14:19:46 -0500 Subject: [PATCH 68/76] changed some class names --- motherload.py | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/motherload.py b/motherload.py index 2b26dc8..af9612f 100644 --- a/motherload.py +++ b/motherload.py @@ -8,7 +8,7 @@ import math -class PygameBrickBreakerView(object): +class GameViewer(object): """ Visualizes a brick breaker game in a pygame window """ def __init__(self, model, screen): """ Initialize the view with the specified model @@ -276,16 +276,6 @@ def draw(self): -class PyGameKeyboardController(object): - def __init__(self, model): - self.model = model - - def handle_event(self, event): - """ Look for left and right keypresses to - modify the x position of the paddle """ - if event.type != KEYDOWN: - return - @@ -305,16 +295,15 @@ def handle_event(self, event): size = (640, 480) screen = pygame.display.set_mode(size) model = game_model.BrickModel() - view = PygameBrickBreakerView(model, screen) - controller = PyGameKeyboardController(model) + view = GameViewer(model, screen) + running = True while running: for event in pygame.event.get(): if event.type == QUIT: running = False - controller.handle_event(event) - model.can_drill_right = False + if model.fuel < 0: running = False From 6053435672196447896a3b682831a20b444d10fe Mon Sep 17 00:00:00 2001 From: Sung Park Date: Thu, 10 Mar 2016 14:29:37 -0500 Subject: [PATCH 69/76] Add installation instruction to readme --- README.md | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 61ec120..af34141 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,14 @@ # InteractiveProgramming -This is the base repo for the interactive programming project for Software Design, Spring 2016 at Olin College. +@authors: Sung Park, Willem Thorbecke + +*Motherload: Cabbage Rendition* is a recreation of Motherload using pygame. This project was created as a part of Olin College Software Design course for Spring 2016. + +##Install + +To run *Motherload: Cabbage Rendition*, you need to install pygame. + +Run below code in your terminal to intsall pygame. + +``` +$ sudo apt-get install python-pygame +``` From fdf846b4988eafc81eb51fb1d1db57935628eb86 Mon Sep 17 00:00:00 2001 From: Sung Park Date: Thu, 10 Mar 2016 14:32:59 -0500 Subject: [PATCH 70/76] Update README --- README.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/README.md b/README.md index af34141..554a398 100644 --- a/README.md +++ b/README.md @@ -12,3 +12,15 @@ Run below code in your terminal to intsall pygame. ``` $ sudo apt-get install python-pygame ``` + +Download the repository to your local environment through cloning this repository or downloading as a zip. + +##Run + +Run motherload.py to start the program. + +``` +python motherload.py +``` + +You are all set. Enjoy the game. From 7b50cb91390b0ff7cb99e9ac2f31e372c82f0c2b Mon Sep 17 00:00:00 2001 From: Sung Park Date: Thu, 10 Mar 2016 14:34:16 -0500 Subject: [PATCH 71/76] Updated the code to run in README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 554a398..e8553f7 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ Download the repository to your local environment through cloning this repositor Run motherload.py to start the program. ``` -python motherload.py +$ python motherload.py ``` You are all set. Enjoy the game. From 31eb139a6c5e84271895acf909c14e23a8f49f6f Mon Sep 17 00:00:00 2001 From: Sung Park Date: Thu, 10 Mar 2016 14:46:53 -0500 Subject: [PATCH 72/76] Add documentation for game_model --- game_model.py | 72 +++++++++++++++++++++------------------------------ 1 file changed, 30 insertions(+), 42 deletions(-) diff --git a/game_model.py b/game_model.py index dd339c1..74b4c24 100644 --- a/game_model.py +++ b/game_model.py @@ -4,13 +4,20 @@ from pygame.locals import QUIT, KEYDOWN, MOUSEMOTION import time """ - Class containing game model and all its components + Class containing the game model and all its components """ class Brick(pygame.sprite.Sprite): + """ + Creates a brick class + + Key attributes: color, type + "Brown" color represents soil and "Black" color represents an empty spot + """ + - # Constructor. Pass in the color of the block, + # Constructor. Pass in the color of the brick, # and its x and y position def __init__(self, left, top, width, height, first): # Call the parent class (Sprite) constructor @@ -24,7 +31,8 @@ def __init__(self, left, top, width, height, first): # Fetch the rectangle object that has the dimensions of the image # Update the position of this object by setting the values of rect.x and rect.y self.rect = self.image.get_rect() - + + #This if statement is executed during initalized of the world at the start of the game. if first: self.rect.x = left*width - width*9 #renders 9 extra columns of blocks off screen to the left self.rect.y = top*height #top*height + height*2 - 1 #starts the world with a 2 block high sky @@ -61,7 +69,7 @@ def __init__(self, left, top, width, height, first): elif self.brick_type == "watsonite": self.image = pygame.image.load('watsonite.png').convert() self.image.set_colorkey((255,255,255)) - #self.image.fill((0,220,255)) + #This else statement is executed during "terrain generation" phase of the game else: self.rect.x = left self.rect.y = top @@ -94,27 +102,16 @@ def __init__(self, left, top, width, height, first): elif self.brick_type == "watsonite": self.image = pygame.image.load('watsonite.png').convert() self.image.set_colorkey((255,255,255)) - #self.image.fill((0,220,255)) -# class FuelStation(object): -# """ Represents a fuel station as a pink block at fixed point""" -# def __init__(self): -# self.left = 400 -# self.top = 40 -# self.width = 40 -# self.height = 40 - class FuelStation(pygame.sprite.Sprite): + """ + Fuel station object. It has the fixed position of (400,40) + """ - # Constructor. Pass in the color of the block, - # and its x and y position def __init__(self): - # Call the parent class (Sprite) constructor pygame.sprite.Sprite.__init__(self) - # Create an image of the block, and fill it with a color. - # This could also be an image loaded from the disk. self.image = pygame.image.load('fuel_station.gif').convert() self.left = 400 @@ -133,6 +130,7 @@ def __init__(self): class Workshop(pygame.sprite.Sprite): """ Workshop tile where the vehicle can upgrade its fuel tank + Fixed position at (560, 40) """ def __init__(self): pygame.sprite.Sprite.__init__(self) @@ -148,15 +146,13 @@ def __init__(self): class Shop(pygame.sprite.Sprite): + """ + Shop tile where the vehicle can sell its minerals. + It has the fixed position at (480,40) + """ - # Constructor. Pass in the color of the block, - # and its x and y position def __init__(self): - # Call the parent class (Sprite) constructor pygame.sprite.Sprite.__init__(self) - - # Create an image of the block, and fill it with a color. - # This could also be an image loaded from the disk. self.image = pygame.image.load('store.jpg').convert() self.rect = self.image.get_rect() @@ -167,25 +163,19 @@ def __init__(self): self.rect.x = 480 self.rect.y = 40 - # Fetch the rectangle object that has the dimensions of the image - # Update the position of this object by setting the values of rect.x and rect.y class Vehicle(pygame.sprite.Sprite): - """ Represents the paddle in our brick breaker game """ + """ Represents the vehicle""" - def __init__(self, left, top, width, height, cheatcode): - # Call the parent class (Sprite) constructor + def __init__(self, left, top, width, height): pygame.sprite.Sprite.__init__(self) - # Create an image of the block, and fill it with a color. - # This could also be an image loaded from the disk. self.image = pygame.Surface([width, height]) - # Fetch the rectangle object that has the dimensions of the image - # Update the position of this object by setting the values of rect.x and rect.y + #Attributes that checks for the available action at the vehicle's current position self.rect = self.image.get_rect() self.can_drill_left = False self.can_drill_right = False @@ -199,7 +189,6 @@ def __init__(self, left, top, width, height, cheatcode): self.width = width self.height = height self.thruster = False - self.cheatcode = cheatcode self.speed = 0 self.gravity = .1 @@ -231,9 +220,9 @@ def __init__(self): self.init_width_dist = 34 #number of columns of blocks self.sprite_list = pygame.sprite.Group() #a list of sprites to be drawn - #initialize world + #initialize world for top in range(0,self.init_height_dist): self.world.append([]) for left in range(0,self.init_width_dist): @@ -244,8 +233,8 @@ def __init__(self): self.sprite_list.add(brick) self.temp_world = self.world - self.fuel = 1000 - self.max_fuel = 1000 + self.fuel = 3000 + self.max_fuel = 3000 #counter for minerals self.red_block = 0 @@ -258,8 +247,7 @@ def __init__(self): self.score = 0 - cheatcode = "dpapp" - self.vehicle = Vehicle(40*8,25, 25, 25, cheatcode) + self.vehicle = Vehicle(40*8,25, 25, 25) self.fuel_station = FuelStation() self.sprite_list.add(self.fuel_station) @@ -269,6 +257,9 @@ def __init__(self): self.sprite_list.add(self.workshop) def world_enlarger(self, what_side): + """ + Function that enlarges the array that represents the map in our game when the vehicle reaches the bottom of the array + """ if what_side == "left": pass @@ -287,6 +278,3 @@ def world_enlarger(self, what_side): self.world[-1].append(brick) if brick.brick_type != "soil" and brick.brick_type != "empty": self.sprite_list.add(brick) - - def get_elapsed_time(self): - return pygame.time.get_ticks() From 9fe7c4532a6a0b001a6d11791aec796d24765676 Mon Sep 17 00:00:00 2001 From: "willem.thorbecke@students.olin.edu" Date: Thu, 10 Mar 2016 14:46:57 -0500 Subject: [PATCH 73/76] added comments --- motherload.py | 71 +++++++++++++++++++++++++++++++-------------------- 1 file changed, 44 insertions(+), 27 deletions(-) diff --git a/motherload.py b/motherload.py index af9612f..21f397e 100644 --- a/motherload.py +++ b/motherload.py @@ -9,7 +9,7 @@ class GameViewer(object): - """ Visualizes a brick breaker game in a pygame window """ + """ Visualizes the game world defined by the brick objects, vehicle, shop, workshop and fuel station""" def __init__(self, model, screen): """ Initialize the view with the specified model and screen. """ @@ -18,22 +18,24 @@ def __init__(self, model, screen): def draw(self): - """ Draw the game state to the screen """ + """ Draws the game state to the screen """ + myFont = pygame.font.SysFont("monospace",15) game_over_font = pygame.font.SysFont("monospace",100) self.screen.fill(pygame.Color('black')) - # draw the bricks to the screen + + # draw the block to the screen for top in range(len(self.model.temp_world)): for left in range(len(self.model.temp_world[top])): - #pulls the appropriate brick model from the list - - - + #pulls the appropriate block model from the list brick = self.model.temp_world[top][left] + + #if there are bricks surrounding the current block, then continue if not (left == 0 or top == 0 or top == len(self.model.temp_world) -1 or left == len(self.model.temp_world[0])-1) and pygame.sprite.collide_rect(brick,self.model.vehicle): + #define the 8 surrounding bricks brick_left = self.model.temp_world[top][left-1] brick_top_left = self.model.temp_world[top-1][left-1] brick_top_right = self.model.temp_world[top-1][left+1] @@ -43,6 +45,7 @@ def draw(self): brick_bottom = self.model.temp_world[top+1][left] brick_top = self.model.temp_world[top-1][left] + #predefines collision which the surrounding blocks as True t = True tl = True tr = True @@ -54,14 +57,15 @@ def draw(self): b = True br = True + #checks collision with each surround block, and if touching, sets the collision variable to True, else false if pygame.sprite.collide_rect(brick,self.model.vehicle): - if pygame.sprite.collide_rect(self.model.vehicle,brick_left): #checks collision with left + if pygame.sprite.collide_rect(self.model.vehicle,brick_left): #checks collision with left brick l = True elif not pygame.sprite.collide_rect(self.model.vehicle,brick_left): l = False - if pygame.sprite.collide_rect(self.model.vehicle,brick_right): #checks collision with right + if pygame.sprite.collide_rect(self.model.vehicle,brick_right): #checks collision with right r = True elif not pygame.sprite.collide_rect(self.model.vehicle,brick_right): r = False @@ -96,12 +100,11 @@ def draw(self): elif not pygame.sprite.collide_rect(self.model.vehicle,brick_top_right): tr = False - #if brick.color == "black" and brick_bottom.color == "black": - #print "gravity is TRUE" + - #Collision detection using sprite collision + #checks if there are blocks above, and if so, dissallow the user from traveling upwards if t and not tl and not tr: - #print "tl",tl,"t: ",t, "tr", tr + if brick_top.color == "black": self.model.vehicle.can_move_up = True else: @@ -119,6 +122,7 @@ def draw(self): else: self.model.vehicle.can_move_up = True + #checks if there are blocks below, if not, allow for free fall if b and not bl and not br: if brick_bottom.color == "black": self.model.can_move_down = True @@ -137,6 +141,7 @@ def draw(self): elif brick.color == "black" and not b and not bl and not br: self.model.can_move_down = True + #checks if there are bricks touching to the left and bottom, if so turn on drilling if l and bl: if brick_left.color == "black": self.model.vehicle.can_move_left = True @@ -149,10 +154,10 @@ def draw(self): else: self.model.vehicle.can_move_right = False - #Checks for drilling availability + #checks for drilling to the right, True if there are blocks to the right if l and b and not self.model.can_move_down: if brick_left.color != "black" and brick_bottom.color != "black": - #print "CAN DRILL!!" + self.model.vehicle.can_drill_left = True else: self.model.vehicle.can_drill_left = False @@ -168,12 +173,13 @@ def draw(self): self.model.vehicle.can_drill_down = True else: self.model.vehicle.can_drill_down = False + + r = pygame.Rect(brick.left, brick.top, brick.width, brick.height) - - + #checks if player has mined a mineral, if so increments the mineral count if not (top == 0 or top ==1): - if math.fabs(brick.left - self.model.vehicle.left) < 20 and math.fabs(self.model.vehicle.top - brick.top)<20: #checks if the vehicle overlaps a block, if so change block to black + if math.fabs(brick.left - self.model.vehicle.left) < 20 and math.fabs(self.model.vehicle.top - brick.top)<20: #checks if the vehicle overlaps a block, if so change block to black (empty) if brick.brick_type == "ruby": self.model.red_block += 1 self.model.score += 100 @@ -208,20 +214,21 @@ def draw(self): pygame.draw.rect(self.screen, pygame.Color(brick.color), r) - + r = pygame.Rect(self.model.vehicle.left,self.model.vehicle.top,self.model.vehicle.width,self.model.vehicle.height) #the mining vehicle - pygame.draw.rect(self.screen, pygame.Color('white'), r) + pygame.draw.rect(self.screen, pygame.Color('white'), r) + + r = pygame.Rect(self.model.fuel_station.left,self.model.fuel_station.top,self.model.fuel_station.width,self.model.fuel_station.height) #defines fuel station - r = pygame.Rect(self.model.fuel_station.left,self.model.fuel_station.top,self.model.fuel_station.width,self.model.fuel_station.height) pygame.draw.rect(self.screen, pygame.Color('deep pink'),r) self.model.sprite_list.draw(self.screen) - r = pygame.Rect(self.model.shop.left,self.model.shop.top,self.model.shop.width,self.model.shop.height) + r = pygame.Rect(self.model.shop.left,self.model.shop.top,self.model.shop.width,self.model.shop.height) #defines the shop #Vehicle visiting fuel station - if pygame.sprite.collide_rect(self.model.fuel_station, self.model.vehicle): + if pygame.sprite.collide_rect(self.model.fuel_station, self.model.vehicle): #checks collision with fuel station self.model.fuel = self.model.max_fuel #Vehicle visiting shop @@ -243,6 +250,7 @@ def draw(self): self.model.money -= 500 self.model.max_fuel += 500 + #ends game if player runs out of fuels if self.model.fuel <= 0: msg = game_over_font.render("GAME OVER",1,(255,255,0)) screen.blit(msg, (0, 240)) @@ -250,6 +258,7 @@ def draw(self): timer = myFont.render(str(self.model.fuel), 1, (255,255,0)) screen.blit(timer, (20,20)) + #increments minterals based on drilling red_counter = myFont.render("Red: " + str(self.model.red_block), 1, (255,255,0)) screen.blit(red_counter,(540,20)) @@ -285,7 +294,8 @@ def draw(self): if __name__ == '__main__': - + #predefines speed and thurster + gravity values + #defines model and view class as objects speed_y = 0; speed_x=0; gravity = 0.25; @@ -299,21 +309,25 @@ def draw(self): running = True + #for loop that runs the game while running: + for event in pygame.event.get(): if event.type == QUIT: running = False - if model.fuel < 0: running = False + #checks if the world should enlarge if model.temp_world[-1][0].top >= model.FAR_BOTTOM and model.temp_world[-1][0].top < model.FAR_BOTTOM + 40: mistake = model.FAR_BOTTOM - model.temp_world[-1][0].top model.world_enlarger("down") - + #checks for key press keys = pygame.key.get_pressed() + + if keys[pygame.K_UP] and model.vehicle.can_move_up: for top in range(len(model.temp_world)): @@ -337,15 +351,18 @@ def draw(self): elif keys[pygame.K_UP] and not model.vehicle.can_move_up: speed_y = 0 + if keys[pygame.K_LEFT] and not model.vehicle.can_drill_left and not model.vehicle.can_move_left: pass elif keys[pygame.K_LEFT] and model.vehicle.can_drill_left: speed_x = .7 + #loops through the game model and moves all the blocks appropriately based off of key press for top in range(len(model.temp_world)): for left in range(len(model.temp_world[top])): brick = model.temp_world[top][left] brick.left += speed_x brick.rect.x = brick.left + #moves all game objects appropriately bassed off of key presses model.fuel_station.left += speed_x model.fuel_station.rect.x = model.fuel_station.left model.shop.left += speed_x @@ -426,6 +443,7 @@ def draw(self): model.workshop.top -= speed_y model.workshop.rect.y = model.workshop.top + elif model.can_move_down and not keys[pygame.K_UP]: for top in range(len(model.temp_world)): for left in range(len(model.temp_world[top])): @@ -449,7 +467,6 @@ def draw(self): speed_y -=.5 - if not model.can_move_down and event.type != KEYDOWN: speed_y = 0 if not model.vehicle.can_drill_left and not model.vehicle.can_drill_right and event.type != KEYDOWN: From 35da2a5df892a75765cdd51f783c4a38e39cc64d Mon Sep 17 00:00:00 2001 From: Sung Park Date: Thu, 10 Mar 2016 15:08:41 -0500 Subject: [PATCH 74/76] Add writeup file --- writeup.pdf | Bin 0 -> 225675 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 writeup.pdf diff --git a/writeup.pdf b/writeup.pdf new file mode 100644 index 0000000000000000000000000000000000000000..930dac246bf13f64a9ddec91a518a8dccf3452d3 GIT binary patch literal 225675 zcmc$_byy@%vo46cyEZ+zTjTD|;O-8CyEC{94uk99PQze>yX)ZY?lSnm^83DX?>*<9 zeRl6(yZt=fky#a$8TrPWQJqnhRLT-kOl-`YNK{=91#d`fTtHT!qv;nU0RbS3f{lZP ziHnVog*lMzqXuMW=j7t%1hU8g^?=-5JU})sPM`shMG45x3S^N4a)DSmK|q$zKrSGQ z`ajAbHa4J;5R!$1`9CcJ|G)eov2p*Wfv9^sSpZqIRV^$(hGF4g*49KGO z0R$V6{p0%qgRFzOh1Wj^xPa_j|2|;p2xRB|utOEdqUz}A24v&;cSY?3Qy>TXzgqP8 zH&X2XJ31_~5x zHx~;NdnB)HGgI>|D`Qh*9z@FYPAEhvGYn6<$UlfO2;m`=NkO5y+zAN!ut~H~SW!Sk zDPUTn5n)kCP@)191Zp~h(Lb*IkCy)baO(dK(f?jY`WL?cgT2ZoRu-;65bM7o|2GB1 zP25cE9IgHnE7|_>&;PjO|CSJHA6);RwBh0YuV@+@e_&}0M-i5T0)?UsVF?0(Au<@1 zsM+-W^4hp}{r_G(-=d(jFOvRVrPuFifz*LQbP{8O?xTSVfP)*N8#hPe~2yV_QCvr)udU0Ahv(EC(Q-~vHz?1567iGy8D-g z)Q84@^eFYA@lT-m;I$Mx5cF?~|D&wz;%KI3@nM_ZM_EGZBMw-2xqVCx`ww4;{f89) z4=MX$;Xl{>+cW=o>p!`L{U2NYAKmirdCUgn;{7n?f6QtQ5a&NL^MBF(T-!E*WZqrq zVZM2D9W)E-xLsQIKASwN@zAOyJx9@%tz48tfYD|VAqImJG-Y6lVkrS}b=AgB!*HxU zTy>(9ls!@B33FQsIB3p5kDVx*P`qC}^nU$MyCE?+ekH#!am zk|AzfAnH#mY=zoAqi=cOSskIA$duu-qF-t$?%TI%%N^+SpQtM-4DkK zx6dk=thz!h#o3}=Y;gWDzWsFeZo~L8X6w1mqhw@eKmL&KcidfLd-(QpOgCCdlILsV1A1HdTMc0EUO1QE1K_$P#eh{CjE`x!RfC?V+p zsJ=Zzf)b-Jl65FvIOU=#QOq||%{o+Y;u^&1$hi}9MvP%8_KeVb5H>=&ooA9Dt;kG%v9FJ<{Hv89kQ6#E8nxT zE;I2QggEhf!z}cIoOlILZI9*prMJVpe!DNd`Ssgd-O;~7;L)v87)idU`O~$3?$S`@ za`8}g70kiOT`zL#{qxFFLgQ?&Y31Kv0-A5R^QIOSV-^ z@@j^WNM%m^m)buupc&`8OR;IWY9{@}cR&SYA#JK31XYsXu-oUi+)nEB>oCFvM5XuTY-d=T0<-&7H^_ znVgvX9NYBkBz$O{aoiMM%agx_?*d}Ai+=@=B1_I*bG6-UEbe|L!_W86xLv0{bG4&z zowxK$RED3ohetzoP6kD%aBEj7NRRjTLb&v*Picfb|4QYpeY%16k)Oucc_A|L6RdvE z@g>d1%U{}{2mC6bHV91ZcUs<7-WpzArb7+UMt!DT6e}yK)xqHsd;W!8oUxyU*34{G zuV_d8bX`T823AIUppyb>e_eyKlF0%2R~%s~fJ$1E+A1CQ`^obY{*GK>TES&sSJIF% zn;%Ag%1CG?H7C<>kwx}(nP&CE7kBr?)9Pmq+eWePz5K=fy!S<{3idDun_RCEUy5W7dmIc;~r7_M2QPWPYagMfP z_)AHMu`+VS%$z2VbRZK%d6+vmQeRoZBsFULa?og*;x7y2#Tk+dB06zy{mn!LXSnZCIgepzE+2V>Sjmn`%TPxOuhB!@i z6HW)*2T_jY>_{t(%F5?#@%rSB7ALXwP=_La8)tFqvDobM=$ITp159u~CpikU-E2|Q zrBj9TCboK^>?{$Jve++U%K&4>Q$B>QK0=Rz>wJ9_>!!U3ieD0=stK+71)u3WX(`tF z@6}!AYiShKf0)S*-7Ca0{7rUVOpL3lDLbK)Hy>(e7{42R+Ar7bMrER<3hwzXtNdr9 zz9)2qgPCLuoFwH#ON;{Bkt`^IVG4@H%*dV#?(!lBq~5d8SqT6mmkm}$tSq3yO@f(Wbg9+Y)?1ZuIzo^=X#J93sbrwM0B z1z3t7KbY4?t%0e=3MUL{j?*;1qcoijhKHSe*6cGM;B=*3XufIBspK@^j@3x3vY!D6 zwR+#)Q%P{U7ZCT3<2?T~Bzh@{Gs9l&{W~v`B`nny(Z<+dS~@tgyV5&}RWfhI0Gb)z zN}{1*&#*LD=BO7vLeg=yG0^#iXF2`S=!Pko@@tVHrBySzQBI#uL1=@Yk?U+W*r&oMpCFRHU>mw{N%NLBEjL&5_*-MQWxRQT=)D4=0O8Fgn z7iLp|c3ziQy{N*84Y2s4_SWsdBG$1~{w-?xdu7*lwgdw;R)e8N7_-b=-S*dZm9bf5 ze8Yyi0;?h|G9ozwA$BNTrIH0Z z*(j-EmD+UYV4wo~=NRSul;xwpaEdAT#S@`S!G`)xv{l+o{h;+wQC`J86MFbN_67dsApJ^`RGGPl`)+8}y7rP79Aste1(6 zL2I4AJt@SGCtkLTzp%vi7w&mQcIIpS;^-*CRLq)4`*?Om93x>CBdG!x6XhSBvhGu;`7140vC7R-OE(qLdK zwI#Kb-ZTnl+<%sFh(Vg&qt3*v6K5c}!jO+GO@l?G2~(*2rRo_rNSlfD;NBduQeyUC zB%sffnQ5Ns1K?-zbw$4;##aASd$vDEvBih*_wQFtl-OXQF3ifiO|IQGaIbU2TMJpH zJ-18+>_y9BXIgjAC=WFwc4<;Ps9Q})R7WM$1aW)IfVjifl0>fZ@Sc?3ie_xYKQGYEz!}XgkFzG+V>Ie=h#O6Y>U`q{*GfsHIzn{C*W$eQB42cFVYBZ7%l5viRldS zJ+TF&EA@SwIYpJ+NBCawM-znY@d|s{(Ay$2`>mM9oF-Sv$~;=_Q)3%&X>|`;mhqH~iOKBOi;oe+x`C`VujQ|CR=i(@6y>dN>CbBNc+og%+LkZ0 ztBajWuv~>ttTC&H2eX#_omwN6oo6b)7}zY~WN6WPud%9s_I5=lH%f||bV z)v-x=p_rlRDrCwIP!L4PuMKd*bK6h?1cGI?@LO)-hEaP9`tL50w)$_hf3f6ctroq$jN20!GZ-urx540|{f;A0o zU)1|f{)=5!A#}45*p^IpFn~GO{*h#0xk6?89WuaNH}b!w>)8Lv>--<2Rel<%N`|2M6c-QJWLJwET~%<5@yJlE$vNYT+iLF&OtABkd|8h_bApf&@^f?X z2wGQ(Bi#V+O~^IK8JRqIe-YsR$+pRp?~zbn0TtCzd-pqY(L+S0z|KgXOv_=}cfx4U zf(=2yMQS!uWyf4MsA*oyJc2{34 zhtjocfoKm=vGa>CC^H}F6n?`kVe!91{7;VT{{&)QZeEW6f^mxfa*YMA!@jSdJ--vI?8Gwq_EqccWA?C8uGYsii2ttbB&$wntnxRU2@6&OT@2lbh}@} zQ!d}%gg4(do2@wBkEh;;&~H88o|?P-zy2NCd_P^ydrR$nUwnTb>{?vwI-Glc=z1S& zet-RwY>cC&p7`euklfOJDh%#+?E3mLYc%^nzWMci%JGRN{OjlDKWQdGUV;U;q3Q8 zFGA?Q?GxsQ2 z0>{jN)s$!GN>9v6gKj7_xjWx!2LUNTD?Y}U6W-Y$wTN62X^zQ#ZOWJeRznLv?)o%0W$PhZ zEwF<+vkH)sj_$0I+_)u?k__)p%-Ei{I6&ZJc8?MqtGgPGpMJ;Yyy z!M+a%h~}p??O&sqw5P~Af$VWfL&B^rf1zgzjtH3y;rp)j2{K)Syou&QAM$gwe(mMK zxf3;H1fx{?j#KLOr-t>U`|jIJQ+rIW4;4F%hj2kot^-1G*7l-G6pd~Ol+I%UOGMkY zEO50^!rig6n&KG{-LgcD4(6MV(f~0BrVU%WM?DpY_Ln)^#V1O*XsNbKeC`pvOwIiD zB}xkD+1mB~j-FOF2+M8KyO*L*Q*~>&EiWOb!qWJWPy&qab(}I7CT_PNna4DPfIC?V zV&UV({B?4b0J(BRq8otQ8DG8}Tc|zPRKpm$y((GxB*%FiJGvNdnDtbMM=vA*4y9(_ z`ic zMu22THm$A(pINWZnT`mC1VB)G1HM1-psPZlsE;amEkmmlj0ANcbGJZk2g$O#bYIhh zN2aHhc?nNaRZfqBG=i`MR3*j>GQ1!PP-Y4;T7`6PwJC2y$F^F6_vuW7f_D|&ima&z z7JDXjVz~%JDLPqMl74~Ik^~`ATCqAKCJ1`~?YEH)u!)BtbwyQUWMihh>`&c^=Do5) z#kLEQdR!RPp<|L?Dz|~5vESB_x@z{}|k@_;2mQvwV5+Q$N*^6#W;RHQzaWhH!E^cx81fk}_pG&*N znji$H;2q}_=1S>gz@LwshX%=batgix0ct%9X;@6~bjq|(JH==%aCBg_B#s2ADwzFH z`zQqt)}`b|n=Bi?Nex2$nD10B7C?A3+O%n~hgd?;mN$&*v?Kv((*XFwqa9gt;F-wk z0>t@E?xIl=#A%IeJVO+9J~Y)KurMbV+vy;J$v&~i*f|8WLnhC}2}|(rrfB#!g)DX+ zXN>cyC}p?;;tXPx&dQjCV2lDA1ui7GTJ${RD9_!cVwVU#HRRXJ2R zl#JqQWXjuBvvt-pXN8h^5ns0-I-iqQNq35Fi70$z_YL%Cg+ozz?Fc^ieBz5${}NRI zDeR+Hu8p)XtcM6?v&Apcs$0exqDMiN=8PPaMO~Pa^4t8bix7<8y`*~?CD4C4yl#SM ztE9#$kC+}`NUqBlOG^#SH`;b-q4>DB@(4s9vLr{8X~cmm@*LQVEWuzdJfZUfv89p_ z*}@kEkymtc5jE7%n!P*P{swCvnLGuQ_VEVj?%r89IrVM@a(0xtxsVQ52}?e_YehW- zRg8+DAN3dk`DD4Rn$x5=Q8tPb{y8?n5~5`btnpv+nF0&J+gzGL_Nn+~XojHU$i4Dz zS@HSU+}AgE3|z(x`KWZ8T)!*vxCaF?7vF*o#?|^m^)Ez`h(!w|jM8?c=_4-PrJ37) zfr+~4RY;J=BRdf!S|e2$t<=S`GHR0jAuZft9GFzSRCj1D>LLmsAr`521sdYrdvsJvFSGbi~@S`={8Ol z!ODuzmh7?=sbi7%alC5_rw5l!BI@Zyf#yw;6P`<{+r@C>nn(y~N!EGKH}3Ef^kOf2 zJ=YpYFsU_ZLYn-YyJe#ZcsuG8ndv-`+^do4Q3TkSZVT2S#iHzx*y8cP4hj!UM8V*g z=XA&<$pR>pKa_wySzsqCzp|^H^P~IV?YxktJ+JDifRSVj;mjPy-KRjyXV&zn>txE) z#3%=p*s7vwyaqY%;E_l>$hFZBF9X{KPldcs2X$e)@OB|MGQmIM>@3aZplj0RYE*J(rtSwTIxiN z2f0>IR}ZHL*aVx!k`eA>5Ny;58;{ zps7Y;5Uyrfbt&qy-Z$=Fv|s*|#2Rg09TAG$G*B%Gge^wxcP(eWaqC{)00d&D&MAa= zNGza!LJ+I62=UzerkxF$8g2wn2eB^5Lf=?u)4u}-6x#sl!-|uty#SBT?qFyHQEfEb zGlPk7Ik{RQTB{G)G-GwWu0+OQN+Y_ZCkOUqv4dCnh?J%Aap!U#MxGjzqwGSlDui~dv!QSy`4mgWTNwQvVAw<#O$n1gPAtDE7dAils|EZ(qY&0 z)_Unq99n6{ywoI^;d_ZtgjUR$HGNWO+SA{zNcdQ8+#rZs>NnEK5V_JdRx*pen4@JO z^d+*mkC^K- zllnJu*(A$+N@}euPDhr(5Y=fP8;a4+shU$2Muy6wy+j6+uMj}cibDsrwhdw@kuE}j z(UW7qqZ8A@%TB|S5;Uk|YQrH(Sk<;{l9E!n#kk#zAQp4J(^o~Laq9=?v!!c zWx<`x?4qu2grME^$zzFo?OXxe^7DFC(OX*CQTbF|Qi=grhg`D_yNV_Tc`;!n6kT-B ztVYn|SQww7QwJPZ*KGBbS1F;NEO@+yBw?_(M#n_ z*Z7&5`}6>xQBmf-OLC|qnRj&h3vTl%enr@`i5inl@9n2TA8A4h)vc+@)9iKr%!k;n z47wn}n9Ni#BV0f*&rWl|D2oL!5AEfO2C6lXD1O4zleB=>LzSVxrh{MI8R-zJN{uW* zi

vrAoNga#2zP%xpX*VmTg3_?9AAZfUzcwF)vIs-vfkR&4Rqrt0D8~6{Z4@WfNm=pE31MEj2upkzULh%VL|ty!jQ9#U;ydljykc zBzZc~mg0u4q9@jP(YBx$k=$}aP;l30`=9YY zy*uRtFeAq*0dpHBkoTwGLub!T>)4$9qr2FTO4e%3?e=WQZF|fi@4p;%C^SXopu(zt zcu0^pu8Jbwsjs=5bO`j94vEhyaFn2U%S6oEZ)$2wuaQphfvla0X>5EjOD{4;-r~L4;nc}e^zAG=r5~P_E6^H2|T-`WqDs9 zGlhAH6@(g5<)OfhN4v=nU0Yyh&d^3*m88!h1Q^Or;!E5k(n_!}o}JT!*=4)bJ-l4# z@h1htopER?a*kl(VJero^+JFqgj6W8uMh+^)3*yzzl3su$plO-xpsiB$nFJX z9`tuznM8~S?`a*W(F{!|Y@T9D#l@#L#@rGv_-qFVhTFTs>oiKw&- zx+>!N90}$Hp-304z(hk~{{mo!?^$6s3X7q@C&)F{+SI+YH?cU9+Dowo0O^5&HA9`n5OR5`RPzqj6kl zoHEuYOYRTq!dogfFsg$80F2dAi(uN`n{PVqbXMi6o;W2nfuim?9Z?fWNtZ|tj+h{bmHzG-(t`q&*@=x0R6r5 zJ$!6`)3#pPs$wDp(o2YXWZB~&fw~-c4kR!YcsJBOJktM~N!qej>$w&Xq+@AIVhU@n=X>fP2;!tAdRO1i{~G9&ac>jM?{=V|P6q(ImATI>c2Q$adJ4C%>CC5Pip zb-}+VqtCp=3812n4+T7Xz3UkI-lPUQMUjkkPOt>d;xfUC?U@|9aSvmlS~nQ>ixELd z)|#Mc&JC8@>ZajljHYrA!bC^Nm^~(5ovOiFJ=vCYj=2dN;fc*Z^IVwt5 zor^&GDxR=UN;8Xy44*qbO{~k;t=&lT>UIZ9?TtnYZYu~pHPa`eU-)-NdV3bO#dtab z)ASH1y;P=MPZE2!Bzxeh*zhEmwwXwj7kk^1JbNKejSCnqPY zo|0CX9^8W`pMP${gCAo~edkby}HDS3>eY*lz^0fpTdbtBI9qrQ%qCn?JYqGeq>b7#QDfv+w5>`}DUn&@O{{cw)VZ}&iPh8B9iimkcj+|;S1pRx@tZY9_YP@L2&5v$ zpA%y~LWqA#zP=6l2FXS!D+Zseoh@Y7C&=vp74TxF)r*^X6EGu^)!w2fpt*W_v$0`x z_On`XmsyJWojU@VZMhD`CRC1Zy0z}awzEpY5Cp68$N$r2_aexq;#{esgAE_=t2st; zlHnBIk%Az(Yc7+EFniD7ePD*&eVT2*LTYh|VYq}}usM?3fK&sCon^?j9R)_pfxp!C zE{;<+ZmIf>h2A7X1j^4bT1>@um!st;Np^IvF$eqD`9sgj-}HY;3#uY_F_NT_+E^w) zq=Ni9V2z(rs#{DB;7n_AymFUmw_;{J&eL!(sF3+%Q6W$parhmuM6)5!7|s@*wsJpt zNrm*o<;vYv^QNNb<7WeA(D95?c%YR#=z7kAFq(-+&O&F4zL%QOQ}QUFy3{6?V+mQm z_@~WRFq1&-*Ty##1gikoh9V|YNN8a~n<(Ts)cfBo6aL$eXukxzMhty#6>N=GAT~;F z-U_YXlGqY&(7$i`6{rQ}6j0IeZi{+C`vC zJSE1>gW%LHo>~ie`P(f`vr2J>)q)lo8x(IBb6{&Q_z={qgQg+pARsJTQZud!HLOh` z2_4IoK%_ddcnVsE2H79V74);! zOCDUg_s!gxg3x*45Y5u~u=+`I8jV!lbKDh!P`(H)y;h*8+MVu%o> zH3lN)Uwd{d7 zo~H`knHEEsqzEKPG5t!s3I~m7IyE&Mj-yT*zDluz2pl-z*{#_mcaWzL*qY8EX z2S7?dftjc6M*}_R25@WI#8{Z0mn@!K)e7+IMFz~~3l{C2GZ5U(6lP@lWF>{c=JDBz zq@_bobwlMlhH zjI|i-QCKnt8tSYK5_%F5qiW2GAfVBJ)N_R2+;jBX+Y_!gs+ar2#pad zQY^p^dG_febv1}K#fushL*Prgv&zA7U)^`79yso;ypeXgYlXdROxOQrv?BK?c%weUyt0iz3r=-X@^a(4HkcE{aCfx!4{ss%-%e2dEoPN z&+Mq=E%-iUG(Bw`qN6o5$rCM*aRU62@!TZkGI{WFJ!&({? zl_D1MXXR4Vih4`SsK=&cH=)a`v2;bi`fKZ>|FAGq^ArrC@nqX1=)9i8y)GS&bl;{* z5N7d4Vb=Li*;_BX&#J!g-g^-GT}k>fi*_%GtVD9N_JpO4p~L0&*t5<@1zc)JzfG%n+QM%?WS%=_5xU|@!wGUQ8fAJmUq@qkbPNocyQET0J? zBi&!}L0Y+gdTPu)Z zoiV)F6lYxelw{>Af^Z(I$p_yAGe^ASM*Xz9p@h507}Jo_b-amizdLmTIjI_RP1*X z*uwP8CovsJSQQ_DPR~!`O?s0i07dxF8N5{{F?RjwXEx@~1#9a2TrYRhmY;zgG(?WI zd)Cu!)&1*nzDA6E6zMk&H(SHOh+qXjGe|{_~ZhQKxjENG-uNpzL>J_*7^_xn; z$C#nhg%TWfqm`&InL&^Bqw>isAK_bKkiK@3>u=EU(~NefUW2DF(b((VHW9Ze!7a(kh@82IEtM_0g1cPgHd)DMdVU$id-0{6X=n1_1VHe2fTf(6v zMnU#|>c{YcL)8UFEYThCIiwT;9gJM4Dzu*vx6aB%L*SG|v@P0-YPnYZF)d4cn3XDRCm!0`J@X)-#rS7rm{Xynm5G z+z29f#tX4Y(9yO(ENHdcE$CT3+zT*}1&rIZcB&$x#svbj;?&JvX2^A5w$tt5l|j zQiBFYiSYft5SAgt9_+{EBDFhBXv!y=`xy0*+mU!%1wG($2r-k&lr*D!SJ9))h&$gh zlBUcEn1C0lXLc}?uIcwEY2S6h$EE%~cpBAVtOwW09BZnQFpyRi@sNT5e>|0y?)l?( zj8`zI3>a!|Bx)^cPm=f?9Z)pk8h^~66`ZjDr{VEbQ z4xyWxka5;G+L-|Y#k*+SpKKRWTL9e5A)dg|1u$m3vee|Aln#sw~)i@in^-Hntg@U<gPM3VIG(P*H7c6H7{jmOa*G-HgcKlobFC9y%5ad2PY+f(*yZwTPeC-G6X4}W3 zX!k6@)EtKpK`YCg%>Auv7fj*aAH1j0U*lG^2co|B(S*NL1n7ORJMo$DSnF{u#%Z__ucR&!UhPYc165MO9Q(U4xBX5C z4-(K$KJ(~JQ||76vzZQReDqTr%_NWG&h@fY{J7z!ng^%d5nS$j2-Q)7UgSMyU50$8 z1+L*_(k1t4FU)1B$%8+_+o0>f0tXH*6nm&`Yvicm+i+_LvmZA23`oPIemTPMT#p|5-Oi5N5$DxR)2{}%jd55HVO+U~ zGzXAN8aKoEy-(v!_e&vAI}s9{k=ALlHz}foP7;6mK8hSSo8NU7vcxIuIQm3Kkp^VN zx{6vHwv#zejPf7|%V3oBI}uRD?6mj6Z!PEFH1Ip!N|d|&(c=`_uXVswFyd8YYQ{<6 zOZz$WyRjzu{@sl<%v&YS*$%P91pGzMY*Kjm{i9Br4F7L z1UZ|p8}A)cFMb;lXq&#D=d0Dm%GF9gudgDCK!~9K0gCiIo(?S-{B)frf_M=P>|Y(6 z%GiH7>}lJ8qLqb9@Kva2J9v%={kj5CPYoTJX6U*en=JL3t%Jt;%pr16K7u{;*~=`p zlX#&8e#V~NQrk$u3-u{E@@`~tD$~>dFYZ@(pdf@D>Y^f`^+C1jptX)W+HyiKx zy3oSeEsX9z!yh(V%3`zjuQ5f>BM&yX|(il^w=EWXo$Xpf;%y=*gBVA(@Ae&;4hqhojOOo_q7SrDHnKCS}g)bKVW-+dK z<m1L6=4bo3{N| zfA11UTC(uwO9C5ug5!`MeA8F>OVDqOCgJ3X7=W}8@hKqkA&s0g%1xrZi#g>zc&yB9 z-%Nkfdu|G9yo;0#r4GxP>Lg+eKR+9PwlZ|o$ufPgASYvEf3_>BPryKWL+!#BPA1>-NEJk1{wP*sV?hPxWjA+Ds)oel`R)eW;) zef%cc!7Qa9N@^#v*8LK3e(0LB+x{*lB?%a+mj>q`q1nw=LJa}3w9;d5Kw##AChV*T z0?Dnveg^JH`S@hb6&H2@;NTcTE%NV zMXOl3Yh1e+Y4*!rE1CS^8CA{t{Xx_o-@Y>B#y#TC#&Ef@){9%M6U2f`*8cs1=r6;T z>gzwlixSzIxuAu$N1_qQC-wP-89aXL2+=oC&8k|t_bfj@H#l8bwN?F3n{C~j)`%yV=+HLG zE+Wtg#h;={Qn>psWY4KI-w_Ev-_!wfLowQlNiDvr18D7%95=DmdHr1MOv(>u$SQJb z22fglivIw2kvIPr(x1cBecZ5cXlmu~6pVRnPkQeilw)aRoOcuE;r(gf7y04xWFz<# z=cTUI>~&4pg>1;5^1;>b@|5=LCqd}|(&xCZWdV=&1f)ibI+0KkLJM^?7t$Wc6En#z zQeBA~(HE)m1#My61#QK?1zG#Hg|)K$g~ZNlI#v&J3+XJor{!iW`#w7_rb9yX;l`?K zdFz#_1NZa(Zr@MfMOrZzH`NIu{&WsJXmp~5#kO21=V@<}H^J7J<@M>FwdpJY#;p2G zSRbP7&~DP>g>p6*k^e8w&apWYCs_NNO*S?+wr$(CZQI`1wr$(V#r?n)%Ii*USg#nX9|4m){51tA4m|fQ+OdIj zd9-2TL%0gVCy{YMZZW<6CwQyf;>rlmlYiJgIJYMK1{vG-f9tEB`Bw5eu9u$L`}jD~ zJ4F7BjY|`Bz`XUl8GdZgTNbUVEOM=cE28trS$MbV2H6*+>4Q49c5$d91N~f_-A$NJ zE4Kyyp=OD!bT7SH{T_I{#obtw&>-6=?5lkG7Ga_K2(>=t*3riSyI$|7^@Dic)6yzE zCl^z{dnEROaI+)k=tZ*P`FH81$RVg1PEE4L!X3hap5xE`6K?F0)@i^8&_??KHWe7> z`okXkKCJQmR^KLpgK};x@m~w))@DG`6J>63qYmNZ14B&`ovM&^PaEb0qbIeJc6(@K$M9f z9nx>%KI%A&r~to6gTWMXpg@?d_MBHz2;W(Cgwr1951LYqb);?h(>fSR2-OqA2zP^c zB4V0B3n$KTWm!WWrx|;~qCiP2!pH9cN>9%Az-6hw-!524^$Mrl7x?4)Uijp}6Zibd ztQlfk|8N#ae|@p;H}d`>{;51Vej&=)GDV12A%44s2sdJ3LZJ({i3s;V96hLQ2%;I+ zKOsgzu1~}^a!UfMa0Wl5Kw%Cu#w0=-*zoJ-#{y6B4iP*78_^TN*LdeZjmGo6MAl2k zpP(-|Uks)0Zwe#&{iIm$lfbq|@z;|;-(M#s!$KNkg3gR&Qz8EJ-#<_rJWs=56!IVq z;Z>X@$kOSo4Y)pW?mOf=31Uuiy4GDJKJ(u0`2#M4eyWBsQk=v#81uz*eZk=Hg}reM zKc7H`b4m-}Njn;_`O#^!(822XPCpJ}P)A?$X>&7vIB zE8o+n^Eap14KOIsO^N#TtP^4kk}b_ zSb6dNJ7&}6ABv<9>_sIGT^XYrpGw1!6|`dL1?s@vmwRC21va8eZ1gl9(3vw3zy$_B z)fEcr3W1~H#yHC9RkQCk%+^8UG9@3DqtC(Lt$#^M4jI`SkpWAZX-p4U}95!Z5vzJp(pMh-l$Zyc%M5ZnMBcmkzJ^q{fXU*kQl*F~r8*?f`kq+y^uk`+GASBmc+M(}asU%NPO-!z{|_oM#O#_{ zzpOVH^S(iQZmQ=QzrRs{9MT`yF&7}lz3dz_obMl_%yJOJuOF`Lb7Y2(_69q!6)&9gb=ny(ftz z6dyU5Ylv=W*n?Ll?oIFOgVhm0GyFzlqo|j{ml_WxCJD(z^>a$Nq}r6)G&2d9V$uch zGo&*|%dUr17lAj{$CV|0U$Z_D z!ks<&`>>Ck58@B?_tn?7;&~Rz>1;FErZUfkZc9x|PD{{*ky2UMxj&@42tx7TaDviv z=q|sKg3kK43>53#Z#oTp9UL7r9aL{-c7yuK17rGi`+57*0`0+{fAPcmp`GI@3Hb`Q z6xcN<_ckoPUI?{F))_)&R?V1v@CEQ4;6C*D5_sG&gSNl!cao(DJx7^xo{Wr60#W%KX zH%Fyg0gJ5#z=&3e+mo5r5ZkCt^cGpmi=Q{5aDPw2jO8EWwjwp2*HgsN@n0XCXvL3> z&NYX$h9ZgY`LjOHmgMbu8ZV-@h}(QSj}{;Es=p5lYx)WV>X6k-u!7Q-WR#k^3qUu4K-lfpw$Px zUZ7L|+SVgqg^lhZ!6K>UYuN{I?}2^5^gICSVfFqD-hlG_(B30|L6RE~z5(k7ult+C z06#LQmHxy2uZRblURd8?)(v_$oceS;749W5wiryhh5{;9D6ep&QQ{Pa3 zfaeWj3`zS8$uEpm9kSkWc?NY$ZVTnTx+4>ukw^%c;IGSX6J94ikGr32`faet6kl>Dp*V!8V zgDh1cfQeQiVp>_CRY~lrA`iDDA-g0)%MzevNz{@cw(Bu&1P*ty@L065w0_hHY z5$qlO?s(#(;-Rxf#zSd?;RY!WLpz|i=ecLP=elRBQ*{jq5sVNL7cv`6A7VV0erQO8>y}nertzJI5wSe)t-TKn?3EVrW zXL#Gp-~4^e?+M;Jt!H%G9AXXP62D#AcZ|;{Y|ZeA@jcjgBDQ{Z?c@^1E!lUx*GRv~ zevR>o_C3~jHnz#X5q}NpiT;WBJtD`1KZ$-!(Jk_GK(0xD-To5x@{d?&;J=rk8`$pf zvLdoIDEfXPk6ivXMot^3t^``s$u+0e zz#5aPH6Aw%?P)t>YX|XOT|m;cF*akV=MUm6xJx{?JX<5UOTn!QeDqFeKyV(|mzvhk zQx8QM1|kTrfX)7_pD3i7MayS!VoB?X2C~iTxN>QmNy*uX=Z~+8KhOFV#LU#(&Fi+)9w-&1-k+#1^!?8M1f;3z@LAl%PZSJ>#{K3zkE}eOSJzW@ zeoWtJV6giLj!3G_;4wXKS=HsY^#Vj=o6ThMnqPHe+rLffpU`V)_}>?5qwjQ@oHZU% ztJP}xZf3T$?Kqz3Uaai&?B#l2Z+d)#W?|v^obHL^0Y27JN89XBay{-UfP1(xvfO!o z$Lq(bx?RtgpPSA#vwb)F()4|I=hk(7x5wJ{-@ZG39w&h3ZT_2net5r^`GP@w|GTr{ zwOgZ04@S4{-`sl9xb!2j7{;Sf4F~_+eNnh*qLgROlGl2?QQj`sT1zGM&Vqhr-CNn0 z)l<<547~Bj&z{Q4iAg+mX^Vz!q*^F6W=Zq;tCp;dBuoLwV?cb0y2lXV7DIGs*x&J^ zivbPkj8ECo8}$fH6SMRvPs^3VJ|}4^^@qhUQdA9z6YGgX`xkIM_fEc_puIPnrXc#v zn7qx_vbA^LE|C05Z-{sFGKhI=w|{Nu=lte#9AD!$;gqxFo*=(1QWQQ*5@Aa?$*}4H=DdjMQZ_ALSPdgA#jjyNgKGY4qRfS;pyz=?qVm zmGum*nQaO2LBQ0I9ClpS&)lJjn$ODATyJ(sjrkqc;n5^&HJZl|?J%_*@73A5$*92Hw{M8FqMnOh}&HQWQ7j2>ePdf7-5 z5$vGd1G^WGl=K6n$J@JFbUF0PAgN@)d4uUVw@tm#T8ymS@Co0yoZc0@w2({#x6Cnz zF+=X843D?`(b9f))o(Yorr>7^21GcbOYG~xT$NuAGQ2OQMhF^=y%6Yw@~natH(=Qb zl!mr_8)&JyJb9C0!vvw>)P7>Cde|IapRb(82b@ZCcgzl{o8y|wgYURL9OUHLIn%Nt zS7FYPzL!O%UB^c=mZgB7uITv4D)=gecB5*~Q{s>BpFV-=Y}5?!D0^=OstwHuBc!Z> ziFwMnr7a(F)}y%Z5`Ja92Q!+t8$Yz}u zFuJ&;)O|;8wA)dOWv4{~t{tEBvSG-ds*n>cvWp}Gy)a_#Dw{$)3nviG1V6|t#CQp5 z@)avFht%;}m*B&7t6crQ^Cnm(Go6Doi^$uPrTj3Wo|(3oPd;4g?iWrTXX=Iiel;T2 z{ATnTh6Z>(Pt1eVXei>{q|}w`GPZJR@zd=#fvGjmjh-4)pTDiT$yhkMtWFd=yjEJ_ z44Eu2BRoMr2WBANh-rtw$)al)EYNH%n#j?pNYM^(m5V4q!UW}`2^w}faMOq=(CE#l zuXfajFw1f&7yO#61H&)GBNPDDi^x>_Cl;D06@jSxN)>Ysq6DBoro5h2Z1Cl zTh~0QwYi(InVVsS+$nkc5|LRyq^JaI;FiYeBM=?+vVw@ldg0vjJC#-IGQ^wFBfdYh zaT1Ah+xAKOSMswmuj$Oj0RHcs=fp`#CDgO1PJ$n z6Jg8zl`VjFs{*|%Xf+V{Xu0IFS3GV(Wkb6R?R#VQyXZ>|%-+^kxm=tuIW$;?LO?;~ zT<8$}j(#47I$k?qvH542*)O?i=*wZ~c!n9hSoc)p44*x+a+Ko%ts$~QOf^e;5xCZJ z880)#s9kiOa;QnWCER`;`J|O0?_;ZGvdUo{S#V{;aXmvaSV4u$k7}~ADu*{aLTy|r zyCmuem?c&#xN^6XT#(s0dXTVW`b4J27UmC?9aHSg>V^D8af4)g+>?*LfKDOk zg}8_k-%0=sbWtz*X0>OwwG#^T?W>zV-3=q4?mWZT#$ zb9h!F8C6X9T;si=0>JTT-b{?gf;zM_h0gTu?W*JE#LucnQ0rP$#PLZ~4@uCi{sd(Q zrtmGT<)}BdI>yaz3au`*L{@bntK20|3klW})EPAG!o1!20DQB2OVGWr!^?Se>Rm|n zx`N^g9|=&0v^u*JToKY*57J-SDV7de1dpt4waT3Ss86nUk*m}OZ$k?sqF!kH(FiXW z--3m$V<-Fye4#e#&18mQ#Ad_*h~r8v6^Q&p1+puJV%UEu`)Ab5iaA7RC6|l-2USul z#X|J|pq8@xS@X}QT8KIg`TB)k@j!N3yU>BCM7dJ7pt-voFJ|xVTmh>4 z7jfwKkjoI+klT)G71ehI>2d!cUvQ{tCMPHA~d^-REo=ocKv4g&wRHl3NTs8ya|W9PLFskJR9Mm7Po zo1zd{*h*&v8*hriJm@abx`Q>jVF>4mVQzyvdlI`=?EW-~=9xbQ#F$7IwLwbC8jF#W zsI!@M18G?k6Lw8?Ttu?rM;)EHs^__(qu^{G%m~LVryy?^*4GpeugwyuI3ihor%A=N zpjtdU2_>$a(jJ$v#`lxwO2n7B$%{Bpu^5K=SrDp5Q+QoFUgvCID}HdR&}5E=^_qp6 z=+|dNE4gg*dLkI?DcKuW#HNjY8j5F!a{6v`akg)H&tUVpWY4GFrl7<%ks}u*e9r<~Oj4$5C*8lqASDIuJ4XnNryod`#@n z@9hO5!-Y%|WK*cjMeg}ZinhD*s6^j~$ipG9px}lAjPmKBw5jurM0OnFvLnqnxoEa{ z%ZO;y^)y?8;x{W9*=5pLQGP2f%M|iltdRKi0t9zgmL+Kg!r%XCIG1;wrYId#G~P*2 z)6zcsOW6FTUq27H(qy6P>VE5?ZD%Us(jCgMlynmLF!O)5DloG?(OVag$yHWqY2dOx zT0s0b627ZTeBH5j_ra)S-u6vVF>##q+twlMy9|NaHQTl2OhbIK~@|IaTRIB zBI((U3hIA1;_~HbkwH2r&^j|fo+JxK39dKd7Q|~&?GmeYqgFt_EXA5upn3Lakjz%0 z6aHTPw~yG+;P`$f>i0;fHIH&p-9#R{HtlX;YMqK@YL%f$y7zy{SYr=kan0@775x$@ zV4L$NDrD<+nlVvt_sgDbGw#29NeWc}w%;ak;&Lz5*Idmt{$Ns-$MEtzXw$E4{u2O?x~|Rl92v7x>$CC+yR1 zTBSU-OS)^2OGIp|zESO-Q&hQG=Gw3j>ZxoCy>K@iY!mxB>jsrp!?0ccMF-Y`3v}Qn zFsHX1_K**7*hn90dX{>WeIXaoJ50A_Vz=70zj{6-yT(#qXkpCA!QODDc zke(3mb%$k1tD`>;IJ3t2&uuXt@{~fq8F;0CePwGSn|ui*Qd&F1nZ>6@KQft5p= zBh*2<58gk+YmSs!O;$42DU0V4lzVbFZ+uP9t954t21a+V8v@Cuggt4+bV4);P0EVnz+U)^58paoWjSo4afe_i}Ef3aoC2 zNmS(lAEyb1pa{nU3YbVeQ1p#bexd_hq+oC5iFrW22{MKtWDnUL1}yim%B?9px&pFQHFN-nfcQBlz(#REZ*n z58pP(Mq_v-5~4+Z5LlljF@HNx`TMK5A377|li-aqI3Eiyl)PS^vp5Cr2fq$X+W`1J zx}KmNF3(RSqkL8&{##BPOM>V?O9l+JziJ*q8j>X*3Oq=k(ht@w4I*Phe6j(?#nhN0 z_@<#2d8gtIq|JY=IrP33Cu&XNBGkpC3ZKRG{}w$qiHJYNp9~A#wmxMQA&BMu1br%F zwlZO8Wrnv4IN5W3!T6BC5W^Vw@jI5bPev&`E?D6JUx8g$00Z(`kQ~Pr?#YeKCXiuf zjBX9iTai6%7t%-4h9p8qY$RcGJZ?#Ve9m{kcR+5>S8VN|{Q3u&qIlD;qKBBTbX#1w zhCfIJiSoFM6MIJk!f%@A3i*SMbXGqX&zh(r=nAI-c3i#@%?Kd9m#XK5SnI+tJ|1uzVa=FJ`Ubq8psS9Ecxb9pSF=w$u!*#r2}B9Rw)4~+KCD8BJr-0A28_gfPIw51TcVdzahB6?=X z=YaaufKWBc#Z+khJWV9CGKC%$JVsmi<`BjZijuu$pbEJ!F?}M2^|sZl-8ae4gz*H2 zVklenpi~zWt9=j;NT472Oh0z{e4lY#++WG;UkJBJu$S(Pl;mh8h#i4CqGXApCX^jP zHU!TJVPnc1KXE`)8m>8;li|yZ&qO-Y=}M~3<*f*v@YwkW}ZaSECk6nx{D z;YJyxKgouHFHNdzxv_8Z*qngf*Dr{MRp)13Tc=yE4^IgnIUBScq|G6= z2q`>D&55*9DedA}Q^_kb^@+)&=c7CpSCR}9<5}O6UW!sXouCRA>XwF(Lk_dz-GqT? z;@N)B-?3HuUNW#vLo``zD z;N!LS&ElXIhuF*UTMO8=q@U*i#q^iOJ!cf1ia+j1?L74hduD^W##&6sY=}oC<(cwa z$YJ(;&k;kDhUd875KTp-!4pyb@czkK2Wx-h?^7lpcK97Dif179r2Zg3U5{t}0QHj0 z1K)?l_{QtS4$?EP@xW9yw{8FH>e0#}hj!@kR1Co>ry0TR?pkgfP{Maf#sShd!03pf zrK0~(tS??#53zKmeW7s}n08`sF?m$_aPCqa8WRzJ}JCITrR>|h_qv8G*hi}Fj>NBcZ_Ll5@3K-52WrFsx4I?R1n`z6G}!EP%aMs#flZ|#|? zJys3Iy8!=I0JnBs=HbBifH)(fg+>TyJM`F%u{r|vfTG^NvrAAg6hVv?2ehuwgI=@hY(RmsE#zB<0`ov>d5Dx;HH>Bzh)RLpM}X=?98|=6ifTxI#i%%C z{}(_FMMub7k70%*&b>B{c#4G?>KpD``~Ll-?!$ae?#Dnee?R~C?@QD_FH*2hY=7LS zeth3aKs@Mwx-;~`7`$=+`4vLb2STzRSxG3q)iN&SY=IED4*1D|EGHFk;?Vcb`UMOH-gnQ9O;<$#?3;<-@ILU$o-HXL2P+* z8>Kh;?RO1oU)}?Cpz*Vs61G)Ii6jpMiAzCe&6~fZN)T@&ei5OyS#NKTT-5EQJn{V^ z9hHuCr;`}+g4%c8kM)t=3QSmR&3j3C_T`N=%5H~2?uY1bP@v4nk|oPJHuWEtV=R5# zY*8|+4zBxE!I1YkdSYt{5kEJ~|T z{RPQOlugSvIqV=V#OxS`z}X}F_Mg$Q8H-8QzqdV>1bV5V_PyzDJ<5xatz-F zSiksxs7XeY5oC~TGGmz-rS>=l(B$LRSxIRj=Amat_orqmvvQDgkOIk_t;}$y_mY`& zVDdwkmX;6|jX>~8H2z*Yb7d1%GRjKT|Es|1W=uM?$$t0roG_SRdPt@u60J>!DhBU~ zmveuURmVEDE|pZv;}~5{STxSkXt%h$cZZGckNrw}2YkNh*jC#!CEqCfv8XLDM2L=# z7U5GKkS~>joYe#=B3g}lF-%-|ie^2`bsIc(E{cPNCLkPw;8+v72MJlDW5`GG=QG`i zA;xtZ75@P4_DCa;I>7)rrV@rOQrtE2ssrof+B%z`nWSHMVytVpixnFdTSi9M zBx!`Ei%I9c*}3L!E77D6>X%#t6u+_?@an$Z{jfbvFTyBcl z3gFqeJGNF!oZocn!zDPn8eK;qDp?_0AzdMFDUskqNv>oONm>LFj@iBD2=cN;Lho^V zxm8Xb%6$76+r$V8?18N5@NT2Kr35i*+E>Z(m5!;l@+sh6Aj+tKMz}G==PRS=} zUDMJTC?V<)`w%Ez3C^E42_%t5bhQVEgO?|B+9G#oQo`9z{#Oip2sLV5{KX|7sfbvD zZwG1U;|~`(u%~ADwK6R@6SElH96W}mHy#v(eYjwF^_I&iJUx_ljqB>FUs>P(s{rWy zrpude9n?O#_wDh%a7+pH^yFWULDZ5nlADXW_uKKY_@CTW2FPn7@HSI7tSh{&@o>tY=uNYZ{+gX^Q}xtlj|yI<{@8OV z6*RVbV>(~A7T50PB&pF+Oj^Kslrg35gvrIh&Bf70ZC=R1=$y(j%RzlFJO}|I++tU3 zX`*TJ{FA*5 zfb&8FZ2FU2G|5(4RssM)7R%g)}CF5@Eq_|4Qg_Jlq{hMcanp0WgElbBU5W#evzD^3KFiUY&0javBmMMc>^fz@{+)hc*HCL z_w6pntbbv53urRl^7#z=niI6;4BXbv%owL;k~52#{TQc}EBb2rmm~mTQ2}3)(pLfh z{oo;LWN4p71p!&6XWQba;xlqx%jQ8d%9U!0=Nfz1>{|cS%%izI~Shmxl!T!f9 zJHpf~P;lVgtS)lEIl-P7KRzzWUf=Ctt}sAyMXpB-@S*~UO7im=)>9G9F3=JZ9zWp+1BNDN8c9 zFv$d;^2e99Fi!?SI+Z1EO_?=ik)7;2ien8z&4!@j#lLi}Lq!z5H+dRvtY^-i<(?nH zjkSKp|Pkp$zwHdR^n1f_j{r%g$Ilte`}`$^VRrD-#2cep40*K z;J2!`u7Il0xLsdhSSJGP&On+LknO3yUG}-$klh;D{UVpGd!#u>BQw439`nlBJ@WZ% z1(SvTG~?7d7M(?si*`ZihzbOj?=R$n_}|dX70E)4^40YRuN<{R(>yWjMT=$`dj?eK zDKbbIdZ<7UVtq42ksQ4hE0P$RC?aE2K$>9LqSd_r9?79~cxeVI1y^3PdY}3@M)=<( zaQts*R8qTxWyiE5M+B?7+xCr3-m539RfDBZ^>Xj1^A4I@{AK&SKCnk65j^Ol>I^)u z8e7Y$1Rryu1^xC%Hh(kBSaJjA?KQ|(Abu)HfKw-##*t~tIC{`YW5x3@c#Pdy2DWB( zZTX5?B)(_PCC=eqar0*J(n{8O=}9w5B+g&OZ^gn=PU-=3rPJo77Zw+&6Zbj_5olRR zd+MEqY8iFM&s36Yi%s{3bCg(kduVe?)5;tWlnt0LbQ6ULh7*zHURgs*iVqX%@(t+X zeo;g}P>(~A`jL(YVx*Og?Z}w(PMZWNrcJu*beAc0*C^2>M3JHnm&yZi7ECOeW0v&> z$v_{mBv6UnhYu;3JVH?u3bmTAHlY<{bsIm7vk#TYG52u}vae9HujrJexQWOf6qsXI zZ{`@tQ@JLH%MZ$Jb@+f1?K?{DdD#c7=|i5VGO25onTmrw(%^5%z1NUzVT-eXD3V_b zDj17B+Rqx*LNDm{ZJZwE+dbOqOpKZLSG~N`XhKR1cQxBYFrau9o+j7j?^hnLcN1r5 z#AC~VUfF9sRX5LXI&|L8?!_K=ReFE6h3@l}$)v6>)}y1CNwK5l=8^* zBz2j&l&AWe8u^_ZK)O@3j45NWxx2Sxjb@6y>Qbm@51zAFce_-Qs3MJyCS>;IjSsE_ z@woL~mORwVS@fKL0PN|*ie{9j+3%N#6)$7}4Z84Cjr2=okz^ld9A_oftgZ;fVr3Hr zXfn17$C$36%p>H*T&E&G7mi>MB|N24yHl(b2C%PeHNIp%Si0UscZc; z_#AMPVl87y@tX2dk-bTt>h;ZfrWCI#*<={UcxwQ-0Nnu{$6C*d_Mz^rp5eFjqT#n_ zVQVEIeMR_USxqaEG6wOiV;OqIQnrH0mgw(O1@jd!UJ4CVR2m4~l|r;Dp`D?d)LBZD zTWT#|KrXYWd*%EK@;KecgAPoA(mHLKX;A$V%>4&z<5Fs>L}d6lN~ z72QL%(Ls}D(G||S9LtY*%6kkwZO(By8&2{aKJ?dEj@Z5%($8Lpm+;NDD}cw*!$)6_ zfKV_}1{nT<8}ml7aA7L}T+){$yc(999bnpV0NzLY1_NLXH==+$H})1c`S z(=)GDjVvn$ZyVNdahj}IHgpd2qzNpN9iWn z-eAKH6*G+&Ga?2)CtczMh+m=|F)udfsXNzW_Q~hA;Gq3BVj;^)0!k@KCFnAe zqGkYR*Pqvaby>kxkW#U7CM+yNht97^Dc3|~>Zsv)@*c=h5$RT+d$JE>a6gxt4qM3S zMRz8uR;JHuvfbWp>rQ4 z+3q!cpq8t*Nv+nL>8#vI6tb2R45V0shLgwqS;tG4(;rQu`6|o2_>j0FNYZgh&I#ai zWsds#T>`&_lnZ6cfJ%j!g%wMXnKIIT1Lw4<^so~iZYFB5x%`o4d{}}Xo0O@&k z7=_^;_W621UO|y zY~Q_nBJkZ<41Sg;a^Kh}#`JE2#7M-*fu+G{7lX>N&r&6f4C8;acgBxljOkp_vI(Ck?8CHE0L#U^vesOFrG z=#Uv7FqSt36N>ffr#X1)6hU}SlJ{)Dp*f3DPZFdISl6@#qee5vQ}}ubBf3$CtTkCH zV#{vFTvMoc%q!N(=5SBB{q{@cWNcu(defV z!3AH^%26vqan%wu@=B2WPz}|qOK=U8D>I*d@ERsQwvOy!N+8Fo;1f9y@Msvc6CT&! z@8@5Q-E^`Fh4}>GFLvdzqdJSJ@~<%KJt|3$xHC^+UmD6SxeH3m8-tpR$buy)BEA@_ zNpL6P-w6z>RW^}3tOKei#ifbo{tfkO8{a!;)+de9F4mx2@M5HCjeH-*H$w2jh=fZg z-2VXvix+|z0KW;!{?5J`rLCQoUQ#jZ3PtlHo-O}-hM-4_0H(yco_32K&TZU~0y&aJ zw6;(H6Ige4O$GDYN62r*!PZvIccrviym<6*I<%~$3~sObQ&YTACO#!kHG(~N^6g*0 z6eXTy62l6H}u!g~eQ_VCyEyuwK02%gMnw`CJwRiq(g+ zIL&hSOzG`@F=B(7{I&$-?V}vC@>Q8{?CQAM;JCN#-#nw$R8Rocs#u>KzGjczY8)5$ z{fTF*E8P8(3VE4J#g2Byeba&%?sr+e4~(mvFvDVB`q-uLlg6$Tke&EC);^LiBlEfi zdl4(wC_CDk)@Ui5qjEQZEV~3Yi#v8^3&bhmZT-`qJ?mTRGwh-x#_6mF+B4BiERRNfXzS4o!f!?1gJrG^8GOON@6FzYf6vb{5-$S9=VfTYYJ zB5HV;9tJ$oMd5yDw+ln+4fd}nR8hU}uh=nq>TvtdX3L8e*{s&w(i)xnVfOFNvpU-C-NR5@NG@DjxJR88XN5!-aSi4;Z;U5V+SdD3+XW_GR|2VMmHE z{Jwe4h5Pm>z^w&BzmMav${q2ZLuS}mrpOjC}Q6cnO7 zkqzQ9BK*`i8-B887Td1AvxYFX0ztZ8h@Dl&JB23Ow8%9Puo&bKO`?Q5TBeycl}$`J zD>gS+r&z*E0@AR;uuF3?Csdk^(NDArl4(#{QLO^nWu{uQLKkGzxW>8`06T!asTxf1 zi!uief5~HU0Dq`7g(czm-0hG3YRZ0)bPzPd6NfMDsgE8jLxiOu z{g$()f~I5vtaj1ouGZ?-w@7LFGgg|skgML->WkSNsW!2%5Mvqv@7CSlO=m1eAe4g8 z7EIYtGk?J^z&8Py7mY2AHCtjeT`{z!>Yw`Ha@g`ElA0q4BM~F6Z(TKUB`v=X7ycyb zp?8wm3RzURR@h2z(4K8v6?`dmd@&s$I(PKhXJ)77BAwfvo?mCKu+FjSrn(pfu3R&j z{a#pD`03=8naI7!FzZ(2E4OlaY5Fw0{=BhjdM&ew$*_{dI-^?a-H1O6eH=qyPovt`&$c~aVVw@l=pHZYk2y$#3hyjklR z&rlcI594OdL8npLAuHas10i|h3s_F{ateeLpgG_CRhlZ}VjwA$%w=E#%iT{wJ-ft> zTD>tpTw%~7_lw$ zOCUj5@(JA&_fVN9$aVgOI>e!@yuUZPSdu%q8tJGAXdq@Wws6b%c@Asw+)G(W(a2H@AK^MC^$A@MssYq58y}}_royaH{7+=gKop~ zZ;!FRwv@!WzH$BTmCpLcH~iV-#vMQR8|1M4eV_BE`55koQegPr?uwq7iTg;RD>C(V zrQs7!s;cC^ZVb7{XEE8Bm^pXM+elR&FkNROdE06(x60~PktABk`#IFpQn90YK=aBAcS;NJIcnH{ z4HV>@XGNEE!td^S;!n7q*9l`zOS4uFkb|0#&v!AA_mRQY$SYBSYEIHUme;}1S_wC- zDa%c2KNqEnUjP8^Tr4WUxTr=%h`Yl*2CaXi?5F{v`u)rwQ*}B zgn1zj34fb4o|R{E$RO{l94Fw)WW*+SwaH(&^`Rci!}hAS+A=t#)r5$i&?!DCty{#P zgC*lBCalqlFn=mH#>FIklKZG3dMv;Gxo-m$rN@`U`v;oNG$hG6YZk5`yxH(2DvxG7 zU97`1{bg*2f*b`VWgk&4#78!Vi=g-#`oP?`lKkbM*fUox+7b~VJ?*Ky2CCY_DWaZv zYZ?YBF*6q~UUc0EyYRP?pr4|%77e*6^@K78T^1nV5|5GVb789kcqci@?|EC z-GU!TDiZG}^3U#vNAoHwC?K?A2fPZ>;CCepm=7Wl$jjq}Y*08XDWu_e>!q^Gq`zU$ zVcP!mYEYztLxL8=4S-AfPE=1#_MoN|n#-7I^~7Q({vE_Al)YG4hYS5-(g@2apH(r* z;1YUegm25KBSnt}F$UV=Y>1adJ+nBoIL%5EVro;-F4HB`wsb@2GX@_H(Tsl%|GPKD zeqHgl{7D<2I9PW>%}tt{DsSn(oWpb&F+Kl`YO6F$ggy|}%K4U%xp13YaDaD{T+H{T zwgcHpC1&yft+#J~0zSMmqg#u5*XI0v7L$eQeNZ~do{~=C4=klzMn-v2FkKD8EBGTI z!|gj{>r)ZpVT8@=e}L}4hwl9^A6viML0OmKY134sg;yc6!Myqj1=R5$o=alTl(Q1o0)t!cD>hgOZAl8B<6!q z!PF%2SJ2Rp^kc`Pq28ndD?PS~+39`gx(Z0`Imu@ca=;i(J+;?Q_0tI4z>tT(@-3aD zksl$wj0Gg~iKin`%c_Cso`p~-*=$B!YU-{sfJRBkVpEfHdI1>{a;Ho%qRIDP@45~3 zPNxR$JGBS3Zbj#^52I`wO3YV@&B22s8OsejlX!!6fotEe5QvI(*`tuj4-xmMEc@hh zxBO$Ox8L7dN0@6v?g!nFbhlX?^a0XN!=9LWiO~Dq;6hHm*{cKp`kQgo8Pk{3I_n`E z$b>j<|45Q?ANDM2R_4Myk#$HpYis&`oDjM%=a3g*`Nlb+WU&6`pcklZ(atu{Z%Q5V zM1ozJ-0u$lXy>3GV!EsiHUJlfz6r!|cG3q@p+AGwvywZEoP|rskP38|5sK zJ=)>$r0fZIjGcXOzyq3g51q0)a>70`di;NxY4=>J>i!Y;I_it6dU3C6C!HL#1j`*d zM{t#LnfpAe`~Eg7uX5Su@s~cDN3>SFvW~f{DAal7=N}%~CtTk$N48e}g^sz; zC*&z@#=X-=vG=e(wQC<-9-ius*`s&0JSpx~M`5F$dS6N@^80MNnVA2Nv2zL%9q1PI z*tTukwr$(CXZG0k9^1BU+xE;Jn`i!e>pq-1_u*7^t%p=4sdQ3VNq4XBJDms9SuOL4 z+{h*T-H)7YRj>K;o?~`$R{hPz4!B0v5zn^IwRFPV`Kv7_=AjIKl`Umf`O=el=D{oH zu;ST16_EuD>?u>AC7E*1Oxgo;eF3>2qL}eKFEMe zMtCYR?Ou>yW;=kVH+J}w(h3s)L?`S%JDytkVe}h+CE35loDU<`y+--RK1L%WBb^<= zvZ{MVA(|gF9{m(*c}pp|4ep#FxgG3-K{^F1^l4gT3&8oicBO`lJ@yc)Rltr$AS#Oh z6r_$cAdApciUgGdLRJxqFac#KAD}im^E&e!sIyZ`ciARJey@<@F94@NysTVeHeI}H z&r8L7oUo*$0m4;AxmWM*$4(^{9SIL|Y<^!(+-06BYQtysG?=dO`ZPjX{c>!e+92^0+BmPVm2x zit`>%Er)eV%nK@&Ii#VNN{j`Vm&!#$u{;*dct$I|kb16T$ez5TIp ztRxvQ%`Z5N9(48Y$aBwV?|P{^)U$B?7$b!K)2fpiB}aS@HZ&TG=1eB7*Xg8nKZGh| zrxxLVd+gX;oK}Vt9!hh%uUES2TkoTS;yAU-FwaefWKp|Ey`pFwxv!aY7+OJ{_kfM9 zGu&e<>#r*0>OcHS^)@a##=%mb9>#7?bPzGWhTi$C8n7SiW?61{4V$E{6IIhhFaJJb z@1#YGp!z7ld!pc8wj#E!NS`RoFgL~6Hn6GZ##B7>%FlpQ-UODqO)Mny^eKzL8wSnQ zwjuj~^I~bNUsq-Q+5CFnO}|t<`^tKA-d=wD$^PhJn`D4hO?UjNx>u`pAPYZ(y^K1u zes&K%1@)m%@20gHlAjDO?cX5b3fqDqAA|nHBPRCp|D(F#|L4?NkH3F{G-nB%-q9&* z?=)K7d_L%m?`I~x{TWU#%5Gcys!~1l{rRgdHje)VhM_E-kW#w!t!c6Mcqz+WJ-(JZ z*O6VE*Nye^`9VGeE}wFF)`p+jC4H7{DvnfJar=|h#vfwGB5^CYo%cqL?`F{#EF;xa zmK{>{%x?Kfez0^%4|j^BKe19T3np<*fo!geO&KN1=DR|?!7UbFI`~{ereW+*YSooUba2e7ML&F zw;iUlYLqr>nce=jcF8Bqu3sX9y8SEOipb#Kt+dMBjR)TH0bgSus@CU~%d`0l`%%VC zotwiJqkFWKD1B7hxciQJf5hUK8G9Z%Igh_*~u=>az-T9dP z)nQ&!&-YxUQV*^i1eHq4TwZ=A=}%vy1~Lkx z@ioDIE?n(>B~6H{>R?R>SbEc9Bvfi^S#R!Gam z519e*N76vcRh>epQq&^juJX!d5eAYIF;%4Vb}7j;<0zB^EJ`gWvuPkhCx|Gn$=g)p zkdLjt2)e`#F1h6n)sj#N1xFfBMb#SU)UqkoDXAg+RRJPYIJ+g zxx5?;Z8IlPI*Cq&7+TYaIf6t2ky2VrvbzSRc0=o=)XG^OtKGjep3iVnBI~0`L8Axz z8L`yDpk6~nnOl!kUA zUIDGjK|H6jGT}4rP+$aC5Fk+}s>}FNB5~L10p5LeR6H70XaEZwRm{cwf;z4-Qd~W zT>ZQ9d0Jkkrn$blzW%r0{`0SA&Hw%Ac6>kRqulwp@w~}0Q*sB5kL|6FJlR8UJhV;# znutQf%lhPO&RK>w2(edGR_k0t+L5xIoo1#gXf(HuS5`Mi)>(Z_N7nhHu!xf}fA~i+ zUlCJnIZgF!k!5dep^!f<>me79>KlqooSUxVhPRLL$FZqn&-&2eSoGC-(ZKfbG{)cN z)A}&iS5-O1u~&@{ijU+bIIgF_K#C-S8FqnADU z<)P|NX~$)KoOf^3clRB*PV-1v#_j0h4^Rl?;^F@!6|(;CNQDGUoE-nnnX8*HYcK!no#x;0=G0J=N&s>@`2-oISGxu>^$<4C1n)Q$Q zjh`AW2p?7@FU`X?^&aq6v}ya%M%gVv*YXl~>hO`BE|5$$uDRN3mN`CS2T1Szw&pA_ zPyN-j_3g;c>-FV===Jr?S04zQLw{zdHHL9<+D`W~@-58bb9JmE@`~@&o3c+0T${*D zIX0`chE8qY%QILNn$Qt!tte$>=%3}E15#7i!uM<53V2D{nF7gV{RB935>G)YIf*+) zMNPsKluEg?`?6Nm-OL2iiK7H6$qJJ3kg6ziFOuVYB6KA*P(;eO-&IfzMSfIoX8}Bm zX^U1Zo)w+H6E|)AS%#T8^>x*2({!fA5721xX=DGh$JzdOJ^ssvWc_b!NETN1|E?{* z>h|P0M*yAKO;#TmZY7jeY-=KzRTnI8amHgAmB?s(hQ z#G?G3n;ICKh`K7%7A;(GzX>8tzV<#J93iIAm1laOZL3ia?t<^9o((^MBUVBjM!3W9 zq!&Rb@%tT5%l72Wu({01tfB=bjH0(eA_s$3*jF{$ZXh>;ypb332Ud%OCj;Wc-@6`Q zm^@PZpqHxDmH{jpf1FEkqxB>SaAQB>lCT3`&ATSCW}K`nA`%+=@L5f)T>Fk&swM-| zd3r}W(bp+$MCkgs9SLs24#U47MgI_^#t!egx}1iFX3)eP+~8gAe24&UX>9ja#k%`1VBK zE_R)97G+wGxDlUh2h<3`B@<@{NC-XVhZz!G!hyUstMPyXflHB{E>aHB+MqlR@$@@B zBUc*W&Juf3P(-cNj~WI!Kx!Fo^DbCrjZz%BGY^?sNcjhjC;^=0`M3_9&WiFx%znxx zgelJ9f7l1Igk>w6SP&XvKD*}U$Y-&q=SE#_pnr4>xWnx1!p~!_7UMXQ4= za${nQ54M=sPb1Kt`xWq$k2M*bVrCitH+wa#&Y60yY))f%XhHRyJW{3nNc?ivE`o zb7y|%=dZ&tWJ5&`%LU|Vyy5? zFrmhK`~f#Q^)hJ11%O7Z8|K6lH%Wu9&wK2%-%xT3@*FJmf8#4Vmg=7hGkqkQ*A{#+ak*_PVP(EAM5 z5i0B&9gS}7kh2+|JGuvXWJ$>_ro7Hb6uDWj8zr!V*gC&1^}c%+L%>?kCC6D){jp2? z!w<+yXD6K9PWv9@L4!5?#xwL1d?B6~a=W5TQ!A28%(RqY65|C_t_BOBDYO}yJ|r}! z1tTb}7IbMW%p2zoI0+uEKLBXRNnta{ z(*rC|tgA(z%RY7&H%n|moz*iWheDJ}=8msLXtv~$2cVVb=BRF5SMEPE&g1SwlQJ`I9BjX>5P&j+gWvVstoK80xQxUC3Ib-0bN8#E@5 z^8%t4$fFNF>3}C^ha7j{tFW7Z!kaSOjFIAP-H|3rkTS_Q`4t4yjPjWCmT;TuOu?=lc6;(l5PfO57d(Na<7(Kl;s~?V51_qwpgM5kg@C zp9`mruuWdBFnB)ruOwZep9d~`jC1JF(I$)zYCGaAh^>dS9ezHTH4GimnQa3L z4exCW=)=0-PSB4?0ZrXW!r36)imOJSE46fw*?!EJf8B;X`bYloO`brUKziR0Cg1v0 zqZd!&-w$wBSEv_f%x371_~8dXV9gDVNd3TWZa-QYAu%Uhxdb>7E`>}GCQiD2^jm?K zA5yd*s?DFUl>5p{bZT+U{&*z2_WI9}&zQ^i+vEE9LT9{oHrgc1K?aAHruoBZ!U27eZ)D{-S>u=c;e9 zmr<7{J@PU;wI}U#obJMZdtZijy$>N;S${sKe&1s+GlWCh;p{*5FT>3+tB6di$mH|z zlmh(s81Lk*{X79&OQh2OD zc+0ogsAofgJ%VQz*Fe6eY=iC{;XBfU{t{Um#UGwV(w$7=S+t_0ZyCs{!#VfnR_OE zyY5@wlUEy2+k4}-OSPM-l1WvZsYF}eqM}|w-fU=PW|g+IUtajNME~In2r(DHM*v<0 zDBg!F0nGw+1a=SX4mJV&02~E82?P($29^V_0`?603=Rjj1B(OcgZ4_6jt>L62`(K- z9OMo{?nCZ(`dafO>Q%2vTm7`sQZ`*{tG!v%Vr*NxQLv%eEN!j6ELIy`MqT#7>O|^A zigirBR42H<1=bLRL*`F-x+5~!Q8-i<<^o|ZFadv_6$^MmfLVM zRQHaGb+W~Z5qOr%pC$qR}Q=bfKG=k8i3J5vK;gG<#JT%j4?$SiB$6z9UA!(L*j(=kys z>3C<%=IVIo{0+F~Y%B1U9c69B4}pIv)UB({qBAMZGorm>{W_@43&M}4`Ie6)zVPnB zkfis7PV5;1B|7T?Z;m=<#2E?E5`z-JGCSZeeJ*XtBSP*L-p5hYU>>J z!L3~l&l8!{v-<1dxnZ?a?My!tU+N>e zNNhj~12oKlr3>_?@8g!P3p{LJyA7BxfY<>=FM#oundi5fJnR;6;^O6&nC8zN0~}eO zNb*jn0kBM=V_FTdJYcQ}gh+~rtRmxwN09dXL&?Bsn1aB|vrw?gaDi)4xLX zkl`JW@+C^`5ZNcWj}hL}dBVG%eEbq2B?3Uk5uK8K1o%ks6XNEDCCFhVgcAYH_i;GE zM)z5Ke%Xr3calI#He<19pbBw+*)yx1qPO4j3;N-~){N%=^&$()(Gr-41$f1fN3w`MnFf zXQc1k-7-I-KY9KOy%x0HL>8dgdE%Es4oZL57q2j%X*LIPjJ4O8B(kKKeR^>?(rUj(ltxB(Ekg4Y`ntx2=$%pG2U&&UyHjUcgy*jqN|I# zLVu?Ih|x9bO{yK&bj$dP`s)8S@vqlfgG^}(JQ}cD1Fki8X@aiUBiMqk9Uxi~?GEk{ zvd@oW5Wt{-K>~yR3jV(3eoI}cTd%`k8Svc7kRKE-0#J*0GvV??_%}RwWLHM^lJIb3 zt~OCp*Ip$zGsbUFCJxg?@Dew7Tvqfxpy9M?cZbBeMkTH z9R6L%@#z3ft>{d;<1!aixWQRG-S6&(t@5cG$|zhd@MQqqmQJu6nE zb2`(2agwZ1uy)aEiAvH0h;*)OZnu008!k0ib8fd-+BoM0el&1@6(u>iTVv_`oz2ib zVqwbLcM_qc>o7DmUt@A^IaTEOMA+|8Y)7b<-KVW^S6epp5i|Py823wb=hl;STUfGI zWdTg)!^b12b&j#6kX=TqD`a18aa0W@)n#b(-;yQwD|hq?n;i&uGndQ-1FGDk{Ej5j zCK9P2GPL$hQ6Ae~-TSc~ zQrQv+H`#7LDXdQFe1to87A)1vovor=LydMYJW=M0;-_q17(6UwU$hI}ne2I!G0S6C zb97hJr>%H!Pjq#K3=%aY)=@8~x=iB;*8Yt7bwdlk7Y%iv`Bo3>OhsuPvQsZq=4xd& zs(T((G-%KS(Cz$~dA~7o+PD$uqJ>7l9Hlo9UOgK_hCu_Z#8~7-| zM?`8r@ol{W{-4Ds(!oPgC4p~TkHpDwRmH*gcNY$3=B$K%QITc9Rg}>+wQ+X)EekK! zrw{T;J(4lLvzRViy`>JyhTYRc=&mL%5Ml;ox*KMW)R%$qA}I*gX&R_SBt2ziePirC z>xoP2njO6ZamgB`0zPdG+^+Xol1*f&(H1!54}WD|F16k2++OWm!l3RDR8q$sw@ZIr zI5MQx?9VwCF|tDM3? z{*OU!t1t%G-VDrM?}dddb!q4yo_yK@Wp8o!+^gHQPzPST<`mI)gMjS@~M_^k({2AtF*2pZS7nHUype!P2xMBEH zIB+;L1nL)1EfeqfOOn&^IS@!O`5o0FGDkJC2kZPS;}ho>PS~@e>15Ycw-iyMCC@(O z5ORd%UGQ*@t}K7mXJdY8reF8u-}Ci3x+p&wLy+MazL7A07(Eet5lAB@p@Ahw8Qd_Z zA*mrS5e&k8-qE|9LyuX)A@A_R_z(y}FXE*~3sN^_**F!jP4A8M^N&Yb36T=K5_{@L z-uDur-C}!+N8De0Cj2}*wKC6~T-Z~<%b0{|k!-zQQSG%^M-iBfCgd*lBj#FB=$wZ<#TuaL)FgfXN~-}B{bl!M5DSV< zH(KK-lFuHY%$>BuH`8yt&1p|RNZZR^WE`gNS3LYrBphV;je1{`v!)M+@71XWO5^{!Dx=qg2dH@y3@z8L-Se#~%`Jeo8xO$@WCYg_3VJ zN_=U_r%CsllAdIg?n(D3N_a%a^a*NXkxobz9dv)uo#O9>i+s2#>4}d8mGB6TEsM6K zwL&Y(Ya6U%g`iLyDsgw!CG0K#+72+j#~1RUSmWD$0DJHThEug8u-%u8U~wyR$Zn@7 zB22PdX7iToqQ7(PymHYEUOHg)JN(fTXY|6wzvtrX3tj~pVi18n03wQvuXCk>^9gZc z-EXEW0APgqeWU>iDF@pF@)#)jhHxkPGDpC-qfXB*UnPg*;@*YE8?pQczL__aW>%HM^c-256UPZb z36~RlB9H(URp-f!vxB#0F6uZe+DbH1Zv)@4DVx?M{7xj@cRqW3yW~Fk+|-n$f6ja* zo+8_`5~t)CYc$x#of^L&&2r0DE^9RKYski5Jy6NMbZC3F;45X$3`e@A$(CRQFb;R6;(!V^Y zBhz9j%C#)^t=SBwi3<9dwKufdU?pciLz zfp&G_dMs1cyImUn1M=W+kv;_3v}8e0*Z^h0D#j)5+Ma1>8i?gyTu5e%(4$b^NGA2F zwRNTlumu7vj_JmMqqK!vpY;6epj{lX86&H-C53zd)VeSvt0R^4$DiF2%f8{rDv4A| z9_XzzhI?hip`<5fAEsseGxs~%E;mEct(g*wGkFw{^m|}FJn?qn+!%NN9#QXRCPDNL zfKY?U=tx5@EDjF+P23$O?$Q16+J^ZNzas4Zg6%t&+t9-Br=L44RLs4~2H8sa41cHI zLj827owoMUdVIOZ$@^z;(CZ=W_`Zj$^)u`uwX1{qrjqpkH0QF$1#}9g9q(H?)+TzP zR^|N8GP$UGt;8d0EBiF^R@LCvm{~?{OZ-FqtHpfun$hr?fIZciO;)?nN(cEnDq{HO z1J&4dTOY}fu~d(g=wUN|@3AbdY8xyLs8QGGFX};jnoO=3W*)a`nvYt)x*CMTmRM6| zz>W~+cUNfiyxdOZ;(-MuzG8>Vcc$zbgzae!Lu4A8X=u=WD`CCV*-4g6k3oO^A4|uL zKR1C+?+bKDQiRI+RT2=TE|>C(sE={p%O7*P2PgSe5ab$SOp=;k%*lqrG_XEBPw8B= zIgt;BR#_w01KJZ8>yA(0H-f69*TCchq}-Sz;riy@yX(3;1=8t~dbN z2Hcq7oBIG=Vst?K>zmN3eY`obw;WsGaeYKhM#6O_kdMQ0;m2_Z=1owU17c0a*!v7E zxFC&&_-hfw@4QogKnKJmP}a#&n2~Uiy`#tW zfx91KU_1s47KNG}EQ$}d4hdc(bL}bTM1~fE*Qa1d8q!n+`4(}W%lID5S;UM(A~6Y~yr8$XS5sI`XOB@|7bJxjGYrX3dWkhsKAoChehmK*u8S zd#1=CJsGuNAl*dx!Khh)0XsC!9%S#v`_HexW)OFcbBS&SA->%coU(NR>La0BN_i#x zX(G%P$wes%!1A^U%~fQ8d+P?v^@A!lgI``G9#FQyu1rZJHZKslkck>3SfRp zWOCx?l%Gn<{jlzfgRP{g+n&vvlF}gyp`&5xg9jvuVn)QJT-Gu1zZ5qrTzM&fOHH78n*I$sUwez1}TS zo+caG4v^q16B&~Fxk2kQp>q!ujGfvzHn-_*5!oT@ zAKomgycA0M-%KdGV!Drq)rP0`UX-TLLV|Mg!(mtiT0sR1YwSu=IZkhBG1=VdZYPIKrz&yBJ zD8CLHFOPF70&((#Vs_9Vc`m4+Xo1#*F-CPe`3nr?&pko?ci^cI(_Ej^9(H_Z#)N;gijH9>$bcPjUQ$Tao=~|XHl$= zaR{`OB;u6MMfEB~>6+Sz{1xT!z|lh#o1k5lgaB-4JuxL8=9o}lgnX0y{Uj8bzx)@W zw50TkbZmwL9UyZ+t0!=(BvTHfhX=C+(YnafIi$~LUSFUS%)B1=xkWRk?t!o5+DF3 z6p$_W&n-88+DGCvPYpAY%NG9n+P4gR1CqCH=uhGz?y(VoRk-V`W{_84K1j?UFCRqn z+J^$^Q|U5;7z@%87r@oFggyq6FW8FMXrJzUSRUg=km&r!ZG`q7PE`P{iQti5dUV2} zd0T5|RQ4HSy>b&{bzbhgpUczJua^c60sJ!{7d;QT2~|H3>KXDeDDbS|j4}BdtjutA z0OC=8_JGEJ1g`^vH6Hm~(p`)jGRd*0G++L4y)4Ya(B@I@4D@5)G6iB#HRBHM`g6BW zo+IaOb&pyn1T0*U@%ANZDhdkevPj)X;qnL2_{Z8}N6gX_-xv5w`o|F_ln!8o+?ZiI zlH;3w3f@qo>DWudk)~x5;Q5Y`gb!#h3qR;`fuFcs5XP=4mXZ=<(+%Wy2H>_EEWQJu zpc+vC;1rDm0$~ea&H!0pP!0g|%*lif%p%zIS2E10hVu2dYPtgQ+&<<^dJ~I zcTlYALZ8yldTN8aPrK;n!qP)=0-@SM8!pIz>jg@aPORhWpqDXLMTCu3-FI#XCjHb9 z0}m(UsdqJzmvp&l^tq#cP<7BsGJ#83n+>9qIFcdwe`UtbRc~G}8vL)P9<@I+NSGJQ z`QL&t{J*F~aQiEBd6GCawWPgplhNrf5l5WBcLek1^s}>!D$G|^{qcD^R*T5` z+{5Y=ITbXR7n0N2Ja%oX#Cnbkg+!RER6zQcR}5q(U{!3j4ISD~k`9dRV99pIR@1Mj zL)GJ=#+OS^-1(-;N57g)ZYHhQSe13c$yQk;Wj|kVoHN)BZhG2`0EbVfi*>b+Q-snc#Tq6sc?bQ%ADDCF0T`o z`wu8=DwyvUK~_L^BtW`vka0*Snk{q|pLcl6L=~}CEZ_f*o}4?Lw_OL1A4?e)unrqY z&@2Y~d~eaf0>)J3XQtpeW2%T-3yIM@2|$|n$)5WJeeL@wo&L94gN-pD&l83FRHGh=-6za2PPh8u2=bnblgoWPS z9Ro9<#?piKz&2YDwm|8s*3uF$pXk0(-JobL3> zh-lB`aKl!rA}Uf@OcNp#dfI3higV!c;T@NDq4N+Vs}}NlxCY{imMd_kDEzR%@)(QE zt_ST7hR)2O*XOD&D-C>b9X6jv<8$w#VPYF+nMs5nd4^xAb)u#q8&(El)2}0SDiV!4 zX>aSA7#V0Dr45}BQ(|0BNo8TYUFv|=UfJ>fIW(~!z{mG-X`gJYwZ+P8@b&KeOkiz< z&*?NC7>rXV!Fjt1`xn%Dz1!vC!F+Vocg8*yn>7_2Cj=`Jw5?#FVPOz*B6xBxDWw0A zeeZEe@xd}Eb15Vo;wrhY2v&WD`np=?@~Li~5%~)1HGqjS5caF7m39KQ)GJ=yOgF~g zhLPi9OE!~sjG`&d?^j}*;vSdoKCWoUYXA=f33Q4FQ)hEiNm5Ihi5uhlW-nEAa`Cqh z6a&wl#YSMm|pp^CMQ5N?_zGKp{L;h?lSwlIGq;gql>LttGo`A6+j! zP`@n&16T7@lTB|lUaZQxR*R~s^4foOoUBsq!PiT7v>3oGyw=BjyMC=yWSXsaQ+)mY zVAIMiVm6EE^8fa^xo#a%iN$*MNJ>t_FN^s6hHdy`jh6cgBXtU&e`HsaF^)Q3iJT+r zq3f^XPb66_>43qk6G$dKweU|E5G6jtDR9M1Qi8*TMKcCct#CX52bL70nX)C`5%|KV zkkW*h?eAt_;7dV7LL5h{B95?M>H%AN*m%+r=RH)$_?TwcfF?L#*i~L^ir%E(0*;Ic zYK?TI)Zw-NLEWhr+|RUe%}PQe=xM^}uo(!|Yh%=sER$%mvci!HqN0+P4{c>aFC^bz zc>%nj=?bB36r9@z+ke?F>bCl97Mek)czLuTHcGgP^PCkznbSnj9u~Th!|P_e8OPrj7fQF z|Af0C=J{VQ&=M$%hy48`0axZj`6ofclw;?^}6WX`Nx zcIOK(i$a^RRo>N*xt_AuqqQr!3w9$H=Le-jFBHZlxcD%OSvMJw$Oe~=oYHf=M!z@~@CQy>e>HMs)?Z%Rm<7N>R1iL3oX3e*< zvlV)sr1$Ub4+-*kn}S?jZiy^b&IG5;VYwe(XG8XAd{3yw({xKcQrGXdIGA-0Q=KvF zJWZ5N`~7J|yXse?Utc8G{e%?6WJj}~3Uil)xJ&gR?30va3Wox$B8T@RlXtH2Z{FK? z?=J=HlNSukOF|M#<)qDJW>#dJxOCttE?V6yd8j0Rx2@!VKeQ6#&xp~8^>D0OEpePTO%ojU*k-+6tSY%hFzY&IW~{i?}6rf#=$( ztsTyDd)vizkzY5Gy5l2qI^C{I9JTMSZ)&qpe|~4!f2Sl26dOQahk$a(!@5A5N*G0I zbqk5AP$6LCQkSX56`C$7UMw)m`jl+2-3{-{B{uMwE7lJmb*4jecr}@+G(ojM=<9Hb z54v^_`)(3fx2|sgkxvg#Y(*!f2gnVDN~)4%(@K=HQzu7=icbaOlO}=%c$O;~LMhyn zPGAWJSp>GkIN8%!kS-G_O)gD(Jjzp-ZkpK}+q^I>4%3N-o&yf+o315d^qHkxPsg1( z905cxB7Pum*R?Cvj(-&7G=TOBya0fH2Zj@FfWImM!DnkB^H5EfMg`_OSlOS@nD&sI zfAxtc+Y^18A*n$S!+2Bg1sq?6GHvwi^U1c^KvtEdfFg$ice-*pRXxeM;^sPoieBZl@vbF4gD7v0XZsV9lnGY`=-F(Nlbr}!t0yV(UAniTc1{sb<%fNuhd4#byt_Oi)NdNoCkw7UcwKb zKT5`MZ8PF?QVzNMTr>~TtmUepekDt=6RaR~6PyT=DiAm~-5`E`+ohx9m7$HSbN;Xfy7c!0ZMvTM zQE+~sbv-}x*B$x_R*Ty0^-~!(4mO(l!IeCX=GT2t#mDlEa=M8HFdl52Fy1tWlSkH^ zLRP-+@+I`O=_OcrQ*mR3gw+s`pWs;Mfc@7l-B8Cw;j*mkw?dHNxnMguwj#bGEWcZ^ zGqeU(tx~PB6=Jr61ez5yMw6&Hl1TLuHk3v&MzXo5wwxX^KSA}O_o09pBU%h|2}{d} zvQ=S{uLBgfz$~Qzo%qv?uv)M1DfH3VMWi(jPQ+dyjI{|%wsAzH&pML^83q`v=L}VP z$Vm~Q@;p`dgl!C)9R5$#18!Lq%4L-0>hjdOQPVK!8xKRzyJLRH37h9U%`h3Upxd{t zk3N`h6IxK>;aN70x{ZBn9o{9D!L}ZQ$j_SP(!J8L^;qcHsJD;jh*%GgFe{n%31*`< z)%bQyeUqb}3{~Wum#}4h!CE+Py{Pm7^T+g%{FJo>Ry*zFwT)aT;$87rA8tbbLC=Oh z{?)<<LCy?*DYqO>>4zo$XDsMtx{2N3O=Om7Y<)^{$e3M7!`P{j(x z@{GL{lKQnuVm)2^UywmVjSl(6QrSwffnuEd$dk5A7IQn5IC*F#%P|jdHp)OZ$_mK{ z!9cH@ZZVwe#Nb+?nS3daD+PDz)Qoa5*F)R#=HZZu8_l@%mlRXc!)bZ6nh4OW{zg*3 z_>l$^W)fS@r*SFm40Vl3vb{NV^kBA#LQjHnTrcUI@9)_OyiXc9$1?9XoSJm86R6KX z0)UkyU*g9Ln31HRUl3+-FCy^F%47YSCl4k>y&To8ylOH|lNOziIar4&SNuDuIWa0n zpPjPq-xV;)fJU^pTfIKcLp#VjN-fMV%rns}(EsAG@|ah!`I>*OkYGP~)vlYc{*^UL z(leGU;7ik`)|_e(q~~J6@-CRnNKA+5Q5jy~z#&Ug%tm72qeJyxBr8oRg|sY>Z5zL9 zUB7P~7bLymx!glbmA2cuHDKgYlbXYd()6V1+pesP#BB3}vRo!q&XKgUZD~5`A}Nj> z!*Z0=nc-ok%LFxqX@59Up&kfo>wpqn<*>4dME(>)j$B!_A34wfx!RPVhU;;k&5!e9 z!Iy-BTOz3$r$yv@XIb-tjQs1uOuX< zj4Bc&t8)j6IS$fcx^T)ER!PCt>P!L_5?I~!p1cqc+OM|(&cC{>GvXt<-@Jbzi|XOL2s1$cAOaNY|H*ESo; zZ2zr#Tl^i%_8p1I__`#P|7us*GT->t@i5k-zF*(F_eNXcyHh)AZ9YPNt2qwZNOPsZ zIh4oAS-&rzPtwC>z3y%wDTbfwu2z?u2?n!ulh1W4vblKS2%~w7f2N$*sErpaq8!6h z_^t{p$xQus|10?WO;-7`phN~!@FY>r#Ph)t zOqJmz5uyJ!f8JxH|A4tWkY6c7_l9+_ph|+VAOLNYywmtb_(ga{m=*Vk`772wTzFqn z7ILvJTe0XhTc}owHudUJX;GrG21o9CH(Th6RgPO!oJh&764bV4CReIgFvivY{S%6H z1Y2kVsw+=vcz7L`xd)g681MO-9A?PeDJ(mDZJLQ>*7F#p7 zzO}rt&WHh)0j>?kdBl3bN=C)NGM)(KS-gDygcUSzvY?GjgZACJg41$g@lA(_qbK)- z#$1|D$kv2JpcGj$AO*o8(#$n{Qnz6P7o}GyS+B`p$#^MCR%_ET(Xd`HUx~{$Z<6{X zAo^Di1*ZWL7ppn5pvGB)#w;3FHzIb850x>J{cs#fp^+4%HA3eLa1^iK^T#kediW6#s0FPi4 zy_ig0{$D}!oVvlCgfb&mU*?b4RB7oYUblL5d|Y>Ib)r}A6nEF0lyljyqna)xyYk9> zq`%0{HIsf;$f}og10B=2V!1dRZ;+$z#KYOZ@rZ2|t1zdp=14t01h&$JHdAeE1Vtq4 z$+p3~=5BF}ZtW;%1@Y+nv;PSvAH*$Xt(S?kqQjw$oXdz!9)$R=SjHBc9|IAoT2^P# zz$5XS4ci`NRqDs|$ya~8ti#e0*8C|8b}$ikz4F4S-=bAVc+-iNC5@@4NH|VB?O1^w z?T2v2VrP|KwXnGEu_LOU9vOz)MjJp&JF%aFEWw@n8TQf)rJ9N*3UMEP52}VyVqSeg z#bI3Q4jr`M6ogkeVfScc^neXKB;PA83n`PyRpW|;qEE){nw(lZ+U-BN(8a$=`B+ys zSuQ+Z%L=J-)qhzDeffOLdGsSkEPuxPA)(?cZ{=y}&PRgI?Z_aPl8j((+6CN^1gI}E znCyH`hJ%*Q2hxvk?ECr?BK>Q=f`WLh?9T*_b&ZoCpD*nu!Epm9dd%&N+1QMXvL~!8 zQ)YScEJbT_xD4C$wL~RUe(CG?INuLwP2gBfZ~-|Mcf3lvz8}Ou5iNI^WuKc-X8wpK zt5XoQAsn%sO>j16lh=-S5BAX7cX}gz<9!xH^fgJ<+{cBDODo)?FnKAD(nq9Z&qrL7 ziG=LO=)dbPR?xCt)o;^7j}Qg^R+9k+okl6E05u_h9W7e{vn{!_2$4W_HQ3wfzZL~Q zZdGw6f9~u<4;Z^{n!n9|bga9!xIPTxi%r6|%jb~cB_@a|7NhxHJX?+-n7n%sSB%Mg z+ZnIxdXCR&Z+e34U(?8j=|7(Zd1I*O{HjQtX&dFo&v+CFI(!HQ)r8y84Ar^35Fa zJEIXeY+QJtyEy2P2*kGZ(JD(J1M~YS$%6LwyGY5l^`_w7Bz>cdWYM>hiD&^f9(3wi ziU2`&?Qg!@#}druuU2#M8DuW;L8P4>ZN6Y*1ecq)2U(dMZ|?TGYZtU06EzM)B>Num+uMZ=yTr0tC{ zv@dVYMiuP@UTw3z83{LU;k?<55uVw!uSYQ-EGRJ*BC*P_j4{JfbpL9wOhj```ePK) z$oU5+qMcojkYbB!+9`!liOWo|rN!D@OsO}IMqWX=E`K#3 zj8bt}ZmOvF<8@ePb+fp4Lay1#NAk@)l)I`VB1-*g$wMsSs{;w7W97BRMd?Fd3isvyBJ#2? z4o6O}r+02lq4T~FoUbjte`Bs*Vu{(admh&jk{8hGD1NS-Hc z<*z`QCSU7B!* zbNi0}+zww@{Iw|e2c4<9z`#asA7?`q_r`2fnIVEOGueEnh?E)o^Jco?OusK*m67v| zw)6Tyk&Lg$NINSBgO`K)8Q>&TeyWIo{e3P}W1aW*I4!Hw6~%oX(bW)6G7-_;g@$by z+y;+;7(Ki%6|`ll8^S);q+XUjK-wtP=1KZ>#AB(z!o>W{YTw56Xv^Z@+z{vZ^n}nR zWifQwMqF z>h40q{=mks-tjJpqj(SfI1);{QI!Na?g^5P>|Cs0D-Z0??iUX+@Vy?_*vzrC8|JiF z5n3t_+-G^V>~=%m6ES|Fa>}U4$6);CDBKuNfcx`B&ct$!Mg3FORZsD6H%d`c%A}`o z1#0ZQyH>}e4ngU08PP{XoP4J8tq6z+`lgX_+)t;tO?=Hm76I9u%?-VxtQD}*zrVGv zOO{UsqDUbyp&SbT;1*n*D_5>`h{|^MbWk1TbFYTsgqm(An4A7l@Pgh*to-1Ik=v zcGOM?i$gSv?{;y=sXH*I3qgFj z;Rx&=Z`Tv6VOm6U1TSxvr#fY2+S7K{$YteJu%1t=@E8BHi>a)Vp+Ynn=%BGH%APMO z%*KDFm5b)6xf^tbb>>v-9l&oDy_}Mv0bT>3#pCE0{NM<|;`W5XzO8pYKMU~<{m$Jv z+=l*ADe5x{<$wi1<;*iuf{ch22*sYIGW&y^vM*%9JTw}rE*eoW=2O>=F=V2n#NKN1 z48K-dD0A4(M>Musg^XeA(`JLc)^xb;gFIU532SV{Y*XX42cZG^`IOwwM$3-JrY{q@ zU%#I#3W*zSQd_81C!pgb`en|HAGcnaMilb4)ilqQQBs<=1dNo*7m9h*ViAX8t~xvd z?4~v^*|5B*#U}`GonULeIV$eG+LPoZS#oWFVOrBvS{nA|wkuu{327-fFh;b7ek80x zYgqqhSss}Js+WUKOp7Wk)IvdtSu`aXq&GXyUwL9QSGI4UAWq4q&Yb+*Gvc!-i14>E z?GiFVZNJJS*-7p%Qdey$`E*)H)#mr2kFLhYvUrzA;=z{iLZ=GMf`+QJ$ z>FFZOYjP2OhxgrFb=qzJEk%wPA7lm*x5ar?`xOD@d|okpS4Q4HC%l#Jh>xp9?bj?R z4WvK;F&mN8*C5cCS;ZNgW-|79r1^Dv=@}meFZzgl1BA<4FweJgs&Ju9m!pfoY}GEGznjsFi{#*6ne$s zSS|cdMn3MFHHyILcYNQ)q?O5FpW4GdwlzWv#jrqdzjY!rAszj?-k-(mxOMK>vF)H0 zlPDaLt32$k7(vC|F6452Jn@->P|i7!PM0aS zak+-Gj9s^RQ#*;4;B`OCg`zJtZkx1EeQyP|hdm-&nQGGL2&tT?9RdX3--}3t@5n; z|F~{Vue~?>dD)353*Lkk>6b99njPlK3q~6!j#elno6Y?W!VMSrGBOLUr2%1A2w6H5 zq3vs{6oGm?evSRAXrJLw=&uh794eMaS74#kdFh`l22wy&csQcfU|ZcCD?S-ukB=AP z%TUm4cq=*;8l+dvW#ZLk;RwDdOq>eK*{tmmExTNkDF=u-XRV|{s@~yq7+iJ`cpgt5 zeQ`yyY`1V+%d2lCgdaKNY*D{VZzdmN#A${o+RiLfq=rGz<=c{pWK7bmY_H`sITVE$Rh`%0 zg%37Xv$PY`cWoO)Ub9}TH5@I{Vx|&5GwM~jUAc_WYBX;)r;(uYdpBF1g#tBh9?cZn zmpd#?EXG_j+%3ctu?N#S^Qp+ir`nAr_n?yZ65qZ>f(9M!|`M5 zQ`8}H5t$sqW}vEYA7;XQ$pxLW0&;xVtYN;rg>&WV^7Qihssfd3ol_kaPf(aJyZ4@f zR84!8VJ?>ft7N8GiW$*fQ`#b1tXY%HA>;kRdSNF3n?7oOy<~x+C1p5*)Kmswuktk? z(xFZXLaBB*ywbXEMr*Qqbtpqu8gGU;P^Kwc!EAp!%Jx(<*N;P3gj}xN66CA zUh1xo11}PA%xw?noml}$v?l7SWZ3%T(| zV@jZ0=Bf6PGEmkk!^v{HLPF$t6MSsTldwklf3x4`8sOT zHifFS36?!+O~-kS^In^T;K2hYK?*UWjHQqmaO8P%UZ@j2r$T}`H1*G4!Db^3(!2>@ zcPH_sKsJeboRNc0cC)sf$@Mr7wDBq_XKh(p$A&vqaHTon7pg6$_UDl!wY{8P>t{a8 zB~SIfj^5&|WM*hIva-l}HRsA@8BejxiC84L*lMfNS_ybvt{GksK0`dsk+aBh1-!;~ zAyx&>ADU5&+12N)9ZI(=>CxJ`I95t8{U+U~*rmY8calC#4(#%p9t@0;AphK;N+dNv zw;{f9;%hgEXkIEXlPH#U(mE~s{4uv&_j5oY!E^l7hUpaOT!H$) z`Jh8qDc`CH)KD~kJel6d6lSkm0$E=sQXJoJI>&wAeaBNyRmOL95`1;uO^$eTbXDIY z0VM!fm2c}u_K+kQq?s%eXx+842_ADH9tkaC&ZRgT>b2ubj)i^AD!)BT9Sgk%sqU5} zo>_QnGZGy*=-WJJ>f(IG-w#`CBL%paFG9;^qEFWnyv?R}107q;S@$loUKh!LAI=Rs zWg8#woSkpOavfv2p=rcg9;o>{WJKZVGicd5lo=ORu9YtLJkS|9MN+r0xx_S}S;Z*9 z-`32aexTtA(97p&z)ymxp1u5`n(I9OEmO@n$N#p!8B;Nclo zfu{Kkye1^{>XSjvG_7oV4Z9f^{79$ucT9Iij?ih^o_cnst&)^!>ps-wzH2lToZOJq zjnq0RM^dRmVMJprUedBwy1=x>vMqQ2dYMpoKoF*;qM$S1(s4v-OrEex5p~n3P~w$V zEwf5t?PwbZq~;AI*hVrB_6%+l=2mm9)-gU&V24kfvr1@efwpw6blv}t=RAghY=ZI&w@jJ!0zDjhMkj(NaVhD8nW+*o^tT-l4>nuG} z!voe@%i%5T7sSt_RESpi@Dpj#kCR{K;Su-nq#TPDO*lLPBJX!{6~uS&y3&g5HVb8U zflKk~fbaP}Q|V8?&E}uld~E-m*eTO$kfY)~N@~=?$U6GlaZj*z#wtyy8tH=ub|K#7 z?piph#5S)lSxr}SENsGJbzyO=+kuZLimE5;F0QNVs%{{-uhmB3SO#9E^r(+F*zCm} zS1g=&c$lAQGp?`HSv+-5+`g~WX?nlx);D{KnVU=PMNX`>FL_;U==daLYBsPMYuTN@ zUN1LR;%*{I*CeUv9TP@lF!xqN^}DmRs$P^_0L_x-VZm3ADGrGD=o3{2Q$4aPTenb@!SJn+E^^b4Y}%*s3Eb%MO?5>} zHatIgxEgreX$$vFUHLwIRQnb%uh+GJOI*g=)%HiCF>J66sL}{=|Pl#7`L- z*O#|~1@pr*)2vr)iqf1{EvhmrZqR6*%D1?dLm<+5V# z4#8FeSG15<45!&?_;N(tZ#SIq1Jz6Ay54RJaT9e(DEJPgvIFT$acy@a@xbt!V8?b2 zVbx3aN>bBq?8*f9V_yJPzh`1$GcP5Qm&H|!l*dKWFL>cvaS6zgt?!s`Hf`S5X)`Mc`poVh-e|9gVFH5CE@%Fj**_ zKh9AF$@sq$#%Gd?J-$s#?P^Y2?hZ^}45m$+J4jl@iiax6N)|vVQaX$CL$IX9hIH1q ze+Bc)g^*CGpn?=pAVosDrq-GYS874o^kI%;2T>KI}S4>3B8OrAP`Byi$^Rm(d=rXoS9n-+x02EQ(l{T&cxW_)=wr5gnKR z%!s;Eh-<*n&oG0w+ZJWMRkiHI3+stdmGjy48oc|r@2WFm7HXyge+A+F$C9&#mE8-j zc!1)Cx%|l+eb-)ok06DYR?~nz@RiCt!gKU3#47~fh5zgc$*8X?%$9dU#dk+=@3~BE z&vg@xO_x+Mb~Dj<=;WsBQNuSo@UbBepdIsF;?8X2_R7Ei<@LQEjZo2eoovXVVjGqw zOzg76BJV3i4!34fV}m%?@JojOaU6fxZd^K2C+Ud)pBw24ALTo@5OlAJvdJ>^#>-9l zsA(~>*m<(4d?$X*&Rq_XUP2<7=gJ3r0hhh|#K|%yBB!6*MEpNC;M+JuW`xXoO3qeB zy3TrhO+Z#gCORmrH3N|+KK{hAU0k`;26UaOb=ulo7(-*o%r{lZwST9=&n(%2mMANI zik5Bvp0x7OSiZ5a4o}_8M3u-ccEF=9eYw6XbJ^RaKGf6>OOucTr`@?>lrP;l2%hn@b1t4&^Jn**#7FPVYxwC*6s|WE$D(LcP;r>Ax`ABJmV>!SP}3ry1}d9^Kq|?%n_3 zbP1fc_4iewXuE(eD&7AH|GRxt?$1rIzu&hCUAXRFGyy%u&QjljnsASAwWluJr9w0% z*DCh($`i`=%3{q4!L#3biC_u$o=MLW-b1olr$5rOZiosFh*Zqk)dAEsnm)>oVx+07 zG!KJO;d|66aXI~dm>9`>Dum^;E&(^iFz%F#WhB|kjRXy=p2t5z+C5xrb5}jlNEFBY z)6&C!Z6CNu4{+uQb+NkX{YdNy@d_FQ*nWAKU8y(YgDUcIZz7{pb`9ibf+b4DxL@LZ zYODsn>WTXcfZxs6euF+&swpDAKVE)4J_$HrbJkJYFQc`W>(BZSF}z#t=R}t6SDC9n zUtbmAzHI{L6gm{~tSm9v+ujGQwKioGb=Ez+(zi=bATr77g7SMF(xdkI#(PR^zSfT| z=UxYdz<}`EA_;_e3pk*Hz&AnF^x+limxNdD&BJLMM7!dh?K}roZ1=5WM>;5of3GaS z+0wX*yQSDtx$^c1D?@;FcJiB~3i`zeFId1=w@$XMeunQxocyK}Ix9>yUV%a``#WD_ zxC^37;a(P{D2WX$Jhl?0V2aFMti%I_A`}g44qs5*NGI?gm0nG&AL~ACRT#)#J zLQB#lVeD7HsY2@U*r=g!{pDr?c@d?Z^9Zk>?OF%q)RATrlZ6hY-OfkcW;l8k#!Bxn!l!IGTz5t9L>)7yT^;Tu^PH0?S%2nTbyzE zAtP!D+bHB#F%^BpCb?9JrND}{*pso;{+Pukp{y>)(hhd=qo{)y^xFk5f&a;PO(<<8 zMkh##T-ArO%jtJGYz;9`c@cNl=sS`_*UvvmL#1h4vk&}H58Tn+3e5nL3^?N| zb|6IT>)k8C@2iT=p>fw%u$)T8=Pu)`R%v&vUPDwMgj*Nxbn*N5*=nx^WIF_(3&uK5~Ms z+P}N~AK z$~PlI6ikec?mB-JIIvxD$^ya$0F?V2t?|K7ZFg^h5%>6%#5be6z_aWXziERN#-+Fd zS#*rWL)g^`?`aQuz6XA7HFxgFDF4;+yJTY9cFvA`n2uXKM?6MbjmFulI{eL7c$mX< zDa>-(_F5naa}|nXoA88)x-qG<;P%FD^V=(@`?(xgyOi6v&FOA2NSiplZ!iqB!wZV= z2+cI@!M}=soem<{4U0A8IHfBE2n|d5*!D1N+mF@gXSQux)av`qUbR}Qea(_5Y}6lm z;=3Q!<2-s`Td9_Y;?HW-?{l8Kt3>o1tO#jY- z=Yly$O;X!A5~MA!3)IiNeF?T!Bli2b5F}DtSl=H+F01Nm)?-uKG+VEagSIoVQoX%+ z{PD?D+>!d_1!VRJWO;Xb1||vQl-`l-)L_pz0p>$uB~KhgQ^v9Cm4Py6i6iGhT8ptLx(=ah<-jU<~Spn?Oe zgAJd$7JeLDTo~*e=WAxsSI9RDc`2Z0?Qt4038F^zJ%XV>n?B=dR2096wH8mj8vRa4 zj6D;=>;P&WtSgI}C-#eh;>03MB&$Iz2&wDVjEEf^b$!!+f$@6 z!JiwLZ|bKqJ%nK;EU3Ov=aiQo2=>S;?RYM0U$<+Y#}funT>BHn(JSeO($yKkxe(*S zU^g(&i?w4#Bv`dE%D;wsNaXx5T+CD$E+?}A4&R~l-M60V$fN;WCSpy#!v)C4>DNiZ zJFr_HQCQ1LmuK~r`K!#B)iCFupK`?DaUbz9p6cLVVc6woXJv3Sw9tQ0E!Uf@c*~lA zFFv3oYMc#hMwy@do(uImr^l1%c857Xt1YnBr;0Epa5h#C4q}N|eoZTGz@EqHvNusT z1k=<=N7n?V0O=6Vb*(KaqGp*^>TeSp#T@A5#PF-&=F_-)Hu5Jn87&^BqOohKj{M9U z&3`LUO-OKrcm9mou|u)e6vk`9HBJ+49m(bhy4EnQ*WAg7EGT?6lUz|zxfGjUU?r1p3sZwvi5h5mA5@F`kRE2t@7^zO`y)dyRY;j^B_fKsjG2zd1c3h*R+csS9c=Xo%?k_PdPZE88)Vf znj^0)rb=+mo&+oz(&Lx;kwHCtqqgkC94G3!W|yCaH|2nu_d{R!V+x*lkNQj8?KWqw zaKd0lqhmF9ae6hRVx?OxnVQIQT*@Co(Tt!+jdwt9{N~`agy078gddhtuoC2I>&Yj9xNTxrlKPwX`zA&kO`w=5Zl$8VD6J-)67R4@gC_V)v znK-6N5e4k5avW>y`w@dYb~hsW0V26fms+7Hf~pGWa48+MfoJXxmI_nA5_{!tm6Yw_ z40_%OU8cLI;1<*>P6=#D%o@t=#d+W26U5Z+n78&081Sa-Gmj6O=`9uQT(9Wz99^^4o1KRh&K^_WIV z^hB{2P7HE;vEG?Ul%e2=p&pFdr_Ut&1eHU7P+Pz&W-j&IHW~1U1QF1i>IIGJ>(!0Y zP-*{ITy09Pk3&jEX6IrIDiir_Ti-J!sW#pmS`M^q+^$k+=o#?m9Yo_&D>F8t-laIz zTMTBV!0~(6*kldLGD%-4ihiW>=s-@T#C8IW8n0>7R;$Z4_tX@f5xt$9$6vM{P?zBK zH{F>@l>oR6{6M_zZf3G&Dls~3AVFX+B$p3}+|fyqe2mL<`c+`NJo^b9k&ry_iFcD}qKtgk+Df6|Vk!kTSb)FO$wnkQut z+dk+kdu4&M8N}XxHiusRSk8~QMjGQ|W_q{=r!O}Ban!I^&hOm} zlSh)+7`#v*-soWuWUvwqJ>Kzcd2#JOJvDKhDO$LNZ`*GHR2h68UH$8TOmCQLaqlWcJg~6vEJ>opShj z9{q>{v0GGP#8L#1P#o4Vl)7WG5+lCQ#Z|9+%a#{(iJ0f0?-<+? ztPM=PfAH-xzSHj>`NbsROCFK+>?|U)`cM?T+gtOc7}MvC3i-8I8GuwETY(|Ko#9$_ zLs$kKKg$m@CEsyaYGyB0BNfJ-nhGOpm=vP+Ei zX0jonEt_S24c=vf0$D;exA>Bi;ohws3mzVb=9)3CVPbe%mp~bGD%&4R1oTydOfh2k z40|@fB(tG3u!NA0SK}-9#-Do(4$?!hiE=#*j=RcfOmoDM6<$m;g773p3u{|zj6Ru@ zoNDK*?Ryt4SGuD~o?Mnu|aI||m?+yY}Ot8(s4fEODMBjJ}Im+z89hP6LQV19rW zMh^L4=Y0NK5WBgVwn!|Kq5xR%aK^_oPp(M>dV`!NZb|daqfLChZJI)p(=A~YoEnAu z=z=m7MUaf_+z8ZeSaj%JMnNEFMl=Bx2Lsm@2Q2}MdqQgRffn{#ebYg}R2T2{PXrw} zAb25|;K>Zwp&potq71V;!p7dM^!?QoY3_|PQ%xdpfPY|c;Bmln&}@e!Y)t^@1?9!Z zDSSBuNAf2j^n{7)zKqx+-t`4FmPx(;?_~uz|7T?dh*{bHvx?2k4`9no zkf>(R!^!^s)RM_Uh|8>dHDvV4-N%>&lIuqNTDz;{%#ya%PzK5o)|2JJ@#Rm9N-z{K zCNTXl3_Zjgfo&iZ;7#ybb4%OACZf1qyC$&#$v6g{fho+52a_qmml||B`ZfZ?uWsj9 zRaNsXhBxp#v=a~3h-*ap8+VQiuP@-MNx<^|?kTQ+^OTaioiQ<^oPhBv5nH90(P6yMHH z1Hvs59nV*KWpPl+5rU(fpjH7TKC8I))lw2XYs`|@hm0$OoVdgt5?q8Ejx;LvgEm9y*!RJ+CxBt-Dmfh;i!xtF>ov6_>yfva7})28pzWz?-QM;# z-=5}TEY_ng;Zk)M-2I+C-~h;Auir6Po!@hCTBSRPqotB98!Ois8&Mu8^Fmp+;(T^t zx7@$80PTBf({Ofn<@Audvgvf9MjObps!SDBVW(F4$)UbZ8JpXV^0xcx3Vc8 zaf!L&vBpj>Ol|yF4b5VRF^&x#ij{Rp_4UnjgWr^b@m*9oU10X>-qDHvR$M8(7zTknENKvTdu5_fB)!@^@A?YP<5*~i=CaX1wD(E^K1 zc9y|3o=+ANUuh_1qa2@n=9+FbaZC;h^D-?Fi@Yauhkbsa-CS&dtVVe^6^}re5r#cEFp(sfR)o`+5 z+FH>Xm;7^^rdUITj0F3j>lvV73FU{~&>xb7d~*Dy`t4i{A-xZ4{v>PJnaVTq{HX zQ5ZpFfM{P%xbrv^dGU+IjE%1%j{qQ53IPV zYoZO%;7%;X|Ar~d{{|_-wl+@2HcpPjte-?hVn!KbBXfNrTQ_3O&vPbX4rUf&PHq-r zZDK}weTUD1#H@djKL;urJK8!s7#ceg^YIZginuw60h~Ue=kGHyCSumVgeZO%0s6$B zPZ58UML)^h|C=oDU~334{*QsBkfHss4|Tk3S%&Frcqs zKfyssLBLQ!!BIg!dO-+2l>`F^{X9VaIUu3IA)vruKw&?-6;MFHK*2#FAt52a;oxDw z|C$yUI0Pyr6xtUOX3XzOc~hhc`t~u<=ziNQLOB>@tcnh~HC@wNSlD0Lg#pS2{`oVU zDu#}6@wJ!Ev2`$?Eb%@?{Uz}qai1+X1Q;X~DD-D1AL^$(Ffb@+7%(tUh`+@BB@Y#X z1QP8F^LGU(bbY^=oGAP;Y zPuz?0aAgCAFYf# zu@v{@%yD}bP~d8A%zXw4hvmv4C9g7Fmku<$9@$XrvE*k?^q8y6x;XQnaJ@Ji7yD<9 zlM9Q>H}h8ZygmfbHJ7@$=J1MZf=prd8~y^!{xEqin@Euhnkj*xeATSfCNpR z#JY%STfDga8HsIO@PS0DJKA&Nrq8+J>n2To(LfrWpT9kUFOzCW3;zIVnk(v>0AE_) zHuYTAEaU2aO0zVkF<)>|W~`)^nb6R1qCb`&wG?GhFMg|<^5*p6myUO=ds{n>uub>? zaeHP>-G1!|`OBCtoV;X~&c5Z^+7|Q6A_WABD(E?~!+?Oao-hfiC9QWU2xEfZC3t5J zQDr3xGiPkU*sI!h1*#0XIjs;g?kAT+VG|DzsVo-by&k&heC)yrWBwJp=NM=oSF`jw= z3viHSj5|oW=C@e)QN88k&iuzyGWyj?N$B+&KrD;ps65dIkGKSai;fZ=6Fp+<8 z!oC0M%NyqM`S2fiUc$@f=FezD`D>yx+epMUTmNxd&G}at{bgEQukXE>PzRrC3;z|+ zav@y)e^&o7kNFieiW*+}=P;yCEg}Vox8cDZ|8a6rFaCEun}0%*?J*#P4srayloicF zv4`~gei3?Y#HZk)`{d0qWXK$ud`W+)oZ7^iGbCt7*_;KF(# z2dTPzu-Ue8PEhFsKlYmMd^uHFK|22h4**L^lG{QNz5|K|Hha444==t-Yv^~!k0Sb4Tt;Oc0~|0v~16R&i2#+IquN9wCKUrv3x z4)iQmoh-G)O^CO4OLbm7o-Mx$JdnxH`L(cjEnt1-c&TH%_b)5u^wrPoJn_qpY5KVg zoMG^D{sM?8w!cky*sdG8bM*vAnEq;wc&DhSTx-GN@wQ!^V{9>(lNwlO?nr(Aa_jC( znKfF(`)?MbvUunux;gH4Y3OwIAYG|nu}q`3nmwb}hijqdiH|Sh-_w?>RKdKUt1O>i zj?Af>H@g?|2xMMY{D+cd7jN5c89>a;QETh|iKFHA3^?X8 zyl2grw9JznKCX*OIYu;g5Ng zvDMzX%p2%TbpR2EH+!9dGmkq>v$Gt-&J4He<}T>-JF@ zrzM{MW>o64R9C)JhIZjIitFnQo$T^0$;=|`?o?&R2esnjA+aURl_4+YD=r(7{{NUC z0br%Bb{pycLtO*({5PUPDbh#?S1{h+3uyRX4izotWgyf=9@rq>G z%^RqiO2ih+6j6IMECfbX>=HFbM)qCNx~2;AU;yE^8SOazd?sWV4SmX`+i~h5_O3%; zw_|I4)a_|~FD+}{;X2>TKR_A<|4op^q9x~xgp{I2!8YibP&!(mF&$OKVSaq< zxQcsWBJT~PsWW^T_sW{_rTO~gX#l>;9g>H z!hyf=WFeh;s)FL6*EzZg&*$vtkbP^H*lw7Ef^WnF~i z^<>LX#%1rzMWm)>J5@%b42alL5S3b;t)7S*6HV`#&fTKA}iCRKUCI34ZrjNx$~@Bz~E0kY?T$)A!Bw2&HjO-D9p^!?*LCs+@FohyZ`}DWCQ_$-uP7U>0bW>#KrgEyz>~H zVZ%xwyk^Dn&nySazytNza3G1hYj_ya#bb@9nXr z)3dc#U%&Ht|28|;VHvG;kva`H^|h#%NOK6Y zD(&pMIqi8r{Q#L*^PLp{5&X>CUH)hEUkeSKKWS}ll;8qmQr$tRrkz16*0xXw(|w1# zryqZQ&V1P??%uE5yh1f7!L(Eb_;!I-g3DC8Gs2e+RP}X7E|MM3IODcZVql=hbUj*` zS2AUg!%hpFK8T+4otLrZ02W$mn(AssB{@sZpC7HQEi1JF9OFy5$C-*t2JG1`>u}f? z=*j@*jVf}g%2%4#K!TSSgoJV{%UP$^jFh~RW%HP6OUbjT97*;Azy+JD&Yf7t%BWEu z7I_GeG7zXeU;ZbM1%8NprL+=#Upe*x za!&gJGDWmq0wg-qPWu2^Rs8_T^)3bx_#|V}$nnX4$J*~K4?^))rd^#l491&f1kG|vp*XYWToK*n@FK;HI2hyTm3N5xwGnvcE} z44oX-+Q-v2Y^IjB?BB;x<2KgKXXBf<)lMi^9X8w~ov~i7KR|YeB&*m>-mXn;^DQJ% z19MM@1Rrliw(J)pMDVrQxt4eZTz!fFwLA;(3RSWyP6X|i8pmxU)Rc;F@q5jQ>nuB1 z@pU6>@%QC6m}4i)HrZRa@dp;?c`|Z1ih=Xz8heQyT;r^C#y328Ypqp`&KWb;pR1v~ zs*-SY<0zhiQZ^xhs`NNLo=h=4EvbH<8Na+EJWD{j;#XX1V(UX?#)dwn%&iNa*byAt zWxQfogt1ZQO{{0#1o@`un)0R=k24Vvu9V(&PYQaJatgOkSx&2^;30ICYpv<(SX3cF zTIr3VV2pFFXyOwN0CFShir&$ejvBaOc{J6s_b!)BAoyGDARx%u&bVmJwH2ahYw>x3 zBh(ebnnBIQOGiN2pn}|)X@ku=Ty`>y6wdYLTM@5kmcFIP=BV(x&gQ7DdD*? zokZqK9>O%y1a5^AMGat!tDc9(Sp*U z!ctPs1Z`}h;IAhyp5HEb!nTI?IWi^6nF)ESGvts7eQ|QjGPhEzPjM}ct3n?jGR^fW zNNE+&hzF`%6F!{o2`#ZNyDM^N%4ppWg`Wililr^mEMeGFfNJ_STM< zfWjC4snff&To3QN${g2Db4QIxJh;*f_1OYZXG4r+Io_4DCMoV%udCqExHOWoWwX=* z%d!`mhxlU+Esatq8w{wX*#b$$b-OI_@&85Ko5wYEbpPYAts7LS$RZ$WtL$4<_O+sb z0SP8RfUs2&F+@Pt01@#~abZ;;pg=$jAtVrxC4>+HiUI{>3jri-vhN9dfUx}1r`qRZ zZJ+k@`+k3~U;apP@7z0gX70?KbKd7YbL{P>AGE2jroqy3EFs*yS?*v>xcdZaEuIG~ zN}Oevlxsq}%H2l?#AEQD=;zb0+PxN0I`VJ6^Yy#MyxcjGp>hB0!1ZOAh6)se^2n_o zB4+M=UmhpwdS1KvK)eqv>BteOH?{pSWb_ghPEjXxgktXDL1?C`49FFkcGw-r9s-ia zX&NVnlc+pB+IoNgfJ+}7J?l-TGG9_7M&*c}#g%=z;!n%)hxllmUAsAk$@2Qjh!MW81H|P;+OMsF7^I89H0E4ezbfV z#uM#Wia}R0iM_Q`Tdb2AeJXIO++m(2aIiGVMVM`vHfZCQJqk9cL(eRa#)UjlP^hO~ zRXY@`D>i4J=dO=OA$&Xfh(-M~`DGqM-8(NBD2%%e8N{$+%&w4$p-BmL!cIg+!iv(_ z)gsrf-Z0-nM>}|FsEmP`MIu3F28z>oW}Q2*n=_SeXVYfAN#0CcEMrM0Q(9ojNj6=b zIQ7bWqevy`dp%L4C#h(ZGN{KuH}Vn57tCT^^D( z!x}~9Yoa>sc%llHgX6gdb=@|&D)WPr6$wUY{F2_KtGx4I5mCNYH2H$kwUcher^N&-fpkC3s(cMLlDH8}0k4U}|Ebz3+ zE7iQ0hl+eFhIC&F-#ymCj4$EoQK%#Viwia$kd$02j+SblO;oLxGtk6BAv=Do%h-^- z|3cZ4bYLZT{#Jycpta5W&C?cC41M!17Irwz*`Xrr1cK2`7tYfnutq(OR$DO_Nv|5; zYp1$Qx3uQH_6Tw{o4a*=)9m8|xumlR`YU3`$Ko)Mz$2#gVbxzJGn>8IZGA`VS z=?**kdaZa_I=OA*XsQvoGqXPK(q+SIYwMy9mDwL3_36p{>Y)S=ESm8Pd*+XY4b1U# zdv70?Vt6a!^6$+FJ&`y?OfIyLxJ|g*!BXcm7MB6`n*Rg<{PDRE3ctkO^#8w#{9x(O zVYyYu_i-x&8@TWpp*c$7(b=js^KHO;S=QMUjXtXbOQRo}XSNVwdEu<|?(jAKLPS7C z3$3cU|800FUk~KV&Y#!xyaK|6?0QsC5bW6)^Mx(?TScE{y{SN%6MV?SzkS!if;}q< zgG(+y&^%eC5z1g<7r1ae%Q>8r*Km7;&VgDVr6{vH% zwIZ8H6c@U6Ak{nzS(J9A3Tm+r7-*>;Ai9#_LF^(xbj7gdrxN1v`#@5KmP-!L`^9TY z{VB`t;l^kwvcQw9o_mxZvWxpFl2$l&v@~~0bm_INan?284WeXvi(q3L$CNBfARj}5=y!Gj6r*MpK_nlzE8x6Ms zvrmRgb|u#}*}m<9#6v6LJxO2(sT2=ko^>%98!H2Abx3%7xj0$Da3U+!=LN6`t=cG1 z^fD6~^CCjK1K#ZT#6Otbk3b=@ea)v5Y9Yr^zm1M;8gMejzT2c$MP_CB^y>gvsaQs3 zT53xesk%Fill;RML&e&TKUR`9|GvwftI~Nqs_YHV+w#<_ zYd`$;z}{f9ZGaoJTq!1YvaV)bs)Sh;qedv)Q@OI0W!69Kp|=evJW|Q?-6~!=UdPy! zUK$-dx*45eGT*Z0JAdom>&3$0&6VLzk413v$MJ6|me&40?EB(wQwu1MG3;%*AXmNQ zBWk+Nhz%=f&AU+AxtyP`&`QQZ$f5Dz2wh*l#0;uTQ&IiLk&fA4JF|i@FC~C#@8EKr z?3-gs${5jUX@m4brE6N2HgT#x+8mvR)rt1(v1E?V<^D#iGhMOX7A>v#Wy_=14B1TL zWLMH@KVL94Q_->{0l~6JfkbTs9-*4PT4e_P&}doIc6oA2)Cc_*qoTSHod$3D&Wq?r zkdcw2i9S`?>_Rv0KZ{s#G{=%f)i=+2cr7(aX5)2?^HeYj=7&vj@-`#AKdzY=FbnTR zK5qXmG&hVxQ)#&qQpJ51S2#syxZKo>E8ekKN~ZMK;^AEy!$ePC46vpR6Q&xW7#5P# zcnj5dWMo}6xH-rtXd2#AMZ!%<*7RxZ$^q$G?rHU*5*dW@0s5s%FK>MNFL0tixWsiK zXp5#7+!K3M$i&8V!C`Y#=($kFt=0hPgI6lwt4m*9uN5f`T>#;3o()Yykl5Y^jjF6j@?7@BZ*_qKAO^a4lF|2)AJv@xKb!ivD zaVkk9(HT}1h%*$@cen1dLg`nT+E1gIl>3a_H3KJ#j{{y#YBi5KLMc+12qkOhm5sN| z1RlM<-u$41lB(fegr4P;-sQXu$c0^Y(nh5v^LmQvf~IfAMVDYSInc_8>z&Lg-JNgQ0g5Y$N)@j=BS;eUC`LjQV&owm-Ay_bu$-!d zuv$p%5jRe>br|!q#c7GQRf8pB6YBn7`K&@tCp@Zom~ zFHH`x5|f>25#gd>Az%(pguQc@Fd@sAv|DPXs5cgSmLe|PQ%5MJ@-tTwHO_N(7~9v8 zt0CS(j2 zs?Ngao$+B7FfKJEUC6lqp@nE%v?}mK`srwQ%Db_EeO!Ru3gl zI6HSYjKw%WFp}1O$+Df?3zvqo{hQo>&>p%Zi={4X@(M)X)mZA6J%)hj%p7x&I(DbR za9$Cs?zLZt+!DzU32$bVC{OeZhvp-Z))Ptlbjz)FiTX^qu$)_K6g5P}H5B=g0z_rx z>xj`WJMD^^Yp#jT1O*L!M=K`5vS*oYAV`zBzKpffNhhY?+}xT}^by&6Zc;RtjidW- zQb-%8d#$@b-ke7|nbS$-=4kY+Lq{MsuEJ8DDqCfn@9IjZ@90=oK_JxB_Xz}CAM}v` zA<08yOyOo5JJn^5OhC-{Q|ewNyv9^}oAN$1U7?Bi1Tv}m6qq0Eqk`0boZ%6qP6}#R zUvqV6=o}7Z_0>0pjmlyb%(|CK29_HcenRL^-TJ zTaMHu2lPmrHnTJf3m~MuZTCjy31`lX>S(SJpN#a3W&DCyoR2Xv@2*;$c-PBFBJ2mq zo>sWAqs-8cPZ*f+if6$>ca9KT+IY>+f`=+a2Xq7BSSJ0f&{OqR1sGK1hSg|xKhafPi(Af0y<$I-*M=(@wtptNWC z1+pEU;hRZy_Wv>1zLIXT;c`)_1gHUm*}$)Ic1#JhL9dfk*9Plrxhmte?JN*0PG z>dOvLlDIR7WEbt9K4r1Dgr4r$qH}7BMMw8n@p8TJOgsd6s+?pxR89hUwV(oJ_6!-= z=`UOfYfeSMk)X~M76}(plIZPLJvEo=S1Vq#pg*Olu{2F}bgn&+d#LtS&G}~4Q;~_V zL`O^Y_7PsgJnl@rCyi#Prp}#jxqtK2NpQr%R=wAARyh*p9;zj_j)t8sFfB$~Y;u8T zA7;J4=*yGAOBRPLId0$Zb%{=03~UZ6z873L2*xRuQGtqw_i7kQx@NXWRpFA`pS+Pw zRBAD;!UmrG4!74w!Km#n*NE%NMMbTCt12m;)sax%&()Kqto#srT&Ngzo;?&L?!Ih} z)Gfuh4E5hrgfm`D^>xsq58`*dM9a;BP=(cf!S)VTRX$cMiR-2BVDLvy)fc1D0#L4M z^8S64XMQ0eUR=X4kZd}WYN5#t_@!|Gl;X4Qa5Oy35mJ%9k%m(Z%uYYqm}pmrufMgc zIzO(O6w+Y_>U0=Iuv^F@d8Ajc)3Yb!r+q6(4xVDoEB)V*Bu}B?Ce-SS1uE)<`>GITwlNdeQI;;1aj*YwQyz{!*Txq`P^x17d zA7XYJfFU8qy*7Sv`P|Y>_=!}Kq3K_5oZ6w*-EUQ#$E1{*~54QoYiumKM z@Z+<^d@Yh*7DDK4&)d;NNcYT02Z!48M1vLMRvU70Njj%f-vcdVEF!jYV1`M= zxCrsFPI|vp@t(Ytw%^(O%Z6DM4t%)??!Wz4c_S!4KvoA$H`HkXCcOYaT6K zZ=qN5vJ(}Z(h(D5pgP%_>94fs49$}t>(BZwV#&2%6grx|)IPPDxPIfO``VI`T?FdF zj74gT%4S{-IK+eZL`KiEqZA6s#XB$y?H=h-t5t~v>bgWT(zgZgvY?95hTMtJHvP`| zxahsOpQ`qh^=~+w_&LGnk--bc&Z<_jo|L3tE=rfFWSS`EuIp;~lRC!a_9(+~M$DYaB!8Nmd+N zXNSwD`lH=d9VX{CzU>Od-785=6_nN`RUqteuD6i-K)Ib@wes0s~_0{*U5qVX}^`j}-cMUX!(I}pT76{`BzBe`sI~aWhCo)vnV3A01m5YAn zQ+k!2r|3Ok&-X~}=~J}98LYJ>if|c;cIOt_-%_=r{ePTZkGYRiwDr24PnxdAD5~13 zVxg)clR2v9X)eAZiy7f+0kv(OVk;Vhk|Of9l}V|_JscbFVW@!qp7xwHH*{5lZ!;GZ zJn@U|1#@N;HwEc%gW^5QE1o&onQjq>ymUYys3XXHh|;HEJk`&RknxqU3iVAxXlA9Q zg+sKforQW-GBBN~UZKl^0wTE`m_5Yyv@1ljKz5bKVP--z(hg;o>SbD;)ZzqRR?f$} zkk3N{v4MwbKmsow6u$8}l(Rsg4kw&LlTb>|kK1u5ALB*wjw#|rTC}3sk6Bo{=reDv zz2or{)V#b=NFbpU8yMnF9nG!gD0f|&NlRjf-;uo^2LTn)siiM%h`K7hRR5gv8u?nQ zWaWxW?*1oPlL@3;(`r%;DX#|+wm#76kwmTcsgQ6SueUf_6%l{z zQJA$YrK}{VQ_R&L3!(HY;_V*M_0{7?3Po_rsy?ZWSI&q@o{DxMcPY^-xfxRPC-1z_by$!7#V!gjKe%TvUp!qPTAaBL8U1+DaT-+Bc&rupi(r~Nv^h<`+1 zt&E9yR0>AnHX)kXT|x@mES>oh=u_sSsaNq|z^Na_D3*^4ANj3-vbT4Bo%dOl06Xkg zu=exmHU@hY7=db+lTIJC+MQcsIgsoT;_&=!sRD9wX@%YHZiRs-6DHTTgehgW}85p?s`GG}{@8r9Sw%{$#b3Si|S z#YBvr6YXwYdoAL6J9NCKe_s?zDK|x9+Ofwj*ZdA7S2v&+Yl#}^GO1tIXijyrtQ}@QdwE#MS^65g9A)YF2N2V^sFIvR1Tm-U*FdDalah_Dth3 z=y!L6I)<|$_+4ESRTYY)MuSOw2Tx&XK@ud~Q9dw0m#rd?KecVAaM+7?c3XJ)OE@}u zR!Av3fP<9(~fcDS{A*+Rt`o#Pg<8qR%u2^ z+)O_>0<(W`l|@c*T&4J!Qu}K|M}UQH9xhvB>MED2Y_sQBkwE3ro{@NG&Xau0nRhZS zx+L5Yq#e{7vnRheJ{RPzG&C%sj9fZV0B*kNvQS& zW*4O(5-j~K`C&ro+0i*><|U+tsm>V!>Ts8?4*Mx#Yf4br4(FO|rTRBBMYWI;0s>I8c>+&V*i0 za7pAI%t-|&I59X5Ttipm2`uO&Zcp8jcaUoKh#4fP{;0;}k!Nr9ujE|J8Nw!6=B=`4 ze;H1HNPNR81gdRF_jB&7rZtmaFzzMI_Mu>p+=9{|aZMakAEQVW%w!GsLp@|bJ&S!@ z+(dSqe*fhe^Jq@saZGhb-D^4~M5bZph3GZkRfm_M8)FJ)?Zxo9x90|!86`>Uk zoIQDc9ci|Nb_&}yjcN<3`Vp{e^<(A#%(DD<(oVj`*=k)gr)wCu0pk1u=x_77);|?+ z%^CWkEj}SJ0a#%|78y9vW3HrM)Mn~`F)E=q_7P1fx#SZ8qtsIL@jYh z#Cp%B|A))Oa}U3vuRMTsvdEsuB&6qEaDh}v11QQzPzR`y?hu909&b8AoH&iWn*cSS?9W_%uL4%I1ekU5=w7; zS}r6IIi+6s%*V2BxL(=6_S7#!(DWFco>~x_p>_HWK@e!}V{fjOs>U_zqCOPc9Wqa_8P0o`HIr}hm7NPE)AD^U%lbnbonqUeGA?6D zXch)m2EUVX7=JLpj1(ConmO#D<=)=$Y~pYF?q|t6)=bx6eLgae-bjb_+0E8>u)OlI z3RI;-&=$*H>|>G-sAO1y;A5g*C|f>Et9l`q7syItYWrsqFD-bQYrD++e80rGU}wWK-L+1(8n%t~K-so81^mSWFb7YFiJCSnlCSW*t7|J`_?g>XGUb|R^_k|=5 zT7>xZ!*R*!=S&Pj8;J4gOTuh|c*|tMLzYe_dI^n7n?9p|RrGrrdurf~(W6*NoSBM) zX`MmDt4VEU0P!MxGlO%`r7?sFPI#NFNpCEB@*}ME1IOHw+9K884tMK~9=#uCbmrRR z&o}s6)mmtEck|u?c9ef?fM3;hs{h`%WfVU>x>@rUGXfOxps3xU&jQaU`&bu7pw(Lw#V!~mYEG>#&!p4&0hfEQEL z5Xnjm(a!U;kPdx%1m}V9_43WKXO@;>VH#K{xlR->o)`~~tPPv2bUuIE_+?4b=-6Wa zVv7MMB)0iPM?VS9)g$V9r_IVBBU~T_Zykx|jxX&Ub3;rP{ca|oZqCek?>wogIbT#B z(Sh6l4MH!c%z|4FvV3zt!=dp=mrQKg`2Me|+o9wIWIvbHyV$5)+blnIZ8oe|eLXm~pt5qiMQ<`t`LSllEWF#9Q2?(k%fY@T)%boG9CK+HRnB)>m%MFV z&A^A5AjT7J8X>(0%M^WMKls4K=L<=8QD$*oE(usz(#mwAqgBG2H$$j|YCY@9K~7k5a(O4>cC(@-#>9;54>MFvX)r<78~N~T?G(v-cXotlM&9vlH~ z0~Cgg_))7gjU1Q=qPb=#VX>c}r6t(;ndyHCjq!}2dB3F>OD_UB^ynCmikUbikc zI?I?htmI9Vx7GE_CORd!61&t2n5;KDq+CM;(^62pDsO1${Wt==8!47gmf1?_*2%l+ zwr(-e^|tliAXp3Jn_?vqWqDX*~7uNE+2aL;PCzAFbG@*E(a^s!g| z);IsbxADqv-h1Hl(5zwV6B{guRQd$e+wmo~(FixZ9!D75O1pXBlLGnC{SLXdFKexk zIkyb}8SaVroBldc{j1@-m-p}jwSQH>q<}{6p@~5c#XkB3N17?GK>H9NfF=uQE?7*SUlTP7M|qdf=m1TR)@E?3c5j5 ztQtLMPVL9j#ZDEF^`~hn48=`jRqkb>Lw-+K^`rd35Ei8YTDh<8a`pMD&2-N<$ zygXX^r?X1KNxz`TlZlDQjN2K1KEb^8&csf^f}Cq|Nx<;zQV`!x*M0)eKi4ntIj?AQ>kCpsitJBFzqW&vs}BL@=H zmOAU3+=h=bTum!a6zl^ly?^6bkaBC+WBuwIIjMN;oB@@^Vh2QU*0ZeLrpXhe&MLr9+LO`!$?oII)-R`^iR$kiba<)042mUcgSj zi+^a2-w(eP{%0P=J(5P_lG}han{7b02N}pbEjaPoi5iTMJBqd`%k5D5H(FXGHE&a&eQ$D zMFplq4|+KvZOOX+ob1g#am77EOb+GT`k=R?wuzFtGM8+7{CH2 zS8POw{x_+%@9TWt`4>3@_NJ%$@5b2eMGZf_l=kRFjgpN!5gZN8Ljrax_BLD%9PuS=G(q;T-LL@foPbGt}=fwg8$*q`cr#xVEL&l^Fxmvhd^**4&erDyaF$1l8 zqYPet(gGu2)fs*yOVohim*kZ*`6Rg#qdu@yWVp3niVHDV(=m6Nw$yh^mM@62ir?6m zHC3JF)E%FLqiOM;utQ@I?-^JHogPP>9N^-+toC@T-n3h!4J)~k%UIDvSuc`=orR4+ zp=7>Ue4PxEjC=(+cmDTY^oKt?@F7(`TK;G}suHm;gS<#YJ^>W06Z z3@+@R-4%gT3>du89&kBX7tALW8Jt%{K}MB(!0pG?!gS$PlUKqvm%YpvPz!#E)XtRP zI#saikqnttDPTv0Hnms=Y!T$cJ>I)4*;R-$h4`12`d>^Ke+I;#$e?O(I zJwdJ=A!xI&*vhx(dSzKtH2l7(*(ttH>iFL(XMnH2`h`Dxe^MJ9YE)s>HRfD?gjFcP z!lO9Bu5#S_+$XQuN1ScXMaS+p@#+SD=WTOu1!$Os{*S(RM3I4q>5<{pS)oHf^;_+D zfr}UMd#VMqF28&-ab)0Mu|)dpQ@|04|8dKge|JZg5ISRLVK)dz%Hl1LmP}SBiYQe7 zcxUoZ-igrNln-vi0@PK&?)yLeeruzTH_;Af@ODa;d8JF8)*054-1_zwxRM_SvHtRn zI#;AE&o8(gv6|Lmp=c8u=ZoJ4$R_Z7wiv2Y>cf&3qkU&;lvUYgq+cPHe3E7tII$NU zt>lr-2J4sBfV1!+Sx&DlvS*md%c4-;>Cwjo(L|DeF2N@Sf;r5+}#GnCe%WuFoQ&Fth5(+I&xq^JT&gp#Z>mf{dHVyo%c{31I21eMI@Z^jo7 z#3JwAAw0|`S(z#gD&LY9e>L(;)I~jMV=8B z@7@as{c1C^a6rD%h#6f%3|%{WwZ!~Uc~BeQY>a_xWbk>H5}izLfdx?>-ul`9jWs@`BEt40n`uhU$XYBu`{(Vil78qcW;$2EGFhx2p%RzAa4<{x~O;;)B-x_VL zUqJ<$cKMJcnHfh|@E%3}TCz1|++y9V>=r|wsMUEOn(}kW0=pQ`Uyg(T zD|@#`g4gI1P2=+>#dPh;4GBfZu|&+<%M)3>+?Snu6u=mEmVX(nY*nkc-~`n<(U`Q~ zNYJqJR7OCh>DhgrPYO`b7hrSS!!MG994D@-WPm2N;&bDk_xXgXc8vi51E00c4vX9S zUN7=xw>W<;J7XpOYGU1JUa#sHz*_gm-!A-94MysAb6TH{!VkJ7D^EIPN(AHj_Wdwy zmD*omvGL+Ax1cj_IYo3B%2wrHrR%pP{9>B6VZY%zbNrfJdQ7U}J1Nx@IilI&PN&T(05KL%~sA)WA?1}$Q)zo5$D>JyGvUQ1-;yfxTqRLUa2-6wz>q2R)nOE+{u8q$i1lHne_ zw_Qd3fg)GtWts~7*e5QCm1yfR61@Fuxg{)n?s1(<8CI<@UHiitL=>ZGCFs^X0N~AU zupP$(krrnN-g%1Vp>M@D%{PyG$tHmB!CHj%7v>SGn$1ml5n(Zdp6i^ps^)o z)y+o=J@C0^!dTtsdaNbj^2jJX-Wm%+ulSm8pl<`__%_tX&*$nE>Z=ufxW?5GJV@ku zCg{LD@$)s8j<*72u0IBR{ZR~ly77>bvo+4wxF52)RT=F22KC+{TRQ6mQrOGkckg~v`lsHj?`{9%m^y(6+c-#hNii;nJxOm) z^}U%z3NO9>3*fZYhyUpIS*->T-`-z{U_7+vJl@-L}md zm9(?l&?|>RJD1sEN=V(KvOPr%_zgx{M&X zS+^Z8XdZ0Fk#G7%$k&sWccmiYxn+4sDHu$$1n2qe*6QI(CEWY-XBzjX&CJ$^@jx!a z*2R=9;qtXJI{bMcD6AG?K@?B4b%edlwdB?;ao+GLgMwBTrLowOa?BVu%Soq;M2GvD zf-$-m(~v2BqlZl{X|Chvb%e-$8LjFxgtVP0r6|*c?Q&xle)$%2u)O~Y{eh@;hQ7t# zEIRILWkmEP(q1FZy27BYGX!TVP{ObxuZ~Yv#J0Cb2=XG$vE`+iHIy4k>{-wWu|>{E z7HhIebq4?LbH;g{Z;_*g)lU^@C6-Z0yV~JPfoCcdOgw~JD)qWuK?`nhGJUrxLp7;! z(k5?NFPpH*d!*2bKRo70T8QQ2d$AYB6g}&^i>a}UQx$Hg`N4tpCg;fX)FNa;MF&=3 zop?7wS238E50&x?&*Cow7h0$?Ey?TkkOz)tclx1_r=49cSpUYfeNxLyAA0)&8-fqw zrj{RX8hE0OR(;0it+h=j(zW{sz)8c3 zzpU!1&3I3Z<75pVB{`^FA%YKC1aTKsh$-nA1+$piXSs0hvV!%U7(G2$gNBmXG9_JX z(aNx)PA$aUVWxwg9wlwqT;JP)4XG`;mrD$sDSKiS1Ul7_EZ0_Pwl5D+3SGx#le4WO zY8j??i)c1-A~`Mj8~zP`h-A5k70V;2Zm%4M!ldqIekN!vrbgE&Bv-J03t

OVZ7kJq2==X*=~|B-$4AH?KKZwX*eKG^!1ThG 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 X$Jo)?-4SAj$IZo$$H*wH0>b-0M(u;N literal 0 HcmV?d00001 From f8d502a1767dac4480d054ee27c8465e8cd60378 Mon Sep 17 00:00:00 2001 From: Sungwoo Park Date: Fri, 18 Mar 2016 14:18:39 -0400 Subject: [PATCH 75/76] Changed the top title of README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e8553f7..7d64d1d 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# InteractiveProgramming +# Motherload: Cabbage Rendition @authors: Sung Park, Willem Thorbecke *Motherload: Cabbage Rendition* is a recreation of Motherload using pygame. This project was created as a part of Olin College Software Design course for Spring 2016. From 077ecd8cb5c27e7078c072c06e0781f7e8d7e9c6 Mon Sep 17 00:00:00 2001 From: "willem.thorbecke@students.olin.edu" Date: Tue, 19 Apr 2016 15:22:18 -0400 Subject: [PATCH 76/76] new classes --- motherload.py | 371 ++++++++++++++++++++++++++------------------------ 1 file changed, 194 insertions(+), 177 deletions(-) diff --git a/motherload.py b/motherload.py index 21f397e..3d8498f 100644 --- a/motherload.py +++ b/motherload.py @@ -15,6 +15,7 @@ def __init__(self, model, screen): and screen. """ self.model = model self.screen = screen + self.running = True def draw(self): @@ -35,7 +36,7 @@ def draw(self): #if there are bricks surrounding the current block, then continue if not (left == 0 or top == 0 or top == len(self.model.temp_world) -1 or left == len(self.model.temp_world[0])-1) and pygame.sprite.collide_rect(brick,self.model.vehicle): - #define the 8 surrounding bricks + #define the 8 surrounding bricks brick_left = self.model.temp_world[top][left-1] brick_top_left = self.model.temp_world[top-1][left-1] brick_top_right = self.model.temp_world[top-1][left+1] @@ -141,7 +142,7 @@ def draw(self): elif brick.color == "black" and not b and not bl and not br: self.model.can_move_down = True - #checks if there are bricks touching to the left and bottom, if so turn on drilling + #checks if there are bricks touching to the left and bottom, if so turn on drilling if l and bl: if brick_left.color == "black": self.model.vehicle.can_move_left = True @@ -177,7 +178,7 @@ def draw(self): r = pygame.Rect(brick.left, brick.top, brick.width, brick.height) - #checks if player has mined a mineral, if so increments the mineral count + #checks if player has mined a mineral, if so increments the mineral count if not (top == 0 or top ==1): if math.fabs(brick.left - self.model.vehicle.left) < 20 and math.fabs(self.model.vehicle.top - brick.top)<20: #checks if the vehicle overlaps a block, if so change block to black (empty) if brick.brick_type == "ruby": @@ -284,195 +285,211 @@ def draw(self): +class KeyboardController(object): + def __init__(self, model,view): + self.model = model + self.view = view + + def handle_event(self): + """ + handles any keyboard input + """ + + pygame.init() + + while self.view.running: + for event in pygame.event.get(): + if event.type == QUIT: + self.view.running = False + + if model.fuel < 0: + self.view.running = False + + + #checks if the world should enlarge + if self.model.temp_world[-1][0].top >= self.model.FAR_BOTTOM and self.model.temp_world[-1][0].top < self.model.FAR_BOTTOM + 40: + mistake = self.model.FAR_BOTTOM - self.model.temp_world[-1][0].top + self.model.world_enlarger("down") + + + #checks for key press + keys = pygame.key.get_pressed() + + + if keys[pygame.K_UP] and self.model.vehicle.can_move_up: + + for top in range(len(self.model.temp_world)): + for left in range(len(self.model.temp_world[top])): + brick = self.model.temp_world[top][left] + brick.top -= self.model.vehicle.speed_y + brick.rect.y = brick.top + + self.model.fuel_station.top -= self.model.vehicle.speed_y + self.model.fuel_station.rect.y = self.model.fuel_station.top + self.model.shop.top -= self.model.vehicle.speed_y + self.model.shop.rect.y = self.model.shop.top + self.model.workshop.top -= self.model.vehicle.speed_y + self.model.workshop.rect.y = self.model.workshop.top + + self.model.vehicle.speed_y = self.model.vehicle.speed_y + self.model.vehicle.thruster; + + if self.model.vehicle.speed_y > 1: + self.model.vehicle.speed_y = 0 + elif self.model.vehicle.speed_y > 10: + self.model.vehicle.speed_y = 10 + elif keys[pygame.K_UP] and not model.vehicle.can_move_up: + self.model.vehicle.speed_y = 0 + + + + if keys[pygame.K_LEFT] and not self.model.vehicle.can_drill_left and not self.model.vehicle.can_move_left: + pass + elif keys[pygame.K_LEFT] and self.model.vehicle.can_drill_left: + speed_x = .7 + #loops through the game model and moves all the blocks appropriately based off of key press + for top in range(len(self.model.temp_world)): + for left in range(len(self.model.temp_world[top])): + brick = self.model.temp_world[top][left] + brick.left += self.model.vehicle.speed_x + brick.rect.x = brick.left + #moves all game objects appropriately bassed off of key presses + self.model.fuel_station.left += self.model.vehicle.speed_x + self.model.fuel_station.rect.x = self.model.fuel_station.left + self.model.shop.left += self.model.vehicle.speed_x + self.model.shop.rect.x = self.model.shop.left + self.model.workshop.left += self.model.vehicle.speed_x + self.model.workshop.rect.x = self.model.workshop.left + + elif keys[pygame.K_LEFT] and self.model.vehicle.can_move_left: + speed_x = 2 + for top in range(len(self.model.temp_world)): + for left in range(len(self.model.temp_world[top])): + brick = self.model.temp_world[top][left] + brick.left += self.model.vehicle.speed_x + brick.rect.x = brick.left + self.model.fuel_station.left += self.model.vehicle.speed_x + self.model.fuel_station.rect.x = self.model.fuel_station.left + self.model.shop.left += self.model.vehicle.speed_x + self.model.shop.rect.x = self.model.shop.left + self.model.workshop.left += self.model.vehicle.speed_x + self.model.workshop.rect.x = self.model.workshop.left + + self.model.vehicle.speed_x = self.model.vehicle.speed_x + self.model.vehicle.thruster_x; + + if self.model.vehicle.speed_x > 1: + self.model.vehicle.speed_x = 0 + elif self.model.vehicle.speed_x > 10: + self.model.vehicle.speed_x = 10 + + if keys[pygame.K_RIGHT] and self.model.vehicle.can_drill_right: + + speed_x = .7 + for top in range(len(self.model.temp_world)): + for left in range(len(self.model.temp_world[top])): + brick = self.model.temp_world[top][left] + brick.left -= self.model.vehicle.speed_x + brick.rect.x = brick.left + self.model.fuel_station.left -= self.model.vehicle.speed_x + self.model.fuel_station.rect.x = self.model.fuel_station.left + self.model.shop.left -= self.model.vehicle.speed_x + self.model.shop.rect.x = self.model.shop.left + self.model.workshop.left -= self.model.vehicle.speed_x + self.model.workshop.rect.x = self.model.workshop.left + + elif keys[pygame.K_RIGHT] and self.model.vehicle.can_move_right: + speed_x = 2 + for top in range(len(self.model.temp_world)): + for left in range(len(self.model.temp_world[top])): + brick = self.model.temp_world[top][left] + brick.left -= self.model.vehicle.speed_x + brick.rect.x = brick.left + + self.model.fuel_station.left -= self.model.vehicle.speed_x + self.model.fuel_station.rect.x = self.model.fuel_station.left + self.model.shop.left -= self.model.vehicle.speed_x + self.model.shop.rect.x = self.model.shop.left + self.model.workshop.left -= self.model.vehicle.speed_x + self.model.workshop.rect.x = self.model.workshop.left + + self.model.vehicle.speed_x = self.model.vehicle.speed_x + self.model.vehicle.thruster_x; + + if self.model.vehicle.speed_x > 1: + self.model.vehicle.speed_x = 0 + elif self.model.vehicle.speed_x > 10: + self.model.vehicle.speed_x = 10 + + + if keys[pygame.K_DOWN] and not self.model.can_move_down and self.model.vehicle.can_drill_down: + + self.model.vehicle.speed_y = .7 + for top in range(len(self.model.temp_world)): + for left in range(len(self.model.temp_world[top])): + brick = self.model.temp_world[top][left] + brick.top -= self.model.vehicle.speed_y + brick.rect.y = brick.top + self.model.fuel_station.top -= self.model.vehicle.speed_y + self.model.fuel_station.rect.y = self.model.fuel_station.top + self.model.shop.top -= self.model.vehicle.speed_y + self.model.shop.rect.y = self.model.shop.top + self.model.workshop.top -= self.model.vehicle.speed_y + self.model.workshop.rect.y = self.model.workshop.top + + + elif self.model.can_move_down and not keys[pygame.K_UP]: + for top in range(len(self.model.temp_world)): + for left in range(len(self.model.temp_world[top])): + brick = self.model.temp_world[top][left] + brick.top -= self.model.vehicle.speed_y + brick.rect.y = brick.top + + + self.model.fuel_station.top -= self.model.vehicle.speed_y + self.model.fuel_station.rect.y = self.model.fuel_station.top + self.model.shop.top -= self.model.vehicle.speed_y + self.model.shop.rect.y = self.model.shop.top + self.model.workshop.top -= self.model.vehicle.speed_y + self.model.workshop.rect.y = self.model.workshop.top + self.model.vehicle.speed_y = self.model.vehicle.speed_y + self.model.vehicle.gravity + if self.model.vehicle.speed_y > 12: + self.model.vehicle.speed_y -=.5 -clock = pygame.time.Clock() + + if not self.model.can_move_down and event.type != KEYDOWN: + self.model.vehicle.speed_y = 0 + if not self.model.vehicle.can_drill_left and not self.model.vehicle.can_drill_right and event.type != KEYDOWN: + self.model.vehicle.speed_x = 0 + + + + #self.view.draw() + self.model.fuel -= 1 #decrease fuel value every frame + self.view.draw() + return + + + +#clock = pygame.time.Clock() if __name__ == '__main__': - #predefines speed and thurster + gravity values - #defines model and view class as objects - speed_y = 0; - speed_x=0; - gravity = 0.25; - thruster = -0.05 - thruster_x = .025 + pygame.init() size = (640, 480) screen = pygame.display.set_mode(size) model = game_model.BrickModel() view = GameViewer(model, screen) + controller = KeyboardController(model,view) + controller.handle_event() - running = True - #for loop that runs the game - while running: - - for event in pygame.event.get(): - if event.type == QUIT: - running = False - - if model.fuel < 0: - running = False - - #checks if the world should enlarge - if model.temp_world[-1][0].top >= model.FAR_BOTTOM and model.temp_world[-1][0].top < model.FAR_BOTTOM + 40: - mistake = model.FAR_BOTTOM - model.temp_world[-1][0].top - model.world_enlarger("down") - - #checks for key press - keys = pygame.key.get_pressed() - - - if keys[pygame.K_UP] and model.vehicle.can_move_up: - - for top in range(len(model.temp_world)): - for left in range(len(model.temp_world[top])): - brick = model.temp_world[top][left] - brick.top -= speed_y - brick.rect.y = brick.top - model.fuel_station.top -= speed_y - model.fuel_station.rect.y = model.fuel_station.top - model.shop.top -= speed_y - model.shop.rect.y = model.shop.top - model.workshop.top -= speed_y - model.workshop.rect.y = model.workshop.top - - speed_y = speed_y + thruster; - - if speed_y > 1: - speed_y = 0 - elif speed_y > 10: - speed_y = 10 - elif keys[pygame.K_UP] and not model.vehicle.can_move_up: - speed_y = 0 - - - if keys[pygame.K_LEFT] and not model.vehicle.can_drill_left and not model.vehicle.can_move_left: - pass - elif keys[pygame.K_LEFT] and model.vehicle.can_drill_left: - speed_x = .7 - #loops through the game model and moves all the blocks appropriately based off of key press - for top in range(len(model.temp_world)): - for left in range(len(model.temp_world[top])): - brick = model.temp_world[top][left] - brick.left += speed_x - brick.rect.x = brick.left - #moves all game objects appropriately bassed off of key presses - model.fuel_station.left += speed_x - model.fuel_station.rect.x = model.fuel_station.left - model.shop.left += speed_x - model.shop.rect.x = model.shop.left - model.workshop.left += speed_x - model.workshop.rect.x = model.workshop.left - - elif keys[pygame.K_LEFT] and model.vehicle.can_move_left: - speed_x = 2 - for top in range(len(model.temp_world)): - for left in range(len(model.temp_world[top])): - brick = model.temp_world[top][left] - brick.left += speed_x - brick.rect.x = brick.left - model.fuel_station.left += speed_x - model.fuel_station.rect.x = model.fuel_station.left - model.shop.left += speed_x - model.shop.rect.x = model.shop.left - model.workshop.left += speed_x - model.workshop.rect.x = model.workshop.left - - speed_x = speed_x + thruster_x; - - if speed_x > 1: - speed_x = 0 - elif speed_x > 10: - speed_x = 10 - - if keys[pygame.K_RIGHT] and model.vehicle.can_drill_right: - - speed_x = .7 - for top in range(len(model.temp_world)): - for left in range(len(model.temp_world[top])): - brick = model.temp_world[top][left] - brick.left -= speed_x - brick.rect.x = brick.left - model.fuel_station.left -= speed_x - model.fuel_station.rect.x = model.fuel_station.left - model.shop.left -= speed_x - model.shop.rect.x = model.shop.left - model.workshop.left -= speed_x - model.workshop.rect.x = model.workshop.left - - elif keys[pygame.K_RIGHT] and model.vehicle.can_move_right: - speed_x = 2 - for top in range(len(model.temp_world)): - for left in range(len(model.temp_world[top])): - brick = model.temp_world[top][left] - brick.left -= speed_x - brick.rect.x = brick.left - - model.fuel_station.left -= speed_x - model.fuel_station.rect.x = model.fuel_station.left - model.shop.left -= speed_x - model.shop.rect.x = model.shop.left - model.workshop.left -= speed_x - model.workshop.rect.x = model.workshop.left - - speed_x = speed_x + thruster_x; - - if speed_x > 1: - speed_x = 0 - elif speed_x > 10: - speed_x = 10 - - - elif keys[pygame.K_DOWN] and not model.can_move_down and model.vehicle.can_drill_down: - speed_y = .7 - for top in range(len(model.temp_world)): - for left in range(len(model.temp_world[top])): - brick = model.temp_world[top][left] - brick.top -= speed_y - brick.rect.y = brick.top - model.fuel_station.top -= speed_y - model.fuel_station.rect.y = model.fuel_station.top - model.shop.top -= speed_y - model.shop.rect.y = model.shop.top - model.workshop.top -= speed_y - model.workshop.rect.y = model.workshop.top - - - elif model.can_move_down and not keys[pygame.K_UP]: - for top in range(len(model.temp_world)): - for left in range(len(model.temp_world[top])): - brick = model.temp_world[top][left] - brick.top -= speed_y - brick.rect.y = brick.top - - - model.fuel_station.top -= speed_y - - model.fuel_station.rect.y = model.fuel_station.top - - model.shop.top -= speed_y - model.shop.rect.y = model.shop.top - - model.workshop.top -= speed_y - model.workshop.rect.y = model.workshop.top - - speed_y = speed_y + gravity - if speed_y > 12: - speed_y -=.5 - - - if not model.can_move_down and event.type != KEYDOWN: - speed_y = 0 - if not model.vehicle.can_drill_left and not model.vehicle.can_drill_right and event.type != KEYDOWN: - speed_x = 0 + + - model.fuel -= 1 #decrease fuel value every frame - view.draw() - + + \ No newline at end of file