Search code examples
javascriptartificial-intelligencep5.js

How do I make an AI move in a human-like way


var playerX;
var playerY;
var playerSize = 15;
var playerSpeed = (playerSize / Math.pow(playerSize, 1.44)) * 10;
var Newcelltimer = 0;
var cell = []
var cellEaten = 0;
var celliseaten = false;
var eaten = false;
var zoom = 1;
var n = 0;
var Xgrid = 600;
var Ygrid = 600;
var cpu = [];

function setup() {
  frameRate(999)
  createCanvas(600, 450);
  playerX = Xgrid / 2
  playerY = Ygrid / 2;

}

function draw() {
  background(220);
  push();
  var Newzoom = 10 / playerSize
  let newnewZoom = 1.3 * lerp(0.9, 10 / playerSize, 0.5)
  Newzoom = lerp(zoom, Newzoom, 0.3)
  translate(Xgrid / 2, Ygrid / 2 - 50);
  scale(newnewZoom)
  translate(-playerX, -playerY);


  playerSpeed = (playerSize / Math.pow(playerSize, 1.44)) * 10

  Newcelltimer++;

  for (var i = 0; i < cell.length / 2; i++) {
    let d = int(dist(cell[i * 2], cell[i * 2 + 1], playerX, playerY))
    if (d <= playerSize / 2) {
      playerSize += 5;
      cell.splice(i * 2, 2)
      celliseaten = true;
    }
  }
  if (keyIsDown(UP_ARROW)) {
    playerY -= playerSpeed;
  }
  if (keyIsDown(RIGHT_ARROW)) {
    playerX += playerSpeed;
  }
  if (keyIsDown(DOWN_ARROW)) {
    playerY += playerSpeed;
  }
  if (keyIsDown(LEFT_ARROW)) {
    playerX -= playerSpeed;
  }

  if (playerX < playerSize / 2 - Xgrid) {
    playerX = playerSize / 2 - Xgrid
  }

  if (playerY < playerSize / 2 - Ygrid) {
    playerY = playerSize / 2 - Ygrid
  }

  if (playerY > 2 * Ygrid - (playerSize / 2)) {
    playerY = 2 * Ygrid - (playerSize / 2)
  }
  if (playerX > 2 * Xgrid - (playerSize / 2)) {
    playerX = 2 * Xgrid - (playerSize / 2)
  }

  if (Newcelltimer % 30 == 0) {
    cell.push(ceil(random(0 - Xgrid, 2 * Xgrid)),
      ceil(random(0 - Ygrid, 2 * Ygrid)))
  }

  if (Newcelltimer % 100 == 0) {
    cpu.push(random(-Xgrid, 2 * Xgrid), random(-Ygrid, 2 * Ygrid), 20)
  }

  for (var j = 0; j < cpu.length / 3; j++) {
    fill(0, 255, 0, 100);
    circle(NewposX,NewposY, cpu[j * 3 + 2])
  }
  for (var k = 0; k < cell.length / 2; k++) {

    fill(0, 255, 255, 100)
    circle(cell[k * 2], cell[k * 2 + 1], 7)
  }

  stroke(0)
  fill(255,255,0)
  circle(playerX,playerY,playerSize);

  if (playerSize >= 3 * Xgrid | playerSize >= 3 * Ygrid) {
    if (Xgrid > Ygrid) {
      playerSize = 3 * Ygrid;
    } else {
      playerSize = 3 * Xgrid;
    }

  }
  noFill();
  stroke(0, 0, 0)
  rect(0 - Xgrid, 0 - Ygrid, 3 * Xgrid, 3 * Ygrid)
  pop();
  text("Your size is " + playerSize, 20, 20);
}

How would I make the programmed unit move in a human-like way, right now, I'm stuck on getting it to move, a way I thought was to use Perlin noise, but that may keep on forcing it to always go one direction, I could use random, and map out that value to degrees/radians, then use trigonometry to find the path. Although if I'm not sure what the trigonometry solution would be.

EDIT: When I say "In a more human-like way," I'm not talking about really anything complicated, just that the AI for example doesn't move like: Right,Left,Right,Up,Down,Left


Solution

  • To make something move like a human is a pretty complicated task! I understand you merely wish to give some movement a natural appearance. P5’s noise function is the easiest way to achieve this.

    P5’s noise function returns a float between 0 and 1, which, if directly applied to an objects position, can only move it in a positive direction. Try using the map function to normalize this output to -1 and 1 instead:

    map(noise(x, y, z), 0, 1, -1, 1)
    

    Apply this to some kind of transformation and your agent will move in both positive and negative directions.

    To displace an agent on the x-axis, therefore, you could do something along these lines:

    let amp = 20; // how much you want the agent to move
    let offsetX = map(noise, 0, 1, -1, 1) * amp;
    ellipse(200 + offsetX, 200, 10, 10);