flash on 2013-1-30
/**
* Copyright mutantleg ( http://wonderfl.net/user/mutantleg )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/zaV4
*/
package {
import flash.ui.Keyboard;
import flash.geom.*;
import flash.display.*;
import flash.utils.ByteArray;
import flash.events.*;
import flash.text.TextField;
import com.adobe.utils.AGALMiniAssembler;
import flash.display3D.*;
import flash.display3D.textures.Texture;
public class FlashTest extends Sprite {
/*
2013-02-18 update: fixed fog
*/
public static var deb:TextField;
public var tmap:wTmap;
public function FlashTest() {
deb = new TextField();
addChild(deb);
deb.width = 400;
deb.text = " debug ";
deb.y = 250;
tmap = new wTmap();
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}//ctor
public function init(e:Event=null):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
stage.stage3Ds[0].addEventListener(Event.CONTEXT3D_CREATE, contReady);
stage.stage3Ds[0].addEventListener(ErrorEvent.ERROR, onError);
stage.stage3Ds[0].requestContext3D(Context3DRenderMode.AUTO);
}//init
private var context:Context3D;
public function onError(e:ErrorEvent):void
{
deb.text = e.text;
deb.textColor = 0xFF0000FF;
}//onerror
public function contReady(e:Event):void
{
deb.text = "context ready ";
context = stage.stage3Ds[0].context3D;
deb.text = context.driverInfo;
//deb.textColor = 0xFFffFFff;
context.addEventListener(ErrorEvent.ERROR, onError);
context.configureBackBuffer(200, 200, 2, true);
initProgram(context);
myTex = new wTex();
myTex.genTex(myTex.getXor(64,64), context);
plTex = new wTex();
plTex.genTex(plTex.getXor(64,64,true,false,false),context);
grTex = new wTex();
grTex.genTex(plTex.getXor(64,64,false,true,false),context);
geo = new wGeo();
// geo.makeSprite();
// geo.makeCube();
geo.makePlane(32,32,64,64);
geo.upload(context);
pgeo = new wGeo();
pgeo.makeCube();
pgeo.upload(context);
tblock = new wGeo();
tblock.makeBlock();
tblock.upload(context);
/*
var pic:Bitmap;
pic = new Bitmap(new BitmapData(200,200,false,0));
context.clear();
draw(context);
context.drawToBitmapData(pic.bitmapData);
//context.present();
addChild(pic);
pic.x = 200;
pic.y =100;
*/
stage.addEventListener(Event.ENTER_FRAME, onEnter);
stage.addEventListener(KeyboardEvent.KEY_DOWN, kdown);
stage.addEventListener(KeyboardEvent.KEY_UP, kup);
}//contready
public function screenShot():void
{
var pic:Bitmap;
pic = new Bitmap(new BitmapData(400,400,false,0));
context.clear();
draw(context);
context.drawToBitmapData(pic.bitmapData);
addChild(pic);
}//shot
public var vecKey:Vector.<Boolean> = new Vector.<Boolean>(512,false);
public function kdown(e:KeyboardEvent):void
{
vecKey[e.keyCode] = true;
if (e.keyCode == Keyboard.M) { screenShot(); }
}//kdown
public function kup(e:KeyboardEvent):void { vecKey[e.keyCode] = false; }
public var tblock:wGeo;
public var prog:Program3D;
public var myTex:wTex;
public var plTex:wTex;
public var grTex:wTex;
public var geo:wGeo;
public var pgeo:wGeo;
public var pyaw:Number = -1.57;
public var px:Number = 3;
public var py:Number = 1;
public var pz:Number = 4;
public var vx:Number = 0;
public var vy:Number = 0;
public var vz:Number = 0;
public function initProgram(c:Context3D):void
{
prog = c.createProgram();
var vert:ByteArray;
var frag:ByteArray;
var assembler:AGALMiniAssembler = new AGALMiniAssembler();
// VERTEX,9, fogRange);
// FRAGMENT, 1, fogConst);
// FRAGMENT, 2, fogColor);
//fogging based on
//http://ryanspeets.com/flash/agalminiassembler-primer/
var code:String;
code = "";
code += "m44 vt0, va0, vc0\n";
code += "m44 v0, va1, vc4\n";
code += "sub vt1.z, vc9.y, vt0.w\n";
code += "div vt1.w, vt1.z, vc9.z\n";
//code += "sat v1, vt1.w\n"; //fix -- feb18 2013
code += "mov v1, vt1.w\n";
code += "mov op, vt0\n";
vert = assembler.assemble(Context3DProgramType.VERTEX, code);
//note: clamp 1-0 (sat) should be done in the fragment shader
code = "";
code += "tex ft0 v0, fs0 <2d, linear, miplinear, wrap>\n";
code += "sat ft5, v1\n" //fix -- feb18 2013
code += "mul ft1.xyz, ft0.xyz, ft5\n"
code += "sub ft2.x, fc1.x, v1\n"
code += "mul ft3, fc2, ft2.x\n"
code += "add ft4.xyz, ft1.xyz, ft3.xyz\n"
code += "mov ft4.w, ft0.w\n"
code += "mov oc, ft4\n";
// code += "mov oc, ft0\n";
frag = assembler.assemble(Context3DProgramType.FRAGMENT, code);
prog.upload(vert, frag);
}//initprogram;
public var bInWall:Boolean = false;
public function onEnter(e:Event):void
{
vy -= 0.01;
vx *= 0.92;
vz *= 0.92;
bInWall = tmap.isWall(px,pz);
if (vx > 0 && tmap.isWall(px+0.75,pz)) { vx = 0; }
if (vx < 0 && tmap.isWall(px-0.75,pz)) { vx = 0; }
if (vz > 0 && tmap.isWall(px,pz+0.75)) { vz = 0; }
if (vz < 0 && tmap.isWall(px,pz-0.75)) { vz = 0; }
if (tmap.isWall(px+0.4,pz) ) { px -= 0.05; }
if (tmap.isWall(px-0.4,pz) ) { px += 0.05; }
if (tmap.isWall(px,pz+0.4) ) { pz -= 0.05; }
if (tmap.isWall(px,pz-0.4) ) { pz += 0.05; }
px += vx;
py += vy;
pz += vz;
if (vy < 0 && py <0.5) { py =0.5; vy = 0;}
if (vecKey[Keyboard.UP]) { vx+= Math.cos(pyaw)*0.02; vz+=Math.sin(pyaw)*0.02; }
if (vecKey[Keyboard.DOWN]) { vx-= Math.cos(pyaw)*0.02; vz-=Math.sin(pyaw)*0.02; }
if (vecKey[Keyboard.LEFT]) { pyaw -= 0.2; }
if (vecKey[Keyboard.RIGHT]) { pyaw += 0.2; }
render();
}//onenter
public function render():void
{
context.clear();
draw(context);
context.present();
}//render
public var camx:Number = 0;
public var camy:Number = 0;
public var camz:Number = 0;
public var projmat:Matrix3D = new Matrix3D();
public var cammat:Matrix3D = new Matrix3D();
public var mat:Matrix3D = new Matrix3D();
public var texMat:Matrix3D = new Matrix3D();
public var ang:Number = 0;
public var spin:Number = 0;
public var fogRange:Vector.<Number> = Vector.<Number>([0.1, 3, 3-0.1,0 ]);
public var fogColor:Vector.<Number> = Vector.<Number>([1,0,0,1]);
public var fogConst:Vector.<Number> = Vector.<Number>([1,0,0,0]);
public function draw(c:Context3D):void
{
var color:Vector.<Number> = Vector.<Number>([1.0,1.0,1.0,1.0]);
c.setCulling(Context3DTriangleFace.BACK);
c.setProgram(prog);
spin += 5;
mat.identity();
mat.appendTranslation(0,0,0);
// mat.appendRotation(spin, Vector3D.Y_AXIS);
// mat.appendRotation(spin, Vector3D.X_AXIS);
var tx:Number;
var ty:Number;
var tz:Number;
tx = px - Math.cos(pyaw)*4;
tz = pz - Math.sin(pyaw)*4;
camy = 0.5;
camx = px; //camx+(tx-camx)*0.5;
camz = pz; //camz +(tz-camz)*0.5;
// camx -= Math.cos(pyaw) *0.5;
// camz -= Math.sin(pyaw) *0.5;
cammat.identity();
// cammat.appendTranslation(0,-1,-5);// + Math.cos(ang)-1);
cammat.appendTranslation(-camx,-camy,-camz);
cammat.appendRotation((pyaw+1.57)*(180.0/3.1415), Vector3D.Y_AXIS);
// cammat.appendRotation(20, Vector3D.X_AXIS);
setProjectionMatrix(projmat,90,1,0.1,1000);
mat.append(cammat);
mat.append(projmat);
ang += 0.03;
var vec:Vector.<Number>;
var s:Number;
texMat.identity();
/*
texMat.appendTranslation(-0.5,-0.5,0);
texMat.appendRotation(Math.cos(ang)*180.0, Vector3D.Z_AXIS);
s = Math.sin(ang)+2;
//texMat.appendScale(s,s,s);
texMat.appendTranslation(0.5,0.5,0);
*/
c.setProgramConstantsFromVector(Context3DProgramType.VERTEX,9, fogRange);
c.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT, 1, fogConst);
c.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT, 2, fogColor);
//draw ground
c.setTextureAt(0, myTex.tex);
c.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX, 0, mat, true);
c.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX, 4, texMat, true);
c.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT, 0, color);
c.setVertexBufferAt(0, geo.bufVert, 0, Context3DVertexBufferFormat.FLOAT_3);
c.setVertexBufferAt(1, geo.bufUv, 0, Context3DVertexBufferFormat.FLOAT_2);
c.drawTriangles(geo.bufFace, 0, geo.numFace);
//draw player
c.setTextureAt(0, plTex.tex);
mat.identity();
mat.appendScale(1.2,1,1);
mat.appendRotation(-pyaw*(180.0/3.1415),Vector3D.Y_AXIS);
if (bInWall)
{
mat.appendRotation(25, Vector3D.Z_AXIS);
}
mat.appendTranslation(px,py,pz);
// mat.appendRotation(pyaw*(180.0/3.1415),Vector3D.Y_AXIS);
mat.append(cammat);
mat.append(projmat);
c.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX, 0, mat, true);
c.setVertexBufferAt(0, pgeo.bufVert, 0, Context3DVertexBufferFormat.FLOAT_3);
c.setVertexBufferAt(1, pgeo.bufUv, 0, Context3DVertexBufferFormat.FLOAT_2);
c.drawTriangles(pgeo.bufFace, 0, pgeo.numFace);
//drawtilemap
c.setTextureAt(0, grTex.tex);
drawTmap(c);
}//draw
public function drawGeo(c:Context3D,gx:Number,gy:Number,gz:Number, g:wGeo):void
{
mat.identity();
mat.appendTranslation(gx,gy,gz);
mat.append(cammat);
mat.append(projmat);
c.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX, 0, mat, true);
c.setVertexBufferAt(0, g.bufVert, 0, Context3DVertexBufferFormat.FLOAT_3);
c.setVertexBufferAt(1, g.bufUv, 0, Context3DVertexBufferFormat.FLOAT_2);
c.drawTriangles(g.bufFace, 0, g.numFace);
}//drawgeo
public function drawTmap(c:Context3D):void
{
var mw:int;
var mh:int;
var k:int;
var i:int;
var yt:int;
var t:int;
var vec:Vector.<int>;
vec = tmap.vecMap;
mw = tmap.mwidth;
mh = tmap.mheight;
for (i = 0; i < mh; i++)
{
yt = i * mw;
for (k = 0; k < mw; k++)
{
t = vec[yt+k];
if (t <= 0) {continue;}
drawGeo(c, k, 0, i, tblock);
}//nextk
}//nexti
}//drawtmap
public function setProjectionMatrix(m:Matrix3D,
fovdeg:Number = 90.0, aspect:Number=1.0, nearp:Number = 0.1, farp:Number=1000.0):void
{
var vec:Vector.<Number> = m.rawData;
var f:Number;
var i:int;
for (i = 0; i < 16; i++) { vec[i] = 0.0; }
f = 1.0 / Math.tan( (fovdeg * (3.1415 / 180.0)) * 0.5 );
if (nearp == 0) { nearp = 0.0001; }
if (farp == 0) { farp = 0.0001; }
vec[0] = f / aspect;
vec[5] = f;
vec[10] = (farp + nearp) / (nearp - farp);
vec[14] = (2.0 * farp * nearp) / (nearp - farp);
vec[11] = -1.0;
vec[15] = 0.0;
m.rawData = vec;
}//projmatrix
}//classend
}
import flash.events.ErrorEvent;
import flash.geom.Matrix;
import flash.display.BitmapData;
import flash.display3D.textures.Texture;
import flash.display3D.*;
internal class wTex
{
public var tex:Texture = null;
public function wTex() {}
public function getXor(w:int, h:int, red:Boolean=true,green:Boolean=true,blue:Boolean=true):BitmapData
{
var bm:BitmapData;
var k:int;
var i:int;
bm = new BitmapData(w,h,false,0);
for (i = 0; i < h; i++)
{
for (k = 0; k < w; k++)
{
bm.setPixel(k,i, (red ? ((i^k)<<16):0) | (green ? ((i ^ k) << 8):0) | (blue ? (i^k):0));
}//nextk
}//nexti
return bm;
}//getxor
public function genTex(bm:BitmapData, c:Context3D):void
{
var s:int; //scale
var m:int; //miplevel
if (bm.width % 2 != 0 || bm.height %2 != 0 || bm.width != bm.height)
{
bm = getResized(bm, 64, 64);
}//endif
tex = c.createTexture(bm.width, bm.height, Context3DTextureFormat.BGRA, false);
tex.uploadFromBitmapData( bm , 0);
m = 1;
s = bm.width*0.5;
while (s > 0)
{
tex.uploadFromBitmapData(getResized(bm, s, s), m);
m += 1;
s *= 0.5;
}//wend
}//gentex
private var tempMat:Matrix = new Matrix();
private function getResized(bm:BitmapData, w:int, h:int):BitmapData
{
var ret:BitmapData;
var mat:Matrix;
mat = tempMat;
//mat.identity();
mat.a = w / bm.width;
mat.d = h / bm.height;
ret = new BitmapData(w, h, bm.transparent, 0);
ret.draw(bm, mat, null, null, null, true);
return ret;
}//getresized
};//classend
internal class wTmap
{
public var mwidth:int = 0;
public var mheight:int = 0;
public var vecMap:Vector.<int>;
public function wTmap()
{
vecMap = Vector.<int>([
1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,0,0,0,0,0,0,0,0,1,
1,1,0,0,1,1,1,1,0,0,0,1,
1,0,0,0,1,0,0,0,0,0,0,1,
1,0,0,0,1,1,1,1,0,0,0,1,
1,0,0,0,1,0,0,0,0,0,1,1,
1,0,0,0,1,0,0,0,0,0,0,1,
1,0,0,0,0,0,0,0,1,0,0,1,
1,1,1,1,1,1,1,1,1,1,1,1
]);
mwidth = 12;
mheight = 9;
}//ctor
public function isWall(wx:Number, wy:Number):Boolean
{
var tx:int;
var ty:int;
tx = Math.floor(wx);
ty = Math.floor(wy);
if (tx < 0) { return false; }
if (ty < 0) { return false; }
if (tx >= mwidth) { return false; }
if (ty >= mheight) { return false; }
return (vecMap[ty*mwidth+tx] > 0);
}//iswall
}//wtmap
internal class wGeo
{
public var vecVert:Vector.<Number> ;
public var vecUv:Vector.<Number> ;
public var vecFace:Vector.<uint> ;
public var bufVert:VertexBuffer3D;
public var bufUv:VertexBuffer3D;
public var bufFace:IndexBuffer3D;
public var numFace:int = 0;
public function wGeo()
{}//ctor
public function upload(c:Context3D):void
{
if (bufVert != null) { bufVert.dispose(); }
if (bufUv != null) { bufUv.dispose(); }
if (bufFace != null) { bufFace.dispose(); }
var numVert:int;
// var numFace:int;
numVert = Math.floor( vecVert.length / 3);
numFace = Math.floor( vecFace.length / 3);
bufVert = c.createVertexBuffer(numVert, 3);
bufUv = c.createVertexBuffer(numVert, 2);
bufFace = c.createIndexBuffer(numFace*3);
bufVert.uploadFromVector(vecVert, 0, numVert);
bufFace.uploadFromVector(vecFace, 0, numFace * 3);
bufUv.uploadFromVector(vecUv, 0, numVert);
}//upload
//make quad (2 tris)
public function makeSprite():void
{
var p:Number;
var n:Number;
var scale:Number;
scale = 1.0;
p = 0.5 * scale;
n = -0.5 * scale;
vecFace = Vector.<uint>([1, 0, 2, 1, 2, 3]);
vecVert = Vector.<Number>([
n, n, 0.0,
p, n, 0.0,
n, p, 0.0,
p, p, 0.0 ]);
vecUv = Vector.<Number>([
0.0, 0.0,
1.0, 0.0,
0.0, 1.0,
1.0, 1.0 ]);
}//makesprite
public function makePlane(w:Number=1.0, h:Number=1.0,
tw:Number=1.0, th:Number=1.0):void
{
vecFace = new Vector.<uint>;
vecVert = new Vector.<Number>;
vecUv = new Vector.<Number>;
var nw:Number;
var nh:Number;
var pw:Number;
var ph:Number;
nw = -0.5 * w;
pw = 0.5 * w;
nh = -0.5 * h;
ph = 0.5 * h;
addQuad(
[nw,0,nh, 0,0],
[pw,0,nh, tw,0],
[nw,0,ph, 0,th],
[pw,0,ph, tw,th]);
}//makeplane
public function makeCube():void
{
vecFace = new Vector.<uint>;
vecVert = new Vector.<Number>;
vecUv = new Vector.<Number>;
var n:Number;
var p:Number;
n = -0.5;
p = 0.5;
addQuad([n,n,n, 0,0],[p,n,n, 1,0], [n,p,n, 0,1], [p,p,n, 1,1]);
addQuad( [n,n,p, 0,0], [n,p,p, 1,0], [p,n,p, 0,1], [p,p,p, 1,1]);
addQuad( [n,n,n, 0,0], [n,n,p, 1,0], [p,n,n, 0,1], [p,n,p, 1,1]);
addQuad( [n,p,n, 0,0], [p,p,n, 1,0], [n,p,p, 0,1], [p,p,p, 1,1]);
addQuad( [n,n,n, 0,0], [n,p,n, 1,0], [n,n,p, 0,1], [n,p,p, 1,1]);
addQuad( [p,n,n, 0,0], [p,n,p, 1,0], [p,p,n, 0,1], [p,p,p, 1,1]);
}//makecube
public function makeBlock():void
{
vecFace = new Vector.<uint>;
vecVert = new Vector.<Number>;
vecUv = new Vector.<Number>;
var n:Number;
var p:Number;
n = 0; //-0.5;
p = 1; //0.5;
addQuad([n,n,n, 0,0],[p,n,n, 1,0], [n,p,n, 0,1], [p,p,n, 1,1]);
addQuad( [n,n,p, 0,0], [n,p,p, 1,0], [p,n,p, 0,1], [p,p,p, 1,1]);
addQuad( [n,n,n, 0,0], [n,n,p, 1,0], [p,n,n, 0,1], [p,n,p, 1,1]);
addQuad( [n,p,n, 0,0], [p,p,n, 1,0], [n,p,p, 0,1], [p,p,p, 1,1]);
addQuad( [n,n,n, 0,0], [n,p,n, 1,0], [n,n,p, 0,1], [n,p,p, 1,1]);
addQuad( [p,n,n, 0,0], [p,n,p, 1,0], [p,p,n, 0,1], [p,p,p, 1,1]);
}//makecube
public function addTri(v1:Array, v2:Array, v3:Array):void
{
if (v1.length < 5) { return; }
if (v2.length < 5) { return; }
if (v3.length < 5) { return; }
// var numFace:int;
// numFace = vecFace.length;
var numVert:int;
numVert = vecVert.length / 3;
vecVert.push(v1[0]); vecVert.push(v1[1]); vecVert.push(v1[2]);
vecUv.push(v1[3]); vecUv.push(v1[4]);
vecVert.push(v2[0]); vecVert.push(v2[1]); vecVert.push(v2[2]);
vecUv.push(v2[3]); vecUv.push(v2[4]);
vecVert.push(v3[0]); vecVert.push(v3[1]); vecVert.push(v3[2]);
vecUv.push(v3[3]); vecUv.push(v3[4]);
vecFace.push(numVert+0); vecFace.push(numVert+1); vecFace.push(numVert+2);
}//addface
public function addQuad(v1:Array, v2:Array, v3:Array, v4:Array):void
{
if (v1.length < 5) { return; }
if (v2.length < 5) { return; }
if (v3.length < 5) { return; }
if (v4.length < 5) { return; }
//var numFace:int;
//numFace = vecFace.length;
var numVert:int;
numVert = vecVert.length / 3;
vecVert.push(v1[0]); vecVert.push(v1[1]); vecVert.push(v1[2]);
vecUv.push(v1[3]); vecUv.push(v1[4]);
vecVert.push(v2[0]); vecVert.push(v2[1]); vecVert.push(v2[2]);
vecUv.push(v2[3]); vecUv.push(v2[4]);
vecVert.push(v3[0]); vecVert.push(v3[1]); vecVert.push(v3[2]);
vecUv.push(v3[3]); vecUv.push(v3[4]);
vecVert.push(v4[0]); vecVert.push(v4[1]); vecVert.push(v4[2]);
vecUv.push(v4[3]); vecUv.push(v4[4]);
vecFace.push(numVert+0); vecFace.push(numVert+1); vecFace.push(numVert+2);
vecFace.push(numVert+1); vecFace.push(numVert+3); vecFace.push(numVert+2);
}//addquad
};//classend