向量学习2:图形围绕自己中心旋转围绕图形外或内任意点为中心旋转
Posted geng_zhaoying
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了向量学习2:图形围绕自己中心旋转围绕图形外或内任意点为中心旋转相关的知识,希望对你有一定的参考价值。
在前边博文“向量学习1”中,介绍了在篮球游戏中,防守者逼近防守投篮者,如何用向量,计算逼近的方向以及前进的距离。方法可用篮球投篮、足球射门和射击的子弹轨迹等等方面。在pygame游戏中,可能图形围绕自己中心旋转;也可能象地球围绕太阳那样,图形围绕远处某点旋转;也可能象坦克炮那样旋转,线形图形以线端点为中心旋转。本文用例子说明用向量实现的方法。首先介绍图形围绕图形自己中心旋转。见下边代码。
p=pygame.image.load("L1.png").convert_alpha()
rect=p.get_rect(center=(150,100))
p1=pygame.transform.rotate(p,10) #将p图旋转10度,返回旋转后的Surface实例
r=p1.get_rect(center=rect.center) #如注释此条语句
screen.blit(p1, r) #同时注释此条语句
#screen.blit(p1,(150,100)) #改为此条语句,将发生抖动
其中第3条语句将p图以p图中心点为旋转中心旋转10度,返回旋转后的Surface实例p1。请注意,每次返回的p1图的中心点可能不重合,为了使图形在原位置显示,第4条语句将p1中心点修改为p图中心点。如按照注释修改,去掉两句,增加一句,在连续旋转时,就会看到图形抖动。本例使用两个图形作为旋转对象,如下图,一条水平线,一个圆,为了看到圆转动,圆有1个突起。后边要用到,凸起和x轴夹角为0。
实际例子完整程序如下。
import pygame
bgcolor = pygame.Color('blue')
pygame.init()
size = width, height = 400,300
screen = pygame.display.set_mode(size)
pygame.display.set_caption("原地旋转")
p=pygame.image.load("c.png").convert_alpha()
rect=p.get_rect(center=(150,100))
fclock = pygame.time.Clock()
fps = 10
angle=0
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
screen.fill(bgcolor)
angle+=10
p1=pygame.transform.rotate(p, angle)
r=p1.get_rect(center=rect.center) #如注释此条语句
screen.blit(p1, r) #同时注释此条语句
#screen.blit(p1,(150,100)) #改为此条语句,将发生抖动
pygame.display.flip()
fclock.tick(fps)
pygame.quit()
3张效果图如下。第1图旋转的图形是圆,第2图是一条水平线段,两图都没有抖动。在第3图可看到水平线段有明显抖动。从第2图可以验证是以图形中心点为旋转中心完成旋转。
如果希望图形象地球绕太阳那样旋转,也就是图形旋转中心不是图形中心点,而是图形外某点,这就需要向量的概念。为了看懂下边论述,有必要解释“向量”和“有向线段”概念。数学意义上的向量,只有方向和长度,向量的位置是没有意义的。但实际上,在程序中处理的向量是在游戏坐标系中的有向线段,位置还是必要的。可以这样理解,有向线段是指定了位置的向量,因此,向量的许多概念和方法也适用于有向线段,下边论述中的向量一般是指有向线段。首先看下边两条语句。
v=pygame.math.Vector2(100,0)
v1 = v.rotate(angle)
第1条语句建立从(0,0)到(100,0)的向量v,该向量和x轴夹角为0,即向量角度为0,长度为100。第2条语句的旋转中心为(0,0),即围绕(0,0)旋转指定角度,旋转后产生新向量v1,起点不变,还是(0,0)。如果每帧中,v向量旋转某角度得到v1后,都把图形放到v1向量头部显示,连续重复这两个动作,就看到图形围绕(0,0)旋转。但问题是pygame游戏坐标,x轴向右为正,y轴向下为正,而且x和y只取正值,即只要x或y有一个为负,图形就不可见,如果围绕(0,0)旋转,只有1/4可见,其余不可见。为此,可把实际的旋转中心移动屏幕中央,例如(240,180)。具体办法是:每次v围绕(0,0)旋转指定角度后,平移v1向量起点到(240,180)为v2,把图形放到v2向量头部显示,每帧中连续重复这两个动作,就看到图形围绕(240,180)旋转了。
那么如何平移向量呢?数学上一条线段,其起点和终点x或y坐标都增加同一个值,生成新线段,例如x都加240,y加180,则这两条线段平行,也就是平移了向量。猜想平移v1到(240,180)可能程序表达式是:v2=(240,180)+v1。为此做了验证,见下图。图中r,a=v.as_polar()是得到向量v的长度r及方向即和x轴夹角。执行了v1=(240,180)+v后,向量v和v1的长度和角度都相同,只是头部终点不同,说明该表达式确实实现了平移。
注意,按上述方法平移后,向量起点总是(240,180)保持不变,向量终点由于旋转,总在变化。也就是说,平移后,图形围绕(240,180)点旋转。总结一下,(240,180)点是旋转中心,v向量长度100是旋转半径。一般使图形中点(center)移到向量的终点。完整程序如下,使用的图像是有凸起的圆。
import pygame
bgcolor = pygame.Color('blue')
pygame.init()
size = width, height = 480,360
screen = pygame.display.set_mode(size)
pygame.display.set_caption("圆围绕某点旋转")
p=pygame.image.load("c.png").convert_alpha()
length=100 #旋转半径
#length=p.get_rect().width//2
v=pygame.math.Vector2(length,0)#从(0,0)到(length,0)的向量,此时旋转中心为(0,0)
c=(240.0,180.0) #以后将要设置的旋转中心
fclock = pygame.time.Clock()
fps = 10
angle=0
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
screen.fill(bgcolor) #背景颜色
angle-=5 #正数是顺时针,负数是逆时针
p1=pygame.transform.rotate(p, -angle+180) #使圆突出部分指向圆心
v1 = v.rotate(angle) #有向线段v1旋转,起点不变为(0,0),终点旋转,坐标改变
#下句等式右侧将v1平移,x轴方向右移240,y轴方向下移180,有向线段起点为(240,180)
a,b=c+v1 #因此旋转中心不变,终点旋转,坐标改变,(a,b)是平移后向量顶点坐标
#v2=c+v1 #此句也正确,坐标元组+向量使向量v1平移到v2
#r=p1.get_rect(center=(240,180)+v1)#使用此句提示将来版本可能不支持默认类型转换
r=p1.get_rect() #改为下边两句,将图形移到平移后向量顶点
r.center=(int(a),int(b))
screen.blit(p1, r) #在新位置显示图形
pygame.display.flip() #刷新游戏场景
fclock.tick(fps)#fps是每秒多少帧,减去程序运行时间,为实现fps,还需延迟时间
pygame.quit()
#a=v.angle_to(v1)#两个向量之间的夹角
效果图如下。
凸起的圆围绕(240,180)点旋转,按以上叙述,圆的凸起应该指向x轴正方向保持不变,但实际效果是这个圆的凸起总是指向圆心。这是因为有如下语句:
angle-=5 #angle是向量每帧旋转角度
p1=pygame.transform.rotate(p, -angle+180) #使圆突出部分指向圆心
v1 = v.rotate(angle) #向量旋转给定角度
其中第2句使图形p(即圆)旋转了一个角度,使圆突出部分指向圆心。这个角度如何得到的呢?首先向量的初始位置角度为0,同样圆的凸起和x轴夹角也为0(见最上边的图形中的圆),两者同向。在这个位置,要让圆的凸起指向圆心,必须旋转180度,如向量再旋转angle,凸起的圆也要自转(-angle+180),这样使圆的凸起总是指向圆心。
最后解决使线形图形以线端点为中心,象坦克炮那样旋转。前边提到v向量长度100是旋转半径,只要修改v向量长度等于要旋转图形宽度一半,在使线形图形水平摆放,即和x轴夹角为0即可,本程序只要把上述程序第9条语句注释去掉即可,并将程序第9条语句的图形文件名称改为线段图形名称:L1.png即可。效果图如下。
以上是关于向量学习2:图形围绕自己中心旋转围绕图形外或内任意点为中心旋转的主要内容,如果未能解决你的问题,请参考以下文章