0
\$\begingroup\$

So I'm currently developing a 2D top down view java game. I have a mob called "Mutant" that currently does nothing. It generates a random number and depending on that number moves a few pixels in that direction. I"m trying to figure out how to make the mutant follow the player's x & y coordinates when the player comes near.

Here is what my mutant does currently:

    int xa = 0;
    int ya = 0;
    move = generator.nextInt(50) + 1;

    if(move == (50)) 
        ya = (random.nextInt(3) - 1) * random.nextInt(2);
        if (!hasCollided(xa, ya)) 

    if(move == 40) 
        ya = (random.nextInt(3) - 1) * random.nextInt(2);
        if (!hasCollided(xa, ya)) 

    if(move == 30) 
        xa = (random.nextInt(3) - 1) * random.nextInt(2);
        if (!hasCollided(xa, ya))

    if(move == 20) 
        xa = (random.nextInt(3) - 1) * random.nextInt(2);
        if (!hasCollided(xa, ya)) 

    if(xa != 0 || ya != 0) {
        move(xa, ya);
        isMoving = true;
    } else {
        isMoving = false;
    }

Does anyone know how to make the mob simulate hostility towards the player? I haven't implemented a health system yet, I've only worked on the mob's A.I.

\$\endgroup\$
1
\$\begingroup\$

A very simple solution might be to compare the mutant's x and y position to the x and y position of the player.

Example: Player at {10, 10}, Mutant at {0, 0}

if (mutant.x < player.x)
    mutant.x += amountToMove;
else if (mutant.x > player.x)
    mutant.x -= amountToMove;

if (mutant.y < player.y)
    mutant.y += amountToMove;
else if (mutant.y > player.y)
    mutant.y -= amountToMove;

This would always move the monster towards the player, but you may need to split the amount to move between the x and y axis so it doesn't move more quickly in a diagonal direction than in a pure vertical or horizontal motion.

totalDistance = xDistance + yDistance;
xSpeed = amountToMove * (xDistance / totalDistance); //uses proportion of xDistance to set proportion of speed.
ySpeed = amountToMove * (yDistance / totalDistance); //same for yDistance
\$\endgroup\$
1
\$\begingroup\$

The mutant can acquire a reference to the player at a certain range. For example, every frame (or less frequently) the range between the mutant and the player can be checked. When the mutant is within a specific range, the mutant can acquire the player as target.

How to represent that is up to you, but a short version could be:

bool isHostile = true
Entity target = player

or maybe a temporary solution:

int targetX = player.x  // needs updated every frame, as player moves
int targetY = player.y

After the mutant has the player as a target, the mutant can movement can head towards the player. A piece of math called a "normalized vector" is useful for figuring out how much to move in a given direction. Without a normalized vector, you'll run into the classic problem of having a game where diagonal movement is significantly faster than left/right or up/down movement. Here is some pseudocode for determining the direction to move, and how much to move:

  // xDiff and yDiff would be the length of the line between mutant and player
  var xDiff = target.x - npc.x
  var yDiff = target.y - npc.y     

  // unitVector is a line which is 1.0 units long and points from mutant to player
  var unitVector = math.normalizeVector(xDiff, yDiff)

  // move along the line from mutant to player
  npc.x += unitVector.x * npc.speed * delta
  npc.y += unitVector.y * npc.speed * delta

In the above code, target would be the player, and npc would be your mutant. You can ignore/remove the delta for now, and also type in some test numbers for speed -- but it may be something for later, a topic called "frame independent movement."

The approximate math for normalizeVector is:

  length = Math.sqrt((x * x) + (y * y))
  var xComponent = x / length
  var yComponent = y / length

This will convert an x,y movement of [+1, +1] into something like [0.707106781186547, 0.707106781186547] which is an ugly set of numbers but carries the correct amount of movement. I'll note that this particular equation will hit an error if x and y are both 0 (it'll divide by zero). If you're using a math or game library it may already have a function like this.

\$\endgroup\$
0
\$\begingroup\$

As DoubleDouble said, then you can layer more complex behaviours on top, for example:

  • Limited sense range, e.g. only attacks the player if they are nearby or ahead of the mob.
  • Play a sound, animation and/or change the movement style when the player is seen to give feedback to the player.
  • Predict the player's future position based on their current velocity.
  • A simple state machine, e.g. monster patrols or acts randomly until the player is seen.
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.