Thruster
Move with arrow keys and stuff
package {
import flash.events.*;
import flash.display.*;
import flash.geom.*;
import flash.ui.*;
//Move with arrow keys and stuff
public class Thruster extends MovieClip {
// player params
private const playerThrust:Number = 2;
// player
private var player:Player
// particles
private var particles:Vector.<Particle> = new <Particle>[];
private var pickups:Vector.<Pickup> = new <Pickup>[];
private var enemies:Vector.<Enemy> = new <Enemy>[];
public function Thruster() {
addEventListener(Event.ADDED_TO_STAGE, addedToStageHandler);
}
private function addedToStageHandler(e:Event):void {
// create the player
player = new Player();
player.x = stage.stageWidth / 2;
player.y = stage.stageHeight / 2;
addChild(player)
// key handling
Key.init(stage);
// start main loop
addEventListener(Event.ENTER_FRAME, update);
}
private function update(e:Event):void {
// update player
player.update();
// update particles
for each(var particle:Particle in particles)
particle.update();
// update pickups
for each(var pickup:Pickup in pickups)
pickup.update();
// spawn pickups
if(Math.random() < .03)
addApple();
// update enemies
for each(var enemy:Enemy in enemies)
enemy.update();
}
// particles
public function addParticle(origin:Point, vector:Point = null):void {
var particle:Particle = new Particle();
particle.x = origin.x;
particle.y = origin.y;
particle.vector = vector || new Point(0, 0);
particles.push(particle);
addChild(particle);
}
public function removeParticle(particle:Particle):void {
var index:int = particles.indexOf(particle);
if(index != -1)
particles.splice(index, 1);
if(particle.parent)
particle.parent.removeChild(particle);
}
public function sprayParticles(origin:Point, count:uint, angle:Number, thrust:Number, jitter:Number = 0):void {
while(count--){
var a:Number = angle - jitter + Math.random() * (jitter * 2);
var d:Number = thrust * Math.random();
addParticle(origin, new Point(Math.cos(a) * d, Math.sin(a) * d));
}
}
public function spraySparks(origin:Point, count:uint):void {
while(count--){
var spark:Spark = new Spark();
spark.x = origin.x;
spark.y = origin.y;
spark.vector = new Point(-30 + Math.random() * 60, -30 + Math.random() * 60);
spark.rotation = Math.atan2(spark.vector.y, spark.vector.x) * (180 / Math.PI);
particles.push(spark);
addChild(spark);
}
}
// pickups
public function addApple():void {
var apple:Apple = new Apple();
apple.x = stage.stageWidth * Math.random();
apple.y = stage.stageWidth * Math.random();
pickups.push(apple);
addChild(apple);
}
public function removePickup(pickup:Pickup):void {
var index:int = pickups.indexOf(pickup);
if(index != -1)
pickups.splice(index, 1);
if(pickup.parent)
pickup.parent.removeChild(pickup);
}
public function getPickups(origin:Point, radius:Number):Vector.<Pickup> {
var nearby:Vector.<Pickup> = new <Pickup>[];
for each(var pickup:Pickup in pickups){
if(Point.distance(origin, pickup.position) <= radius + pickup.radius)
nearby.push(pickup);
}
return nearby;
}
// enemies
public function addWorm(origin:Point):void {
var worm:Worm = new Worm();
worm.x = origin.x;
worm.y = origin.y;
enemies.push(worm);
addChild(worm);
}
public function getPlayer():Player {
return player;
}
}
}
import flash.utils.*;
import flash.geom.*;
import flash.events.*;
import flash.display.*;
import flash.ui.*;
internal class AbstractGameObject extends Sprite {
protected const RADIANS:Number = Math.PI / 180;
public function update():void {
// abstract
}
public function get position():Point { return new Point(x, y); }
public function get radius():Number { return width * .5; }
public function get thruster():Thruster { return Thruster(root); }
}
internal class MovingGameObject extends AbstractGameObject {
public var friction:Number = .8;
public var vector:Point = new Point();
override public function update():void {
// apply friction to movement
vector.x *= friction;
vector.y *= friction;
// move
x += vector.x;
y += vector.y;
}
// applies thrust to a vector
public function thrust(vector:Point, angle:Number, amount:Number):void {
const radians:Number = angle * (Math.PI / 180);
var delta:Point = new Point(
Math.cos(radians) * amount,
Math.sin(radians) * amount
);
vector.x += delta.x;
vector.y += delta.y;
}
}
internal class Player extends MovingGameObject {
private var thrustAmount:Number = 2;
public function Player(){
graphics.beginFill(0xCCCCCC);
graphics.drawCircle(0, 0, 10);
}
override public function update():void {
// keyboard input
if(Key.isDown(Keyboard.LEFT))
thrust(vector, 180, thrustAmount);
if(Key.isDown(Keyboard.RIGHT))
thrust(vector, 0, thrustAmount);
if(Key.isDown(Keyboard.UP))
thrust(vector, -90, thrustAmount);
if(Key.isDown(Keyboard.DOWN))
thrust(vector, 90, thrustAmount);
// move
super.update();
// spray particles
if(vector.length > 1)
thruster.sprayParticles(position,
1 + Math.random() * 15,
Math.atan2(vector.y, vector.x),
vector.length * 1.5,
Math.PI * .1
);
// loop around
if(x < -radius)
x = stage.stageWidth + radius;
else if(x > stage.stageWidth + radius)
x = -radius
if(y < -radius)
y = stage.stageHeight + radius;
else if(y > stage.stageHeight + radius)
y = -radius;
// pickups
var pickups:Vector.<Pickup> = thruster.getPickups(position, radius);
if(pickups.length){
for each(var pickup:Pickup in pickups)
pickup.pickup();
}
}
}
internal class Particle extends MovingGameObject {
protected var shrinkSpeed:Number = .03;
public function Particle() {
graphics.beginFill(0xCCCCCC, Math.random());
graphics.drawCircle(0, 0, Math.random() * 10);
super();
friction = .93;
}
override public function update():void {
super.update();
scaleX = (scaleY -= shrinkSpeed);
if(scaleX <= 0)
thruster.removeParticle(this);
}
}
internal class Spark extends Particle {
public function Spark() {
graphics.beginFill(0xFF3300);
graphics.drawRect(0, 0, 15 + Math.random() * 30, 3);
super();
shrinkSpeed = 0;
friction = .6 + .3 * Math.random();
}
override public function update():void {
super.update();
scaleX = (scaleY *= friction);
if(scaleY <= .01)
thruster.removeParticle(this);
}
}
internal class Pickup extends AbstractGameObject {
public function pickup():void {
thruster.removePickup(this);
}
}
internal class Apple extends Pickup {
private var growSpeed:Number = .003;
public function Apple() {
graphics.beginFill(0xFF0000);
graphics.drawCircle(0, 0, 10);
scaleX = scaleY = .1;
}
override public function update():void {
scaleX = scaleY += growSpeed;
if(scaleX >= 1){
//thruster.spraySparks(position, 3);
thruster.sprayParticles(position, 25, 0, 10, Math.PI);
thruster.addWorm(position);
thruster.removePickup(this);
}
}
override public function pickup():void {
thruster.spraySparks(position, 10 + 20 * Math.random());
super.pickup();
}
}
internal class Enemy extends MovingGameObject {
public function Enemy(){
}
protected function get player():Player { return thruster.getPlayer(); }
}
internal class Chaser extends Enemy {
protected var rotateSpeed:Number = 1;
protected var moveThrust:Number = .12;
public function Chaser(){
}
override public function update():void {
rotation = rotateTowards(rotation, angleBetween(position, player.position), rotateSpeed);
thrust(vector, rotation, moveThrust);
super.update();
}
protected function angleBetween(p1:Point, p2:Point):Number {
return Math.atan2(p2.y - p1.y, p2.x - p1.x) * (180 / Math.PI);
}
protected function rotateTowards(angle:Number, targetAngle:Number, amount:Number):Number {
var dif:Number = (targetAngle - angle) % 360;
if (dif > 180) dif -= 360;
else if (dif < -180) dif += 360;
return dif > 0 ? (dif < amount ? targetAngle : angle + amount) : (dif > -amount ? targetAngle : angle - amount);
}
}
internal class Worm extends Chaser {
private var time:int = 0;
public function Worm() {
var currRadius:Number = 5, currX:Number = 5;
for(var i:int = 0; i < 6; i++){
graphics.beginFill(0x000000, .5);
graphics.drawCircle(currX, 0, currRadius);
currX -= currRadius;
currRadius--;
}
rotation = 360 * Math.random();
}
override public function update():void {
super.update();
time++;
scaleX = 1 + Math.sin(time / 4) * .2;
}
}
internal class Fly extends Chaser {
}
internal class Spider extends Chaser {
}
// track keyboard input
internal class Key {
private static var keys:Array = [];
public static function init(stage:Stage):void {
stage.addEventListener(KeyboardEvent.KEY_DOWN, stageKeyHandler);
stage.addEventListener(KeyboardEvent.KEY_UP, stageKeyHandler);
}
public static function stageKeyHandler(e:KeyboardEvent):void {
keys[e.keyCode] = (e.type == KeyboardEvent.KEY_DOWN);
}
public static function isDown(keyCode:uint):Boolean {
return keys[keyCode] == true;
}
}