Austin Z. Henley

Assistant Professor



Useful functions for game development

9/21/2020

When I was making games, I found myself using a lot of the same functions over and over. They are quite simple, but I thought it interesting how they popped up everywhere and how conveniently I could make complex behaviors by combining them. I ended up with about 40 functions in a utility class that I could reach into like a bag of tricks. You can find a handful of them below, converted to JavaScript, along with a short description and a visual of what they can do.

run: move object forward

I used run to move objects in a given direction. I used it for virtually anything that moved relative to a variable direction: the player, enemies, projectiles, particles, and even floating text boxes.

// Moves obj towards its current rotation at its current speed.
function run(obj) {
  obj.x += Math.cos(obj.rotation)*obj.speed;
  obj.y += Math.sin(obj.rotation)*obj.speed;
}

A variation I used of this function is project, which returns the object's future location. This can be useful for collision detection.

// Like run(), but returns an object and uses an independent rotation and distance.
function project(obj, rot, dist) {
  return {x: obj.x + Math.sin(rot)*dist,
          y: obj.y + Math.cos(rot)*dist};
}

rotateTo: rotate object towards another object

The run function requires the angle to be calculated, which I often did using rotateTo. It points one object towards another, such as pointing the player towards the mouse cursor.

// Rotates obj to point at target.
function rotateTo(obj, target) {
  obj.rotation = Math.atan2(target.y - obj.y, target.x - obj.x);
}

rotateToGradual: rotate object towards another object at a fixed speed

A more complicated use of rotateTo is for objects that home in on a target. I used rotateToGradual for enemies that are trying to tackle the player but also for missiles. The idea is similar to rotateTo, but it can only turn so much each frame. (There are much shorter ways to code this, but I think this is the most understandable.)

// Gradually rotates obj to point at target using obj.turnSpeed.
// NOTE: Requires obj's rotation to be -Math.PI to Math.PI.
function rotateToGradual(obj, target) {
  let leftDist = 0;
  let rightDist = 0;
  let goal = Math.atan2(target.y - obj.y, target.x - obj.x);

  // Calculate distance to goal.
  if(goal > obj.rotation) { 
    leftDist = Math.abs(-Math.PI - obj.rotation) + (Math.PI - goal); // Passing -PI goes to PI.
    rightDist = goal - obj.rotation; 
  }
  else { 
    leftDist = obj.rotation - goal; 
    rightDist = (Math.PI - obj.rotation) + Math.abs(-Math.PI - goal); // Passing PI goes to -PI.
  }

  // If the goal is close, just snap to it.
  if(leftDist < obj.turnSpeed || rightDist < obj.turnSpeed) { obj.rotation = goal; }
  // Turn left if it is closer.
  else if(leftDist < rightDist) { obj.rotation -= obj.turnSpeed;}
  // Turn right if it is closer.
  else { obj.rotation += obj.turnSpeed; }
}

distance: calculate distance between two objects

A classic function indeed, but I found ways to use that I wouldn't have expected. For example, it can be used as a quick and dirty way to do collision detection in a top down shooter by checking if the distance from the target is less than the bullet radius.

// Returns distance between two objects.
function distance(objA, objB) {
  return Math.sqrt(((objA.x - objB.x)*(objA.x - objB.x))
          +((objA.y - objB.y)*(objA.y - objB.y)));
}

overlapping: check whether two objects are overlapping

I used overlapping to see if two rectangular objects are intersecting as another fundamental way to perform simple collision detection.

// Returns true or false if overlapping.
// NOTE: Assumes shapes are rectangular and not rotated.
function overlapping(objA, objB) {
  // Check x axis.
  if(objA.x < (objB.x + objB.w) && (objA.x + objA.w) > objB.x) {
    // Check y axis.
    if((objA.y + objA.h) > objB.y && objA.y < (objB.y + objB.h)) {
      return true;
    }
  }
  return false;
}

A minor variation is for checking whether a point is contained inside an object.

// Check if point overlaps with rectangle.
function intersectPointRectangle(px, py, rect) {
  if(px >= rect.x && px <= rect.x + rect.w) {
    if(py >= rect.y && py <= rect.y + rect.h) {
      return true;
    }
  }
  return false;
}

snap: round value to the nearest interval

I needed to snap numbers to a specific step. This can be useful for snapping coordinate values to the nearest tile index or for making scores more pretty (e.g., by snapping it to the nearest 2 or 50)

// Snaps the value x to the current increment of step. Ex: snap(144, 5) results in 145.
function snap(x, step) {
    return Math.round(x / step) * step;
}



See? Simple, but useful.

If you want more random game development goodness, check out:

  • The 8 lessons I learned from releasing 8 video games (web)
  • Game Design Patterns (Amazon, web)
  • Data Structures for Game Programmers (Amazon)
  • Programming Game AI by Example (Amazon)


There are Amazon affiliate links on this page.