im making a flash shooter game and ive encountered one problem. When there are a lot of monsters on the stage which are visible by player, the game starts to lag. In my opinion, its due to Event.ENTER_FRAME (each enemy instance has it) where z-sorting, enemy movement, updating other stuff like health is done. Since things like theese, cant be done each second or at similar time interval,im using ENTER_FRAME. My question is, how can i have many instances of the enemy in my game and still dont have it lagging. Ive done optimising in all over the code and if im not mistaken,big ammount of enemies is the performance bottleneck here.
Question me if i wasnt clear; to see the game go to http://ernyz.lhosting.info/bandymas.html or if you want to see the code,i will be able to put it here,just ask :)
Having an enter frame events for each instance is most likely the problem. A single event where you loop over all instances and do actions is usually faster.
There shouldn't be much for you to change: Instead of adding the listener to each enemy, add only one listener to the stage and call the enemies' update functions.
class Enemy {
function update(e:Event) { /* ... */ }
}
class Main {
function onEnterFrame(e:Event) {
for each (var enemy:Enemy in enemies) {
enemy.update(e);
}
}
}
From my experience, unless you're doing something very wrong, flash rendering pipeline is what takes the most time of your application. And since you get more enemies, you get more MovieClips and more complex rendering.
But having one ENTER_FRAME event for each object is indeed a big overhead that can be easily avoided.
A good practice before optimizing your code is to actually run it through a profiler. I don't believe the actual Flash program has it, but Flash Builder surely does. If you post us a screenshot or a log of the game being profiled, we can be of more assistance.
By quickly playing your game, I've seen that all your enemies are a bunch of graphics with a bunch of gradients, therefore costly to render. Have you tried setting the quality to low? Does the lag go away?
Related
Hey everyone so I have a lot of timers in my game to be specific around 8 timers. They all control different Movie clip objects that appear on the stage at different times. I also change the timers in my difficulty update function. Now I have read a lot to understand that Timers do cause lag and decrease the performance. I am creating this game using AS3 Adobe AIR for Android devices. My game seems to freeze for half a second every second which I believe is do to the timers as well as the garbage collector. Either way I was wondering if I remove all these timers and instead replace them with TweenLite TweenLite.delayedCallfuncion if it would dramatically increase performance. I Have tried this on one of my old timers that i removed and replaced with the tweenlite function and it seems to be working just fine but not sure if this is the correct way of doing it here is how i have it set up in my constructor:
TweenLite.delayedCall(6.0, addWatch);
and the addWatch function:
private function addWatch():void
{
TweenLite.delayedCall(6.0, addWatchTimer);
var newWatch:mcWatchTimer = new mcWatchTimer();
stage.addChild(newWatch);
aWatchTimerArray.push(newWatch);
//Start screen sound
watchSoundChannel;
watchSound = new watch();
watchSoundChannel = watchSound.play(0, 9999);
}
this seems to loop it without me having to attach an ENTER_FRAME Eveent listener to it. But not sure if this would be wise since I want to be able to change the delayedCall in my difficulty update to a faster time interval.
Any feedback on the situation would be appreciated. Hope I made enough sense.
This question may get downvoted or go unanswered because it's not the greatest and incredible silly but anyway,
I'm taking an intro level Webanimation course this semester at UNI and had I know what their expectations are for our hand-in projects i would have never taken it up.
Basically the teacher taught us stuff to the extent of masking/tweening and very few mouse-event and basic function codes.
Now she is expecting us to make a god damn ENTIRE PIPE GAME. The one where there are a bunch of rotating pipes and you gotta rotate them in place before a timer runs out and then the water flows through them.
For this project I have to somehow figure out the following (even though she didn't teach any of this):
-creature a grid of rotate-able pipes (one mouse click I assume would do a 90 degree classic tween rotation of the object)
-creature some sort of logic hit-box value chain to make pipes decide when to fill with water (they fill with water (a.k.a turn blue inside as an animation) once they are connected to another water filled pipe, for example)
-creature multiple levels and a menu screen
-add a music track.
Now i know this site is for specific help only and you basically can't ask for help on an entire project, so for now if somebody could just help me out with the following:
How do I create a rotating pipe on mouseclick?
So I have my pipe movieclip created and I have my Mouse Event code ready but I don't have the faintest on how to make a tween within the pipe and connect it to the code so that it rotates on mouseclick.
So this far, let's say for one of the pipes, instance pipe_1, I want to do this:
pipe_1.addEventListener(MouseEvent.CLICK, fl_MouseClickHandler);
function fl_MouseClickHandler(event:MouseEvent):void
{
trace("Mouse clicked");
}
I also have the simple tween of rotation already created within the instance of the pipe, but dunno how to connect it to code.
I'm supposed to figure out what to put inside the function but I honestly have no clue. Hours of googling have come up with nothing either except a 12 dollar purchasable source code for an even more complicated pipe game.
I hope somebody can at least help a bit, and thanks.
The way to rotate a clip is via it's rotation property. It defaults to 0.
If you were set the rotation property of your tile to 90, you'd rotate your pipe tile 90 degrees.
for example :
pipe_1.rotation += 90;
A tween is a means of changing a property of a given DisplayObject over time. So what you want to do is tween your rotation property 90 degrees over time.
Here is a tutorial on Tweening - http://www.republicofcode.com/tutorials/flash/as3tweenclass/
I think it'd be more beneficial for you to take the time to learn about it, than to have me just write a few lines of code to solve your problem.
StackOverflow is a place where you can ask a question, AFTER you have tried something and have hit an issue.
I have provided you with the basic concept of what you need to do, and if you take the time to learn about tweening, you'll be able to achieve your goal rather simply.
There are also tweening libraries such as TweenLite and TweenMax that simplify tweening. Not sure if your class will allow you to use them, but worthwhile to check out for your own benefit.
You can find TweenLite here :
http://www.greensock.com/tweenlite/
Are you talking about a frame by frame tween? or tweening with code?
for frame by frame tweening, you can try to do this:
pipe_1.addEventListener(MouseEvent.CLICK, f1_MouseClickHandler);
function f1_MouseClickHandler(e:MouseEvent) {
pipe_1.gotoAndPlay(2); //if the tween starts at frame 2
}
For code tweening, just call the tween function inside that handler function
Hi Im relatively new to flash developing and i have a quick question about saving user input. I have a maze scene whereby the user navagates a character around until confronted with another object, when the character hits the object a new scene is opened promting the user to pick a solution to a problem. Once the user clicks the correct answer a box appears saying return to the maze, however when clicked and returned to the maze the character starts back in its original postion, where as I would like the scene to resume where it left off, ie the character is at the point where it collided with the object, the object has dissappeared and the character can resume on the same course.
Thanks for giving this a read I hope it makes sense and some one has a solution for me.
I did have some nice images to explain it better but apprently i need 10 reputation points to upload those.
EDIT: First Id like to say thanks for the rep points you bunch of stars and secondly I know using scenes in flash is seriously cr*p practice and outdated but its the way I learnt all those years ago and seen as Flash itself will be outdated soon Im not really looking to learn another approach using sprites or frames, I just kind of want a fix for this way if poss thank you for answering!
EDIT: Wanting the red rectangle to be removed from the scene once the black square collides with it. It also takes you to the next frame upon doing so. here is my code.
addEventListener(Event.ENTER_FRAME, fl_EnterFrameHandler);
function fl_EnterFrameHandler (event:Event):void
{
if (player.hitTestObject(Risk))
{
removeEventListener(Event.ENTER_FRAME, fl_EnterFrameHandler);
removeChild(Risk);
nextFrame();
}
}
I'd suggest you forget about Scenes! They are old, buggy, bring loads of issues with code and are generally a Bad Pratice!! So if you are just learning AS3, dont learn with Scenes!!
Use MovieClips or Sprites instead. And just add and remove them as you need!
EDIT:
To ur edit ;)
and seen as Flash itself will be outdated soon
thats just plain false and a widespread misinformation. It just has a new purpose like MultiPlattform Game Development. But thats a whole different discussion.
You could solve this by saving the x,y coordinates and then restoring them. But i promise you, you will run in to alot more problems/bugs as you go allong!
Like saved Points and Time. Will you triger the Questionscene again when u place the player on the object(last Position). Save the answers, and so on ...
Changing to DisplayObjects will save you time in the end. Just saying ;)
EDIT2:
your code in the comment should look like this:
function fl_EnterFrameHandler (event:Event):void
{
if (player.hitTestObject(Risk))
{
removeEventListener(Event.ENTER_FRAME, fl_EnterFrameHandler);//remove to prevent errors if it fires again and there is no Object to hitTest
removeChild(Risk);// do what needs to be done on this frame
nextFrame();// and then move to the next
}
}
And following correct convetions and make everybody's life easier reading this, it would look like this!
function fl_EnterFrameHandler (event:Event):void
{
if (player.hitTestObject(risk))
{
removeEventListener(Event.ENTER_FRAME, fl_EnterFrameHandler);//remove to prevent errors if it fires again and there is no Onject to hitTest
removeChild (risk);
nextFrame ();
}
}
i'm probaly confusing u now, just use the top one ;)
EDIT3:
Ok, i just had a butchers at it. It's all on a single Frame now. I would have prefered Classes but that'lljust confuse you.
To add new qestions you just have to dublicate the Question MovieClip in the Library and change texts, leave instance names the same tho, then the code will work as is!
DOWLOAD
It is certainly possible. You would store the characters attributes (e.g. current position) within a variable. Then on returning to your game you would use this variable to set the starting position of your character.
I agree that scenes are not the ideal route you should be taking. Possibly reading a good AS3 book would save you hours/days/weeks in the long run.
I'm having trouble with sound in Flash. I may have went about coding the wrong way, because most of my codes are on frames.
So, I have these two variables
var outsideDay:Sound = new daysong();
var outsideNight:Sound = new nightsong();
And I want to play these songs on a specific frame. However, the sounds play sporadically, like 50 times at once. I think it's because I have other codes that link to the frames with a Enter_Frame function. How can I get the sounds to loop and not play multiple times at once?
Have you dropped the sound anywhere on the timeline in any frame? If so remove that frame.
Also, if you have your code declared on a keyframe that does not have a stop(); call on it, likely it is hitting that frame over and over again, when it "enters" it. Try adding stop(); either at the beginning of your code or at an ending key-frame, wherever it makes most sense for your project.
After trying those two things, another method I have learned to love that may come in handy is:
flash.media.SoundMixer.stopAll();
This will stop all sounds so that whatever sounds you start to play after making this call will not have other previously started sounds to contend with.
This sound tutorial may also be of use to you.
Let us know how it goes, or if any of this stuff helped.
Recently I took on a rather daunting task of creating an interactive music video for the popular show Ghost Whisperer. I was brought in late in the project and was confronted with a giant authoring file (some 5000+ frames long). The previous programmer (who did everything in AS2) had essentially embedded a two and half minute FLV on the time main time line and at certain frame points would add in clips for interactivity with basic mouse click functionality that would trigger those clips to play other clips with some flash elements and some video elements.
(the final version I created can be viewed here http://www.gwghostmagic.com);
Being a neat freak I decided to rebuild the whole thing in AS3, ditch the time line altogether and rather load in my elements at run time so that instead of 5000 frames I had one frame and to trigger the actions added an Event.ENTER_FRAME event listener to trigger the interactivity when the loaded .swf would reach certain frames. From a programmers stand point it made everything much clearer and easier to manipulate certain actions. The problem was, the thing ran like crap.
The 5000+ frame version loaded faster and ran smoother than my AS3 version. Which brings me to the question, when is it better to embed and run off the time line than run off of an event listener? Is flash better suited for time line functionality?
Initially I decided to build and run off of a streaming .flv but syncing up the actions to the .flv was impossible because the .flv was running at 23.975 fps whereas my flash movie was running at 24 fps. Alas I was forced to compile an .swf with the flv embedded. That .swf was then loaded into my main .swf that contained all the functions and extra clips that would play according to the loaded .swf's frame position.
One thing I've noticed is that the Event.ENTER_FRAME seems to slow the whole damn application down because at every frame it has to run down a list of if statements 200 lines of code long. Wherein if the whole thing was embedded I might only need to insert a keyframe where the interactive clip would be instantiated and then would know immediately what to do, rather than cycle through if else statements.
Did I screw up trying to make things nice and tidy? Is it better to let flash be flash? Should I seek out another career? Any input is greatly appreciated.
I think that having the event trigger every frame as opposed to only triggering actions occasionally accounts for the performance difference. Hopefully you could minimize the amount of code and conditionals that was run through in the event handler.
Here's an idea I haven't tested:
var dispatch:Object = {
f1: function () {textBubble.text = "This is Rush Hour 2";},
f61: function () {textBubble.text = "";},
f111: function () {textBubble.text = "This scene has 50 takes; "
+"Jackie Chan said \"Square Madison\" each time.";},
f171: function () {textBubble.text = "";}
};
addEventListener(Event.ENTER_FRAME, function (e:event) {
if (dispatch["f"+e.target.currentFrame] is Function) {
dispatch["f"+e.target.currentFrame]();
}
});
This uses the Object as an Associative Array as described in the live docs.
You are probably correct - running 200+ lines of code on every frame is slowing you down. Instead of a huge list of statements, split your frame functions up and only call the ones you need - this is an expansion on dlamblin's idea - this way you are running the smallest amount of code necessary for each frame:
function doThisOnFrame20():void
{
//do stuff...
}
function doThisOnFrame50():void
{
//do stuff...
}
var frameFunctions:Array = new Array();
frameFunctions[20] = doThisOnFrame20;
frameFunctions[50] = doThisOnFrame50;
function enterFrameListener(event:Event):void
{
if(frameFunctions[swfWithFLV.currentFrame] is Function)
{
frameFunctions[swfWithFLV.currentFrame]();
}
}
addEventListener(Event.ENTER_FRAME,enterFrameListener);