敌方 AI 碰撞检测不起作用



我的敌人AI没有检测到碰撞。我一直在使用用于玩家碰撞检测的代码。我调整了它以适应敌人,但它不起作用:

class Enemy(Entity):
def __init__(self, x, y,player):
pygame.sprite.Sprite.__init__(self)
self.image = Surface((32, 32))
self.xvel = 0
self.yvel = 0
self.image.fill(Color("#FF0000"))    #Enemy is red
self.onGorund = False
#Enemy is 32 * 32 pixels
self.image.convert()
self.rect = Rect(x, y, 32, 32)
self.counter = 0    #counter variable
self.player = player

def move(self, speed = 5):    # chase movement
if self.rect.x > self.player.rect.x:    # Movement along x direction 
self.rect.x -= speed
elif self.rect.x < self.player.rect.x:
self.rect.x += speed
if self.rect.y < self.player.rect.y:    # Movement along y direction
self.rect.y += speed
elif self.rect.y > self.player.rect.y:
self.rect.y -= speed
def collide(self, xvel, yvel, platforms):
for p in platforms:
if pygame.sprite.collide_rect(self, p):
if isinstance(p, Player_class):
pygame.quit()
sys.exit()
if xvel > 0:
self.rect.right = p.rect.left
print ("collide right")
if xvel < 0:
self.rect.left = p.rect.right
print ("collide left")
if yvel > 0:
self.rect.bottom = p.rect.top
self.onGround = True
self.yvel = 0
if yvel < 0:
self.rect.top = p.rect.bottom
def update(self, platforms):
if up:
if self.onGround: self.yvel -= 10    #only jump if player is on the ground
if down:
pass
if running:
self.xvel = 12
if left:
self.xvel = -8
if right:
self.xvel = 8
if not self.onGround:
self.yvel += 0.3    #only accelerate with gravity if in the air
if self.yvel > 100: self.yvel = 100    #terminal velocity = 100
if not(left or right):
self.xvel = 0
self.rect.left += self.xvel    #falls or jumps
self.collide(self.xvel, 0, platforms)    #creates collisions along the x axis
self.rect.top += self.yvel    #creates collisions along the y axis
self.onGround = False;    #assumes that the player is in the air
# do y-axis collisions
self.collide(0, self.yvel, platforms)

我一直试图让窗户在敌人触摸玩家时关闭,问题是,如果敌人不知道它正在触摸玩家,它就无法关闭窗口。请询问是否需要更多代码。

