如何使箭头朝着鼠标的方向射击? [英] How to make arrow shoot in direction of mouse?

查看:94
本文介绍了如何使箭头朝着鼠标的方向射击?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图在单击鼠标时向箭头射击,但是朝着鼠标的方向射击.我已经完成了射击部分,但是无法将其射向鼠标.我在下面列出了我的代码,非常感谢所有帮助!

I am attempting to shoot an arrow on mouse click, however in the direction of the mouse. I've accomplished the shooting part, however I am not able to have it shoot towards the mouse. I've listed my code below and I really appreciate all help!

与箭击有关的代码部分为:

The portion of the code which is relevant to the arrow shooting is:

for shot in daggers:
    index = 0
    shotx = math.cos(shot[0])*35
    shoty = math.sin(shot[0])*35
    shot[1] += shotx
    shot[1] += shoty
    if shot[1] < -40 or shot[1] > 900 or shot[1] < -40 or shot[1]> 600:
        daggers.pop(index)
    index =+ 1

    for shoot in daggers:
        daggerOne = pygame.transform.rotate(daggerPlayer, 360 - shoot[0]*57.29)
        screen.blit(daggerOne, (shoot[1], shoot[1]))

        pygame.display.update()

编辑-整个代码:

#Import the necessary modules
import pygame
import sys
import os
import math

#Initialize pygame
pygame.init()

# Set the size for the surface (screen)
screenSize = (900,600)
screen = pygame.display.set_mode((screenSize),0)

# Set the caption for the screen
pygame.display.set_caption("Neverland")

#Define Colours
WHITE = (255,255,255)
BLUE = (0,0,255)
BLACK = (0,0,0)
GRAY = (128, 128, 128)
MAROON = (128, 0, 0)
NAVYBLUE = (0, 0, 128)
OLIVE = (128, 128, 0)
PURPLE = (128, 0, 128)
TEAL = (0,128,128)
PINK = (226,132,164)
MUTEDBLUE = (155,182,203)
PLUM = (221,160,221)

#Clock Setup
clock = pygame.time.Clock()

#Load Images
peterPlayer = pygame.image.load('pixelPirateOne.png')
nightBackground = pygame.image.load ('skyTwo_1.png')
daggerPlayer = pygame.image.load('daggerPlayer.png')

#Settting Variables for Moving Character
xPlayer = 200
yPlayer = 275
dxPlayer = 0
dyPlayer = 0
playerPosition = (200,275)
accuracyShot = [0,0]
daggers = []
angle = 0

def quitGame():
    pygame.quit()
    sys.exit()

def outOfBounds(shot):
    return shot[0] < -40 or shot[0] > 900 or shot[1] < -40 or shot[1] > 600

go = True
while go:

#Quit Game
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
                quitGame()

#Move Player                
        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_LEFT:
                dxPlayer -= 25
            elif event.key == pygame.K_RIGHT:
                dxPlayer += 25
            elif event.key == pygame.K_UP:
                dyPlayer -= 25
            elif event.key == pygame.K_DOWN:
                dyPlayer += 25

        elif event.type == pygame.KEYUP:
            if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
                dxPlayer = 0
            elif event.key == pygame.K_UP or event.key == pygame.K_DOWN:
                dyPlayer = 0

        elif event.type == pygame.MOUSEBUTTONDOWN:
            mousePosition = pygame.mouse.get_pos()   
            velx = math.cos(angle)*6
            vely = math.sin(angle)*6
            daggers.append([math.atan2(mousePosition[1]-(playerPositionNew[1]+32), mousePosition[0]-(playerPositionNew[0]+26)), playerPositionNew[1]+32]) 

#Update move player
    xPlayer = xPlayer + dxPlayer
    yPlayer = yPlayer + dyPlayer
    pygame.display.update()

#Learned about atan2 from --> https://docs.python.org/2/library/math.html
#Allows To Rotate Player With Mouse    
    mousePosition = pygame.mouse.get_pos()   
    angle = math.atan2(mousePosition[1]-(yPlayer+32),mousePosition[0]-(xPlayer+26))
    playerRotate = pygame.transform.rotate(peterPlayer, 360-angle*57.29)
    playerPositionNew = (xPlayer-playerRotate.get_rect().width/2, yPlayer-playerRotate.get_rect().height/2)
    pygame.display.update()

#Learned about cos and sin in python from --> https://docs.python.org/2/library/math.html
#Learned about .pop from --> https://docs.python.org/2/tutorial/datastructures.html
#Draw daggers to screen
    filtered_daggers = []
    for shot in daggers:
        if not outOfBounds(shot[0]):
            filtered_daggers.append(shot)
        daggers = filtered_daggers

    for shot in daggers:
        shot[0][0] += shot[1][0]
        shot[0][1] += shot[1][1]

    screen.blit(nightBackground, (0,0))
    screen.blit(playerRotate, playerPositionNew)


    for shot in daggers:
        x, y = shot[0]       
        screen.blit(daggerPlayer, (shot[2], shot[0]))

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

推荐答案

要计算弹丸的速度,请使用angle并使用math.cos表示x速度,使用math.sin表示y速度,通过将它们乘以任意数字,将它们缩放到所需的速度.

To calculate the velocity of the projectiles, take the angle and use math.cos for the x-velocity and math.sin for the y-velocity, scale them to the desired speed by multiplying them with an arbitrary number.

将弹丸的位置和速度存储在列表或其他数据结构中(我建议为弹丸创建一个类),将此弹丸列表附加到您的匕首列表中,并在while循环中遍历匕首以更新通过添加速度来定位位置.

