Setting the ToggleButtonBar to be completely unselected

//-------------------AS3 version
var tb:ToggleButtonBar = new ToggleButtonBar();
tb.selectedIndex = -1;
//-------------------MXML version
<mx:ToggleButtonBar selectedIndex="-1" />

Ctrl+M in Flash Builder makes me feel less claustrophobic

If you feel like your code is getting too crowded and you don’t have enough space. Press Control + M.
If you feel you have made a terrible mistake in pressing Control + M… Press it again to restore to the way it was. Thanks CtrlM. Pronounced: “Controlum”

Vector vs Array in Flex or Flash

One really great thing I have recently found invaluable is the Vector object.

It’s like an Array but you are able so say what is going to be in the array. And you can set a fixed length!
Just read this

So instead of putting a String and a Number and a Cat in the Array, you choose what you want to be in there the compiler will make sure that is what is happening.
The best part is that when you go to access the elements of the Vector you get code hints, which you wouldn’t if you just used an array.

private var v:Vector = new Vector.<Number>();

Accessing the num gives you code hints! IT KNOWS!

v[i].toString();

BisonKick Help & Shortcuts

Here are some shortcut keys and quick tips for BisonKick:

X: unselect

Delete: Deletes currently selected

Shift+Click shapes: Selects Multiple shapes.  When multiple shape are selected you can move, rotate, resize, make dynamic, change restitution, mass, friction for all shapes selected.

Follower: When a shape is selected as the “follower” it means that when you preview the scene your view will stay fixed on the object.  Only one object can be a follower for very obvious reasons.

Changing the follower: Unselect the current follower. Select the new follower.

Resitution: Bounciness

Friction: friction

Density: Think of a wiffleball versus a baseball. Same size.

From left to right

Add a new rectangle to the stage.

Add a new circle to the stage. Ovals are not an option, sorry.

Add a new polygon (coming soon!)

Export to XML- takes all the shapes on the stage and exports their coordinates, rotation and all other properties you chose to export (under settings) as valid XML for you to copy and paste.

Export to AS3- takes all the shapes on the stage and exports their coordinates, rotation and all other properties you chose to export (under settings) as a valid Actionscript 3 array for you to copy and paste. Order of properties are contained within the comments of the array.

Zoom in & Out- allows you to see more or less detail and place your objects on a finer scale.  There is a known issue that when you zoom and create a new object, that new object may be placed off screen.  For now just scroll over to it to get it. This will be fixed.

Delete currently selected- allows you to delete the current objects selected.  Can also press the Delete button (not Backspace).

Run it- Will open up the preview window and allow you to see a preview of the world you created. Static shapes will not move.

Updates to BisonKick-round 1 complete

I just updated BisonKick ,which completes round one of updates.  So if you saw the site go down for .2 seconds I am sorry. Some updates include but are not limited to:

  • Fixed the circle sizing.
  • Made radians the default since most people will be using BK with Box2d.
  • Made friction, mass, & restitution appear in the preview window by default.
  • Fixed the handle’s size.
  • Put in a mysterious “New Polygon” button, whose functionality is yet to be seen.

You can expect in the next update I will make drawing custom polygons available and attempt to fix any other bugs that you find.  Report bugs in the comment section. And let me know about features you would like to see.  QA it up.

How to tell if a Polygon is Convex or Concave

Here are three actionscript 3 functions that will tell you whether the polygon you created is concave or not. given the vertices.
Try out the demo here
Click around the screen to create vertices. If you create a concave shape it will scold you.. Here are the functions:

			public function isConvex():Boolean
			{
				var isPositive:Boolean = false;
				var nVerts:int = vertices.length;
				for(var i:int = 0; i < nVerts; ++i)
				{
					var lower:int = (i == 0) ? (nVerts - 1) : (i - 1);
					var middle:int = i;
					var upper:int = (i == nVerts - 1) ? (0) : (i + 1);
					var dx0:Number = xArray[middle] - xArray[lower];
					var dy0:Number = yArray[middle] - yArray[lower];
					var dx1:Number = xArray[upper] - xArray[middle];
					var dy1:Number = yArray[upper] - yArray[middle];
					var cross:Number = dx0 * dy1 - dx1 * dy0;
					var newIsP:Boolean = (cross > 0) ? true : false;
					if(i == 0)
					{
						isPositive = newIsP;
					}
					else if(isPositive != newIsP)
					{
						return false;
					}
				}
				return true;
			}
 
//is the currently draw vertex inside the shape.. that's a no no
public function isInside(_x:Number, _y:Number):Boolean
			{
				var vx2:Number = _x - xArray[0];
				var vy2:Number = _y - yArray[0];
 
				var vx1:Number = xArray[1] - xArray[0]; 
				var vy1:Number = yArray[1] - yArray[0];
 
				var vx0:Number = xArray[2] - xArray[0];
				var vy0:Number = yArray[2] - yArray[0];
 
				var dot00:Number = vx0 * vx0 + vy0 * vy0;
				var dot01:Number = vx0 * vx1 + vy0 * vy1;
				var dot02:Number = vx0 * vx2 + vy0 * vy2;
				var dot11:Number = vx1 * vx1 + vy1 * vy1;
				var dot12:Number = vx1 * vx2 + vy1 * vy2;
				var invDenom:Number = 1.0 / (dot00 * dot11 - dot01 * dot01);
				var u:Number = (dot11 * dot02 - dot01 * dot12) * invDenom;
				var v:Number = (dot00 * dot12 - dot01 * dot02) * invDenom;
 
				return ((u > 0) && (v > 0) && (u + v < 1));	
			}
//here's that function to get 2 arrays of x and y points
			private function setXYArrays():void
			{
				xArray = new Array();
				yArray = new Array();
				for(var i:uint = 0; i < vertices.length; i++)
				{
					xArray[i] = vertices[i].x;
					yArray[i] = vertices[i].y;
				}
			}

Attach Joints in Box2d using levelEditor

Let’s Learn how to make joints using the level editor and Box2d.
Learn how to make this:
Sorry for the ubiquitous busy cursor. Won’t happen again.


press Space to start and stop.
embedded by Embedded Video

Download Video
Here’s the code from the tutorial:
Make a new Actionscript project in Flash Buidler or use FlashDevelop and make this the Document class in Flash.

