问题
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