Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Tank doesn't Shoot Multiple Bullets  (Read 7543 times)

0 Members and 1 Guest are viewing this topic.

zuryx

  • Newbie
  • *
  • Posts: 4
    • View Profile
Tank doesn't Shoot Multiple Bullets
« on: February 02, 2012, 07:29:30 am »
Hey guys, I'm creating a little game using C++ and SFML. Ran into a little problem trying to make my tank shoot more than one bullet. Hope you guys can give me some help. I've attached a small snippet of code that recreates the problem.


Loop to shoot

Code: [Select]

if(Game::GetInput().IsKeyDown(sf::Key::Space))
{
PrimaryWeapon PW1;
sf::Vector2f pos = PlayerTank::GetPosition();
if(!Game::GetGameObjectManager().Get("SmallBullet"))
{
PW1.Fire(pos);
}

}


Code: [Select]

void PrimaryWeapon::Fire(sf::Vector2f pos)
{


SmallBullet* i = new SmallBullet;
i->SetPosition(pos.x, pos.y);
Game::GetGameObjectManager().Add( "SmallBullet", i);

}


Code: [Select]

void SmallBullet::Update(float elapsedTime)
{

GetSprite().Move(Velocity * elapsedTime, 0);
sf::Vector2f pos = GetPosition();
if (pos.x >= Game::SCREEN_WIDTH)
{
Game::GetGameObjectManager().Remove( "SmallBullet");
}
}


the GameObjectManager in the code is a std::map that automatically draws and updates all items added to it, in the game loop. Remove() deletes the pointer to the object and then entry in the map.

Edit:: the code is supposed to cause the bullet to be deleted if it hits the side of the screen. Once it is deleted, a new bullet can be created and "shot" again. In my program however, once it hits the side of the screen, it disappears and no new bullets are created when spacebar is pressed.

TheCake

  • Newbie
  • *
  • Posts: 19
    • View Profile
Tank doesn't Shoot Multiple Bullets
« Reply #1 on: February 02, 2012, 12:50:04 pm »
Hi

In your Fire method, you add "SmallBulleti"

Also, the bullet may not be correctly removed. Could you show us your GameObjectManager::Remove() method ?

zuryx

  • Newbie
  • *
  • Posts: 4
    • View Profile
Tank doesn't Shoot Multiple Bullets
« Reply #2 on: February 02, 2012, 01:38:07 pm »
hi, yes because the gamobject manager stores the items in a std::map, which stores an item with an associated unique label. the label for the bullet is "SmallBulleti". The GameObjectManager::Remove() is as shown below.


Code: [Select]

void GameObjectManager::Remove(std::string name)
{
std::map<std::string, VisibleGameObject*>::iterator results = _gameObjects.find(name);
if (results != _gameObjects.end())
{
delete results->second;
_gameObjects.erase(results);
}
}


Edit:: _gameObjects is the name of my variable, of type GameObjectManager

2ndEdit: Sorry TheCake, I saw what you meant by "SmallBulleti". That I corrected it, but a new problem arises.

zuryx

  • Newbie
  • *
  • Posts: 4
    • View Profile
Tank doesn't Shoot Multiple Bullets
« Reply #3 on: February 02, 2012, 04:04:08 pm »
So after correcting the mistake pointed out by TheCake, thanks :), I get a new error when the bullet hits the side of the screen. This Pops up:

http://imageshack.us/photo/my-images/821/errorgl.png/


the debugger shows an exception thrown as below:

Code: [Select]

// throw -- terminate on thrown exception REPLACEABLE
#define _HAS_EXCEPTIONS 0
#include <cstdio>
#include <cstdlib>
#include <exception>
#include <crtdbg.h>

_STD_BEGIN

#ifdef _DEBUG
_CRTIMP2_PURE void __CLRCALL_PURE_OR_CDECL _Debug_message(const wchar_t *message, const wchar_t *file, unsigned int line)
{ // report error and die
        if(::_CrtDbgReportW(_CRT_ASSERT, file, line, NULL, message)==1)
        {
            ::_CrtDbgBreak();
        }
}
_CRTIMP2_PURE void __CLRCALL_PURE_OR_CDECL _Debug_message(const unsigned short *message, const unsigned short *file, unsigned int line)
{ // report error and die
        _Debug_message((wchar_t *) message, (wchar_t *) file, line);
}

#endif

_STD_END

jone

  • Newbie
  • *
  • Posts: 12
    • View Profile
Tank doesn't Shoot Multiple Bullets
« Reply #4 on: February 03, 2012, 04:20:48 pm »
You're not showing us the right code. :) In fact, I'm not sure what code you're showing us as that seems to be a part of Microsoft Visual C++ library code, but you didn't tell us the file name. :)

How familiar are you with debugging? You might want to check out some tutorials on the subject. For this problem, check out the information on the call stack here: http://www.learncpp.com/cpp-tutorial/a5-debugging-your-program-watching-variables-and-the-call-stack/

The tutorial is using the VS2005 IDE, so it might differ slightly from what you'll see.

Using the call stack, figure out what line of your code is causing the debug assertion to fail, and see if you can't figure out what's wrong with your code.

TheEnigmist

  • Full Member
  • ***
  • Posts: 119
    • View Profile