package
{
	import Box2D.Collision.Shapes.b2CircleShape;
	import Box2D.Collision.Shapes.b2PolygonShape;
	import Box2D.Common.Math.b2Vec2;
	import Box2D.Dynamics.Joints.b2PrismaticJointDef;
	import Box2D.Dynamics.Joints.b2RevoluteJoint;
	import Box2D.Dynamics.Joints.b2RevoluteJointDef;
	import Box2D.Dynamics.b2Body;
	import Box2D.Dynamics.b2BodyDef;
	import Box2D.Dynamics.b2DebugDraw;
	import Box2D.Dynamics.b2FixtureDef;
	import Box2D.Dynamics.b2World;
 
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.KeyboardEvent;
 
	[SWF(backgroundColor='#000000', frameRate='40')]
 
	public class Box2dTesgter extends Sprite
	{
 
			public var world:b2World=new b2World(new b2Vec2(0,10.0),true);
			public var world_scale:int = 30;
 
			public static const SQUARE:String = "SQUARE";
			public static const CIRCLE:String = "CIRCLE";
			public var fixtureDef:b2FixtureDef = new b2FixtureDef();
 
			private var jd:b2RevoluteJointDef;
			private var theWheel:b2RevoluteJoint;
 
			private var largeWheel:b2Body;
			private var longArm:b2Body;
			private var pushingBox:b2Body;
			private var springyBox:b2Body;
			private var theWall:b2Body;
 
			public var specialB2Body:b2Body;
 
			public var motorOn:Boolean = true;
 
			//order: x , y , height, width, rotation, isDynamic, shape, friction,density,restitution,ID
			private var map:Array = [
				[148, 161.5, 149, 149, 0, true, 'CIRCLE' , 0.5, 0.5, 0.5, 'largeWheel']
				,
				[436.5,606.5,19,827,0.00000,false,'SQUARE' , 0.5,0.5,0.5]
				,
				[268.9498895023159, 186.79943882439528, 23, 271, 2.86251, true, 'SQUARE' , 0.5, 0.5, 0.5, 'longArm']
				,[393, 148, 50, 50, 0.00000, true, 'SQUARE' , 0.5, 10, 0.5, 'pushingBox']
				,[511,180.5,179,50,0.00000,false,'SQUARE' , 0.5,0.5,0.5,'theWall']
				,[479,147,50,30,0.00000,true,'SQUARE' , 0.5,0.5,0.5,'springyBox']
			];
 
			//[472.5,418.5,19,827,0.00000,false,'SQUARE' , 0.5,0.5,0.5,'floor']
 
			public function Box2dTesgter()
			{
				debug_draw();
 
				for (var i:uint = 0; i &lt; map.length; i++)
				{
					var sx:Number = map[i][0];
					var sy:Number = map[i][1];
					var sizerh:Number = map[i][2];
					var sizerw:Number = map[i][3];
					var srot:Number = map[i][4];
					var sIsDynamic:* = map[i][5];
					var sShape:String = map[i][6];
					var sFric:Number = map[i][7];
					var sMass:Number = map[i][8];
					var sRest:Number = map[i][9];
					var boxId:String = map[i][10];
 
					if (sShape == SQUARE)
					{
						draw_box(sx, sy, sizerw, sizerh, sIsDynamic,srot,sFric,sMass,sRest,boxId);
					}
					else if (sShape == CIRCLE)
					{
						draw_circle(sx, sy, sizerw / 2, sIsDynamic,srot,sFric,sMass,sRest,boxId);
					}
				}
				//createCar();
				addEventListener(Event.ENTER_FRAME, update);
			}
 
			public function draw_circle(px:Number, py:Number, r:Number, d:Boolean, rot:Number,
										fric:Number,mass:Number,rest:Number,boxId:String):void {
				var my_body:b2BodyDef= new b2BodyDef();
				my_body.position.Set(px / world_scale, py / world_scale);
				if (d)
				{
					my_body.type=b2Body.b2_dynamicBody;
				}
				my_body.angle = rot;
				var my_circle:b2CircleShape=new b2CircleShape(r/world_scale);
				var my_fixture:b2FixtureDef = new b2FixtureDef();
				my_fixture.density = mass;
				my_fixture.friction = fric;
				my_fixture.restitution = rest;
				my_fixture.shape=my_circle;
				var world_body:b2Body = world.CreateBody(my_body);
				world_body.CreateFixture(my_fixture);
				if (boxId == 'largeWheel')
				{
					largeWheel = world_body;
				}
			}
			public function draw_box(px:Number, py:Number, w:Number, h:Number, d:Boolean, rot:Number,
									 fric:Number,mass:Number,rest:Number,boxId:String):void {
				var my_body:b2BodyDef = new b2BodyDef();
 
				my_body.position.Set(px / world_scale, py / world_scale);
				my_body.angle = rot;
				if (d)
				{
					my_body.type=b2Body.b2_dynamicBody;
				}
				var my_box:b2PolygonShape = new b2PolygonShape();
				my_box.SetAsBox(w/2/world_scale, h/2/world_scale);
				var my_fixture:b2FixtureDef = new b2FixtureDef();
				my_fixture.density = mass;
				my_fixture.friction = fric;
				my_fixture.restitution = rest;
				my_fixture.shape=my_box;
				var world_body:b2Body=world.CreateBody(my_body);
				world_body.CreateFixture(my_fixture);
				if (boxId == 'longArm')
				{
					longArm = world_body;
				}
				if (boxId == 'pushingBox')
				{
					pushingBox = world_body;
				}
				if (boxId == 'springyBox')
				{
					springyBox = world_body;
					joinByJoints();
				}
				if (boxId == 'theWall')
				{
					theWall = world_body;
				}
			}
 
			private function joinByJoints():void
			{
				// JOINTS
				jd = new b2RevoluteJointDef();
				jd.Initialize(largeWheel, world.GetGroundBody(), largeWheel.GetWorldCenter());
				jd.enableLimit = false;
				jd.enableMotor = true;
				jd.maxMotorTorque = 400;
				jd.motorSpeed = 2;
				theWheel = world.CreateJoint(jd) as b2RevoluteJoint;
 
				//,[152,219.5,17,18,0.00000,true,'CIRCLE' , 0.5,0.5,0.5,3]
				jd.Initialize(largeWheel, longArm, new b2Vec2(152/world_scale, 219/world_scale));
				world.CreateJoint(jd);
				jd.enableLimit = false;
				jd.enableMotor = false;
 
				//,[387.5,152.25,20.5,21,0.00000,false,'CIRCLE' , 0.5,0.5,0.5]
				jd.Initialize(longArm, pushingBox, new b2Vec2(387.5 / world_scale, 152.25 / world_scale));
				world.CreateJoint(jd);
				jd.enableLimit = false;
				jd.enableMotor = false;
 
				var pmj:b2PrismaticJointDef = new b2PrismaticJointDef();
				pmj.Initialize(pushingBox, world.GetGroundBody(), pushingBox.GetWorldCenter(), new b2Vec2(1.0, 0));
				pmj.lowerTranslation = -5.0;
				pmj.upperTranslation = 5.0;
				pmj.enableLimit = true;
				world.CreateJoint(pmj);
 
				pmj.Initialize(springyBox, theWall, springyBox.GetWorldCenter(),new b2Vec2(1.0,0));
				pmj.lowerTranslation = -0.5;
				pmj.upperTranslation = 0.2;
				pmj.enableLimit = true;
				pmj.enableMotor = true;
				pmj.motorSpeed = 5;
				pmj.maxMotorForce = 80;
				world.CreateJoint(pmj);
 
				stage.addEventListener(KeyboardEvent.KEY_DOWN, kd);
			}
 
			private function kd(e:KeyboardEvent):void
			{
				if (e.keyCode == 32)
				{
					if (motorOn)
					{
						motorOn = false;
						theWheel.SetMotorSpeed(0);
					}
					else
					{
						motorOn = true;
						theWheel.SetMotorSpeed(5);
					}
 
				}
			}
 
			public function debug_draw():void {
				var debug_draw:b2DebugDraw = new b2DebugDraw();
				var debug_sprite:Sprite = new Sprite();
				addChild(debug_sprite);
				debug_draw.SetSprite(debug_sprite);
				debug_draw.SetFillAlpha(0.3);
				debug_draw.SetDrawScale(world_scale);
				debug_draw.SetFlags(b2DebugDraw.e_shapeBit);
				world.SetDebugDraw(debug_draw);
			}
			public function update(e : Event):void {
				//var pos_x:Number;
				//var pos_y:Number;
 
				//pos_x= specialB2Body.GetWorldCenter().x*world_scale;
				//pos_y= specialB2Body.GetWorldCenter().y*world_scale;
				//x=stage.stageWidth/2-pos_x;
				//y=stage.stageHeight/2-pos_y;
 
				world.Step(1 / 30, 10, 10);
				world.ClearForces();
				world.DrawDebugData();
			}
 
		}
}

