使子弹朝玩家面对的方向发射

2024-09-27 09:31:17 发布

您现在位置:Python中文网/ 问答频道 /正文

我刚刚得到一些帮助,想知道如何让我的玩家发射子弹,这时我意识到它们只能发射(这有点像预期的,但因为只有y值的运动)。我不知道怎样才能让子弹朝玩家面对的方向发射

我有一些想法,但我只是不知道怎么做。。。我想我可以用这个游戏中的光标和玩家跟踪作为视觉效果,但我不知道如何让它成为一个一次性的东西,而不是一个常量。关于子弹的对角线运动,我不知道

代码如下(分为两部分/文件Main.py和PlayerSprite.py):

Main:

py.init()
py.mixer.init()
screen = py.display.set_mode((WIDTH, HEIGHT))
py.display.set_caption("Dimensional Drifter")
clock = py.time.Clock()

all_sprites = py.sprite.Group()
NPCs = py.sprite.Group()
bullets = py.sprite.Group()
player = Player()
all_sprites.add(player)
for i in range(14):
    n = NPC(player)
    all_sprites.add(n)
    NPCs.add(n)
# Game loop
running = True
while running:
    # keep loop running at the right speed
    clock.tick(FPS)

    for event in py.event.get():
        # check for closing window
        if event.type == py.QUIT:
            running = False
        elif event.type == py.KEYDOWN:
            if event.key == py.K_SPACE:
                New_bullet = player.Shoot()
                all_sprites.add(New_bullet)
                bullets.add(New_bullet)

    # Update
    all_sprites.update()
    # # check if there a collision between the bullet and NPC
    hits = py.sprite.groupcollide(NPCs, bullets, True, True)
    # check if there a collision between the player and NPC
    hits = py.sprite.spritecollide(player, NPCs, True)
    if hits:
        running = False

    # updates the position of of mouse and rotates it towards the mouse position
    mouse_x, mouse_y = py.mouse.get_pos()
    player.rotate(mouse_x, mouse_y)
    # render
    screen.fill(BLACK)
    all_sprites.draw(screen)
    # flip the display
    py.display.flip()

py.quit()

PlayerSprite

import pygame as py
import math
import random

WIDTH = 800
HEIGHT = 600
FPS = 60

# define colors
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
YELLOW = (255, 255, 0)


class Player(py.sprite.Sprite):
    def __init__(self):
        py.sprite.Sprite.__init__(self)
        self.image = py.Surface((40, 40), py.SRCALPHA)
        self.image.fill(GREEN)
        self.rect = self.image.get_rect()
        self.rect.centerx = WIDTH / 2
        self.rect.bottom = HEIGHT / 2
        self.Yspeed = 0
        self.rotatableimage = self.image

    def update(self):
        self.Xspeed = 0
        self.Yspeed = 0
        # line below allow for key press to equate to move of sprite
        keypreesed = py.key.get_pressed()
        if keypreesed[py.K_a]:
            self.Xspeed = - 11
        if keypreesed[py.K_d]:
            self.Xspeed = 11
        if keypreesed[py.K_w]:
            self.Yspeed = - 11
        if keypreesed[py.K_s]:
            self.Yspeed = 11
        self.rect.x += self.Xspeed
        self.rect.y += self.Yspeed
        # line below allow the sprite to wrap around the screen
        if self.rect.left > WIDTH:
            self.rect.right = 0
        if self.rect.right < 0:
            self.rect.left = WIDTH
        if self.rect.top > HEIGHT:
            self.rect.top = 0
        if self.rect.bottom < 0:
            self.rect.bottom = HEIGHT

    def rotate(self, mouse_x, mouse_y):
        rel_x = mouse_x - self.rect.x
        rel_y = mouse_y - self.rect.y
        angle = (180 / math.pi) * -math.atan2(rel_y, rel_x)

        self.image = py.transform.rotate(self.rotatableimage, int(angle))
        self.rect = self.image.get_rect(center=(self.rect.centerx, self.rect.centery))
        return

    def Shoot(self):
       return Bullet(self.rect.centerx, self.rect.top)



class NPC(py.sprite.Sprite):
    def __init__(self, player):
        py.sprite.Sprite.__init__(self)
        self.player = player
        self.image = py.Surface((30, 30)).convert_alpha()
        self.image.fill(RED)
        self.originalimage = self.image
        self.rect = self.image.get_rect()
        self.spawn()

    # allows of spawning from all four side of the screen and set the x, y speed and spawn position
    def spawn(self):
        self.direction = random.randrange(4)
        if self.direction == 0:
            self.rect.x = random.randrange(WIDTH - self.rect.width)
            self.rect.y = random.randrange(-100, -40)
            self.Xspeed = random.randrange(-2, 2)
            self.Yspeed = random.randrange(4, 8)
        elif self.direction == 1:
            self.rect.x = random.randrange(WIDTH - self.rect.width)
            self.rect.y = random.randrange(HEIGHT, HEIGHT + 60)
            self.Xspeed = random.randrange(-2, 2)
            self.Yspeed = -random.randrange(4, 8)
        elif self.direction == 2:
            self.rect.x = random.randrange(-100, -40)
            self.rect.y = random.randrange(HEIGHT - self.rect.height)
            self.Xspeed = random.randrange(4, 8)
            self.Yspeed = random.randrange(-2, 2)
        elif self.direction == 3:
            self.rect.x = random.randrange(WIDTH, WIDTH + 60)
            self.rect.y = random.randrange(HEIGHT - self.rect.height)
            self.Xspeed = -random.randrange(4, 8)
            self.Yspeed = random.randrange(-2, 2)

    def update(self):
        self.rect.x += self.Xspeed
        self.rect.y += self.Yspeed
        # makes it so that NPC point to wards the player as it passes from side to side
        dir_x, dir_y = self.player.rect.x - self.rect.x, self.player.rect.y - self.rect.y
        self.rot = (180 / math.pi) * math.atan2(-dir_x, -dir_y)
        self.image = py.transform.rotate(self.originalimage, self.rot)
        # Respawns the NPC when they hit an side
        if self.direction == 0:
            if self.rect.top > HEIGHT + 10:
                self.spawn()
        elif self.direction == 1:
            if self.rect.bottom < -10:
                self.spawn()
        elif self.direction == 2:
            if self.rect.left > WIDTH + 10:
                self.spawn()
        elif self.direction == 3:
            if self.rect.right < -10:
                self.spawn()