Tank doesn't Shoot Multiple Bullets
« Reply #5 on: February 03, 2012, 11:35:12 pm »
For the error you are deleting somthing inside your map iterator for loop . I got the same error some week ago.
You do something like this:
Code: [Select]
for(std::list<T>::iterator it= list.begin(); it!=list.end(); ++it)
{
   do something
   if( condition)
      list.erase(it);
}

For working with it you have to do something like this:
Code: [Select]
for(std::list<T>::iterator it= list.begin(); it!=list.end();)
{
   if(condition)
      list.erase(it);
   else{
      do something
      ++it;
   }
}

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6286
  • Thor Developer
    • View Profile
    • Bromeon
Tank doesn't Shoot Multiple Bullets
« Reply #6 on: February 04, 2012, 12:24:31 am »
Quote from: "TheEnigmist"
For working with it you have to do something like this:
Code: [Select]
[...]
      list.erase(it);
[...]
You have to assign the return value of erase(), otherwise it becomes invalid.

For associative containers, you can use the post-fix version of operator++.
Code: [Select]
map.erase(itr++)
For sequential, continuous containers, you had better use std::remove() and std::remove_if(), as these STL algorithms come with linear instead of quadratic complexity.
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

TheEnigmist

  • Full Member
  • ***
  • Posts: 119
    • View Profile
Tank doesn't Shoot Multiple Bullets
« Reply #7 on: February 04, 2012, 08:07:06 pm »
Quote from: "Nexus"
Quote from: "TheEnigmist"
For working with it you have to do something like this:
Code: [Select]
[...]
      list.erase(it);
[...]
You have to assign the return value of erase(), otherwise it becomes invalid.


Oh yes, my fault:
Code: [Select]
[...]
it=list.erase(it);
[...]

I do like this and it works, so i think is good, isn't it?

zuryx

  • Newbie
  • *
  • Posts: 4
    • View Profile
Tank doesn't Shoot Multiple Bullets
« Reply #8 on: February 05, 2012, 09:11:25 am »
I tried your suggestion but it doesn't fix it. I still get the Same Error. Thnx for all the help though guys, I really appreciate it. I'll be putting this project on hold for now though, work requires me to focus on php and mysql instead =(

TheEnigmist

  • Full Member
  • ***
  • Posts: 119
    • View Profile
Tank doesn't Shoot Multiple Bullets
« Reply #9 on: February 06, 2012, 02:05:57 pm »
Try to post your complete code, so some1 can help you better!

stefanpunt

  • Newbie
  • *
  • Posts: 3
    • View Profile
Re: Tank doesn't Shoot Multiple Bullets
« Reply #10 on: May 02, 2012, 07:06:45 pm »
Hi,

I know this is not my topic, and that it's probably in the wrong board, but I have exactly the same problem.

My gameobjects are managed by the GameObjectManager. This is the update iteration:

Code: [Select]
void GameObjectManager::UpdateAll(float elapsedTime)
{
std::map<int, GameObject*>::const_iterator itr = gameObjects.begin();

while (itr != gameObjects.end())
{
itr->second->Update(elapsedTime);
itr++;
}
}

It calls the Update() method of Block:

Code: [Select]
void Block::Update(float elapedTime)
{
sf::Time time = clock.getElapsedTime();

if (time.asSeconds() >= 5.0f)
{
Game::GetGameObjectManager().Remove(id);
}
}

After 5 seconds, it is giving me the 'debug assertion failed map set iterators incompatible' error.

Remove() method:

Code: [Select]
void GameObjectManager::Remove(int id)
{
std::map<int, GameObject*>::iterator result = gameObjects.find(id);

if (result != gameObjects.end())
{
delete result->second;
gameObjects.erase(result);
}
}

I've noticed that there is nothing wrong with the Remove() method. When I make Block delete not his own 'id' but e.g. 'id + 1' it deletes that block without any problem. It seems like these objects just can't delete itself.

Any help would be appreciated :)!
« Last Edit: May 02, 2012, 07:12:29 pm by stefanpunt »

stefanpunt

  • Newbie
  • *
  • Posts: 3
    • View Profile
Re: Tank doesn't Shoot Multiple Bullets
« Reply #11 on: May 04, 2012, 03:16:44 pm »
:(?

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6286
  • Thor Developer
    • View Profile
    • Bromeon
Re: Tank doesn't Shoot Multiple Bullets
« Reply #12 on: May 04, 2012, 05:31:05 pm »
I know this is not my topic, and that it's probably in the wrong board, but I have exactly the same problem.
You should nevertheless open a new thread, you can still reference the old one in your post.

You remove objects from the map while you iterate over it, this invalidates the current iterator. Either postpone the removal by using flags in the objects, or make sure the iterator remains valid:
for (auto itr = map.begin(); itr != map.end(); /* nothing here */)
{
    if (/* object shall be removed */)
        map.erase(itr++);
    else
        ++itr;
}
« Last Edit: May 04, 2012, 05:38:45 pm by Nexus »
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

stefanpunt

  • Newbie
  • *
  • Posts: 3
    • View Profile
Re: Tank doesn't Shoot Multiple Bullets
« Reply #13 on: May 04, 2012, 09:50:35 pm »
You sir, are indeed a Hero Member.

Thanks :)

 

anything