XNA collision weird behavior - c#

I'm reading the book "Learning XNA 4.0", and I'm in the object oriented design part. I'm having a weird problem with the collision of 2 rectangles.
I have a list of automateSprite and a Player class both derived from the class Sprite.
In the update method I'm checking the play and the aotomatedSprite rectangles are touching each other, now when I got over the list I have a string called touching that represents the collision.
My problem is the veriable touching, only change if the player Sprite touch the last automateSprite in the list.
The code that the book offer for testing is to do Game.Exit() if any collison was found.
That work on every automatedSprite in the list, but when I change it to my simple test, it acts like I only check the last item from a list of 4 automatedSprite.
here is the code:
string touching = "";
public override void Update(GameTime gameTime)
{
// TODO: Add your update code here
player.Update(gameTime, Game.Window.ClientBounds);
foreach (Sprite sprite in spriteList)
{
sprite.Update(gameTime, Game.Window.ClientBounds);
if (sprite.collisionRect.Intersects(player.collisionRect))
touching = "touching";
else
touching = "not touching";
}
base.Update(gameTime);
}
public override void Draw(GameTime gameTime)
{
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend);
spriteBatch.DrawString(font, touching, Vector2.Zero, Color.Red);
player.Draw(gameTime, spriteBatch);
foreach (Sprite sprite in spriteList)
{
sprite.Draw(gameTime, spriteBatch);
}
spriteBatch.End();
base.Draw(gameTime);
}
Edit-------------------------------------------------------------------------
solution:
I ask it in the game devlopment section and I got an answer.
I had to have a break; in the foreach loop so it will not keep going after the it found a collison.

It is because your code constantly overwrites the touching variable, so in the end only the last result is presented in it.
Before the foreach, reset the touching variable, with touching = ""; and extend the if like this:
if (sprite.collisionRect.Intersects(player.collisionRect) || touching == "touching")
This way you will get "touching" if any of the sprites are touching your players sprite.

Related

Damage Over Time Area code not working, while using very similar code to Ground Check that is working?

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

Detecting collisions between two separate animations

My animations enters a state and it's collision with enemy projectiles either defends himself or gets hurt depending on what animation he is currently in. I'm trying to detect collisions with the ONTRIGGERENTER function and boxcollider2D's but it's not having any affect. I want to figure out how to correctly facilitate trigger enters and collisions between these animations.
I've already tried giving my sprite a tag and calling that tag when the ONTRIGGERENTER function is called but it didn't work. I also tried a more complicated way of calling the tag of the collider but that didn't work either. How do you access the trigger when it's an animation?
string DefenceAnimTag = "Defending";
string DestroyEnemTag = "Eliminated";
//This code is connected to the enemy projectile and trying to
//sense when it's collided with the player
void OnTriggerEnter(Collider2D col)
{
if (col.tag == Defending)
{
GetComponent<Animator>().SetBool("Elim", true);
}
else { //deal damage to the player }
}
//The first method didn't work so I tried a second method.
//Here is an alternative attempt at detecting triggers in
//animations.
void OnCollisionStay2D(Collider2D col)
{
if (col.gameobject.CompareString("Defending"))
{
GetComponent<Animator>().SetBool("Elim", true);
}
}
//This method didn't work either even though the Animation
//WOULD be Defending
I expected enemy projectiles to collide with my player when he was defending himself and get defeated. I knew that it was working when the Enemy projectiles transition into their Elim state, where they get defeated by enemy defenses, however they made collisions and then continued unaffected.
Okay, okay, I figured it out. Because a Gameobject can have many animations to it, you cannot go by the tag that the GameObject in the inspector has. You have to go by the title of the Animations that is currently playing. In order to access the animation currently playing we must use the following code:
AnimatorClipInfo[] m_AnimClipInf;
string m_ClipName;
void Start()
{
//Set up our projectile for possible Elimination
//upon Collision
Getcomponent<Animator>().SetBool("Elim", false);
}
void OnTriggerEnter2D(Collider2D col)
{
m_AnimClipInf = col.GetComponent<Animator>
().GetCurrentAnimatorClipInfo(0);
m_ClipName = m_AnimClipInf[0].clip.name;
if (m_ClipName == "Defending")
{
GetComonent<Animator>().SetBool("Elim", true);
//Projectile gets eliminated
}
}

How do I detect if a sprite is touching another sprite

How do I determine if a sprite (Sprite1) if on top of (Sprite2)
I need this to switch levels when you touch another sprite with your sprite.
I tried:
void OnCollisionEnter2D(Collision2D other)
{
//code to run
}
But this made it so that everything it touched ran the code. :(
You should attach the script that contains oncollisioneneter to your sprite1 game object for example and in your sprite 2 game object add a tag like sp2 or whatever you want , then in your script when collision happens you check if the object that sprite one collided with is sprite 2 you check it with tag property of sprite 2 like this
void OnCollisionEnter2D(Collision2D other)
{
if(other.gameObject.tag == "sp2")
{
//put your change levelcode here
}
}
Your halfway there. Right now you are running the code whenever the sprite collides with another 2D collider. What you then need to do is determine if that collider is the one attached to the particular sprite we want to trigger the code.
Tag the object containing your level exit, and check for the tag when you get a hit.
void OnCollisionEnter2D(Collision2D other)
{
if(other.gameObject.tag == "levelExit")
{
Debug.Log("next level");
}
}

Bullet list collision isn't colliding with enemy list

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

How to set the position of a sprite to the position of another sprite?

Is it possible to set the position of a sprite to the exact same position of another sprite which is being moved.
So I want to set the "sprite.position" to a the same position that my class Character is in:
Character.cs:
class Character
{
Texture2D texture;
public Vector2 position;
Vector2 velocity;
public Character(Texture2D newTexture, Vector2 newPosition)
{
texture = newTexture;
position = newPosition;
}
public void Update(GameTime gameTime)
{
position += velocity;
}
public void Draw(SpriteBatch spriteBatch)
{
spriteBatch.Draw(texture, position, Color.White);
}
}
Game1.cs:
public class Game1 : Microsoft.Xna.Framework.Game
{
Bullet bullet;
Character player;
protected override void Initialize()
{
allSprites = new List<ISprite>();
allSpriteObstakels = new List<ISprite>();
bullet.position = Character.position; // not working
base.Initialize();
}
}
As the comments have suggested, when you say "it's not working" you need to be clear about what "not working" actually means. For example, are you getting a compile error? Are you getting a runtime exception? Is the game running but it isn't doing what you expect (logical error)?
That said, here's my best guess as to what might be going on:
I don't know if the code above is complete but the bullet and player are not instantiated anywhere. You need to "new" the instances before you use them.
You are using the "bullet.position" where bullet is an instance, but then you're using "Character.position" where Character is a class. Did you intend to use "player.position" instead?
This code will only run once, which means the bullet will be set to the same position as the character. If you intend for the bullet position to always be the same as the character, then you need to continually re-assign the bullet.position value every frame.
But the most important thing is to learn to ask questions so that the community here can help you out.

Categories