Pygame图像旋转非常摇摆/不稳定
我正在研究游戏,玩家输入图f(x)= ...并绘制图形。所有这些都无缝起来。火箭应沿着这条路径旋转,因此它留在上面。我正在使用Math.degrees(Math.atan2(-dy,dx))
来查找应旋转到2分之间的角度。我旋转图像:
def blit_rotate_center(self, surf, topleft, rot_angle):
rotated_image = pygame.transform.rotate(self.image, rot_angle)
new_rect = rotated_image.get_rect(center=self.image.get_rect(topleft=topleft).center)
surf.blit(rotated_image, new_rect)
self.rect = new_rect
它确实有些可行,但是有很多怪异和小故障的旋转。
提前致谢! 主要循环:
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
print(easy_high_score, med_high_score, hard_high_score)
pygame.quit()
sys.exit()
if event.type == pygame.MOUSEBUTTONDOWN:
if input_rect.collidepoint(event.pos):
box_active = True
else:
box_active = False
if launch_rect.collidepoint(event.pos) and not box_active:
launch = True
launch_active = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
box_active = False
if box_active:
if event.key == pygame.K_BACKSPACE:
if user_text == "Invalid Input":
user_text = ""
else:
user_text = user_text[:-1]
pt_list = []
coord_list = []
draw = False
elif event.key == pygame.K_RETURN:
draw = True
if user_text == "Alim":
end_planet_pos = (1920, 540)
start_planet_pos = (0, 540)
cp_pos = (960, 540)
else:
user_text += event.unicode
pt_list = []
coord_list = []
screen.blit(bg_list[bg_index], (0, 0))
start.blit_start(start_planet_pos, (500, 500))
end.blit_start(end_planet_pos, (500, 500))
if difficulty == 0:
enemy0.blit_start(enemy0_pos, (200, 200))
if pygame.sprite.collide_mask(enemy0, checkpoint):
enemy0_pos = (random.randint(200, 1720), random.randint(200, 880))
if difficulty == 1:
enemy0.blit_start(enemy0_pos, (200, 200))
enemy1.blit_start(enemy1_pos, (200, 200))
if pygame.sprite.collide_mask(enemy0, checkpoint):
enemy0_pos = (random.randint(200, 760), random.randint(200, 880))
if pygame.sprite.collide_mask(enemy1, checkpoint):
enemy1_pos = (random.randint(1160, 1720), random.randint(200, 880))
if difficulty == 2:
enemy0.blit_start(enemy0_pos, (200, 200))
enemy1.blit_start(enemy1_pos, (200, 200))
enemy2.blit_start(enemy2_pos, (200, 200))
if pygame.sprite.collide_mask(enemy0, checkpoint):
enemy0_pos = (random.randint(200, 760), random.randint(200, 880))
if pygame.sprite.collide_mask(enemy1, checkpoint):
enemy1_pos = (random.randint(1160, 1720), random.randint(200, 880))
if pygame.sprite.collide_mask(enemy2, checkpoint):
enemy2_pos = (random.randint(200, 1720), random.randint(200, 880))
if not thru_cp:
checkpoint.blit_cp(cp_pos)
if pygame.sprite.collide_mask(enemy0, checkpoint):
enemy0_pos = (random.randint(200, 1720), random.randint(200, 880))
# draws the coordinate system
pygame.draw.line(screen, (255, 255, 255), (960, 0), (960, 1080), 2)
pygame.draw.line(screen, (255, 255, 255), (0, 540), (1920, 540), 2)
for numbers in range(0, 64):
pygame.draw.aaline(screen, (255, 255, 255), (numbers * 30, 530), (numbers * 30, 550))
for numbers in range(0, 36):
pygame.draw.aaline(screen, (255, 255, 255), (950, numbers * 30), (970, numbers * 30))
if box_active:
inp_rect_color = color_active
else:
inp_rect_color = color_passive
pygame.draw.rect(screen, inp_rect_color, input_rect, 2)
inp_text_surface = base_font.render(fixed_text_inp_box + user_text, False, (255, 255, 255))
input_rect.w = max(100, inp_text_surface.get_width() + 10)
screen.blit(inp_text_surface, (input_rect.x + 5, input_rect.centery - 5))
launch_button.blit_button((1820, 55), launch_active)
if len(coord_list) > 1:
try:
pygame.draw.aalines(screen, (255, 255, 255), False, coord_list, 3)
except (ValueError, SyntaxError, NameError, TypeError):
user_text = "Invalid Input"
if draw:
try:
coord_list = get_pt_list(user_text)
prev_coord = coord_list[0]
for coord in coord_list:
pygame.draw.aaline(screen, (255, 255, 255), prev_coord, coord)
pygame.display.flip()
pygame.time.delay(1)
prev_coord = coord
except (ValueError, SyntaxError, NameError, TypeError):
user_text = "Invalid Input"
draw = False
if launch:
try:
if not thru_enemy:
y1 = int(coord_list[coord_index][1])
y2 = int(coord_list[coord_index + 1][1])
x1 = int(coord_list[coord_index][0])
x2 = int(coord_list[coord_index + 1][0])
dy = y1 - y2
dx = x2 - x1
angle = math.degrees(math.atan2(dy, dx))
custom_round(angle, 5)
angle %= 360
center = (round(int(coord_list[coord_index][0])), round(int(coord_list[coord_index][1])))
rocket.blit_rotate_center(screen, center, angle)
if pygame.sprite.collide_mask(start, rocket):
thru_start = True
if pygame.sprite.collide_mask(rocket, end):
thru_end = True
if pygame.sprite.collide_mask(checkpoint, rocket):
thru_cp = True
if pygame.sprite.collide_mask(rocket, enemy0):
thru_enemy = True
print("dead")
if difficulty > 0:
if pygame.sprite.collide_mask(rocket, enemy1):
thru_enemy = True
print("dead")
if pygame.sprite.collide_mask(rocket, enemy2) and difficulty == 2:
thru_enemy = True
print("dead")
pygame.display.flip()
rocket.update()
angle = 0
coord_index += 20
except IndexError:
launch_complete = True
if thru_enemy:
launch_complete = True
if launch_complete:
coord_index = 0
launch = False
launch_active = False
draw_rocket = False
launch_complete = False
if thru_start and thru_end and thru_cp and not thru_enemy:
win = True
else:
thru_start = False
thru_end = False
thru_enemy = False
thru_cp = False
if win:
thru_cp = False
thru_enemy = False
thru_end = False
thru_start = False
end_planet_pos = (1920, random.randint(0, 980))
start_planet_pos = (0, random.randint(0, 980))
cp_pos = (random.randint(300, 1620), random.randint(200, 880))
bg_index = random.randint(0, 3)
start_exo = end_exo
end_exo = random.randint(0, 12)
if start_exo == end_exo:
if end_exo == 12:
end_exo -= 1
else:
end_exo -= 1
start = Obstacle(exo_list[start_exo], (500, 500))
end = Obstacle(exo_list[end_exo], (500, 500))
enemy_index1 = random.randint(0, 3)
enemy_index2 = random.randint(0, 3)
enemy_index3 = random.randint(0, 3)
if enemy_index1 == enemy_index2 == enemy_index3:
enemy_index2 += 1
enemy0_pos = (random.randint(200, 1720), random.randint(200, 880))
enemy1_pos = (random.randint(200, 1720), random.randint(200, 880))
enemy2_pos = (random.randint(200, 1720), random.randint(200, 880))
pt_list = []
coord_list = []
if difficulty == 0:
easy_score += 1
if easy_score > easy_high_score:
easy_high_score = easy_score
with open('easy_score.dat', 'wb') as file:
pickle.dump(easy_high_score, file)
if difficulty == 1:
med_score += 1
if med_score > med_high_score:
med_high_score = med_score
with open("med_score.dat", "wb") as file:
pickle.dump(med_high_score, file)
if difficulty == 2:
hard_score += 1
if hard_score > hard_high_score:
hard_high_score = hard_score
with open("hard_score.dat", "wb") as file:
pickle.dump(hard_high_score, file)
pygame.display.flip()
clock.tick(60)
链接到游戏的镜头: https://youtu.be/lkkxzzicook8
I am working on a game, where the player inputs a graph f(x) = ... and it draws the graph. All that works seamlessly. A Rocket should follow this path and rotate, so it stays on it. I am using math.degrees(math.atan2(-dy, dx))
to find the angle between 2 points which it should rotate to. I rotate the image with:
def blit_rotate_center(self, surf, topleft, rot_angle):
rotated_image = pygame.transform.rotate(self.image, rot_angle)
new_rect = rotated_image.get_rect(center=self.image.get_rect(topleft=topleft).center)
surf.blit(rotated_image, new_rect)
self.rect = new_rect
It does work somewhat, but there is a lot of weird and glitchy rotation.
thanks in advance!
The Main loop:
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
print(easy_high_score, med_high_score, hard_high_score)
pygame.quit()
sys.exit()
if event.type == pygame.MOUSEBUTTONDOWN:
if input_rect.collidepoint(event.pos):
box_active = True
else:
box_active = False
if launch_rect.collidepoint(event.pos) and not box_active:
launch = True
launch_active = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
box_active = False
if box_active:
if event.key == pygame.K_BACKSPACE:
if user_text == "Invalid Input":
user_text = ""
else:
user_text = user_text[:-1]
pt_list = []
coord_list = []
draw = False
elif event.key == pygame.K_RETURN:
draw = True
if user_text == "Alim":
end_planet_pos = (1920, 540)
start_planet_pos = (0, 540)
cp_pos = (960, 540)
else:
user_text += event.unicode
pt_list = []
coord_list = []
screen.blit(bg_list[bg_index], (0, 0))
start.blit_start(start_planet_pos, (500, 500))
end.blit_start(end_planet_pos, (500, 500))
if difficulty == 0:
enemy0.blit_start(enemy0_pos, (200, 200))
if pygame.sprite.collide_mask(enemy0, checkpoint):
enemy0_pos = (random.randint(200, 1720), random.randint(200, 880))
if difficulty == 1:
enemy0.blit_start(enemy0_pos, (200, 200))
enemy1.blit_start(enemy1_pos, (200, 200))
if pygame.sprite.collide_mask(enemy0, checkpoint):
enemy0_pos = (random.randint(200, 760), random.randint(200, 880))
if pygame.sprite.collide_mask(enemy1, checkpoint):
enemy1_pos = (random.randint(1160, 1720), random.randint(200, 880))
if difficulty == 2:
enemy0.blit_start(enemy0_pos, (200, 200))
enemy1.blit_start(enemy1_pos, (200, 200))
enemy2.blit_start(enemy2_pos, (200, 200))
if pygame.sprite.collide_mask(enemy0, checkpoint):
enemy0_pos = (random.randint(200, 760), random.randint(200, 880))
if pygame.sprite.collide_mask(enemy1, checkpoint):
enemy1_pos = (random.randint(1160, 1720), random.randint(200, 880))
if pygame.sprite.collide_mask(enemy2, checkpoint):
enemy2_pos = (random.randint(200, 1720), random.randint(200, 880))
if not thru_cp:
checkpoint.blit_cp(cp_pos)
if pygame.sprite.collide_mask(enemy0, checkpoint):
enemy0_pos = (random.randint(200, 1720), random.randint(200, 880))
# draws the coordinate system
pygame.draw.line(screen, (255, 255, 255), (960, 0), (960, 1080), 2)
pygame.draw.line(screen, (255, 255, 255), (0, 540), (1920, 540), 2)
for numbers in range(0, 64):
pygame.draw.aaline(screen, (255, 255, 255), (numbers * 30, 530), (numbers * 30, 550))
for numbers in range(0, 36):
pygame.draw.aaline(screen, (255, 255, 255), (950, numbers * 30), (970, numbers * 30))
if box_active:
inp_rect_color = color_active
else:
inp_rect_color = color_passive
pygame.draw.rect(screen, inp_rect_color, input_rect, 2)
inp_text_surface = base_font.render(fixed_text_inp_box + user_text, False, (255, 255, 255))
input_rect.w = max(100, inp_text_surface.get_width() + 10)
screen.blit(inp_text_surface, (input_rect.x + 5, input_rect.centery - 5))
launch_button.blit_button((1820, 55), launch_active)
if len(coord_list) > 1:
try:
pygame.draw.aalines(screen, (255, 255, 255), False, coord_list, 3)
except (ValueError, SyntaxError, NameError, TypeError):
user_text = "Invalid Input"
if draw:
try:
coord_list = get_pt_list(user_text)
prev_coord = coord_list[0]
for coord in coord_list:
pygame.draw.aaline(screen, (255, 255, 255), prev_coord, coord)
pygame.display.flip()
pygame.time.delay(1)
prev_coord = coord
except (ValueError, SyntaxError, NameError, TypeError):
user_text = "Invalid Input"
draw = False
if launch:
try:
if not thru_enemy:
y1 = int(coord_list[coord_index][1])
y2 = int(coord_list[coord_index + 1][1])
x1 = int(coord_list[coord_index][0])
x2 = int(coord_list[coord_index + 1][0])
dy = y1 - y2
dx = x2 - x1
angle = math.degrees(math.atan2(dy, dx))
custom_round(angle, 5)
angle %= 360
center = (round(int(coord_list[coord_index][0])), round(int(coord_list[coord_index][1])))
rocket.blit_rotate_center(screen, center, angle)
if pygame.sprite.collide_mask(start, rocket):
thru_start = True
if pygame.sprite.collide_mask(rocket, end):
thru_end = True
if pygame.sprite.collide_mask(checkpoint, rocket):
thru_cp = True
if pygame.sprite.collide_mask(rocket, enemy0):
thru_enemy = True
print("dead")
if difficulty > 0:
if pygame.sprite.collide_mask(rocket, enemy1):
thru_enemy = True
print("dead")
if pygame.sprite.collide_mask(rocket, enemy2) and difficulty == 2:
thru_enemy = True
print("dead")
pygame.display.flip()
rocket.update()
angle = 0
coord_index += 20
except IndexError:
launch_complete = True
if thru_enemy:
launch_complete = True
if launch_complete:
coord_index = 0
launch = False
launch_active = False
draw_rocket = False
launch_complete = False
if thru_start and thru_end and thru_cp and not thru_enemy:
win = True
else:
thru_start = False
thru_end = False
thru_enemy = False
thru_cp = False
if win:
thru_cp = False
thru_enemy = False
thru_end = False
thru_start = False
end_planet_pos = (1920, random.randint(0, 980))
start_planet_pos = (0, random.randint(0, 980))
cp_pos = (random.randint(300, 1620), random.randint(200, 880))
bg_index = random.randint(0, 3)
start_exo = end_exo
end_exo = random.randint(0, 12)
if start_exo == end_exo:
if end_exo == 12:
end_exo -= 1
else:
end_exo -= 1
start = Obstacle(exo_list[start_exo], (500, 500))
end = Obstacle(exo_list[end_exo], (500, 500))
enemy_index1 = random.randint(0, 3)
enemy_index2 = random.randint(0, 3)
enemy_index3 = random.randint(0, 3)
if enemy_index1 == enemy_index2 == enemy_index3:
enemy_index2 += 1
enemy0_pos = (random.randint(200, 1720), random.randint(200, 880))
enemy1_pos = (random.randint(200, 1720), random.randint(200, 880))
enemy2_pos = (random.randint(200, 1720), random.randint(200, 880))
pt_list = []
coord_list = []
if difficulty == 0:
easy_score += 1
if easy_score > easy_high_score:
easy_high_score = easy_score
with open('easy_score.dat', 'wb') as file:
pickle.dump(easy_high_score, file)
if difficulty == 1:
med_score += 1
if med_score > med_high_score:
med_high_score = med_score
with open("med_score.dat", "wb") as file:
pickle.dump(med_high_score, file)
if difficulty == 2:
hard_score += 1
if hard_score > hard_high_score:
hard_high_score = hard_score
with open("hard_score.dat", "wb") as file:
pickle.dump(hard_high_score, file)
pygame.display.flip()
clock.tick(60)
Link to footage of the game: https://youtu.be/lkKxZicoOk8
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
问题可能是
rect
属性是在BLIT_ROTATE_CENTER
方法中修改的。由于您使用
rect
属性来计算图像的左上角,因此这可能会导致反馈循环:简化您的代码。使用使用图像中心而不是左上方的旋转方法:
并将对象的中心传递给方法:
另请参见如何知道两个向量之间的角度?和 *如何使用Pygame?如何在其中心周围旋转图像?
Likely the problem is that the
rect
attribute is modified in theblit_rotate_center
method.Since you're using the
rect
attribute to calculate the top-left corner of the image, this can result in a feedback loop:Simplify your code. Use a rotation method that uses the center of the image instead of the top left:
And pass the center of the object to the method:
See also How to know the angle between two vectors? and *How do I rotate an image around its center using PyGame?.