如何使怪物在游戏中随机移动

时间:2019-12-13 17:50:51

标签: python python-3.x pygame

我对编程还很陌生,通过一个教程创建了一个迷宫游戏,我也添加了它。一切都很好,但是我现在想添加一个或两个怪物使其更具挑战性!我只想保持简单,让怪物随机在迷宫中移动。我创建了一个怪物,但是尽管尝试了不同的方法,它仍然不会移动。我怀疑我需要在主循环中添加一些内容,但我不知道是什么。代码如下。任何帮助表示赞赏!

import os
import random
import pygame

os.environ['SDL_VIDEO_CENTERED'] = '1'
#Initalise pygame
pygame.init()

#Colours required
black = (0,0,0)
blue = (0,0,255)
green = (0,255,0)
red = (255,0,0)
orange = (255,200,0)

#Set up the display
width = 640
height = 480
screen = pygame.display.set_mode((width, height))
background = pygame.image.load('path.png')
caption = pygame.display.set_caption('Escape from the mazes!')
clock = pygame.time.Clock()

#Class for the player rect
class Player(object):
    def __init__(self, pos):
        self.rect = pygame.Rect(pos[0], pos[1], 32, 32) #x-axis, y-axis, width, height
        self.image = pygame.image.load('player.png')

    def move(self, dx, dy):
        #Move each axis separately. NB this checks for collisions both times
        if dx != 0:
            self.move_single_axis(dx, 0)
        if dy != 0:
            self.move_single_axis(0, dy)

    def move_single_axis(self, dx, dy):
        #Move the rect
        self.rect.x += dx
        self.rect.y += dy

        #If you collide with a wall, move out based on velocity
        for wall in walls:
            if self.rect.colliderect(wall.rect):
                if dx > 0: #Moving right, hit the left side of wall
                    self.rect.right = wall.rect.left
                if dx < 0: #Moving left, hit the right side of wall
                    self.rect.left = wall.rect.right
                if dy > 0: #Moving down, hit the top side of wall
                    self.rect.bottom = wall.rect.top
                if dy < 0: #Moving up, hit the bottom side of wall
                    self.rect.top = wall.rect.bottom

#Class for the monster rect
class Monster(object):
    def __init__(self, pos):
        self.rect = pygame.Rect(pos[0], pos[1], 32, 32)
        self.direction = random.randint(1,4)
        self.dist = 3
        #self.moves = random.randint(100,200)
        #self.moveCount = 0

    def move(self, x, y):
        xMove, yMove = 0,0

        if self.direction == 1:
            xMove = -self.dist
        elif self.direction == 2:
            yMove = -self.dist
        elif self.direction == 3:
            xMove = self.dist
        elif self.direction == 4:
            yMove = self.dist

        self.rect.move_ip(xMove, yMove)
        #self.moveCount += 1

        for wall in walls:
            if self.rect.colliderect(wall.rect):
                if x > 0: #Moving right, hit the left side of wall
                    self.rect.right = wall.rect.left
                if x < 0: #Moving left, hit the right side of wall
                    self.rect.left = wall.rect.right
                if y > 0: #Moving down, hit the top side of wall
                    self.rect.bottom = wall.rect.top
                if y < 0: #Moving up, hit the bottom side of wall
                    self.rect.top = wall.rect.bottom
                self.rect.move_ip(-xMove, -yMove)
                self.direction = random.randint(1,4)

#Class for the wall rect
class Wall(object):
    def __init__(self, pos):
        self.rect = pygame.Rect(pos[0], pos[1], 32, 32)
        self.image = pygame.image.load('hedge.png')

#Class for end rect
class Finish(object):
    def __init__(self, pos):
        self.rect = pygame.Rect(pos[0], pos[1], 32, 32)
        self.image = pygame.image.load('gate.png')

#Variables
currentLevel = 0

