Staredit Network > Forums > Technology & Computers > Topic: [C++] Fire Emblem-esque Game/Project
[C++] Fire Emblem-esque Game/Project
Oct 26 2011, 11:02 pm
By: Sand Wraith  

Oct 26 2011, 11:02 pm Sand Wraith Post #1

she/her

Hello there.

I know there are a few programmers here, so I was thinking I could get some help for a problem I'm having with my project. (Below is the code).

My current problem is with removing units. Presently, the behaviour is like this:
I cannot remove units in places where no units exist.
I can place units.
I can only remove the first unit I place. <- Main problem.

Can anyone help me fix this problem? My logic "feels" correct, but I have no idea what is actually wrong.

Functions of interest:
removeUnit
CUnit.removeSelf

Other information:
Programmed for/tested with Windows
Use ESC to access the menu
Use arrow keys to move the cursor (*)

Code
#include <cstdlib>
#include <conio.h>
#include <iostream>
#include <string>

#define WIDTH 45
#define HEIGHT 15
#define AREA WIDTH * HEIGHT

using namespace std;

struct SMapInfo
{
   int tileType;
   int unitType;
   bool cursor;
};

SMapInfo GMap[WIDTH][HEIGHT];

class CUnit
{
   int coordX, coordY; // coordinMainAtes
   int HP; // HP
   int wType; // weapon type: 1 = sword, 2 = axe, 3 = pike
public:
   bool exists;
   void addAtLoc(int x, int y, int iniHP, int iniWType) // Adds a unit at the location
   {
       coordX = x; // change coordinMainAtes
       coordY = y;
       wType = iniWType; // set weapon
       HP = iniHP; // alive
       GMap[coordX][coordY].unitType = wType; // add self to map
       exists = 1; // now exists
   }
   bool isAtLoc(int x, int y) // Returns true if unit is at a location
   {
       if(x == coordX && y == coordY)
       {
           return 1;
       }
       else
       {
           return 0;
       }
   }
   bool moveToLoc(int x, int y) // Returns true if unit is moved successfully
   {
       if(GMap[x][y].unitType == 0)
       {
           GMap[coordX][coordY].unitType = 0; // remove self from map
           coordX = x; // change coordinMainAtes
           coordY = y;
           GMap[coordX][coordY].unitType = wType; // add self to map
           return 1;
       }
       else
       {
           return 0;
       }
   }
   void removeSelf() // Removes self.
   {
       GMap[coordX][coordY].unitType = 0; // remove self from map
       exists = 0;
   }
};

CUnit GUnitArray[AREA];

int GCursorX = 0;
int GCursorY = 0;

void resetGMap()
{
   for(int y = 0; y < HEIGHT; y++)
   {
       for(int x = 0; x < WIDTH; x++)
       {
           GMap[x][y].tileType = 0;
           GMap[x][y].unitType = 0;
           GMap[x][y].cursor = 0;
       }
   }
}

void drawGMap()
{    
   for(int y = 0; y < HEIGHT; y++)
   {
       int xsum = 0;
       for(int x = 0; x < WIDTH; x++)
       {
           xsum += GMap[x][y].unitType;
           xsum += GMap[x][y].tileType;
           xsum += GMap[x][y].cursor;
       }
       string emptyLine = "";
       if(xsum == 0)
       {
           for(int i = 0; i < WIDTH; i++)
           {
               emptyLine += ".";
           }
           cout << emptyLine;
       }
       else
       {
           for(int x = 0; x < WIDTH; x++)
           {
               int xsum = 0;
               
               if(GMap[x][y].cursor == 1) // draw cursor
               {
                   cout << "*";
               }
               else if(GMap[x][y].unitType != 0) // draw unit
               {
                   switch(GMap[x][y].unitType) // units
                   {
                       case 1: // swordsman
                           cout << "s";
                           break;
                       case 2: // axeman
                           cout << "a";
                           break;
                       case 3: // pikeman
                           cout << "p";
                           break;
                       default:
                           cout << "!";
                           break;
                   }
               }
               else
               {
                   switch(GMap[x][y].tileType) // tiles
                   {
                       case 0: // open
                           cout << ".";
                           break;
                       case 1: // void
                           cout << " ";
                           break;
                       case 2: // high ground
                           cout << ":";
                           break;
                       default:
                           cout << "?";
                           break;
                   }
               }
           }
       }    
       cout << endl;
   }
}

