Setting the ToggleButtonBar to be completely unselected
//-------------------AS3 version var tb:ToggleButtonBar = new ToggleButtonBar(); tb.selectedIndex = -1; //-------------------MXML version <mx:ToggleButtonBar selectedIndex="-1" />
//-------------------AS3 version var tb:ToggleButtonBar = new ToggleButtonBar(); tb.selectedIndex = -1; //-------------------MXML version <mx:ToggleButtonBar selectedIndex="-1" />
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”
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();
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.
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:
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.
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; } }
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.
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 < 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(); } } }
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(); }
A quick tutorial on Bison Kick.
embedded by Embedded Video
Download Video
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) && Input.isKeyDown(17)) { Alert.show("Copy"); }
I just finished putting together a pretty neat box2d editor.
One of things that I felt was lacking in some of them was:
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(); } } }
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:
<?php $browser = strpos($_SERVER['HTTP_USER_AGENT'], "iPhone"); if ($browser == true) { echo 'its an iPhone!'; } ?>
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:
cat_idcat_namecat_parentJust 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
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?
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'; }
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!
The following are FREE tools for various languages (in no particular order)
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.
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.
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.
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>wp_enqueue_script('thickbox'); and wp_enqueue_style('thickbox');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. _x()? It’s another translation tool, since our plugins will be in many different languages.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 appropriateaction.
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" ); }
Check in your db… It worked.
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.
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&action=delete&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'); ?> »" />
</td></tr>
</table>
</div>
</div>
</form>
</div>
<?php
}
//delete this thing
?>function rq_display_quotes()class="widefat page fixed" which will make a nice looking table as you will see.thead and thif($action == delete) part.rq_add_form$_SERVER['PHP_SELF'];. And the variables will be set.. That means the data will get saved. $action will still be set to ‘add’._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

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.
Try it out as you did before and add some quotes.