Basically I am making an adventure game in a 2D array, I would like the character to move around fighting monsters and have that represented in a 2D array. I have the movement done and I have just figured out how to detect if there is another character on the players coordinates. Right now my problem is because I've used rand() to determine where each of my monsters are every time my map updates the monsters also move, I understand why this is happening but the only way I can think of fixing it is to put the randomisation of the monsters coordinates into main or somewhere that only gets called once.
I was wondering if I could make an array that stored all of those coordinates within a couple lines of code. For example if I wanted 17 monsters if I could make an array with 17 parts then have each of them hold their own X and Y variable, then put that array into the for loop that spawns monsters something like:
1 2 3 4 5 6
for (int i = 0; i < AMMOUNT_OF_MONSTERS; i++)
{
monsterX = myXArray[i];
monsterY = myYArray[i];
map[monsterX][monsterY] = 'M';
}
It would be a huge help of someone could show me how to fix this, I am quite new to C++ and I would like to learn as much as I can.
Thank you,
Michael Burdge.
Here is everything I have so far, i have made the size of the map so small and limited the amount of things spawning to test the detection without having to rely on randomisation.
#include "stdafx.h"
#include <ctime>
#include <iostream>
#define GRID_SIZE 3
#define AMMOUNT_OF_MONSTERS 1//17
#define AMMOUNT_OF_CHURCHES 1//10
#define AMMOUNT_OF_SURVIVORS 1//6
usingnamespace std;
int NewMap(int playerX, int playerY);
//int ContinueMap(int moveDistance, int direction);
void FightMonster();
void HealAtChurch();
void RecruitSurvivor();
int main()
{
int playerX;
int playerY;
bool canContinue;
playerX = GRID_SIZE / 2;
playerY = GRID_SIZE / 2;
int direction;
char directionCHR;
int moveDistance;
time_t t;
srand((unsigned)time(&t));
cout << "The Aim Is To Kill" << endl;
cout << "A = Adventurer: You are the Adventurer" << endl;
cout << "M = Monsters: Fight Monsters" << endl;
cout << "C = Churches: Heal After Fighting Monsters" << endl;
cout << "S = Survivors: Recruit People To Help Fight Monsters" << endl;
NewMap(playerX, playerY);
for (int i = 0; i < 5; i++)
{
do
{
cout << "Which Direction Would You Like To Move?" << endl << "N for North, E for East, S for South, W for West" << endl;
cin >> directionCHR;
if (directionCHR == 'N' || directionCHR == 'n')
{
direction = 0;
}
elseif (directionCHR == 'E' || directionCHR == 'e')
{
direction = 1;
}
elseif (directionCHR == 'S' || directionCHR == 's')
{
direction = 2;
}
elseif (directionCHR == 'W' || directionCHR == 'w')
{
direction = 3;
}
} while (directionCHR != 'N' && directionCHR != 'n' && directionCHR != 'E' && directionCHR != 'e' && directionCHR != 'S' && directionCHR != 's' && directionCHR != 'W' && directionCHR != 'w');
do
{
canContinue = true;
cout << "How Far Would You Like To Move?" << endl;
cin >> moveDistance;
if (direction == 0) // the reason why i did it like this is because originally i had the movement in the function along with the generation of the map.
{
playerX -= moveDistance;
if (playerX < 0)
{
cout << "out of bounds" << endl;
canContinue = false;
playerX = 1;
}
}
elseif (direction == 1)
{
playerY += moveDistance;
if (playerY > GRID_SIZE)
{
cout << "out of bounds" << endl;
canContinue = false;
playerY = GRID_SIZE - 1;
}
}
elseif (direction == 2)
{
playerX += moveDistance;
if (playerX > GRID_SIZE)
{
cout << "out of bounds" << endl;
canContinue = false;
playerX = GRID_SIZE - 1;
}
}
elseif (direction == 3)
{
playerY -= moveDistance;
if (playerY < 0)
{
cout << "out of bounds" << endl;
canContinue = false;
playerY = 1;
}
}
} while (!canContinue);
NewMap(playerX, playerY);
}
return 0;
}
int NewMap(int playerX, int playerY)
{
char map[GRID_SIZE][GRID_SIZE];
char grid = 176; //what ive chosen as the map ground, i chose this because it looks good as a background
int x; //Map X
int y; //Map Y
int howManyMonsters; //How many Monsters on the map
int monsterX; //Monsters X
int monsterY; //Monsters Y
int howManyChurches; //How many Churches on the map
int churchX; //Church X
int churchY; //Church Y
int howManySurvivors; //How many Survivors on the map
int survivorX; //Survivor X
int survivorY; //Survivor Y
for (x = 0; x < GRID_SIZE; x++)
{
for (y = 0; y < GRID_SIZE; y++)
{
map[x][y] = grid; //chooses what the map is
map[playerX][playerY] = 'A';
}
}
for (howManyMonsters = 0; howManyMonsters < AMMOUNT_OF_MONSTERS; howManyMonsters++) // to create the ammount of monsters i want
{
do // to randomize the coordinates of the monsters so they arent overwriting anything.
{
x = rand() % GRID_SIZE;
y = rand() % GRID_SIZE;
monsterX = rand() % GRID_SIZE; //will randomize each monsters X position
monsterY = rand() % GRID_SIZE; //will randomize each monsters Y position
} while (map[x][y] != grid && map[x][y] != map[playerX][playerY]); // this is so the monster wont replace the adventurer with monsters
map[monsterX][monsterY] = 'M';// place monsters at map[monsterX][monsterY]
}
for (howManyChurches = 0; howManyChurches < AMMOUNT_OF_CHURCHES; howManyChurches++)
{
do
{
x = rand() % GRID_SIZE;
y = rand() % GRID_SIZE;
churchX = rand() % GRID_SIZE; //will randomize each church X position
churchY = rand() % GRID_SIZE; //will randomize each church Y position
} while (map[x][y] != grid && map[x][y] != 'M' && map[x][y] != map[playerX][playerY]); // so we dont replace the adventurer or monsters with churches
map[churchX][churchY] = 'C';
}
for (howManySurvivors = 0; howManySurvivors < AMMOUNT_OF_SURVIVORS; howManySurvivors++)
{
do
{
x = rand() % GRID_SIZE;
y = rand() % GRID_SIZE;
survivorX = rand() % GRID_SIZE; //will randomize each survivor X position
survivorY = rand() % GRID_SIZE; //will randomize each survivor Y position
} while (map[x][y] != grid && map[x][y] != 'M' && map[x][y] != 'C' && map[x][y] != map[playerX][playerY]); //so we dont replace the adventurer, monsters or churches with survivors
map[survivorX][survivorY] = 'S';
}
for (x = 0; x < GRID_SIZE; x++)//this here makes the spacing between each background character, i made a space between them because
{
for (y = 0; y < GRID_SIZE; y++)
{
cout << map[x][y] << " ";
}
cout << endl;
}
for (x = 0; x < GRID_SIZE; x++)
{
for (y = 0; y < GRID_SIZE; y++)
{
if (map[playerX][playerY] == char('M'))
{
FightMonster(); //runs the function to fight a monster.
map[playerX][playerY] = 'A'; // places the Adventurer aka the player in that position
}
elseif (map[playerX][playerY] == char('C'))
{
HealAtChurch(); //runs the function to heal at the churche.
map[playerX][playerY] = 'A'; // places the Adventurer aka the player in that position
}
elseif (map[playerX][playerY] == char('S'))
{
RecruitSurvivor(); // runs the function to recruit a survivor;
map[playerX][playerY] = 'A'; // places the Adventurer aka the player in that position
}
else
{
map[playerX][playerY] = 'A'; // places the Adventurer aka the player in that position
}
}
}
return 0;
}
void FightMonster()
{
cout << "FIGHT A MONSTER" << endl;
}
void HealAtChurch()
{
cout << "HEAL AT A CHURCH" << endl;
}
void RecruitSurvivor()
{
cout << "RECRUIT A SURVIVOR" << endl;
}
for (howManyMonsters = 0; howManyMonsters < AMMOUNT_OF_MONSTERS; howManyMonsters++) // to create the ammount of monsters i want
{
do // to randomize the coordinates of the monsters so they arent overwriting anything.
{
x = rand() % GRID_SIZE;
y = rand() % GRID_SIZE;
monsterX = rand() % GRID_SIZE; //will randomize each monsters X position
monsterY = rand() % GRID_SIZE; //will randomize each monsters Y position
} while (map[x][y] != grid && map[x][y] != map[playerX][playerY]); // this is so the monster wont replace the adventurer with monsters
map[monsterX][monsterY] = 'M';// place monsters at map[monsterX][monsterY]
}
As you stated, every time you redraw your map, you re-locate your monsters. Instead, create your monsters at the beginning like this:
1 2 3 4 5 6 7 8
struct Location { int x; int y;};
Location monster[AMOUNT_OF_MONSTERS];
for (int i = 0; i < AMOUNT_OF_MONSTERS; ++i)
{
monster[i].x = rand() % GRID_SIZE; //will randomize each monsters X position
monster[i].y = rand() % GRID_SIZE; //will randomize each monsters Y position
}
Then change your do-loop to if (map[monster[i].x][monster[i].y] != grid && map[monster[i].x][monster[i].y] != map[playerX][playerY])
This probably isn't quite right, but it should get you thinking in the right direction. I would recommend only working with on addition at a time. Comment out your churches and survivors until you get monsters working, and then add things back in steps.
yes, moving random setup to either main or better still, a function that is called only once from main, would be ideal.
You can do better:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
struct mobxy //user defined type for xy coordinates
{
int x;
int y;
}
...
mobxy monsterlist[17]; //an array of 17 monsters or really, just 17 x/y pairs.
for (int i = 0; i < AMMOUNT_OF_MONSTERS; i++)
{
monsterlist[i].x = somex;
monsterlist[i].y = somey;
map[somex][somey] = 'M'
}
what you are looking for here is probably object oriented programming where you can bundle your data (like the x/y pairs and all) together into one single user defined type along with some functions that do the work. The struct above is the beginnings of this, but you will need to study a bit to use these ideas.
class monster
{
public: //for now this lets anyone and everything touch the class data members.
mobxy current_position;
int current_health;
string type;
monster() //what to do when the object is created, called a constructor
{ //with this simply creating a monster gives it a random starting location!
current_position.x = rand()%maxX;
current_position.y = rand()%maxY;
current_health = 100; //whatever
type = "Orc";
}
bool isdead();
};
bool monster::isdead() //this function is part of the class. it had a header in the class above.
{
return (health <= 0); //if it has 0 or less health, it died.
}
These are just some off the cuff really basic examples of what you might like to do.
then you can allocate an array (or better, a vector..!) of 17 monsters and they all immediately have a starting location and health and all. You can just start fighting them!
Thank you both for replying, I have looked over what you both have said and tried implementing it yet it hasn't worked, I am still getting the same result. Every time I load the map it will change where the monster spawns.
struct Character
{
int X;
int Y;
int health;
string name;
Character()
{
health = 99999;
name = "ChangeMe";
}
};
class Monster
{
public:
Character _Character[AMMOUNT_OF_MONSTERS];
string type;
Monster()
{
for (int howManyMonsters = 0; howManyMonsters < AMMOUNT_OF_MONSTERS; howManyMonsters++)
{
_Character[howManyMonsters].X = rand() % GRID_SIZE;//will randomize each monsters X position
_Character[howManyMonsters].Y = rand() % GRID_SIZE;//will randomize each monsters Y position
}
}
};
for (howManyMonsters = 0; howManyMonsters < AMMOUNT_OF_MONSTERS; howManyMonsters++) // to create the ammount of monsters i want
{
if (map[x][y] != grid && map[x][y] != map[playerX][playerY])
{
map[_Monster._Character[howManyMonsters].X][_Monster._Character[howManyMonsters].Y] = 'M';
}
}