Flash object collision problem :S

Subscribe to Flash object collision problem :S 28 posts, 6 voices

 
avatar for Dealmaster13 Dealmaster13 54 posts
Hi guys, this is the first time I’ve ever attempted to create a flash game (after learning flash for a few days now) with some gamemaker and MSWLogo (LOL) experience, so I’m not affraid of those evil codes ;) However, until now a problem has cropped up and me being a total newb to Flash have now idea what’s going on. For some reason, in my game (link below), if you shoot rapidly, the game completely disobeys my collision detection coding and lets the bullet shoot straight past the object. What’s even more worrying is that it actually does work sometimes i.e. either if the asteroid is in a certain range (I think about 100 pixels away from turret, max) or if you fire very slowly. The coding for my crappy collision detection is as follows:
    
if(this.hitTest(cannonball_fired)) {
        this.pushy += 0.3/((25+this.scalerx)/100);
        removeMovieClip(cannonball_fired);
        }
Cannonball_fired being the bullet and ‘this’ being a duplicate of an Asteroid movie clip. Also, if I were to use the ‘real’ asteroid and not a duplicate, the collision detection would work fine every time. I have also created a duplicate of the collision detection in the ‘cannonball_fired.onEnterFrame = function() {‘
if(this.hitTest("Asteroid"+bob)) {
        eval("Asteroid"+bob).pushy += 0.3/((25+eval("Asteroid"+bob).scalerx)/100);
        removeMovieClip(this);
        }
(“Asteroid”+bob) being the asteroid copy and ‘this’ as the bullet

Help, as usual is deeply appreciated.

SWF file: http://www.megafileupload.com/en/file/72906/sho… OR http://www.megaupload.com/?d=5TGR3KCO

Full code:

Mouse.hide();
scaler = random(75)
time = 0

attachMovie("crosshair", "crosshair", 100);
attachMovie("Asteroid", "Asteroid", 3, {_x:((random(1099))-200), _y:-199});
attachMovie("tank", "tank", 2, {_x:350, _y:350});
crosshair.onEnterFrame = function() {
    this._x = _xmouse;
    this._y = _ymouse;
};
tank.onEnterFrame = function() {
    time += 0.04
    if (time>6){
        bob = random(100)
        duplicateMovieClip("Asteroid","Asteroid"+bob,bob);
        eval("Asteroid"+bob)._x = (random(500))+200
        eval("Asteroid"+bob)._y = 0
            eval("Asteroid"+bob).pull = 0
            eval("Asteroid"+bob).pushy = 0
            eval("Asteroid"+bob).scalerx = random(75)
        eval("Asteroid"+bob).onEnterFrame = function(){

    this._xscale = 25+this.scalerx
    this._yscale = 25+this.scalerx
    if(this.hitTest(cannonball_fired)) {
        this.pushy += 0.3/((25+this.scalerx)/100);
        removeMovieClip(cannonball_fired);
        }
    ratio = ((tank._x - this._x)/(tank._y - this._y))
    if(ratio < 0) {ratio = 1-(1+ratio)}
    this.pull += 0.0075
    if(tank._x > this._x){
this._x += (this.pull-this.pushy)*ratio
}
else {
this._x -= (this.pull-this.pushy)*ratio
    }
if(tank._y > this._y){
    this._y += (this.pull-this.pushy)
}
else {
    this._y -= (this.pull-this.pushy)
}
if(this._x < -200 or this._y < -200 or this._x > 900 or this._y > 900) {
                removeMovieClip(this);
    }
                }
            time=0}
    mousex = _xmouse-this._x;
    mousey = (_ymouse-this._y)*-1;
    angle = Math.atan(mousey/mousex)/(Math.PI/180);
    if (mousex<0) {
        angle += 180;
    }
    if (mousex>=0 && mousey<0) {
        angle += 360;
    }
    firepower = Math.sqrt(mousex*mousex+mousey*mousey);
    if (firepower>1000) {
        firepower = 1000;}
        firepower = 800

    this.cannon._rotation = angle*-1;
};

function onMouseDown() {
    angle = tank.cannon._rotation-1;
    start_ball_x = tank._x+42*Math.cos(angle*Math.PI/180);
    start_ball_y = tank._y+42*Math.sin(angle*Math.PI/180);
    cannonball_fired = attachMovie("cannonball", "cannonball_"+_root.getNextHighestDepth(), _root.getNextHighestDepth(), {_x:start_ball_x, _y:start_ball_y});
        cannonball_fired.dirx = Math.cos(angle*Math.PI/180)*firepower;
    cannonball_fired.diry = Math.sin(angle*Math.PI/180)*firepower;
    cannonball_fired.onEnterFrame = function() {
        this._x += this.dirx/50;
        this._y += this.diry/50;
        this._rotation += 40
        if(this.hitTest("Asteroid"+bob)) {
        eval("Asteroid"+bob).pushy += 0.3/((25+eval("Asteroid"+bob).scalerx)/100);
        removeMovieClip(this);
        }
        if(this._x < -100 or this._y < -100 or this._x > 800 or this._y > 800) {
        removeMovieClip(this);
    }
    };
}

I would rather not upload the .FLA file due to copyright reasons

 
avatar for BigCheese BigCheese 367 posts

The problem happens because you are only testing the last bullet fired. You would need to store an array of bullets and loop through testing each.

 
avatar for Dealmaster13 Dealmaster13 54 posts
Sorry, but how do I do that? I have looked through varoius tutorials on arrays and so far, I can’t see how this could help with my bullet problem. The closest I’ve come to is this:
for (var i=0; i < Array.length; i++)
{
    trace( Array[i] )

}
However still don’t know how to implement it into my game so that I have an array of bullets which my collision detection checks against. p.s. thanks for the quick reply
 
avatar for Jabor Jabor 2793 posts

First, create a function that takes a Bullet object as a parameter (you are using objects, aren’t you?) that checks the supplied Bullet for a collision against whatever you’re checking against. Then use a loop to call that function once for each Bullet in the array, passing that particular bullet as a parameter.

e.g. if your collision detection function is named DetectCollision, and takes a single parameter, then you’d use the following to loop through the array:

for (var i=0; i < BulletArray.length; i++)
{
    DetectCollision( BulletArray[i] );
}

When you create an instance of a bullet, simply add it to the array, and when it leaves the screen or hits the target, remove it from the array and let the garbage collector deal with it (ActionScript has garbage collection, right?)

 
avatar for Dealmaster13 Dealmaster13 54 posts

Thanks for your reply Jabor, but me, being completely new to flash (only been on it for a few days now) would not really understand what exact coding is needed i.e. a step by step guide would be much more helpful. Anyway, here is the new .swf file: http://www.megaupload.com/?d=H3J7UANA The changes I’ve made are:

    for (var i=0; i < BulletArray.length; i++)
{
    if(this.hitTest( BulletArray[i] )) {
        this.pushy += 0.3/((25+this.scalerx)/100);
        removeMovieClip(BulletArray[i]);
        };
}
within
eval("Asteroid"+bob).onEnterFrame = function(){
and
BulletArray = new Array(this)
within
cannonball_fired.onEnterFrame = function() {
It would help to open the swf file I uploaded as it is quite hard to explain the problem with enough detail. Firstly if I shoot rapidly at a certain asteroid, the bullet may go through it, however they don’t disobey the collision detection as often as before. Secondly – not really relavent to the collision detection problem – sometimes an asteroid disappears with a new one taking its place :S Full code below:
Mouse.hide();
scaler = random(75)
time = 0

attachMovie("crosshair", "crosshair", 100);
attachMovie("Asteroid", "Asteroid", 3, {_x:((random(1099))-200), _y:-199});
attachMovie("tank", "tank", 2, {_x:350, _y:350});
crosshair.onEnterFrame = function() {
    this._x = _xmouse;
    this._y = _ymouse;
};
tank.onEnterFrame = function() {
    time += 0.04
    if (time>4){
        bob = random(100)
        duplicateMovieClip("Asteroid","Asteroid"+bob,bob);
        eval("Asteroid"+bob)._x = (random(500))+200
        eval("Asteroid"+bob)._y = 0
            eval("Asteroid"+bob).pull = 0
            eval("Asteroid"+bob).pushy = 0
            eval("Asteroid"+bob).scalerx = random(75)
        eval("Asteroid"+bob).onEnterFrame = function(){

    this._xscale = 25+this.scalerx
    this._yscale = 25+this.scalerx
    for (var i=0; i < BulletArray.length; i++)
{
    if(this.hitTest( BulletArray[i] )) {
        this.pushy += 0.3/((25+this.scalerx)/100);
        removeMovieClip(BulletArray[i]);
        };
}
    ratio = ((tank._x - this._x)/(tank._y - this._y))
    if(ratio < 0) {ratio = 1-(1+ratio)}
    this.pull += 0.0075
    if(tank._x > this._x){
this._x += (this.pull-this.pushy)*ratio
}
else {
this._x -= (this.pull-this.pushy)*ratio
    }
if(tank._y > this._y){
    this._y += (this.pull-this.pushy)
}
else {
    this._y -= (this.pull-this.pushy)
}
if(this._x < -200 or this._y < -200 or this._x > 900 or this._y > 900) {
                removeMovieClip(this);
    }
                }
            time=0}
    mousex = _xmouse-this._x;
    mousey = (_ymouse-this._y)*-1;
    angle = Math.atan(mousey/mousex)/(Math.PI/180);
    if (mousex<0) {
        angle += 180;
    }
    if (mousex>=0 && mousey<0) {
        angle += 360;
    }
    firepower = Math.sqrt(mousex*mousex+mousey*mousey);
    if (firepower>1000) {
        firepower = 1000;}
        firepower = 800

    this.cannon._rotation = angle*-1;
};

function onMouseDown() {
    angle = tank.cannon._rotation-1;
    start_ball_x = tank._x+42*Math.cos(angle*Math.PI/180);
    start_ball_y = tank._y+42*Math.sin(angle*Math.PI/180);
    cannonball_fired = attachMovie("cannonball", "cannonball_"+_root.getNextHighestDepth(), _root.getNextHighestDepth(), {_x:start_ball_x, _y:start_ball_y});
        cannonball_fired.dirx = Math.cos(angle*Math.PI/180)*firepower;
    cannonball_fired.diry = Math.sin(angle*Math.PI/180)*firepower;
    cannonball_fired.onEnterFrame = function() {
        this._x += this.dirx/50;
        this._y += this.diry/50;
        this._rotation += 40
        BulletArray = new Array(this)
        if(this._x < -100 or this._y < -100 or this._x > 800 or this._y > 800) {
        removeMovieClip(this);
    }
    };
}
Unfortunately everything is in one layer and frame as I do not know how to create codes for a single object/movie clip.

 
avatar for Dealmaster13 Dealmaster13 54 posts

hello? :(

 
avatar for BigCheese BigCheese 367 posts

Can you use imageshack.us or swfupload, I hate waiting for a minute just to view the file. I’ll take a look once it downloads.

Hmmmm…. why are you defining cannonball_fired.onEnterFrame inside of the onMouseDown function?

 
avatar for Jabor Jabor 2793 posts

Ok, I see the problem with the occasional replacement.

You’re using a random number to try and keep different asteroids different, right? So what’s happening when the game creates a new asteroid and the same random number comes up? That’s right, the game removes the old asteroid and creates a new one.

Also, all your actionscript should be in one place. Splitting it up amongst several movieclips is bad.

My suggestion would be to add the following to the following to the top of the code:

AsteroidArray = new Array();
BulletArray = new Array();

Then add the bullets and asteroids to the appropriate arrays when they are created, and remove them when they are no longer needed.

Are you using AS2 or AS3?

 
avatar for Dealmaster13 Dealmaster13 54 posts

AS2 When you say this – “Also, all your actionscript should be in one place. Splitting it up amongst several movieclips is bad.” Do you mean having everything in one scene and frame is bad? Because I don’t know how to have separate movie clip codes. @BigCheese: I don’t know, I have modified this game from an open source file – does it make a difference i.e. is that what’s causing the problem? @Jabor: Is this the correct code to use?

BulletArray = new Array(this)
I don’t know if it is because I just made it up lol :p I will also need how to remove an object from an array when they are deleted Also, when I create an asteroid from a random number i.e. 100, surely the asteroids don’t come often enough to delete each other as often as they do. However, will a bigger number help?

 
avatar for Phantasmagoria Phantasmagoria 276 posts

Wow, I’ve heard stories of people using a random number generator to create “unique” ids, but never ran into someone who actually did so until now. Seriously, it’s a hilariously bad idea, fundamentally flawed, and there are plenty of ways to do it right.

One simple way – if you need actual id numbers – is to keep a counter and increment it each time you use a number. Guaranteed unique, unless the counter overflows… but I doubt you’ll be using it enough to have to worry about that.

 
avatar for Dealmaster13 Dealmaster13 54 posts

ok… :S

 
avatar for Jabor Jabor 2793 posts

Let me clarify:

Unless you’re using objects and writing your own classes, all the code that you write should be in one place. Everything. On its own layer, with nothing else on it. If you place a little bit on this button here, and another bit on this movieclip here, and something else over here, then it becomes a real mess to follow. Keep it all in one place.

 
avatar for Dealmaster13 Dealmaster13 54 posts

Which is what I am currently doing… I just need help with the arrays then I suppose… thanks for your help so far

 
avatar for Dealmaster13 Dealmaster13 54 posts

If I uploaded a copy of the flash file do you believe you’d be able to fix it? http://www.megaupload.com/?d=QM0GKE8B or http://www.uploading.com/files/VX34YD2A/shooter…

 
avatar for Dealmaster13 Dealmaster13 54 posts

Hello?

 
avatar for BigCheese BigCheese 367 posts

I’ll look into it. I can’t guarantee anything, though.

EDIT: Sorry, I’ve got MX 2004, so the file isn’t compatible.

 
avatar for Dealmaster13 Dealmaster13 54 posts

I’ll try converting it for you tomorrow, however I have to go to bed now. I greatly appreciate your help btw.

EDIT: very sorry to have to get you to keep downloading these files… but here it is: ................................... FLASH MX 2004 versionhttp://www.megaupload.com/?d=OLZP6CI1 or http://www.uploading.com/files/3ZQJDGDL/shooter… ................................................................................................................................................................. Flash CS3 versionhttp://www.megaupload.com/?d=27R85YKY ............................................................................................................................................................ Flash 8 versionhttp://www.megaupload.com/?d=T33QH0DR ...goodnight ;)

 
avatar for Dealmaster13 Dealmaster13 54 posts

bump

 
avatar for Dealmaster13 Dealmaster13 54 posts

hello?

 
avatar for BigCheese BigCheese 367 posts

Sorry, the code you wrote doesn’t look like it was meant to support multiple bullets. Instead of using enterFrame to loop through the bullets, you should be using a for statement. One sec, I’ll put up an example.

Okay, look at this code and post if you have any questions: Here

 
avatar for Dealmaster13 Dealmaster13 54 posts

Thanks, that looks very helpful, I’ll see into that in a bit, however since I have duplicate asteroids as well, would then need to be in an array like that which was shown in the tutorial, if so, how does the collision checking work, because surely that would be complicated having 2 for statements?

 
avatar for Tidenburg Tidenburg 33 posts

No it wouldn’t. Some games have much more than that running at once ;)

 
avatar for Dealmaster13 Dealmaster13 54 posts

Are you saying that all you need to do is put one for statement within another?

 
avatar for Jabor Jabor 2793 posts

When you’re checking all objects in one array against all objects in another array, nesting for loops is the simplest way of doing so.

 
avatar for Phantasmagoria Phantasmagoria 276 posts

Tsk, the simplest way is to abstract the behavior of applying some code to every combination of items from a set of arrays, and then to apply the abstraction whenever you need that behavior. ;)