15Aug
APE Project - Step 8 - Adding a Fixed Bridge
No commentsFrom a few past experiments [1 | 2 ] I wanted to add a bridge to my movie here. For now:
- Hold down the Shift key to and drag your mouse across the stage to draw a rectangle
- Hold down the Command (or Ctrl key) key and click an area on the stage to build a bridge
You can download the files for this project here:
http://www.manewc.com/projects/flash/APEProject8/manewc.zip
Here is the updated Main.as file
package {
import flash.display.Sprite;
import flash.display.Shape;
import flash.ui.Keyboard;
import flash.events.MouseEvent;
import flash.events.KeyboardEvent;
import flash.events.Event;
import flash.geom.Rectangle;
import fl.controls.Button;
import org.cove.ape.*;
public class Main extends Sprite {
private var beginX:Number; // top left x position
private var beginY:Number; // top left y position
private var endX:Number; // bottom right x position
private var endY:Number; // bottom right y position
private var dynRect:RectangleParticle;
private var canDraw:Boolean = false; // this allows the drawing of rectangles
private var circle:CircleParticle;
private var circleGroup:Group;
private var defaultGroup:Group;
private var canDrawBridge:Boolean = false; // this allows the drawing of bridges
private var bridge:Bridge;
private var car:Car;
private var btnCar:Button;
// rectangle particle dimensions
private var _xpos:Number;
private var _ypos:Number;
private var _rwidth:Number;
private var _rheight:Number;
private var _rrotation:Number = 0;
public function Main()
{
init();
}
private function init():void
{
stage.frameRate = 55;
// Initialize the engine. The argument here is the time step value.
// Higher values scale the forces in the sim, making it appear to run
// faster or slower. Lower values result in more accurate simulations.
APEngine.init(1/4);
// set up the default diplay container
APEngine.container = this;
APEngine.addMasslessForce(new Vector(0,8));
defaultGroup = new Group();
defaultGroup.collideInternal = true;
circleGroup = new Group();
circleGroup.collideInternal = true;
// this is the bottom
var rect:RectangleParticle = new RectangleParticle(345, 680, 710, 40, 0, true);
defaultGroup.addParticle(rect);
var l:RectangleParticle = new RectangleParticle(0, stage.stageHeight / 2 - 20, 10, stage.stageHeight-40, 0, true);
defaultGroup.addParticle(l);
var r:RectangleParticle = new RectangleParticle(stage.stageWidth, stage.stageHeight / 2 - 20, 10, stage.stageHeight-40, 0, true);
defaultGroup.addParticle(r);
APEngine.addGroup(defaultGroup);
APEngine.addGroup(circleGroup);
// make the groups collidable
defaultGroup.addCollidable(circleGroup);
addEventListener(Event.ENTER_FRAME, run);
stage.addEventListener(KeyboardEvent.KEY_DOWN, allowDraw);
stage.addEventListener(KeyboardEvent.KEY_UP, disallowDraw);
stage.addEventListener(MouseEvent.MOUSE_DOWN, dragDraw);
stage.addEventListener(MouseEvent.MOUSE_UP, dragDrawStop);
// build the UI
buildUI();
}
private function allowDraw(event:KeyboardEvent):void
{
if ( event.keyCode == 16 )
{
canDraw = true;
}
else if ( event.keyCode == 17 ) // 'command'
{
canDrawBridge = true;
}
}
private function disallowDraw(event:KeyboardEvent):void {
if ( canDraw ) canDraw = false;
if ( canDrawBridge ) canDrawBridge = false;
}
private function dragDraw (m:MouseEvent):void
{
if ( canDraw )
{
beginRectDraw();
}
else if ( canDrawBridge )
{
beginDrawBridge();
}
}
private function dragDrawStop (m:MouseEvent):void
{
if ( canDraw )
{
stopRectDraw();
}
else if ( canDrawBridge )
{
}
}
private function beginDrawBridge():void
{
// if exists.. delete it for now
if ( bridge ) APEngine.removeGroup(bridge);
// add the bridge
bridge = new Bridge(mouseX, mouseY, 11.9, 55, 5);
APEngine.addGroup ( bridge );
// add the collidables
defaultGroup.addCollidable(bridge);
circleGroup.addCollidable(bridge);
if ( car ) car.addCollidable(bridge);
}
private function beginRectDraw():void
{
beginX = mouseX;
beginY = mouseY;
}
private function stopRectDraw():void
{
// set the end points
endX = mouseX;
endY = mouseY;
// now draw the rectangle
if ( canDraw ) drawRectangle();
}
private function drawRectangle():void
{
if ( beginY < 660 && endY < 660 )
{
// store the data
_xpos = beginX + ((endX - beginX)/2);
_ypos = beginY + ((endY - beginY)/2);
_rwidth = endX - beginX;
_rheight = endY - beginY;
_rrotation = 0;
dynRect = new RectangleParticle(_xpos, _ypos, _rwidth, _rheight, _rrotation, true);
defaultGroup.addParticle(dynRect);
dynRect.sprite.addEventListener ( MouseEvent.MOUSE_DOWN, rotateRectangle );
}
}
private function rotateRectangle( m:MouseEvent ):void
{
if ( !canDraw )
{
// increment the angle
_rrotation += .05;
// rid of the particle
defaultGroup.removeParticle(dynRect);
// redraw the particle
dynRect = new RectangleParticle(_xpos, _ypos, _rwidth, _rheight, _rrotation, true);
defaultGroup.addParticle(dynRect);
dynRect.sprite.addEventListener ( MouseEvent.MOUSE_DOWN, rotateRectangle );
}
}
private function addBall( m:MouseEvent ):void
{
circle = new CircleParticle(Math.random() * stage.stageWidth, Math.random() * 100, Math.random() * 25 + 5);
circleGroup.addParticle(circle);
}
private function addCar ( m:MouseEvent ):void
{
btnCar.removeEventListener(MouseEvent.CLICK, addCar);
car = new Car(Math.random() * 0xffffff,Math.random() * 0xffffff);
APEngine.addGroup(car);
defaultGroup.addCollidable(car);
circleGroup.addCollidable(car);
if ( bridge ) bridge.addCollidable(car);
stage.addEventListener(KeyboardEvent.KEY_DOWN, keyPressed);
stage.addEventListener(KeyboardEvent.KEY_UP, keyReleased);
// change the type of the button
btnCar.label = "Remove Car";
btnCar.addEventListener(MouseEvent.CLICK, removeCar);
}
private function removeCar ( m:MouseEvent ):void
{
btnCar.removeEventListener(MouseEvent.CLICK, removeCar);
// remove the car
APEngine.removeGroup(car);
// change the label
btnCar.label = "Add Car";
// change the button action
btnCar.addEventListener(MouseEvent.CLICK, addCar);
}
private function run(e:Event):void
{
APEngine.step();
APEngine.paint();
}
private function removeLastBall( m:MouseEvent ):void
{
if ( circle ) circle.cleanup();
}
private function clearBoard( m:MouseEvent ):void
{
APEngine.removeGroup(defaultGroup);
APEngine.removeGroup(circleGroup);
if ( bridge ) APEngine.removeGroup(bridge);
if ( car ) APEngine.removeGroup(car);
init();
}
function keyPressed(event:KeyboardEvent):void {
var keySpeed:Number = 0.8;
if (event.keyCode == Keyboard.UP || event.keyCode == Keyboard.RIGHT)
{
car.speed = keySpeed;
}
if (event.keyCode == Keyboard.DOWN || event.keyCode == Keyboard.LEFT)
{
car.speed = -keySpeed;
}
}
function keyReleased(event:KeyboardEvent):void
{
car.speed = 0;
}
private function buildUI():void
{
// NEW BUTTONS
var btnAddBall:Button = new Button();
btnAddBall.width = 65;
btnAddBall.height = 25;
btnAddBall.move ( 5, stage.stageHeight - 20 - btnAddBall.height / 2 );
btnAddBall.label = "Add Ball";
addChild(btnAddBall);
btnAddBall.addEventListener(MouseEvent.CLICK, addBall);
var btnRemoveBall:Button = new Button();
btnRemoveBall.width = 120;
btnRemoveBall.height = 25;
btnRemoveBall.move ( 75, stage.stageHeight - 20 - btnRemoveBall.height / 2 );
btnRemoveBall.label = "Remove Last Ball";
addChild(btnRemoveBall);
btnRemoveBall.addEventListener(MouseEvent.CLICK, removeLastBall);
btnCar = new Button();
btnCar.width = 100;
btnCar.height = 25;
btnCar.move ( 200, stage.stageHeight - 20 - btnCar.height / 2 );
btnCar.label = "Add Car";
addChild(btnCar);
btnCar.addEventListener(MouseEvent.CLICK, addCar);
var btnClearBoard:Button = new Button();
btnClearBoard.width = 120;
btnClearBoard.height = 25;
btnClearBoard.move ( 575, stage.stageHeight - 20 - btnClearBoard.height / 2 );
btnClearBoard.label = "Clear Board";
addChild(btnClearBoard);
btnClearBoard.addEventListener(MouseEvent.CLICK, clearBoard);
}
}
}
The new Car class
package {
import org.cove.ape.*;
public class Car extends Group {
private var wheelParticleA:WheelParticle;
private var wheelParticleB:WheelParticle;
public function Car(colC:uint, colE:uint) {
wheelParticleA = new WheelParticle(140,10,14,false,2);
wheelParticleA.setStyle(0, colC, 1, colE);
addParticle(wheelParticleA);
wheelParticleA.sprite.cacheAsBitmap = true;
wheelParticleB = new WheelParticle(200,10,14,false,2);
wheelParticleB.setStyle(0, colC, 1, colE);
addParticle(wheelParticleB);
wheelParticleB.sprite.cacheAsBitmap = true;
var wheelConnector:SpringConstraint = new SpringConstraint(wheelParticleA, wheelParticleB, 0.5, true, 8);
wheelConnector.setStyle(0, colC, 1, colE);
addConstraint(wheelConnector);
}
public function set speed(s:Number):void {
wheelParticleA.angularVelocity = s;
wheelParticleB.angularVelocity = s;
}
}
}
The new Bridge class
package {
import org.cove.ape.*;
public class Bridge extends Group {
public function Bridge(bx:Number, by:Number, yslope:Number, bsize:Number, particleSize:Number=20, colB:uint=0x000000, colC:uint=0x000000, colD:uint=0x000000) {
var bridgePAA:CircleParticle = new CircleParticle(bx,by,particleSize,true);
bridgePAA.setStyle(1, colC, 1, colB);
addParticle(bridgePAA);
bx += bsize;
by += yslope;
var bridgePA:CircleParticle = new CircleParticle(bx,by,particleSize);
bridgePA.setStyle(1, colC, 1, colB);
addParticle(bridgePA);
bx += bsize;
by += yslope;
var bridgePB:CircleParticle = new CircleParticle(bx,by,particleSize);
bridgePB.setStyle(1, colC, 1, colB);
addParticle(bridgePB);
bx += bsize;
by += yslope;
var bridgePC:CircleParticle = new CircleParticle(bx,by,particleSize);
bridgePC.setStyle(1, colC, 1, colB);
addParticle(bridgePC);
bx += bsize;
by += yslope;
var bridgePD:CircleParticle = new CircleParticle(bx,by,particleSize);
bridgePD.setStyle(1, colC, 1, colB);
addParticle(bridgePD);
bx += bsize;
by += yslope;
var bridgePDD:CircleParticle = new CircleParticle(bx,by,particleSize,true);
bridgePDD.setStyle(1, colC, 1, colB);
addParticle(bridgePDD);
var bridgeConnA:SpringConstraint = new SpringConstraint(bridgePAA, bridgePA, 0.9, true, 10, 0.8);
// collision response on the bridgeConnA will be ignored on
// on the first 1/4 of the constraint. this avoids blow ups
// particular to springcontraints that have 1 fixed particle.
bridgeConnA.fixedEndLimit = 0.25;
bridgeConnA.setStyle(1, colC, 1, colB);
addConstraint(bridgeConnA);
var bridgeConnB:SpringConstraint = new SpringConstraint(bridgePA, bridgePB, 0.9, true, 10, 0.8);
bridgeConnB.setStyle(1, colC, 1, colB);
addConstraint(bridgeConnB);
var bridgeConnC:SpringConstraint = new SpringConstraint(bridgePB, bridgePC, 0.9, true, 10, 0.8);
bridgeConnC.setStyle(1, colC, 1, colB);
addConstraint(bridgeConnC);
var bridgeConnD:SpringConstraint = new SpringConstraint(bridgePC, bridgePD, 0.9, true, 10, 0.8);
bridgeConnD.setStyle(1, colC, 1, colB);
addConstraint(bridgeConnD);
var bridgeConnE:SpringConstraint = new SpringConstraint(bridgePD, bridgePDD, 0.9, true, 10, 0.8);
bridgeConnE.fixedEndLimit = 0.25;
bridgeConnE.setStyle(1, colC, 1, colB);
addConstraint(bridgeConnE);
}
}
}
Categories: APE - Actionscript Physics Engine, Actionscript 3
Friday, August 15th, 2008 at 10:14 am and is filed under APE - Actionscript Physics Engine, Actionscript 3. You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.