Video Tutorial: BisonKick Use Custom Array in a Basic Project

Use the Array that Bison Kick Creates and make your own basic project. More advanced features next.

In the tutorial I mention Chris Hecker and David Baraff.  There is more to Google on them.

embedded by Embedded Video

Download Video

Here’s the complete code for that tutorial:

package 
{	
	import Box2D.Dynamics.Joints.*;
	import flash.display.Sprite;
	import flash.events.KeyboardEvent;
	import flash.events.Event;
	import Box2D.Dynamics.*;
	import Box2D.Collision.*;
	import Box2D.Collision.Shapes.*;
	import Box2D.Common.Math.*;
 
	public class Main extends Sprite {
		public var world:b2World=new b2World(new b2Vec2(0,10.0),true);
		public var world_scale:int = 30;
 
		public static const SQUARE:String = "SQUARE";
		public static const CIRCLE:String = "CIRCLE";
		public var fixtureDef:b2FixtureDef = new b2FixtureDef();
 
		public var specialB2Body:b2Body;
 
		public var motorOn:Boolean;
 
		//order: x , y , height, width, rotation, isDynamic, shape, friction,density,restitution,ID 
 var map:Array = [
[178.4246951759643,152.08217416150734,50,312.988474529966,0.4818088365028909,false,'SQUARE' , 0.5,0.5,0.54,'floor']
,[401.6,162.7,50,269,-0.44942046244170436,false,'SQUARE' , 0.5,0.5,0.5,'floor']
,[284,78,50,50,0,true,'CIRCLE' , 0.5,0.6,0.77,'ball']
];
		//
		public function Main():void 
		{
			debug_draw();
 
			for (var i:uint = 0; i < map.length; i++)
			{
				var sx:Number = map[i][0];
				var sy:Number = map[i][1];
				var sizerh:Number = map[i][2];
				var sizerw:Number = map[i][3];
				var srot:Number = map[i][4];
				var sIsDynamic:* = map[i][5];
				var sShape:String = map[i][6];
				var sFric:Number = map[i][7];
				var sMass:Number = map[i][8];
				var sRest:Number = map[i][9];
				var boxId:int = map[i][10];
 
				if (sShape == SQUARE)
				{	
					draw_box(sx, sy, sizerw, sizerh, sIsDynamic,srot,sFric,sMass,sRest,boxId);
				}
				else if (sShape == CIRCLE)
				{
					draw_circle(sx, sy, sizerw / 2, sIsDynamic,srot,sFric,sMass,sRest,boxId);
				}
			}
			addEventListener(Event.ENTER_FRAME, update);
		}
 
		public function draw_circle(px:Number, py:Number, r:Number, d:Boolean, rot:Number,
		fric:Number,mass:Number,rest:Number,boxId:int):void {
			var my_body:b2BodyDef= new b2BodyDef();
			my_body.position.Set(px / world_scale, py / world_scale);
			if (d) 
			{
				my_body.type=b2Body.b2_dynamicBody;
			}
			my_body.angle = rot;
			var my_circle:b2CircleShape=new b2CircleShape(r/world_scale);
			var my_fixture:b2FixtureDef = new b2FixtureDef();
			my_fixture.density = mass;
			my_fixture.friction = fric;
			my_fixture.restitution = rest;
			my_fixture.shape=my_circle;
			var world_body:b2Body = world.CreateBody(my_body);
			world_body.CreateFixture(my_fixture);
		}
 
		public function draw_box(px:Number, py:Number, w:Number, h:Number, d:Boolean, rot:Number,
		fric:Number,mass:Number,rest:Number,boxId:int):void {
			var my_body:b2BodyDef = new b2BodyDef();
 
			my_body.position.Set(px / world_scale, py / world_scale);
			my_body.angle = rot;
			if (d) 
			{
				my_body.type=b2Body.b2_dynamicBody;
			}
			var my_box:b2PolygonShape = new b2PolygonShape();
			my_box.SetAsBox(w/2/world_scale, h/2/world_scale);
			var my_fixture:b2FixtureDef = new b2FixtureDef();
			my_fixture.density = mass;
			my_fixture.friction = fric;
			my_fixture.restitution = rest;
			my_fixture.shape=my_box;
			var world_body:b2Body=world.CreateBody(my_body);
			world_body.CreateFixture(my_fixture);
		}
 
		public function debug_draw():void {
			var debug_draw:b2DebugDraw = new b2DebugDraw();
			var debug_sprite:Sprite = new Sprite();
			addChild(debug_sprite);
			debug_draw.SetSprite(debug_sprite);
			debug_draw.SetFillAlpha(0.3);
			debug_draw.SetDrawScale(world_scale);
			debug_draw.SetFlags(b2DebugDraw.e_shapeBit);
			world.SetDebugDraw(debug_draw);
		}
		public function update(e : Event):void {
			world.Step(1 / 30, 10, 10);			
			world.ClearForces();
			world.DrawDebugData();
		}
	}
}

