How to make enemies circulate randomly and follow player if withing certain distance? C++ Console game

StackOverflow https://stackoverflow.com/questions/22338048

  •  13-06-2023
  •  | 
  •  

Question

I have been stuck on trying to make the Z's move around randomly for literally hours. What I am aiming to do;-

  • Make the Zombies's(Z) move around randomly around the map
  • Follow the player(M) if he is a certain distance away

I am a complete amateur to programming and I will definitely appreciate the help! Here is the full code:

#include <iostream>
#include <Windows.h>
#include <time.h>
#include <conio.h>
using namespace std;



inline void Refresh(char q[50][50]){
system("cls");
int i, j;
cout << endl;
for (i = 0; i < 50; i++) {
    cout << "\t";
    for (j = 0; j < 50; j++)
    {
        cout << q[i][j];
    }
    cout << endl;
}
}


int launch(char q[][50], int a1, int a2, int p1, int p2, int x0, int y0);

//**************************Main Function*********************************************
int main(){
char map[50][50] = {
    "#################################################",
    "#                                               #",
    "#                                               #",
    "#                                               #",
    "#                                               #",
    "#                                               #",
    "#                                               #",
    "#                                               #",
    "#                                               #",
    "#                                               #",
    "#                                               #",
    "#                                               #",
    "#                                               #",
    "#                                               #",
    "#                                               #",
    "#                                               #",
    "#                                               #",
    "#                                               #",
    "#                                               #",
    "#                                               #",
    "#                                               #",
    "#                                               #",
    "#                                               #",
    "#                                               #",
    "#                                               #",
    "#                                               #",
    "#                                               #",
    "#                                               #",
    "#                                               #",
    "#                                               #",
    "#                                               #",
    "#                                               #",
    "#                                               #",
    "#                                               #",
    "#                                               #",
    "#                                               #",
    "#                                               #",
    "#                                               #",
    "#                                               #",
    "#                                               #",
    "#                                               #",
    "#                                               #",
    "#                                               #",
    "#                                               #",
    "#                                               #",
    "#                                               #",
    "#                                               #",
    "#                                               #",
    "#                                               #",
    "#################################################"
};
// my character
int x0 = 1, y0 = 1;



// Randomly make and spawn the holes
int a1, a2;
srand(time(0));
do {
    a1 = rand() % 48 - 1;
    a2 = rand() % 48 - 1;
} while (map[a1][a2] != ' ');
map[a1][a2] = 'O';

// Randomly make and spawn the zombies
int p1, p2;
srand(time(0));
do {
    p1 = rand() % 48 - 1;
    p2 = rand() % 48 - 1;
} while (map[p1][p2] != ' ');
map[p1][p2] = 'Z';


launch(map, a1, a2, p1, p2, x0, y0);

 }


int launch(char q[][50], int a1, int a2, int p1, int p2,int x0, int y0){
int over, x = x0, y = y0;
while (1) // Infinite loop
{
    _getch();

    // UP key
    if (GetAsyncKeyState(VK_UP))
    {
        x = x - 1;
    }
    // DOWN key
    else if (GetAsyncKeyState(VK_DOWN))
    {
        x = x + 1;
    }
    // LEFT key
    else if (GetAsyncKeyState(VK_LEFT))
    {
        y = y - 1;
    }
    // RIGHT key
    else if (GetAsyncKeyState(VK_RIGHT))
    {
        y = y + 1;
    }


    if (x == 0 || x == 50 || y == 0 || y == 50)  
    {
        cout << "Game Over" << endl;
        return 0;
    }

    if (x == p1 && y == p2) { // Touch the zombies
        cout << "Game Over" << endl;
        system("PAUSE");
        return 0;
    }

    if (x == a1 && y == a2) { // Touch the holes
        cout << "Game Over" << endl;
        system("PAUSE");
        return 0;
    }

    else { // the hero just moving around
        q[x0][y0] = ' ';
        q[x][y] = 'M';

        Refresh(q);
    }
    x0 = x;
    y0 = y;

}
return 0;
}
Was it helpful?

Solution

What you're perhaps missing is holding some state for the zombies which can be more easily accessed than searching the map for the character 'Z'. For example, hold the x,y coordinates in a structure, and have an array of them to represent zombies.

struct position {
    int x, y;
};

#define NUM_ZOMBIES 5;
struct position zombies[NUM_ZOMBIES];

Inside main, you would then create a simple loop around your current code for creating zombies, where instead of directly setting a character in the map to 'Z', you set the zombie's locations

for (int i=0; i<NUM_ZOMBIES; i++) {
    int p1, p2;
    srand(time(0));
    do {
        p1 = rand() % 48 - 1;
        p2 = rand() % 48 - 1;
    } while (map[p1][p2] != ' ');
    zombies[i] = { .x = p1, .y = p2 };
}

For convenience, lets also use the position for the player too.

struct position player = {.x = x0, .y = y0 };

You would then change your Refresh function to draw the zombies onto it, by adding the zombies to the map before you print them it to screen.

for (int i=0; i<NUM_ZOMBIES; i++) {
    q[[zombies[i].x][zombies[i].y] = 'Z';
}

So the final part is testing whether they are in range. You have another loop inside your main loop which similarly loops through all the zombies, compares the distance to the player, and if they are within the range you want, you begin to follow

for (int i=0; i<NUM_ZOMBIES; i++) {
    if (in_range(zombies[i], player)) {
        zombie[i] = move_towards(zombies[i], player);
    }
}

I'll leave you to implement in_range and move_towards, but here's their prototypes to help you.

bool in_range(struct position zombie, struct position player);
struct position move_towards(struct position zombie, struct position player);

OTHER TIPS

"I have tried and can only get it to work if a button is pressed"

This is because you use _getch(). First off, note the leading underscore. This signals the function as a Microsoft extension. That's not the actual cause of your problem, but it means your code only runs on Windows. Then again, you have all those GetAsyncKeyState calls, so that was a given anyway.

The real cause is that _getch() might wait for keyboard input. If you don't press a key, nothing happens. In particular, no (Z)ombie moves while _getch() waits. There's another Microsoft function, _kbhit which will tell you if a key is hit (but not which); if no key is hit you can skip the _getch call.

But why are you even calling _getch in the first place? You're not using the value returned. I can predict one thing which will happen, though: your zombies will move quite rapidly if you remove the key press limitation. You will need another limit.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top