Advertisement

How to do a collision check only once, game maker studio (GML)

Started by November 22, 2018 03:06 PM
19 comments, last by akshayMore 5 years, 11 months ago

Hey, 

So I have a bullet setup that will destroy itself upon collision with an enemy and enemyHP will decrease as per the damage variable on the bullet. Works fine. No problem.

My issue:

I want to have a second kind of bullet that fires from a certain tower (This part is working fine) but I want the bullet to pass through the enemy and continue for approximately a second.. 

I moved the code to destroy itself so now it registers an alarm and when the alarm triggers it destroys itself. That is fine. The bullet passes through enemies, fine BUT it 'hits' them multiple times for the duration of colliding with the enemy... I'm trying to figure out how to just get it to damage once... 

In the collision with objBullet 

if (!hit)
{
    currentHp = currentHp - pain;
}

This was my initial thinking... I just need to get the hit to turn true and false properly... 

In the step event

if (place_meeting(x,y, objBullet))
{
    hit = true;
}

hit = false;

This was what I was thinking was going to work but it doesn't yet. 

So I want it to tell itself not to take damage if its already been hit but it still just takes as much damage as it it colliding... I again think this is just something simple that i'm just missing but I am a tiny bit stuck right now -.- Any ideas? I can't find a 'collision start' or 'collision end' event to use, I figured place_meeting would work to check for collisions ? I dunno though

Many Thanks,

Check out my game '3NDL3ZZ: Base Defense' A simple militant styled, tower defense game.

GameDev.Net Project Page

Very simple. :) You have a variable (boolean) dontCheckCollision or whatever you want to name it... and for whatever collision you do you always do this first:


// assuming object1 is alive
// ---
if (object1.dontCheckCollision == false) {

check collision;

    if (collision == true) {

    // Do stuff

    object1.dontCheckCollision = true;

    }

}

else if (object1.dontCheckCollision == true)

{

keep moving and do stuff

}

 

Once your first collision is done, set dontCheckCollision to true so you don't check anymore, and the object can still be alive doing whatever else, or continuing to move until you decide to kill it (such as a few seconds after the first collision).

The above is a simple example.

Programmer and 3D Artist

Advertisement

There's just one bit I'm getting stuck with atm (I hope its just one bit)

 


if (objBullet.dontCheckCollision == false) // So its 'okay' to check collision of this bullet..
{
    if (place_meeting(x,y, objBullet)) // Checking if Enemy is meeting a bullet
    {
        if(sprite_index = sprEnemySmall) // Small Enemy Takes More Damage (pain) from "gun" bullets
        {
            if other.sprite = "gun"
            {
                pain = other.damage * 2;
            }
            else pain = other.damage
        }

    	if(sprite_index = sprEnemyMedium) // Medium Enemy Takes More Damage (pain) from "flame" bullets
    	{
        	if other.sprite = "flame"
        	{
            	pain = other.damage * 2;
        	}
        	else pain = other.damage
    	}

    	if(sprite_index = sprEnemyLarge) // Large Enemy Takes More Damage (pain) from "missile" bullets
    	{
        	if other.sprite = "missile"
        	{
            	pain = other.damage * 2;
        	}
        	else pain = other.damage
    	}
    
    	objBullet.dontCheckCollsion = true;  // Telling it not to check collision again...      
    }
    
    else if (objBullet.dontCheckCollsion == true)
    {
        //Not sure what to put here ... I want to reactivate the ability to collide again if it hits a different enemy after hitting this one..
    }
}

I'm stuck on the 

else if (object1.dontCheckCollision == true)

{

keep moving and do stuff

}

 

part... How do I retrigger all of this on a fresh collision with a different enemy in the same lifetime of the bullet? -- This code is in the Step event of my enemy object so each enemy would be able to do this but this is where I'm getting a bit lost... Would I want to put this code somewhere else? 

Check out my game '3NDL3ZZ: Base Defense' A simple militant styled, tower defense game.

GameDev.Net Project Page

Sorry, I'm half asleep right now haha long night and got up early...

I initially read your questions as this:

"I would like a bullet to hit an object one time, but continue moving and no longer triggering collision."

The above would solve this.

Unless you're asking how to make the bullet pierce more than one object? Which I also have a solution for if you need.

Programmer and 3D Artist

10 minutes ago, CyberFlash said:

I'm stuck on the 

else if (object1.dontCheckCollision == true)

{

keep moving and do stuff

}

This code will be never executed, you probably wanted to move it outwards the scope of: if (objBullet.dontCheckCollision == false).

 

However, as i understand it, by using a single flag per bullet the bullet becomes inactive after the first hit, which is not what you want.

Likely you want the bullet to store the index (or id - whatever you have) of the object it has hit the last time, so when the collision is triggered again you know this bullet already has done damage to this object. Issue: if multiple close objects form a cycle, the bullet could still damage them multiple times. But that's likely rare and the alternative - storing a list of objects - would be expensive.

(Not sure if @Rutin has i different idea which would be simpler)

 

