Collisions detected after the MovieClip was removed - actionscript-3

Okay, so let's say I have "ball" MovieClips that collide against a "wall" MovieClip.
if ( !ball.hitTestObject(wall) ) {
// If they didn't find any obstacle keep falling.
ball.y++;
}
Then I remove the wall, and the balls keep colliding against a wall that I cannot see. No ball moves, not the ones that were there, neither the new ones.
case Keyboard.K: removeChild(wall); break;
What am I missing or doing wrong?
Thanks in advance.

removeChild only removes the instance from the display list, display list has nothing to do with game logic actually... you have to either disable your movieclip with a boolean (if you later want to use it then you can enable it) or null the reference, but beware of nulling your reference, because if you try to access it after nulling, you get an error, so you might want to check that if your wall is whether null or not before checking your collision.
if(wall!=null){
if ( !ball.hitTestObject(wall) ) {
// If they didn't find any obstacle keep falling.
ball.y++;
}
}
...
case Keyboard.K:
removeChild(wall);
wall = null;
break;

Related

Jumping back and forth inside a Movieclip with a button?

So, I'm very much a beginner in AS3. I've been reading and figuring out things as I go, though I can't wrap my head around this.
So, I have 4 frames. Each frame has a different movie clip, MC1,MC2,MC3,MC4
Inside those four movie clips, there is another movie clip with the same instance name for each: BC, and inside that movie clip there are two frames. Frame 1 has a dot, and frame 2 does not.
MC1>BC>(2 frames)
MC2>BC>(2 frames)
and so on....
What I'm trying to do: I wanted to see if there was any way to control the frame navigation of BC inside all four MC clips at the same time with one button.
I want to switch back and fourth between the two frames inside the BC movie clip.
I'm at a loss, I've tried quite a few things.
You should be able to do so by giving them all the same instance name (so long as there is only ever one of them on screen at once).
So lets say you have a button that spans all 4 frames with an instance name of navBtn and you gave each of the MC1-4 clips the same instance name of MC. You could do the following on frame 1:
navBtn.addEventListener(MouseEvent.CLICK, navBtnClick);
function navBtnClick(e:Event):void {
if(MC.BC.currentFrame == 2){
MC.BC.gotoAndStop(1);
}else{
MC.BC.gotoAndStop(2);
}
}
Reading your question again, perhaps what are looking for is to have each clip automatically go to the same frame for their BC child when they load? If that is the case, then follow the example in the comment on your question by #Organis. Here is one way you could accomplish this:
Create two variable on frame one of your main timeline:
var BC_NAV_CHANGE:String = "BC_NAV_CHANGE";
var BC_CurFrame:int = 1;
Then, when you need to change the frame of the BC objects, do the following:
//create a function that you call when you want to change the BC frame
function toggleBCFrame(e:Event = null){
MovieClip(root).BC_CurFrame = MovieClip(root).BC_CurFrame == 1 ? 2 : 1;
//the line above is a if/else shorthand, that is setting a new value to the `BC_CurFrame` var,
//if the current value is `1`, it will set it to `2`, otherwise it will set it to `1`
MovieClip(root).dispatchEvent(new Event(MovieClip(root).BC_NAV_CHANGE));
//this line (above) dispatches a event telling anything that's listening that the variable has changed
}
If the code above is on the main timeline, you can forgo all the MovieClip(root). parts of the code.
Now, on the timeline of your BC MovieClip(s), put the following code:
//create a function that goes to and stops at the frame stored in the global variable
function updateFrame(e:Event = null){
gotoAndStop(MovieClip(root).BC_CurFrame);
}
//next listen for the BC_NAV_CHANGE event, and call the above update function above any time that event happens
MovieClip(root).addEventListener(MovieClip(root).BC_NAV_CHANGE, updateFrame);
//lastly, call the update function right away so when the BC clips loads it immediately goes to the correct frame
updateFrame();

How do I stop my character moving through objects with actionscript 3?

I am new to flash and want to make it so when my character hits an object, they won't go through it, but still maintains control after they have hit it. I want it to be a solid object from all 4 points (top, left, right, bottom) of the object. Here is what I have been experimenting with...
function hitsTheObject(e:Event)
{
if (myCharacter.hitTestObject(Ball_mc))
{
gravity = 0
hitObject = true
}
if (dIsDown == true && hitObject == true)
myCharacter.x -=10
}
The first if statement works, though the second one turns off the dIsDown button I have coded. Any thoughts?
Edit: Basically I want the character to hit an object and for it to block the character, as if it was a wall.
Lewis, you're best bet is point collision. Here's some links to help you think it through and start off: http://www.wildbunny.co.uk/blog/2011/12/14/how-to-make-a-2d-platform-game-part-2-collision-detection/ and http://www.anotherearlymorning.com/2009/07/pixel-perfect-collision-detection-in-actionscript-3/
Check out my collision engine, it supports continuous/bullet collisions: https://github.com/Murplyx/AAE---Axis-Aligned-Engine

