gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

C/C++ > getting funky results from movement checker

#172412 - zelbo - Fri Feb 05, 2010 2:21 am

i probably need to start from scratch on this one. since i'm just working with hard-coded maps for now, i built a function to read the map and build an array of tile information (passable, block line of sight...) to be used in my movement checker. Maybe i should just read the map value and evaluate each tile from that? I'm planning to implement a bitset for this, but i'm not sure i need it. Anyway, i forgot to ever call this function after i made it, so i went and made a bunch of changes trying to fix it when it didnt work. I've tried to backtrack, but now it is acting very strange.
At first, it would not stop my character from moving at all, and the checkspace function was returning 0 all the time. So i changed the else condition of my array builder to be false, which should make all movement impossible. But it makes just a couple of seemingly random tiles and an entire row towards the middle of the map impassable. It does return values now, and i'm trying to use those to track down what i screwed up (maybe my formula on converting a 1D array to a 2D array?) I know i'm doing something very wrong, but am having trouble pin-pointing it. Any help would be very appreciated.
the map is a u16 array, the list array is of type "tile" currently defined in monster.h because that's where it 'works', i know i need to move it:
Code:
struct tile// does not belong in monster.h - how to move it but keep everything working?
{
// pointer to object or int ID, something to find what is on the tile for pickup item or fight monster...
bool passable; // default not passable
bool blockLOS; // default block line of sight
int type;
};

Here is the temporary flag array in main.cpp:
Code:
void tempBuildList() // just until we get some actual level generation set up, then build list and map at same time
{ // use list as map? or map as list...
   int iz, iy, ix, i = 0;

   for(iz = 0; iz < 3; iz++)
   {
      for(iy = 0; iy < 64; iy++)
      {
         for(ix = 0; ix < 64; ix++)
         {
            i = ix + (iy * 64);// n = x + (y * w)
            list[iz][iy][ix].type = map2_64x64[i];
            if (map2_64x64[i] == 4)
            {
               list[iz][iy][ix].passable = false;
            }
            else
            {
               // this should be true - trying false to see what happens.
               list[iz][iy][ix].passable = false;
            }
            
            
         }
      }
   }
   
}

invoking the checkSpace method of the player object in main.cpp:
Code:
         i = player->checkSpace(direction, list);
         switch (i)
         {
            case (0):
               player->moveMonster(direction);
               //direction = D_NONE;
               break;
            case (1):
               // combat?
               //direction = D_NONE;
               break;
            case (2):
               // bump
               //direction = D_NONE;
               break;
            case (3):
               // swim?
               //direction = D_NONE;
               break;
            case (4):
               // open?
               //direction = D_NONE;
               break;
            default: // nothing there, go for it!
               player->moveMonster(direction);
               break;
         }

the checkSpace function in monster.cpp:
Code:
   int Monster::checkSpace(int direction, tile plist[3][64][64])
   {
   // potentials
   int potX = 0;
   int potY = 0;
   // 0=none 1=Creature 2=Wall 3=Water 4=Door
   int obstacle = 0;
   /*
      1) check creature array for monsters
         fight?
      2) check terrain array for walls/water/door
         bump head/ swim? / open?
   */
      switch (direction)
      { // first figure out what square we're looking at
         case (D_UP):
            potX = this->x;
            potY = this->y - 1;
            break;
         case (D_RIGHT):
            potX = this->x + 1;
            potY = this->y;
            break;
         case (D_DOWN):
            potX = this->x;
            potY = this->y + 1;
            break;
         case (D_LEFT):
            potX = this->x - 1;
            potY = this->y;
            break;
         default:
            potX = this->x;
            potY = this->y;
            break;
      }
      
      if (plist[0][potY][potX].passable)
      {
         obstacle = 0;
      }
      else
      {
         obstacle = plist[0][potY][potX].type;
      }

      return obstacle;
   }


Let me know if you need more information. I'd also be willing to email a copy of my entire project folder or the .nds file upon request.

One thing i just noticed is that in struct tile "type" is defined as an int, but my map units are u16, but it doesn't seem like that should be causing the strange results i'm getting, should it? Gar, i wish i had internet access at my dev machine, this whole process would be so much easier...

#172419 - sgeos - Fri Feb 05, 2010 8:24 am

Quote:
i probably need to start from scratch on this one.

My thoughts are just rewrite it. You are familiar with the Pareto Principle (AKA 80-20 Rule), right? If you can identify a problem module, chances are you will be better off just discarding it. Use the experience gained writing it the first time to do a decent job on next iteration, rewriting from scratch, unless you have very good reasons not to do so.

#172433 - zelbo - Fri Feb 05, 2010 11:27 pm

I hadn't heard of that one, but now that i've read it, the concept sounds familiar.
At this point, i think i need to get a better handle on my map structure, then i'm going to implement a "look" command. If all goes well with that, i should be able to get the movement checker working without too much trouble.
I guess i don't really need to muck with it now, but i wonder what is causing such strange results. i've noticed a couple of spots that wont let me move, but only when the map is scrolled all the way to the right or left. If it scrolls just a little either way, there is nothing blocking my movement on these mystery spots, neither where it was or where it should have scrolled to, but the line in the middle is still there.
So i'm going to rewrite it, but now i'm very curious, i will probably come back to it later and try to figure it out.

#172451 - zelbo - Sat Feb 06, 2010 11:15 pm

Ok, so i've realized something. I'm using a map that is 64 tiles tall by 64 tiles wide, but it is basically split into quarters for putting it into mapbase memory, so the formula n=x+(y*w) doesn't work here.
Even though i'm not going to be using this particular function, i think i still need to deal with x and y in 1d arrays. Now i either need to figure out a new formula to deal with this, or cut my map size down. Since i'd really like to stick with 64x64 if i can, i think i'm going to be doing some math on paper for this.
While this helps me to understand why it's not working the way it should, i still don't think this explains the behavior i've been getting from it.

maybe something like n=x+(y*w)+(q*1024) where q can be 0 to 3?

#172456 - elwing - Sun Feb 07, 2010 8:14 pm

that said, why don't you use a 32x32 map? 64x64 is prolly too small for a game map so you'll need scrolling anyway... 32x32 leads to smaller map and you avoid the screenblocks management problem...