Skip to content


APE Project - Step 8 - Adding a Fixed Bridge

From 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);

		}
	}
}

Share/Save/Bookmark

Posted in APE - Actionscript Physics Engine, Actionscript 3.

0 Responses

Stay in touch with the conversation, subscribe to the RSS feed for comments on this post.

Some HTML is OK

(required)

(required, but never shared)

or, reply to this post via trackback.