string tileInfo(int T)
{
   string tile;
   switch (T)
   {
       case 0:
           tile = "Ground";
           break;
       case 1:
           tile = "Void";
           break;
       case 2:
           tile = "High Ground";
           break;
   }
   return tile;
}

string unitInfo(int U)
{
   // 1 sword > 2 axe > 3 lance > 1 sword...
   string unit;
   switch (U)
   {
       case 0:
           unit = "None";
           break;
       case 1:
           unit = "Swordsman";
           break;
       case 2:
           unit = "Axeman";
           break;
       case 3:
           unit = "Pikeman";
           break;
   }
   return unit;
}

void clrScrn()
{
   system("CLS");
}

void placeCursor()
{
   GMap[GCursorX][GCursorY].cursor = 1;
}

void removeCursor()
{
   GMap[GCursorX][GCursorY].cursor = 0;
}

bool addUnit(int x, int y, int iniHP, int iniWType)
{
   if(GMap[GCursorX][GCursorY].unitType == 0) // no unit presently occupies space
   {
       GMap[GCursorX][GCursorY].unitType = iniWType;
       for(int i = 0; i < AREA; i++)
       {
           if(GUnitArray[i].exists != 1)
           {
               GUnitArray[i].addAtLoc(x, y, iniHP, iniWType);
           }
       }
       return 1;
   }
   else
   {
       cout << "Failed to add unit." << endl;
       system("PAUSE");
       return 0;
   }
}

bool removeUnit(int x, int y)
{
   for(int i = 0; i < AREA; i++)
   {
       if(GUnitArray[i].exists == 1)
       {
           if(GUnitArray[i].isAtLoc(x, y) == 1)
           {
               GUnitArray[i].removeSelf();
               cout << "Removed unit." << endl;
               system("PAUSE");
               return 1;
           }
           else
           {
               cout << "Failed to remove unit." << endl;
               system("PAUSE");
               return 0;
           }
       }
   }
}

