<div class="floor"></div>
<canvas id="canvas"></canvas>
<article>In this vanilla JavaScript example I use sprite sheet to animate randomised characters created with JavaScript ES6 class. This technique can be used to generate NPCs or enemies for 8 directional isometric (top down) canvas games.<br><br> Image comes from general Google search, used for educational purposes only.<br>
</article>
<footer><span>Created by <a href="https://www.youtube.com/channel/UCEqc149iR-ALYkGM6TG-7vQ" target='blank'>Frank's Laboratory</a> @2020</span>
</footer>
* {
    box-sizing: border-box;
}
body {
    width: 100%;
    height: 100%;
    overflow: hidden;
}
.floor {
    position: absolute;
    top: -200%;
    left: -200%;
    width: 500%;
    height: 500%;
    background: url('https://i.ibb.co/Jm1kQTJ/Brick-01.png');
    transform: rotate3d(1, 0, 1, 50deg);
}
canvas {
    position: absolute;
    top: 0; left: 0;
    width: 100%;
    height: 100%;
}

footer, article {
  font-family: monospace;
  position: absolute;
  width: 100%;
  color: white;
  font-size: 15px;
  text-shadow: 1px 1px 1px #737373; 
  background: rgba(0,0,0,0.4);
}
footer {
  left: 0;
  bottom: 0;
  width: 100%;
  text-align: right;
  height: 30px;
  line-height: 30px;
  padding-right: 20px;
}
footer a{
  color: white;
}
article {
  z-index: 100;
  width: 50%;
  max-width: 350px;
  font-size: 15px;
  color: white;
  padding: 20px;
  border-radius: 0 0 5px 0;
}
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
canvas.height = window.innerHeight;
canvas.width = window.innerWidth;

// load images
const images = {};
images.player = new Image();
images.player.src = 'https://i.ibb.co/Ybk7y06/character.png';
const characterActions = ['up', 'top right', 'right', 'down right', 'down'];
const numberOfCharacters = 25;
const characters = [];

class Character {
    constructor(){
        this.width = 40;
        this.height = 43.875;
        this.frameX = 3;
        this.x = Math.random() * canvas.width - this.width;
        this.y = Math.random() * canvas.height - this.height;
        this.speed = (Math.random() * 2) + 3;
        this.minFrame = 0;
        this.action = characterActions[Math.floor(Math.random() * characterActions.length)];
        if (this.action === 'up') {
            this.frameY = 0; 
            this.minFrame = 4;
            this.maxFrame = 15;
        }
        else if (this.action === 'top right') {
            this.frameY = 1; 
            this.minFrame = 4;
            this.maxFrame = 14;
        }
        else if (this.action === 'right') {
            this.frameY = 3; 
            this.minFrame = 3;
            this.maxFrame = 13;
        }
        else if (this.action === 'down right') {
            this.frameY = 4;
            this.minFrame = 4;
            this.maxFrame = 15;
        } 
        else if (this.action === 'down') {
            this.minFrame = 0;
            this.frameY = 6;
            this.maxFrame = 12;
        }
        else if (this.action === 'jump') {
            this.minFrame = 0;
            this.frameY = 7; 
            this.maxFrame = 9;
        }

    }
    draw(){
        drawSprite(images.player, this.width * this.frameX, this.height * this.frameY, this.width, this.height, this.x, this.y, this.width * 1.5, this.height * 1.5);
        
        if (this.frameX < this.maxFrame) this.frameX++;
        else this.frameX = this.minFrame;
    }
    update(){
        if (this.action === 'up') {
            if (this.y < 0 - (this.height * 5)) {
                 this.y = canvas.height + this.height;
                 this.x = Math.random() * canvas.width;
                 this.speed = (Math.random() * 2) + 3;
             } else {
                 this.y -= this.speed;  
             }
         }
         else if (this.action === 'top right') {
             if (this.y < 0 - this.height && this.x > canvas.width + this.width) {
                 this.y = canvas.height + this.height
                 this.x = Math.random() * canvas.width;
                 this.speed = (Math.random() * 2) + 3;
             } else {
                 this.y -= this.speed; 
                 this.x += this.speed; 
             }
         }
         else if (this.action === 'right') {
             if (this.x > canvas.width + (this.width * 5)) {
                 this.x = 0 - this.width;
                 this.y = Math.random() * canvas.height; 
                 this.speed = (Math.random() * 2) + 3;
             } else {
                 this.x += this.speed; 
             }
         }
         else if (this.action === 'down right') {
             if (this.y > canvas.height + this.height && this.x > canvas.width + this.width) {
                 this.y = 0 - this.height
                 this.x = Math.random() * canvas.width;
                 this.speed = (Math.random() * 2) + 3;
             } else {
                 this.y += this.speed; 
                 this.x += this.speed; 
             }
         } 
         else if (this.action === 'down') {
             if (this.y > canvas.height + (this.height * 5)) {
                 this.y = 0 - this.height;
                 this.x = Math.random() * canvas.width;
                 this.speed = (Math.random() * 2) + 3;
             } else {
                 this.y += this.speed;  
             }
         }
         else if (this.action === 'jump') {
 
         }
    }
}

for (i = 0; i < numberOfCharacters; i++){
    characters.push(new Character());
}


function drawSprite(img, sX, sY, sW, sH, dX, dY, dW, dH){
    ctx.drawImage(img, sX, sY, sW, sH, dX, dY, dW, dH);
}

function animate(){
    ctx.clearRect(0,0,canvas.width, canvas.height);
    for (i = 0; i < characters.length; i++ ){
        characters[i].draw();
        characters[i].update();
    }

}

window.onload = setInterval(animate, 1000/20);

window.addEventListener('resize', function(){
    canvas.height = window.innerHeight;
    canvas.width = window.innerWidth;
})
Run Pen

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.