LockOnForever
LockOnForever.as
<Control>
Mouse Move : Move aim
Mouse Click : Shoot lock-on laser
+Z
` | /
`----+-----------/
` | / |
` | / | sc_depth
` | / |
`| / |
------+------------+X
0|` /sc_w |
| ` / | focalLength
| `/ |
| @ FP10's camera
// forked from keim_at_Si's Arena Shooting in 100 Lines
// LockOnForever.as
// <Control>
// Mouse Move : Move aim
// Mouse Click : Shoot lock-on laser
//
// +Z
//` | /
// `----+-----------/
// ` | / |
// ` | / | sc_depth
// ` | / |
// `| / |
//------+------------+X
// 0|` /sc_w |
// | ` / | focalLength
// | `/ |
// | @ FP10's camera
//
package {
import flash.display.*;
import flash.geom.*;
import flash.filters.*;
import flash.text.*;
import flash.events.*;
[SWF(width="465", height="465", backgroundColor="0x4080ff", frameRate="30")]
public class LockOnForever extends MovieClip {
public const SC_WIDTH:int = 465, SC_HEIGHT:int = 465, SC_DEPTH:Number = 465, FOV:Number = 90;
public const ENEMY_R:Number = 32, ENEMY_SPEED:Number = 2, ENEMY_COLOR:uint = 0x404040;
public const LASER_R:Number = 4, LASER_SPEED:Number = 16, LASER_COLOR:uint = 0x8080ff;
public const TRAIL_FRAME:int = 10, TRAIL_COLOR:uint = 0x4040ff, EXP_FRAME:int = 10, EXP_COLOR:uint = 0xff0000;
public var m_ScoreField:TextField = new TextField(), m_IsMousePressed:Boolean;
public var m_Laser:MovieClip = new MovieClip(), m_Range:MovieClip = new MovieClip();
public var m_Score:int = 0, m_Ticks:int = 0, m_EnemyPopDelay:int = 0, m_Locks:Array = [];
public var m_LockGlow:Array = [new GlowFilter(0xff0000, 1, 16, 16, 255)], m_NearDist:Number;
function LockOnForever() {
transform.perspectiveProjection.fieldOfView = FOV; // focalLegth has changed too.
m_NearDist = transform.perspectiveProjection.focalLength;
stage.addEventListener(MouseEvent.MOUSE_DOWN, function(e:Event):void { m_IsMousePressed = true; } );
stage.addEventListener(MouseEvent.MOUSE_UP , function(e:Event):void { m_IsMousePressed = false; } );
$(m_Range, {x:SC_WIDTH / 2, y:SC_HEIGHT / 2}, 0xffffff, SC_WIDTH / 2 + 16); // for outcheck
$(addChild(m_Laser), {visible:false, fn:updateLaser}, LASER_COLOR, LASER_R);
$(addChild(m_ScoreField), {selectable:false, width:SC_WIDTH});
addEventListener(Event.ENTER_FRAME, updateScene);
}
public function updateScene(event:Event):void { // scene
m_Ticks = (m_Laser.visible) ? (m_Ticks + 1) : 0;
m_ScoreField.htmlText = "<font color='#ff4040' size='" + (m_Laser.visible ? "20" : "40")
+ "' face='_sans'>Chains:" + String(m_Score) + "</font>";
if (--m_EnemyPopDelay <= 0) {
var ratio:Number = 1.0 + ((m_NearDist + SC_DEPTH) / m_NearDist - 1.0) * Math.random();
var ex:Number = SC_WIDTH / 2 + (SC_WIDTH / 2) * (Math.random() * 2 - 1) * ratio;
var ey:Number = SC_HEIGHT / 2 - SC_HEIGHT / 2 * ratio - ENEMY_R;
var ez:Number = -m_NearDist + m_NearDist * ratio;
$(addChild(new MovieClip()), {x:ex, y:ey, z:ez, fn:updateEnemy}, ENEMY_COLOR, ENEMY_R);
m_EnemyPopDelay = (12 + Math.random() * 25) * ((30 * 60 * 2) + m_Ticks) / (30 * 60 * 2);
}
}
public function updateEnemy(e:Event):void { // enemy
var a:* = e.target;
a.y += ENEMY_SPEED;
if (!a.hitTestObject(m_Range)) {
kill(a);
unlock(a);
return;
}
if (m_Locks.indexOf(a) < 0 && a.hitTestPoint(stage.mouseX, stage.mouseY)) { m_Locks.push(a); }
a.filters = (m_Locks.indexOf(a) < 0) ? [] : m_LockGlow;
applyFog(a);
}
public function updateLaser(e:Event):void { // laser
var a:* = e.target;
if (!a.visible) {
if (m_IsMousePressed && m_Locks.length > 0) {
$(m_Laser, {x:stage.mouseX, y:stage.mouseY, z:0, visible:true});
m_Score = 0;
}
return;
}
$(addChild(new MovieClip()), {x:a.x, y:a.y, z:a.z, frame:0, fn:updateTrail}, TRAIL_COLOR, LASER_R);
if (m_Locks.length == 0) {
a.move.z = 0;
}
else {
var t:* = m_Locks[0];
a.move = getPos(t).subtract(getPos(a));
if (a.move.length <= LASER_SPEED) {
$(addChild(new MovieClip()), {x:t.x, y:t.y, z:t.z, frame:0, fn:updateExp}, EXP_COLOR, ENEMY_R);
kill(t);
unlock(t);
m_Score++;
}
}
if (a.move.normalize() == 0) { a.move = new Vector3D(0,-1,0); }
a.move.scaleBy(LASER_SPEED);
setPos(a, getPos(a).add(a.move));
a.visible = (m_Locks.length > 0) || a.hitTestObject(m_Range);
}
public function updateTrail(e:Event):void { // laser trail
if (++e.target.frame >= TRAIL_FRAME) { kill(e.target); }
applyFog(e.target);
}
public function updateExp(e:Event):void { // enemy explosion
if ((e.target.alpha = (EXP_FRAME - (++e.target.frame)) / EXP_FRAME) == 0) { kill(e.target); }
}
public function $(a:*, props:*, color:uint=0, radius:Number=0):void { // property setter etc
for (var p:String in props) { a[p] = props[p]; }
if (props.fn) { a.addEventListener(Event.ENTER_FRAME, props.fn); }
if (radius == 0) { return; }
a.graphics.beginFill(color);
a.graphics.drawRect(-radius, -radius, radius * 2 + 1, radius * 2 + 1);
}
public function kill(a:*):void { a.parent.removeChild(a).removeEventListener(Event.ENTER_FRAME, a.fn); }
public function unlock(a:*):void { if (m_Locks.indexOf(a) >= 0) { m_Locks.splice(m_Locks.indexOf(a), 1); } }
public function getPos(a:*):Vector3D { return new Vector3D(a.x, a.y, a.z); }
public function setPos(a:*, v:Vector3D):void { a.x = v.x; a.y = v.y, a.z = v.z; }
public function applyFog(a:*):void { a.alpha = 1.0 - a.z / SC_DEPTH / 2; }
}
}