int main()
{
   resetGMap();
   int inMainA, inMainB;
   bool gameOn = 1;
   while(gameOn)
   {
       clrScrn();
       placeCursor();
       drawGMap();
       cout << "Tile: " << tileInfo(GMap[GCursorX][GCursorY].tileType) << endl;
       cout << "Unit: " << unitInfo(GMap[GCursorX][GCursorY].unitType) << endl;
       cout << ">> ";
       inMainA = getch();
       cout << inMainA << endl; // return input
       switch(inMainA)
       {
           case 224: // special key
               inMainB = getch();
               switch(inMainB)
               {
                   case 72: // up
                       if (GCursorY > 0)
                       {
                           removeCursor();
                           GCursorY--;
                       }
                       break;
                   case 80: // down
                       if (GCursorY < HEIGHT - 1)
                       {
                           removeCursor();
                           GCursorY++;
                       }
                       break;
                   case 75: // left
                       if (GCursorX > 0)
                       {
                           removeCursor();
                           GCursorX--;
                       }
                       break;
                   case 77: // right
                       if (GCursorX < WIDTH - 1)
                       {
                           removeCursor();
                           GCursorX++;
                       }
                       break;
               }
               break;
           case 27: // ESC menu
               int inMenu;
               bool menuOn;
               menuOn = 1;
               while(menuOn)
               {
                   cout << "\n   MENU" << endl;
                   cout << "ESC - Return" << endl;
                   cout << "1 - Place Tile" << endl;
                   cout << "2 - Place Unit" << endl;
                   cout << "3 - Remove Unit" << endl;
                   cout << "0 - Exit" << endl;
                   inMenu = getch();
                   switch(inMenu)
                   {
                       case 27: // ESC return
                           menuOn = 0;
                           break;
                       case 49: // 1 Tile Input
                           int inTile;
                           bool tileOn;
                           tileOn = 1;
                           while(tileOn)
                           {
                               cout << "\n    TILE" << endl;
                               cout << "ESC - Return" << endl;
                               cout << "1 - Ground" << endl;
                               cout << "2 - Void" << endl;
                               cout << "3 - High Ground" << endl;
                               inTile = getch();
                               switch(inTile)
                               {
                                   case 49: // 1 ground
                                       tileOn = 0;
                                       menuOn = 0;
                                       GMap[GCursorX][GCursorY].tileType = 0;
                                       break;
                                   case 50: // 2 void
                                       tileOn = 0;
                                       menuOn = 0;
                                       GMap[GCursorX][GCursorY].tileType = 1;
                                       break;
                                   case 51: // 3 high ground
                                       tileOn = 0;
                                       menuOn = 0;
                                       GMap[GCursorX][GCursorY].tileType = 2;
                                       break;
                                   case 27: // ESC return
                                       tileOn = 0;
                                       break;
                                   default:
                                       break;
                               }
                           }
                           break;
                       case 50: // 2 Unit Input
                           int inUnit;
                           bool unitOn;
                           unitOn = 1;
                           while(unitOn)
                           {
                               cout << "\n    UNIT" << endl;
                               cout << "ESC - Return" << endl;
                               cout << "1 - Swordsman" << endl;
                               cout << "2 - Axeman" << endl;
                               cout << "3 - Pikeman" << endl;
                               inUnit = getch();
                               switch(inUnit)
                               {
                                   case 49: // 1 swordsman
                                       unitOn = 0;
                                       menuOn = 0;
                                       addUnit(GCursorX, GCursorY, 3, 1);
                                       break;
                                   case 50: // 2 swordsman
                                       unitOn = 0;
                                       menuOn = 0;
                                       addUnit(GCursorX, GCursorY, 3, 2);
                                       break;
                                   case 51: // 3 swordsman
                                       unitOn = 0;
                                       menuOn = 0;
                                       addUnit(GCursorX, GCursorY, 3, 3);
                                       break;
                                   case 27: // ESC return
                                       unitOn = 0;
                                       break;
                                   default:
                                       break;
                               }
                           }
                           break;
                       case 51: // 3 remove unit
                           menuOn = 0;
                           removeUnit(GCursorX, GCursorY);
                           break;
                       case 48: // 0 exit
                           gameOn = 0;
                           menuOn = 0;
                           break;
                       default:
                           break;
                   }
               }
           default:
               break;
       }
   }
   return 0;
}





Oct 27 2011, 12:24 am Raitaki Post #2



How about removing and replacing units when they move?



None.

Oct 27 2011, 12:38 am ShadowFlare Post #3



Both the addUnit and removeUnit functions have some issues. Here are some versions that should work (with the changes marked by comments).

Code
bool addUnit(int x, int y, int iniHP, int iniWType)
{
  if(GMap[GCursorX][GCursorY].unitType == 0) // no unit presently occupies space
  {
      // GMap[GCursorX][GCursorY].unitType = iniWType; // redundant since addAtLoc already does this
      for(int i = 0; i < AREA; i++)
      {
          if(GUnitArray[i].exists != 1)
          {
              GUnitArray[i].addAtLoc(x, y, iniHP, iniWType);
              break; // If you don't break out of the loop, it is going to fill the whole array
          }
      }
      return 1;
  }
  else
  {
      cout << "Failed to add unit." << endl;
      system("PAUSE");
      return 0;
  }
}

bool removeUnit(int x, int y)
{
  for(int i = 0; i < AREA; i++)
  {
      if(GUnitArray[i].exists == 1)
      {
          if(GUnitArray[i].isAtLoc(x, y) == 1)
          {
              GUnitArray[i].removeSelf();
              cout << "Removed unit." << endl;
              system("PAUSE");
              return 1;
          }
          // This shouldn't be here, otherwise it will stop after checking the first unit that exists
          // else
          // {
          //     cout << "Failed to remove unit." << endl;
          //     system("PAUSE");
          //     return 0;
          // }
      }
  }
  // The failure condition should be after the search is finished
  cout << "Failed to remove unit." << endl;
  system("PAUSE");
  return 0;
}


