【问题标题】:How To Make Bullets Move Towards Cursor From Player Point? [duplicate]如何让子弹从玩家点向光标移动? [复制]
【发布时间】:2021-06-11 04:55:11
【问题描述】:

我目前正在 pygame 中制作一个 2d 自上而下的游戏,其中玩家(船/光标)随着键盘输入移动,并且总是看向鼠标点。我还设置了当玩家按下或按住 SPACE 键时,飞船会从它的矩形中间向上射击。

我遇到的问题是我需要子弹面对朝向 鼠标位置。过去一周我一直在努力解决这个问题,但我不知道该怎么做。

我想要的是让子弹(一个矩形图像)在发射时朝着鼠标的点移动,并且让子弹像飞船一样朝着鼠标旋转。这意味着即使鼠标移动,我也希望子弹继续以相同的路径前进,直到它碰到屏幕边缘并保持与以前相同的角度,如果这有意义的话。

对不起,代码中的间距,它只是让我更容易识别与什么有关的内容。

任何帮助都会非常感激:)

import math, pygame

pygame.init()

# === CONSTANTS ===

#window dimensions set into the name 'win'
win = pygame.display.set_mode((1280,800))

#cursor / player ship image
cursor = pygame.image.load("images/cursor.png").convert_alpha()


# === CLASSES ===

#bullet class, holds image and other points
class projectile(object):
    def __init__(self,x,y,radius,color):
        self.x = x
        self.y = y
        self.image = pygame.transform.smoothscale(pygame.image.load('images/bullet.png'), (30,60))
        self.vel = 3

    #gets called in the update_win() to draw the bullet on the screen
    def draw(self,win):
        win.blit(self.image, (self.x,self.y))



# === MAIN FUNCTIONS ===


#keeps the display.update() and other blit code for easier layout
def update_win():

    win.fill((31,27,24))

    for bullet in bullets:
        bullet.draw(win)

    win.blit(rot_image, rot_image_rect.topleft)
    
    pygame.display.update()



#   0 - image is looking to the right
#  90 - image is looking up
# 180 - image is looking to the left
# 270 - image is looking down
correction_angle = 90

cursor_pos = list(win.get_rect().center)

#this is where the bullets go into a list
bullets = []
#for control of how many bullets are fired and at what interval
shoot_loop = 0


# === MAIN LOOP ===

run = True
while run:
    pygame.time.delay(2)
    
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False


    
    #cursor postion and rectangle
    cursor_rect = cursor.get_rect(center = (cursor_pos))
    




    #simple movement / key presses
    keys = pygame.key.get_pressed()
    if keys[pygame.K_a] and cursor_rect.x > -10:
        cursor_pos[0] -= 1
    if keys[pygame.K_d] and cursor_rect.x < 1210:
        cursor_pos[0] += 1
    if keys[pygame.K_w] and cursor_rect.y > -10:
        cursor_pos[1] -= 1
    if keys[pygame.K_s] and cursor_rect.y < 730:
        cursor_pos[1] += 1
    if keys[pygame.K_SPACE]:
        x,y = pygame.mouse.get_pos()
        print(x,y)




    #controls how many bullets are shot (interval)
    if shoot_loop > 0:
        shoot_loop += 0.06
    if shoot_loop > 3:
        shoot_loop = 0


    #will move the bullet image in list and .pop it if it goes above screen
    for bullet in bullets:
        if bullet.y < 800 and bullet.y > -10:
            bullet.y -= bullet.vel  # Moves the bullet by its vel (3)
        else:
            bullets.pop(bullets.index(bullet))  # This will remove the bullet if it is off the screen


    #checks the bullet loop and will add another bullet to the loop if conditions are met
    if keys[pygame.K_SPACE] and shoot_loop == 0:
        if len(bullets) < 100:
            bullets.append(projectile(round(cursor_rect.x + 25), round(cursor_rect.y ), 6, (255,255,255)))

        shoot_loop = 1
        



    







    #calculates mouse position, angle and rotation for image
    mx, my = pygame.mouse.get_pos()
    dx, dy = mx - cursor_rect.centerx, my - cursor_rect.centery
    angle = math.degrees(math.atan2(-dy, dx)) - correction_angle

    #rotated image surface
    rot_image      = pygame.transform.rotate(cursor, angle)
    rot_image_rect = rot_image.get_rect(center = cursor_rect.center)





    update_win()


pygame.quit()
exit()

这里有一个 gif 以便更好地理解

【问题讨论】:

    标签: pygame 2d mouse angle topdown


    【解决方案1】:

    projectile 类的构造函数中计算子弹的单位方向向量(Unit Vector 的长度为 1):

    mx, my = pygame.mouse.get_pos()
    dx, dy = mx - self.x, my - self.y
    len = math.hypot(dx, dy)
    self.dx = dx / len
    self.dy = dy / len
    

    并旋转弹丸图像:

    angle = math.degrees(math.atan2(-dy, dx)) - 90
    self.image = pygame.transform.rotate(self.image, angle)
    

    在类projectile中添加方法move

    def move(self):
        self.x += self.dx * self.vel
        self.y += self.dy * self.vel
    

    致电move 而不是bullet.y -= bullet.vel

    for bullet in bullets:       
        if -10 < bullet.x < 1200 and -10 < bullet.y < 800:
            bullet.move()
        else:
            bullets.pop(bullets.index(bullet))
    

    变化:

    class projectile(object):
        def __init__(self,x,y,radius,color):
            self.x = x
            self.y = y
            self.image = pygame.transform.smoothscale(pygame.image.load('images/bullet.png'), (30,60))
            self.vel = 3
            
            mx, my = pygame.mouse.get_pos()
            dx, dy = mx - self.x, my - self.y
            len = math.hypot(dx, dy)
            self.dx = dx / len
            self.dy = dy / len
    
            angle = math.degrees(math.atan2(-dy, dx)) - 90
            self.image = pygame.transform.rotate(self.image, angle)
    
        def move(self):
            self.x += self.dx * self.vel
            self.y += self.dy * self.vel
    
        def draw(self,win):
            win.blit( self.image, (round(self.x), round(self.y)))
    
    run = True
    while run:
        # [...]
    
        #will move the bullet image in list and .pop it if it goes above screen
        for bullet in bullets:       
            if -10 < bullet.x < 1200 and -10 < bullet.y < 800:
                bullet.move()
            else:
                bullets.pop(bullets.index(bullet))  # This will remove the bullet if it is off the screen
    
        # [...]
    

    【讨论】:

    • 哇。我在这里阅读了很多帖子,答案几乎没有意义,您发布它的方式很容易理解。谢谢大家:)
    猜你喜欢
    • 1970-01-01
    • 2014-06-21
    • 1970-01-01
    • 2022-06-10
    • 1970-01-01
    • 2021-09-12
    • 1970-01-01
    • 2022-11-22
    • 1970-01-01
    相关资源
    最近更新 更多