Author Topic: Timing and monster issues  (Read 10089 times)

sausage

  • Newcomer
  • Posts: 12
  • Karma: +0/-0
    • View Profile
    • Email
Timing and monster issues
« on: December 01, 2010, 05:16:55 PM »
So, I'm not a very good programmer, and I decided to make a roguelike a couple days ago.

I have two problems.

First, the timing, it feels weird using a for loop to slow down the game so you aren't just flying across the screen.  I could use some help making it like crawl, where you can hold the arrow and go quickly after a second or so, or rapidly press the arrow for precision.

Second, my monsters, I have them recognizing the player, but not each other.  I need help setting up how I should initialize them so that they can see each other.  I am also having issues with their death, currently it's a function that puts them in the top left corner and changes their symbol to a wall and prevents them from moving, but I know that's probably not going to work if I want to respawn monsters.

Krice

  • (Banned)
  • Rogueliker
  • ***
  • Posts: 2316
  • Karma: +0/-2
    • View Profile
    • Email
Re: Timing and monster issues
« Reply #1 on: December 01, 2010, 06:24:14 PM »
First, the timing, it feels weird using a for loop to slow down the game so you aren't just flying across the screen.

The speed depends on the keyboard/event system. The easiest way to fix this is use a keyboard input that is waiting for input and using automatic keyboard repeat values. Whatever system you are using should have that kind of routines ready so you don't have to write your own low level routines.

ps. It could be helpful to reveal the programming language/system you are using.

sausage

  • Newcomer
  • Posts: 12
  • Karma: +0/-0
    • View Profile
    • Email
Re: Timing and monster issues
« Reply #2 on: December 01, 2010, 08:34:22 PM »
Thanks for the reply. :)

I'm using the GetAsyncKeyState() function in c++

dephbokks

  • Newcomer
  • Posts: 37
  • Karma: +0/-0
    • View Profile
Re: Timing and monster issues
« Reply #3 on: December 01, 2010, 10:23:06 PM »
Why do you want the monsters to 'recognize' each other? Not that they should or shouldn't... I'm just trying to figure out what you're trying to achieve.

Are you trying to avoid pathfinding collisions? Or should they attack, help, work together, each other?

Unfortunately ai can get pretty complicated which is why it's best to spell out the functionality that you're after and also to examine how feasible it is. Also, complicated interactions are not worth it if the player cannot detect or observe these complex interactions.

The death issue: since you're using C++, I will describe what I do. Maybe you will find it useful.

Firstly, I store a monster pool. This is an available pool of monsters whereby I can randomly select them based on certain criteria, like which level of the dungeon the player's on, the rng, etc.

Then I store a list of active monsters on the player's level. These monsters are updated each game tick with an update method and rendered, if on screen, via their render method. The list of active monsters are chosen from the monster pool when generating a new level.

For these pools, I use a std::vector of boost smart pointers. The nice thing about these smart pointers is that they garbage collect automatically. That way when they are not referenced anymore, they are cleaned up. They imo are the best tool for the job.

I then iterate over the container updating each monster and removing them from the game if applicable.

For example:

Code: [Select]
void MonsterMgr::Update()
{
for ( std::vector< boost::shared_ptr<Monster> >::iterator i = monsters[currentLevel].begin(); i != monsters[currentLevel].end(); )
{
(*i)->update();

if ( (*i)->hp <= 0.0f )  // zero hitpoints or lower, delete; monster is dead.
{
i = monsters[currentLevel].erase(i); // remove dead monster
}
else
{
++i; // Only increment the iterator if you do not delete since
                               // the erase method returns the next iterator.
}
}
}




sausage

  • Newcomer
  • Posts: 12
  • Karma: +0/-0
    • View Profile
    • Email
Re: Timing and monster issues
« Reply #4 on: December 01, 2010, 10:30:02 PM »
Recognize as in be able to tell if they're there, currently they just stack on top of one another.

