def create_blocks(self): """ description: - Create the bricks for the player's current level using the LevelGenerator-Class. :return: nothing """ self.bricks, self.number_unbreakable_bricks = LevelGenerator().create_level(self.player.current_level)
def __init__(self, screenWidth, screenHeight, board1X, board1Y, board1Z, board2X, board2Y, board2Z, countersX, countersY, countersZ, timerX, timerY, timerZ, arcadeLevels, gameLevels): self.currentScene = "menu" self.arcadeLevels = arcadeLevels self.currentLevel = 0 self.gameLevels = gameLevels self.BackButton = Button(430, 40, 50, 110, "Back", "menu", 30) self.playerBoard = Board(board1X, board1Y, board1Z) self.refBoard = Board(board2X, board2Y, board2Z) self.MoveCounter = MoveCounter(countersX, countersY, countersZ) self.Timer = Timer(timerX, timerY, timerZ) # TODO: After updating the MoveCounter, add a second counter for the MAX moves (or target moves) self.LevelGenerator = LevelGenerator(board2X, board2Y, board2Z) self.mainMenu = MainMenu(screenWidth / 2, screenHeight / 2, 50, 50) self.levelSelectMenu = LevelSelect(screenWidth / 2, screenHeight / 2, 50, 50, self.gameLevels) self.levelCompleteMenu = LevelComplete(screenWidth / 2, screenHeight / 2, 50, 50) self.arcadeOverMenu = ArcadeOver(screenWidth / 2, screenHeight / 2, 50, 50) self.resetList = [ self.playerBoard, self.refBoard, self.MoveCounter, self.LevelGenerator ]
def __init__(self,main): self.main = main self.sounds = Sounds() self.loadBackground() self.levelGen = LevelGenerator() print "initializing levelnode" self.LevelNr = 0
class Brickbreaker: def __init__(self): """ description: - Create a new instance of the Brickbreaker class. - Initialize all attributes. """ self.clock_speed = DEFAULT_CLOCK_SPEED self.screen = pygame.display.set_mode((DISPLAY_WIDTH, DISPLAY_HEIGHT)) self.bricks = [] self.number_unbreakable_bricks = 0 self.paddle = Paddle() self.ball = Ball() self.present_specials = [] self.active_special = None self.spcl_text = None pygame.font.init() self.font = pygame.font.SysFont("Arial", 25) self.player = Player(current_level=1) def start_game(self): """ description: - Create new level. - Position the paddle to the middle of the screen. - Call method to choose starting angle. :return: nothing """ self.create_blocks() self.paddle.reset_position() self.reset_ball() def reset_ball(self): """ description: - Center the ball over paddle and give the player the opportunity to choose inital angle. - Loop: - Switch angles using custom set left and right keys. Selected angles is displayed. - Shoot ball using custom set key. :return: nothing """ if not (self.active_special is None): self.remove_special() dbi = DatabaseInteract() sets = dbi.get_settings() key_left = int(sets[2]) key_right = int(sets[4]) key_shoot = int(sets[9]) self.ball.center_over_paddle(self.paddle.get_center()) vector_indicator_start = (self.ball.form.centerx, self.ball.form.centery - 5) current_index = int(len(BOUNCE_OFF_VECTORS)/2) - 1 clock = pygame.time.Clock() vector_selected = False while not vector_selected: clock.tick(60) self.draw_all() self.draw_start_text() currently_selected_vector = BOUNCE_OFF_VECTORS[current_index] events = pygame.event.get() for event in events: if event.type == QUIT: os._exit(1) if event.type == pygame.KEYDOWN: if event.key == key_left: if current_index > 0: current_index -= 1 elif event.key == key_right: if current_index < len(BOUNCE_OFF_VECTORS) - 1: current_index += 1 elif event.key == key_shoot: self.ball.vector = currently_selected_vector vector_selected = True break elif event.key == pygame.K_ESCAPE: return GameState.TITLE vector_indicator_end = (vector_indicator_start[0] + 10 * currently_selected_vector[0], vector_indicator_start[1] + 10 * currently_selected_vector[1]) pygame.draw.line(self.screen, WHITE, vector_indicator_start, vector_indicator_end, 3) pygame.display.flip() def create_blocks(self): """ description: - Create the bricks for the player's current level using the LevelGenerator-Class. :return: nothing """ self.bricks, self.number_unbreakable_bricks = LevelGenerator().create_level(self.player.current_level) def check_ball_collisions(self): """ description: - Checks all possible collisions that can occur for the ball. - Bounce off at left, right and top edge. - Bounce off from paddle using paddle.hitzones' vectors. - Check for brick collision and delegate handling. - Check if player dropped the ball. - if decremented to 0 --> game over --> save score --> restart :return: """ # collision left or right edge if self.ball.form.x <= 0 or self.ball.form.x >= DISPLAY_WIDTH: self.ball.collide_vertical() if self.ball.form.x <= 0: self.ball.form.x = 1 else: self.ball.form.x = DISPLAY_WIDTH - 1 # collision top edge if self.ball.form.y <= 0: self.ball.form.y = 1 self.ball.collide_horizontal() # collission paddle for paddle_part in self.paddle.hitzones: if paddle_part[0].colliderect(self.ball.form): self.ball.vector = paddle_part[1] break # brick collisions collision_bricks = [] for brick in self.bricks: if brick.rect.colliderect(self.ball.form): collision_bricks.append(brick) if len(collision_bricks) > 0: self.handle_brick_collisions(collision_bricks) # collision bottom edge --> lost if self.ball.form.y > DISPLAY_HEIGHT: self.player.lives -= 1 if self.player.lives == 0: highscore(self.screen, self.player.score) self.player.set_lives() self.player.score = 0 self.player.current_level = 1 self.start_game() else: self.reset_ball() def check_previously_horizontally_outside(self, brick_rect, horizontal_movement): """ description: - Check whether the ball did not horizontally overlap with the currently brick hit in the previous frame. - Aligned edges do not count as overlap. :param brick_rect: pygame.Rect-Object representing the hit brick's position. :param horizontal_movement: Movement-Enum value indicating left or right movement :return: true if no overlap, false otherwise """ ball_pos_previous = self.ball.get_previous_position() ball_rect_previous = pygame.Rect(ball_pos_previous[0], ball_pos_previous[1], self.ball.form.width, self.ball.form.height) if horizontal_movement == Movement.RIGHT: return ball_rect_previous.right <= brick_rect.left else: return ball_rect_previous.left >= brick_rect.right def check_previously_vertically_outside(self, brick_rect, vertical_movement): """ description: - Check whether the ball did not vertically overlap with the currently brick hit in the previous frame. - Aligned edges do not count as overlap. :param brick_rect: pygame.Rect-Object representing the hit brick's position. :param vertical_movement: Movement-Enum value indicating up or down movement :return: true if no overlap, false otherwise """ ball_pos_previous = self.ball.get_previous_position() ball_rect_previous = pygame.Rect(ball_pos_previous[0], ball_pos_previous[1], self.ball.form.width, self.ball.form.height) if vertical_movement == Movement.DOWN: return ball_rect_previous.bottom <= brick_rect.top else: return ball_rect_previous.top >= brick_rect.bottom def handle_brick_collisions(self, collision_bricks): """ description: - Handle the brick-collision based on the number of bricks hit. - If only one brick was hit: Call function to perform brick collision with determined collision type - More than one (basically working with the first 2, edge-case of more than 2 ignored due to unlikelihood and complexity): - Determine expected collision type based on the relative position of the 2 bricks. - Determine calculated collision type for 2 bricks. - Perform brick collision with the brick matching the expected collision type. - If none matches: chose one (irrelevant for user experience) to perform the brick collision with using expected collision type. :param collision_bricks: list of Brick-objects hit by the ball :return: nothing """ if len(collision_bricks) == 1: self.perform_brick_collision(collision_bricks[0], self.determine_collision_type(collision_bricks[0])) else: if collision_bricks[0].rect.x == collision_bricks[1].rect.x: # above each other collision_required = CollisionType.VERTICAL else: # next to each other collision_required = CollisionType.HORIZONTAL brick1_collision = self.determine_collision_type(collision_bricks[0]) brick2_collision = self.determine_collision_type(collision_bricks[1]) if brick1_collision == collision_required: self.perform_brick_collision(collision_bricks[0], brick1_collision) elif brick2_collision == collision_required: self.perform_brick_collision(collision_bricks[1], brick2_collision) else: self.perform_brick_collision(collision_bricks[0], collision_required) def determine_collision_type(self, brick_hit): """ description: - Determine the collision type based on the movement and overlap in the previous frame. :param brick_hit: Brick-object determine the theoretical collision type for. :return: CollisionType-enum value """ horizontal_movement = self.ball.get_horizontal_movement() vertical_movement = self.ball.get_vertical_movement() previously_horizontally_outside = self.check_previously_horizontally_outside(brick_hit.rect, horizontal_movement) previously_vertically_outside = self.check_previously_vertically_outside(brick_hit.rect, vertical_movement) # neither horizontal nor vertical overlap in the previous frame # --> compare ratio of horizontal and vertical overlap in the current frame if previously_horizontally_outside and previously_vertically_outside: horizontal_delta = (self.ball.form.right - brick_hit.rect.left) if horizontal_movement == Movement.RIGHT \ else (brick_hit.rect.right - self.ball.form.left) vertical_delta = (self.ball.form.bottom - brick_hit.rect.top) if vertical_movement == Movement.DOWN \ else (brick_hit.rect.bottom - self.ball.form.top) if horizontal_delta > vertical_delta: return CollisionType.HORIZONTAL else: return CollisionType.VERTICAL # horizontal overlap but no vertical overlap in the previous frame --> vertical collision elif previously_horizontally_outside and not previously_vertically_outside: return CollisionType.VERTICAL # no horizontal overlap but vertical overlap in the previous frame --> horizontal collision elif not previously_horizontally_outside and previously_vertically_outside: return CollisionType.HORIZONTAL # horizontal overlap and vertical overlap in the previous frame # --> irrelevant here because collision would have already happended and been handled in the previous frame. def perform_brick_collision(self, brick_hit, collision_type): """ description: - Call function to change ball's movement direction based on the collision_type. - Call Brick's get_hit() function. - Destroy brick, increase score if brick was destroyed and create a special with a certain probability. :param brick_hit: Brick-object to perform the collision with :param collision_type: CollisionType-Enum :return: nothing """ if collision_type == CollisionType.HORIZONTAL: self.ball.collide_horizontal() else: self.ball.collide_vertical() if brick_hit.get_hit(): self.bricks.remove(brick_hit) self.player.score += 1 if to_drop_special(): spcl = choose_random_special() txt = spcl.get_german_name() self.spcl_text = SpecialText(txt, self.clock_speed) self.present_specials.append(Special(brick_hit.rect.topleft, spcl)) def check_special_collisions(self): """ description: - Check if any specials, i.e. special.rect, currently present on the screen is caught with the paddle. - To be caught the special has to be completely within the paddle's horizontal width and the paddle's height. - Remove active special if new special is caught. - Activate special on self or paddle based on its type. - Remove the special from the currently present specials and set self.active special. - If special is off screen, remove it. :return: nothing """ if len(self.present_specials) > 0: for special in self.present_specials: if (self.paddle.get_top_edge() < special.rect.bottom <= self.paddle.get_bottom_edge()) \ and self.paddle.get_left_edge() <= special.rect.left \ and self.paddle.get_right_edge() >= special.rect.right: if not (self.active_special is None): self.remove_special() if special.is_paddle_special(): self.paddle.activate_special(special) else: self.activate_special(special) self.present_specials.remove(special) self.active_special = special self.active_special.activate(self.clock_speed) elif special.rect.top > DISPLAY_HEIGHT: self.present_specials.remove(special) def activate_special(self, special): """ description: - Activate a caught non-paddle special. - Either add a bonus life or adjust clock speed based on special.type :param special: the caught special :return: nothing """ if special.special_type == SpecialType.BONUS_LIFE: self.player.lives += 1 elif special.special_type == SpecialType.FASTER: self.clock_speed = DEFAULT_CLOCK_SPEED * CLOCK_SPEED_CHANGE_FACTOR elif special.special_type == SpecialType.SLOWER: self.clock_speed = DEFAULT_CLOCK_SPEED / CLOCK_SPEED_CHANGE_FACTOR def remove_special(self): """ description: - Remove the currently active special and negate its effect. - If is_paddle_special: remove special from pedal - else: reset self.clock_speed :return: nothing """ if self.active_special.is_paddle_special(): self.paddle.remove_special() else: self.clock_speed = DEFAULT_CLOCK_SPEED self.active_special = None def draw_all(self): """ description: - Called every tick - draws screen with every element :return: """ self.screen.fill(BLUE) for brick in self.bricks: brick.show_brick(self.screen) for paddle_part in self.paddle.hitzones: pygame.draw.rect(self.screen, WHITE, paddle_part[0]) for triangle in self.paddle.triangle_views: pygame.draw.polygon(self.screen, WHITE, triangle) for special in self.present_specials: special.fall() special.show_special(self.screen) self.player.draw_lives(self.screen) pygame.draw.rect(self.screen, WHITE, self.ball.form) self.screen.blit(self.font.render(str(self.player.score), -1, WHITE), (400, 550)) self.draw_spcl_txt() def draw_spcl_txt(self): """ description: - Write the type of the special that just dropped to the top of the screen. :return: nothing """ if self.spcl_text is not None: info = TextElement( center_position=(590, 10), font_size=16, bg_rgb=BLUE, text_rgb=WHITE, text=f"Spezial: {self.spcl_text.text} aufgetaucht", ) elems = RenderUpdates(info) elems.draw(self.screen) if self.spcl_text.tick(): self.spcl_text = None def level_completed(self): """ description: - Called when the player completes a level. - If level 10 was completed: show Highscore Page - Else: increase level, add bonus life :return: """ if self.player.current_level == 10: highscore(self.screen, self.player.score) return GameState.TITLE else: self.player.current_level += 1 self.player.lives += 1 self.start_game() def pause_elems(self): """ description: - Creates the Text object when being in pause mode :return: elements to be drawn during pause mode """ dbi = DatabaseInteract() sets = dbi.get_settings() heading = TextElement( center_position=(400, 400), font_size=18, bg_rgb=BLUE, text_rgb=WHITE, text=f"Spiel Pausiert, zum Fortsetzen '{sets[5]}' drücken, zum Beenden 'ESC' drücken ", ) elems = RenderUpdates(heading) return elems def draw_start_text(self): """ description: - Creates and draws the Text object when being in pause mode :return: nothing """ dbi = DatabaseInteract() sets = dbi.get_settings() key_left = sets[1] key_right = sets[3] key_shoot = sets[8] heading1 = TextElement( center_position=(400, 400), font_size=18, bg_rgb=BLUE, text_rgb=WHITE, text=f"Startwinkel mit '{key_left}' und '{key_right}' auswählen", ) heading2 = TextElement( center_position=(400, 450), font_size=18, bg_rgb=BLUE, text_rgb=WHITE, text=f"Mit '{key_shoot}' Ball abschiessen, zum Beenden 'ESC' drücken ", ) elems = RenderUpdates(heading1,heading2) elems.draw(self.screen) def main(self): """ description: - Contains game logic. - Process game events by calling corresponding functions. - Update the UI. - Check whether level was completed. :return: nothing """ clock = pygame.time.Clock() self.start_game() dbi = DatabaseInteract() sets = dbi.get_settings() key_left = sets[2] key_right = sets[4] pause_key = sets[6] while True: clock.tick(self.clock_speed) for event in pygame.event.get(): if event.type == QUIT: os._exit(1) if event.type == pygame.KEYDOWN: if event.key == int(pause_key): elems = self.pause_elems() game_paused = True while game_paused: elems.draw(self.screen) events = pygame.event.get() for event in events: if event.type == QUIT: os._exit(1) if event.type == pygame.KEYDOWN: if event.key == int(pause_key): game_paused = False break elif event.key == pygame.K_ESCAPE: return GameState.TITLE pygame.display.update() keys = pygame.key.get_pressed() if keys[int(key_left)]: self.paddle.move(-1) if keys[int(key_right)]: self.paddle.move(1) if keys[pygame.K_ESCAPE]: return GameState.TITLE # update ball self.ball.move() self.check_ball_collisions() # update specials if not (self.active_special is None): if self.active_special.tick(): self.remove_special() self.check_special_collisions() # Update screen self.draw_all() pygame.display.flip() if len(self.bricks) == self.number_unbreakable_bricks: if self.level_completed() == GameState.TITLE: return GameState.TITLE
class GameManager(): def __init__(self, screenWidth, screenHeight, board1X, board1Y, board1Z, board2X, board2Y, board2Z, countersX, countersY, countersZ, timerX, timerY, timerZ, arcadeLevels, gameLevels): self.currentScene = "menu" self.arcadeLevels = arcadeLevels self.currentLevel = 0 self.gameLevels = gameLevels self.BackButton = Button(430, 40, 50, 110, "Back", "menu", 30) self.playerBoard = Board(board1X, board1Y, board1Z) self.refBoard = Board(board2X, board2Y, board2Z) self.MoveCounter = MoveCounter(countersX, countersY, countersZ) self.Timer = Timer(timerX, timerY, timerZ) # TODO: After updating the MoveCounter, add a second counter for the MAX moves (or target moves) self.LevelGenerator = LevelGenerator(board2X, board2Y, board2Z) self.mainMenu = MainMenu(screenWidth / 2, screenHeight / 2, 50, 50) self.levelSelectMenu = LevelSelect(screenWidth / 2, screenHeight / 2, 50, 50, self.gameLevels) self.levelCompleteMenu = LevelComplete(screenWidth / 2, screenHeight / 2, 50, 50) self.arcadeOverMenu = ArcadeOver(screenWidth / 2, screenHeight / 2, 50, 50) self.resetList = [ self.playerBoard, self.refBoard, self.MoveCounter, self.LevelGenerator ] def Click(self, x, y): if "level" in self.currentScene: clicked = self.BackButton.IsIn(x, y) if clicked: self.ChangeScene(self.BackButton.Value) return squareX, squareY = self.playerBoard.GetSquare(x, y) if squareX != -1: self.playerBoard.Click(squareX, squareY) self.MoveCounter.Add() if self.CheckWin(): if "arcade" in self.currentScene: self.currentLevel += 1 self.ChangeScene("level arcade") else: self.ChangeScene("complete") elif self.currentScene == "menu": button = self.mainMenu.GetButton(x, y) if button is not None: self.ChangeScene(button.Value) elif self.currentScene == "select menu": button = self.levelSelectMenu.GetButton(x, y) if button is not None: self.ChangeScene(button.Value) elif self.currentScene == "complete": button = self.levelCompleteMenu.GetButton(x, y) if button is not None: if button.Value == "next level": self.currentLevel += 1 self.ChangeScene( str(self.arcadeLevels[self.currentLevel]) + " level") else: self.ChangeScene(button.Value) elif self.currentScene == "arcade complete": button = self.arcadeOverMenu.GetButton(x, y) if button is not None: self.currentLevel = 0 self.ChangeScene(button.Value) #I need to add a value to the button which makes it go to next level # IF we clicked on "next level" then: # Check what the current level is (self.currentLevel), and increase it by 1. # Change level to that -> self.ChangeScene("2.2 level") elif self.currentScene == "settings": pass else: self.currentScene = "menu" def ChangeScene(self, newScene): if "complete" not in newScene: for object in self.resetList: object.Reset() else: self.Timer.Pause() if "level" in newScene: if "arcade" in newScene: self.GenerateLevel(int(self.arcadeLevels[self.currentLevel])) else: if newScene is "next level": self.currentLevel += 1 self.GenerateLevel(int(gameLevels[self.currentLevel][0])) #change generate level to my code inside generate level + make an actual input self.currentScene = newScene def CheckWin(self): if self.playerBoard.Equals( self.refBoard): #Impliment Equals check in board return True else: return False def Reset(self): self.MoveCounter.Reset() self.playerBoard.Reset() self.Timer.Increment(self.arcadeLevels[self.currentLevel] * 5) def GenerateLevel(self, moves): self.Reset() self.refBoard = self.LevelGenerator.GenerateLevel(moves) def Display(self): if "level" in self.currentScene: self.playerBoard.Display() self.refBoard.Display() self.MoveCounter.Display() self.Timer.Display() self.BackButton.Display() if self.Timer.OutofTime(): self.ChangeScene("arcade complete") elif self.currentScene == "arcade complete": self.playerBoard.Display() self.refBoard.Display() self.MoveCounter.Display() self.Timer.Display() self.arcadeOverMenu.Display() elif self.currentScene == "menu": self.mainMenu.Display() elif self.currentScene == "select menu": self.levelSelectMenu.Display() elif self.currentScene == "complete": self.playerBoard.Display() self.refBoard.Display() self.MoveCounter.Display() self.Timer.Display() # Task 3: Gray out what is behind it Look at processing docs, self.levelCompleteMenu.Display() elif self.currentScene == "settings": pass else: self.currentScene = "menu"
def __init__(self): # self.screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT),FULLSCREEN) self.screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT), DOUBLEBUF) self.width = SCREEN_WIDTH self.height = SCREEN_HEIGHT self.dimensions = (SCREEN_WIDTH, SCREEN_HEIGHT) self.playing = True self.paused = True self.audio = GameAudio() self.total_game_time = 0 self.pointFont = pygame.font.Font(POINT_FONT, 96) self.game_objects = [] self.level = 1 self.score = 0 self.needs_sorting = True self.cursor_image = pygame.image.load(CURSOR_SPRITE).convert_alpha() self.cursor_dimensions = (50, 50) self.cursor_image = pygame.transform.scale(self.cursor_image, self.cursor_dimensions) pygame.mouse.set_visible(False) # Camera self.world_x = 0 self.world_y = 0 # Background self.backdrop = Backdrop(self) # Particle system self.particle_system = ParticleSystem(self) # Player self.player = None # gotta pass it a reference to the Game class self.player_gender = 1 self.bear = None # self.game_objects.append(self.player) self.weapon = Weapon(self) # Level self.level_generator = LevelGenerator(self) self.bomb_generator = BombGenerator(self) floating_text = FloatingText.New(self, (255, 255, 255), "Use WASD or Arrow keys", SCREEN_WIDTH * 0.6, SCREEN_HEIGHT * 0.2, line2="to run around", life=6) # floating_text = FloatingText.FloatingText(self) floating_text.x = -20 floating_text.y = -200 self.AddObject(floating_text) for i in range(15): tree = Tree(self) tree.x = SCREEN_WIDTH * random.random() tree.y = SCREEN_HEIGHT * random.random() self.game_objects.append(tree) # Enemies self.enemy_generator = EnemyGenerator(self) # Coin Generator self.coin_generator = CoinGenerator(self) self.again_button_style = ButtonStyle('sprites/blue_button00.png', (100, 100, 100), 'sprites/blue_button01.png', (150, 150, 150), POINT_FONT, vert_align=ALIGN_CENTER, hor_align=ALIGN_CENTER, border_perc=0.25, font_up_color=WHITE, font_down_color=BLACK, font_disabled_color=DARK_GREY) self.again_button = Button(self.screen, 'again', self.width * 0.7, self.height * 0.7, self.width * 0.2, self.height * 0.15, self.again_button_style) self.title_image = pygame.image.load(TITLE_SPRITE).convert_alpha() tit_width, tit_height = self.title_image.get_size() new_tit_width = int(self.width * 0.9) new_tit_height = int(new_tit_width * (tit_height / tit_width)) self.title_image = pygame.transform.scale( self.title_image, (new_tit_width, new_tit_height)) self.boy_button = Button(self.screen, '', self.width * 0.05, self.height * 0.25, self.width * 0.4, self.height * 0.7, self.again_button_style) self.girl_button = Button(self.screen, '', self.width * 0.5 + self.width * 0.05, self.height * 0.25, self.width * 0.4, self.height * 0.7, self.again_button_style) self.title_cowboy = pygame.image.load(TITLE_COWBOY).convert_alpha() tit_width, tit_height = self.title_cowboy.get_size() new_tit_width = int(self.width * 0.3) new_tit_height = int(new_tit_width * (tit_height / tit_width)) self.title_cowboy = pygame.transform.scale( self.title_cowboy, (new_tit_width, new_tit_height)) self.title_cowgirl = pygame.image.load(TITLE_COWGIRL).convert_alpha() tit_width, tit_height = self.title_cowgirl.get_size() new_tit_width = int(self.width * 0.3) new_tit_height = int(new_tit_width * (tit_height / tit_width)) self.title_cowgirl = pygame.transform.scale( self.title_cowgirl, (new_tit_width, new_tit_height)) # Running measurements self.last_time = time.time() self.delta_time = 0 self.mouse_x = 0 self.mouse_y = 0 self.score = 0 # layers for collision detection self.collision_layers = {}
class Game(object): def __init__(self): # self.screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT),FULLSCREEN) self.screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT), DOUBLEBUF) self.width = SCREEN_WIDTH self.height = SCREEN_HEIGHT self.dimensions = (SCREEN_WIDTH, SCREEN_HEIGHT) self.playing = True self.paused = True self.audio = GameAudio() self.total_game_time = 0 self.pointFont = pygame.font.Font(POINT_FONT, 96) self.game_objects = [] self.level = 1 self.score = 0 self.needs_sorting = True self.cursor_image = pygame.image.load(CURSOR_SPRITE).convert_alpha() self.cursor_dimensions = (50, 50) self.cursor_image = pygame.transform.scale(self.cursor_image, self.cursor_dimensions) pygame.mouse.set_visible(False) # Camera self.world_x = 0 self.world_y = 0 # Background self.backdrop = Backdrop(self) # Particle system self.particle_system = ParticleSystem(self) # Player self.player = None # gotta pass it a reference to the Game class self.player_gender = 1 self.bear = None # self.game_objects.append(self.player) self.weapon = Weapon(self) # Level self.level_generator = LevelGenerator(self) self.bomb_generator = BombGenerator(self) floating_text = FloatingText.New(self, (255, 255, 255), "Use WASD or Arrow keys", SCREEN_WIDTH * 0.6, SCREEN_HEIGHT * 0.2, line2="to run around", life=6) # floating_text = FloatingText.FloatingText(self) floating_text.x = -20 floating_text.y = -200 self.AddObject(floating_text) for i in range(15): tree = Tree(self) tree.x = SCREEN_WIDTH * random.random() tree.y = SCREEN_HEIGHT * random.random() self.game_objects.append(tree) # Enemies self.enemy_generator = EnemyGenerator(self) # Coin Generator self.coin_generator = CoinGenerator(self) self.again_button_style = ButtonStyle('sprites/blue_button00.png', (100, 100, 100), 'sprites/blue_button01.png', (150, 150, 150), POINT_FONT, vert_align=ALIGN_CENTER, hor_align=ALIGN_CENTER, border_perc=0.25, font_up_color=WHITE, font_down_color=BLACK, font_disabled_color=DARK_GREY) self.again_button = Button(self.screen, 'again', self.width * 0.7, self.height * 0.7, self.width * 0.2, self.height * 0.15, self.again_button_style) self.title_image = pygame.image.load(TITLE_SPRITE).convert_alpha() tit_width, tit_height = self.title_image.get_size() new_tit_width = int(self.width * 0.9) new_tit_height = int(new_tit_width * (tit_height / tit_width)) self.title_image = pygame.transform.scale( self.title_image, (new_tit_width, new_tit_height)) self.boy_button = Button(self.screen, '', self.width * 0.05, self.height * 0.25, self.width * 0.4, self.height * 0.7, self.again_button_style) self.girl_button = Button(self.screen, '', self.width * 0.5 + self.width * 0.05, self.height * 0.25, self.width * 0.4, self.height * 0.7, self.again_button_style) self.title_cowboy = pygame.image.load(TITLE_COWBOY).convert_alpha() tit_width, tit_height = self.title_cowboy.get_size() new_tit_width = int(self.width * 0.3) new_tit_height = int(new_tit_width * (tit_height / tit_width)) self.title_cowboy = pygame.transform.scale( self.title_cowboy, (new_tit_width, new_tit_height)) self.title_cowgirl = pygame.image.load(TITLE_COWGIRL).convert_alpha() tit_width, tit_height = self.title_cowgirl.get_size() new_tit_width = int(self.width * 0.3) new_tit_height = int(new_tit_width * (tit_height / tit_width)) self.title_cowgirl = pygame.transform.scale( self.title_cowgirl, (new_tit_width, new_tit_height)) # Running measurements self.last_time = time.time() self.delta_time = 0 self.mouse_x = 0 self.mouse_y = 0 self.score = 0 # layers for collision detection self.collision_layers = {} def StartNewGame(self): if self.bear is not None: self.ExplodeObject(self.bear) self.DestroyObject(self.bear) self.bear = None self.total_game_time = 0 self.playing = True self.score = 0 self.level = 1 self.CreatePlayer() self.enemy_generator.Reset() self.coin_generator.Reset() self.weapon.Reset() self.bomb_generator.Reset() pygame.mouse.set_visible(False) def CreatePlayer(self): if self.player is not None and not self.player.dead: self.DestroyObject(self.player) self.player = Player.Player(self, self.player_gender) self.AddObject(self.player) # self.player.x = 0 # self.player.y = 0 self.player.x = -(self.world_x - SCREEN_WIDTH * 0.5) self.player.y = -(self.world_y - SCREEN_HEIGHT * 0.5) def AddObject(self, game_object): self.game_objects.append(game_object) self.needs_sorting = True def DestroyObject(self, game_object): game_object.dead = True try: self.game_objects.remove(game_object) except ValueError: print(self.__class__.__name__, 'was trying to destroy itself but failed') self.needs_sorting = True def DisplayPoints(self): pointText = pointFont.render('$' + str(self.score), True, POINTS_COLOR, None) TX, TY = pointText.get_size() textWidth = int(POINTS_HEIGHT * (TX / TY)) pointText = pygame.transform.scale(pointText, (textWidth, POINTS_HEIGHT)) x = int(SCREEN_WIDTH * 0.95 - textWidth) y = int(SCREEN_HEIGHT * 0.97 - POINTS_HEIGHT) self.screen.blit(pointText, (x, y)) def AddPoints(self, value): self.score += value if self.score >= self.weapon.next_upgrade: self.weapon.UpgradeWeapon() def ExplodeObject(self, game_object): if game_object.IsEnemy(): self.particle_system.EnemyExplode(game_object.x, game_object.y, game_object.radius) elif game_object.IsBomb(): self.particle_system.BombExplode(game_object.x, game_object.y) else: self.particle_system.TreeExplode(game_object) def NextLevel(self): self.level += 1 self.bomb_generator.Reset() def Play(self): while self.playing: # lets keep track of how much time has passed between the last frame and this one current_time = time.time() self.delta_time = current_time - self.last_time #should be in seconds # if are game is running faster than our target FPS then pause for a tick if self.delta_time < 1 / TARGET_FPS: continue self.total_game_time += self.delta_time ######### # Handle events for event in pygame.event.get(): # if the app is quit then break and close if event.type == pygame.QUIT: self.playing = False pygame.quit() sys.exit() # if the player is holding the left mouse button then fire some bullets if event.type == pygame.MOUSEBUTTONDOWN and event.button is 1: if self.player is not None and not self.player.dead: self.weapon.firing = True if event.type == pygame.MOUSEBUTTONUP and event.button is 1: self.weapon.firing = False if event.type == pygame.ACTIVEEVENT: print('Active event', event.state, event.gain) if event.state == 6 or event.state == 2: self.paused = True if event.type == KEYDOWN and event.key == K_ESCAPE: if not self.paused: self.paused = True elif self.player is not None: self.paused = False # pressed = pygame.key.get_pressed() # if pressed[pygame.K_ESCAPE]: # if not self.paused: # self.paused = True # elif self.player is not None: # self.paused = False # # self.playing = False # # pygame.quit() # # sys.exit() # store the mouse pos for easy getting self.mouse_x, self.mouse_y = pygame.mouse.get_pos() if not self.paused: if self.player is not None and not self.player.dead: if self.mouse_x < 30: self.mouse_x = 30 if self.mouse_x > SCREEN_WIDTH - 30: self.mouse_x = SCREEN_WIDTH - 30 if self.mouse_y < 30: self.mouse_y = 30 if self.mouse_y > SCREEN_HEIGHT - 30: self.mouse_y = SCREEN_HEIGHT - 30 pygame.mouse.set_pos(self.mouse_x, self.mouse_y) # if pygame.mouse.get_focused() == 0: # print( 'Mouse left the screen' ) # Check for key presses and update the player's velocity ########### # Update game objects # update the weapon (fire bullets) self.weapon.Update() # update the level self.level_generator.Update() # spawn more enemies sometimes self.enemy_generator.Update() self.coin_generator.Update() self.bomb_generator.Update() # self.bomb_generator.Update() # clear the collision layers # (we really only need to do this if objects have been added or removed since the last time) if self.needs_sorting: for flag in GameObject.COL_FLAGS: self.collision_layers[flag] = [] # iterate through all our game objects and add them to any layers they apply to for game_object in self.game_objects: # go through each (if any) collision flags there are for this item for key, value in game_object.collision_flags.items(): # the key will be the collision flag # the value will be a bool for if it applies to this layer if value: # add it to the collision layer self.collision_layers[key].append(game_object) self.needs_sorting = False # we'll copy the game object list and iterate through the copy so that # we can remove dead elements from the original without getting tripped up object_list = self.game_objects.copy() for game_object in object_list: # we'll let each game object handle their own update # mostly they'll just check whether or not they're dead but sometimes they'll do collision detection game_object.Update() if self.player is not None: # since the camera follows the player just set the world origin to the player's position dif_x = -self.world_x + (-self.player.x + SCREEN_WIDTH * 0.5) dif_y = -self.world_y + (-self.player.y + SCREEN_HEIGHT * 0.5) self.world_x += dif_x * 0.4 self.world_y += dif_y * 0.4 ######### # draw # clear the screen self.screen.fill((220, 220, 200)) # draw the ground layer self.backdrop.Draw() # sort the objects object_sort_tree = TreeList() # just by putting them into the TreeList one by one we'll get them in ascending order for game_object in self.game_objects: # sorted by they're y position # that way when we draw them from highest on the screen to the lowest on the screen # the ones below (and in front) will be drawn on top object_sort_tree.Put( game_object.y + game_object.radius * 0.5 + game_object.z, game_object) # draw the game objects for game_object in object_sort_tree.ToList(): game_object.Draw() self.DisplayPoints() cx = int(self.mouse_x - self.cursor_dimensions[0] * 0.5) cy = int(self.mouse_y - self.cursor_dimensions[1] * 0.5) self.screen.blit(self.cursor_image, (cx, cy)) if self.player is not None and self.player.dead and not self.weapon.firing: self.again_button.Draw() if self.again_button.pressed: self.StartNewGame() self.again_button.pressed = False if self.paused: # draw the main menu: self.boy_button.Draw() self.girl_button.Draw() self.screen.blit( self.title_image, (int(self.width * 0.05), int(self.height * 0.03))) self.screen.blit( self.title_cowboy, (int(self.width * 0.1), int(self.height * 0.25))) self.screen.blit(self.title_cowgirl, (int(self.width * 0.5 + self.width * 0.1), int(self.height * 0.25))) if self.boy_button.pressed: self.player_gender = 1 if self.girl_button.pressed: self.player_gender = 2 if self.girl_button.pressed or self.boy_button.pressed: self.girl_button.pressed = False self.boy_button.pressed = False if self.player is None or self.player.dead: self.StartNewGame() else: self.CreatePlayer() self.paused = False # display what we've drawn to the screen pygame.display.flip() ######### # finalize # save the current time as our last time self.last_time = current_time def ShowMenu(self): pass
def main(): pygame.init() width = 1200 height = 800 levelLoader = LevelGenerator() #Loads planet layouts into planet array screen = pygame.display.set_mode([width, height]) screen_center = Vec2d(width / 2, height / 2) coords = Coords(screen_center.copy(), 1, True) # ^ Center of window is (0,0), scale is 1:1, and +y is up coords.zoom_at_coords(Vec2d(0, 0), 1) # ^Sets camera center # Used to manage how fast the screen updates clock = pygame.time.Clock() planets = [] planets = levelLoader.loadLevel(levelLoader.getLevel()) arrow = Arrow(10, Vec2d(-565, 0), Vec2d(-540, 0), Vec2d(0, 0)) #textFont = pygame.font.Font(None, 144) #Strength of arrow shot. Will be divided by 60, adding roughly 1 to force per second powerMeter = 0 arrowShootingTime = 30 #Time to apply force of shooting arrow in frames arrowShootingStart = False originalThrustVector = Vec2d(0, 0) frame_rate = 60 playback_speed = 4 dt = playback_speed / frame_rate done = False while not done: gameMouse = pygame.mouse # --- Main event loop for event in pygame.event.get(): if event.type == pygame.QUIT: # If user clicked close done = True if event.type == pygame.MOUSEBUTTONDOWN: if (not arrow.getActive()): #Click and hold for power. Release to shoot arrow.setCharging(True) if event.type == pygame.MOUSEBUTTONUP: if (not arrow.getActive()): arrow.setActive(True) arrow.setCharging(False) arrowShootingStart = True originalThrustVector = ForceCalculator.calculateThrust( arrow.center, arrow.tip, powerMeter) arrow.update_force(originalThrustVector) if (arrow.getActive()): if (arrowShootingTime > 0): arrowShootingTime -= 1 #calculate all forces that would apply to arrow here forces = [] for planet in planets: forces.append( ForceCalculator.calculateGravity(arrow.center, arrow.mass, planet.center, planet.mass, -10)) if (arrowShootingTime > 0): forces.append(originalThrustVector) else: powerMeter = 0 forceSum = ForceCalculator.sumForces(forces) arrow.update_force(forceSum) print("Arrow is active") else: #Aim input here mouseTup = gameMouse.get_pos() mouseVec = Vec2d(mouseTup[0] - 1200, mouseTup[1]) coordMouseVec = coords.pos_to_screen(mouseVec).int() arrow.rotateByMouse(coordMouseVec) if (arrow.getCharging()): powerMeter += 2 print("Arrow is deactive") print("Power Meter:", powerMeter) # Drawing screen.fill(BLACK) # wipe the screen for obj in planets: obj.draw(screen, coords) # draw object to screen obj.update(dt) arrow.update(dt) arrow.draw(screen, coords) #mouseTup = gameMouse.get_pos() #mouseVec = Vec2d(mouseTup[0] - 1200, mouseTup[1]) #coordMouseVec = coords.pos_to_screen(mouseVec).int() #arrow.rotateByMouse(coordMouseVec) #mousePosSurface = textFont.render("x: " + str(coordMouseVec[0]) + " y: " + str(coordMouseVec[1]), 0, WHITE) #screen.blit(mousePosSurface, (500,500)) #print("Arrow is deactive") # --- Update the screen with what we've drawn. pygame.display.update() # This limits the loop to 60 frames per second clock.tick(frame_rate) pygame.quit()
def main(): # Initialize screen pygame.init() screen = pygame.display.set_mode((1054, 714)) pygame.display.set_caption('Labyrinth') #initializing constants for drawing maze black = (0, 0, 0) thickness = 4 width = 34 height = 34 none = 0 offset = 30 constant = 34 # Fill background background = pygame.Surface(screen.get_size()) background = background.convert() background.fill((250, 250, 250)) # Blit everything to the screen screen.blit(background, (0, 0)) pygame.display.flip() def drawMaze(maze): """ View a maze """ # initialize north and west for i in range(maze.width): if maze.cell[i,0].north: drawWall(True,i,0) for i in range(maze.height): if maze.cell[0,i].west: drawWall(False,0,i) # loop through to draw the rest of the walls for i in range(maze.width): for j in range(maze.height): if maze.cell[i,j].south: drawWall(True,i,j+1) if maze.cell[i,j].east: drawWall(False,i+1,j) def drawWall(isHorizontal, x, y): """ Draw wall for a cell """ if isHorizontal: pygame.draw.rect(background, black, (x*constant + offset, y*constant + offset, width, none), thickness) else: pygame.draw.rect(background, black, (x*constant + offset, y*constant + offset, none, height), thickness) l = LevelGenerator() m = l.nextLevel() drawMaze(m) # Event loop while 1: for event in pygame.event.get(): if event.type == QUIT: return screen.blit(background, (0, 0)) pygame.display.flip()