class Bullet(py.sprite.Sprite):
    def __init__(self, x, y):
        py.sprite.Sprite.__init__(self)
        self.image = py.Surface((5, 5))
        self.image.fill(YELLOW)
        self.rect = self.image.get_rect()
        self.rect.bottom = y
        self.rect.centerx = x
        self.Yspeed = -10

    def update(self):
        self.rect.y += self.Yspeed
        # kill if moved of screen
        if self.rect.bottom > HEIGHT or self.rect.top < 0:
            self.kill()
        if self.rect.right > WIDTH or self.rect.left < 0:
            self.kill()

Tags: thepyrectimageselfifdefrandom
2条回答

在类Player中添加2个属性self.lastXself.lastY,并在玩家更改方向时更改属性:

class Player(py.sprite.Sprite):
    def __init__(self):
        # [...]

        self.lastX = 0
        self.lastY = -10   

    def update(self):
        # [...]
        self.rect.x += self.Xspeed
        self.rect.y += self.Yspeed

        if self.Xspeed != 0 or self.Yspeed != 0:
            self.lastX = self.Xspeed
            self.lastY = self.Yspeed  

向类Bullet添加参数XspeedansYspeed

class Bullet(py.sprite.Sprite):
    def __init__(self, x, y, Xspeed, Yspeed):
        py.sprite.Sprite.__init__(self)
        self.image = py.Surface((5, 5))
        self.image.fill(YELLOW)
        self.rect = self.image.get_rect()
        self.rect.bottom = y
        self.rect.centerx = x
        self.Xspeed = Xspeed
        self.Yspeed = Yspeed

    def update(self):
        self.rect.x += self.Xspeed
        self.rect.y += self.Yspeed
        # [...]

在项目符号生成时设置属性

class Player(py.sprite.Sprite):
    # [...]

    def Shoot(self):
       return Bullet(self.rect.centerx, self.rect.centery, self.lastX, self.lastY)

或者,也可以根据鼠标光标的方向设置速度

获取播放器和鼠标光标的位置,并计算x和y距离(Vector ):

pos = self.rect.center
mpos = py.mouse.get_pos()
vx = mpos[0] - pos[0]
vy = mpos[1] - pos[1]

如果鼠标位置和项目符号位置相等,则没有任何意义,因此跳过项目符号

if vx == 0 and vy == 0:
    return None

当然,这个向量很长,如果你直接用它来表示方向(XspeedYspeed),那么子弹会在一圈内移动到鼠标光标上。
在下面的示例中,我使用^{},因为它提供了方便的方法^{},可以将向量缩放到指定的Euclidean length

direction = py.math.Vector2(vx, vy)
direction.scale_to_length(10)

现在向量的x和y分量包含速度的x和y分量。由于组件是浮点值,因此它们是^{}到整数值:

return Bullet(pos[0], pos[1], round(direction.x), round(direction.y))

方法Shoot

class Player(py.sprite.Sprite):
    # [...]

    def Shoot(self):
        pos = self.rect.center
        mpos = py.mouse.get_pos()
        vx, vy = mpos[0] - pos[0], mpos[1] - pos[1]
        if vx == 0 and vy == 0:
            return None
        direction = py.math.Vector2(vx, vy)
        direction.scale_to_length(10) 
        return Bullet(pos[0], pos[1], round(direction.x), round(direction.y))

注意,如果根据鼠标光标的方向设置项目符号,则通过鼠标单击生成项目符号可能会很有用:

while running:
    # [...]

    for event in py.event.get():
        if event.type == py.QUIT:
            # [...]


        elif event.type == py.MOUSEBUTTONDOWN:
             if event.button == 1:
                New_bullet = player.Shoot()
                if New_bullet:
                    all_sprites.add(New_bullet)
                    bullets.add(New_bullet)

您可以使用pygamesVector2向任何方向移动。你可以计算球员的角度,你可以使用它

class Player(py.sprite.Sprite):
    def __init__(self):
        ...
        self.angle = 0

    def rotate(self, mouse_x, mouse_y):
        ...
        self.angle = -angle #make negative otherwise it will be going away from mouse

    def Shoot(self):
         return Bullet(self.rect.centerx, self.rect.top, py.math.Vector2(1,0).rotate(self.angle))

然后在bullet类中,获取方向并添加到其位置

class Bullet(py.sprite.Sprite):
    def __init__(self, x, y, Dir):
        ...
        self.Dir = Dir

    def update(self):
        self.rect.y += self.Dir[1] * self.speed
        self.rect.x += self.Dir[0] * self.speed
        ...

相关问题 更多 >

    热门问题