Click here to Skip to main content
15,393,205 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I am a student of first semester and I am making a console based game in c++.
There are two players in game, 'player-2' is CPU player and 'player-1' is controlable player. After every 20 seconds one of player becomes red and other becomes green. The red ones need to catch green one and green one needs to run away from red one.
Problem I am now facing is that, I cant make logic to run Player-2(CPU Player) away from Player-1(controlable player) when Player-1 is red.
I have following class for both players
class Player
{
    // XPos is the row position of player and YPos is column position of player
    int XPos, YPos, Width, Height, Init_XPos, Init_YPos, MovSpeed;
    WORD Color;
    const float HurtSoundVol = 0.7;
    string HurtSound;
    virtual void Draw(int x, int y);
    virtual void Erase(int x, int y);
    template <typename T> void ConfCollision(IEntity& obj, bool& scoreChanged);
    void SetCursorPosition(int row, int col);
    template <typename T> void MoveUp();
    template <typename T> void MoveDown();
    template <typename T> void MoveLeft();
    template <typename T> void MoveRight();
};

following is code for player movement
template <typename T> void IEntity::MoveUp() {
if (XPos > EnvSetup::UpBoundary) {
    Hunter* this_x = (T*)this;
    (this_x->IsHunter) ? this_x->HErase(XPos, YPos) : Erase(XPos, YPos);
    XPos -= MovSpeed;
    if (XPos <= EnvSetup::UpBoundary) XPos = 0 + EnvSetup::TopMargin;
    (this_x->IsHunter) ? this_x->HDraw(XPos, YPos) : Draw(XPos, YPos);
  }
}

template <typename T> void IEntity::MoveDown() {
    if (XPos + Height < EnvSetup::DownBoundary) {
        Hunter* this_x = (T*)this;
        (this_x->IsHunter) ? this_x->HErase(XPos, YPos) : Erase(XPos, YPos);
        XPos += MovSpeed;
        if (XPos + Height >= EnvSetup::DownBoundary) XPos = EnvSetup::Height - Height - EnvSetup::BottomMargin;
        (this_x->IsHunter) ? this_x->HDraw(XPos, YPos) : Draw(XPos, YPos);
    }
}
template <typename T> void IEntity::MoveLeft() {
    if (YPos > EnvSetup::LeftBoundary) {
        Hunter* this_x = (T*)this;
        (this_x->IsHunter) ? this_x->HErase(XPos, YPos) : Erase(XPos, YPos);
        YPos -= MovSpeed;
        if (YPos <= EnvSetup::LeftBoundary) YPos = 0 + EnvSetup::LeftMargin;
        (this_x->IsHunter) ? this_x->HDraw(XPos, YPos) : Draw(XPos, YPos);
    }
}
template <typename T> void IEntity::MoveRight() {
    if (YPos + Width < EnvSetup::RightBoundary) {
        Hunter* this_x = (T*)this;
        (this_x->IsHunter) ? this_x->HErase(XPos, YPos) : Erase(XPos, YPos);
        YPos += MovSpeed;
        if (YPos + Width >= EnvSetup::RightBoundary) YPos = EnvSetup::Width - Width - EnvSetup::RightMargin;
        (this_x->IsHunter) ? this_x->HDraw(XPos, YPos) : Draw(XPos, YPos);
    }
}

If a player has a flag IsHunter=true than HDraw(draw it red) else draw it simply

This is image showing my game

What I have tried:

I used distance formula(sqrt((x2-x1)^2 + (y2-y1)^2)) in many ways to move player-2 away from player-1 but there is always some position of Player-1 and Player-2 (i.e along corner of screen or center of screen) where Player-2 starts to vibrate along its positon(One time moves up and second time moves down)
Posted
Updated 14-Jan-22 13:40pm
v2
Comments
Richard MacCutchan 14-Jan-22 7:30am
   
I find your code looks over complicated, especially the use of templates for what should be simple methods. The hunter's moves should be modified by the position of the hunted player, and the boundaries of the playing arena. If the player is vibrating between two positions then there is a logic problem in some of the code that we cannot see.
Abu Bakar 2022 14-Jan-22 13:52pm
   
I havn't share all of code on the CP, I cant use simple methods bcz there are three sub classes derived from Player class and these three classes are also derived from a class Hunter
I know there is a problem in my logic, I want if anyone can guide me how can I achieve my goal
Rick York 14-Jan-22 11:55am
   
Here's an optimization I often use: the sqrt is one of the most expensive math functions there is and multiplication is much faster. Also - never, ever use the pow function to square values because it is even more expensive that sqrt. Make a template function to square values instead. Anyway, the optimization is if you want to compare with a given distance - square that distance and compare it with the sum of the squared differences in point coordinates. It's essentially the formula you are using except no square root is used. I have seen tremendous performance gains with these two simple things.
Abu Bakar 2022 14-Jan-22 13:57pm
   
Thank you for telling me about optimization, my teacher didn't told us about this
but my problem is I want to know logic to always keep Player-2 (CPU-Player) away from Player-1 (Controlable player). I will try to add pictures in question, to make my problem prominent

Sounds like an threading problem. As informtic student you should use some MVC architecture or MVVM architecture to avoid such edge cases.

The result shoulde be:
1. the model calculates ALL position
2. the drawing code draws ALL elements (at once)
   
Comments
Abu Bakar 2022 14-Jan-22 6:33am
   
no, there is no threading problem, every thing is working fine i.e both players can move at same time, I can detect collision etc
I only want logic to always run CPU-player(Player-2) away from Controlable player (Player-1)
Assuming you know how to run towards some point, how about running in the opposite direction? In other words, assuming you have available for each point the distance to some point, rather than going downhill, go uphill.
   
Comments
Abu Bakar 2022 15-Jan-22 4:32am
   
yes, I can move it in opposite direction but when it reaches left/right boundary or up/down boundary it stucks and Player-1 catch it
Luc Pattyn 15-Jan-22 15:32pm
   
When backed against say the east wall, moving one step north or south will change the (squared) distance, and at least one of these will be smaller; so you can always improve your position unless at least one of those directions is prohibited (corner or cul-de-sac).

This approach is based on extremely local optimization, which is not guaranteeing the absolute optimum (you might enter a small room without another exit rather than taking a long corridor).

So when the simple approach isn't good enough, you need a more complex algorithm that takes into account much more information.

AFAIK the optimal approach is pretty complex, it would resemble a flood fill: before each step you really execute, you should simulate performing multiple steps (both by you and the enemy) starting from the current positions and going in all possible directions, you avoiding all cells the enemy can reach at the same time or sooner. Stop the simulation (i.e. limit the number of steps simulated) whenever (1) you don't want to calculate any further or (2) no safe cells remain; then pick the safest spot you have found and finally do one real step on the path you used to get there during the simulation.

Warning 1: the slightest mistake in the implementation is bound to put you on an eternal loop, never getting far away from your current positions;

Warning 2: make sure you got the rules correct; do you have to move when the enemy does? does the enemy have to move when you do? etc

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900