#Holds the level layout in a list of strings
levels = [[
'WWWWWWWWWWWWWWWWWWWW',
'WP          W      W',
'W         WWWWWW   W',
'W   WWWW       W   W',
'W   W        WWWW  W',
'W WWW  WWWW        W',
'W   W    MW W      W',
'W   W     W   WWW WW',
'W   WWW WWW   W W  W',
'W     W   W   W W  W',
'WWW   W   WWWWW W  W',
'W W      WW        W',
'W W   WWWW   WWWWWWW',
'W     W           FW',
'WWWWWWWWWWWWWWWWWWWW',
],
[
'WWWWWWWWWWWWWWWWWWWW',
'W W     W     W   FW',
'W W     W     W    W',
'W W  W  W  W  W  WWW',
'W W  W  W  W  W    W',
'W W  W  W  W  W    W',
'W W  W  W  W  W  W W',
'W    W     W  W  W W',
'W    W     W  W  WWW',
'WWW  WWWWWWW  W    W',
'W      W      W    W',
'W      W  WWWWWWW  W',
'WWWWW  W           W',
'WP     W           W',
'WWWWWWWWWWWWWWWWWWWW',
],
[
'WWWWWWWWWWWWWWWWWWWW',
'WP W           W   W',
'W  W  WWWW  WWWW W W',
'W  W     W       W W',
'W  WWWW  W    WWWW W',
'W     W  W  WW     W',
'W     W  W  W  WWWWW',
'WWWW  W  W  W     FW',
'W  W  W  W  WWWWWWWW',
'W  W     W         W',
'W  W     W         W',
'W  W  WWWWWWWWWWW  W',
'W               W  W',
'W               W  W',
'WWWWWWWWWWWWWWWWWWWW',
],
[
'WWWWWWWWWWWWWWWWWWWW',
'W     W            W',
'W     W            W',
'W  W  W  WWWWWWWW  W',
'W  W  W  W         W',
'W  W  W  W         W',
'W  W  W  W  WWWWWWWW',
'WP W  W  W         W',
'WWWW  W  W         W',
'W     W  WWWWWWWW  W',
'W     W  W         W',
'W  WWWW  W         W',
'W        W  WWWWWWWW',
'W        W        FW',
'WWWWWWWWWWWWWWWWWWWW',
],
[
'WWWWWWWWWWWWWWWWWWWW',
'W  W        W     FW',
'W  W        WWW W  W',
'W  W  WWWW    W WWWW',
'W  W     W    W    W',
'W  WWWW  WWWW W  W W',
'W     W     W WWWW W',
'W     W     W      W',
'W  W  WWWW  WWWWWWWW',
'W  W     W         W',
'W  W     W         W',
'WWWW  W  WWWWWWWW  W',
'W     W            W',
'WP    W            W',
'WWWWWWWWWWWWWWWWWWWW',
],
[
'WWWWWWWWWWWWWWWWWWWW',
'WP     W     W   W W',
'WWWWW  W     W W W W',
'W  W  W  WWWWWWW W W',
'W W  W   W         W',
'WW  W  W W WWWWW   W',
'W  W   W W     W WWW',
'W  WWWWW WWWWW W WFW',
'W      W       W W W',
'WWWWWW W WWWWWWW W W',
'W      W W       W W',
'W W  WWW W       W W',
'W W      W WWWWWWW W',
'W W      W         W',
'WWWWWWWWWWWWWWWWWWWW',
]]

def load_level(level):
    walls = []
    players = []
    monsters = []
    finishes = []

    #Parse the level string above. W = wall, F = exit, P = player
    x = y = 0
    for row in levels[level]:
        for col in row:
            if col == 'W':
                walls.append(Wall((x, y)))
            if col == 'P':
                players.append(Player((x, y)))
            if col == 'M':
                monsters.append(Monster((x, y)))
            if col == 'F':
                finishes.append(Finish((x, y)))
            x += 32
        y += 32
        x = 0
    return walls, players, monsters, finishes

walls, players, monsters, finishes = load_level(currentLevel)
Highest_level = len(levels)-1 #index of last level

def text_objects(text, font):
    textSurface = font.render(text, True, black)
    return textSurface, textSurface.get_rect()

