Copy link to clipboard
Copied
Hi. We have created a game using box2d and AS3 but it's running real slow and at 80% CPU when other physics games run at 10%. It's not the graphics as I have other games with same graphics. An angry bird drops an egg etc...
There is a lot of code but I just thought that someboy knows exactly where to look on these things. If not, then please don't wade through code and waste your valuable time.
Cheers
package game
{
import Box2D.Collision.b2AABB;
import Box2D.Common.Math.b2Vec2;
import Box2D.Common.b2Color;
import Box2D.Dynamics.b2Body;
import Box2D.Dynamics.b2DebugDraw;
import Box2D.Dynamics.b2World;
import box2d.Box2DProps;
import box2d.Box2dElement;
import box2d.Box2dUtils;
import clk.ui.efectos.WindowBlur;
import common.ObjectUtil;
import dynamics.TweenFunctions;
import flash.display.Loader;
import flash.display.LoaderInfo;
import flash.display.MovieClip;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.geom.Point;
import flash.media.Sound;
import flash.media.SoundChannel;
import flash.media.SoundTransform;
import flash.net.URLRequest;
import flash.system.ApplicationDomain;
import flash.system.LoaderContext;
import flash.text.TextField;
import flash.utils.Timer;
import flash.utils.getDefinitionByName;
import flash.utils.getTimer;
import game.popups.ScorePopUp;
import game.popups.SplashScreen;
import proyectos.trivia.TriviaEvent;
public class angrybirdgame extends MovieClip
{
//flas vars
public var mainChar:MainChar;
public var plat1:MovieClip;
public var plat2:MovieClip;
public var pointsTxt:MovieClip;
public var soundRepeat:MovieClip;
public var splashScreen:SplashScreen;
public var timeTxt:MovieClip;
public var gameLayer:MovieClip;
public var loaderLayer:MovieClip;
//correct and incorrect counters
private var _correctCounter:int=0;
private var _incorrectCounter:int=0;
private var _loader:LoaderScreen;
private var _endGame:Boolean = false;
private var _gamePause:Boolean = false;
private var _points:int = 0;
//array of game elements
private var _definitionsArray:Array;
private var _backSoundLevel:Number = 0.3;
private var _ambientSound:SoundChannel;
public var _bckSound:SoundChannel;
private var elementsToGet:Array = [];
//the egg!
private var _egg:Egg = null;
private var _currentIndex:int=0;
private var _incorrectSoundName:String="IncorrectSound";
private var _correctSoundName:String="CorrectSound";
private var _correctsoundChannel:SoundChannel;
private var _incorrectsoundChannel:SoundChannel;
private var _blockSound:Boolean = false;
private var eggCrashed:Egg;
private var _platformSoundChanel:SoundChannel;
private var _initTime:int;
private var _endTime:int;
//box2d elements
//the box 2d world
private var _world:b2World;
private var _velocityIterations:int = 10;
private var _positionIterations:int = 10;
private var _timeStep:Number = 1.0 / 30.0;
public var _gravity:Number = 9.8;
public var _pixelMeterConversion:Number = 70;
private var _deleteObjectArray:Array /* array of elements box2d */ = [];
private var _box2dElementArray:Array = [];
private var _timingMode:Boolean = false;
public function angrybirdgame()
{
super();
_loader = new LoaderScreen();
loaderLayer.addChild(_loader);
soundRepeat.buttonMode = true;
if(stage)
{
init();
}
else
{
addEventListener(Event.ADDED_TO_STAGE,init);
}
}
private function init(evt:Event=null):void
{
_correctCounter =0;
_incorrectCounter=0;
//remove the stage listener
removeEventListener(Event.ADDED_TO_STAGE,init);
_endGame = false;
_points = 0;
//set the conversion
Box2dUtils.METTERS_CONVERSOR = _pixelMeterConversion;
// Define the gravity vector
var gravity:b2Vec2 = new b2Vec2(0.0, _gravity);
// Allow bodies to sleep
var doSleep:Boolean = true;
// Construct a world object
_world = new b2World(gravity, doSleep);
/*_definitionsArray = new Array();
_definitionsArray.push({ mc:"Apple", sound:"AppleSound" });
_definitionsArray.push({ mc:"Banana", sound:"BananaSound" });
_definitionsArray.push({ mc:"Bread", sound:"BreadSound" });
_definitionsArray.push({ mc:"Cake", sound:"CakeSound" });
_definitionsArray.push({ mc:"Water", sound:"WaterSound" });
_definitionsArray.push({ mc:"Tomato", sound:"TomatoSound" });
_definitionsArray.push({ mc:"Sandwich", sound:"SandwichSound" });
_definitionsArray.push({ mc:"Pizza", sound:"PizzaSound" });
_definitionsArray.push({ mc:"Pear", sound:"PearSound" });
_definitionsArray.push({ mc:"Orange", sound:"OrangeSound" });
getData("../library/food.swf", _definitionsArray);*/
}
public function onTimer(event:Event):void
{
event.stopImmediatePropagation();
event.stopPropagation();
splashScreen.btnTimer.removeEventListener(MouseEvent.CLICK,onTimer);
splashScreen.btnNoTimer.removeEventListener(MouseEvent.CLICK,onNoTimer);
setTimingMode(true);
}
public function onNoTimer(event:Event):void
{
event.stopImmediatePropagation();
event.stopPropagation();
splashScreen.btnTimer.removeEventListener(MouseEvent.CLICK,onTimer);
splashScreen.btnNoTimer.removeEventListener(MouseEvent.CLICK,onNoTimer);
setTimingMode(false);
}
public function setTimingMode(value:Boolean):void
{
_initTime = getTimer();
timeTxt.visible = value;
_timingMode = value;
start();
}
/**
* read data from library
*/
public function getData(libreria:String,matriz:Array):void
{
_definitionsArray = matriz;
//ShuffleArray.shuffleKnuth(definitionsArray);//Shuffle/mezclar array
//mix the content of the array
_definitionsArray = ObjectUtil.mixArray(_definitionsArray);
var loader:Loader = new Loader() ;
var context:LoaderContext = new LoaderContext(false,ApplicationDomain.currentDomain);
loader.contentLoaderInfo.addEventListener(Event.COMPLETE,onAssetsLoaded);
try
{
trace("loading assets");
loader.load(new URLRequest("../" +libreria),context);
}
catch (e:Error)
{
trace(("Asset load error: " + e));
}
}
public function get definitionsArray():Array
{
return _definitionsArray;
}
/**
* on assets loaded we crate and save them in an array
*/
private function onAssetsLoaded(e:Event):void
{
LoaderInfo(e.target).removeEventListener(Event.COMPLETE, onAssetsLoaded);
var rslClasses:Array;
rslClasses = definitionsArray;
elementsToGet = [];
for each (var className:Object in rslClasses)
{
elementsToGet.push(new Wrapper(className["mc"],className["sound"]));
}
placeElements();
}
private function placeElements():void
{
var i:uint = 1;
for each (var bubble:Wrapper in elementsToGet)
{
bubble.x = this["poser" + i].x;//poser are the boxes. The images are imported into those positions
bubble.y = this["poser" + i].y;
this["poser" + i].visible = false;
bubble.cacheAsBitmap = true;
i++;
gameLayer.addChild(bubble);
}
elementsToGet = ObjectUtil.mixArray(elementsToGet);
//trace("a")
showTimerOption();
}
private function showTimerOption():void
{
_loader.parent.removeChild(_loader);
splashScreen.play();
//start listening the time or not timing mode
splashScreen.btnTimer.addEventListener(MouseEvent.CLICK,onTimer);
splashScreen.btnNoTimer.addEventListener(MouseEvent.CLICK,onNoTimer);
}
/**
* start the game
*/
private function start():void
{
try
{
var classS:Class = getDefinitionByName("AmbientSound") as Class;
var sound:Sound = new classS() as Sound;
_ambientSound = sound.play(0,int.MAX_VALUE);
}
catch (e:Error)
{
trace(e.toString());
}
try
{
var clasS:Class = getDefinitionByName("BackMusic") as Class;
var s:Sound = new clasS() as Sound;
var trans:SoundTransform = new SoundTransform(_backSoundLevel);
_bckSound = s.play(0,int.MAX_VALUE,trans);
}
catch (e:Error)
{
trace(e.toString());
}
configurePlatforms();
setPoints();
//SEBAS UNCOMMMENT THIS IF WE WANT TO SEE THE BOX2d Bodies
initDraw();
playNextSound();
togglePauseGameState(false);
}
private function initDraw():void
{
var dbgDraw:b2DebugDraw = new b2DebugDraw();
dbgDraw.SetSprite(this);
dbgDraw.SetDrawScale(Box2dUtils.METTERS_CONVERSOR);
dbgDraw.SetFillAlpha(1);
dbgDraw.SetLineThickness(1.0);
dbgDraw.SetFlags(b2DebugDraw.e_shapeBit | b2DebugDraw.e_jointBit);
//dbgDraw.SetFlags(b2DebugDraw.e_jointBit);
_world.SetDebugDraw(dbgDraw);
}
private function configurePlatforms():void
{
var props:Box2DProps = new Box2DProps();
props.density = 1;
props.friction = 1;
props.isBullet = false;
props.isDynamic = false;
props.isSensor = false;
props.restitution = 0.5;
plat2.platform.world = _world;
plat2.platform.copyLocationToBodyMode=true;
plat2.platform.createBoxByProps(_world,props,(plat2.platform.width/2),(plat2.platform.height/2));
plat1.platform.world = _world;
plat1.platform.copyLocationToBodyMode=true;
plat1.platform.createBoxByProps(_world,props,(plat2.platform.width/2),(plat2.platform.height/2));
}
/**
* pause game
*
* @Param value is true if we want to pause it false otherwise
*/
public function togglePauseGameState(value:Boolean):void
{
removeEventListener(Event.ENTER_FRAME, enterFrameHandler);
mainChar.removeEventListener(MainChar.CREATE_EGG,createEgg);
soundRepeat.removeEventListener(MouseEvent.CLICK,repeatSound);
_gamePause = value;
if (value == false)
{
//start listening enter frame
addEventListener(Event.ENTER_FRAME, enterFrameHandler);
mainChar.addEventListener(MainChar.CREATE_EGG,createEgg);
soundRepeat.addEventListener(MouseEvent.CLICK,repeatSound);
}
mainChar.togglePause(value);
}
/**
* creaates an egg
*/
private function createEgg(event:Event):void
{
if(_egg!=null)
{
return;
}
try
{
var sound:SoundShoot = new SoundShoot();
sound.play();
}
catch(e:Error)
{
trace(e);
}
_egg = new Egg();
_egg.x = mainChar.x;
_egg.y = mainChar.y;
_egg.createBody(_world);
gameLayer.addChild(_egg);
_box2dElementArray.push(_egg);
}
private function checkEggOutScreen():void
{
for (var i:int = 0;i<_box2dElementArray.length;i++)
{
if(_box2dElementArray.y>(stage.stageHeight)+(stage.stageHeight/stage.scaleY))
{
if(_box2dElementArray == _egg)
{
_egg = null;
}
addToDelete(_box2dElementArray);
break;
}
}
}
/**
* enter frame handler
*/
private function enterFrameHandler(event:Event):void
{
drawTime();
destroyQueuedBodies();
updateWorld();
copyBx2DMovements();
checkEggOutScreen();
checkEggCollision();
checkPlatformCollision();
}
private function drawTime():void
{
if(_timingMode)
{
timeTxt.timeTxt.text = getTimeString(getTimer()-_initTime);
}
}
private function getTimeString(actualTime:int):String
{
var min:int = (actualTime%3600000)/60000;
var restMin:int = (actualTime%3600000)%60000;
var sec:int = restMin/1000;
return min+":"+(sec<10?("0"+sec):sec);
}
private function checkPlatformCollision():void
{
if (_egg==null)
{
eggCrashed = null;
return;
}
if(((plat1.hitTestObject(_egg))||(plat2.hitTestObject(_egg)))&&_egg!=eggCrashed)
{
eggCrashed = _egg;
try
{
var sound:SoundBarrier = new SoundBarrier();
_platformSoundChanel= sound.play();
_platformSoundChanel.addEventListener(Event.SOUND_COMPLETE,platformSoundComplete);
}
catch (e:Error)
{
trace(e.toString());
}
}
}
private function platformSoundComplete(event:Event):void
{
_platformSoundChanel.removeEventListener(Event.SOUND_COMPLETE,platformSoundComplete);
eggCrashed = null;
}
private function checkEggCollision():void
{
if(_egg)
{
for (var i:int = 0; i<elementsToGet.length;i++)
{
if(_egg.hitTestObject(elementsToGet)&&elementsToGet.visible == true)
{
_egg.visible = false;
if(i==_currentIndex)
{
if (!_blockSound)
{
_blockSound = true;
var CL:Class = ApplicationDomain.currentDomain.getDefinition(_correctSoundName) as Class;
var sound:Sound = new CL () as Sound;
_correctsoundChannel = sound.play();
_correctsoundChannel.addEventListener(Event.SOUND_COMPLETE, soundCorrectComplete);
_correctCounter++;
deleteElement();
}
}
else
{
if (!_blockSound)
{
_blockSound = true;
var CL2:Class = ApplicationDomain.currentDomain.getDefinition(_incorrectSoundName) as Class;
var sound2:Sound = new CL2 () as Sound;
_incorrectsoundChannel = sound2.play();
_incorrectsoundChannel.addEventListener(Event.SOUND_COMPLETE, soundInCorrectComplete);
_incorrectCounter++;
var friedEgg:AnimationIncorrect = new AnimationIncorrect();
friedEgg.x = (elementsToGet as Wrapper).x;
friedEgg.y = (elementsToGet as Wrapper).y;
gameLayer.addChild(friedEgg);
}
}
break;
}
}
}
}
private function soundCorrectComplete(evt:Event):void
{
_correctsoundChannel.removeEventListener(Event.SOUND_COMPLETE, soundCorrectComplete);
_blockSound = false;
if (_currentIndex<elementsToGet.length)
{
playNextSound();
}
}
private function soundInCorrectComplete(evt:Event):void
{
_incorrectsoundChannel.removeEventListener(Event.SOUND_COMPLETE, soundInCorrectComplete);
_blockSound = false;
}
private function deleteElement():void
{
//(elementsToGet[_currentIndex] as Wrapper).parent.removeChild(elementsToGet[_currentIndex]);
(elementsToGet[_currentIndex] as Wrapper).visible = false;
//elementsToGet.splice(_currentIndex,1);
var friedEgg:AnimationCorrect = new AnimationCorrect();
friedEgg.x = (elementsToGet[_currentIndex] as Wrapper).x;
friedEgg.y = (elementsToGet[_currentIndex] as Wrapper).y;
gameLayer.addChild(friedEgg);
var pointBurst:PointBurst = new PointBurst();
pointBurst.x = friedEgg.x;
pointBurst.y = friedEgg.y;
gameLayer.addChild(pointBurst);
setPoints();
_currentIndex++;
if (_currentIndex<elementsToGet.length)
{
//playNextSound();
}
else
{
endGame();
}
}
public function setPoints():void
{
(pointsTxt.pointsTxt as TextField).text = (_correctCounter * 10).toString();
trace("points: "+_correctCounter);
}
private function repeatSound(event:MouseEvent):void
{
event.stopPropagation();
event.stopImmediatePropagation();
playNextSound();
}
private function playNextSound():void
{
(elementsToGet[_currentIndex] as Wrapper).playSound();
}
/**
* add to an array to delete the next update
*/
public function addToDelete(obj:Object):void
{
//check is not already there
for (var i:int = 0 ;i<_deleteObjectArray.length;i++)
{
if (_deleteObjectArray==obj)
{
return;
}
}
_deleteObjectArray.push(obj);
}
/**
* method called after a world step to destroy bodies
*/
public function destroyQueuedBodies():void
{
for (var i:int = 0;i<_deleteObjectArray.length; i++)
{
killBox2dMc(_deleteObjectArray as Box2dElement);
}
//clean the array
_deleteObjectArray = [];
}
/**
* deletes a balloon
*/
public function killBox2dMc(elment:Box2dElement):void
{
//get the index of this balloon
var index:int = 0;
for (;index<_box2dElementArray.length;index++)
{
if (_box2dElementArray[index] == elment)
{
break;
}
}
//now we make an splice of the array
_box2dElementArray.splice(index,1);
//now kill it
elment.killIt();
//remove it from the game
elment.parent.removeChild(elment);
}
/**
* end game
*
*/
private function endGame():void
{
_endGame = true;
_endTime = getTimer()-_initTime;
togglePauseGameState(true);
showScorePopUp();
}
/**
* Update world
*/
private function updateWorld():void
{
_world.Step(_timeStep, _velocityIterations, _positionIterations);
_world.DrawDebugData();
}
/**
* copy the box movement to the real world
*/
private function copyBx2DMovements():void
{
// Go through body list and update sprite positions/rotations
for (var bb:b2Body = _world.GetBodyList(); bb; bb = bb.GetNext()){
if (bb.GetUserData() is Box2dElement ){
var sprite:Box2dElement = bb.GetUserData() as Box2dElement;
if(!sprite.copyLocationToBodyMode&&!sprite.stopCopingLocation)
{
sprite.x = Box2dUtils.metersToPixels(bb.GetPosition().x);
sprite.y = Box2dUtils.metersToPixels(bb.GetPosition().y);
//trace("body position"+sprite.x+" "+sprite.y);
if (sprite.copyRotation)
{
sprite.rotation = Box2dUtils.radsToDeg( bb.GetAngle());
}
else
{
sprite.rotation = 0;
}
}
}
}
}
/**
* show the score pop up
*/
private function showScorePopUp():void
{
//show the score pop up
var scorePopUp:ScorePopUp = new ScorePopUp();
scorePopUp.points = _correctCounter*10;
scorePopUp.time = getTimeString(_endTime);
scorePopUp.onEndClicked = onEndClickedButton;
addChild(scorePopUp);
}
/**
* on end clicked button
*/
private function onEndClickedButton(ev:Event=null):void
{
var evt:TriviaEvent = new TriviaEvent(TriviaEvent.ON_GAME_COMPLETE);
evt.correctas = _correctCounter;
evt.erroneas = _incorrectCounter;
evt.tiempo = _endTime;
//evt.puntos = _points;
dispatchEvent(evt);
//loaderF("../screens/kids/middleScreen1.swf",false,false);
}
}
}
Copy link to clipboard
Copied
i didn't get too far into your code and already see a problem. i read your class declaration and skipped to you constructor where i see you are calling super() which is superfluous and loaderLayer appears null when you apply addChild() to it.
Copy link to clipboard
Copied
Hi. I took out "super()" and yes it doesn't need to be there but the CPU usage stays the same. Don't understand the comment re: loaderLayer. Do I need to do something with it?
Copy link to clipboard
Copied
you're not adding _loader to the display so what purpose does it serve?
Copy link to clipboard
Copied
There seems to be a lot going on so my question is can I open this game and use the profiler in flash builder or flash develop? Would that show me where bottlenecks are? btw - just read anout Monocle - a profiler for flash pro - will check to see if it's out yet.