We showed up Friday evening not really knowing what to expect, this was the first time that I or my brother have ever attended a Start Up Camp. All we knew was that we had three days to work on something, and that there would be prizes! We also knew that Ansca would be there, and that we would be able to use the Corona SDK, which we would find out later to be a tremendous help in speeding the development on our game.
The first night consisted of people pitching ideas. We didn’t really come in with an idea, so I just made an announcement that we were looking for an “idea person”, someone to come on to our team and flesh out a really nice game idea. Unfortunately everyone seemed to be more focused on application instead of games. At the end of the first night we came to the conclusion that we were going to have to do this ourselves.
The next morning, Saturday, I find out that my brother stayed up for a large portion of the night (he only got 3 hours of sleep) thinking of game ideas. We went to breakfast and narrowed down the ideas to a couple game mechanics. The main game mechanic would allow the user to draw real-time platforms with physics properties. The second game mechanic would be the ability to flip the phone 180 degrees and change the gravitational pull of the game. Both of these mechanics would be used to help our rolling ball find it’s way home.
Once we got back to San Francisco, later that day, we fleshed three levels on the white board, and I began coding while my brother started on the artwork. I was able to get the walls and physics mechanics by the end of the day thanks to Corona’s built in physics engine based of the popular Box2D Physics Engine (which I’ve used in the past). By the end of the day we had a decent base of code and some nice artwork, we also came up with the code name “Sticky Spider” (which we would later change).
On the final day we decided to come in at 9am, since we needed as much time as possible to finish up the game. I spent the first half of the day implementing our real-time platform creating mechanic. My brother spent time finalizing the background and working on a replacement for the ball in our original idea, a roly poly (which we ended up using as the final name for the game). After finishing off the first game mechanic, I finalized our first level and we were ready to move on to creating level two. Level two consisted of the user flipping the phone around and changing the gravity of the game. This took nothing but a couple lines of code thanks to the physics engine and the easy accelerometer support provided by the Corona SDK. We soon realized that we wouldn’t have enough time to put in all three levels, so we decided to concentrate on putting in two very good levels. After a couple of hours of polishing up the game, we were ready to present!
Level 1 of Roly Poly (Photo provided by Ansca)
While getting ready to present we found out that only 2 out of the 5 teams made it through the Start Up Camp, so at the very lease we would get 2nd place, but we were aiming for first! We presented first and everyone was impress with the artwork and how quickly we were able to put the game together. They were especially impress with how very little lines of code it took to create the game: 340 lines (including blank lines). After our presentation we got a nice round of applause, and watched the second teams presentation.
After the second team’s presentation the judges were ready to cast their votes. We were extremely gratified when we were declared the winners! Winning an iPad, $500, and a years subscription to the Corona SDK. The judges explained that it was the fact that we had a working game with two levels that caught their eyes. In a market where games come and go, you have to be quick on your feat and have to be able to put out a game very fast.
My brother (Cesar Miranda), the Co Founder and Chief Evangelist of Ansca (Carlos Icaza), and me (Photo provided by Ansca)
I had a great weekend with everyone at Start Up Camp, made lots of great connection, and had lots of fun. I can’t wait to finish up Roly Poly with my brother and have it out on the Apple and Android market!
I have been working on a prototype for a new Flash game, codenamed “Word Attack”. The finished game will eventually be submitted to Word Play- A Flash Game Contest, that is being hosted by Dictionary.com and Mochi Media. Check out the prototype below…
Note: There is no gameplay mechanic revolving around the blocks turning red after they stop moving, this is just something that the Box2D API does to let the developer know that objects are “sleeping” (not being simulated anymore).
As you can see, the player’s goal is to clear every level by creating words with the letters provided (for the prototype I created nine levels). One thing that is worth pointing out is that the player has the choice of completing a level in whatever fashion the player chooses, as long as the player clears out all the letters in the level by typing in valid words. For example, in level seven the letters falling down consist of “c”, “o”, “m”, “p”, “u”, “t”, “e”, and “r”. So the player can complete the level by either typing in “computer”, or by typing in “mop” and then typing in “cuter”.
I plan to expand more on the gameplay by working with a game designer, since it feels like it needs a bit more “fun” in order for it to not just be Scrabble with physics. This is also the first time I have used the Box2D API to develop a Flash game, and I must say, it’s turning out quite well so far .
Feel free to comment on the game, I’m also open to suggestions on gameplay or anything in general related to the game.
I mention in my last post that Todd Kerpelman created a set of Box2D video tutorials (http://www.kerp.net/box2d/), I just finished up the first chapter and here is what I came up with…
As you can see it isn’t a whole lot, just a bunch of boxes falling down, but damn does it look good .
Here is the source code for the project
package
{
import Box2D.Collision.b2AABB;
import Box2D.Collision.Shapes.b2PolygonDef;
import Box2D.Common.Math.b2Vec2;
import Box2D.Dynamics.b2Body;
import Box2D.Dynamics.b2BodyDef;
import Box2D.Dynamics.b2DebugDraw;
import Box2D.Dynamics.b2World;
import flash.display.MovieClip;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.ui.Keyboard;
import fl.controls.Button;
import flash.events.MouseEvent;
/**
* Final result of Todd Kerpelman's chapter 1 box2d video tutorial
* (http://www.kerp.net/box2d/).
* The code here is pretty much line for line from Kerpelman's tutorial
* I added a small modification so the simulation may be restarted when
* the user clicks the restart button in the top left of the screen.
* @author Edgar Miranda
*/
public class HelloBoxWorld extends MovieClip
{
protected var _world:b2World;
// Ratio of pixels to meters
public static const RATIO:Number = 40;
// Number of frames until we launch another crate
private var _nextCrateIn: int;
// Button to restart simulation
public var restartButton: Button;
public function HelloBoxWorld()
{
// 1. Set up the world
setupWorld();
// 2. Creating walls and floor
createWallsAndFloor();
setupDebugDraw();
_nextCrateIn = 0;
addEventListener(Event.ENTER_FRAME, newFrameEvent);
// Put the restart button on the top most index
// so it isn't covered by the falling crates
addChild(restartButton);
// Event listener in order to restart
// simulation when the restart button is pressed
restartButton.addEventListener(MouseEvent.CLICK, onRestartButtonClick)
}
private function onRestartButtonClick(e: MouseEvent): void {
// Remember that the world counts as one body so you
// want to remove bodies until there is only one body left
while (_world.GetBodyCount() > 1) {
_world.DestroyBody(_world.GetBodyList());
}
// recreate the walls again
createWallsAndFloor();
// set to default value
_nextCrateIn = 0;
}
private function setupDebugDraw():void
{
var spriteToDrawOn:Sprite = new Sprite();
addChild(spriteToDrawOn);
var artistForHire:b2DebugDraw = new b2DebugDraw();
artistForHire.m_sprite = spriteToDrawOn;
artistForHire.m_drawScale = RATIO;
artistForHire.SetFlags(b2DebugDraw.e_shapeBit);
artistForHire.m_lineThickness = 2.0;
artistForHire.m_fillAlpha = 0.6;
_world.SetDebugDraw(artistForHire);
}
private function newFrameEvent(e:Event):void
{
_world.Step( 1.0 / 30, 10);
// Every few frames, until a certain numer of crates have been added
if (_nextCrateIn-- <= 0 && _world.m_bodyCount < 80) {
// add a random create to the world
addARandomCrate();
_nextCrateIn = 1;
}
//trace("Falling crate is at", _fallingCrate.GetPosition().x, ",", _fallingCrate.GetPosition().y);
}
private function addARandomCrate():void
{
// Add a falling block to the world.
var fallingCrateDef:b2PolygonDef = new b2PolygonDef();
fallingCrateDef.SetAsBox(randomInt(5, 40) / RATIO, randomInt(5, 40) / RATIO);
fallingCrateDef.friction = 0.8;
fallingCrateDef.restitution = 0.3;
fallingCrateDef.density = 0.7;
// Set it to, 250, -30
var fallingBodyDef:b2BodyDef = new b2BodyDef();
fallingBodyDef.position.Set(randomInt(15, 530) / RATIO, randomInt(-100, -10) / RATIO);
fallingBodyDef.angle = randomInt(0,360) * Math.PI / 180;
var fallingCrate:b2Body = _world.CreateBody(fallingBodyDef);
fallingCrate.CreateShape(fallingCrateDef);
fallingCrate.SetMassFromShapes();
}
// Return a random number between lowVal and highVal, INCLUSIVE
private function randomInt(lowVal:int, highVal:int): int
{
if (lowVal <= highVal) {
return (lowVal + Math.floor(Math.random() * (highVal - lowVal + 1)));
}else
{
throw(new Error("OMG! Wrong values passed to randomInt!!"));
}
}
private function createWallsAndFloor():void
{
// Create the shape (polygon) definition
var bigLongShapeDef: b2PolygonDef = new b2PolygonDef();
bigLongShapeDef.vertexCount = 4;
b2Vec2(bigLongShapeDef.vertices[0]).Set(0 / RATIO, 0 / RATIO);
b2Vec2(bigLongShapeDef.vertices[1]).Set(550 / RATIO, 0 / RATIO);
b2Vec2(bigLongShapeDef.vertices[2]).Set(550 / RATIO, 10 / RATIO);
b2Vec2(bigLongShapeDef.vertices[3]).Set(0 / RATIO, 10 / RATIO);
bigLongShapeDef.friction = 0.5;
bigLongShapeDef.restitution = 0.3;
bigLongShapeDef.density = 0.0;
// Create the body definition
var floorBodyDef:b2BodyDef = new b2BodyDef();
floorBodyDef.position.Set(0 / RATIO, 390 / RATIO);
// Create the body
var floorBody:b2Body = _world.CreateBody(floorBodyDef);
// Create the shape
floorBody.CreateShape(bigLongShapeDef);
floorBody.SetMassFromShapes();
var tallSkinnyShape:b2PolygonDef = new b2PolygonDef();
tallSkinnyShape.SetAsBox( 5 / RATIO, 195 / RATIO);
tallSkinnyShape.friction = .5;
tallSkinnyShape.restitution = 0.3;
tallSkinnyShape.density = 0.0;
var wallBodyDef:b2BodyDef = new b2BodyDef();
wallBodyDef.position.Set(5 / RATIO, 195 / RATIO);
var leftWall:b2Body = _world.CreateBody(wallBodyDef);
leftWall.CreateShape(tallSkinnyShape);
leftWall.SetMassFromShapes();
wallBodyDef.position.Set(545 / RATIO, 195 / RATIO);
var rightWall:b2Body = _world.CreateBody(wallBodyDef);
rightWall.CreateShape(tallSkinnyShape);
rightWall.SetMassFromShapes();
//trace("My world now has", _world.m_bodyCount, "bodies in it! Wow!");
}
private function setupWorld():void
{
// 1. Set up the size of the universe
var universeSize:b2AABB = new b2AABB();
universeSize.lowerBound.Set( -3000 / RATIO, -3000 / RATIO);
universeSize.upperBound.Set( 3000 / RATIO, 3000 / RATIO);
// 2. Define gravity
var gravity: b2Vec2 = new b2Vec2(0, 9.8);
// 3. Ignore sleeping objects
var ignoreSleeping:Boolean = true;
_world = new b2World(universeSize, gravity, ignoreSleeping);
//trace("My world has", _world.GetBodyCount(), "bodies in it!");
}
}
}
You can get the Zip file containing all the project resources (source code, FLA, FlashDevelop project file) by clicking the link below.
My next goal is to finish up chapter 2, which is a bit longer then chapter 1 (50 lessons instead of 22). I’m currently on chapter 2 lesson 4, and I’m aiming to do around 5-10 lessons a day. I find it it’s easier to learn if I do about an hour or so of lessons each day instead of doing the whole batch in a day or two, there is also so much I can take of just watching video tutorials all day .
So a while ago (almost a year ago) I got bored one night and decided to make a beginner video tutorial on using the Box2DFlashAS3 physics engine, you can find the tutorial at the following … http://shah-soft.com/~warhell/box2d/Box2DFlash%20HelloWorld.html. Since that time, Todd Kerpelman (kerp.net) has created an extensive set of video tutorials for Box2DFlashAS3. If you’re interested in learning how to use this great Flash physics engine I highly recommend checking out videos, you can find them at… http://www.kerp.net/box2d/. Be sure to check out chapter 1.2, he gives me a shout out for creating the original beginner video tutorial .