To make the camera follow the follower:

In your array add one more element to the shape that you want to be followed:
Let’s make the dynamic ball followed

//order: x , y , height, width, rotation, isDynamic, shape, friction,density,restitution,ID 
 var map:Array = [
[314.5,105,50,467,0.13952573808365668,false,'SQUARE' , 0.5,0.5,0.5,'column']
,[225,198,50,50,0,false,'SQUARE' , 0.5,0.5,0.5,'floor']
,[165,17,50,50,0,true,'CIRCLE' , 0.5,0.5,0.5,'hero', 'follower']
];

Then declare a specialB2Body in your member properties area:
And declare whether this time there is a follower.

public var specialB2Body:b2Body;
//is there a follower this time around
public var follower:Boolean;

Then create a new variable under the declaration of the boxId variable.. About line 48

var sFollow:String = map[i][11] == null ? "": map[i][11];

This way if they add a follower It’s ok. but if not that’s ok too.
Then let’s test for a follower:

if (sFollow == 'follower')
				 {
					 special = true;
					 follower = true;
				 }

In draw_box and draw_circle functions we need to add one more parameter: ‘special’.

if (sShape == SQUARE)
				{	
					draw_box(sx, sy, sizerw, sizerh, sIsDynamic,srot,sFric,sMass,sRest,special);
				}
				else if (sShape == CIRCLE)
				{
					draw_circle(sx, sy, sizerw / 2, sIsDynamic,srot,sFric,sMass,sRest,special);
				}

Then in draw_circle and draw_box functions we want to add the following line of code. If the shape is special let’s assign the SpecialB2Body to it.

if (special)
			{
				specialB2Body = world_body;
			}

And last we need to change that update() function around so that the camera follows the follower.
It’s all about that x and y… Thanks to Emanuele Feronato for this part.

		public function update(e : Event):void {
			var pos_x:Number;
			var pos_y:Number;
 
			if(follower)
			{
				pos_x= specialB2Body.GetWorldCenter().x*world_scale;
				pos_y= specialB2Body.GetWorldCenter().y*world_scale;
				x=stage.stageWidth/2-pos_x;
				y=stage.stageHeight/2-pos_y;
			}
 
			world.Step(1 / 30, 10, 10);			
			world.ClearForces();
			world.DrawDebugData();
		}

Quick Video tutorial on Bison Kick

A quick tutorial on Bison Kick.

embedded by Embedded Video

Download Video

Actionscript3 Copy (Ctrl+c) Keyboard listener in Flex

It’s tricky to get the Ctrl C command just right.
Here’s how:
use the input class included in Box2d. It’s great
It wants a reference to the stage which should be a sprite.

input = new Input(this.systemManager as Sprite);

Then you just need to catch both Ctrl and C:

if(Input.isKeyDown(67) &amp;&amp; Input.isKeyDown(17))
{
Alert.show("Copy");
}

Bisonkick Box2d Editor with live preview

I just finished putting together a pretty neat box2d editor.

Bison Kick

One of things that I felt was lacking in some of them was:

  • Allowing the user to see his creation before he puts it on the screen.
  • Colors that correspond to Box2d.
  • Online.
  • Fun

Try it out for yourself.

One of the biggest challenges that I faced was making a upper left registration point calculate to a center point.

I did achieve this. Here’s how

I also made a live preview window.

I did this by checking out the box2d live sample.  It was only a matter of a titleWindow with a UIComponent & a Sprite child.

I still have some good work to do on it. And of course all your suggestions and bug finds are most wanted.
I may be releasing this open source soon. Is that of any interest to you?

Update:
Here is some sample code that you could paste your array into:
Make sure that you have the Box2d Library 2.01a
Also make sure you mark one box (or array) with an extra string ‘special’. Doing this will allow the camera to follow it.
Like this line:,[103,106,50,50,0.00000,true,'CIRCLE', 0.5,0.81,0.5,'special']:

package 
{	
	import Box2D.Dynamics.Joints.*;
	import flash.display.Sprite;
	import flash.events.Event;
	import Box2D.Dynamics.*;
	import Box2D.Collision.*;
	import Box2D.Collision.Shapes.*;
	import Box2D.Common.Math.*;
	public class Main extends Sprite {
		public var world:b2World=new b2World(new b2Vec2(0,10.0),true);
		public var world_scale:int = 30;
 
		public static const SQUARE:String = "SQUARE";
		public static const CIRCLE:String = "CIRCLE";
		public var fixtureDef:b2FixtureDef = new b2FixtureDef();
 
		public var rear_motor_added:b2RevoluteJoint;
		public var front_motor_added:b2RevoluteJoint;
 
		public var specialB2Body:b2Body;
 
//order: x , y , height, width, rotation, isDynamic, shape, friction,mass,restitution 
 var map:Array = [
[289.50030740925064,231.99920164944322,50,465,0.26044,false,'SQUARE', 0.5,0.5,0.52]
,[94,300,240,50,0.00000,false,'SQUARE', 0.5,0.5,0.5]
,[470,356,156,50,0.00000,false,'SQUARE', 0.5,0.5,0.52]
,[103,106,50,50,0.00000,true,'CIRCLE', 0.5,0.81,0.5,'special']
,[751.475,411.7,50,521.55,0.00000,false,'SQUARE', 0.5,0.5,0.5]
,[984.9,234.32500000000002,387.55,50,0.00000,false,'SQUARE', 0.5,0.5,0.5]
];
 
		public function Main():void 
		{
			debug_draw();
 
			for (var i:uint = 0; i < map.length; i++)
			{
				var sx:Number = map[i][0];
				var sy:Number = map[i][1];
				var sizerh:Number = map[i][2];
				var sizerw:Number = map[i][3];
				var srot:Number = map[i][4];
				var sIsDynamic:* = map[i][5];
				var sShape:String = map[i][6];
				var sFric:Number = map[i][7];
				var sMass:Number = map[i][8];
				var sRest:Number = map[i][9];
				var special:Boolean;
				if (map[i].length > 10)
				{
					special = true;
				}
				else 
				{
					special = false;
				}
 
				if (sShape == SQUARE)
				{	
					draw_box(sx, sy, sizerw, sizerh, sIsDynamic,srot,sFric,sMass,sRest,special);
				}
				else if (sShape == CIRCLE)
				{
					draw_circle(sx, sy, sizerw / 2, sIsDynamic,srot,sFric,sMass,sRest,special);
				}
			}
			//createCar();
			addEventListener(Event.ENTER_FRAME, update);
		}
 
		public function draw_circle(px:Number, py:Number, r:Number, d:Boolean, rot:Number,
		fric:Number,mass:Number,rest:Number,special:Boolean):void {
			var my_body:b2BodyDef= new b2BodyDef();
			my_body.position.Set(px / world_scale, py / world_scale);
			if (d) 
			{
				my_body.type=b2Body.b2_dynamicBody;
			}
			my_body.angle = rot;
			var my_circle:b2CircleShape=new b2CircleShape(r/world_scale);
			var my_fixture:b2FixtureDef = new b2FixtureDef();
			my_fixture.density = mass;
			my_fixture.friction = fric;
			my_fixture.restitution = rest;
			my_fixture.shape=my_circle;
			var world_body:b2Body = world.CreateBody(my_body);
			world_body.CreateFixture(my_fixture);
			if (special)
			{
				trace("SPECIAL Circle");
				specialB2Body = world_body;
			}
		}
		public function draw_box(px:Number, py:Number, w:Number, h:Number, d:Boolean, rot:Number,
		fric:Number,mass:Number,rest:Number,special:Boolean):void {
			var my_body:b2BodyDef = new b2BodyDef();
 
			my_body.position.Set(px / world_scale, py / world_scale);
			my_body.angle = rot;
			if (d) 
			{
				my_body.type=b2Body.b2_dynamicBody;
			}
			var my_box:b2PolygonShape = new b2PolygonShape();
			my_box.SetAsBox(w/2/world_scale, h/2/world_scale);
			var my_fixture:b2FixtureDef = new b2FixtureDef();
			my_fixture.density = mass;
			my_fixture.friction = fric;
			my_fixture.restitution = rest;
			my_fixture.shape=my_box;
			var world_body:b2Body=world.CreateBody(my_body);
			world_body.CreateFixture(my_fixture);
			if (special)
			{
				trace("SPECIAL Square");
				specialB2Body = world_body;
			}
		}
 
		public function debug_draw():void {
			var debug_draw:b2DebugDraw = new b2DebugDraw();
			var debug_sprite:Sprite = new Sprite();
			addChild(debug_sprite);
			debug_draw.SetSprite(debug_sprite);
			debug_draw.SetDrawScale(world_scale);
			debug_draw.SetFlags(b2DebugDraw.e_shapeBit);
			world.SetDebugDraw(debug_draw);
		}
		public function update(e : Event):void {
			var pos_x:Number;
			var pos_y:Number;
 
			pos_x= specialB2Body.GetWorldCenter().x*world_scale;
			pos_y= specialB2Body.GetWorldCenter().y*world_scale;
			x=stage.stageWidth/2-pos_x;
			y=stage.stageHeight/2-pos_y;
 
			world.Step(1 / 30, 10, 10);			
			world.ClearForces();
			world.DrawDebugData();
		}
	}
}

Removing eventlisteners from MXML tags

You cannot remove eventlisteners from MXML tags. Only from actionscript. If anyone knows of a way to do it. Let me know.
Aka this will not work:

<mx:Button id="button1" label="button 1" click="clicked(event);"/>
<mx:Script>
		<![CDATA[
			import mx.controls.Alert;
			private function clicked(e:MouseEvent):void
			{
				Alert.show('Oh Hai this working now.');	
			}
			private function removeUm(e:MouseEvent):void
			{
				button1.removeEventListener(MouseEvent.CLICK,removeMeBaby);
			}
		]]>
	</mx:Script>

Detect iPhone with PHP

Detect iPhone with PHP:

<?php
$browser = strpos($_SERVER['HTTP_USER_AGENT'], "iPhone");
if ($browser == true)  
{
	echo 'its an iPhone!'; 
}
?>

MYSQL Join a table to itself

Sometimes you need to do this in MYSQL. But I have not figured out how to use it in wordpress yet because it has the same columns twice. But it does work.  Let’s say you have a table named my_table which stores categories. Three columns:

  1. cat_id
  2. cat_name
  3. cat_parent

Just like wordpress… every category would have a parent. So now you want to join the table on the parent.. You need to see where the cat_parent and the cat_id are the same so you can get the cat_name. Here’s the code.

SELECT * FROM my_table AS child
LEFT JOIN my_table AS parent ON parent.cat_id = child.cat_parent

Stick with Flash

Even if Apple does create it’s own version of Flash… (Which is a really dumb idea to assume that after all these years Adobe has no idea how to do this stuff right and that suddenly Apple could do it better.) I will stick will Flash till the very end. Even if no one is using it.  Which is not going to happen, and you wanna know why?

Because Steve Jobs is a nut job.

Adding an Administration Menu in your WordPress plugin

Here is how to add an Administration Menu in your WordPress plugin:

This is “ill advised” or last resort. Because usually there are better options like adding a menu to the “Appearance” section or “Plugins” section. But sometimes you need to do this.

First you need to add your action.

<?php
add_action('admin_menu', 'whatsnew_menu');
?>

Where admin_menu is where you want this action to be called. In this case it will be called when WordPress is generating administration menus. Then ‘whatsnew_menu’ is the function that will get called to actually add the menu.

Next we write the function that will add the menu to the administration menu.

