FollowMe

May 7, 2012 Leave a comment

package
{
import away3d.cameras.lenses.OrthogonalLens;
import away3d.cameras.SpringCam;
import away3d.containers.View3D;
import away3d.primitives.Cube;
import away3d.primitives.Sphere;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.geom.Vector3D;
import flash.ui.Keyboard;
/**
* …
* @author Shiu
*/
public class FollowMe extends Sprite
{
private var _cube:Cube, _sphere1:Sphere, _sphere2:Sphere;
private var _view:View3D;
private var followerCam:SpringCam;
private var forward:Boolean, backward:Boolean, turnLeft:Boolean, turnRight:Boolean;

public function FollowMe()
{
followerCam = new SpringCam();

_view = new View3D(); addChild(_view);
_view.x = stage.stageWidth >> 1;
_view.y = stage.stageHeight >> 1;
_view.addEventListener(Event.ENTER_FRAME, update);
_view.camera = followerCam;

_cube = new Cube(); _view.scene.addChild(_cube);
_sphere1 = new Sphere(); _view.scene.addChild(_sphere1);
_sphere1.x += 300
_sphere2 = new Sphere(); _view.scene.addChild(_sphere2);
_sphere2.x -= 300

followerCam.target = _cube;
followerCam.positionOffset = new Vector3D(0, 200, -1000);
followerCam.stiffness = 5;
followerCam.damping = 20;

stage.addEventListener(KeyboardEvent.KEY_DOWN, keyFunction);
stage.addEventListener(KeyboardEvent.KEY_UP, keyFunction);
}

private function keyFunction(e:KeyboardEvent):void
{
if(e.type == “keyDown”){
if (e.keyCode == Keyboard.UP) forward = true;
else if (e.keyCode == Keyboard.DOWN) backward = true;
if (e.keyCode == Keyboard.LEFT) turnLeft = true;
else if (e.keyCode == Keyboard.RIGHT) turnRight = true;
}
else if (e.type == “keyUp”) {
if (e.keyCode == Keyboard.UP) forward = false;
else if (e.keyCode == Keyboard.DOWN) backward = false;
if (e.keyCode == Keyboard.LEFT) turnLeft = false;
else if (e.keyCode == Keyboard.RIGHT) turnRight = false;
}
}

private function update(e:Event):void {
if (forward) _cube.z += 100;
else if (backward) _cube.z -= 100;

if(turnLeft) _cube.rotationY += 10;
else if(turnRight) _cube.rotationY -= 10;

followerCam.view
_view.render();
}
}

}

Categories: Uncategorized

Vector2D

April 29, 2012 Leave a comment

