Creating a teammate for Pacman In python Pygame

人盡茶涼 提交于 2021-01-07 06:31:18

问题


Im currently making a pacman styled game using pygame and im trying to create an AI controlled teammate that can move around a maze, But im struggling on how to actually do it, i thought i could use my player class as a guide and edit things to make it work but i had no luck (made a new class so it didnt actually interfere with my game) does anyone have any ideas. all i need is a simple teammate that just wonders around, it doesnt have to collect the coins to add to the score just avoid walking straight at a wall and stopping moving.

Player Class(teammate class):

    import pygame
    from settings import *
    vec = pygame.math.Vector2


    class Player:
        def __init__(self, app, pos):
            self.app = app
            self.starting_pos = [pos.x, pos.y]
            self.grid_pos = pos
            self.pix_pos = self.get_pix_pos()
            self.direction = vec(1, 0)
            self.stored_direction = None
            self.able_to_move = True
            self.current_score = 0
            self.speed = 2.5
            self.lives = 1

        def update(self):
            if self.able_to_move:
                self.pix_pos += self.direction*self.speed
            if self.time_to_move():
                if self.stored_direction != None:
                    self.direction = self.stored_direction
                self.able_to_move = self.can_move()
            # Setting grid position in reference to pix pos
            self.grid_pos[0] = (self.pix_pos[0]-TOP_BOTTOM_BUFFER +
                                self.app.cell_width//2)//self.app.cell_width+1
            self.grid_pos[1] = (self.pix_pos[1]-TOP_BOTTOM_BUFFER +
                                self.app.cell_height//2)//self.app.cell_height+1
            if self.on_coin():
                self.eat_coin()

        def draw(self):
            pygame.draw.circle(self.app.screen, PLAYER_COLOUR, (int(self.pix_pos.x),
                                                                int(self.pix_pos.y)), self.app.cell_width//2-2)

            # Drawing player lives
            for x in range(self.lives):
                pygame.draw.circle(self.app.screen, PLAYER_COLOUR, (30 + 20*x, HEIGHT - 15), 7)


        def on_coin(self):
            if self.grid_pos in self.app.coins:
                if int(self.pix_pos.x+TOP_BOTTOM_BUFFER//2) % self.app.cell_width == 0:
                    if self.direction == vec(1, 0) or self.direction == vec(-1, 0):
                        return True
                if int(self.pix_pos.y+TOP_BOTTOM_BUFFER//2) % self.app.cell_height == 0:
                    if self.direction == vec(0, 1) or self.direction == vec(0, -1):
                        return True
            return False

        def eat_coin(self):
            self.app.coins.remove(self.grid_pos)
            self.current_score += 20

        def move(self, direction):
            self.stored_direction = direction

        def get_pix_pos(self):
            return vec((self.grid_pos[0]*self.app.cell_width)+TOP_BOTTOM_BUFFER//2+self.app.cell_width//2,
                       (self.grid_pos[1]*self.app.cell_height) +
                       TOP_BOTTOM_BUFFER//2+self.app.cell_height//2)

            print(self.grid_pos, self.pix_pos)

        def time_to_move(self):
            if int(self.pix_pos.x+TOP_BOTTOM_BUFFER//2) % self.app.cell_width == 0:
                if self.direction == vec(1, 0) or self.direction == vec(-1, 0) or self.direction == vec(0, 0):
                    return True
            if int(self.pix_pos.y+TOP_BOTTOM_BUFFER//2) % self.app.cell_height == 0:
                if self.direction == vec(0, 1) or self.direction == vec(0, -1) or self.direction == vec(0, 0):
                    return True

        def can_move(self):
            for wall in self.app.walls:
                if vec(self.grid_pos+self.direction) == wall:
                    return False
            return True

App Class (Holds Other info used by player class):

    import pygame
    import sys
    import copy
    from settings import *
    from player_class import *
    from enemy_class import *


    pygame.init()
    vec = pygame.math.Vector2


    class App:
        def __init__(self):
            self.screen = pygame.display.set_mode((WIDTH, HEIGHT))
            self.clock = pygame.time.Clock()
            self.running = True
            self.state = 'start'
            self.cell_width = MAZE_WIDTH//COLS
            self.cell_height = MAZE_HEIGHT//ROWS
            self.walls = []
            self.coins = []
            self.enemies = []
            self.e_pos = []
            self.p_pos = None
            self.load()
            self.player = Player(self, vec(self.p_pos))
            self.make_enemies()

        def run(self):
            while self.running:
                if self.state == 'start':
                    self.start_events()
                    self.start_update()
                    self.start_draw()
                elif self.state == 'playing':
                    self.playing_events()
                    self.playing_update()
                    self.playing_draw()
                elif self.state == 'game over':
                    self.game_over_events()
                    self.game_over_update()
                    self.game_over_draw()
                else:
                    self.running = False
                self.clock.tick(FPS)
            pygame.quit()
            sys.exit()

    ############################ HELPER FUNCTIONS ##################################

        def draw_text(self, words, screen, pos, size, colour, font_name, centered=False):
            font = pygame.font.SysFont(font_name, size)
            text = font.render(words, False, colour)
            text_size = text.get_size()
            if centered:
                pos[0] = pos[0]-text_size[0]//2
                pos[1] = pos[1]-text_size[1]//2
            screen.blit(text, pos)

        def load(self):
            self.background = pygame.image.load('maze.png')
            self.background = pygame.transform.scale(self.background, (MAZE_WIDTH, MAZE_HEIGHT))

            # Opening walls file
            # Creating walls list with co-ords of walls
            # stored as  a vector
            with open("walls.txt", 'r') as file:
                for yidx, line in enumerate(file):
                    for xidx, char in enumerate(line):
                        if char == "1":
                            self.walls.append(vec(xidx, yidx))
                        elif char == "C":
                            self.coins.append(vec(xidx, yidx))
                        elif char == "P":
                            self.p_pos = [xidx, yidx]
                        elif char in ["2", "3", "4", "5"]:
                            self.e_pos.append([xidx, yidx])
                        elif char == "B":
                            pygame.draw.rect(self.background, BLACK, (xidx*self.cell_width, yidx*self.cell_height,
                                                                      self.cell_width, self.cell_height))

        def make_enemies(self):
            for idx, pos in enumerate(self.e_pos):
                self.enemies.append(Enemy(self, vec(pos), idx))

        def draw_grid(self):
            for x in range(WIDTH//self.cell_width):
                pygame.draw.line(self.background, GREY, (x*self.cell_width, 0),
                                 (x*self.cell_width, HEIGHT))
            for x in range(HEIGHT//self.cell_height):
                pygame.draw.line(self.background, GREY, (0, x*self.cell_height),
                                 (WIDTH, x*self.cell_height))

        def reset(self):
            self.player.lives = 3
            self.player.current_score = 0
            self.player.grid_pos = vec(self.player.starting_pos)
            self.player.pix_pos = self.player.get_pix_pos()
            self.player.direction *= 0
            for enemy in self.enemies:
                enemy.grid_pos = vec(enemy.starting_pos)
                enemy.pix_pos = enemy.get_pix_pos()
                enemy.direction *= 0

            self.coins = []
            with open("walls.txt", 'r') as file:
                for yidx, line in enumerate(file):
                    for xidx, char in enumerate(line):
                        if char == 'C':
                            self.coins.append(vec(xidx, yidx))
            self.state = "playing"


    ########################### INTRO FUNCTIONS ####################################

        def start_events(self):
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    self.running = False
                if event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE:
                    self.state = 'playing'

        def start_update(self):
            pass

        def start_draw(self):
            self.screen.fill(BLACK)
            self.draw_text('PUSH SPACE BAR TO PLAY', self.screen, [
                           WIDTH//2, HEIGHT//2-50], START_TEXT_SIZE, (242, 255, 0), START_FONT, centered=True)
            self.draw_text('1 PLAYER ONLY', self.screen, [
                           WIDTH//2, HEIGHT//2+50], START_TEXT_SIZE, (44, 167, 198), START_FONT, centered=True)
            self.draw_text('CREATED BY CALLUM FAWCETT', self.screen, [
                           WIDTH//2, HEIGHT//2+150], START_TEXT_SIZE, (208, 22, 22), START_FONT, centered=True)
            self.draw_text('HIGH SCORE', self.screen, [4, 0],
                           START_TEXT_SIZE, (255, 255, 255), START_FONT)
            pygame.display.update()

    ########################### PLAYING FUNCTIONS ##################################

        def playing_events(self):
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    self.running = False
                if event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_LEFT:
                        self.player.move(vec(-1, 0))
                    if event.key == pygame.K_RIGHT:
                        self.player.move(vec(1, 0))
                    if event.key == pygame.K_UP:
                        self.player.move(vec(0, -1))
                    if event.key == pygame.K_DOWN:
                        self.player.move(vec(0, 1))

        def playing_update(self):
            self.player.update()
            for enemy in self.enemies:
                enemy.update()

            for enemy in self.enemies:
                if enemy.grid_pos == self.player.grid_pos:
                    self.remove_life()

        def playing_draw(self):
            self.screen.fill(BLACK)
            self.screen.blit(self.background, (TOP_BOTTOM_BUFFER//2, TOP_BOTTOM_BUFFER//2))
            self.draw_coins()
            self.draw_text('CURRENT SCORE: {}'.format(self.player.current_score),
                           self.screen, [60, 0], 18, WHITE, START_FONT)
            self.draw_text('HIGH SCORE: 0', self.screen, [WIDTH//2+60, 0], 18, WHITE, START_FONT)
            self.player.draw()
            for enemy in self.enemies:
                enemy.draw()
            pygame.display.update()

        def remove_life(self):
            self.player.lives -= 1
            if self.player.lives == 0:
                self.state = "game over"
            else:
                self.player.grid_pos = vec(self.player.starting_pos)
                self.player.pix_pos = self.player.get_pix_pos()
                self.player.direction *= 0
                for enemy in self.enemies:
                    enemy.grid_pos = vec(enemy.starting_pos)
                    enemy.pix_pos = enemy.get_pix_pos()
                    enemy.direction *= 0

        def draw_coins(self):
            for coin in self.coins:
                pygame.draw.circle(self.screen, (255, 0, 191),
                                   (int(coin.x*self.cell_width)+self.cell_width//2+TOP_BOTTOM_BUFFER//2,
                                    int(coin.y*self.cell_height)+self.cell_height//2+TOP_BOTTOM_BUFFER//2), 5)

    ########################### GAME OVER FUNCTIONS ################################

        def game_over_events(self):
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    self.running = False
                if event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE:
                    self.reset()
                if event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE:
                    self.running = False

        def game_over_update(self):
            pass

        def game_over_draw(self):
            self.screen.fill(BLACK)
            quit_text = "Press the escape button to QUIT"
            again_text = "Press SPACE bar to PLAY AGAIN"
            self.draw_text("GAME OVER", self.screen, [WIDTH//2, 100],  52, RED, "arial", centered=True)
            self.draw_text(again_text, self.screen, [
                           WIDTH//2, HEIGHT//2],  36, (190, 190, 190), "arial", centered=True)
            self.draw_text(quit_text, self.screen, [
                           WIDTH//2, HEIGHT//1.5],  36, (190, 190, 190), "arial", centered=True)
            pygame.display.update()

来源:https://stackoverflow.com/questions/65289867/changing-enemy-class-to-teammate-class-pacman-pygame

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!