sorry if that's not the right word, took it right out of the 15 steps guide.

dephbokks

  • Newcomer
  • Posts: 37
  • Karma: +0/-0
    • View Profile
Re: Timing and monster issues
« Reply #5 on: December 01, 2010, 10:38:53 PM »
Oh I see.

Let's say each of your dungeon level is a grid of squares DX = DY = 20. So you have a DXxDY dungeon which is 20x20 squares.

You can then make an array:

Code: [Select]
bool occupied[DX][DY]. Initialize all values to false. If the tile is empty, set it to false; if occupied by a monster set it to true. When each monster moves set the current square
Code: [Select]
occupied[x][y] to false and the new square
Code: [Select]
occupied[x'][y'] to true. That way before the monster moves, you can check for a valid move by checking the
Code: [Select]
occupied[x][y] array.

So if a monster tries to move into an occupied square you can run a valid move check. If the square is already occupied, the monster must wait for the square to be vacant or navigate around the obstruction.

This is a simple solution, but it works. You can also look into spatial hashing, collision detection, etc., but this simple method is easy to use.
« Last Edit: December 01, 2010, 10:42:24 PM by dephbokks »

sausage

  • Newcomer
  • Posts: 12
  • Karma: +0/-0
    • View Profile
    • Email
Re: Timing and monster issues
« Reply #6 on: December 01, 2010, 10:50:04 PM »
ok, the issue isn't how to check it, it's how to set up the monster so that I can check it.

I haven't figured out how to have a specific object read from another instance of it's class

dephbokks

  • Newcomer
  • Posts: 37
  • Karma: +0/-0
    • View Profile
Re: Timing and monster issues
« Reply #7 on: December 01, 2010, 11:08:38 PM »
You have to pass a pointer/pointers of the monsters on the level to each monster's update function, for example.

So, if you have something like:
Code: [Select]
class Monster
{
     Update();
};

You'd modify it to:
Code: [Select]
class Monster
{
     Update(Monster* m); // you are now passing a pointer of another monster to the monster
                                      // update method.
};

If you are using an STL container (recommended) you'd write:
Code: [Select]
class Monster
{
     Update(std::vector<Monster*> monsterList); // you are now passing
                                                                            // a vector of Monster pointers
};

That way, each individual monster would 'know' about all its fellow monsters.

If you are using smart pointers (again suggested) you'd write:
Code: [Select]
class Monster
{
     Update(std::vector< boost::shared_ptr<Monster> > monsterList);
    // you are now passing a vector of Monster smart pointers (boost)
};

The above is addressing your statement: "I haven't figured out how to have a specific object read from another instance of it's class."

However, if you determine where each monster can move by passing a vector of monsters to each individual monster, this is computationally inefficient. Instead, the bool occupied array method is better since you are only tracking each monster's occupation once ~O(n) time rather than O(n^2) by passing a vector to each monster.

I put the bool occupy array in the map or dungeon class and pass it to each monster's update like:

Code: [Select]
class Monster
{
     Update( bool occupy[DX][DY] );
      // pass the tile occupation information to each monster.
      // each monster is responsible for updating its position in this array
      // and deciding how to navigate around a potential obstacle or wait for
      // it to be vacant.

};

sausage

  • Newcomer
  • Posts: 12
  • Karma: +0/-0
    • View Profile
    • Email
Re: Timing and monster issues
« Reply #8 on: December 01, 2010, 11:29:17 PM »
Alright sweet! I'll take a look at it and let you know how it goes :)

Krice

  • (Banned)
  • Rogueliker
  • ***
  • Posts: 2316
  • Karma: +0/-2
    • View Profile
    • Email
Re: Timing and monster issues
« Reply #9 on: December 02, 2010, 09:20:02 AM »
I'm using the GetAsyncKeyState() function in c++

It's a Windows function, not C++ one. It seems to constatly check if a key is pressed so it's not that clever function for a turn based roguelike.