Store the position and the velocity of the projectile in a list or other data structure (I recommend creating a class for the projectiles), append this projectile list to your daggers list and in the while loop iterate over the daggers to update the positions by adding the velocities.

更多注意事项:

  • 要将角度转换为度,请调用math.degrees而不是将其乘以57.29.这使代码更具可读性.

  • To convert the angle to degrees, call math.degrees instead of multiplying it by 57.29. This makes the code more readable.

for shot in daggers循环中不要调用pygame.display.update().每帧只能调用一次.

Don't call pygame.display.update() in the for shot in daggers loop. It should be called only once per frame.

在迭代列表时,切勿修改列表(或其他可迭代对象),否则会得到意想不到的结果.而是建立一个新的过滤列表.

Never modify a list (or other iterables) while you're iterating over it or you'll get unexpected results. Build a new filtered list instead.

使用pygame.time.Clock限制帧速率.

我建议使用矢量,pygame精灵和精灵组,因为它们将有助于您的代码更整洁,更易于阅读.

And again I recommend using vectors, pygame sprites and sprite groups, since they'll help to make your code cleaner and easier to read.

import sys
import math
import pygame as pg


def out_of_bounds(position):
    """Check if the position of a projectile is out of bounds.

    Args:
        position (list): The coordinates of the projectile.

    Returns:
        bool: True if out of bounds, False if not.
    """
    x, y = position  # You can unpack a list or tuple like so.
    return x < -40 or x > 500 or y < -40 or y > 400


pg.init()

screen = pg.display.set_mode((640, 480))

PLAYER_IMG = pg.Surface((50, 30), pg.SRCALPHA)
pg.draw.polygon(PLAYER_IMG, (30, 150, 90), ((0, 0), (50, 15), (0, 30)))
DAGGER_IMG = pg.Surface((30, 20), pg.SRCALPHA)
pg.draw.polygon(DAGGER_IMG, (190, 150, 90), ((0, 0), (30, 10), (0, 20)))

# Player variables. I store the position in a rect.
player = pg.Rect(200, 275, 50, 30)
velocity_x = 0  # The x-speed of the player.
velocity_y = 0  # The y-speed of the player.
angle = 0
# In this list I'll store the data for the projectiles,
# i.e. lists of the positions and the velocities.
daggers = []

clock = pg.time.Clock()  # Use a clock to limit the frame rate.

while True:
    for event in pg.event.get():
        if event.type == pg.QUIT:
            pg.quit()
            sys.exit()
        # Move the player.
        elif event.type == pg.KEYDOWN:
            if event.key == pg.K_LEFT:
                velocity_x -= 5
            elif event.key == pg.K_RIGHT:
                velocity_x += 5
            elif event.key == pg.K_UP:
                velocity_y -= 5
            elif event.key == pg.K_DOWN:
                velocity_y += 5
        elif event.type == pg.KEYUP:
            if event.key == pg.K_LEFT or event.key == pg.K_RIGHT:
                velocity_x = 0
            elif event.key == pg.K_UP or event.key == pg.K_DOWN:
                velocity_y = 0
        # Here I create the projectiles and add them to the daggers list.
        elif event.type == pg.MOUSEBUTTONDOWN:
            # Use sine and cosine to get the velocity of the projectile.
            # To make it move faster, you need to scale the velocity
            # (i.e. multiply it by a number).
            vel_x = math.cos(angle) * 3
            vel_y = math.sin(angle) * 3
            # Now rotate the original image by the negative angle (because
            # pygame's y-axis is flipped).
            dagger_img = pg.transform.rotate(DAGGER_IMG, -math.degrees(angle))
            width, height = dagger_img.get_size()
            # The projectile data consists of position, velocity and the
            # rotated image. -width/2 and -height/2 to center them.
            daggers.append(
                [[player.centerx-width/2, player.centery-height/2],  # Pos
                 [vel_x, vel_y],  # Velocity
                 dagger_img  # Image
                 ])

    # Update the game.
    # Move the player by adding the velocity to the x- and y-coords
    # of the player rect.
    player.x += velocity_x
    player.y += velocity_y
    # Rotate player toward the mouse.
    mouse_position = pg.mouse.get_pos()
    # Distances to the mouse position.
    rise = mouse_position[1] - player.centery
    run = mouse_position[0] - player.centerx
    angle = math.atan2(rise, run)  # atan2 gives you the angle to the target.
    # Rotate the player image.
    player_rotated = pg.transform.rotate(PLAYER_IMG, -math.degrees(angle))
    player = player_rotated.get_rect(center=player.center)

    # Filter the daggers list.
    filtered_daggers = []
    for shot in daggers:
        if not out_of_bounds(shot[0]):
            filtered_daggers.append(shot)
    daggers = filtered_daggers
    # The 5 lines above can be reduced to this list comprehension.
    # daggers = [shot for shot in daggers if not out_of_bounds(shot[0])]

    # Move the daggers by adding the velocity to the position.
    # shot[0] is the pos, shot[1] the velocity.
    for shot in daggers:
        shot[0][0] += shot[1][0]
        shot[0][1] += shot[1][1]

    # Draw everything.
    screen.fill((30, 40, 50))
    screen.blit(player_rotated, player)
    # Blit the projectiles in a for loop.
    for shot in daggers:
        screen.blit(shot[2], shot[0])

    pg.display.update()
    clock.tick(30)  # Limit frame rate to 30 fps.

这篇关于如何使箭头朝着鼠标的方向射击?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