I just noticed, you don't nest this inside the dontCheckCollision == false. 


else if (objBullet.dontCheckCollsion == true)
    {
        //Not sure what to put here ... I want to reactivate the ability to collide again if it hits a different enemy after hitting this one..
    }

I didn't type it that way in my example. ;) 

Should be:


if (objBullet.dontCheckCollision == false) // So its 'okay' to check collision of this bullet..
{
    if (place_meeting(x,y, objBullet)) // Checking if Enemy is meeting a bullet
    {
        if(sprite_index = sprEnemySmall) // Small Enemy Takes More Damage (pain) from "gun" bullets
        {
            if other.sprite = "gun"
            {
                pain = other.damage * 2;
            }
            else pain = other.damage
        }

    	if(sprite_index = sprEnemyMedium) // Medium Enemy Takes More Damage (pain) from "flame" bullets
    	{
        	if other.sprite = "flame"
        	{
            	pain = other.damage * 2;
        	}
        	else pain = other.damage
    	}

    	if(sprite_index = sprEnemyLarge) // Large Enemy Takes More Damage (pain) from "missile" bullets
    	{
        	if other.sprite = "missile"
        	{
            	pain = other.damage * 2;
        	}
        	else pain = other.damage
    	}
    
    	objBullet.dontCheckCollsion = true;  // Telling it not to check collision again...      
    } 
}
else if (objBullet.dontCheckCollsion == true)
{
//Not sure what to put here ... I want to reactivate the ability to collide again if it hits a different enemy after hitting this one..
}

 

Again, I might be misunderstanding the question as I'm not too alert right now.

Programmer and 3D Artist

Advertisement
2 minutes ago, JoeJ said:

collision is triggered again you know this bullet already has done damage to this object

That's the one! Sorry my title skills are abysmal! I want have a bullet that passes through enemies which i want it to do damage once per enemy hit, another bullet will hit and destroy itself so I don't need to worry about that one. My 'flame' bullet will keep moving without destroying itself, It does damage as it passes through the enemies which is good but it damages multiple times, I want it to do damage only once per 'instance' ? I think that's the key word I need to use ? BUT the if a different bullet of the same type from another tower also hits this enemy, I want that to be able to damage once and move on regardless of the state of the first bullets damage/collision stuff if that makes sense?

 

 

Check out my game '3NDL3ZZ: Base Defense' A simple militant styled, tower defense game.

GameDev.Net Project Page

Just now, CyberFlash said:

That's the one! Sorry my title skills are abysmal! I want have a bullet that passes through enemies which i want it to do damage once per enemy hit, another bullet will hit and destroy itself so I don't need to worry about that one. My 'flame' bullet will keep moving without destroying itself, It does damage as it passes through the enemies which is good but it damages multiple times, I want it to do damage only once per 'instance' ? I think that's the key word I need to use ? BUT the if a different bullet of the same type from another tower also hits this enemy, I want that to be able to damage once and move on regardless of the state of the first bullets damage/collision stuff if that makes sense?

 

 

Then do what @JoeJ suggested. :) It will work fine.

As long as each enemy has some form of an ID which you can check against, then when the bullet goes to check for collision, if that ID is on your hit list then do nothing...

Example..

Assuming Enemy1 has a variable called id=1, and so forth. Your bullet can store a list of hit IDs in a list. When you go to check for collision just see if object1.listContains(enemy.id) ect...

Hope this helps! If I'm still off, then let me know! :D 

Programmer and 3D Artist

2 minutes ago, CyberFlash said:

'instance' ? I think that's the key word I need to use ?

No, 'instance' can mean so many things :) I got you right from the beginning. The code should look like this:


	for each collision involving a lasting bullet
	{
	if (bullet.lastHit != npc.id)
	{
	npc.health -= bullet.damage;
	bullet.lastHit = npc.id;
	}
	}
	

 

 

14 minutes ago, Rutin said:

long night and got up early..

Definitely a party life! Anyway yeah so the getting of the ID, I'm not sure how to give each one an id when they're created as it'll all be the same but would this be where 'for' could come in? I did something like this for the towers to be able to shoot the enemies ? I dunno if this would be the right approach for giving them all values or not though? 

if (instance_exists(objEnemy))
{
    enemyId = 0;
    
    for (var i = 0; i < instance_number(objEnemy); i++)
    {
        var enemy = instance_find(objEnemy, i);

   }
}

Something like this perhaps? I'm not really sure how to keep track of it ? -.- Like I have done this before for the bullets to give them an ID like Gun, Flame and Missile to determine damage types against enemyTypes but these are like 'general ID's ', Wait Game Maker has something called 'id' that should give me the values already? I just need to compare them somehow perhaps?

 

 

 

8 minutes ago, JoeJ said:

.id

that's the one! :D Okay yeah cool I think I got it now, guna quickly try not breaking everything :P

Check out my game '3NDL3ZZ: Base Defense' A simple militant styled, tower defense game.

GameDev.Net Project Page

This topic is closed to new replies.

Advertisement