<?php
function whatsnew_menu()
{
    $allowed_group = 'manage_options';
 
    //Add the admin panel for whats new
        add_menu_page(__('What\'s New','whtsnew'), __('What\'s New','whtsnew'),$allowed_group,'whtsnew','menu_page_display');
}
?>

add_menu_page will add a top level menu. You can add an icon to this too! allowed group is who will be able to see this top level menu.. Just admins, authors or who? You decide. See this page for more info.

Last but not least we write a function that will echo what is displayed when one clicks on the menu.

function menu_page_display()
{
	echo 'HEY MOM';	
}

Book on Programming at the Binary Level in AS3.

Want to learn how to program at the Binary level in AS3 (Actionscript 3)? This is something that is hard to find a good tutorial or even good information on the web. You need someone who can really explain this stuff from the ground up.
Check out this great first chapter that Thibault Imbert posted at his site. I love free stuff. I mean who doesn’t? But an open source book… That is so rare. We can all agree that Thibault Imbert is one really nice guy and one smart cookie.
Thanks Thibault!

14 free IDEs for 4 languages (Actionscript, Java, Javascript, and PHP)

The following are FREE tools for various languages (in no particular order)

Actionscript

Windows

  • FlashDevelop

Java

Mac

  • BlueJ
  • Eclipse JDT
  • Geany
  • Greenfoot
  • IntelliJ IDEA
  • JDeveloper (freeware)
  • MonoDevelop
  • NetBeans
  • XCode (freeware)

Windows

  • BlueJ
  • Eclipse JDT
  • Geany
  • Greenfoot
  • IntelliJ IDEA
  • JDeveloper (freeware)
  • MonoDevelop
  • NetBeans

Javascript

Mac/Apple OR Windows

  • Aptana Studio
  • NetBeans

PHP

Mac/Apple

  • Aptana Studio
  • Eclipse PDT
  • NetBeans
  • PHPEclipse

Windows

  • Aptana Studio
  • Dev-PHP
  • Eclipse PDT
  • NetBeans
  • PHPEclipse

How to get all pictures listed from the media library for your WordPress plugin

Here is how to get all the pictures listed from the media library.
Pictures from the media library are stored in the database in the posts table. So technically they are a post.
Here are a list of whats available in the posts table.

  • ID
  • post_author
  • post_date
  • post_date_gmt
  • post_content
  • post_title
  • post_excerpt
  • post_status
  • comment_status
  • ping_status
  • post_password
  • post_name
  • to_ping
  • pinged
  • post_modified
  • post_modified_gmt
  • post_content_filtered
  • post_parent
  • guid
  • menu_order
  • post_type
  • post_mime_type
  • comment_count

Now some of these are only for attachments, some are for posts, and some are for pages.
post_type will tell you if it is a post,page or attachment.
If it is an attachment then post_mime_type will tell you what type of media it is. I.e: jpeg,png,video or whatever.

So Heres What We Are Gonna Do

We will make a query to the posts table asking for post_type to be 'attachment'. And the post_mime_type to be all different types of picture files aka: jpeg,png,gif,tiff, or whatever. Then we will display it in a nice table.

Let’s Do It

 
global $wpdb;
$pictures = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $wpdb->posts WHERE post_type = 'attachment' AND post_status != 'trash' AND (post_mime_type = 'image/jpeg'
             OR post_mime_type = 'image/gif' OR post_mime_type = 'image/png')"));
             ?>
 
<table class="widefat page fixed" width="80%" cellpadding="3" cellspacing="3">
       <thead>
        <tr>
            <th scope="col"><?php  echo _x('Preview','preview of the image'); ?></th>
       </tr>
        </thead>
