開発環境 Apache Flex SDK 4.12.1
FlashDevelop 4.6.2.5
実行環境 Microsoft Windows 8.1 (64bit)
プロジェクトの種類 ActionScript 3/AS3 Project
プロジェクト名 CarRace


Main.as
package 
{
    import com.adobe.utils.*;
    import flash.display.*;
    import flash.display3D.*;
    import flash.events.*;
    import flash.geom.*;
    import flash.text.*;
    import flash.ui.Keyboard;
    import mx.utils.StringUtil;
 
    public class Main extends Sprite 
    {
        [Embed(source="course1.png")]
        private const CourseBitmap:Class;
        private var bitmap:Bitmap = new CourseBitmap;
        private var bitmapData:BitmapData = bitmap.bitmapData;
 
        private var context3D:Context3D;
        private var vertexBuffer:VertexBuffer3D;
        private var indexBuffer:IndexBuffer3D;
 
        private var projectionTransform:PerspectiveMatrix3D;
        private var cameraWorldTransform:Matrix3D;
        private var viewTransform:Matrix3D;
 
        private var carVelocity:Vector3D = new Vector3D;
        private var carAcceleration:Number = 0;
        private var carRotation:Number = 0;
 
        private var tf:TextField = new TextField;
 
        public function Main():void 
        {
            if (stage) init();
            else addEventListener(Event.ADDED_TO_STAGE, init);
        }
 
        private function init(e:Event = null):void 
        {
            removeEventListener(Event.ADDED_TO_STAGE, init);
            // entry point
 
            stage.stage3Ds[0].addEventListener(Event.CONTEXT3D_CREATE, onContext3DCreate);
            stage.stage3Ds[0].requestContext3D();
 
            addEventListener(Event.ENTER_FRAME, onRender);
 
            stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
            stage.addEventListener(KeyboardEvent.KEY_UP, onKeyUp);
 
            tf.defaultTextFormat = new TextFormat(null, 20, 0x000000);
            tf.autoSize = TextFieldAutoSize.LEFT;
            addChild(tf);
        }
 
        private function onContext3DCreate(e:Event):void 
        {
            context3D = stage.stage3Ds[0].context3D;
            context3D.configureBackBuffer(800, 600, 2);
            context3D.setCulling(Context3DTriangleFace.BACK);
 
            const vertices:Vector.<Number> = Vector.<Number>([
            //  x, y, z, r, g, b,
                0, 0, 0, 1, 1, 1,
                1, 0, 0, 1, 1, 1,
                1, 0, 1, 1, 1, 1,
                0, 0, 1, 1, 1, 1,
                0, 1, 0, 1, 1, 0,
                1, 1, 0, 1, 1, 0,
                1, 1, 1, 1, 1, 0,
                0, 1, 1, 1, 1, 0,
            ]);
            const indices:Vector.<uint> = Vector.<uint>([
                0, 4, 5, 5, 1, 0,
                1, 5, 6, 6, 2, 1,
                2, 6, 7, 7, 3, 2,
                3, 7, 4, 4, 0, 3,
            ]);
 
            var vertexData:Vector.<Number> = new Vector.<Number>;
            var indexData:Vector.<uint> = new Vector.<uint>;
            var numVertices:int = 0;
            for (var y:int = 0; y < 64; y++) 
            {
                for (var x:int = 0; x < 64; x++) 
                {
                    var color:uint = bitmapData.getPixel(x, y);
                    if (color == 0) continue;
 
                    for (var i:int = 0; i < 8; i++) 
                    {
                        var base:int = i * 6;
                        vertexData.push(vertices[base + 0] + x);
                        vertexData.push(vertices[base + 1]);
                        vertexData.push(vertices[base + 2] + y);
                        vertexData.push(vertices[base + 3]);
                        vertexData.push(vertices[base + 4]);
                        vertexData.push(vertices[base + 5]);
                    }
                    for (i = 0; i < indices.length; i++) 
                    {
                        indexData.push(numVertices + indices[i]);
                    }
                    numVertices += 8;
                }
            }
 
            // vertexBuffer
            vertexBuffer = context3D.createVertexBuffer(numVertices, 6);
            vertexBuffer.uploadFromVector(vertexData, 0, numVertices);
 
            // indexBuffer
            indexBuffer = context3D.createIndexBuffer(indexData.length);
            indexBuffer.uploadFromVector(indexData, 0, indexData.length);
 
            // program
            var vertexProgram:AGALMiniAssembler = new AGALMiniAssembler;
            vertexProgram.assemble(Context3DProgramType.VERTEX,
                "m44 op va0 vc0\n" +
                "mov v0 va1"
            );
            var fragmentProgram:AGALMiniAssembler = new AGALMiniAssembler;
            fragmentProgram.assemble(Context3DProgramType.FRAGMENT,
                "mov oc v0"
            );
            var program:Program3D = context3D.createProgram();
            program.upload(vertexProgram.agalcode, fragmentProgram.agalcode);
 
            //
            cameraWorldTransform = new Matrix3D;
            cameraWorldTransform.appendTranslation(32, 0.2, 52);
            cameraWorldTransform.appendRotation(90, Vector3D.Y_AXIS, cameraWorldTransform.position);
            viewTransform = cameraWorldTransform.clone();
            viewTransform.invert();
 
            projectionTransform = new PerspectiveMatrix3D;
            projectionTransform.perspectiveFieldOfViewLH(45 * Math.PI / 180, 800 / 600, 0.1, 50);
 
            //
            context3D.setVertexBufferAt(0, vertexBuffer, 0, Context3DVertexBufferFormat.FLOAT_3);
            context3D.setVertexBufferAt(1, vertexBuffer, 3, Context3DVertexBufferFormat.FLOAT_3);
            context3D.setProgram(program);
        }
 
        private function onRender(e:Event):void 
        {
            if (!context3D) return;
 
            context3D.clear(0.39, 0.58, 0.93);
            updateViewMatrix();
 
            var m:Matrix3D = new Matrix3D;
            m.append(viewTransform);
            m.append(projectionTransform);
 
            context3D.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX, 0, m, true);
            context3D.drawTriangles(indexBuffer);
            context3D.present();
 
            tf.text = StringUtil.substitute(
                "Velocity:{0}",
                carVelocity.z.toFixed(3));
        }
 
        private function updateViewMatrix():void 
        {
            carVelocity.z = calculateUpdateVelocity(carVelocity.z, carAcceleration, 1);
 
            var degrees:Number = carRotation * (carVelocity.z == 0 ? 3 : 1);
            cameraWorldTransform.appendRotation(
                degrees, Vector3D.Y_AXIS, cameraWorldTransform.position);
 
            var pos:Vector3D = cameraWorldTransform.transformVector(carVelocity);
            var color:uint = bitmapData.getPixel(pos.x, pos.z);
            if (color == 0)
            {
                cameraWorldTransform.position = pos;
            }
            else
            {
                carVelocity.z = 0;
                carAcceleration = 0;
            }
 
            viewTransform.copyFrom(cameraWorldTransform);
            viewTransform.invert();
        }
 
        private function calculateUpdateVelocity(
            curVelocity:Number, curAcceleration:Number, maxVelocity:Number):Number 
        {
            var newVelocity:Number = curVelocity + curAcceleration;
            if (maxVelocity < newVelocity) return maxVelocity;
            if (newVelocity < 0) return 0;
            return newVelocity;
        }
 
        private function onKeyDown(e:KeyboardEvent):void 
        {
            switch (e.keyCode) 
            {
                case Keyboard.Z:
                    carAcceleration = -0.003;
                    break;
                case Keyboard.X:
                    carAcceleration = 0.001;
                    break;
                case Keyboard.LEFT:
                    carRotation = -1;
                    break;
                case Keyboard.RIGHT:
                    carRotation = 1;
                    break;
            }
        }
 
        private function onKeyUp(e:KeyboardEvent):void 
        {
            switch (e.keyCode) 
            {
                case Keyboard.Z:
                case Keyboard.X:
                    carAcceleration = 0;
                    break;
                case Keyboard.LEFT:
                case Keyboard.RIGHT:
                    carRotation = 0;
                    break;
            }
        }
 
    }
 
}
 
最終更新:2014年07月17日 21:19