Billy the Box
It's a box! It can move. Arrow keys and space bar. I think I put more time into the particles...
♥0 |
Line 232 |
Modified 2012-08-27 11:10:04 |
MIT License
archived:2017-03-20 09:10:32
ActionScript3 source code
/**
* Copyright mach51 ( http://wonderfl.net/user/mach51 )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/iGj9
*/
package
{
import flash.display.MovieClip;
import flash.events.KeyboardEvent;
import flash.events.Event;
import flash.ui.Keyboard;
[SWF(width = '400', height = '600', backgroundColor = '#000000', frameRate = '30')]
/**
* there is some reduncancy in the code
* I was just playing around.
*/
public class Main extends MovieClip
{
public var bill:Billy;
public const g:Number = 1.5;
public const kf:Number = 0.98;
public const bounciness:Number = 0.5;
public const PARTICLE_COUNT:int = 20;
public const PARTICLE_LIFE:int = 30;
public var particles:Vector.<Particle> = new Vector.<Particle>();
public function Main()
{
bill = new Billy(5.0, new PhysicalWorld(1.5, 0.98, 0.5)); // (mass), g, kf, bounciness
addChild(bill);
bill.x = (stage.stageWidth - bill.width) / 2;
bill.y = (stage.stageHeight - bill.height) / 2;
stage.addEventListener(KeyboardEvent.KEY_DOWN, pushBox);
stage.addEventListener(KeyboardEvent.KEY_UP, stopPushing);
stage.addEventListener(Event.ENTER_FRAME, step);
}
public function pushBox(e:KeyboardEvent):void
{
switch(e.keyCode)
{
case Keyboard.LEFT:
bill.ax = -1.0;
break;
case Keyboard.RIGHT:
bill.ax = 1.0;
break;
case Keyboard.UP:
bill.ay = -(g + 1.0);
break;
case Keyboard.DOWN:
bill.ay = 1.0;
break;
case Keyboard.SPACE:
if(bill.isOnGround){
bill.vy = -25.0;
}
break;
case Keyboard.ENTER:
bill.x = (stage.stageWidth - bill.width) / 2;
bill.y = (stage.stageHeight - bill.height) / 2;
bill.ax = 0.0;
bill.ay = 0.0;
bill.vx = 0.0;
bill.vy = 0.0;
break;
}
}
public function stopPushing(e:KeyboardEvent):void
{
switch(e.keyCode)
{
case Keyboard.LEFT:
bill.ax = 0.0;
break;
case Keyboard.RIGHT:
bill.ax = 0.0;
break;
case Keyboard.UP:
bill.ay = 0.0;
break;
case Keyboard.DOWN:
bill.ay = 0.0;
break;
}
}
public function step(e:Event):void
{
bill.vy += bill.ay + g;
bill.vx += bill.ax;
bill.y += bill.vy;
bill.x += bill.vx;
bill.vy *= kf;
bill.vx *= kf;
stepParticles();
if(bill.y + bill.height > stage.stageHeight)
{ // on ground
bill.y = stage.stageHeight - bill.height;
spawnParticlesAt(bill.x + bill.width/2, bill.y + bill.height);
bill.vy *= -bounciness;
bill.isOnGround = true;
}
else
{
bill.isOnGround = false;
}
if(bill.y < 0){ // hits roof
bill.y = 0;
spawnParticlesAt(bill.x + bill.width/2, bill.y);
bill.vy *= -bounciness;
}
if(bill.x + bill.width > stage.stageWidth){ // on right wall
bill.x = stage.stageWidth - bill.width;
spawnParticlesAt(bill.x + bill.width, bill.y + bill.height/2);
bill.vx *= -bounciness;
}
if(bill.x < 0){ // on left wall
bill.x = 0;
spawnParticlesAt(bill.x, bill.y + bill.height/2);
bill.vx *= -bounciness;
}
}
public function spawnParticlesAt(x:int, y:int):void
{
for(var i:int = particles.length; i < PARTICLE_COUNT; i++)
{
var p:Particle = new Particle(10, 10, PARTICLE_LIFE);
particles.push(p);
addChild(p);
p.x = x;
p.y = y;
p.vx = -(bill.vx + (Math.random()*20));
p.vy = -(bill.vy + (Math.random()*20));
}
}
public function stepParticles():void
{
for(var k:int = 0; k < particles.length; k++)
{
var p:Particle = particles[k];
p.alpha -= 1/p.frameLife;
if(p.alpha < 0)
{
removeChild(particles[k]);
particles.splice(k, 1);
}
else
{
p.x += p.vx;
p.y += p.vy;
p.vx *= kf;
p.vy *= kf;
}
}
}
} // end class
} // end package
import flash.events.Event
import flash.display.MovieClip;
/**
* The Billy object is basically a MovieClip that can handle it's own physics, given a set of rules (the PhysicalWorld) and a mass.
* In that sense, you can use the Billy object as a generic 'PhysicalMovieClip' object to create any kind of MovieClip that also has
* physical properties.
*
* In a hardcore programming environment, TECHNICALLY you'd want PhysicalWorld to be an abstract class requiring the coder to fill in how
* the PhysicalWorld should actually use and execute the "laws of physics".
* In this case, I'll just let the Billy class deal with those methods--err sorry, functions. I'm a java person.
* ... Can you even have abstract classes in as3?
*
* Ahhh forget this... it's way beyond the scope of this program. Billy can't actually take care of all his
* own physics because he's not aware of where the 'bill' instance is on the stage's coordinate space.
* You can make this work by expanding the PhysicalWorld class so that it actually keeps a list of different
* instances of physical MovieClip objects (the world knows what's inside it) and you'd use the PhysicalWorld by adding
* objects to it. The PhysicalWorld will then take care of all the physics with an ENTER_FRAME event listener and handles the
* speeds, accelerations, etc of the MovieClips, and returns to the stage the new positions of the MovieClips.
*
* Basically what I'm saying is the PhysicalWorld class is a simpler way of organizing and simulating physics of objects
* instead of dumping it all in the document class. Organizing the laws of physics into a single class also makes it easier
* to mess with the laws of physics later on in the game or simulation or whatever it is you're coding.
*
* okay so: DON'T BRUTE FORCE YOUR PHYSICS, ORGANIZE IT AND MAKE IT EPIC
*
*/
class Billy extends MovieClip
{
private var hasFlashed:Boolean = false;
private var fCounter:int = 0;
public var mass:Number = 5.0;
public var pw:PhysicalWorld;
private const dwidth:int = 50;
private const dheight:int = 50;
public var vx:Number = 0.0;
public var vy:Number = 0.0;
public var ax:Number = 0.0;
public var ay:Number = 0.0;
public var isOnGround:Boolean = false;
public function Billy(mss:Number, p:PhysicalWorld)
{
mass = mss;
pw = p;
graphics.lineStyle(2, 0xffffff);
graphics.beginFill(0x000000);
graphics.drawRect(0, 0, dwidth, dheight);
graphics.endFill();
//addEventListener(Event.ENTER_FRAME, flash);
}
public function flash(e:Event):void
{
fCounter++;
if(fCounter == 10)
{
if(hasFlashed)
{
graphics.beginFill(0x000000);
graphics.drawRect(0, 0, dwidth, dheight);
graphics.endFill();
hasFlashed = !hasFlashed;
fCounter = 0;
}
else
{
graphics.beginFill(0xffffff);
graphics.drawRect(0, 0, dwidth, dheight);
graphics.endFill();
hasFlashed = !hasFlashed;
fCounter = 0;
}
}
}
} // end class
class PhysicalWorld
{
public var g:Number;
public var kf:Number;
public var bounciness:Number;
public function PhysicalWorld(gravity:Number, frictionKonstant:Number, collisionBounciness:Number)
{
g = gravity;
kf = frictionKonstant;
bounciness = collisionBounciness;
}
// functions that handle forces (acceleration)
// you'll probably need one to start the force and another to end the force.
// a function to actually change the speed and calculate the new position.
// if this class is abstract it's basically letting you fuck with the laws of physics
// and do whatever you want. Inertia? What's that? LET'S INCREASE ACCELERATION WITH EVERY SECOND?
// (this makes running into the wall really exciting if you're wondering -- the longer you try to run through the wall the 'harder' it pushes you off.).
} // end
class Particle extends MovieClip
{
public var vx:Number = 0.0;
public var vy:Number = 0.0;
public var ax:Number = 0.0;
public var ay:Number = 0.0;
public var frameLife:int;
public function Particle(width:Number, height:Number, frameLife:int) // frameLife is the number of frames the particle will be 'alive' in
{
this.frameLife = frameLife;
graphics.lineStyle(2, 0xffffff);
graphics.beginFill(0x000000);
graphics.drawRect(0, 0, width, height);
graphics.endFill();
var randScale:Number = 1 + Math.random();
scaleX *= randScale;
scaleY *= randScale;
addEventListener(Event.ENTER_FRAME, decaySize);
}
public function decaySize(e:Event):void
{
scaleX -= 0.09;
scaleY -= 0.09
}
}