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 |
|
|
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. |
|
|
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 |
|
|
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?) |
|
|
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. |
|
|
Dealmaster13
54 posts
|
|
|
|
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? |
|
|
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? |
|
|
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? |
|
|
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. |
|
|
Dealmaster13
54 posts
|
|
|
|
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. |
|
|
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 |
|
|
Dealmaster13
54 posts
|
|
|
|
Dealmaster13
54 posts
|
|
|
|
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. |
|
|
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 version –
http://www.megaupload.com/?d=OLZP6CI1 or http://www.uploading.com/files/3ZQJDGDL/shooter… .................................................................................................................................................................
Flash CS3 version – http://www.megaupload.com/?d=27R85YKY ............................................................................................................................................................
Flash 8 version – http://www.megaupload.com/?d=T33QH0DR
...goodnight ;) |
|
|
Dealmaster13
54 posts
|
|
|
|
Dealmaster13
54 posts
|
|
|
|
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 |
|
|
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? |
|
|
Tidenburg
33 posts
|
No it wouldn’t. Some games have much more than that running at once ;) |
|
|
Dealmaster13
54 posts
|
Are you saying that all you need to do is put one for statement within another? |
|
|
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. |
|
|
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. ;) |