A Simple Sprite Class

The Sprites

Images courtesy of software_atelier at https://opengameart.org/content/cowboy Modified into character sheets by me.

The HTML File

<script type="text/javascript" src="code/scene.js"></script>
<script type="text/javascript" src="code/sprite.js"></script>

<h1>A Simple Sprite Class</h1>
<canvas id="oldWest" width="400" height="400" style="border:1px solid #000000;"></canvas>

<script type="text/javascript">
Setup("oldWest");
</script>

scene.js


"use strict"

let count =0;
let timer;
let sprites = [];

const SPRITE_FILES =["idle.png","idleGun.png","jump.png","shoot.png","walk.png","walkGun.png"];

function Setup(canvas){
   
   for(let i=0;i<SPRITE_FILES.length; i++) {
      sprites.push(
         new Sprite(canvas, "cowboy/"+SPRITE_FILES[i],40,40,4)
      );
      sprites[i].Pos = {x:40, y:i*50};
   }
   

   timer = setInterval(NextFrame, 200);

   return;
}


function NextFrame() {

   console.log("Drawing the next frame");
   for(let i=0; i< sprites.length; i++) {
      sprites[i].Draw();

      let pos = sprites[i].Pos;

      if (i == 2) {
          let sign = 3-count%7;
          pos.y += sign*2;
      } else if (i == 4 || i == 5) {
          pos.x+= 3;
      }

      sprites[i].Pos = pos;
   }

   count++;
   if (count > 100) {
       clearInterval(timer);
   }

   return;
}

sprite.js

"use strict"
const IMAGE_PATH = "img/";

class Sprite{
    constructor (canvasName, imageName = "player.png", 
                 width = 24, height = 30,frames = 8) {

       // canvas info
       this.ctx = document.getElementById(canvasName).getContext("2d");
       this.image = document.createElement("img");
       let path = IMAGE_PATH+ imageName;
       this.image.src = path;

       // don't start drawing  until the image is loaded.
       this.draw = false;

       // let me know when the image is loaded
       this.image.addEventListener("load", this, false);

       // drawing information
       this.width = width;
       this.height = height;

       this.frames = frames;

       this.cycle = 0;

       // dorawing location
       this.x = 0;
       this.y = 0;
       this.oldx = 0;
       this.oldy = 0;

       // moving information
       this.dx = 0;
       this.dy = 0;
       this.steps = 0;
       this.moving = false;
       this.timer = 0;

       // bounds information
       this.maxx = document.getElementById(canvasName).width;
       this.maxy = document.getElementById(canvasName).height;

       return;
    }

    handleEvent(e) {
       this.draw = true;
       this.Draw();
       return;
    }

    get Pos() {
       return {x:this.x, y:this.y};
    }

    set Pos( pos) {
       this.x = pos.x;
       this.y = pos.y;
       return;
    }

    get Bounds() {
        return({width:this.width, height: this.height});
    }

    Draw() {
        if(this.draw) {
            let width = this.width;
            let height = this.height;

            this.ctx.clearRect(this.oldx, this.oldy, width, height);
            this.oldx = this.x;
            this.oldy= this.y;

            this.ctx.drawImage(this.image, 
                            this.cycle*width, 0, width, height,
                            this.x, this.y, width, height);
            this.cycle = (this.cycle + 1) % this.frames;
        }
        return;
    }

    DoMove() {
        // make a bounded move
        let x = this.x + this.dx;
        let y = this.y + this.dy;
        if ( x > 0 && x+this.width < this.maxx && 
             y > 0 && y+this.height < this.maxy) {
           this.x = x;
           this.y = y;
        }

        this.steps--;
        this.Draw();

        // If I am done moving
        if (this.steps <= 0) {
            this.moving = false;
            this.steps =0;
            this.dx = 0;
            this.dy = 0;
        } else {
           // else keep going.
           // .bind(this) is very important
           this.timer = setTimeout(this.DoMove.bind(this), 100);
        }

    }

    Move(dx, dy, steps=100) {
       // do this only if I am not moving.
       if (!this.moving) {
           this.dx = dx;
           this.dy = dy;
           this.steps = steps;
           this.moving = true;
           // .bind(this) is very important
           this.timer = setTimeout(this.DoMove.bind(this), 100);
       }
    }

}