add tiled background rendering and one ghosty boi
This commit is contained in:
parent
d7a88b6d67
commit
ce3ee42c4e
@ -21,13 +21,15 @@
|
|||||||
<body>
|
<body>
|
||||||
<!-- SNES resolution: 256x224. 4x scaled: 1024 x 896. -->
|
<!-- SNES resolution: 256x224. 4x scaled: 1024 x 896. -->
|
||||||
<canvas id="canvas" width="256" height="224"></canvas>
|
<canvas id="canvas" width="256" height="224"></canvas>
|
||||||
|
<div id="fps"></div>
|
||||||
<div id="debug"></div>
|
<div id="debug"></div>
|
||||||
<button id="1x">1x</button>
|
<button id="1x">1x</button>
|
||||||
<button id="2x">2x</button>
|
<button id="2x">2x</button>
|
||||||
<button id="3x">3x</button>
|
<button id="3x">3x</button>
|
||||||
<button id="4x">4x</button>
|
<button id="4x">4x</button>
|
||||||
<button id="5x">5x</button>
|
<button id="5x">5x</button>
|
||||||
|
<img src="resources/tf_atlantis_tiles.png" id="atlantis" style="display: none">
|
||||||
|
<img src="resources/ghost1.png" id="ghost" style="display: none">
|
||||||
<script src="main.js"></script>
|
<script src="main.js"></script>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
215
main.js
215
main.js
@ -1,3 +1,10 @@
|
|||||||
|
const Orientation = {
|
||||||
|
UP: 'up',
|
||||||
|
DOWN: 'down',
|
||||||
|
LEFT: 'left',
|
||||||
|
RIGHT: 'right'
|
||||||
|
}
|
||||||
|
|
||||||
class Input {
|
class Input {
|
||||||
constructor() {
|
constructor() {
|
||||||
this.left = false;
|
this.left = false;
|
||||||
@ -13,6 +20,8 @@ class Input {
|
|||||||
this.select = false;
|
this.select = false;
|
||||||
this.start = false;
|
this.start = false;
|
||||||
|
|
||||||
|
this.leftArrowPressed = false;
|
||||||
|
this.rightArrowPressed = false;
|
||||||
window.addEventListener('gamepadconnected', this.gamepadConnected);
|
window.addEventListener('gamepadconnected', this.gamepadConnected);
|
||||||
window.addEventListener('gamepaddisconnected', this.gamepadDisconnected);
|
window.addEventListener('gamepaddisconnected', this.gamepadDisconnected);
|
||||||
}
|
}
|
||||||
@ -140,6 +149,16 @@ class Graphics {
|
|||||||
this.ctx_.font = '' + size + 'px monospace';
|
this.ctx_.font = '' + size + 'px monospace';
|
||||||
this.ctx_.fillText(string, x, y);
|
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];
|
||||||
|
this.ctx_.drawImage(
|
||||||
|
src, sx, sy, width, height, dx, dy, width, height);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class FpsCounter {
|
class FpsCounter {
|
||||||
@ -162,7 +181,8 @@ class FpsCounter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
draw(gfx) {
|
draw(gfx) {
|
||||||
gfx.text('FPS: ' + Math.round(this.fps), 8, 16, 16, 'yellow');
|
const fpsDiv = document.getElementById('fps');
|
||||||
|
fpsDiv.innerText = 'FPS: ' + Math.round(this.fps);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -171,27 +191,214 @@ class World {
|
|||||||
this.state_ = null;
|
this.state_ = null;
|
||||||
this.fpsCounter_ = new FpsCounter();
|
this.fpsCounter_ = new FpsCounter();
|
||||||
this.input_ = new Input();
|
this.input_ = new Input();
|
||||||
|
this.player_ = new Player();
|
||||||
|
|
||||||
|
// TODO: move rendering stuff to a separate object.
|
||||||
|
this.resources_ = new Resources();
|
||||||
|
this.tileRenderer_ = new TileRenderer();
|
||||||
|
this.playerRenderer_ = new PlayerRenderer();
|
||||||
this.gamepadRenderer_ = new GamepadRenderer();
|
this.gamepadRenderer_ = new GamepadRenderer();
|
||||||
}
|
}
|
||||||
|
|
||||||
update(timestampMs) {
|
update(timestampMs) {
|
||||||
this.fpsCounter_.update(timestampMs);
|
this.fpsCounter_.update(timestampMs);
|
||||||
this.input_.update();
|
this.input_.update();
|
||||||
|
if (this.input_.left) {
|
||||||
|
this.player_.moveLeft();
|
||||||
|
}
|
||||||
|
if (this.input_.right) {
|
||||||
|
this.player_.moveRight();
|
||||||
|
}
|
||||||
|
if (this.input_.up) {
|
||||||
|
this.player_.moveUp();
|
||||||
|
}
|
||||||
|
if (this.input_.down) {
|
||||||
|
this.player_.moveDown();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
draw(gfx) {
|
draw(gfx) {
|
||||||
this.gamepadRenderer_.draw(gfx, this.input_);
|
gfx.fill('black');
|
||||||
|
this.tileRenderer_.draw(gfx, this.resources_.sprites);
|
||||||
|
this.playerRenderer_.draw(gfx, this.resources_.sprites, this.player_);
|
||||||
|
// this.gamepadRenderer_.draw(gfx, this.input_);
|
||||||
this.fpsCounter_.draw(gfx);
|
this.fpsCounter_.draw(gfx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class Resources {
|
||||||
|
constructor() {
|
||||||
|
const atlantis = document.getElementById('atlantis');
|
||||||
|
const ghost = document.getElementById('ghost');
|
||||||
|
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],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Player {
|
||||||
|
constructor() {
|
||||||
|
this.x = (256 - 26) / 2;
|
||||||
|
this.y = (224 - 36) / 2;
|
||||||
|
this.orientation = Orientation.DOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
moveLeft() {
|
||||||
|
this.orientation = Orientation.LEFT;
|
||||||
|
this.x -= 2;
|
||||||
|
if (this.x < -4) {
|
||||||
|
this.x = -4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
moveRight() {
|
||||||
|
this.orientation = Orientation.RIGHT;
|
||||||
|
this.x += 2;
|
||||||
|
if (this.x > 256 - 21) {
|
||||||
|
this.x = 256 - 21;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
moveUp() {
|
||||||
|
this.orientation = Orientation.UP;
|
||||||
|
this.y -= 2;
|
||||||
|
if (this.y < -7) {
|
||||||
|
this.y = -7;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
moveDown() {
|
||||||
|
this.orientation = Orientation.DOWN;
|
||||||
|
this.y += 2;
|
||||||
|
if (this.y > 224 - 36) {
|
||||||
|
this.y = 224 - 36;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class PlayerRenderer {
|
||||||
|
constructor() {
|
||||||
|
this.frameNum = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
this.frameNum++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class TileRenderer {
|
||||||
|
draw(gfx, sprites) {
|
||||||
|
const tileSize = 16;
|
||||||
|
const rows = gfx.height / tileSize;
|
||||||
|
const columns = gfx.width / tileSize;
|
||||||
|
const layer1 = ["-,*-...*'.,-_'`o",
|
||||||
|
"_..'-_**,',_.'oo",
|
||||||
|
"-*-''_-'o,0O_```",
|
||||||
|
"o`0_._,*O'`--'-'",
|
||||||
|
"`0O-_'',`o*o*`-,",
|
||||||
|
"*,`'---o'O'_*''-",
|
||||||
|
"'-.**.'_'`.,'-.'",
|
||||||
|
".O'``*``'`*,,_o`",
|
||||||
|
"_*_''*O'`_OO-_'o",
|
||||||
|
"0`0,*-,`_*'`O'*.",
|
||||||
|
".o'-*.*_',`,,`.'",
|
||||||
|
"`o`O',.`OO,*-'**",
|
||||||
|
"-..*'-''',*'.'.O",
|
||||||
|
"*-_'-0.--__O`O`_",
|
||||||
|
"*-_,O_'*'`*'_._.",
|
||||||
|
"-.*,`OO'_`'*-0-O"];
|
||||||
|
const layer2 = [" ",
|
||||||
|
" ",
|
||||||
|
" iil ",
|
||||||
|
" ",
|
||||||
|
" A ",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
" i ",
|
||||||
|
" l ",
|
||||||
|
" ",
|
||||||
|
" c R ",
|
||||||
|
" "];
|
||||||
|
const spriteLookup = {
|
||||||
|
'.': sprites.ground0,
|
||||||
|
',': sprites.ground1,
|
||||||
|
'_': sprites.ground2,
|
||||||
|
'`': sprites.ground3,
|
||||||
|
'-': sprites.ground4,
|
||||||
|
'*': sprites.ground5,
|
||||||
|
"'": sprites.ground6,
|
||||||
|
'o': sprites.rock0,
|
||||||
|
'O': sprites.rock1,
|
||||||
|
'0': sprites.rock2,
|
||||||
|
'A': sprites.anchor0,
|
||||||
|
'i': sprites.seaweed0,
|
||||||
|
'l': sprites.seaweed1,
|
||||||
|
'c': sprites.coral0,
|
||||||
|
'R': sprites.rockpile0,
|
||||||
|
};
|
||||||
|
for (let j = 0; j < columns; j++) {
|
||||||
|
for (let i = 0; i < rows; i++) {
|
||||||
|
const dx = tileSize * j;
|
||||||
|
const dy = tileSize * i;
|
||||||
|
const sprite = spriteLookup[layer1[i][j]];
|
||||||
|
if (sprite) {
|
||||||
|
gfx.drawImage(sprite, dx, dy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (let j = 0; j < columns; j++) {
|
||||||
|
for (let i = 0; i < rows; i++) {
|
||||||
|
const dx = tileSize * j;
|
||||||
|
const dy = tileSize * i;
|
||||||
|
const sprite = spriteLookup[layer2[i][j]];
|
||||||
|
if (sprite) {
|
||||||
|
gfx.drawImage(sprite, dx, dy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
class GamepadRenderer {
|
class GamepadRenderer {
|
||||||
draw(gfx, input) {
|
draw(gfx, input) {
|
||||||
const centerX = gfx.width / 2;
|
const centerX = gfx.width / 2;
|
||||||
const centerY = gfx.height / 2;
|
const centerY = gfx.height / 2;
|
||||||
|
|
||||||
gfx.fill('black');
|
|
||||||
|
|
||||||
// Select & Start
|
// Select & Start
|
||||||
gfx.circle(centerX + 12, centerY, 8, input.start ? 'cyan' : 'grey');
|
gfx.circle(centerX + 12, centerY, 8, input.start ? 'cyan' : 'grey');
|
||||||
gfx.circle(centerX - 12, centerY, 8, input.select ? 'cyan' : 'grey');
|
gfx.circle(centerX - 12, centerY, 8, input.select ? 'cyan' : 'grey');
|
||||||
|
Loading…
Reference in New Issue
Block a user