如何在鼠标方向上射箭?

时间:2017-06-09 19:56:48

标签: python python-3.x pygame mouseevent

我试图在鼠标点击时射箭,但是在鼠标的方向上。我已经完成了拍摄部分,但是我无法向鼠标拍摄。我在下面列出了我的代码,我非常感谢所有的帮助!

与箭头射击相关的代码部分是:

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)

1 个答案:

答案 0 :(得分:1)

要计算射弹的速度,请使用math.cos并使用math.sin作为x速度,使用math.degrees作为y速度,通过相乘将其缩放到所需的速度他们有一个任意数字。

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

更多说明:

  • 要将角度转换为度数,请调用pygame.display.update(),而不是将其乘以57.29。这使代码更具可读性。

  • 请勿在{{1​​}}循环中调用for shot in daggers。它应该每帧只调用一次。

  • 在迭代它时,永远不要修改列表(或其他迭代),否则会得到意想不到的结果。而是建立一个新的过滤列表。

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

  • 再次I recommend using vectors,pygame精灵和精灵组,因为它们有助于使您的代码更清晰,更易于阅读。

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.