如何让子弹从玩家点向光标移动?
How To Make Bullets Move Towards Cursor From Player Point?
我目前正在 pygame 中制作一个 2d top down 游戏,其中玩家 (ship/cursor) 通过键盘输入移动并且总是看向鼠标点。我还做到了当玩家按下或按住 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 可以更好地理解
在 class 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)
添加方法move
到class projectile
:
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
# [...]
我目前正在 pygame 中制作一个 2d top down 游戏,其中玩家 (ship/cursor) 通过键盘输入移动并且总是看向鼠标点。我还做到了当玩家按下或按住 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 可以更好地理解
在 class 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)
添加方法move
到class projectile
:
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
# [...]