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

3 Answers 3

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\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .