add tiled background rendering and one ghosty boi
This commit is contained in:
parent
d7a88b6d67
commit
ce3ee42c4e
@ -21,13 +21,15 @@
|
||||
<body>
|
||||
<!-- SNES resolution: 256x224. 4x scaled: 1024 x 896. -->
|
||||
<canvas id="canvas" width="256" height="224"></canvas>
|
||||
<div id="fps"></div>
|
||||
<div id="debug"></div>
|
||||
<button id="1x">1x</button>
|
||||
<button id="2x">2x</button>
|
||||
<button id="3x">3x</button>
|
||||
<button id="4x">4x</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>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
215
main.js
215
main.js
@ -1,3 +1,10 @@
|
||||
const Orientation = {
|
||||
UP: 'up',
|
||||
DOWN: 'down',
|
||||
LEFT: 'left',
|
||||
RIGHT: 'right'
|
||||
}
|
||||
|
||||
class Input {
|
||||
constructor() {
|
||||
this.left = false;
|
||||
@ -13,6 +20,8 @@ class Input {
|
||||
this.select = false;
|
||||
this.start = false;
|
||||
|
||||
this.leftArrowPressed = false;
|
||||
this.rightArrowPressed = false;
|
||||
window.addEventListener('gamepadconnected', this.gamepadConnected);
|
||||
window.addEventListener('gamepaddisconnected', this.gamepadDisconnected);
|
||||
}
|
||||
@ -140,6 +149,16 @@ class Graphics {
|
||||
this.ctx_.font = '' + size + 'px monospace';
|
||||
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 {
|
||||
@ -162,7 +181,8 @@ class FpsCounter {
|
||||
}
|
||||
|
||||
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.fpsCounter_ = new FpsCounter();
|
||||
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();
|
||||
}
|
||||
|
||||
update(timestampMs) {
|
||||
this.fpsCounter_.update(timestampMs);
|
||||
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) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
draw(gfx, input) {
|
||||
const centerX = gfx.width / 2;
|
||||
const centerY = gfx.height / 2;
|
||||
|
||||
gfx.fill('black');
|
||||
|
||||
// Select & Start
|
||||
gfx.circle(centerX + 12, centerY, 8, input.start ? 'cyan' : 'grey');
|
||||
gfx.circle(centerX - 12, centerY, 8, input.select ? 'cyan' : 'grey');
|
||||
|
Loading…
Reference in New Issue
Block a user