<tbody>
   <?php
    foreach($pictures as $picture)
    {
        ?>
        <tr>
            <td>
        <?php
        $the_img = wp_get_attachment_image_src( $picture->ID,"full" );
        $the_img_link = $the_img[0];
 
        echo '<a href="' . $the_img_link . '" title="Nice Pic" class="thickbox">' . wp_get_attachment_image( $picture->ID,array(80,60) ) . '</a>';
 
        ?>
            </td>
        </tr>
 </tbody>
</table>

A Couple Things to Note

  • You must import thickbox in order for this example to work so wp_enqueue_script('thickbox'); and wp_enqueue_style('thickbox');
  • There are two really important functions for getting the right attachment/picture returned from the database. wp_get_attachment_image_src('') and wp_get_attachment_image('');

    • wp_get_attachment_image() “Returns an HTML image element representing an attachment file, if there is any, otherwise an empty string.” At minimum you need to supply it with the id of the image. Which you will get from our for each loop. You can also get it to return the picture in the correct size by saying either thumbnail, medium, large or full. Or you can tell it what size you want the pic to be in an array: array(60,80). In our code we do a little bit of both. And last you can tell it (boolean) whether or not you want it to represent the media with an icon.
    • wp_get_attachment_image_src() returns the facts about the image in an array $image[0] => url, $image[1] => width, $image[2] => height… So we can use it to get the array of the photo.
  • $wpdb->prepare() takes care of all that quote mess you would have to do to put in $wpdb->posts in the middle of a mysql statement.
  • Oh and what the heck is this: _x()? It’s another translation tool, since our plugins will be in many different languages.

Make a WordPress plugin with database

WordPress has a great class for interacting with the database.
That class is wpdb

Let’s take a sample plugin from the last post..
Here’s the full code:

<?php
/*
Plugin Name: Random Quote Maker
Plugin URI: http://www.jacobchatz.com
Description: Allows you to insert a random quote.
Author: Jacob Schatz
Author URI: http://www.jacobschatz.com
Version: 1.0
*/
 
// [randomquote]
function random_quote($atts)
{
 
 
    return $quotes[rand(0,(count($quotes)-1))];
}
 
add_shortcode('randomquote', 'random_quote');
 
?>

If you are confused see that last post for explanation.
We made a shortcode.
Now let’s fill a custom table in our database with quotes and allow users to add more quotes in the admin section of our plugin. There’s is a lot to learn.

First let’s get rid of that $quotes array because all our info will be stored in the database.


We first need to make an admin menu in the back-end.
We need to add an action…

There are a lot of things being fired off at different times when a page loads in WordPress
To slip some code in at the exact right time we use the appropriate action.

add this below the blockquotes and before the function

//master menu for castlist and subpages
add_action('admin_menu', 'randomquote_menu');
 
function randomquote_menu()
{
    $allowed_group = 'manage_options';
 
    //Add the admin panel for randomquote
    if(function_exists('add_menu_page'))
    {
        add_menu_page(__('Random Quote Maker','rndmqmker'), __('Random Quote Maker','rndmqmker'),$allowed_group,'rndmqmker','edit_options');
    }
}

Explanation: This add_action will fire off when the admin menu is loading up. This is the time to add our own admin menu.


This may be overkill for a small plugin. You can also put your menu in other places.

For this example we will make an entirely new menu.


Then we respond to the admin menu being ready by adding our own menu.


‘rndmqmker’ is our custom call code I made up that stands for random quote maker. It has to be unique. You will see it in those
At the end we need to call a function edit_options so we can add stuff to our admin menu.

Add that function and echo some fun message and let’s check it out.. Full code so far:

<?php
/*
Plugin Name: Random Quote Maker
Plugin URI: http://www.jacobchatz.com
Description: Allows you to insert a random quote.
Author: Jacob Schatz
Author URI: http://www.jacobschatz.com
Version: 1.0
*/
 
//master menu for castlist and subpages
add_action('admin_menu', 'randomquote_menu');
 
function randomquote_menu()
{
    $allowed_group = 'manage_options';
 
    //Add the admin panel for randomquote
    if(function_exists('add_menu_page'))
    {
        add_menu_page(__('Random Quote Maker','rndmqmker'), __('Random Quote Maker','rndmqmker'),$allowed_group,'rndmqmker','edit_options');
    }
}
 
function edit_options()
{
    echo 'Hey it worked';
}
 
// [randomquote]
function random_quote($atts)
{
    return $quotes[rand(0,(count($quotes)-1))];
}
 
add_shortcode('randomquote', 'random_quote');
 
?>

Upload it and make sure the plugin is activated and refresh your admin panel and check it out:



Click the menu and see your message. Also take note of the url ending in /admin.php?page=rndmqmker.




Now let’s check if the user has our database install already and has the latest version of it.


Add this into edit_options():
check_random_quote_database();


Define a constant for the table name:
define('RANDOM_Q_TABLE',$wpdb->prefix . 'random_q_table');
This adds whatever db prefix they have onto your table name.
Now write that function.

function check_random_quote_database()
{
    global $wpdb;
	$rq_db_version = 1.0;
	$table_name = RANDOM_Q_TABLE;
	if($wpdb->get_var("SHOW TABLES LIKE '$table_name'") != $table_name)
	{
		$sql = "CREATE TABLE " . $table_name . " (
		rq_id INT(11) NOT NULL AUTO_INCREMENT,
		rq_quote TEXT,
		rq_author VARCHAR(100) NOT NULL DEFAULT 'anonymous',
		PRIMARY KEY  id (rq_id)
		);";
 
		require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
		dbDelta($sql);
 
		$insert = "INSERT INTO " . $table_name .
		" (rq_quote, rq_author) " .
            "VALUES ('A penny saved is a penny earned.','Ben Franklin')";
 
		$results = $wpdb->query( $insert );
		add_option("rq_db_version", $rq_db_version);
	}
        //for updates
        $installed_ver = get_option( "cl_db_version" );
}
  1. We call $wpdb to make the wordpress database class available.
  2. See if the table exists… If not create it
  3. Create a id, the quote and author.
  4. dbDelta checks (and runs the query) this against other existing table structures and changes accordingly, makes things really easy on us(make sure you have 2 spaces between primary key and id)
  5. Insert dummy data.
  6. Run the query.
  7. Save the database version in our options for later. This makings updating and changing the database structure a lot easier for your plugin clients.

Check in your db… It worked.





Adding quotes through back-end

Now we will allow the user to add the quotes finally. They could add 999 billion quotes if they wanted to.


Let’s make a UI.
Erase echo 'Hey it worked'; Replace it with this:

function rq_edit_options()
{
    global $wpdb;
 
    //get everything if it is available...
    $action     = !empty($_REQUEST['action']) ? $_REQUEST['action'] : 'add';
    //for deleting
    $quote_id   = !empty($_REQUEST['quote_id']) ? $_REQUEST['quote_id'] : '';
    //the quote itself
    $quote      = !empty($_REQUEST['quote']) ? $_REQUEST['quote'] : '';
    //the author of the quote... Anonymous if left blank...
    $author     = !empty($_REQUEST['author']) ? $_REQUEST['author'] : 'Anonymous';
 
    //check to see if the database is installed... and if they have the right version later...
    check_random_quote_database();
 
    //if there is a quote ready to be saved let's save it right away
    if(!empty($quote))
    {
        //some security.
        $quote = trim(htmlspecialchars(mysql_real_escape_string($quote)));
        //trust no one and escape everything.
        $author = trim(htmlspecialchars(mysql_real_escape_string($author)));
        //the query.
        $sql = "INSERT INTO " . RANDOM_Q_TABLE . " (rq_quote,rq_author) VALUES ('" . $quote . "','" . $author . "');";
        //run the query.
        $wpdb->get_results($sql);
        //See if the query successfully went through...
        $sql = "SELECT * FROM " . RANDOM_Q_TABLE . " WHERE rq_quote='" . mysql_real_escape_string($quote) . "'";
            $results = $wpdb->get_results($sql);
            //if it returned a non empty quote we know it worked
            if(!empty($results[0]->rq_quote))
            {
                //pre setup class for the div to display that nice updated message...
                ?>
                <div class="updated"><p><?php _e('Quote saved successfully','rndmqmker'); ?></p></div>
                <?php
            }
            else
            {
                //pre setup error class for the div to display that nice error message...
                ?>
                <div class="error"><p><strong><?php _e('Failure','rndmqmker'); ?></strong><?php _e(' It did not save, sorry, try again');?></p></div>
                <?php
            }
    }
 
    //will be 'add' by default
    if($action == 'add')
    {
        //wrap will make everything look nice and wordpress like.
        ?>
        <div class="wrap">
        <h2><?php _e('Add Quote','rndmqmker'); ?></h2>
        <?php
        //put the add quote form in
        rq_add_form();
        //show a table of all the quotes.
        rq_display_quotes();
        ?>
        </div>
        <?php
    }
    //if they are deleting a quote
    else if($action == 'delete')
    {
        //do we have a quote id?
        if(!empty($quote_id))
        {
            //the query
            $sql = "DELETE FROM " . RANDOM_Q_TABLE . " WHERE rq_id='" . mysql_real_escape_string($quote_id) . "'";
            //run the query
            $wpdb->get_results($sql);
            //check that it worked... The query
            $sql = "SELECT * FROM " . RANDOM_Q_TABLE . " WHERE rq_id='" . mysql_real_escape_string($quote_id) . "'";
            //run it
            $results = $wpdb->get_results($sql);
            //did we get anything back? If so it didn't delete
            if(empty($results) || empty($results[0]->rq_id))
            {
                ?>
                <div class="updated"><p><?php _e('Deleted successfully','rndmqmker'); ?></p></div>
                <?php
            }
            else
            {
                ?>
                <div class="error"><p><strong><?php _e('Failure','rndmqmker'); ?></strong><?php _e('It did not delete, sorry, try again');?></p></div>
                <?php
            }
        }
        else
        {
            ?>
            <div class="error"><p><strong><?php _e('Hey...','rndmqmker'); ?></strong><?php _e('You can\'t delete a quote without a quote id' );?></p></div>
            <?php
        }
    }
}

