def test_snake_check_collision_with_fruit_while_moving(self): """ A Snake instance will be created at given coordinates. It will then be moved in a pattern around a fruit, not being able to take it before the last move. After each movement, a test will be conducted. """ fruit_coordinates = (60, 60) fruit_size = (30, 30) snake = Snake((30, 30), (30, 30), (0, 0, 0)) expected_results = [ False, False, False, False, False, False, False, True ] test_vector = [ Snake.move_down, Snake.move_down, Snake.move_right, Snake.move_right, Snake.move_up, Snake.move_up, Snake.move_left, Snake.move_down ] for expected, test_move in zip(expected_results, test_vector): with self.subTest("Snake.{}".format(test_move.__name__)): test_move(snake) self.assertEqual( snake.check_collision_with_fruit(fruit_coordinates, fruit_size), expected)
def test_snake_growing_while_moving(self): """ A snake instance will be created at given coordinates. It will then be moved in a pattern, growing after each movement. Each movement will carry with it a control to make sure that the entire body moves as expected. """ snake = Snake((30, 30), (30, 30), (0, 0, 0)) expected_results = [[(30, 0), (30, 30)], [(60, 0), (30, 0), (30, 30)], [(60, 30), (60, 0), (30, 0), (30, 30)], [(60, 60), (60, 30), (60, 0), (30, 0), (30, 30)], [(30, 60), (60, 60), (60, 30), (60, 0), (30, 0), (30, 30)], [(0, 60), (30, 60), (60, 60), (60, 30), (60, 0), (30, 0), (30, 30)], [(0, 90), (0, 60), (30, 60), (60, 60), (60, 30), (60, 0), (30, 0), (30, 30)], [(30, 90), (0, 90), (0, 60), (30, 60), (60, 60), (60, 30), (60, 0), (30, 0), (30, 30)]] test_vector = [ Snake.move_up, Snake.move_right, Snake.move_down, Snake.move_down, Snake.move_left, Snake.move_left, Snake.move_down, Snake.move_right ] for expected, test_move in zip(expected_results, test_vector): with self.subTest("Snake.{}".format(test_move.__name__)): snake.grow() test_move(snake) result = [] for parts in snake: result.append(parts.get_coordinates()) self.assertListEqual(result, expected)
def mode_1(screen): snake = Snake(screen) apple = Apple(screen) def Key_Board_Ev(event): if event.keysym == 'd': snake.KeyBoard(1, 0) if event.keysym == 'a': snake.KeyBoard(-1, 0) if event.keysym == 'w': snake.KeyBoard(0, -1) if event.keysym == 's': snake.KeyBoard(0, 1) screen.root.bind('<Key>', Key_Board_Ev) while True: snake.S_Update() if snake.Is_Exit: break if snake.body_pos[0] == apple.apple_pos: apple.Apple_Is_Eatten() snake.Apple_Is_Eatten() snake.Wall() screen.root.update()
def test_snake_check_collision_with_self(self): """ This test will create a Snake instance at given coordinates. A collision with self check will then be conducted. This check is expected to be false. """ snake = Snake((30, 30), (30, 30), (0, 0, 0)) self.assertEqual(snake.check_collision_with_self(), False)
def test_snake_grow(self): """ This test will create a Snake instance at given coordinates. Grow will then be called to make sure that no chrash occour. """ snake = Snake((30, 30), (30, 30), (0, 0, 0)) self.assertIsNone( snake.grow(), "Snake.grow() should neither return an object nor raise an error.")
def mode_2(screen): leader_table = Leader_Table(screen) snake = Snake(screen) apple = Apple(screen) def Key_Board_Ev(event): if event.keysym == 'd': snake.KeyBoard(1, 0) if event.keysym == 'a': snake.KeyBoard(-1, 0) if event.keysym == 'w': snake.KeyBoard(0, -1) if event.keysym == 's': snake.KeyBoard(0, 1) screen.root.bind('<Key>', Key_Board_Ev) otimer = Timer(screen) bufs = Bufs(screen) score = Score(screen) while True: otimer.Update() snake.S_Update() if (otimer.min_col < 0 or snake.Is_Exit): break if snake.body_pos[0] == apple.apple_pos: apple.Apple_Is_Eatten() snake.Apple_Is_Eatten() bufs.Is_Gen() score.Apple_Is_Eatten() snake.Wall() nbuf = bufs.Is_Buffed(snake.body_pos[0]) bufs.Clean_buf() if nbuf != -1: if nbuf == 'tplus': otimer.sec_col += 40 otimer.min_col += int(otimer.sec_col // 60) otimer.sec_col = otimer.sec_col % 60 if nbuf == 'lucky': ind = bufs.Gen_Rand_Int(0, 1) if ind == 1: score.score += 100 score.Set_Score() else: break screen.root.update() leader_table.Update_T(score.score) leader_table.Table_Visual()
def test_snake_iterable(self): """ This test will create a Snake instance at given coordinates. An attempt will then be made to iterate over the instance. """ snake = Snake((30, 30), (30, 30), (0, 0, 0)) self.assertIsInstance(snake, Iterable)
def test_snake_check_collision(self): """ This test will create a Snake instance at given coordinates. Two collision checks will then be conducted. One of the collision checks will be true. The other will be false. """ snake = Snake((30, 30), (30, 30), (0, 0, 0)) expected_results = [True, False] results = [] test_vectors = [[(30, 30), (5, 5)], [(70, 70), (10, 10)]] for test_vector in test_vectors: results.append( snake.check_collision(test_vector[0], test_vector[1])) self.assertListEqual(results, expected_results)
def test_snake_inside_bounds(self): """ This test will create a Snake instance at given coordinates. Three bounds will then be created. One of the bounds will the Snake be completely inside of One will it be partially inside of And the last one will it be outside of """ snake = Snake((30, 30), (30, 30), (0, 0, 0)) expected_results = [True, False, False] results = [] test_vectors = [[(0, 0), (150, 150)], [(30, 30), (35, 35)], [(70, 70), (100, 100)]] for test_vector in test_vectors: results.append(snake.inside_bounds(test_vector[0], test_vector[1])) self.assertListEqual(results, expected_results)
def main(): #global vars global s, snack st.init() s = Snake(st.snake_color, (st.snake_x, st.snake_y)) snack = Cube(randomSnack(st.rows, s), color=st.snack_color) #create window window = pygame.display.set_mode((st.width, st.width)) #Display elements flag = True clock = pygame.time.Clock() delay_time = 50 tick_time = 10 while flag: pygame.time.delay(delay_time) clock.tick(tick_time) s.move() snack_check() # snake_check() for x in range(len(s.body)): if s.body[x].pos in list(map(lambda z: z.pos, s.body[x + 1:])): print('Score: ', len(s.body)) # message_box('You Lost!', 'Play again...') s.reset((10, 10)) break redrawWindow(window) pass
def run_game(): #initializing game pygame.init() #creating an object so as to access variables values in class settings sn_settings = Settings() #drawing screen screen = pygame.display.set_mode( (sn_settings.screen_width, sn_settings.screen_height)) #creating an object snake so as to access variables values in class Snake snake = Snake(screen, sn_settings) #a list to store values of snake body to track it's movement snake_list = [] ##creating an object food so as to access variables values in class Food food = Food(screen, sn_settings) #adding screen caption pygame.display.set_caption("kings snake game") #to keep track of time while playing the game clock = pygame.time.Clock() # Make the Play button. play_button = Button(sn_settings, screen, "Play") #game statistics game_stats = GameStats(sn_settings) #game scores sb = Scoreboard(sn_settings, screen, game_stats) while True: #start main loop for the game if game_stats.game_active == True: #calling update in Snake class to automate snake movement snake.update(sn_settings) #watch for keyboard / mouse input Gf.check_event(screen, sn_settings, snake, game_stats, snake_list, play_button, sb) #displaying screen objects Gf.update(screen, sn_settings, snake_list, snake, food, play_button, game_stats, sb) #rate at which the screen is update clock.tick(sn_settings.snake_speed)
def test_snake_collision_while_growing_and_moving(self): """ A Snake instance will be created at given coordinates. It will then be moved in a pattern. After each movement, a inside_bounds test will be conducted. """ snake = Snake((30, 30), (30, 30), (0, 0, 0)) expected_results_inside_bounds = [ True, True, True, True, True, True, False, False, True ] expected_results_collision_with_self = [ False, False, False, False, False, False, False, False, True ] test_vector = [ Snake.move_up, Snake.move_right, Snake.move_down, Snake.move_down, Snake.move_left, Snake.move_left, Snake.move_down, Snake.move_right, Snake.move_up ] for expected_bounds, expected_collision, test_move in zip( expected_results_inside_bounds, expected_results_collision_with_self, test_vector): with self.subTest("Snake.{}".format(test_move.__name__)): snake.grow() test_move(snake) self.assertEqual(snake.inside_bounds((0, 0), (90, 90)), expected_bounds) self.assertEqual(snake.check_collision_with_self(), expected_collision)
def __init__(self, background_colour, width, height): """Initialize the game. The parameters are passed on to the init function of Window Parameters: ------------------------------------------ colour : list(int, int, int) A triple of values between 0 and 255 indicating the r, g, b value of the rectangle top_left : tuple(int, int) The x- and y-coordinates for the top left corner of the rectangle size : tuple(int, int) The width and height of the rectangle """ self.window = Window(background_colour, width, height) self.snake_size = (30, 30) self.snake = Snake((width//2, height//2), self.snake_size, (75, 75, 75)) self.current_movement = Snake.move_up self.fruit_coordinates = (0, 0) self.fruit_size = (30, 30) self.running = True self.last_update_time = pygame.time.get_ticks()
def test_snake_inside_bounds_while_moving(self): """ A snake instance will be created at given coordinates. It will then be moved in a pattern, growing after each movement. After each movement is done, a collision_with_self check will be conducted. """ snake = Snake((30, 30), (30, 30), (0, 0, 0)) expected_results = [ False, False, False, False, False, False, False, False, True ] test_vector = [ Snake.move_up, Snake.move_right, Snake.move_down, Snake.move_down, Snake.move_left, Snake.move_left, Snake.move_down, Snake.move_right, Snake.move_up ] for expected, test_move in zip(expected_results, test_vector): with self.subTest("Snake.{}".format(test_move.__name__)): snake.grow() test_move(snake) self.assertEqual(snake.check_collision_with_self(), expected)
def test_snake_internal_get_size(self): """ A Snake instance will be created at given coordinates. The instance will then be iterated over, and get_size called, on the internal structure to make sure that the size match the provided one. """ snake = Snake((30, 30), (30, 30), (0, 0, 0)) expected_results = [(30, 30)] results = [] for part in snake: results.append(part.get_size()) self.assertListEqual(results, expected_results)
class SnakeGame: """ A simple structure for a Snake-like game. Attributes: ----------------- window : Window The main window of the game. Makes sure that the implementation is visible to the user. snake_size : tuple(int, int) The size of the snake. snake : Snake The controllable snake. current_movement : Callable One of the four directional functions from the Snake class. Saved for convenience and used to call movement on the snake-attribute. fruit_coordinates : list(int, int) The positional coordinates of the fruit that the snake is to eat. fruit_size : tuple(int, int) The size of the fruit. running : bool Used to control the state of the game. If false, the player has either exited or lost the game. last_update_time : int If the difference between this and a clock check is above 150 the method update_movement is called and this attribute updated. Methods: ----------------- handle_keydown(event): Function to handle user input events incoming from the underlying pygame module. draw(): Draw the game to the screen. move_fruit(): Randomly moves the fruit until it does not collide with the snake anymore. Used after the fruit is picked up. fruit_pickup(): Used to control if the snake is able to pick up the fruit. If the snake is able to pick the fruit up, the snake will grow and the fruit will be moved to a new position. check_if_inside_window(): Used to control whether the snake is inside the boundaries of the screen or not. If the snake is not inside the boundaries, the game is over. run_game_logic(): The main function used to run the game logic. Makes sure that all other functions are called as they should. game_loop(): The entry point of the game. Clears the screen, runs the game logic, and make sure that the screen is presented at the end. update_move(): Function to update the movement and control if the snake collides with itself. """ #pylint: disable=no-member def __init__(self, background_colour, width, height): """Initialize the game. The parameters are passed on to the init function of Window Parameters: ------------------------------------------ colour : list(int, int, int) A triple of values between 0 and 255 indicating the r, g, b value of the rectangle top_left : tuple(int, int) The x- and y-coordinates for the top left corner of the rectangle size : tuple(int, int) The width and height of the rectangle """ self.window = Window(background_colour, width, height) self.snake_size = (30, 30) self.snake = Snake((width//2, height//2), self.snake_size, (75, 75, 75)) self.current_movement = Snake.move_up self.fruit_coordinates = (0, 0) self.fruit_size = (30, 30) self.running = True self.last_update_time = pygame.time.get_ticks() def handle_keydown(self, event): """Handle key input from the user. Check if the key pressed is any of the keys used to control the snake, that is any of the WASD-keys or the arrow keys, or ESC for quiting the game. If any of the WASD-keys or arrow keys are pressed, change direction of the snake to the appropiate direction. Parameters: event : pygame.event An event containing a pressed key. """ pressed_key = event.key if pressed_key in (pygame.K_a, pygame.K_LEFT): self.current_movement = Snake.move_left elif pressed_key in (pygame.K_d, pygame.K_RIGHT): self.current_movement = Snake.move_right elif pressed_key in (pygame.K_w, pygame.K_UP): self.current_movement = Snake.move_up elif pressed_key in (pygame.K_s, pygame.K_DOWN): self.current_movement = Snake.move_down elif pressed_key == pygame.K_ESCAPE: self.running = False def draw(self): """Makes sure all the components of the game are presented on the screen.""" self.window.draw_rect( (255, 0, 0), self.fruit_coordinates, self.fruit_size ) for part in self.snake: coordinates = part.get_coordinates() size = part.get_size() colour = part.get_colour() self.window.draw_rect( colour, coordinates, size ) def move_fruit(self): """ Randomly moves the fruit until it does not collide with the snake anymore. Used after the fruit is picked up. """ while True: screen_size = (self.window.width(), self.window.height()) new_x = randrange(0, screen_size[0] - self.fruit_size[0], self.fruit_size[0]) new_y = randrange(0, screen_size[1] - self.fruit_size[1], self.fruit_size[1]) self.fruit_coordinates = (new_x, new_y) position_ok = True if self.snake.check_collision(self.fruit_coordinates, self.fruit_size): position_ok = False if position_ok: break def fruit_pickup(self): """ Used to control if the snake is able to pick up the fruit. If the snake is able to pick the fruit up, the snake will grow and the fruit will be moved to a new position. """ if self.snake.check_collision_with_fruit(self.fruit_coordinates, self.fruit_size): self.move_fruit() self.snake.grow() def is_inside_window(self): """ Used to control whether the snake is inside the boundaries of the screen or not. If the snake is not inside the boundaries, the game is over. Return: bool True: Inside window False: Not inside window """ screen_size = (self.window.width(), self.window.height()) if self.snake.inside_bounds( (0, 0), (screen_size[0] - self.snake_size[0], screen_size[1] - self.snake_size[1])): return True return False def update_move(self): """ Function to update the movement and control if the snake collides with itself. Called through a pygame registered event. """ self.current_movement(self.snake) if self.snake.check_collision_with_self() or not self.is_inside_window(): self.running = False def run_game_logic(self): """ The entry point of the game. Clears the screen, runs the game logic, and make sure that the screen is presented at the end. """ for event in pygame.event.get(): if event.type == pygame.QUIT: self.running = False elif event.type == pygame.KEYDOWN: self.handle_keydown(event) time_since_update = pygame.time.get_ticks() - self.last_update_time if time_since_update > 150: self.last_update_time = pygame.time.get_ticks() self.update_move() self.fruit_pickup() self.draw() def game_loop(self): """ The main loop of the game. Will continue to play until running is set to false. """ self.running = True while self.running: self.window.clear() self.run_game_logic() pygame.display.flip()