zoukankan      html  css  js  c++  java
  • 简单的2d图形变换--仿设变换AffineTransform

    在ios中常常遇到些小的动画效果,比如点击一个按钮后,按钮上的三角形图片就旋转了。这种简单的小动画,常常通过更改view的transform属性来实现。这个transform属性,就是一个仿射变化矩阵。

    什么是AffineTransform呢?先看看百度上的说法:

    AffineTransform类描述了一种二维仿射变换的功能,它是一种二维坐标到二维坐标之间的线性变换,保持二维图形的“平直性”和“平行性”。仿射变换可以通过一系列的原子变换的复合来实现。

    .
                        | a,  b,  0 |
    {x',y',1}={x,y,1} x | c,  d,  0 |
                        | tx, ty, 1 |

    我们平常遇到的2d变化,比如平移(Translation)、缩放(Scale)、翻转(Flip)、旋转(Rotation)和错切(Shear),都可以通过不同的仿射矩阵进行变化。其实,在ios中,系统为我们提供了不少的函数,可以根据需要,创建不同的变换矩阵。比如CGAffineTransformRotate等等。

    下面举例说明几个仿射矩阵:

    1 view的默认仿射矩阵是

    | 1,  0,  0 |
    | 0,  1,  0 |
    | 0,  0,  1 |

    那么 x' = 1*x+0*y+0  ;   y' = 0*x +1*y +0;

    2 平移的放射矩阵是

    | 1,  0,  0 |
    | 0,  1,  0 |
    |tx, ty,  1 |

    这种变化有2种看法:即可以看成坐标系不变,图形相对于原点进行位移;也可以看做系统移动了坐标系,并在新的坐标系上绘图。第一种理解方法更为直接,不容易出错。

    3 看一张通用变换的图解,同样出自百度

    这张图,表示了从 P点从S坐标系的坐标,经过变化,转化为T坐标系的坐标的计算过程。

    在这个顺时针旋转的例子中,Xtp = Ysp*sin0y + Xsp*cos0x + Xto,可以看出,如果x轴和y轴的转动角度相同,那么坐标变换矩阵中的 b和a的比值,就是tan0,也就是说,向量(a,b)可以表示旋转的方向。这一点可以在许多动画中用到,比如下列代码

    -(void)fireBullet
    {
        // Don't fire bullets if the ship is destroyed.
        if(_ship == nil) return;
        
        // This is sort of a fancy math way to figure out where to fire the bullet from.
        // You could figure this out with more code, but I wanted to have fun with some maths.
        // This gets the transform of one of the "gunports" that I marked in the CCB file with a special node.
        CGAffineTransform transform = _ship.gunPortTransform;
        
        // An affine transform looks like this when written as a matrix:
        // | a, c, tx |
        // | b, d, ty |
        // The first column, (a, b), is the direction the new x-axis will point in.
        // The second column, (c, d), is the direction the new y-axis will point in.
        // The last column, (tx, ty), is the location of the origin of the new transform.
        
        // The position of the gunport is just the matrix's origin point (tx, ty).
        CGPoint position = ccp(transform.tx, transform.ty);
        
        // The original sprite pointed downwards on the y-axis.
        // So the transform's y-axis, (c, d), will point in the opposite direction of the gunport.
        // We just need to flip it around.
        CGPoint direction = ccp(-transform.c, -transform.d);
        
        // So by "fancy math" I really just meant knowing what the numbers in a CGAffineTransform are. ;)
        // When I make my own art, I like to align things on the positive x-axis to make the code "prettier".
        
        // Now we can create the bullet with the position and direction.
        Bullet *bullet = (Bullet *)[CCBReader load:@"Bullet"];
        bullet.position = position;
        //bullet.rotation = -CC_RADIANS_TO_DEGREES(ccpToAngle(direction));
        
        // Make the bullet move in the direction it's pointed.
        bullet.physicsBody.velocity = ccpMult(direction, bullet.speed);
        
        [_physics addChild:bullet];
        [_bullets addObject:bullet];
        
        // Give the bullet a finite lifetime.
        [bullet scheduleBlock:^(CCTimer *timer){
            [self destroyBullet:bullet];
        } delay:bullet.duration];
        
        // Make some noise. Add a little chromatically tuned pitch bending to make it more musical.
        int half_steps = (arc4random()%(2*4 + 1) - 4);
        float pitch = pow(2.0f, half_steps/12.0f);
        [[OALSimpleAudio sharedInstance] playEffect:@"Laser.wav" volume:1.0 pitch:pitch pan:0.0 loop:NO];
    }

    这段代码是cocos2d-iphone官网demo的一部分代码,它的作用就是用户点击屏幕时,根据当前飞船的位置和方向,设置子弹精灵的旋转角度和起始坐标,让子弹看起来像是从飞船中发射出的。注意这里的  CGPoint direction = ccp(-transform.c, -transform.d); 它的原理就是利用了放射变换矩阵的数学意义,得到了飞船的y轴旋转方向,并利用这个向量旋转子弹精灵。

  • 相关阅读:
    【HDOJ6667】Roundgod and Milk Tea(模拟)
    【HDOJ6655】Just Repeat(贪心)
    【HDOJ6651】Final Exam(贪心)
    【HDOJ6646】A + B = C(模拟)
    【HDOJ6656】Kejin Player(期望DP)
    【2019 Multi-University Training Contest 7】
    【HDOJ6635】Nonsense Time(时间倒流,lis)
    【HDOJ6638】Snowy Smile(线段树)
    【HDOJ6641】TDL(数论)
    【HDOJ6645】Stay Real(堆)
  • 原文地址:https://www.cnblogs.com/breezemist/p/3554368.html
Copyright © 2011-2022 走看看