Okay, so I'm making a 2D platform game and I'm coming to the finishing stages. I've got the bullets firing, and my AI working etc. However I'm having an issue where when I try and see if the bullet's bounding box is colliding with the enemies, then it should kill the enemies. However they don't collide - I have to checked by console.writeline to see if the boundingbox for the spell is getting updating, which it is, and the same for the enemy. the code for the collision is this:
foreach (EnemyClass enemy in enemies)
{
for (int i = 0; i < spells.Count; i++)
{
if (enemy.collisionBox.Intersects(spells[i].boundingBox))
{
Console.WriteLine("Collision");
enemy.enemyHP -= spells[i].damageToDeal;
spells.ElementAt(i).isVisible = false;
}
if (enemy.enemyHP == 0)
{
enemy.isAlive = false;
}
}
}
This is the Update function that is in the spell class:
public void Update(GraphicsDevice graphics)
{
boundingBox = new Rectangle((int)position.X, (int)position.Y, 15, 15);
}
Fixed it - thanks for peoples help. It was a problem with the y-coordinate of the spells bounding box - I never thought to check it since collision in my game is all based around the x coordinate
Related
I'm very new to C# and Unity and am working on a simple platformer for a school project. I'm currently trying to get a piece of group that does damage over time to the player. To detect whether the player is on this piece of ground, I thought I could use the same code as I did for my ground check, but with altered variable names etc. However the ground check code works, and the detection for the damage over time doesn't and I have no idea why.
void CheckIfGrounded()
{
Collider2D collider = Physics2D.OverlapCircle(isGroundedChecker.position, checkGroundRadius, groundLayer);
if (collider != null)
{
isGrounded = true;
}
else
{
if (isGrounded)
{
lastTimeGrounded = Time.time;
}
isGrounded = false;
}
}
void CheckIfDOT()
{
Collider2D collider = Physics2D.OverlapCircle(isDOT.position, checkDOT_AreaRadius, DOT_AreaLayer);
if (collider != null)
{
damageOverTime = true;
}
else
{
damageOverTime = false;
}
}
The first thing is that you need to know how Physics2D.OverlapCircle works.
As in unity documentation, it says :
Checks if a Collider falls within a circular area.
The circle is defined by its centre coordinate in world space and by its radius.
It means that from one point, which is position, they will draw a circle have radius like the radius you use and if there is any collider is in that range, it will result in the collider2d, like your example.
You need to check :
Where is that point : In the player or in the obstacles ?
Is the circle big enough for collider to fall within ? ( depends on radius )
Try to use Debug.Log() to show if the function is executed normally
I would like some help with figuring this out as my brain is having a funny day today at what is the best way to go about this.
I have an OnDrawGizmos as follows
Transform parentBounds;
void OnDrawGizmos()
{
parentBounds = this.gameObject.transform;
Vector3 from;
Vector3 to;
for (int a = 0; a < parentBounds.childCount; a++)
{
from = parentBounds.GetChild(a).position;
to = parentBounds.GetChild((a + 1) % parentBounds.childCount).position;
Gizmos.color = new Color(1, 0, 0);
Gizmos.DrawLine(from, to);
}
}
This code is attached on a "parent" object which contains 4 empty game objects as follows
Which produces the following Gizmo (Drawing a square based on where I put the empty objects within the parent)
I can even add more points if I desire.
SO WHAT IS THE PROBLEM ?
What I need is that if the player is not within this box area, I want the player to be destroyed. I'm not sure what the best practice is for this , should I make an array to hold the xmin, ymax, etc. ? or should I generate a new position vector on every loop ? I've tried a few ways that are not giving me the results I want and I taught to ask for some assistance.
Thank you all in advance !
If this is a 2D game (which I assume it is), how about having a script, that has reference to the player object and...
a) game is not using physics
... a public Rect boundaries. On each Update() check if player is within the boundaries and if not - destroy it.
void Update()
{
if (!boundaries.Contains(playerObject.transform.position))
{
Destroy(playerObject);
}
}
b) game is using physics
... a BoxCollider2D with the following script
void OnColliderExit2D(Collider2D collider)
{
// If collider is player object -> destroy collider.gameObject
}
So I'm making a game where you evade enemies and trigger certain powerups that has various effects on the enemies. One of them is a bomb that explodes 4 seconds after the player collides with it, destroying all enemies within its radius as it explodes.
I think I've got everything figured out except the actual destroying of the enemy. I feel like the solution is so obvious but I just never learned the method. At this point the bomb object is destroyed upon explosion instead of the enemies, which I expected to happen, because Destroy(other.gameObject) just doesn't work in this context! What do I do??
private void OnTriggerEnter(Collider other)
{
if (other.CompareTag("Player"))
{
Debug.Log("player");
StartCoroutine(BombCountdownRoutine());
}
}
IEnumerator BombCountdownRoutine()
{
bombAudio.PlayOneShot(bombSound, 0.8f);
yield return new WaitForSeconds(4);
Collider[] hitColliders = Physics.OverlapSphere(transform.position, 10);
for (int i = 0; i < hitColliders.Length; i++)
{
if (hitColliders[i].gameObject.tag == "Enemy")
{
Destroy(gameObject);
}
}
}
I wrote a collision detection system for a game I am working on, and I am experiencing a weird glitch where, occasionally, projectiles will go through the player or walls scattered throughout the level. Because the projectiles can be fired at any angle, I decomposed the bounding box of each projectile into multiple, smaller bounding boxes that I then rotate around the center of the texture according to the rotation of the projectile in space. For some reason, occasionally a Spear projectile will go through the player or a wall even through others do not.
I use the following methods to determine the rotation of the texture and to translate the bounding boxes:
public double RotateToFaceTarget()
{
double rotation = Math.Atan2((double)_direction.Y, (double)_direction.X);
return rotation;
}
public List<BoundingBox> TranslateBoundingBox(List<BoundingBox> box, double rotation)
{
List<BoundingBox> newBounds = new List<BoundingBox>();
foreach (BoundingBox b in box)
{
Vector2 boundsOrigin = new Vector2(b.Pos.X + b.Size.X / 2, b.Pos.Y + b.Size.Y / 2);
Vector2 texOrigin = new Vector2(_pos.X + _texture.Width / 2, _pos.Y + _texture.Height / 2);
Vector2 newPosBasedOnOrigin = Vector2.Transform(boundsOrigin - texOrigin, Matrix.CreateRotationZ((float)rotation)) + boundsOrigin;
newBounds.Add(new BoundingBox(newPosBasedOnOrigin, b.Size));
}
return newBounds;
}
_direction is calculated by subtracting the position of the projectile from the target location and normalizing. I use this method to determine if the projectile is colliding with another entity:
public bool ProjectileCollision(Entity e, Projectile entity2)
{
if (entity2.CanCollide)
{
foreach(GameObject.BoundingBox b in entity2.BoundingBox)
{
foreach(GameObject.BoundingBox b2 in e.BoundingBox)
{
if (b2.Intersect(b) && (entity2.IgnoredEntities.Contains(e.Type) == false))
{
entity2.IsActive = false;
e.Health -= entity2.Damage;
return true;
}
return false;
}
}
return false;
}
return false;
}
And this is my Bounding Box Intersection method:
public bool Intersect(BoundingBox intersected)
{
if ((_pos.Y < intersected.Pos.Y + intersected.Size.Y) && (_pos.Y + _size.Y > intersected.Pos.Y) && (_pos.X + _size.X > intersected.Pos.X) && (_pos.X < intersected.Pos.X + intersected.Size.X))
{ return true; }
return false;
}
EDIT: On further testing, it seems that the projectile will always detect a hit if the player hits based on the top left corner ( which makes sense now that I look at my intersect code). Is there another way to re-write my Intersect method to use something more accurate than the top left corner?
EDIT2: I drew the hitboxes for certain objects, and this is one instance of when I catch the spear going through the player:
http://imgur.com/a/fAxZw
the player is the larger pink square. The hitboxes are not being translated correctly, but it shouldn't just stop working, for some and not others, right?
It could happen, because of high velocity and small object, projectile could fly through object. Beside of checking if objects are intersecting, you have to check if object will intersect, to check if object is in line of fire. You could achieve this by raycasting.
On those cases like your i had function that check if object is near other. Simple checking if object is inside of some radius of other object. If yes then i was checking if object is flying toward other object, and checking distance between them. When distance is really close then collision happened.
I'm currently writing a platforming game in XNA.
My collision testing currently operates by testing the bounding box of the player with every tile's bounding box by running through a foreach loop. However, I can't figure out how to test whether the player is NOT touching any blocks.
How would I run through my array and test for if they player isn't touching any blocks so that I can check if he is in mid air? Any help or advice would be greatly appreciated. Thank you in advance!
/////////////////////////////////////
My collision code is
if (personRectangle.TouchTopOf(newRectangle))
{
onGround = true;
test = false;
test2 = true;
}
The corresponding bool test is
public static bool TouchTopOf(this Rectangle r1, Rectangle r2)
{
return (r1.Bottom >= r2.Top - 1 &&
r1.Bottom <= r2.Top + (r2.Height / 2) &&
r1.Right >= r2.Left + (r2.Width / 5) &&
r1.Left <= r2.Right - (r2.Width / 5));
}
And this piece of code tests collision in the Game1.cs update.
foreach (CollisionTiles tile in map.CollisionTiles)
player.Collision(tile.Rectangle);
Which is a list of tiles in my map class
private List<CollisionTiles> collisionTiles = new List<CollisionTiles>();
XNA Rectangles have a built-in intersects method:
if (rect1.Intersects(rect2)){
...
}
just loop through the tile rectangles and call intersects on each one. To make it more efficient you should map the player coords onto world coords and determine the tiles nearest to the player, doing this you can narrow down the number of tiles you need to loop over.
EDIT: for clarification, you could have:
bool collision=false;
foreach (CollisionTiles tile in map.CollisionTiles) {
if(personRectangle.Intersects(tile.Rectangle)) {
collision =true;
break;
}
}
Then if collision is true you know there was a collision somewhere.
Unless you have a reason not to, keep it simple. Just keep track of how many things you collided with. If your count ends up being 0 then you didn't collide with anything.
Without worrying about modifying / optimizing any of the code you have, it could be something like:
int touchedCount = 0;
foreach (CollisionTiles tile in map.CollisionTiles)
{
if (player.Collision(tile.Rectangle))
{
touchedCount++;
}
}
if (touchedCount == 0)
{
//You did not collide with anything
}
Then inside your collision method do something similar to keep track of your checks and if you collided at all. This would probably be easiest using Rectangle.Intersects as the other answer suggests.