如何控制子弹的速度?
How to control the speed of bullets?
我做了一个简单的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)
您当前的代码似乎在您单击鼠标时使用鼠标的位置来确定速度。更远的点击会导致更快的拍摄。但听起来你只想用鼠标的位置来确定射击的方向,所有子弹的速度都相同。
这是向量归一化的作业!
你可以把你的角色位置减去点击位置计算出来的位置向量除以它自己的长度,变成一个单位向量。然后你可以将单位向量乘以所需的速度。
尝试这样的事情:
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_x
和 unit_y
变量存在,你可以直接去velocity_x
和 velocity_y
乘以速度,同时除以 distance
)。
请注意,我保留了 kx
/ky
和 kx1
/ky1
列表,但存储以下组件可能更有意义kx1
/ky1
中的子弹速度,而不是存储以前的位置(因为无论如何你都要减去位置以获得速度)。
您也可以考虑制作一个 Bullet
class 来将子弹的位置和速度一起存储在一个对象中,而不是有多个并行列表。
@Blckknght 描述的问题,我只展示如何使用 pygame.math.Vector2
顺便说一句:我使用一个 bullets
而不是 4 个列表 kx
、ky
、kx1
、ky1
并将所有信息保存为列表 [position, speed]
其中 position
和 speed
是 Vector2
,因此它们保持为浮点数,并且仅当 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 -
我做了一个简单的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)
您当前的代码似乎在您单击鼠标时使用鼠标的位置来确定速度。更远的点击会导致更快的拍摄。但听起来你只想用鼠标的位置来确定射击的方向,所有子弹的速度都相同。
这是向量归一化的作业!
你可以把你的角色位置减去点击位置计算出来的位置向量除以它自己的长度,变成一个单位向量。然后你可以将单位向量乘以所需的速度。
尝试这样的事情:
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_x
和 unit_y
变量存在,你可以直接去velocity_x
和 velocity_y
乘以速度,同时除以 distance
)。
请注意,我保留了 kx
/ky
和 kx1
/ky1
列表,但存储以下组件可能更有意义kx1
/ky1
中的子弹速度,而不是存储以前的位置(因为无论如何你都要减去位置以获得速度)。
您也可以考虑制作一个 Bullet
class 来将子弹的位置和速度一起存储在一个对象中,而不是有多个并行列表。
@Blckknght 描述的问题,我只展示如何使用 pygame.math.Vector2
顺便说一句:我使用一个 bullets
而不是 4 个列表 kx
、ky
、kx1
、ky1
并将所有信息保存为列表 [position, speed]
其中 position
和 speed
是 Vector2
,因此它们保持为浮点数,并且仅当 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 -