package
{
/**
* Vector2D
* Purpose: Utility class to assist in Vector manipulation in a 2D environment
* @author Shiu
* @version 1.0 9 August 2011
* @version 2.0 22 August 2011
*/
public class Vector2D
{
private var _vecX:Number;
private var _vecY:Number;

/**
* Constructor of Vector2D
* @param mc_x x-component of vector
* @param mc_y y-component of vector
*/
public function Vector2D(mc_x:Number, mc_y:Number)
{
this._vecX = mc_x;
this._vecY = mc_y;
}

/**
* Provision for an alternate constructor
* @param mag Magnitude of vector
* @param ang_rad Orientation of vector in radians
*/
public function polar (mag:Number, ang_rad:Number):void
{
this._vecX = mag*Math.cos(ang_rad);
this._vecY = mag*Math.sin(ang_rad);
}

/**
* Accessors of individual x-component
*/
public function set x(new_x:Number):void
{
this._vecX = new_x;
}

public function get x ():Number
{
return this._vecX;
}

/**
* Accessors of individual y-component
*/
public function set y(new_y:Number):void
{
this._vecY = new_y;
}

public function get y ():Number
{
return _vecY;
}

/**
* Method to obtain the vector
* @return A vector array of x and y components
*/
public function getVector ():Vector.<Number>
{
return new <Number>[_vecX, _vecY]
}

/**
* Method to obtain current angle of vector
* @return Angle in radians
*/
public function getAngle ():Number
{
return Math.atan2(_vecY, _vecX);
}

/**
* Method tl alter current angle of vector
* @param ang_rad New angle for current vector in radians
*/
public function setAngle(ang_rad:Number):void
{
var mag_current:Number = this.getMagnitude();
this.polar(mag_current, ang_rad);
}

/**
* Method to obtain current magnitude of vector
* @return Magnitude of type Number
*/
public function getMagnitude():Number
{
return Math.sqrt(_vecX * _vecX + _vecY * _vecY);
}

/**
* Method ot alter current magnitude of vector
* @param magnitude New magnitude of vector
*/
public function setMagnitude(magnitude:Number):void
{
var ang_current:Number = this.getAngle();
this.polar(magnitude, ang_current);
}

/**
* Method to invert both x and y components of vector
*/
public function invert():void
{
_vecX *= -1;
_vecY *= -1;
}

/**
* Version 2.0
* Method to invert only the x-component of Vector2D
*/
public function invertX():void
{
_vecX *= -1;
}

/**
* Version 2.0
* Method to invert only the x-component of Vector2D
*/
public function invertY():void
{
_vecY *= -1;
}

/**
* Version 2.0
* Method to scale current vector by a scalar magnitude
* @param multiplier A scalar number to mulitply current vector
*/
public function scale (magnitude:Number):void
{
_vecX *= magnitude;
_vecY *= magnitude;
}

/**
* Method to generate a copy of current vector
* @return A copy of current vector
*/
public function clone ():Vector2D
{
var clone1:Vector2D = new Vector2D(_vecX, _vecY);
return clone1;
}

/**
* Method to perform subtration on current vector
* @param toMinus A vector to minus current vector
* @return A copy of subtration product
*/
public function minus(toMinus:Vector2D):Vector2D
{
var newX:Number = this._vecX – toMinus.x;
var newY:Number = this._vecY – toMinus.y;
return new Vector2D(newX, newY);
}

/**
* Method to perform addition on current vector
* @param toAdd A vector to add onto current vector
* @return A copy of addition product
*/
public function add(toAdd:Vector2D):Vector2D
{
var newX:Number = this._vecX + toAdd.x;
var newY:Number = this._vecY + toAdd.y;
return new Vector2D(newX, newY);
}

/**
* Version 2.0
* Method to multiply current vector with a certain magnitude
* @param multiplier
* @return A copy of the multiplied product
*/
public function multiply(multiplier:Number):Vector2D
{
var newX:Number = this._vecX * multiplier;
var newY:Number = this._vecY * multiplier;
return new Vector2D(newX, newY);
}

/**
* Method to rotate current vector
* @param angle_rad Angle in radian to rotate current vector
* @param offset A vector to offset current circular into an eliptical course
* @return A copy of the rotated vector
*/
public function rotate(angle_rad:Number):Vector2D
{
var newX:Number = _vecX * Math.cos(angle_rad) – _vecY * Math.sin(angle_rad);
var newY:Number = _vecX * Math.sin(angle_rad) + _vecY * Math.cos(angle_rad);

return new Vector2D(newX, newY);
}

/**
* Method to obtain vector unit of current vector
* @return A copy of normalised vector
*/
public function normalise():Vector2D
{
return new Vector2D(this._vecX/this.getMagnitude(), this._vecY/this.getMagnitude())
}

/**
* Method to perform dot product with another vector
* @param vector2 A vector to perform dot product with current vector
* @return A scalar number of dot product
*/
public function dotProduct(vector2:Vector2D):Number
{
var componentX:Number = this._vecX * vector2.x;
var componentY:Number = this._vecY * vector2.y;
return componentX+componentY;
}

/**
* Method to perform perpendiculart dot product with another vector
* @param vector2 A vector on the plane of projection
* @param rightNormal Decide whether to project onto the right or left normal
* @return A scalar number of perp dot product
*/
public function perpProduct(vector2:Vector2D, rightNormal:Boolean = true): Number
{
var componentY:Number, componentX:Number;
if(rightNormal){
componentX = this._vecY * vector2.x;
componentY = -1*this._vecX * vector2.y;
}
else {
componentX = -1*this._vecY * vector2.x;
componentY = this._vecX * vector2.y;
}
return componentX+componentY;
}

/**
* Method to perform vector product of current vector with input vector
* @param vector2 A vector to perform vector product with current vector
* @return The magnitude of pseudo-vector on z-axis
*/
public function vectorProduct(vector2:Vector2D):Number
{
return this._vecX * vector2.y – this._vecY * vector2.x;
}

/**
* Method to obtain the smaller angle, in radian, sandwiched from current vector to input vector
* @param vector2 A vector to bound the angle
* @return Angle in radian, positive is clockwise, negative is anti-clockwise
*/
public function angleBetween(vector2:Vector2D):Number
{
//get normalised vectors
var norm1:Vector2D = this.normalise();
var norm2:Vector2D = vector2.normalise();

//dot product of vectors to find angle
var product:Number = norm1.dotProduct(norm2);
product = Math.min(1, product);
var angle:Number = Math.acos(product);

//sides of angle
if (this.vectorProduct(vector2) < 0) angle *= -1
return angle;
}

/**
* Method to obtain the projection of current vector on a given axis
* @param axis An axis where vector is projected on
* @return The projection length of current vector on given axis
*/
public function projectionOn(axis:Vector2D):Number
{
return this.dotProduct(axis.normalise())
}

/**
* Method to obtain normal
* @param right Decide whether to return the right or left normal.
*/
public function getNormal(rightNormal:Boolean = true):Vector2D
{
var normal:Vector2D = new Vector2D(0,0);
if(rightNormal){
normal.x = -1*this._vecY
normal.y = this._vecX
}
else {
normal.x = this._vecY
normal.y = -1*this._vecX
}
return normal;
}
}

}