If you want to catch the case that the units table is full but there are still empty spaces (in case you resize the board without increasing the size of that table), you could make addUnit like this:

Code
bool addUnit(int x, int y, int iniHP, int iniWType)
{
  if(GMap[GCursorX][GCursorY].unitType == 0) // no unit presently occupies space
  {
      for(int i = 0; i < AREA; i++)
      {
          if(GUnitArray[i].exists != 1)
          {
              GUnitArray[i].addAtLoc(x, y, iniHP, iniWType);
              return 1;
          }
      }
  }
  cout << "Failed to add unit." << endl;
  system("PAUSE");
  return 0;
}




None.

Oct 27 2011, 2:36 am Sand Wraith Post #4

she/her

Thanks for the solution, SF! It works perfectly fine now.

I'll post more problems if I run into them.




Oct 27 2011, 3:33 am ShadowFlare Post #5



btw, what compiler are you using?



None.

Oct 27 2011, 4:18 pm Sand Wraith Post #6

she/her

"Dev-C++ version 4.9.9.2, includes full Mingw compiler system with GCC 3.4.2 and GDB 5.2.1"




Nov 9 2011, 4:39 pm CecilSunkure Post #7



I don't have time to look specifically at the code, but am interested in how you're printing to the screen? I actually wanted to do the same thing for a Freshman project at DP, but we decided against due to time constraints. Are you using MSDN's console functions for printing?



None.

Nov 9 2011, 5:17 pm Sand Wraith Post #8

she/her

No, I'm just running a nested for loop and using switch and cout.

What are MSDN's console functions?

herpaderpicantprogram




Nov 9 2011, 10:15 pm CecilSunkure Post #9



Quote from Sand Wraith
No, I'm just running a nested for loop and using switch and cout.

What are MSDN's console functions?

herpaderpicantprogram
http://msdn.microsoft.com/en-us/library/windows/desktop/ms682073%28v=vs.85%29.aspx

http://benryves.com/tutorials/winconsole/

Lets you make games that look like: http://forums.tigsource.com/index.php?topic=14588.0

Might be really cool to try to use a double buffer for outputting to the console's screen buffer, using http://msdn.microsoft.com/en-us/library/windows/desktop/ms687404%28v=vs.85%29.aspx which is what I'm doing in my current project. I can't post the source though since it's a school project, but I can post an example exe if you'd like to see what I have so far.



None.

Nov 17 2011, 2:43 am CecilSunkure Post #10



In case you were still interested....

http://cecilsunkure.blogspot.com/2011/11/windows-console-game-setting-up-window.html
http://cecilsunkure.blogspot.com/2011/11/windows-console-game-writing-to-console.html



None.

Options
  Back to forum
Please log in to reply to this topic or to report it.
Members in this topic: None.
[01:39 am]
Ultraviolet -- no u elky skeleton guy, I'll use em better
[10:50 pm]
Vrael -- Ultraviolet
Ultraviolet shouted: How about you all send me your minerals instead of washing them into the gambling void? I'm saving up for a new name color and/or glow
hey cut it out I'm getting all the minerals
[10:11 pm]
Ultraviolet -- :P
[10:11 pm]
Ultraviolet -- How about you all send me your minerals instead of washing them into the gambling void? I'm saving up for a new name color and/or glow
[2024-4-17. : 11:50 pm]
O)FaRTy1billion[MM] -- nice, now i have more than enough
[2024-4-17. : 11:49 pm]
O)FaRTy1billion[MM] -- if i don't gamble them away first
[2024-4-17. : 11:49 pm]
O)FaRTy1billion[MM] -- o, due to a donation i now have enough minerals to send you minerals
[2024-4-17. : 3:26 am]
O)FaRTy1billion[MM] -- i have to ask for minerals first tho cuz i don't have enough to send
[2024-4-17. : 1:53 am]
Vrael -- bet u'll ask for my minerals first and then just send me some lousy vespene gas instead
[2024-4-17. : 1:52 am]
Vrael -- hah do you think I was born yesterday?
Please log in to shout.


Members Online: Roy