【问题标题】:How to control the speed of bullets?如何控制子弹的速度?
【发布时间】:2017-05-22 10:22:18
【问题描述】:

我做了一个简单的 2D 游戏,但是当英雄射击时,有些子弹比其他子弹移动得更快,尤其是从英雄角落射出的子弹(英雄的形状是简单的盒子)。

这是我编写射击代码的方式(我写那行代码只是为了确保子弹射向正确的方向)。我正在使用 Python 3.5.2。

运行代码,到处乱拍,你会发现有的更快。

import pygame
from pygame.locals import*
import os
os.environ['SDL_VIDEO_WINDOW_POS'] = "%d,%d" % (0,25)
pygame.init()
x=pygame.display.set_mode((1360,705))
clock = pygame.time.Clock()
kx=[]
ky=[]
kx1=[]
ky1=[]
while True :
     x.fill((0,0,0))
     for event in pygame.event.get():
                if event.type==QUIT :
                    pygame.quit()
                    quit()
                if event.type== pygame.MOUSEBUTTONDOWN and event.button == 1:
                     xvx=pygame.mouse.get_pos()
                     xa=(int(xvx[0]))
                     ya=(int(xvx[1]))
                     wox=(xa-680)
                     woy=(ya-352)
                     ox=wox/70
                     oy=woy/70
                     while True :
                         if xa >= 700 or xa <=660 or ya>=372 or ya<=332 :
                              xa=xa-ox
                              ya=ya-oy
                         else :
                              break
                     pygame.draw.line(x,(255,150,100),(xa,ya),(680,352))
                     kx.append(xa-1)
                     ky.append(ya-1)
                     kx1.append(680)
                     ky1.append(352)
     for i in range (len(kx)):
          wox=(kx[i]-kx1[i])
          woy=(ky[i]-ky1[i])
          ox=wox/20
          oy=woy/20
          kx[i]=kx[i]+ox
          ky[i]=ky[i]+oy
          kx1[i]=kx1[i]+ox
          ky1[i]=ky1[i]+oy
          pygame.draw.rect(x,(250,250,250),(kx[i],ky[i],2,2))
     pygame.display.update()
     clock.tick(60)

【问题讨论】:

  • 请您添加一些有意义的变量名,目前很难理解发生了什么
  • 顺便说一句:如果您有 MOUSEBUTTONDOWN 事件,那么您的鼠标位置在 event.pos 并且您不需要 pygame.mouse.get_pos()。两者都将位置作为整数值,因此您不必使用int() - xa, ya = event.pos

标签: python pygame motion


【解决方案1】:

@Blckknght 描述了问题,我只展示了如何使用pygame.math.Vector2

顺便说一句:而不是 4 个列表 kxkykx1ky1 我使用一个 bullets 并将所有信息保留为列表 [position, speed],其中 positionspeed 是 @987654332 @ 所以它们保持为浮点数,并且只有在 pygame 绘制对象时才会将值四舍五入为整数。

position += speed 

position.x += speed.x
position.y += speed.y

完整代码:

#!/usr/bin/env python3

import pygame
import os

# --- constants ---

WIDTH = 1360
HEIGHT = 705

BLACK = (0, 0, 0)
WHITE = (250, 250, 250)

BULLET_SPEED = 5

# --- classes ---

#empty

# --- functions ---

#empty

# --- main ---

# - init -

os.environ['SDL_VIDEO_WINDOW_POS'] = '0, 25'

pygame.init()

screen = pygame.display.set_mode((WIDTH, HEIGHT))

# - objects -

bullets = []

# center of screen as Vector2
#center = pygame.math.Vector2(WIDTH//2, HEIGHT//2)
center = pygame.math.Vector2(screen.get_rect().center)

# - mainloop -

clock = pygame.time.Clock()

while True:
    screen.fill(BLACK)

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            quit()

        if event.type== pygame.MOUSEBUTTONDOWN:
            if event.button == 1:

                # get vector from center to mouse position
                vector = event.pos - center
                # `center` is `Vector2` so `vector` will be `Vector2` too
                #print(type(vector))

                # normalize
                normal = vector.normalize()

                # create speed vector
                speed = normal * BULLET_SPEED

                # move object (first move 5 times bigger then next moves )
                pos = center + (speed * 5)

                #pygame.draw.line(screen, (255,150,100), (pos.x, pos.y), (center.x, center.y))
                pygame.draw.line(screen, (255,150,100), pos, center)

                # remeber position and speed as one object
                bullets.append( [pos, speed] )

    # - draws -

    for pos, speed in bullets:
        # move
        pos += speed

        # draw
        pygame.draw.rect(screen, WHITE, (pos.x, pos.y, 2, 2))

    pygame.display.update()

    # - speed -

    clock.tick(60)

# - end -

【讨论】:

  • 非常感谢,这对我非常有用,我是学习 python 和编程的新手(几个月前才开始)所以我不明白你的代码中的一些东西你有什么我能读懂的东西吗?你的代码更多?喜欢阅读和理解更多游戏数学知识吗?
  • 我没有一个地方可以存放所有信息。多年来,我从许多地方和书籍中学到了一切——我什至不记得这些地方和书籍。
  • 互联网上有很多教程、视频教程和书籍。 IE。见Program Arcade Games With Python And Pygame,或者GameDev.net
【解决方案2】:

您当前的代码似乎在您单击鼠标时使用鼠标的位置来确定速度。更远的点击会导致更快的拍摄。但听起来您只希望鼠标的位置来确定射击的方向,所有子弹都获得相同的速度。

这是向量归一化的工作!

你可以将你计算的位置向量从你的字符位置减去点击位置变成一个单位向量,方法是把它除以它自己的长度。然后你可以将单位向量乘以所需的速度。

试试这样的:

if event.type== pygame.MOUSEBUTTONDOWN and event.button == 1:
     xvx=pygame.mouse.get_pos()
     click_x = int(xvx[0]) - 680 # get relative position of the click
     click_y = int(xvx[1]) - 352
     distance = math.sqrt(click_x**2 + click_y**2)
     unit_x = click_x / distance            # make a unit vector
     unit_y = click_y / distance
     BULLET_SPEED = 20   # this constant could be defined elsewhere
     velocity_x = unit_x * BULLET_SPEED     # make the velocity vector
     velocity_y = unit_y * BULLET_SPEED
     pygame.draw.line(x, (255, 150, 100),
                      (680, 352), (680+velocity_x, 352+velocity_y))
     kx.append(680 + velocity_x)
     ky.append(352 + velocity_y)
     kx1.append(680)
     ky1.append(352)

我使用了更有意义的变量名,因此希望代码比名称过于简洁的原始代码更容易理解。如果您愿意,可以通过将一些顺序操作组合成一行上的一个组合操作来缩短时间(例如,不需要存在 unit_xunit_y 变量,您可以直接转到 velocity_xvelocity_y 乘以速度,同时除以 distance)。

请注意,我保留了 kx/kykx1/ky1 列表,但将子弹速度的分量存储在 kx1/ 中可能更有意义ky1 而不是存储以前的位置(因为无论如何你要减去位置以获得速度)。

您还可以考虑创建一个Bullet 类来将子弹的位置和速度一起存储在一个对象中,而不是使用多个并行列表。

【讨论】:

  • @OP pygame 有pygame.math.Vector2 有方法distance_to()normalize() - 所以以后你可以用更短的方式编写@Blckknght 代码。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-23
  • 1970-01-01
  • 2015-03-14
相关资源
最近更新 更多