diff --git a/index.html b/index.html index 40b8c64..ff27b56 100644 --- a/index.html +++ b/index.html @@ -37,6 +37,7 @@ + diff --git a/main.js b/main.js index 2c3473f..c962bbc 100644 --- a/main.js +++ b/main.js @@ -196,14 +196,13 @@ class Graphics { this.ctx_.fillText(string, x, y); } - drawImage(image, dx, dy) { - const src = image[0]; - const sx = image[1]; - const sy = image[2]; - const width = image[3]; - const height = image[4]; + drawSprite(sprite, dx, dy) { this.ctx_.drawImage( - src, sx, sy, width, height, dx, dy, width, height); + sprite.image, + sprite.ulx, sprite.uly, + sprite.width, sprite.height, + dx, dy, + sprite.width, sprite.height); } } @@ -248,7 +247,11 @@ class World { update(timestampMs) { this.fpsCounter_.update(timestampMs); + const wasRPressed = this.input_.r; this.input_.update(); + if (!wasRPressed && this.input_.r) { + this.player_.cycleSprite(); + } if (this.input_.left) { this.player_.moveLeft(); } @@ -272,40 +275,71 @@ class World { } } +class Sprite { + constructor(image, ulx, uly, width, height) { + this.image = image; + this.ulx = ulx; + this.uly = uly; + this.width = width; + this.height = height; + } +} + +class CharacterSprite { + constructor(image, ulx, uly, tileWidth, tileHeight) { + // Assumption: a character sprite consists of 4 rows, which include the + // character facing down, left, right, up (in that order). Each row has 3 + // columns, which can be used for a walking animation. + this.down = []; + this.left = []; + this.right = []; + this.up = []; + for (let i = 0; i < 3; i++) { + const x = ulx + i * tileWidth; + this.down.push(new Sprite( + image, x, uly, tileWidth, tileHeight)); + this.left.push(new Sprite( + image, x, uly + tileHeight, tileWidth, tileHeight)); + this.right.push(new Sprite( + image, x, uly + tileHeight * 2, tileWidth, tileHeight)); + this.up.push(new Sprite( + image, x, uly + tileHeight * 3, tileWidth, tileHeight)); + } + } +} + class Resources { constructor() { const atlantis = document.getElementById('atlantis'); const ghost = document.getElementById('ghost'); + const cats = document.getElementById('cats'); const ts = 16; this.sprites = { - 'ground0': [atlantis, 2 * ts, 1 * ts, 16, 16], - 'ground1': [atlantis, 3 * ts, 1 * ts, 16, 16], - 'ground2': [atlantis, 4 * ts, 1 * ts, 16, 16], - 'ground3': [atlantis, 5 * ts, 1 * ts, 16, 16], - 'ground4': [atlantis, 6 * ts, 1 * ts, 16, 16], - 'ground5': [atlantis, 7 * ts, 1 * ts, 16, 16], - 'ground6': [atlantis, 8 * ts, 1 * ts, 16, 16], - 'rock0': [atlantis, 1 * ts, 2 * ts, 16, 16], - 'rock1': [atlantis, 2 * ts, 2 * ts, 16, 16], - 'rock2': [atlantis, 3 * ts, 2 * ts, 16, 16], - 'anchor0': [atlantis, 21 * ts, 1 * ts, 16, 16], - 'seaweed0': [atlantis, 20 * ts, 2 * ts, 16, 32], - 'seaweed1': [atlantis, 16 * ts, 2 * ts, 16, 32], - 'coral0': [atlantis, 15 * ts, 9 * ts, 32, 16], - 'rockpile0': [atlantis, 17 * ts, 10 * ts, 32, 32], - - 'ghostdown0': [ghost, 0, 0, 24, 36], - 'ghostdown1': [ghost, 26, 0, 24, 36], - 'ghostdown2': [ghost, 52, 0, 24, 36], - 'ghostleft0': [ghost, 0, 36, 24, 36], - 'ghostleft1': [ghost, 26, 36, 24, 36], - 'ghostleft2': [ghost, 52, 36, 24, 36], - 'ghostright0': [ghost, 0, 72, 24, 36], - 'ghostright1': [ghost, 26, 72, 24, 36], - 'ghostright2': [ghost, 52, 72, 24, 36], - 'ghostup0': [ghost, 0, 108, 24, 36], - 'ghostup1': [ghost, 26, 108, 24, 36], - 'ghostup2': [ghost, 52, 108, 24, 36], + 'ground0': new Sprite(atlantis, 2 * ts, 1 * ts, 16, 16), + 'ground1': new Sprite(atlantis, 3 * ts, 1 * ts, 16, 16), + 'ground2': new Sprite(atlantis, 4 * ts, 1 * ts, 16, 16), + 'ground3': new Sprite(atlantis, 5 * ts, 1 * ts, 16, 16), + 'ground4': new Sprite(atlantis, 6 * ts, 1 * ts, 16, 16), + 'ground5': new Sprite(atlantis, 7 * ts, 1 * ts, 16, 16), + 'ground6': new Sprite(atlantis, 8 * ts, 1 * ts, 16, 16), + 'rock0': new Sprite(atlantis, 1 * ts, 2 * ts, 16, 16), + 'rock1': new Sprite(atlantis, 2 * ts, 2 * ts, 16, 16), + 'rock2': new Sprite(atlantis, 3 * ts, 2 * ts, 16, 16), + 'anchor0': new Sprite(atlantis, 21 * ts, 1 * ts, 16, 16), + 'seaweed0': new Sprite(atlantis, 20 * ts, 2 * ts, 16, 32), + 'seaweed1': new Sprite(atlantis, 16 * ts, 2 * ts, 16, 32), + 'coral0': new Sprite(atlantis, 15 * ts, 9 * ts, 32, 16), + 'rockpile0': new Sprite(atlantis, 17 * ts, 10 * ts, 32, 32), + + 'ghost': new CharacterSprite(ghost, 0, 0, 26, 36), + 'cat0': new CharacterSprite(cats, 0, 0, 26, 36), + 'cat1': new CharacterSprite(cats, 26 * 3, 0, 26, 36), + 'cat2': new CharacterSprite(cats, 26 * 6, 0, 26, 36), + 'cat3': new CharacterSprite(cats, 26 * 9, 0, 26, 36), + 'cat4': new CharacterSprite(cats, 0, 36 * 4, 26, 36), + 'cat5': new CharacterSprite(cats, 26 * 3, 36 * 4, 26, 36), + 'cat6': new CharacterSprite(cats, 26 * 6, 36 * 4, 26, 36), + 'cat7': new CharacterSprite(cats, 26 * 9, 36 * 4, 26, 36), } } } @@ -316,6 +350,21 @@ class Player { this.x = (SNES_WIDTH - 26) / 2; this.y = (SNES_HEIGHT - 36) / 2; this.orientation = Orientation.DOWN; + this.spriteNames_ = [ + 'ghost', 'cat0', 'cat1', 'cat2', 'cat3', 'cat4', 'cat5', 'cat6', + 'cat7']; + this.spriteNamesIdx_ = 3; + } + + get spriteName() { + return this.spriteNames_[this.spriteNamesIdx_]; + } + + cycleSprite() { + this.spriteNamesIdx_++; + if (this.spriteNamesIdx_ >= this.spriteNames_.length) { + this.spriteNamesIdx_ = 0; + } } moveLeft() { @@ -359,8 +408,8 @@ class PlayerRenderer { draw(gfx, sprites, player) { let spriteIndex = Math.floor((this.frameNum % 40) / 10); if (spriteIndex == 3) { spriteIndex = 1; } - const spriteName = 'ghost' + player.orientation + spriteIndex; - gfx.drawImage(sprites[spriteName], player.x, player.y); + const charSprite = sprites[player.spriteName][player.orientation][spriteIndex]; + gfx.drawSprite(charSprite, player.x, player.y); this.frameNum++; } } @@ -423,7 +472,7 @@ class TileRenderer { const dy = tileSize * i; const sprite = spriteLookup[layer1[i][j]]; if (sprite) { - gfx.drawImage(sprite, dx, dy); + gfx.drawSprite(sprite, dx, dy); } } } @@ -433,12 +482,11 @@ class TileRenderer { const dy = tileSize * i; const sprite = spriteLookup[layer2[i][j]]; if (sprite) { - gfx.drawImage(sprite, dx, dy); + gfx.drawSprite(sprite, dx, dy); } } } } - } class GamepadRenderer {