Movie Clip Object adding Multiple Times with Enter_Frame Event - arrays

Hey Guys so I am using TweenLite to act as a timer for Performance with Mobile usage. I ran into a little problem here that I can't seem to figure out. So In my ENTER_FRAME Listener I have this function difficultyController Where I add my TweenLite control like so:
private function difficultyController():void
{
if (nScore >= 10)
{
TweenLite.delayedCall(nChainsaw, addChainsaw);
trace("DIFFICULTY_UPDATE");
}
}
In my addChainsaw Function I have the Movie Clip Objects added to the stage like so:
private function addChainsaw():void
{
TweenLite.delayedCall(nChainsaw, addChainsaw);
var newChainsaw = new mcChainsaw();
//Add Child
addChild(newChainsaw);
//Push Move CLips into array
aChainsawArray.push(newChainsaw);
trace(aChainsawArray.length + "chainsaw");
}
Now I want the chainsaw Movie clip in the array to be added to the stage every 2 seconds which is what the value of nChainsaw is. Ill kill it off when the nScore reaches a higher number. But as of right now when I test the Game like so It adds Multiple Movie clips over and over again then freezes the game. I know it has to do with the ENTER_FRAME Listener But I don't know what else to do. SHould I just remove the TweenLite and add A Actual Timer and in the diffucultyController(); just add timer.start??
If anyone has anyother Ideas I would really Appreciate it thanks!

Related

What's a more efficient way to do collisions?

