# “AS3.0高级动画编程”学习：第三章等角投影(上)

[转载]等角(斜45度)游戏与数学

[转载]使用illustrator和正交投影原理以及基本三视图制图

```package {
public class Point3D {
public var x:Number;
public var y:Number;
public var z:Number;
public function Point3D(x:Number=0,y:Number=0,z:Number=0) {
this.x=x;
this.y=y;
this.z=z;
}
}
}```

```package {

import flash.geom.Point;
public class IsoUtils {

//public static const Y_CORRECT:Number=Math.cos(- Math.PI/6)*Math.SQRT2;
public static const Y_CORRECT:Number = 1.2247448713915892;

//把等角空间中的一个3D坐标点转换成屏幕上的2D坐标点
public static function isoToScreen(pos:Point3D):Point {
var screenX:Number=pos.x-pos.z;
var screenY:Number=pos.y*Y_CORRECT+(pos.x+pos.z)*0.5;
return new Point(screenX,screenY);
}

//把屏幕上的2D坐标点转换成等角空间中的一个3D坐标点
public static function screenToIso(point:Point):Point3D {
var xpos:Number=point.y+point.x*.5;
var ypos:Number=0;
var zpos:Number=point.y-point.x*.5;
return new Point3D(xpos,ypos,zpos);
}
}
}```

```package {

import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.geom.Point;

[SWF(backgroundColor=0xefefef,height="200",width="300")]
public class IsoTransformTest extends Sprite {
public function IsoTransformTest() {
stage.align=StageAlign.TOP_LEFT;
stage.scaleMode=StageScaleMode.NO_SCALE;

var p0:Point3D=new Point3D(0,0,0);
var p1:Point3D=new Point3D(100,0,0);
var p2:Point3D=new Point3D(100,0,100);
var p3:Point3D=new Point3D(0,0,100);

var sp0:Point=IsoUtils.isoToScreen(p0);
var sp1:Point=IsoUtils.isoToScreen(p1);
var sp2:Point=IsoUtils.isoToScreen(p2);
var sp3:Point=IsoUtils.isoToScreen(p3);

var tile:Sprite = new Sprite();
tile.x=150;
tile.y=50;

tile.graphics.lineStyle(0);
tile.graphics.moveTo(sp0.x, sp0.y);
tile.graphics.lineTo(sp1.x, sp1.y);
tile.graphics.lineTo(sp2.x, sp2.y);
tile.graphics.lineTo(sp3.x, sp3.y);
tile.graphics.lineTo(sp0.x, sp0.y);

trace(Math.cos(- Math.PI/6)*Math.SQRT2);//1.2247448713915892
trace(tile.width,tile.height);//200 100 符合上面提到的2:1
}
}
}```

```package {
import flash.display.Sprite;
import flash.geom.Point;
import flash.geom.Rectangle;

public class IsoObject extends Sprite {

protected var _position:Point3D;
protected var _size:Number;
protected var _walkable:Boolean=false;

//public static const Y_CORRECT:Number=Math.cos(- Math.PI/6)*Math.SQRT2;
public static const Y_CORRECT:Number=1.2247448713915892;

public function IsoObject(size:Number) {
_size=size;
_position = new Point3D();
}

//更新屏幕坐标位置
protected function updateScreenPosition():void {
var screenPos:Point=IsoUtils.isoToScreen(_position);
super.x=screenPos.x;
super.y=screenPos.y;
}

override public function toString():String {
return "[IsoObject (x:" + _position.x + ", y:" + _position.y+ ", z:" + _position.z + ")]";
}

//设置等角空间3D坐标点的x,y,z值
override public function set x(value:Number):void {
_position.x=value;
}

override public function get x():Number {
return _position.x;
}

override public function set y(value:Number):void {
_position.y=value;
}
override public function get y():Number {
return _position.y;
}

override public function set z(value:Number):void {
_position.z=value;
}

override public function get z():Number {
return _position.z;
}

//_position的属性封装
public function set position(value:Point3D):void {
_position=value;
}
public function get position():Point3D {
return _position;
}

//深度排序时会用到，现在不用理这个
public function get depth():Number {
return (_position.x + _position.z) * .866 - _position.y * .707;
}

//这个暂时也不用理
public function set walkable(value:Boolean):void {
_walkable=value;
}
public function get walkable():Boolean {
return _walkable;
}

public function get size():Number {
return _size;
}

public function get rect():Rectangle {
return new Rectangle(x - size / 2, z - size / 2, size, size);
}
}
}```

```package {
public class DrawnIsoTile extends IsoObject {
protected var _height:Number;
protected var _color:uint;
public function DrawnIsoTile(size:Number,color:uint,height:Number=0) {
super(size);
_color=color;
_height=height;
draw();
}

//画矩形"贴片"
protected function draw():void {
graphics.clear();
graphics.beginFill(_color);
graphics.lineStyle(0,0,.5);
graphics.moveTo(- size,0);
graphics.lineTo(0,- size*.5);
graphics.lineTo(size,0);
graphics.lineTo(0,size*.5);
graphics.lineTo(- size,0);
}

//height属性暂时不用管（在draw里也没用到）
override public function set height(value:Number):void {
_height=value;
draw();
}
override public function get height():Number {
return _height;
}

//设置颜色
public function set color(value:uint):void {
_color=value;
draw();
}
public function get color():uint {
return _color;
}
}
}```

