Get the source code of Slingy, a Flash game I would like to see on mobile devices
Talking about Slingy game, Actionscript 3, Box2D, Flash, Game development and Monetize.
More than three years ago I released Slingy game, sponsored by Hairy Games.
The game did not have the success I expected, but today I played it again and I thought it would be nice to have a similar game on a mobile device.
So I am giving you the source code of the game, with a lot of outdated libraries like Mochi Media and Playtomic APIs, but you will find the game engine, powered by Box2D, quite interesting, have a look at the main class:
package triqui{
import flash.display.Sprite;
import flash.events.MouseEvent;
import flash.events.Event;
import flash.events.KeyboardEvent;
import Box2D.Dynamics.*;
import Box2D.Collision.*;
import Box2D.Collision.Shapes.*;
import Box2D.Dynamics.Contacts.*;
import Box2D.Common.Math.*;
public class Game extends Sprite {
private var level:Number;
private var newMouse:NewMouse;
private var ball:Ball;
private var world:b2World=new b2World(new b2Vec2(0,10.0),true);
private var worldScale:Number=30;
private var levels:Levels=new Levels();
private var ballBody:b2Body;
private var totalCoins:Number=0;
private var launchedBalls:Number=0;
private var totalBalls:Number=5;
private var collectedCoins:Number=0;
private var comboCoins:Number;
private var removeTexts:Boolean=false;
private var levelCompleted:Boolean=false;
private var starsToGive:Number=0;
private var levelScore:Number=0;
private var neededToComplete:Array=new Array(50,/*2*/30,/*3*/10,/*4*/30,/*5*/40,/*6*/10,/*7*/25,/*8*/20,/*9*/30,/*10*/30,/*11*/55,/*12*/45,/*13*/10,/*14*/25,/*15*/15,/*16*/35,/*17*/20,/*18*/15,/*19*/10,/*20*/20,/*21*/50,/*22*/5,/*23*/25,/*24*/40,/*25*/20,/*26*/15,/*27*/40,/*28*/25,/*29*/40,/*30*/25,/*31*/40,/*32*/25,/*33*/30,/*34*/25,/*35*/35,/*36*/20,/*37*/35,/*38*/30,/*39*/25,/*40*/10);
private var starScores:Array=new Array(5000,/*2*/5400,/*3*/2100,/*4*/2500,/*5*/3200,/*6*/400,/*7*/1200,/*8*/4400,/*9*/3100,/*10*/2700,/*11*/6500,/*12*/10800,/*13*/900,/*14*/2000,/*15*/4500,/*16*/3700,/*17*/700,/*18*/300,/*19*/1000,/*20*/1900,/*21*/9900,/*22*/200,/*23*/2300,/*24*/8500,/*25*/1100,/*26*/2000,/*27*/3500,/*28*/5300,/*29*/3400,/*30*/2400,/*31*/8400,/*32*/2600,/*33*/3000,/*34*/2700,/*35*/4600,/*36*/1100,/*37*/3800,/*38*/2200,/*39*/2380,/*40*/1400);
public var circle:Circle;
public var crosshair:Crosshair;
public var ballTrail:BallTrail;
public var launchedBall:LaunchedBall;
public function Game(n:Number) {
world.SetContactListener(new CustomContact());
level=n;
addEventListener(Event.ADDED_TO_STAGE,init);
}
private function init(e:Event):void {
addChild(levels);
levels.gotoAndStop(level+1);
for (var i:int=0; i<levels.numChildren; i++) {
with (levels.getChildAt(i)) {
switch (name) {
case "theCoin" :
addCoin(x,y);
levels.removeChildAt(i);
i--;
totalCoins++;
break;
case "theWall" :
addWall(x,y);
levels.removeChildAt(i);
i--;
break;
case "thePushable" :
addPushable(x,y);
levels.removeChildAt(i);
i--;
break;
case "theOneWayU" :
addOneWayU(x,y);
levels.removeChildAt(i);
i--;
break;
case "theCircle" :
addStuff(x,y);
levels.removeChildAt(i);
i--;
break;
case "theBreakable" :
addBreakable(x,y);
levels.removeChildAt(i);
i--;
break;
case "theAbsorbing" :
addAbsorbing(x,y);
levels.removeChildAt(i);
i--;
break;
case "theKiller" :
addKiller(x,y);
levels.removeChildAt(i);
i--;
break;
}
}
}
stage.addEventListener(MouseEvent.MOUSE_DOWN,fire);
stage.addEventListener(KeyboardEvent.KEY_DOWN,destroyBall);
addEventListener(Event.ENTER_FRAME,update);
}
private function addStuff(pX:Number,pY:Number):void {
circle=new Circle(totalBalls-launchedBalls);
addChild(circle);
circle.x=pX;
circle.y=pY;
circle.goalText.text=collectedCoins+"/"+neededToComplete[level];
circle.scoreText.text=levelScore.toString();
circle.star1.alpha=0.3;
circle.star2.alpha=0.3;
circle.star3.alpha=0.3;
if (collectedCoins>=neededToComplete[level]) {
circle.star1.alpha=1;
if (levelScore>=starScores[level]*0.8) {
circle.star2.alpha=1;
if (levelScore>=starScores[level]) {
circle.star3.alpha=1;
}
}
}
newMouse=new NewMouse();
addChild(newMouse);
crosshair=new Crosshair();
addChild(crosshair);
ball=new Ball();
addChild(ball);
}
private function addWall(pX:Number,pY:Number):void {
var wallShape:b2PolygonShape = new b2PolygonShape();
wallShape.SetAsBox(20/worldScale,20/worldScale);
var wallFixture:b2FixtureDef = new b2FixtureDef();
wallFixture.density=0;
wallFixture.friction=10;
wallFixture.restitution=0.6;
wallFixture.shape=wallShape;
var wallBodyDef:b2BodyDef = new b2BodyDef();
wallBodyDef.position.Set(pX/worldScale,pY/worldScale);
wallBodyDef.userData=new Wall();
wallBodyDef.userData.name="wall";
addChild(wallBodyDef.userData);
var wall:b2Body=world.CreateBody(wallBodyDef);
wall.CreateFixture(wallFixture);
}
private function addBreakable(pX:Number,pY:Number):void {
var breakableShape:b2PolygonShape = new b2PolygonShape();
breakableShape.SetAsBox(20/worldScale,20/worldScale);
var breakableFixture:b2FixtureDef = new b2FixtureDef();
breakableFixture.density=0;
breakableFixture.friction=10;
breakableFixture.restitution=0.6;
breakableFixture.shape=breakableShape;
var breakableBodyDef:b2BodyDef = new b2BodyDef();
breakableBodyDef.position.Set(pX/worldScale,pY/worldScale);
breakableBodyDef.userData=new Breakable();
breakableBodyDef.userData.name="breakable";
addChild(breakableBodyDef.userData);
var breakable:b2Body=world.CreateBody(breakableBodyDef);
breakable.CreateFixture(breakableFixture);
}
private function addKiller(pX:Number,pY:Number):void {
var killerShape:b2PolygonShape = new b2PolygonShape();
killerShape.SetAsBox(20/worldScale,20/worldScale);
var killerFixture:b2FixtureDef = new b2FixtureDef();
killerFixture.density=0;
killerFixture.friction=10;
killerFixture.restitution=0.6;
killerFixture.shape=killerShape;
var killerBodyDef:b2BodyDef = new b2BodyDef();
killerBodyDef.position.Set(pX/worldScale,pY/worldScale);
killerBodyDef.userData=new Killer();
killerBodyDef.userData.name="killer";
addChild(killerBodyDef.userData);
var killer:b2Body=world.CreateBody(killerBodyDef);
killer.CreateFixture(killerFixture);
}
private function addAbsorbing(pX:Number,pY:Number):void {
var absorbingShape:b2PolygonShape = new b2PolygonShape();
absorbingShape.SetAsBox(20/worldScale,20/worldScale);
var absorbingFixture:b2FixtureDef = new b2FixtureDef();
absorbingFixture.density=10;
absorbingFixture.friction=1;
absorbingFixture.restitution=0.1;
absorbingFixture.shape=absorbingShape;
var absorbingBodyDef:b2BodyDef = new b2BodyDef();
absorbingBodyDef.position.Set(pX/worldScale,pY/worldScale);
absorbingBodyDef.userData=new Absorbing();
absorbingBodyDef.userData.name="absorbing";
addChild(absorbingBodyDef.userData);
var absorbing:b2Body=world.CreateBody(absorbingBodyDef);
absorbing.CreateFixture(absorbingFixture);
}
private function addOneWayU(pX:Number,pY:Number):void {
var oneWayUShape:b2PolygonShape = new b2PolygonShape();
oneWayUShape.SetAsBox(20/worldScale,20/worldScale);
var oneWayUFixture:b2FixtureDef = new b2FixtureDef();
oneWayUFixture.density=0;
oneWayUFixture.friction=10;
oneWayUFixture.restitution=0.6;
oneWayUFixture.shape=oneWayUShape;
var oneWayUBodyDef:b2BodyDef = new b2BodyDef();
oneWayUBodyDef.position.Set(pX/worldScale,pY/worldScale);
oneWayUBodyDef.userData=new OneWayU();
oneWayUBodyDef.userData.name="oneWayU";
addChild(oneWayUBodyDef.userData);
var oneWayU:b2Body=world.CreateBody(oneWayUBodyDef);
oneWayU.CreateFixture(oneWayUFixture);
}
private function addPushable(pX:Number,pY:Number):void {
var pushableShape:b2PolygonShape = new b2PolygonShape();
pushableShape.SetAsBox(20/worldScale,20/worldScale);
var pushableFixture:b2FixtureDef = new b2FixtureDef();
pushableFixture.density=2;
pushableFixture.friction=10;
pushableFixture.restitution=0.5;
pushableFixture.shape=pushableShape;
var pushableBodyDef:b2BodyDef = new b2BodyDef();
pushableBodyDef.type=b2Body.b2_dynamicBody;
pushableBodyDef.position.Set(pX/worldScale,pY/worldScale);
pushableBodyDef.userData=new Pushable();
pushableBodyDef.userData.name="pushable";
addChild(pushableBodyDef.userData);
var pushable:b2Body=world.CreateBody(pushableBodyDef);
pushable.CreateFixture(pushableFixture);
}
private function addCoin(pX:Number,pY:Number):void {
var coinBodyDef:b2BodyDef= new b2BodyDef();
coinBodyDef.userData=new Coin();
coinBodyDef.userData.name="coin";
addChild(coinBodyDef.userData);
coinBodyDef.position.Set(pX/worldScale, pY/worldScale);
var coinShape:b2CircleShape=new b2CircleShape(10/worldScale);
var coinFixture:b2FixtureDef = new b2FixtureDef();
coinFixture.isSensor=true;
coinFixture.shape=coinShape;
var coinBody:b2Body=world.CreateBody(coinBodyDef);
coinBody.CreateFixture(coinFixture);
}
private function fire(e:MouseEvent):void {
removeTexts=true;
if (ball!=null) {
if (ball.x>20&&ball.y>20&&ball.x<620&&ball.y<460) {
launchBall(ball.x,ball.y,8,ball.xSpeed,ball.ySpeed);
}
}
}
private function destroyBall(e:KeyboardEvent):void {
if (ball==null && e.keyCode==32 && launchedBalls<=totalBalls) {
launchedBall.removeTimer();
destroyLaunchedBall();
}
if (ball==null && e.keyCode==81 && launchedBalls<=totalBalls) {
launchedBall.removeTimer();
launchedBalls=totalBalls;
destroyLaunchedBall();
}
}
private function launchBall(pX:Number,pY:Number,r:Number,sX:Number,sY:Number):void {
comboCoins=0;
launchedBalls++;
removeChild(ball);
ball=null;
var ballBodyDef:b2BodyDef= new b2BodyDef();
launchedBall =new LaunchedBall();
ballBodyDef.userData=launchedBall;
ballBodyDef.userData.name="ball";
var force:b2Vec2=new b2Vec2(sX,sY);
ballBodyDef.position.Set(pX/worldScale, pY/worldScale);
ballBodyDef.type=b2Body.b2_dynamicBody;
var ballShape:b2CircleShape=new b2CircleShape(r/worldScale);
var ballFixture:b2FixtureDef = new b2FixtureDef();
ballFixture.restitution=0.5;
ballFixture.friction=0;
ballFixture.density=4;
ballFixture.shape=ballShape;
ballBody=world.CreateBody(ballBodyDef);
ballBody.SetBullet(true);
ballBody.SetLinearVelocity(force);
ballBody.CreateFixture(ballFixture);
ballTrail=new BallTrail();
addChild(ballTrail);
addChild(ballBodyDef.userData);
}
public function destroyLaunchedBall():void {
world.DestroyBody(ballBody);
removeChild(launchedBall);
ballTrail.destroy();
var explosion:Explosion = new Explosion();
addChild(explosion);
explosion.x=launchedBall.x;
explosion.y=launchedBall.y;
if (launchedBalls<totalBalls) {
var saveX:Number=circle.x;
var saveY:Number=circle.y;
removeChild(circle);
removeChild(newMouse);
removeChild(crosshair);
addStuff(saveX,saveY);
}
else {
stage.removeEventListener(MouseEvent.MOUSE_DOWN,fire);
stage.removeEventListener(KeyboardEvent.KEY_DOWN,destroyBall);
levelCompleted=true;
}
}
private function update(e:Event):void {
if (removeTexts && levels.alpha>0) {
levels.alpha-=0.05;
}
world.Step(1/30,10,10);
for (var bb:b2Body = world.GetBodyList(); bb; bb = bb.GetNext()) {
if (bb.GetUserData() is Sprite) {
bb.GetUserData().x=bb.GetPosition().x*worldScale;
bb.GetUserData().y=bb.GetPosition().y*worldScale;
bb.GetUserData().rotation=bb.GetAngle()*(180/Math.PI);
if (bb.GetUserData().name=="removeBall") {
launchedBall.removeTimer();
world.DestroyBody(bb);
destroyLaunchedBall();
}
if (bb.GetUserData().name=="removeCoin") {
comboCoins++;
levelScore+=(comboCoins*10);
collectedCoins++;
if (collectedCoins>=neededToComplete[level]) {
circle.star1.alpha=1;
if (levelScore>=starScores[level]*0.8) {
circle.star2.alpha=1;
if (levelScore>=starScores[level]) {
circle.star3.alpha=1; }
}
}
circle.goalText.text=collectedCoins+"/"+neededToComplete[level];
circle.scoreText.text=levelScore.toString();
var explodingCoin:ExplodingCoin=new ExplodingCoin();
addChild(explodingCoin);
explodingCoin.x=bb.GetUserData().x;
explodingCoin.y=bb.GetUserData().y;
var points:Points=new Points();
addChild(points);
points.x=bb.GetUserData().x;
points.y=bb.GetUserData().y;
points.PointsText.text=(comboCoins*10).toString();
removeChild(bb.GetUserData());
world.DestroyBody(bb);
if (collectedCoins==totalCoins && launchedBalls!=totalBalls) {
stage.removeEventListener(MouseEvent.MOUSE_DOWN,fire);
stage.removeEventListener(KeyboardEvent.KEY_DOWN,destroyBall);
launchedBall.removeTimer();
levelCompleted=true;
}
}
if (bb.GetUserData().name=="broken") {
removeChild(bb.GetUserData());
world.DestroyBody(bb);
var explodingWall:ExplodingWall=new ExplodingWall();
addChild(explodingWall);
explodingWall.x=bb.GetUserData().x;
explodingWall.y=bb.GetUserData().y;
}
}
}
world.ClearForces();
if (levelCompleted) {
alpha-=0.04;
if (alpha<=0) {
removeEventListener(Event.ENTER_FRAME,update);
var theParent:Main=this.parent as Main;
if (collectedCoins>=neededToComplete[level]) {
starsToGive=1;
if (levelScore>=starScores[level]*0.8) {
starsToGive=2;
if (levelScore>=starScores[level]) {
starsToGive=3;
}
}
}
theParent.endLevel(level,collectedCoins>=neededToComplete[level],starsToGive,levelScore);
}
}
}
}
}
Moreover, I will make a Box2D Phaser prototype soon, to see if it can be nicely played on mobile like I think.
So, download the source code and enjoy.
Never miss an update! Subscribe, and I will bother you by email only when a new game or full source code comes out.