Here's my dilemma
I have 4 walls around the stage of my game, when a player hits these walls I do not want to make an if statement for each and every one of the walls checking if the player is hitting it, so I have created an array to hold the walls, then check if the player is hitting that. Now, because I am doing this I will not know what the player is actually hitting if he hits something, and I cannot do a check in my array if he's hitting like [0], [1], [2] etc because then I'm back to doing the checks if he's hitting specific walls. The reason I don't want to do that is for the future, when I add more barriers, buildings, and so on.
So my question is, how can I do collision checks, without hard coding checks on specific objects, and giving some sort of value that can be used for the player to respond to, for example if your hitting the top wall and you can figure that out somehow without doing the above, then make it so you can't walk through or something,
if (main.playerPosKeeper_mc.hitTestObject(this[main.StageCollisions]))
{
trace("hit");
}
StageCollisions is an array which contains all of my barriers in it.
When the player hits anything in StageCollisions, I cannot just simply subtract from his y value, or x value, because I do not know which object he hit, but I also do not want to hard code it so that I check if I'm hitting lets say the top barrier, because then why do an array in the first place if I'm just going back to making static if else statements.
^^ Refrencing this topic
AS3 - How to Cycle States of Character Animations (moving & stopped)
This has been stumping me for a little while, so help would be greatly appreciated. It is a hard question to form so I can clarify points if necessary.
So my question is, how can I do collision checks, without hard coding
checks on specific objects, and giving some sort of value that can be
used for the player to respond to, for example if your hitting the top
wall and you can figure that out somehow without doing the above, then
make it so you can't walk through or something
Right, so you want a way to perform a generic collision response. This can be a big topic. The simplest approach is usually to check for a collision after a move, then reverse the move if there's a collision.
Something like this:
function movePlayer(movementX:Number, movementY:Number):void {
var originalX:Number = player.x;
var originalY:Number = player.y;
player.x += movementX;
if (checkCollision()) {
player.x = originalX;
}
player.y += movementY;
if (checkCollision()) {
player.y = originalY;
}
}
function checkCollision():Boolean {
for each (var wall:MovieClip in walls) {
if (player.hitTestObject(wall)) {
return true;
}
}
return false;
}
This way you could have checkCollision() check 4 walls or 50 walls, it doesn't matter. It won't let the player move into them.
This is just a starting point and there are many ways it can break down or be refined.
Some trivial pseudo code for you to study:
private function collisionCheck(h:Sprite):Sprite{ // pass the hero Sprite into this function and it will return the wall that it hit
for each (b:Sprite in blockArray){ // if your array of hit-able objects is called "blockArray"
if (h.hitTtestObject(b)){ // check the hero Sprite against all objects in the array
return b;
}
}
return null;
}
Then, elsewhere in your code (maybe in your gameTick function or gameLoop function or wherever you have your game logic repeating on each frame:
private function gameTick():void{
var objectHit:Sprite = collisionCheck(_myHero); // this will run the collision check function, and return the sprite that the hero collides with;
if (objectHit != null){
objectHit.alpha = 0.5;
// this will give you a visible representation that your code is indeed working, or not.
}
}
For those moments when your hero isn't colliding with anything, this function will return null. That's why I first check if objectHit is not null before trying to perform an operation on its alpha value. Of course, you will do something other than change its alpha value in your project, but this is something I often do (with the alpha) to quickly get a visual confirmation that things are detecting what they are supposed to.

How to Loop a script in gamemaker

cantSee = collision_line(x,y,obj_player.x,obj_player.y,obj_corner,false,true)
canSee = !(collision_line(x,y,obj_player.x,obj_player.y,obj_corner,false,true))
Define the loop as the following:
if cantSee {
cantSeeTimer = cantSeeTimer +1
}
if cantSeeTimer >60 {
speed=0
stopped=true
} else {
mp_potential_step(obj_player.x,obj_player.y,5,false)
}
}
if stopped=true && canSee {
mp_potential_step(obj_player.x,obj_player.y,5,false)
loop()
}
I know the language is bad, but I just want to create a loop command to summon at will.
Thanks, Finn.
so you haven't specified which object in your game currently has this code but it shouldn't matter too much.
So in Game Maker or Game Maker Studio there are a series of events an object can have and one of them is called a "Step" event. A step event is basically a loop that will cycle the amount of times the room speed is per second. Eg: If the room speed of a room is 30 the step event will loop 30 times per second.
I think I can see what you are trying to do and I think I have a solution for you.
Since you can write GML code I am going to assume you understand how to use the GMS or GM IDE.
We want to create a new object called obj_control (or you can choose a custom name). Also don't give this object a sprite as we don't want the player to see it.
Now we want to add an event to our new object so make sure you still have the windows for obj_control (or whatever u called it open). and click on the 'Add Event button' shown in this image: http://imgur.com/A7szwFO
Once you click on it, click on 'Step'. http://imgur.com/s0ksiyD
Now select 'Step' again. ('Begin Step' and 'End Step' don't do what we want so let's just ignore them)
Now we need to add your code to the step event we just created. So make sure you are on the 'Control' tab and find the script editor (you should know where to find it) and drag one into the 'Actions' for the step event.
http://imgur.com/de3gE01
Now a script editor should pop up automatically but if it doesn't just double click the "Execute piece of code". Now we just need to copy and paste all of your code into the script editor.
http://imgur.com/sNBOCFu
Now click on the green tick on the top left corner of the window to save the code.
Now before we are done let's make sure we define the variables in a create event. So make a create event and add this code:
cantSee = collision_line(x,y,obj_player.x,obj_player.y,obj_corner,false,true)
canSee = !(collision_line(x,y,obj_player.x,obj_player.y,obj_corner,false,true))
After you have added that create event and inserted that code into it save all changes to the object.
All that is left is to add this object we created to every room of the game so it can function.
Hopefully this helped and if it didn't just let me know and we can get it sorted.

Movie Clip through Display Object Not working correctly