有几件事需要改变。

  • move方法中,您应该设置速度(self.xvelself.yvel(,而不是直接移动矩形。

  • 然后在update方法中调用move方法,移动精灵的矩形并处理碰撞。另外,你现在需要在main函数中调用update方法,而不是move并传递platforms列表:

    enemy_list.draw(screen)
    for e in enemy_list:
    e.update(platforms)
    
  • 在碰撞方法中,检查其中一个平台是否是播放器实例:

    for p in platforms:
    if pygame.sprite.collide_rect(self, p):
    if isinstance(p, Player_class):
    pygame.quit()
    sys.exit()
    

    但是,玩家角色不在此列表中,因此无法发生冲突。

    敌人实际上有一个对玩家的引用(self.player(,所以你可以这样做来检查他们是否碰撞:

    if pygame.sprite.collide_rect(self, self.player):
    

    或:

    if self.rect.colliderect(self.player.rect):
    

这是一个完整的示例(我从您之前的问题中获取了代码,并尝试改进更多内容(:

import sys
import pygame
from pygame.locals import *

win_height = 750    #height of window is 750 pixles
win_width = 1050    #height of window is 1050 pixels
half_win_width = int(win_width / 2)    #will be used to centre camera
half_win_height = int(win_height / 2)
display = (win_width, win_height)    #creates the window as 500*500 pixels
depth = 32    #prevents infinate recursion
flags = 0    #message to Les: I don't really know what this does, however I have seen it in many places being used, therefore I assumed that it was important
camera_slack = 30    #how many pixels the player can move before the camera moves with them
pygame.init()

def main():    #main game function
global cameraX, cameraY
pygame.init()
screen = pygame.display.set_mode(display, flags, depth)
pygame.display.set_caption("Super Castlevania Man")
timer = pygame.time.Clock()
move_cameraX = 0
move_cameraY = 0
up = down = left = right = running = False
background = pygame.Surface((32,32))    #the background takes up space on the screen
background.convert()
background.fill(pygame.Color("#000000"))    #background is black
entities = pygame.sprite.Group()
player = Player_class(32, 32*15)    #the player is 32*32 pixels large
platforms = []
x = y = 0
level = [
"PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP",
"P                               P",
"P         E                     P",
"P                               P",
"P                    PPPPPPPPP  P",
"P                               P",
"P                               P",
"P                               P",
"P    PPPPPPPP                   P",
"P                               P",
"P                          PPPP P",
"P                 PPPPPP        P",
"P         PPPPPPP               P",
"P                               P",
"P                     PPPPPP    P",
"P                               P",
"P   PPPPPPPPPPP                 P",
"P                               P",
"P                 PPPPPPPPPPP   P",
"P                               P",
"P                               P",
"P                               P",
"P                               P",
"PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP",    
]
#builds the level
for row in level:
for col in row:
if col == "P":
p = Platform(x, y)    #makes P a solid object
platforms.append(p)
entities.add(p)
if col == "E":
e = Exit_block(x, y)
platforms.append(e)
entities.add(e)
x += 32
y += 32
x = 0
entities.add(player)
enemy = Enemy(60, 200, player)    #Spawns enemy
enemy_list = pygame.sprite.Group()    #creates an enemy group
enemy_list.add(enemy)    #Add an enemy to the group
while 1:
timer.tick(60)    #makes game run at 60 frames per second
for e in pygame.event.get():    #shortens event to e
if e.type == QUIT:
return
if e.type == KEYDOWN and e.key == K_ESCAPE:
return
if e.type == KEYDOWN and e.key == K_UP:
up = True
move_cameraY = -10
if e.type == KEYDOWN and e.key == K_DOWN:
down = True
move_cameraY = 10
if e.type == KEYDOWN and e.key == K_LEFT:
left = True
move_cameraX = -10
if e.type == KEYDOWN and e.key == K_RIGHT:
right = True
move_cameraX = 10
if e.type == KEYDOWN and e.key == K_SPACE:
running = True
if e.type == KEYUP and e.key == K_UP:
up = False
move_cameraY = 0
if e.type == KEYUP and e.key == K_DOWN:
down = False
move_cameraY = 0
if e.type == KEYUP and e.key == K_RIGHT:
right = False
move_cameraX = 0
if e.type == KEYUP and e.key == K_LEFT:
left = False
move_cameraX = 0
if e.type == KEYUP and e.key == K_RIGHT:
right = False        
# Update the game.
for e in enemy_list:
e.update(platforms)
player.update(up, down, left, right, running, platforms)
# Draw everything.
for y in range(32):    #draws the background
for x in range(32):
screen.blit(background, (x * 32, y * 32))
entities.draw(screen)
enemy_list.draw(screen)
pygame.display.flip()  # You need only one flip or update call per frame.

class Entity(pygame.sprite.Sprite):    #makes player a sprite
def __init__(self):
pygame.sprite.Sprite.__init__(self)    #sets sprite to initiate

class Player_class(Entity):    #defines player class
def __init__(self, x, y):    #x is the player x coordinate, y is the player y coordinate
Entity.__init__(self)    #the player is an entity
self.xvel = 0    #how fast the player is moving left and right
self.yvel = 0    #how fast the player is moving up and down
self.onGround = False    #assumes the player is in the air
self.image = pygame.Surface((32,32))    #the player is 32*32 pixels
self.image.fill(pygame.Color("#0000FF"))    #makes the player blue
self.rect = pygame.Rect(x, y, 32, 32)
self.x = x
self.y = y
def update(self, up, down, left, right, running, platforms):
if up:
if self.onGround:
self.yvel -= 10    #only jump if player is on the ground
if down:
pass
if running:
self.xvel = 12
if left:
self.xvel = -8
if right:
self.xvel = 8
if not self.onGround:
self.yvel += 0.3    #only accelerate with gravity if in the air
if self.yvel > 100: self.yvel = 100    #terminal velocity = 100
if not(left or right):
self.xvel = 0
self.rect.left += self.xvel    #falls or jumps
self.collide(self.xvel, 0, platforms)    #creates collisions along the x axis
self.rect.top += self.yvel    #creates collisions along the y axis
self.onGround = False;    #assumes that the player is in the air
# do y-axis collisions
self.collide(0, self.yvel, platforms)
def collide(self, xvel, yvel, platforms):
for p in platforms:
if pygame.sprite.collide_rect(self, p):
if isinstance(p, Exit_block):
pygame.quit()
sys.exit()
if xvel > 0:
self.rect.right = p.rect.left
if xvel < 0:
self.rect.left = p.rect.right
if yvel > 0:
self.rect.bottom = p.rect.top
self.onGround = True
self.yvel = 0
if yvel < 0:
self.rect.top = p.rect.bottom

class Platform(Entity):
def __init__(self, x, y):
Entity.__init__(self)
self.image = pygame.Surface((32, 32))
self.image.fill(pygame.Color("#FFFFFF"))
self.rect = pygame.Rect(x, y, 32, 32)

class Exit_block(Platform):
def __init__(self, x, y):
Platform.__init__(self, x, y)
self.image.fill(pygame.Color("#FF7700"))#exit block is orange

class Enemy(Entity):
def __init__(self, x, y,player):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface((32, 32))
self.xvel = 0
self.yvel = 0
self.image.fill(pygame.Color("#FF0000"))    #Enemy is red
self.rect = pygame.Rect(x, y, 32, 32)
self.player = player
def move(self, speed=5):    # chase movement
if self.rect.x > self.player.rect.x:    # Movement along x direction 
self.xvel = -speed
elif self.rect.x < self.player.rect.x:
self.xvel = speed
if self.rect.y < self.player.rect.y:    # Movement along y direction
self.yvel = speed
elif self.rect.y > self.player.rect.y:
self.yvel = -speed
def collide(self, xvel, yvel, platforms):
# Check if the enemy collides with the player.
if self.rect.colliderect(self.player.rect):
pygame.quit()
sys.exit()
for p in platforms:
if pygame.sprite.collide_rect(self, p):
if xvel > 0:
self.rect.right = p.rect.left
if xvel < 0:
self.rect.left = p.rect.right
if yvel > 0:
self.rect.bottom = p.rect.top
if yvel < 0:
self.rect.top = p.rect.bottom
def update(self, platforms):
self.move()  # Set the velocity.
self.rect.left += self.xvel
self.collide(self.xvel, 0, platforms)    #creates collisions along the x axis
self.rect.top += self.yvel    #creates collisions along the y axis
self.collide(0, self.yvel, platforms)

if __name__ == "__main__":
main()
pygame.quit()

最新更新