python - Pygame以与玩家相同的方式移动绘制的矩形(不是图像),包括旋转
问题描述
我正在尝试为我的星舰创建激光束,该激光束是绘制的矩形而不是图像,我用“wasd”移动星舰并用鼠标瞄准,我创建了一个“激光”类,我已经设法使其瞄准与玩家相同的方向。除了旋转之外,横梁也应该移动以保持附着在船上,但我不明白该怎么做。
class Player:
#inizialize the player
def __init__(self, x, y, player):
self.x = x
self.y = y
self.image = player
self.is_shooting = False
self.original_player_image = player
self.angle = 0
#move the player
def movePlayer(self):
if key[0]:
self.x -= 10
elif key[1]:
self.x += 10
if key[2]:
self.y -= 10
elif key[3]:
self.y += 10
#check borders
if self.x <= 0:
self.x = 0
if self.x + rock_image.get_width() >= display_width:
self.x = display_width - player_image.get_width()
if self.y <= 0:
self.y = 0
if self.y + player_image.get_height() >= display_height:
self.y = display_height - player_image.get_height()
#rotate the player where the mouse is aiming
def rotate(self):
mouse_x, mouse_y = pygame.mouse.get_pos()
rel_x, rel_y = mouse_x - self.x, mouse_y - self.y
self.angle = (180 / math.pi) * -math.atan2(rel_y, rel_x) - 90
self.image = pygame.transform.rotate(self.original_player_image, int(self.angle))
self.rect = self.image.get_rect()
#draw the player
def drawPlayer(self):
screen.blit(self.image, (self.x, self.y))
class Laser:
def __init__(self, player_x, player_y):
self.x = player_x
self.y = player_y
self.original_image = pygame.Surface((5, 150))
self.original_image.set_colorkey( (0,0,0) )
self.original_image.fill( (255,0,0) )
self.copy_image = self.original_image.copy()
self.copy_image.set_colorkey( (0,0,0) )
self.rect = self.copy_image.get_rect()
self.rect.center = self.x + player_image.get_width()//2, self.y - 75
self.new_image = pygame.Surface((5, 150))
def continueDrawLaser(self):
if laser_bool:
screen.blit(self.new_image, self.rect)
def rotate(self):
mouse_x, mouse_y = pygame.mouse.get_pos()
rel_x, rel_y = mouse_x - player1.x, mouse_y - player1.y
angle = (180 / math.pi) * -math.atan2(rel_y, rel_x) - 85
vel_x = math.cos(angle)
vel_y = math.sin(angle)
self.new_image = pygame.transform.rotate(self.original_image, angle)
self.rect = self.new_image.get_rect()
self.rect.center = player1.x + vel_x, player1.y + vel_y
第一个是玩家类(星舰)第二个是激光类(激光束)
这就是我得到的:
如果您需要我在这里发布的整个代码:
为了让你测试代码我把所有没用的东西都去掉了,只给玩家留下了激光束,所以你只需要下载宇宙飞船来测试代码,这里是缩短的代码:
飞船下载链接:
https://www.flaticon.com/free-icon/spaceship_1114780?term=space%20ship&page=1&position=57
解决方案
在如何使用 Pygame 围绕其中心旋转图像的答案中?提出了一种围绕枢轴旋转图像的算法。
使用算法实现rotate
类中的功能Laser
,取决于方向和位置player1
class Laser:
# [...]
def rotate(self):
# get rectangle of player and laser, as if the angle would be 0
player_rect = player1.original_player_image.get_rect(topleft = (player1.x, player1.y))
laser_rect = self.original_image.get_rect(midbottom = player_rect.midtop)
self.angle = player1.angle
pos = player_rect.center
pivotPos = [pos[0] - laser_rect.x, pos[1] - laser_rect.y]
# calcaulate the axis aligned bounding box of the rotated image
w, h = self.original_image.get_size()
box = [pygame.math.Vector2(p) for p in [(0, 0), (w, 0), (w, -h), (0, -h)]]
box_rotate = [p.rotate(self.angle) for p in box]
min_box = (min(box_rotate, key=lambda p: p[0])[0], min(box_rotate, key=lambda p: p[1])[1])
max_box = (max(box_rotate, key=lambda p: p[0])[0], max(box_rotate, key=lambda p: p[1])[1])
# calculate the translation of the pivot
pivot = pygame.math.Vector2(pivotPos[0], -pivotPos[1])
pivot_rotate = pivot.rotate(self.angle)
pivot_move = pivot_rotate - pivot
# calculate the upper left origin of the rotated image
origin = (pos[0] - pivot[0] + min_box[0] - pivot_move[0], pos[1] + pivot[1] - max_box[1] + pivot_move[1])
# get a rotated image
self.new_image = pygame.transform.rotate(self.original_image, self.angle)
# get new rectangle
self.rect = self.new_image.get_rect(topleft = (round(origin[0]), round(origin[1])))
更进一步,您必须确保正确放置旋转的宇宙飞船。计算未旋转的宇宙飞船的中心并将该中心应用于旋转的宇宙飞船。使用.rect
飞船的属性来blit
:
class Player:
# [...]
# rotate the player where the mouse is aiming
def rotate(self):
mouse_x, mouse_y = pygame.mouse.get_pos()
rel_x, rel_y = mouse_x - self.x, mouse_y - self.y
self.angle = (180 / math.pi) * -math.atan2(rel_y, rel_x) - 90
self.image = pygame.transform.rotate(self.original_player_image, int(self.angle))
orig_center = self.original_player_image.get_rect(topleft = (self.x, self.y)).center
self.rect = self.image.get_rect(center = orig_center)
# draw the player
def drawPlayer(self):
screen.blit(self.image, self.rect.topleft)
当然,每次玩家旋转时,激光也必须旋转:
player1.movePlayer()
player1.rotate()
laser1.rotate()
推荐阅读
- c++ - 我正在修改一些代码,并将一些函数更改为系统调用,但现在我遇到了一些让我感到困惑的错误
- session-state - 是否可以使用 GTM 跨多个数据中心进行粘性会话?
- c++ - 构建 CppBenchmark 时出错 (https://github.com/chronoxor/CppBenchmark)
- .net-core - OpenIdConnect 的点网核心设置 redirect_uri 与点网框架不同?
- c++ - C++ 可重用模块类设计
- sql - 如何从两个表中获取特定记录
- javascript - 使用 .map 转换嵌套的 For 循环
- laravel - 图像在数据库中保存为 C:\wamp64\tmp\phpAE1C.tmp 而不是保存在 public/images
- mysql - GROUP BY 和 SUM 但拆分 GROUP BY 结果
- events - 为 RxJava 2.x 配置 Grails 事件总线调度程序