def win():
    screen.fill(blue)
    largeText = pygame.font.Font('freesansbold.ttf', 95)
    TextSurf, TextRect = text_objects('You Escaped!', largeText)
    TextRect.center = (int((width/2)), int((height/2)))
    screen.blit(TextSurf, TextRect)

    while True:
        for e in pygame.event.get():
            if e.type == pygame.QUIT:
                pygame.quit()
                quit()

        pygame.display.update()
        clock.tick(15)

running = True
while running:
    clock.tick(60)
    for e in pygame.event.get():
        if e.type == pygame.QUIT:
            pygame.quit()
            quit()
        if e.type == pygame.KEYDOWN and e.key == pygame.K_ESCAPE:
            pygame.quit()
            quit()

    #Move the player if an arrow key is pressed
    key = pygame.key.get_pressed()
    if key[pygame.K_LEFT]:
        player.move(-2, 0)
    if key[pygame.K_RIGHT]:
        player.move(2, 0)
    if key[pygame.K_UP]:
        player.move(0, -2)
    if key[pygame.K_DOWN]:
        player.move(0, 2)

    #Moving to next level/win
    for player in players:
        for finish in finishes:
            if player.rect.colliderect(finish.rect):
                if currentLevel < Highest_level:
                    currentLevel +=1
                    walls, players, monsters, finishes = load_level(currentLevel)
                else:
                    win()

    #Draw the scene
    screen.fill(blue)
    screen.blit(background, (0,0))
    for wall in walls:
        #pygame.draw.rect(screen, green, wall.rect)
        screen.blit(wall.image, wall.rect)
    for player in players:
        #pygame.draw.rect(screen, orange, player.rect)
        screen.blit(player.image, player.rect)
    for monster in monsters:
        pygame.draw.rect(screen, blue, monster.rect)
    for finish in finishes:
        #pygame.draw.rect(screen, red, finish.rect)
        screen.blit(finish.image, finish.rect)
    pygame.display.update()

1 个答案:

答案 0 :(得分:2)

为主应用程序循环中的每个怪物调用方法move。但请注意,该方法不需要任何参数:

while running:

  # [...]

  #Moving to next level/win
  # [...]

  # Move monster
  for monster in monsters:
      monster.move()

此外,您还必须在类Monster中进行Som更改。

direction索引映射到方向矢量(dxdy)并通过矢量更改怪物的位置:

direction_list = ((-1, 0), (1, 0), (0, -1), (0, 1))
dx, dy = direction_list[self.direction]
self.rect.x += dx
self.rect.y += dy

当怪物撞到墙壁时,在range(0, 3)中创建一个新的随机方向。创建一个随机数steps,并在怪物移动时递减。当步数为0时更改方向,并创建一个新的随机数。步骤数应为32的倍数,因为这是一个图块的长度:

#Class for the monster rect
class Monster(object):
    def __init__(self, pos):
        self.rect = pygame.Rect(pos[0], pos[1], 32, 32)
        self.dist = 3
        self.direction = random.randint(0, 3)
        self.steps = random.randint(3, 6) * 32

    def move(self):
        direction_list = ((-1, 0), (1, 0), (0, -1), (0, 1))
        dx, dy = direction_list[self.direction]
        self.rect.x += dx
        self.rect.y += dy

        #If you collide with a wall, move out based on velocity
        collide = False
        for wall in walls:
            if self.rect.colliderect(wall.rect):
                collide = True

                if dx > 0: #Moving right, hit the left side of wall
                    self.rect.right = wall.rect.left
                if dx < 0: #Moving left, hit the right side of wall
                    self.rect.left = wall.rect.right
                if dy > 0: #Moving down, hit the top side of wall
                    self.rect.bottom = wall.rect.top
                if dy < 0: #Moving up, hit the bottom side of wall
                    self.rect.top = wall.rect.bottom

        self.steps -= 1
        if collide or self.steps == 0:
            # new random direction
            self.direction = random.randint(0, 3)
            self.steps = random.randint(3, 6) * 32