我的NPC不会追逐我的玩家或对碰撞做出反应

时间:2018-09-28 08:12:19

标签: python pygame

我是编码的新手,我最近一直在尝试制作2D平台游戏,但遇到了一个我似乎无法解决的问题,我的NPC不会跟随玩家,也不会它对碰撞做出反应,欢迎任何帮助。

我还一直在考虑创建一种算法,该算法将按程序在平台框中生成我的关卡,并将退出块放置在关卡中的其他位置,我该如何存档?

import pygame    #imports pygame
import time    #imports the timer so I can use the tick function to make game 60fps
import math    #imports maths
import sys    #imports system
from pygame import *    #imports all pygame files
from pygame.math import *
from pygame.mixer 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()
pygame.mixer.music.load('Toby Fox - Megalovania [Electro Swing Remix].mp3')
pygame.mixer.music.play(-1)


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 = Surface((32,32))    #the background takes up space on the screen
    background.convert()
    background.fill(Color("#000000"))    #background is black
    entities = pygame.sprite.Group()
    player = Player_class(32, 32)    #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)

    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: raise SystemExit ("QUIT")
            if e.type == KEYDOWN and e.key == K_ESCAPE:
                pygame.quit()
                sys.exit()
                raise SystemExit ("ESCAPE")
            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        


        for y in range(32):    #draws the background
            for x in range(32):
                screen.blit(background, (x * 32, y * 32))

        #updates the player and draws everything else
        player.update(up, down, left, right, running, platforms)
        entities.draw(screen)
        pygame.display.update()

        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
        enemy_list.draw(screen)
        for e in enemy_list:
            e.move()
        pygame.display.flip()


"""
        enemysprite.draw(screen)
        enemysprite.update()
        enemy.move_towards_player(player)
"""
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 = Surface((32,32))    #the player is 32*32 pixels
        self.image.fill(Color("#0000FF"))    #makes the player blue
        self.image.convert()
        self.rect = 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
                    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


class Platform(Entity):    #defines the platform class
    def __init__(self, x, y):
        Entity.__init__(self)    #platform is an entity
        self.image = Surface((32, 32))    #platforms are 32*32 pixels
        self.image.convert()
        self.image.fill(Color("#FFFFFF"))    #platforms are white
        self.rect = Rect(x, y, 32, 32)    #platforms, like many things in this game, are rectangles

    def update(self):
        pass

class Exit_block(Platform):    #defines the exit block class
    def __init__(self, x, y):
        Platform.__init__(self, x, y)
        self.image.fill(Color("#FF0000"))#exit block is red
"""
class Enemy(pygame.sprite.Sprite):
    def __init__(self, image_file, pos=(0,0)):
        super(Enemy, self).__init__()
        self.image = (32, 32)
        self.image.fill(color("00FF00"))
        self.rect = Rect(x, y, 32, 32)
        self.speed = 1

    def move_towards_player(self, Player):
        dx, dy = self.rect.x - Player.rect.x, self.rect.y - Player.rect.y
        dist = math.hypot(dx, dy)
        dx, dy = dx/dist, dy/dist
        self.rect.x += dx * self.speed
        self.rect.y += dy * self.speed
"""


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("#00FF00"))    #Enemy is green
        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.x:    # Movement along x direction
            self.rect.x -= speed
        elif self.rect.x < self.player.x:
            self.rect.x += speed
        if self.rect.y < self.player.y:    # Movement along y direction
            self.rect.y += speed
        elif self.rect.y > self.player.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)

"""
class Enemy(Entity):
    def __init__(self,x,y):  # initial position
        self.x = x 
        self.y = y
    def move(self, speed=5): # chase movement
        # Movement along x direction
        if self.x > px:
            self.x -= speed
        elif self.x < px:
            self.x += speed
        # Movement along y direction
        if self.y < py:
            self.y += speed
        elif self.y > py:
            self.y -= speed
"""
class Vector:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __add__(self, other):
        return Vector(self.x + other.x, self.y + othery)

    def __sub__(self, other):
        return Vector(self.x - other.x, self.y  - other.y)

    def __mul__(self, scalar):
        return Vector(self.x * scalar, self.y * scalar)

    def __div__(self, scalar):
        return Vector(self.x / scalar, self.y / scalar)

    def length(self):
        return ((self.x ** x) + (self.y ** 2)) ** 0.5

    def normal(self):
        return self / self.length()






class Camera(object):
    def __init__(self, Player_class):
        self.left_viewbox = display_width/2 - display_width/8
        self.right_viewbox = display_width/2 + display_width/10

    def follow(self, shift_x):
        virtualwindow.x += shift_x
        print (virtualwindow.x)
        for i in Player_class:   
            i.rect.x += shift_x

    def viewbox(self):
        if player.x <= self.left_viewbox:
            view_difference = self.left_viewbox - player.x
            player.x = self.left_viewbox
            self.follow(view_difference)

        if player.x >= self.right_viewbox:
            view_difference = self.right_viewbox - player.x
            player.x = self.right_viewbox
            self.follow(view_difference)
"""
class Camera(object):
    def __init__(self, camera_func, win_width, win_height):
        self.camera_func = camera_func
        self.state = rect(0, 0, win_width, win_height)

    def apply(self, target):
        self.state = self.camera_func(self.state, target.rect)

    def simple_camera(camera, target_rect):
        def __init__(self, Camera, camera_func, win_width, win_height):
            pass
"""        

if __name__ == "__main__":
    main()

1 个答案:

答案 0 :(得分:1)

第一个问题是,您总是在相同的坐标处创建新的enemy实例,而在while循环中始终在创建新的enemy_list。您应该在while循环之前创建一个精灵组和一个精灵:

enemy = Enemy(60, 200, player)
enemy_list = pygame.sprite.Group()
enemy_list.add(enemy)

while 1:

第二个问题是您在self.player.x的{​​{1}}方法中使用了.ymove属性,但实际上它们从未在Enemy,您只能移动播放器的Player_class。因此,请改用self.rectself.player.rect.x属性:

.y