Recently I was using ActionScript Physics Engine to create a simple 2-D arcade-style game. I looked into building an elliptical spring constraint in APE to serve as the boundaries of the game. In the end I decided not to use the elliptical boundaries, but they are easy enough to code up. Here’s a quick demo, and the ActionScript source code:


	package
{
	import flash.display.Sprite;
	import flash.events.Event;
	import org.cove.ape.*;

	public class Main extends Sprite
	{
		public var defaultGroup:Group;
		var car:SpringConstraint;
		var ellipsePoints:Array; // points that define the outer ellipse
		var wheel1:WheelParticle;

		public function Main()
		{
			stage.frameRate = 30;
			APEngine.init(1/4);  

            // set the default diplay container
            APEngine.container = this;
            defaultGroup = new Group();
            defaultGroup.collideInternal = true;
			init();

			APEngine.addGroup(defaultGroup);
			stage.addEventListener(Event.ENTER_FRAME, run);
		}

		public function init():void
		{
			ellipsePoints = new Array();
			ellipsePoints = drawEllipse(calculateEllipse(380, 80, 60, 36, -24, 32));

			addBall();
		}

		public function addBall():void
		{
			var circle = new CircleParticle(
											160, 	// x
											210, 	// y
											40, 	// radius
											false,  // fixed
											10, 	// mass
											1.0, 	// elasticty
											0  		// friction
											);
			circle.setStyle(0, 0, 0, Math.random() * 0xffffff);
			defaultGroup.addParticle(circle);
			circle.velocity = (new Vector(20, 1));
		}

		/*
		* This functions returns an array containing the points to draw an
		* ellipse.
		*
		* @param x {double} X coordinate
		* @param y {double} Y coordinate
		* @param a {double} Semimajor axis
		* @param b {double} Semiminor axis
		* @param angle {double} Angle of the ellipse
		*/
		private function calculateEllipse(x, y, a, b, angle, steps)
		{
		  if (steps == null)
			steps = 36;
		  var points:Array = new Array();

		  // Angle is given by Degree Value
		  var beta = -angle * (Math.PI / 180); //(Math.PI/180) converts Degree Value into Radians
		  var sinbeta = Math.sin(beta);
		  var cosbeta = Math.cos(beta);

		  for (var i = 0; i < 360; i += 360 / steps)
		  {
			var alpha = i * (Math.PI / 180) ;
			var sinalpha = Math.sin(alpha);
			var cosalpha = Math.cos(alpha);

			var x = x + (a * cosalpha * cosbeta - b * sinalpha * sinbeta);
			var y = y + (a * cosalpha * sinbeta + b * sinalpha * cosbeta);
		 	var o:Object = new Object();
			o.x = x;
			o.y = y;
			points.push(o);
		   }
		  return points;
		}

		private function drawEllipse(points:Array):Array
		{
			var circles:Array = new Array();
			var i:Number;
			for( i= 0; i < points.length; i++)
			{
				// CircleParticle(x, y, radius, fixed, mass, elasticity, friction)
				var c:CircleParticle = new CircleParticle(points[i].x, points[i].y, 0, true, 0.4, 0, 0);
				defaultGroup.addParticle(c);
				circles.push(c);

				if(i > 0)
				{
					var s:SpringConstraint = new SpringConstraint(circles[i-1], circles[i], 1, true, 1, 1, true);
					defaultGroup.addConstraint(s);
				}
			}

			// create the final constraint  to close the ellipse:
			var t:SpringConstraint = new SpringConstraint(circles[i-1], circles[0], 1, true, 1, 1, true);
			defaultGroup.addConstraint(t);
			return circles;
		}

		private function run(e:Event):void
        {
            APEngine.step();
            APEngine.paint();
        }
	}
}

Anatomy of an Ellipse:

anatomy_of_an_ellipse

Comments

Leave a Reply