Having a problem to get values from different methods which contain different classes

Started by
14 comments, last by Lactose 8 years, 4 months ago
@dave thanks, I will try to fix those things when I get home

@phill Well yes I think that you are right, Im aware that I didnt study and practice even some what you experienced programmers call basics, I would say I know like basics of basics of C#, I made my first hello world program like 2 years ago and then learned some more things, but yeah I didnt cover everything and I just didnt practice some things I just read, but to get to my point Im a person that loses motivation fast but Im interested in programming to that degree that I want to point my career in that direction, so a week ago I started fooling around with XNA(MONOGAME) and well I learned sone things along the way and I just find game development (simple 2D game) a great way to get myself more deeply in peogramming becouse motivation loss is not the case when Im (trying to) making games, Im thinking about fooling around xna for a while with 2D games abd after that Im planning to study c# more (before I get to 3D game development) any feedback from experienced programmers is welcome, thanks on helping me with my code everyone I really appreciate it

Sorry for my bad english :)
Advertisement

It is possible that the error messages you were getting were because you were calling the "isHit" method incorrectly. In your current code, you'd have to call it like this:

if (someEnemyObject.isHit(someBulletObject, someEnemyObject, someBoolean))
{
   // There was a hit!
}

Note that the boolean parameter doesn't do anything (it is assigned to and returned), so we can remove it from the "isHit" method:

public bool isHit(Bullet b, Enemy e)
{
    if (b.position.X == e.ePosition.X && b.position.Y == e.ePosition.Y)
    {
        return true;
    }
    else
    {
        return false;
    }
    
}

Now to call it:

if (someEnemyObject.isHit(someBulletObject, someEnemyObject))
{
   // Hit!
}

It is now a bit odd to have to pass the enemy object to the method in two ways, the explicit parameter but also using the "this" mechanism (by calling the method on a given object).

There are a couple of solutions to this, but given that this logic crosses two different objects, we can just move this logic into the game class where the two different objects are interacting anyway:

private bool isHit(Bullet b, Enemy e)
{
    if (b.position.X == e.ePosition.X && b.position.Y == e.ePosition.Y)
    {
        return true;
    }
    else
    {
        return false;
    }
    
}
 
 
protected override void Update(GameTime gameTime)
{
    if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
        Exit();
 
    if (Keyboard.GetState().IsKeyDown(Keys.Space) && pastKey.IsKeyUp(Keys.Space))
    {
        Shoot();
    }
 
    pastKey = Keyboard.GetState();
 
    // Level Check ----- Level Check ----- Level Check ----- Level Check ----- Level Check -----
 
    Enemyss();
 
    // Updates
    UpdateBullet();
    pla.Update();
    foreach (Bullet bullet in bullets)
    {
        foreach (Enemy enemy in enemies)
        {
            if (isHit(bullet, enemy))
            {
                // There was a hit!
                // Maybe do something like enemy.TakeDamage();
            }
        }
    }
    base.Update(gameTime);
}

If your game class starts getting very long, you can move all the bullet and enemy game logic handling into a separate class, e.g. "World" or something.

A god design rule of thumb is to try not to let too many classes know about the overall program state. So try keep the bullet and enemy class to simple objects that don't really know or care about the existence of other game objects, and just rely on higher level parts of the program to inform them about interesting events from the outside world (like having an enemy.TakeDamage() method for example).

Alright I made something and it doesnt show any errors and no errors appear while debuging expect my isHit checking doesnt work, here is what i did:


public bool isHit(Bullet b, Enemy e)
        {
            
            if (b.position.X == e.ePosition.X  && b.position.Y == e.ePosition.Y)
            {
                return true;
            }
            else
            {
                return false;
            }
            
        }

isHit bool method, nothing wrong here, and then in Game1.cs, here is my Enemys() method that is called in Game1.cs Update():


 public void Enemys()
        {
            Enemy enemy = new Enemy(Content.Load<Texture2D>("Enemy"), new Vector2(e_x, 100), new int());            
            enemy.Health = 50;

            if (enemys.Count() < 3)
            {
                enemys.Add(enemy);
                e_x += 100;
            }

            foreach (Bullet bullet in bullets)
            {
                if (enemy.isHit(bullet, enemy))
                {
                    enemy.Health -= 5;
                    bullet.isVisible = false;
                }
            }

            for (int i = 0; i < enemys.Count(); i++)
            {
                if (enemy.Health < 1)
                {
                    enemys.RemoveAt(i);
                    i--;
                }
            }
            
        }        

So yeah I have been shothing at them for a minute and nothing happens hahah, I even created text above enemys


foreach (Enemy enemy in enemys)
            {
                enemy.Draw(spriteBatch);
                spriteBatch.DrawString(font, "Health " + enemy.Health, new Vector2((enemy.ePosition.X), (enemy.ePosition.Y + 10)), Color.Black);
            }

To see if Health will decrease but no it doesnt :/

Your check "b.position.X == e.ePosition.X && b.position.Y == e.ePosition.Y" only marks a hit if both positions are precisely the same upto somewhere around 7 digits, ie it's like being equal to each other within 1/1,000,000 of a meter (or foot, or whatever you use as unit of length in your country). That doesn't very happen often smile.png

try something like


public bool isHit(Bullet b, Enemy e) {
    float size = 0.1;
    float dx = b.position.X - e.ePosition.X;
    float dy = b.position.Y - e.ePosition.Y;
    if ((dx > -size && dx < size) && (dy > -size && dy < size)) {
        return true;
    } else {
        return false;
    }
}

"dx" is the difference between X positions of the enemy and the bullet.

"dy" is the difference between Y positions of the enemy and the bullet.

(think of "size" as a small number)

if dx close to zero (less than a small number around 0), and dy close to zero (less than a small number around 0), then mark it as a hit.

If you make "size" smaller, you increase the needed accuracy of hitting, if you make "size" bigger, you decrease accuracy.

Yes, you definitely don't want to use floating point equality. I was going to mention about bounding box collisions but it slipped my mind, but Googling for "XNA sprite collision" or "XNA bounding box collision" should return some useful results.

In addition to the accuracy issue when comparing position, there's also this:


Enemy enemy = new Enemy(Content.Load("Enemy"), new Vector2(e_x, 100), new int());

//Other code goes here...

foreach (Bullet bullet in bullets)
{
	if (enemy.isHit(bullet, enemy))
	{
		enemy.Health -= 5;
		bullet.isVisible = false;
	}
}

You aren't testing against the enemies in your "enemys" list.

You're testing to see if the bullets collide with a newly created enemy.

You need to check every bullet against every enemy in your "enemys" list*.

It also seems wrong to me creating a new instance of Enemy every time the function is called, and then only adding it if less than 3 exist in your list.

Check first, then only create & add if needed.

*Note that there are better ways of dealing with this later on, but for now a brute force way should be sufficent.

Hello to all my stalkers.

This topic is closed to new replies.

Advertisement