Hey everyone so I have a movie Clip called popEffect that i want to show on the current bubbles that are being clicked by the mouse. Now Whenever I click on a Bubble everything works correctly they get removed from the stage, but the problem I am having is that the popEffect is not positioned to the current bubbles that are being clicked. Instead they are positioned at a different bubble that shows on the screen in the display object array.
Here is how I have it all set up:
private function addBubbles(e:TimerEvent):void
{
bubbles = new mcBubbles();
stage.addChild(bubbles);
aBubbleArray.push(bubbles);
bubbles.addEventListener(MouseEvent.CLICK, bubblesBeingClicked);
}
Then the BubblesBeingClicked function:
private function bubblesBeingClicked(e:MouseEvent):void
{
var BubblePop:DisplayObject = e.target as DisplayObject; // HERE is your clicked square
var i:int = aBubbleArray.indexOf(BubblePop); // and HERE is your index in the array
if (i < 0)
{
// the MC is out of the array
//trace("Pop Clicked");
onBubbleIsClicked(BubblePop);
aBubbleArray.splice(i, 1);
BubblePop.parent.removeChild(BubblePop);
//Remove Listeners!!!
BubblePop.removeEventListener(MouseEvent.MOUSE_DOWN, onBubbleIsClicked);
// Null
BubblePop = null;
}
}
Finally my onBubbleIsClicked function where i have the popEffect located:
private function onBubbleIsClicked(bubblePop:DisplayObject):void
{
nScore++;
updateHighScore();
//Pop Effect
popEffect = new mcBubblePop();
stage.addChild(popEffect);
popEffect.x = bubbles.x;
popEffect.y = bubbles.y;
}
Can anyone see why the popEffect wont position on the current bubble that is being popped? Its acting really weird.
The reason is this:
popEffect.x = bubbles.x;
popEffect.y = bubbles.y;
As far as I can understand, bubbles is a member variable in the class (you are using it in the addBubbles function. Inside onBubbleIsClicked, you provide bubblePop, but do not use it. You are using bubbles instead, which is actually the last instance you've created inside the tick function!
So every time you create popEffect, you actually assign the x and y to the latest created bubblePop.
Some advises:
Do not use member variables that often. They are used WHEN you need to use a variable between functions. In your case, bubbles is a variable that is used only inside the creational function. You even put them into an array! And because you override it with a new one every time you create an instance, your member variables just saves the last one. Is this really needed? Same with popEffect, does anyone else uses it, as it's again just the last one? Such things create mistakes, as you see..
I truly don't understand what this means: if (i < 0). You search if the object you've clicked is not in the array? Well if it is not (how come?!), then what's the meaning of aBubbleArray.splice(i, 1);? Since i < 0, you actually splice with negative value, so you splice some other element! Plan what you want to do, thing logically and then do the actual code. If the object is not in the array, then why do you remove anything from the array?
Start formatting your code better. Read about camel case and variables scope.
Try to manage your logic better. For example this is pretty awkward: BubblePop.parent.removeChild(BubblePop);, as long as you've added it by using stage.addChild(bubbles);. So isn't it more simple to use stage.removeChild(child);? There are some rules in programming (especially in Flash), like 'what added it should remove it'. This will keep you safe in future.
Good luck!

Referencing an array on stage from another movieclip

I have an array of MovieClips (on the main stages actions) that i want to refer to from within other movieclips placed on the stage.
var hotSpots:Array =[hotSpot1, hotSpot2, control_mc, tip_mc]
for each (var removeHotspots:MovieClip in hotSpots)
{
removeHotspots.visible = false;
}
How do i refer back to this array from within another movieclip without having to add the array again?
I tried...
var hotSpots:Array = Object(this).hotSpots
and then within my event Listener...
for each (var removeHotspots:MovieClip in hotSpots)
{
removeHotspots.visible = true;
}
But it doesn't seem to work? Can anyone help.
I have alot of arrays like this that i really dont want to have to add to each movieclip everytime i need to call them.
"this" refers to the MovieClip your code is within. If you want to access the parent MovieClip (in this case the root or stage) you can either use parent.hotSpots or stage.hotSpots. However, this requires the MovieClip to be added to the stage (and thereby the display list), otherwise both parent and stage will be null.
If you want to wait for a MovieClip to be on stage before executing code where you refer to the stage variable you can use the event Event.ADDED_TO_STAGE

How to effectively garbage collect in AS3

I have a flash game that I'm building where I have an array keeping track of a bunch of power ups on the screen. When the player goes an grabs one it needs to disappear from the screen (which is easy) but it also needs to be removed from the array so that collision detection loops don't become really cumbersome. I tried using splice, but I keep get null reference errors, here's the relevant code.
public function collect():void {
try {
Main.powerUps.splice(index, 1);
stage.removeChild(this);
}catch (e:Error) {
trace("Error in splice");
}
}
}
Then when I create my PowerUp object I pass it a parameter that gets assigned to index which is the length of the array of Power Ups at the time. Can anyone see what's wrong with this code or (preferably) provide a more elegant solution? Thanks in advance for any help.
Elegant solution: use indexOf() and splice() together!
var index:int = Main.powerUps.indexOf( powerup );
Main.powerUps.splice(index, 1);
Where powerup is a reference to the object stored within the array Main.powerUps.
I also created a little class a while back that may be useful to you:
https://github.com/MartyWallace/Lotus/blob/master/Lotus/lotus/utils/Set.as
It has a .remove() method so you can just do:
powerUps.remove(powerup);

Resources