<small id='y9ObM'></small><noframes id='y9ObM'>

    • <bdo id='y9ObM'></bdo><ul id='y9ObM'></ul>

    1. <i id='y9ObM'><tr id='y9ObM'><dt id='y9ObM'><q id='y9ObM'><span id='y9ObM'><b id='y9ObM'><form id='y9ObM'><ins id='y9ObM'></ins><ul id='y9ObM'></ul><sub id='y9ObM'></sub></form><legend id='y9ObM'></legend><bdo id='y9ObM'><pre id='y9ObM'><center id='y9ObM'></center></pre></bdo></b><th id='y9ObM'></th></span></q></dt></tr></i><div id='y9ObM'><tfoot id='y9ObM'></tfoot><dl id='y9ObM'><fieldset id='y9ObM'></fieldset></dl></div>

        <legend id='y9ObM'><style id='y9ObM'><dir id='y9ObM'><q id='y9ObM'></q></dir></style></legend><tfoot id='y9ObM'></tfoot>

        如何在其比例变大时围绕其中心旋转图像(在 Pygame 中)

        时间:2023-07-03
        <i id='5KJnv'><tr id='5KJnv'><dt id='5KJnv'><q id='5KJnv'><span id='5KJnv'><b id='5KJnv'><form id='5KJnv'><ins id='5KJnv'></ins><ul id='5KJnv'></ul><sub id='5KJnv'></sub></form><legend id='5KJnv'></legend><bdo id='5KJnv'><pre id='5KJnv'><center id='5KJnv'></center></pre></bdo></b><th id='5KJnv'></th></span></q></dt></tr></i><div id='5KJnv'><tfoot id='5KJnv'></tfoot><dl id='5KJnv'><fieldset id='5KJnv'></fieldset></dl></div>
          <bdo id='5KJnv'></bdo><ul id='5KJnv'></ul>

              <tbody id='5KJnv'></tbody>
          • <tfoot id='5KJnv'></tfoot>

              • <small id='5KJnv'></small><noframes id='5KJnv'>

                <legend id='5KJnv'><style id='5KJnv'><dir id='5KJnv'><q id='5KJnv'></q></dir></style></legend>
                  本文介绍了如何在其比例变大时围绕其中心旋转图像(在 Pygame 中)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着跟版网的小编来一起学习吧!

                  问题描述

                  我加载了一张图片,我希望它围绕它的中心旋转,同时它的比例越来越大.我最初知道如何围绕其中心旋转图像,但是如果比例变大,我很难计算位置.我试过了,但图像只是跳舞",而不是停留在中心.

                  解决方案

                  简答:

                  存储源图像矩形的中心,并通过存储的中心位置更新旋转和缩放操作后旋转和缩放的图像矩形的中心.通过

                  这是原因,因为旋转图像的边界矩形总是大于原始图像的边界矩形(除了某些旋转 90 度的倍数).
                  由于多重副本,图像会变形.每次旋转都会产生一个小错误(不准确).错误的总和在增加,图像在衰减.

                  这可以通过保留原始图像和blit"来解决.由原始图像通过单次旋转操作生成的图像.

                  angle = 0虽然没有完成:# [...]旋转图像 = pygame.transform.rotate(图像,角度)角度 += 1screen.blit(rotated_image, pos)pygame.display.flip()

                  现在图像似乎可以随意改变它的位置,因为图像的大小会随着旋转而改变,并且原点始终是图像边界矩形的左上角.

                  这可以通过比较旋转前图像的

                  要在原始图像上定义一个轴心,平移"必须计算相对于图像左上角的枢轴的blit".图像的位置必须通过平移移动.

                  定义一个枢轴,例如在图像的中心:

                  pivot = pygame.math.Vector2(w/2, -h/2)

                  计算旋转轴的平移:

                  pivot_rotate = pivot.rotate(angle)pivot_move = pivot_rotate - 枢轴

                  最后计算旋转图像的原点:

                  origin = (pos[0] + min_box[0] - pivot_move[0], pos[1] - max_box[1] + pivot_move[1])旋转图像 = pygame.transform.rotate(图像,角度)screen.blit(旋转图像,原点)

                  如果图像必须额外缩放,那么在计算图像的原点时必须考虑缩放:

                  move = (-pivot[0] + min_box[0] - pivot_move[0], pivot[1] - max_box[1] + pivot_move[1])原点 = (pos[0] + zoom * move[0], pos[1] + zoom * move[1])rotozoom_image = pygame.transform.rotozoom(图像,角度,缩放)screen.blit(rotozoom_image,原点)

                  在下面的示例程序中,函数 blitRotate 完成上述所有步骤并blit".将图像旋转到表面.pos 是图像的位置.originPos 是图像上放置在 pos 和轴心上的点.


                  最小示例:

                  import pygamepygame.init()screen = pygame.display.set_mode((300, 300))时钟 = pygame.time.Clock()def blitRotate(surf, image, pos, originPos, angle, zoom):# 计算旋转图像的轴对齐边界框w, h = image.get_size()box = [pygame.math.Vector2(p) for p in [(0, 0), (w, 0), (w, -h), (0, -h)]]box_rotate = [p.rotate(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])# 计算轴的平移枢轴= pygame.math.Vector2(originPos [0],-originPos [1])pivot_rotate = pivot.rotate(角度)pivot_move = pivot_rotate - 枢轴# 计算旋转图像的左上原点move = (-originPos[0] + min_box[0] - pivot_move[0], -originPos[1] - max_box[1] + pivot_move[1])原点 = (pos[0] + zoom * move[0], pos[1] + zoom * move[1])# 得到一个旋转的图像rotozoom_image = pygame.transform.rotozoom(图像,角度,缩放)# 旋转和blit图像surf.blit(rotozoom_image,原点)# 在图像周围绘制矩形pygame.draw.rect (surf, (255, 0, 0), (*origin, *rotozoom_image.get_size()),2)尝试:image = pygame.image.load('AirPlaneFront1-128.png')除了:text = pygame.font.SysFont('Times New Roman', 50).render('image', False, (255, 255, 0))图像 = pygame.Surface((text.get_width()+1, text.get_height()+1))pygame.draw.rect(图像, (0, 0, 255), (1, 1, *text.get_size()))image.blit(文本, (1, 1))w, h = image.get_size()开始 = 假角度,缩放 = 0, 1完成 = 假虽然没有完成:时钟.tick(60)对于 pygame.event.get() 中的事件:如果 event.type == pygame.QUIT:完成=真elif event.type == pygame.KEYDOWN 或 event.type == pygame.MOUSEBUTTONDOWN:开始 = 真pos = (screen.get_width()/2, screen.get_height()/2)screen.fill(0)blitRotate(屏幕、图像、位置、(w/2、h/2)、角度、缩放)如果开始:角度 += 1缩放 += 0.01如果缩放>5:缩放 = 1pygame.draw.line(screen, (0, 255, 0), (pos[0]-20, pos[1]), (pos[0]+20, pos[1]), 3)pygame.draw.line(screen, (0, 255, 0), (pos[0], pos[1]-20), (pos[0], pos[1]+20), 3)pygame.draw.circle(screen, (0, 255, 0), pos, 7, 0)pygame.display.flip()pygame.quit()出口()

                  I loaded an image and I want it to rotate around its center, while its scale is getting larger. I know how to rotate an image around its center originally, but it's hard for me to calculate the position if the scale is getting larger. I tried it, but the image just 'dances', not staying in the center.

                  解决方案

                  Short answer:

                  Store the center of the source image rectangle and update the center of the rotated and zoomed image rectangle after the rotation and zoom operation, by the stored center position. Rotate and zoom the image by pygame.transform.rotozoom():

                  def blitRotateCenter(surf, image, topleft, angle):
                      
                      center = image.get_rect(topleft = topleft).center
                      rotated_image = pygame.transform.rotozoom(image, angle, scale)
                      new_rect = rotated_image.get_rect(center = center)
                  
                      surf.blit(rotated_image, new_rect.topleft)
                  


                  Long Answer:

                  An image (pygame.Surface) can be rotated by pygame.transform.rotate.

                  If that is done progressively in a loop, then the image gets distorted and rapidly increases:

                  while not done:
                  
                      # [...]
                  
                      image = pygame.transform.rotate(image, 1)
                      screen.blit(image, pos)
                      pygame.display.flip()
                  

                  This is cause, because the bounding rectangle of a rotated image is always greater than the bounding rectangle of the original image (except some rotations by multiples of 90 degrees).
                  The image gets distort because of the multiply copies. Each rotation generates a small error (inaccuracy). The sum of the errors is growing and the images decays.

                  That can be fixed by keeping the original image and "blit" an image which was generated by a single rotation operation form the original image.

                  angle = 0
                  while not done:
                  
                      # [...]
                  
                      rotated_image = pygame.transform.rotate(image, angle)
                      angle += 1
                  
                      screen.blit(rotated_image, pos)
                      pygame.display.flip()
                  

                  Now the image seems to arbitrary change its position, because the size of the image changes by the rotation and origin is always the top left of the bounding rectangle of the image.

                  This can be compensated by comparing the axis aligned bounding box of the image before the rotation and after the rotation.
                  For the following math pygame.math.Vector2 is used. Note in screen coordinates the y points down the screen, but the mathematical y axis points form the bottom to the top. This causes that the y axis has to be "flipped" during calculations

                  Set up a list with the 4 corner points of the bounding box:

                  w, h = image.get_size()
                  box = [pygame.math.Vector2(p) for p in [(0, 0), (w, 0), (w, -h), (0, -h)]]
                  

                  Rotate the vectors to the corner points by pygame.math.Vector2.rotate:

                  box_rotate = [p.rotate(angle) for p in box]
                  

                  Get the minimum and the maximum of the rotated points:

                  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 "compensated" origin of the upper left point of the image by adding the minimum of the rotated box to the position. For the y coordinate max_box[1] is the minimum, because of the "flipping" along the y axis:

                  origin = (pos[0] + min_box[0], pos[1] - max_box[1])
                  
                  rotated_image = pygame.transform.rotate(image, angle)
                  screen.blit(rotated_image, origin)
                  

                  To define a pivot on the original image, the "translation" of the pivot in relation to the upper left of the image has to be calculated and the "blit" position of the image has to be displaced by the translation.

                  Define a pivot e.g. in the center of the image:

                  pivot = pygame.math.Vector2(w/2, -h/2)
                  

                  Calculate the translation of the rotated pivot:

                  pivot_rotate = pivot.rotate(angle)
                  pivot_move   = pivot_rotate - pivot
                  

                  Finally calculate the origin of the rotated image:

                  origin = (pos[0] + min_box[0] - pivot_move[0], pos[1] - max_box[1] + pivot_move[1])
                  
                  rotated_image = pygame.transform.rotate(image, angle)
                  screen.blit(rotated_image, origin)
                  

                  If the image has to be additionally zoomed, then the zoom has to be taken into account when the origin of the image is calculated:

                  move   = (-pivot[0] + min_box[0] - pivot_move[0], pivot[1] - max_box[1] + pivot_move[1])
                  origin = (pos[0] + zoom * move[0], pos[1] + zoom * move[1])
                  
                  rotozoom_image = pygame.transform.rotozoom(image, angle, zoom)
                  screen.blit(rotozoom_image, origin)
                  

                  In the following example program, the function blitRotate does all the above steps and "blit" a rotated image to a surface. pos is the position of the image. originPos is the point on the image which is placed on pos and the pivot.


                  Minimal example:

                  import pygame
                  
                  pygame.init()
                  screen = pygame.display.set_mode((300, 300))
                  clock = pygame.time.Clock()
                  
                  def blitRotate(surf, image, pos, originPos, angle, zoom):
                  
                      # calcaulate the axis aligned bounding box of the rotated image
                      w, h       = image.get_size()
                      box        = [pygame.math.Vector2(p) for p in [(0, 0), (w, 0), (w, -h), (0, -h)]]
                      box_rotate = [p.rotate(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(originPos[0], -originPos[1])
                      pivot_rotate = pivot.rotate(angle)
                      pivot_move   = pivot_rotate - pivot
                  
                      # calculate the upper left origin of the rotated image
                      move   = (-originPos[0] + min_box[0] - pivot_move[0], -originPos[1] - max_box[1] + pivot_move[1])
                      origin = (pos[0] + zoom * move[0], pos[1] + zoom * move[1])
                  
                      # get a rotated image
                      rotozoom_image = pygame.transform.rotozoom(image, angle, zoom)
                    
                      # rotate and blit the image
                      surf.blit(rotozoom_image, origin)
                  
                      # draw rectangle around the image
                      pygame.draw.rect (surf, (255, 0, 0), (*origin, *rotozoom_image.get_size()),2)
                  
                  try:
                      image = pygame.image.load('AirPlaneFront1-128.png')
                  except:
                      text = pygame.font.SysFont('Times New Roman', 50).render('image', False, (255, 255, 0))
                      image = pygame.Surface((text.get_width()+1, text.get_height()+1))
                      pygame.draw.rect(image, (0, 0, 255), (1, 1, *text.get_size()))
                      image.blit(text, (1, 1))
                  w, h = image.get_size()
                  
                  start = False
                  angle, zoom = 0, 1
                  done = False
                  while not done:
                      clock.tick(60)
                      for event in pygame.event.get():
                          if event.type == pygame.QUIT:
                              done = True
                          elif event.type == pygame.KEYDOWN or event.type == pygame.MOUSEBUTTONDOWN:
                              start = True
                  
                      pos = (screen.get_width()/2, screen.get_height()/2)
                      
                      screen.fill(0)
                      blitRotate(screen, image, pos, (w/2, h/2), angle, zoom)
                      if start:
                          angle += 1
                          zoom += 0.01
                          if zoom > 5:
                              zoom = 1
                  
                      pygame.draw.line(screen, (0, 255, 0), (pos[0]-20, pos[1]), (pos[0]+20, pos[1]), 3)
                      pygame.draw.line(screen, (0, 255, 0), (pos[0], pos[1]-20), (pos[0], pos[1]+20), 3)
                      pygame.draw.circle(screen, (0, 255, 0), pos, 7, 0)
                  
                      pygame.display.flip()
                      
                  pygame.quit()
                  exit()
                  

                  这篇关于如何在其比例变大时围绕其中心旋转图像(在 Pygame 中)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!

                  上一篇:对 Python 集类进行子类化、添加新实例变量的正确(或最佳)方法是什么? 下一篇:使用 PIL 在 python 中旋转并将扩展参数设置为 true 时指定图像填充颜色

                  相关文章

                  <legend id='2wlpp'><style id='2wlpp'><dir id='2wlpp'><q id='2wlpp'></q></dir></style></legend>

                    <small id='2wlpp'></small><noframes id='2wlpp'>

                    <tfoot id='2wlpp'></tfoot>
                  1. <i id='2wlpp'><tr id='2wlpp'><dt id='2wlpp'><q id='2wlpp'><span id='2wlpp'><b id='2wlpp'><form id='2wlpp'><ins id='2wlpp'></ins><ul id='2wlpp'></ul><sub id='2wlpp'></sub></form><legend id='2wlpp'></legend><bdo id='2wlpp'><pre id='2wlpp'><center id='2wlpp'></center></pre></bdo></b><th id='2wlpp'></th></span></q></dt></tr></i><div id='2wlpp'><tfoot id='2wlpp'></tfoot><dl id='2wlpp'><fieldset id='2wlpp'></fieldset></dl></div>

                        <bdo id='2wlpp'></bdo><ul id='2wlpp'></ul>