```package {
public class DrawnIsoBox extends DrawnIsoTile {
public function DrawnIsoBox(size:Number, color:uint, height:Number) {
super(size, color, height);
}
override protected function draw():void {
graphics.clear();

//提取r,g,b三色分量
var red:int=_color>>16;
var green:int=_color>>8&0xff;
var blue:int=_color&0xff;

//假如光源在右上方（所以左侧最暗，顶上最亮，右侧在二者之间）
var leftShadow:uint = (red * .5) << 16 |(green * .5) << 8 |(blue * .5);
var rightShadow:uint = (red * .75) << 16 |(green * .75) << 8 | (blue * .75);
var h:Number=_height*Y_CORRECT;

//顶部
graphics.beginFill(_color);
graphics.lineStyle(0, 0, .5);
graphics.moveTo(-_size, -h);
graphics.lineTo(0, -_size * .5 - h);
graphics.lineTo(_size, -h);
graphics.lineTo(0, _size * .5 - h);
graphics.lineTo(-_size, -h);
graphics.endFill();

//左侧
graphics.lineStyle(0, 0, .5);
graphics.moveTo(-_size, -h);
graphics.lineTo(0, _size * .5 - h);
graphics.lineTo(0, _size * .5);
graphics.lineTo(-_size, 0);
graphics.lineTo(-_size, -h);
graphics.endFill();

//右侧
graphics.lineStyle(0, 0, .5);
graphics.moveTo(_size, -h);
graphics.lineTo(0, _size * .5 - h);
graphics.lineTo(0, _size * .5);
graphics.lineTo(_size, 0);
graphics.lineTo(_size, -h);
graphics.endFill();
}
}
}```

```package {

import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.events.*;
import flash.events.MouseEvent;
import flash.geom.Point;
[SWF(backgroundColor=0xffffff,height=380,width=600)]
public class BoxTest extends Sprite
{
private var world:Sprite;

public function BoxTest()
{
stage.align = StageAlign.TOP_LEFT;
stage.scaleMode = StageScaleMode.NO_SCALE;
world = new Sprite();
world.x = stage.stageWidth / 2;
world.y = 50;
for(var i:int = 0; i < 15; i++)
{
for(var j:int = 0; j < 15; j++)
{
var tile:DrawnIsoTile = new DrawnIsoTile(20, 0xcccccc);
tile.position = new Point3D(i * 20, 0, j * 20);
}
}
}

private function onWorldClick(event:MouseEvent):void
{
var box:DrawnIsoBox = new DrawnIsoBox(20, Math.random() * 0xffffff, 20);
var pos:Point3D = IsoUtils.screenToIso(new Point(world.mouseX, world.mouseY));
pos.x = Math.round(pos.x / 20) * 20;
pos.y = Math.round(pos.y / 20) * 20;
pos.z = Math.round(pos.z / 20) * 20;
box.position = pos;
}

private function resizeHandler(e:Event):void{
world.x = stage.stageWidth / 2;
}
}
}```

0 条评论

• ### flash：二次贝塞尔曲线应用-生成飞机路径示意图

本周听到公司其它项目组同事在讨论一个小需求： 给定3个点（其实是飞机经过的航站，比如：从浦东-西安-北京），在UI上生成一段曲线，用来示意飞机的路线图（其实用直...

• ### “AS3.0高级动画编程”学习：第四章 寻路（AStar/A星/A*）算法 (上)

一提到“A*算法”，可能很多人都有"如雷贯耳"的感觉。用最白话的语言来讲：把游戏中的某个角色放在一个网格环境中，并给定一个目标点和一些障碍物，如何让角色快速“绕...

• ### 安装树莓派实验的Pi 仪表盘

树莓派仪表盘网址：Pi Dashboard (Pi 仪表盘) - MAKER 趣无尽  http://maker.quwj.com/project/10

• ### 【Java】几道常见的秋招面试题

Redis目前还在看，今天来分享一下我在秋招看过(遇到)的一些面试题(相对比较常见的)

• ### 十道常见的面试题

值得一说的是：并不是被final修饰的成员变量就一定是编译期常量了。比如说我们可以写出这样的代码：private final int java3y = new ...

• ### Android 带你撸一个好玩的 DoodleView（涂鸦）

可以看到这个这个自定义 View 的功能还是很丰富的，无论是设置画笔的形状、颜色、粗细，还是进行重置和保存，该有的 API，基本都已经实现了。有需要的读者直接 ...

• ### 吐血推荐：这个开源工具你值得拥有，让你轻松面对各种调试

前天晚上分享了一篇国人把 GitHub 玩出新高度的文章，培训机构的学员为了找工作买卖 GitHub 账号，很多人说：其实面试的时候，只要深度一点的询问，一问就...