as3 hittestobject not working, dont understand why

the collision not working i cant understand why, i put collision movieclips in the object and it doesnt seem to recognise one of the but does with the other, sorry for the confusing way of stating the problem if you play the game you will understand. im open to changing the way collision works too as long as it works ill be super happy
I'll try to explain. When You click "Down" or "Up" hero (box_MC) collide with both doors "Top_Door" and "Bottom_Door". Inside "bang" function at first checking collision with "Bottom_Door", so, hero always go down (.y += 100) and second condition (Top_Door) never will be true. How to fix this? Add variable var lastAction:String;. This variable will store last action: "up" or "down". Inside "down_MC_P" function initialize this variable by "down". Inside "up_MC_P" — "up". Next, replace the first condition to this if (box_MC.hitTestObject(cycle[i].Bottom_Door) && lastAction == "down") and second: if(box_MC.hitTestObject(cycle[i].Top_Door) && lastAction == "up"). That's all.

AS3 How to delete an object for good?

I create a new Shape, make a listener that starts a function when an object hits the shape, the function clears graphics of the shape, removes listener and deletes the child. But it looks like it leaves some ghost that still triggers when my object comes to it's place. I'm not sure why it happens, I thought clear+remove should make it impossible to hitTest. But somehow children still pile over one another and the last created one triggers the function. So if you understand, please give me a hint, if not please tell me in general what is a way to delete a created Shape for good, so it didn't count existing?
A bit of details. Hitting the shape must start a function that deletes it and creates a new shape of the same name that has a different function that does the same etc. so the current function must be the one I called for, not the last one, whose listener I deleted. Making new shape each time may overload memory, besides I do clean up every time. Did I forget anything?
fun0(){
var bob:Shape = new Shape();
addChild(bob);
bob...drawRect...
addEventListener(...,fun1)
function fun1(){ if(hitTest...){
bob...clear();
removeChild(bob);
removeEventListener(...,fun1)
fun2();
}
}
fun2(){
var bob:Shape = new Shape();
addChild(bob);
bob...drawRect...
addEventListener(...,fun3)
function fun1(){ if(hitTest...){
bob...clear();
removeChild(bob);
removeEventListener(...,fun3)
fun0();
}
}
etc., it only sees fun3 after I once trigger it even though I deleted the listener. Again, I do move object away, it doesn't hitTest anymore, then clear+remove. If you don't understand or cannot help, please don't flame, just ignore this, I need help, not the info that I'm not as smart as you are. Thank you.
first of dont declare functions inside of functions. then use weak reference for event listners.
// params: eventName, listener, capturePhase, priority, useWeakReference
someObj.addEventListener("eventName",myFunct,false,0,true);
you musst get rid of any references to the object, then set it to null
removeChild(bob);
bob= null;
after that GC will collect it!
edit:
if you keep doing the hitTest, like on enterFrame for example. check if the object is on the stage, by checking its .stage property.
if(bob.stage)
{
if(hitTest ...){};
}

Animation flickering problem

This is the game loop in my code and the drawing code:
float frames_per_second = 60;
display_timer = al_create_timer(1/frames_per_second);
queue = al_create_event_queue();
al_register_event_source(queue, al_get_timer_event_source(display_timer));
al_start_timer(display_timer);
while(!end_game)
{
ALLEGRO_EVENT event;
al_wait_for_event(queue, &event);
if(event.type == ALLEGRO_EVENT_DISPLAY_CLOSE) break;
if(event.any.source == al_get_timer_event_source(display_timer))
{update_display();}
update_input();
}
void update_display()
{
al_clear_to_color(al_map_rgb(255, 255,255));
draw_objects(); //this is just an al_draw_bitmap() call
al_flip_display();
}
The animation created by moving objects on screen flickers, I'm surprised by this since I write to the back buffer of the screen thus I expect double buffering. What can I do to correct the flickering? Thanks.
Unrelated to the problem, you can check a timer by looking for the ALLEGRO_EVENT_TIMER event. You can use event.timer.source to check which timer it is, if you have more than one.
I think the main problem here is that you are drawing the graphics at 60fps but you are updating the input at an unlimited rate. This is actually backwards. You want to update the input at a fixed rate. You can draw the graphics as often as you like... although it makes no sense to update the graphics if nothing has changed.
So it should look something more like:
if(event.type == ALLEGRO_EVENT_TIMER)
{
update_input();
update_display();
}
However, this does not implement frame skipping if things get too slow. What you should do is set up the timer in a dedicated queue (that contains no other event sources). Then as long as there are events sitting in that dedicated timer queue, update the input.
Then update the display, assuming you've processed at least one tick. So you may, if things get too slow, do multiple input updates per drawn frame.