Flash/Flex学习笔记(18):画线及三角函数的基本使用

Sprite有一个graphics可以用来绘制基本图形,比如我们要画下面这个图形:

对应的AS3代码为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package {
    import flash.display.Sprite;
     
    public class Arrow extends Sprite {
        public function Arrow():void {
            init();
        }      
        private function init():void{              
            graphics.lineStyle(1,0,1);
            graphics.beginFill(0xffff99);
            graphics.drawCircle(0,0,2);//中心点
            graphics.moveTo(0,50);
            graphics.lineTo(100,50);
            graphics.lineTo(100,0);
            graphics.lineTo(150,75);
            graphics.lineTo(100,150);
            graphics.lineTo(100,100);
            graphics.lineTo(0,100);
            graphics.lineTo(0,50);
            graphics.endFill();        
        }
    }
}

把它加到舞台上,并自动跟着鼠标转动(下列代码写在第一帧):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var _arrow:Arrow = new Arrow();
addChild(_arrow);
_arrow.x=stage.stageWidth/2-50;
_arrow.y=stage.stageHeight/2-75;
 
this.addEventListener(Event.ENTER_FRAME,EnterFrameHandler);
 
function EnterFrameHandler(e:Event):void {
    var dx:Number=mouseX-_arrow.x;
    var dy:Number=mouseY-_arrow.y;
    //trace("dy=" + dy + ",dx=" + dx);
    var angle:Number=Math.atan2(dy,dx);
    _arrow.rotation=angle*180/Math.PI; 
}

这里用到了反正切函数,其原理示意图如下:

即以鼠标所在点与Arrow图形中心点为参考,构建一个三角形,利用对边比邻边得到正切,然后利用反正切求出角度,最终让图形旋转该角度,下面是效果:

但是好象有点问题,相信您也看出来了,因为我们绘制图形时,默认是以坐标原点为中心,而非图形中心点为中心,所以在跟随鼠标旋转时,总感觉有些错位,没关系,只要调整一下Arrow.cs即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package {
    import flash.display.Sprite;
     
    public class Arrow extends Sprite {
        public function Arrow():void {
            init();
        }      
        private function init():void{              
            graphics.lineStyle(1,0,1);
            graphics.beginFill(0xffff99);
            graphics.drawCircle(0,0,2);//中心点
            graphics.moveTo(-75,-25);
            graphics.lineTo(25,-25);
            graphics.lineTo(25,-75);
            graphics.lineTo(75,0);
            graphics.lineTo(25,75);
            graphics.lineTo(25,25);
            graphics.lineTo(-75,25);
            graphics.lineTo(-75,-25);
            graphics.endFill();        
        }
    }
}

另一个很有用的三角函数就是正弦Sin函数--对边比斜边

当Sin函数的角度参数从0度变化到360度时,正弦函数的值会在1到-1之间来回摆动,如果在动画中需要来回振荡的情况,正弦函数就派上用场了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package{
    import flash.display.Sprite;
     
    //小球 类
    public class Ball extends Sprite{
         
        private var radius:Number ;//半径
        private var color:uint;//颜色
         
        public function Ball(r:Number=50,c:uint=0xff0000){
            this.radius = r;
            this.color = c;
            init();
        }
         
        private function init():void{
            graphics.beginFill(color);
            graphics.drawCircle(0,0,radius);
            graphics.endFill();
        }
    }
}

这里我们先定义一个基本的小球类Ball,在接下来的动画里,我们让小球沿正弦轨迹运行,同时另一个小球模拟“心跳”运动(即改变大小)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
var angle:Number = 0;
 
//参数常量
const Y_SPEED = 0.1; //y轴移动速度
const X_SPEED = 1; //x轴移动速度
const AMPLITUDE = 50.0; //最大振幅
const X_START = 0; //x轴的起始点
 
//变量
var ySpeed:Number = Y_SPEED;
var xSpeed:Number = X_SPEED;
var amplitude:Number = AMPLITUDE;
 
var b:Ball = new Ball(5,0xff0000);
addChild(b);
b.x = X_START;
 
var heart:Ball = new Ball(50,0x0000ff);
addChild(heart);
heart.x = stage.stageWidth/2;
heart.y = stage.stageHeight/2;
heart.alpha = 0.3;
 
addEventListener(Event.ENTER_FRAME,EnterFrameHandler);
 
function EnterFrameHandler(e:Event){
    b.y = stage.stageHeight/2 + Math.sin(angle) * amplitude;
    angle += ySpeed;
    b.x += xSpeed;
     
    heart.scaleX = heart.scaleY = 1 + Math.sin(angle) * 0.5;
     
    graphics.lineStyle(1,0xefefef,1);
    graphics.lineTo(b.x,b.y);
     
     
    //x,y,振幅 逐渐加大
    xSpeed += 0.08;
    ySpeed += 0.003;
    amplitude += 1;
     
    if (b.x > stage.stageWidth + b.width){
        //超出舞台后,还原参数
        b.x = X_START;
        xSpeed = X_SPEED;
        ySpeed = Y_SPEED;
        amplitude = AMPLITUDE;
    }  
     
}

甚至还可以同时把正弦函数应用到多个属性:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
//参数常量
const Y_SPEED = 0.07; //y轴变化速度
const X_SPEED = 0.10; //x轴变化速度
const AMPLITUDE = 150.0; //最大振幅
const X_START = stage.stageWidth/2; //x轴的起始点
const Y_START = stage.stageHeight/2; //y轴的起始点
 
//变量
var ySpeed:Number = Y_SPEED;
var xSpeed:Number = X_SPEED;
var amplitude:Number = AMPLITUDE;
var angleX = 0;
var angleY = 0;
 
var b:Ball = new Ball(5,0xff0000);
addChild(b);
 
b.x = X_START;
b.y = Y_START;
 
graphics.moveTo(b.x,b.y);
 
addEventListener(Event.ENTER_FRAME,EnterFrameHandler);
 
function EnterFrameHandler(e:Event){   
 
    b.y = Y_START + Math.sin(angleY) * amplitude;
    b.x = X_START + Math.sin(angleX) * amplitude;
     
    angleX += xSpeed;
    angleY += ySpeed;
     
    //angleX += Math.random()/10;
    //angleY += Math.random()/5;
     
    graphics.lineStyle(1,0xefefef,1);
    graphics.lineTo(b.x,b.y);
}

如果把代码中的二行注释启用,即让x,y的变化速度改成随机,结果可能更有趣:

posted @   菩提树下的杨过  阅读(3586)  评论(0编辑  收藏  举报
编辑推荐:
· 深入理解 Mybatis 分库分表执行原理
· 如何打造一个高并发系统?
· .NET Core GC压缩(compact_phase)底层原理浅谈
· 现代计算机视觉入门之:什么是图片特征编码
· .NET 9 new features-C#13新的锁类型和语义
阅读排行:
· Sdcb Chats 技术博客:数据库 ID 选型的曲折之路 - 从 Guid 到自增 ID,再到
· 语音处理 开源项目 EchoSharp
· 《HelloGitHub》第 106 期
· Spring AI + Ollama 实现 deepseek-r1 的API服务和调用
· 使用 Dify + LLM 构建精确任务处理应用
历史上的今天:
2009-03-31 WCF运行错误:“此集合已经包含方案 http 的地址”的解决办法
点击右上角即可分享
微信分享提示