A lot done here. Read a lot of the comments to get the idea. Here’s more explanation.

  • We checked for all the info.
  • Checked that the database is installed. If not we install it.
  • If there is a quote ready we save it right into the database.
  • If we saved it we relay the message saying it was saved.. or that it didn’t work.
  • If the action is add, which it will be the first time around. We display the form and the available quotes(not written yet).
  • If they pressed delete then we will delete the quote from the database using it is quote id. And display the message saying whether it worked or not

Now we need those two functions. 1 will show the form to write quotes. 2 will show all the quotes in a nice predefined table.
Here are those two functions.

 
function rq_display_quotes()
{
        //we need the wp database functions
	global $wpdb;
 
        //get all the quotes and authors
        $quotes = $wpdb->get_results( 'SELECT * FROM ' . RANDOM_Q_TABLE . ' ORDER BY ' . RANDOM_Q_TABLE . '.rq_author ASC');
 
        //if we got quotes back...
	if( !empty($quotes))
	{
		?>
		<table class="widefat page fixed" width="100%" cellpadding="3" cellspacing="3">
			<thead>
			<th><?php _e('ID','rndmqmker') ?></th>
			<th><?php _e('Quote','rndmqmker') ?></th>
			<th><?php _e('Author','rndmqmker') ?></th>
			<th><?php _e('Delete','rndmqmker') ?></th>
			</thead>
			<tbody>
		<?php
                //loop through the results of all the quotes
		$class = '';
		foreach($quotes as $quote)
		{
                    //make the rows look nice by alternating the colors of the row.. Prebuilt feature
			$class = ($class == 'alternate') ? '' : 'alternate';
			if(strlen($quote->rq_quote) > 30)
			{
                            //if this quote is longer than 30 do a dot dot dot
				$new_quote = substr($quote->rq_quote,0, 30);
				$new_quote .= "...";
			}
			else
			{
				$new_quote = $quote->rq_quote;
			}
			$url = get_bloginfo('wpurl');
                        //output the info into the table.. It will call itelf when they press delete... PHP_SELF
			?>
			<tr class="<?php echo $class; ?>">
				<th scope="row"><?php echo $quote->rq_id;?></th>
				<td><?php echo $new_quote; ?></td>
                                <td><?php echo $quote->rq_author; ?></td>
				<td><a href="<?php echo $_SERVER['PHP_SELF'] ?>?page=rndmqmker&amp;action=delete&amp;quote_id=<?php echo $quote->rq_id;?>" class="delete" onclick="return confirm('<?php _e('Are you sure you want to delete this quote?','rndmqmker'); ?>')"><?php echo __('Delete','rndmqmker'); ?></a></td>
			</tr>
		<?php
		}
		?>
		</tbody>
		</table>
		<?php
	}
	else
	{
            //otherwise there is nothing to show
		?>                
		<p><?php _e("There are no quotes in the database yet!", 'rndmqmker');?></p>
		<?php
	}
}
 
function rq_add_form()
{
    // here is the form they fillout. to make a new quote...
        ?>
    <div class="wrap">
	<form class="wrap" method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>?page=rndmqmker">
            <div id="linkadvanceddiv" class="postbox">
                <div style="float: left; width: 100%; clear: both;" class="inside">
                <table cellpadding="5" cellspacing="5">
                <tr>
                <td><?php _e('Quote', 'rndmqmker'); ?></td>
                <td>
                    <textarea name="quote" class="input" rows="5" cols="50"></textarea>
                </td>
                </tr>
                <tr>
                    <td><?php _e('Author','rndmqmker');?></td>
                    <td>
                        <input type="text" name="author" class="input" size="40" maxlength="200" value=""/>
                    </td>
                </tr>
                <tr><td>
                   <input type="submit" name="save" class="button bold" value="<?php _e('Save', 'rndmqmker'); ?> &raquo;" />
                </td></tr>
                </table>
                </div>
            </div>
        </form>
    </div>
        <?php
}
//delete this thing
?>
  • First we get all the quotes from the database of quotes using: function rq_display_quotes()
  • We use a table because this is tabular info, perfect for a table. We use the class class="widefat page fixed" which will make a nice looking table as you will see.
  • Make table headers in thead and th
  • Loop through the quotes
  • Clicking delete will call this script and run the if($action == delete) part.
  • Then we make a form to fill out for a new quote.. in rq_add_form
  • When it submits this script will get called again $_SERVER['PHP_SELF'];. And the variables will be set.. That means the data will get saved. $action will still be set to ‘add’.

What is _e()

They are for translating into other languages. They save everything you type into them so you can set up translation file later.
_e() echos the stuff and __() just makes it available for translation.


Save and upload the script. You will have the ability to save things to the database and delete things too.


Only one step left and that is to have the data display in the shortcode…


Let’s see a little preview


Finish it up

Now we just have to change that random_quote function to go to the database and return a random quote.

Here is how we do that:

// [randomquote]
function random_quote($atts)
{
    global $wpdb;
 
    $result = $wpdb->get_row('SELECT * FROM ' . RANDOM_Q_TABLE . ' ORDER BY RAND() LIMIT 1');
 
    return $result->rq_quote . '<br />--' . $result->rq_author;
}
  • RAND() returns a random order.
  • It returns it in an array.



Try it out as you did before and add some quotes.