Categories: Uncategorized

Circle.as

April 25, 2012 Leave a comment

package
{
import flash.display.Sprite;
/**
* Circle
* Purpose: Circle object
* @author Shiu
*/
public class Circle extends Sprite
{
private var _col:Number, _radius:Number;
private var _drawBound:Boolean = false;

public function Circle(color:Number, radius:Number = 10) {
_col = color, _radius = radius;
draw();
}

private function draw():void {
graphics.lineStyle(1);
graphics.beginFill(_col);
graphics.drawCircle(0, 0, _radius);
graphics.endFill();
}

public function set color (value:Number):void {
_col = value;
graphics.clear()
draw();
}

public function get radius ():Number {
return _radius;
}

public function set showBound(status:Boolean):void {
_drawBound = status;
graphics.clear();
draw()
if(_drawBound){
graphics.lineStyle(1);
graphics.drawRect(_radius * -1, _radius * -1, _radius*2, _radius*2);

}
}

public function get showBound ():Boolean {
return _drawBound;
}

}

}

Categories: Uncategorized

Lighting

April 23, 2012 Leave a comment

package
{
import away3d.containers.View3D;
import away3d.lights.PointLight3D;
import away3d.materials.WhiteShadingBitmapMaterial;
import away3d.primitives.Sphere;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
/**
* …
* @author Shiu
*/
public class AssignLighting extends Sprite
{
private var _view:View3D;
private var sp:Sphere;
private var light:PointLight3D;

[Embed(source = “../lib/Earth_Diffuse_2.jpg”)]
private var Earth:Class;

public function AssignLighting()
{
_view = new View3D(); addChild(_view);
_view.x = stage.stageWidth >> 1;
_view.y = stage.stageHeight >> 1;

//one fill color, perlin noise and bitmap
var bmp:BitmapData = new BitmapData(100, 100, true, 0xffAAAAAA);
//var bmp : BitmapData = new BitmapData(200, 200);
//bmp.perlinNoise(200, 200, 2, Math.random(), true, true);

//var earthBmp:Bitmap = new Earth as Bitmap;
//var bmp:BitmapData = new BitmapData(640, 320);
//bmp.draw(earthBmp);

sp = new Sphere(); _view.scene.addChild(sp);
sp.segmentsH = 10; sp.segmentsW = 10;
sp.material = new WhiteShadingBitmapMaterial(bmp);

light = new PointLight3D(); _view.scene.addLight(light);
light.z = -500; light.brightness = 0.1;

addEventListener(MouseEvent.MOUSE_DOWN, interact);
_view.addEventListener(MouseEvent.MOUSE_MOVE, interact);
_view.addEventListener(MouseEvent.MOUSE_WHEEL, interact);
_view.addEventListener(Event.ENTER_FRAME, refresh);
}

private function interact(e:MouseEvent):void
{
if (e.type == “mouseDown”) {
light.brightness += 0.1;
}
if(e.type == “mouseMove”){
sp.x = mouseX – stage.stageWidth * 0.5;
sp.y = -(mouseY – stage.stageHeight * 0.5);
}
if (e.type == “mouseWheel”) {
if (e.delta > 0) sp.z -= 100;
if (e.delta < 0) sp.z += 100;
}
}

private function refresh(e:Event):void
{
sp.rotationY += 1;
_view.render();
}

}

}

