diff --git a/src/debug.js b/src/debug.js index 43c4581..e2db9cb 100644 --- a/src/debug.js +++ b/src/debug.js @@ -1,4 +1,5 @@ import { ctx } from './canvas' +import Input from './input' class Debugging { constructor () { @@ -6,9 +7,12 @@ class Debugging { this.overlay.style = 'color:#fff;position:absolute;top:15px;right:15px;background-color:hsla(0,0%,47%,0.5);padding:10px;display:flex;flex-direction:column;' document.body.appendChild(this.overlay) this.drawGrid = false + this.infotext = true + this.addCheckbox(this, 'infotext') } draw (vp, world, fps) { + if (!this.infotext) return let p = vp.chunkIn(world.chunkSize * world.tileSize) ctx.fillStyle = '#fff' ctx.fillText(fps + ' fps', 4, 16) @@ -17,6 +21,14 @@ class Debugging { ctx.fillText('loaded ' + world.chunks.length, 4, 16 * 4) ctx.fillText('drawn ' + world._lastDrawCount, 4, 16 * 5) ctx.fillText('updates ' + world._lastUpdateCount, 4, 16 * 6) + // Mouse + let mpos = Input.mouse.pos + let mpin = world.pickMouse(vp, mpos) + ctx.fillText('mouse (x: ' + mpos.x + '; y: ' + mpos.y + ')', 4, 16 * 8) + if (mpin.chunk) { + ctx.fillText('mouse-in-chunk (x: ' + mpin.chunk.x + '; y: ' + mpin.chunk.y + ')', 4, 16 * 9) + ctx.fillText('mouse-in-tile (x: ' + mpin.tile.x + '; y: ' + mpin.tile.y + ')', 4, 16 * 10) + } } createSliders (obj, args, fn) { @@ -40,7 +52,7 @@ class Debugging { slider.addEventListener('input', function (e) { obj[a] = parseFloat(slider.value) value.innerHTML = slider.value - fn(a, slider.value) + fn && fn(a, slider.value) }) div.appendChild(name) div.appendChild(slider) @@ -60,7 +72,7 @@ class Debugging { checkbox.checked = obj[arg] === true checkbox.addEventListener('change', function (e) { obj[arg] = checkbox.checked - fn(arg, obj[arg]) + fn && fn(arg, obj[arg]) }) div.appendChild(checkbox) div.appendChild(name) diff --git a/src/index.js b/src/index.js index 96d9883..abb7d8b 100644 --- a/src/index.js +++ b/src/index.js @@ -12,7 +12,7 @@ let frameTime = 0 let frameCount = 0 let fps = 0 -let vp = new Viewport(0, 0) +let vp = new Viewport(1111, 900) let height = new HeightMap(0, 32, 16, 0) let map = new TileMap('assets/ground.png', 32) @@ -87,6 +87,18 @@ function update (dt) { } else if (vp.y + vp.height > world.height * full) { vp.y = (full * world.height) - vp.height } + + if (Input.mouse['btn0']) { + let mpin = world.pickMouse(vp, Input.mouse.pos) + if (mpin.chunk) { + mpin.chunk.setTile('fg', mpin.tile, map.indexOf('DIRT')) + } + } else if (Input.mouse['btn2']) { + let mpin = world.pickMouse(vp, Input.mouse.pos) + if (mpin.chunk) { + mpin.chunk.setTile('fg', mpin.tile, map.indexOf('AIR')) + } + } } function draw () { diff --git a/src/input.js b/src/input.js index ecc59de..79d2d7f 100644 --- a/src/input.js +++ b/src/input.js @@ -73,7 +73,6 @@ class Input { this.mouse = { pos: { x: 0, y: 0 }, - frame: { x: 0, y: 0 }, previous: { x: 0, y: 0 } } @@ -103,8 +102,8 @@ class Input { x -= canvas.offsetLeft y -= canvas.offsetTop - this.mouse.frame.x = x - this.mouse.frame.y = y + this.mouse.pos.x = x + this.mouse.pos.y = y }, false) canvas.addEventListener('mousedown', (e) => { @@ -212,11 +211,6 @@ class Input { // Mouse positions in the previous frame this.mouse.previous.x = this.mouse.pos.x this.mouse.previous.y = this.mouse.pos.y - - // Mouse positions in the current frame - // Convert to OpenGL coordinate system - this.mouse.pos.x = this.mouse.frame.x / this.canvas.width * 2 - 1 - this.mouse.pos.y = this.mouse.frame.y / this.canvas.height * 2 - 1 } } diff --git a/src/tiles.js b/src/tiles.js index aa40c55..3b351ad 100644 --- a/src/tiles.js +++ b/src/tiles.js @@ -59,6 +59,18 @@ class TileLayer { this.tiles = [] } + setTile (x, y, i) { + if (typeof x === 'object') { + if (!i && y) i = y + y = x.y + x = x.x + } + let t = this.tileAtXY(x, y) + if (!t || t === i) return false + this.tiles[x + this.size * y] = i + return true + } + tileAt (i) { return this.tiles[i] } @@ -95,6 +107,7 @@ class Chunk { this.tile = tileSize this.layers = [] this.dirty = true + this.modified = false this.img = null this._updated = false } @@ -128,6 +141,28 @@ class Chunk { this.dirty = true } + getLayer (name) { + for (let i in this.layers) { + let layer = this.layers[i] + if (layer.name === name) return layer + } + return null + } + + setTile (layer, x, y, tile) { + if (!tile && typeof x !== 'object') { + tile = y + y = x.y + x = x.x + } + let l = this.getLayer(layer) + if (!l) return false + if (!l.setTile(x, y, tile)) return false + this.dirty = true + this.modified = true + return true + } + toAbs (x, y) { if (typeof x === 'object') { y = x.y @@ -145,6 +180,12 @@ class Chunk { } draw (view, map) { + if (this.img) { + // Draw the cached image + let p = this.absPos + ctx.drawImage(this.img, p.x - view.x, p.y - view.y) + } + // Create a cached image of the chunk if (this.dirty || !this.img) { cacheFactory.prepare(this.size * this.tile, this.size * this.tile) @@ -163,11 +204,7 @@ class Chunk { // Don't update again next tick this.dirty = false this._updated = true - return } - // Draw the cached image - let p = this.absPos - ctx.drawImage(this.img, p.x - view.x, p.y - view.y) } update (dt) { @@ -241,15 +278,25 @@ class World { } } + pickMouse (vp, mousePos) { + let a = this.chunkSize * this.tileSize + let abs = { x: mousePos.x + vp.x, y: mousePos.y + vp.y } + let chunk = { x: Math.floor(abs.x / a), y: Math.floor(abs.y / a) } + let tile = { + x: Math.floor(abs.x / this.tileSize - chunk.x * this.chunkSize), + y: Math.floor(abs.y / this.tileSize - chunk.y * this.chunkSize) + } + return { chunk: this.getChunk(chunk.x, chunk.y), tile } + } + draw (vp) { this._lastDrawCount = 0 this._lastUpdateCount = 0 - const adj = this.tileSize for (let i in this.chunks) { let chunk = this.chunks[i] let absPos = chunk.absPos - if (absPos.x > vp.x + vp.width + adj || absPos.x + chunk.fullSize < vp.x - adj || - absPos.y > vp.y + vp.height + adj || absPos.y + chunk.fullSize < vp.y - adj) continue + if (absPos.x > vp.x + vp.width + this.tileSize || absPos.x + chunk.fullSize < vp.x - this.tileSize || + absPos.y > vp.y + vp.height + this.tileSize || absPos.y + chunk.fullSize < vp.y - this.tileSize) continue chunk._updated = false chunk.draw(vp, this.tileMaps.GROUND) if (chunk._updated) this._lastUpdateCount++