Categories: Uncategorized

Source for Basic3D

March 26, 2012 Leave a comment

package
{
import flash.display.TriangleCulling;
import flash.display.Sprite;
import flash.events.Event;
import net.richardlord.coral.Matrix3d;
import net.richardlord.coral.Point3d;
import net.richardlord.coral.Vector3d;

/**
* …
* @author Shiu
*/
public class Proj_3D2 extends Sprite
{
private var modelSpace:Vector.<Vector3d>
private var worldSpace:Vector.<Vector3d>
private var local:Vector3d;

private var projected:Vector.<Number>
private var dex:Vector.<int>;

public function Proj_3D2()
{
modelSpace = new Vector.<Vector3d>;
modelSpace.push(new Vector3d( -50, -50, -50)); //A
modelSpace.push(new Vector3d( 50, -50, -50)); //B
modelSpace.push(new Vector3d( 50, 50, -50)); //C
modelSpace.push(new Vector3d( -50, 50, -50)); //D

modelSpace.push(new Vector3d( -50, -50, 50)); //E
modelSpace.push(new Vector3d( 50, -50, 50)); //F
modelSpace.push(new Vector3d( 50, 50, 50)); //G
modelSpace.push(new Vector3d( -50, 50, 50)); //H

worldSpace = new Vector.<Vector3d>;
worldSpace = modelSpace;

local = new Vector3d(stage.stageWidth*0.2, stage.stageHeight >> 1, 100);
addEventListener(Event.ENTER_FRAME, refresh);
}

private function refresh(e:Event):void
{
//spin(10);
convert2World();
prepareData();
//perspective();
draw();
}

private function perspective():void
{

}

private function spin(angle:Number):void
{
var m3:Matrix3d = new Matrix3d();
m3.appendRotation(angle / 180 * Math.PI, Vector3d.Y_AXIS);

modelSpace = m3.transformVectors(modelSpace);
}

private function convert2World():void {
worldSpace = new Vector.<Vector3d>;
worldSpace.push(local.add(modelSpace[0])); //A
worldSpace.push(local.add(modelSpace[1])); //B
worldSpace.push(local.add(modelSpace[2])); //C
worldSpace.push(local.add(modelSpace[3])); //D

worldSpace.push(local.add(modelSpace[4])); //E
worldSpace.push(local.add(modelSpace[5])); //F
worldSpace.push(local.add(modelSpace[6])); //G
worldSpace.push(local.add(modelSpace[7])); //H
}

private function prepareData():void {
//verts
projected = new Vector.<Number>;
projected.push(
worldSpace[0].x, worldSpace[0].y,
worldSpace[1].x, worldSpace[1].y,
worldSpace[2].x, worldSpace[2].y,
worldSpace[3].x, worldSpace[3].y);

dex = new Vector.<int>;
dex.push(3, 0, 1,
3, 1, 2);
}

private function draw():void {
graphics.clear();
graphics.lineStyle(0);
graphics.beginFill(0xFF8000);
//graphics.drawTriangles(projected, dex, null,TriangleCulling.POSITIVE);
graphics.drawTriangles(projected, dex, null);
graphics.endFill();
}

}

}

Categories: Uncategorized

Example1

February 23, 2012 Leave a comment

v_mag = 5
v_ang = 0

c.onPress = function(){
c.startDrag()
}
c.onRelease = function(){
c.stopDrag()
}

b.onEnterFrame = function(){
dist = Pythagoras(b._x, b._y,c._x, c._y)
if(dist > 100){
v_ang = getAngle(b._x, b._y,c._x,c._y)
vx = v_mag*Math.cos(v_ang)
vy = v_mag*Math.sin(v_ang)

b._x += vx;
b._y += vy;
}
}

function getAngle(x1, y1,x2, y2):Number{
distX = x2-x1
distY = y2-y1
ang = Math.atan2(distY, distX)
return ang
}

/*b.onPress = function(){
b.startDrag()
}
b.onRelease = function(){
b.stopDrag()
}
b.onEnterFrame = function(){
//min = (b._width +c._width)*0.5
//dist = Pythagoras(b._x, b._y,c._x, c._y)

if(){
c._x += 1
}
}
*/
function Pythagoras(x1, y1,x2, y2):Number{
distX = x2-x1
distY = y2-y1
z = Math.sqrt(distX*distX + distY*distY)

return z
}

Categories: Basics

Let’s Get Started

February 20, 2012 Leave a comment

I’ve been delivering a module that introduces Mathematical manipulations to simulate physics environment in my workplace. It’s my interest to get students across the hurdle of programming interface in the shortest time and really dip into the Math. After trying several rounds of AS 2.0 and AS 3.0 with batches of students, I find students benefitted most when I used As 2.0.

While Actionscript 3.0 had been rocking for the past 5-6 years, whenever it comes to teaching and learning for fresh students (absolute beginner in programming), I still find Actionscript 2.0 superior. Here are a few observations:

  1. Less-overwhelmed. AS 2.0 has a smaller set of tools compared to AS 3.0. Students reach the boundary of what’s possible through API sooner and will look elsewhere like Math to improve + build upon the basic scaffolding provided through API calls.
  2. Syntatically simpler. Needless to say, they are able to write their own AS 2.0 easier.
  3. Structurally simpler. Although AS 2.0 do make use of event model, but structure required to write it is short. No separate function to do the event handling, you can write all in one line.
  4. Loosely typed. Variable declaration is loose. No need to get know the exact datatype of variables. Students will not know the whole extend of things they can create initially, so this help is valuable for jump start.

Now I’m not undermining the importance of knowing AS 3.0. My point is rather to start students off easily using AS 2.0, then only at level 2 (or upon their own effort) usher in migration to AS 3.0.

There’s advantage in knowing both these programming structures. AS 3.0 is mature in the way the language is structured and libraries are organised. It’s comparable to the way Java and C# programs are being written. On the other hand, AS 2.0 is a little similar to Javascript, which is used to develop HTML 5.0 games. So students get a taste of both worlds. As the need to program for different platform comes, they can quickly adapt because they are exposed already.

Categories: Basics