From 4b7f58dfab69ca235dc37c65c8b7ffb2c0ff4526 Mon Sep 17 00:00:00 2001 From: Evert Prants Date: Tue, 14 Jan 2020 21:33:17 +0200 Subject: [PATCH] mining drill and tile damage --- assets/item_drill.png | Bin 0 -> 553 bytes src/index.js | 4 ++- src/inventory.js | 3 ++- src/items.js | 42 ++++++++++++++++++++++++++++--- src/player.js | 47 +++++++++++++++++----------------- src/register.js | 57 ++++++++++++++++++++++-------------------- src/tiles.js | 42 ++++++++++++++++++++++++++++--- 7 files changed, 136 insertions(+), 59 deletions(-) create mode 100644 assets/item_drill.png diff --git a/assets/item_drill.png b/assets/item_drill.png new file mode 100644 index 0000000000000000000000000000000000000000..5bc8b0460291c1f5566d4809bef34476c882c678 GIT binary patch literal 553 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|*pj^6T^M{A z3>idqOj4_XBAf*tk;M!QddeWoSh3W;3@FH6;_2(k{)CZF$W*;WeQgO)NH#MhqQp5r zH#ap8#ARS`E=o--Nlj5G&n(GMaQE~LNYP7W2U^$Q>Eak-aeD0}!)$3oi8lG2KlP>y zbG|F_*4%fryZs-}|K`4>n{BJkKe#Ddo7~>h>hST|!v7D&^xKj&w%^e;6;XX2EL56N z`t_zJuZcW|%8}nME~+1_pT;!f{Bw!q3sK2yRlAhdZ0$MzcsZln;)&LGUVQ(pb^ddj z?d-F1taE;NinywHHg#;cn-{tMI^TlpuU9H?%yO{d(VTYGP{DK3GpW=_BMBY>!A&}! z%e3U$+$Z$0=a@-vxz^#q{Q2*Wf4?T)Pki3qzLjUqR*B>nWxF%h&eT(5@Zi~Yz_aJn z`c<_vUNJ1mTotxjRLLoFT0}Nb(&J8xWwq>v@=e;)re?)5W_(%R%_*MmBijtw8h%H&?|EY~VR!7=x7%+WzO%Yq(VdM!eqW4|;gzy-mXB%-KSRGh zSC$R4;hB5ngPGOy%~$qV1mAeif9Gx1gK&Sjw~gzQA~mBAET1jEhd=goiv6GPW@lj~ pjwd3U?`=KwpQYl&KFRa3_Ke|2mVExz@T3P6NuI8LF6*2UngBdT-{JrO literal 0 HcmV?d00001 diff --git a/src/index.js b/src/index.js index ab904f2..483c043 100644 --- a/src/index.js +++ b/src/index.js @@ -25,6 +25,8 @@ const tileSize = 16 let world = new World(height, { GROUND: map }, chunkSize, tileSize, 32, 64) +p.inv.addItem('drill') + function update (dt) { world.update(dt, vp) p.update(dt, vp, world) @@ -82,7 +84,7 @@ function start () { async function loadAll () { let images = ['assets/ground.png', 'assets/item_grass.png', - 'assets/item_dirt.png', 'assets/item_stone.png'] + 'assets/item_dirt.png', 'assets/item_stone.png', 'assets/item_drill.png'] for (let i in images) { await RES.loadImage(images[i]) } diff --git a/src/inventory.js b/src/inventory.js index 4842988..a254e4a 100644 --- a/src/inventory.js +++ b/src/inventory.js @@ -1,5 +1,5 @@ import { canvas, ctx } from './canvas' -import { Item, ItemStack, MAX_STACK_SIZE } from './items' +import { Item, ItemTool, ItemStack, MAX_STACK_SIZE } from './items' const SLOT_SIZE = 32 @@ -76,6 +76,7 @@ class Inventory { ctx.fillRect(x, 16, SLOT_SIZE, SLOT_SIZE) if (!stack || stack.isEmpty()) continue ctx.drawImage(stack.item.image, x, 16, SLOT_SIZE, SLOT_SIZE) + if (stack.item instanceof ItemTool) continue ctx.font = '16px sans' let measure = ctx.measureText(stack.count) ctx.fillStyle = '#000' diff --git a/src/items.js b/src/items.js index 35c3056..04cf373 100644 --- a/src/items.js +++ b/src/items.js @@ -1,4 +1,6 @@ import RES from './resource' +import { ItemEntity } from './entity' +import Input from './input' const MAX_STACK_SIZE = 999 @@ -37,9 +39,43 @@ class ItemPlaceable extends Item { } class ItemTool extends Item { - use (dt, world, player) {} + use (dt, vp, world, player) {} - useSecondary (dt, world, player) {} + useSecondary (dt, vp, world, player) {} +} + +class ItemMiningTool extends ItemTool { + constructor (name, img, power, description) { + super(name, img, description) + this.power = power + } + + mine (l, dt, vp, world, player) { + let mabs = { x: Input.mouse.pos.x + vp.x, y: Input.mouse.pos.y + vp.y } + let mpin = world.gridPosition(mabs) + if (!mpin.chunk) return false + let layer = mpin.chunk.getLayer(l) + let tile = layer.tileAtXY(mpin.tile.x, mpin.tile.y) + if (tile === -1) return false + let broken = layer.damageTileAtXY(mpin.tile.x, mpin.tile.y, this.power) + if (!broken) return false + let itile = layer.map.getTileByID(tile) + let success = mpin.chunk.setTile(l, mpin.tile, layer.map.indexOf('AIR')) + if (success) { + let e = ItemEntity.new(ItemStack.new(itile.item, 1), mabs.x - 8, mabs.y - 8) + let p = world.getLayer('ents') + p.entities.push(e) + return true + } + } + + use (dt, vp, world, player) { + return this.mine('fg', dt, vp, world, player) + } + + useSecondary (dt, vp, world, player) { + return this.mine('bg', dt, vp, world, player) + } } class ItemStack { @@ -94,4 +130,4 @@ class ItemStack { } } -export { Item, ItemPlaceable, ItemTool, ItemStack, ItemRegistry, MAX_STACK_SIZE } +export { Item, ItemPlaceable, ItemTool, ItemMiningTool, ItemStack, ItemRegistry, MAX_STACK_SIZE } diff --git a/src/player.js b/src/player.js index 8a034f2..806c6b8 100644 --- a/src/player.js +++ b/src/player.js @@ -16,38 +16,37 @@ class Player extends PhysicsEntity { this.itemPickUpDistance = 40 } - handleTool (dt, vp, world) { + place (layer, vp, world) { let mabs = { x: Input.mouse.pos.x + vp.x, y: Input.mouse.pos.y + vp.y } let mpin = world.gridPosition(mabs) - if (Input.mouse['btn0']) { - if (mpin.chunk) { - if (this.inv.isEmpty(this.inv.selected)) return - let tile = mpin.chunk.getTile('fg', mpin.tile) - if (tile !== -1) return - let itm = this.inv.getItem(this.inv.selected) - if (itm && itm.item.placeable) { - let success = mpin.chunk.setTile('fg', mpin.tile, itm.item.placeable.id) - if (success) { - this.inv.takeItem(this.inv.selected, 1) - } - } - } - } else if (Input.mouse['btn2']) { - if (mpin.chunk) { - let layer = mpin.chunk.getLayer('fg') - let tile = layer.tileAtXY(mpin.tile.x, mpin.tile.y) - if (tile === -1) return - let itile = layer.map.getTileByID(tile) - let success = mpin.chunk.setTile('fg', mpin.tile, layer.map.indexOf('AIR')) + if (mpin.chunk) { + if (this.inv.isEmpty(this.inv.selected)) return + let tile = mpin.chunk.getTile(layer, mpin.tile) + if (tile !== -1) return + let itm = this.inv.getItem(this.inv.selected) + if (itm && itm.item.placeable) { + let success = mpin.chunk.setTile(layer, mpin.tile, itm.item.placeable.id) if (success) { - let e = ItemEntity.new(ItemStack.new(itile.item, 1), mabs.x - 8, mabs.y - 8) - let p = world.getLayer('ents') - p.entities.push(e) + this.inv.takeItem(this.inv.selected, 1) } } } } + handleTool (dt, vp, world) { + if (!Input.mouse['btn0'] && !Input.mouse['btn2']) return + let item = this.inv.getItem(this.inv.selected) + if (item) item = item.item + if (!item) return + if (Input.mouse['btn0']) { + if (item.use) return item.use(dt, vp, world, this) + if (item.placeable) return this.place('fg', vp, world) + } else if (Input.mouse['btn2']) { + if (item.useSecondary) return item.useSecondary(dt, vp, world, this) + if (item.placeable) return this.place('bg', vp, world) + } + } + handleMovement (dt, vp, world) { this.mY += this.gravity if (Input.isDown('a')) { diff --git a/src/register.js b/src/register.js index 011d164..3726526 100644 --- a/src/register.js +++ b/src/register.js @@ -1,17 +1,20 @@ import { Tile, TileMap } from './tiles' -import { ItemPlaceable } from './items' +import { ItemPlaceable, ItemMiningTool } from './items' const map = new TileMap('assets/ground.png', 32) +const dirtStrength = 2 + // Basic tiles -const dirtTile = new Tile('DIRT', 33) -const grassTile = new Tile('GRASS_TOP', 6) -const stoneTile = new Tile('STONE', 10) +const dirtTile = new Tile('DIRT', 33, true, null, dirtStrength) +const grassTile = new Tile('GRASS_TOP', 6, true, null, dirtStrength) +const stoneTile = new Tile('STONE', 10, true, null, 10) // Items for basic tiles const dirtItem = new ItemPlaceable(dirtTile, 'dirt', 'assets/item_dirt.png') const grassItem = new ItemPlaceable(grassTile, 'dirt_with_grass', 'assets/item_grass.png') const stoneItem = new ItemPlaceable(stoneTile, 'stone', 'assets/item_stone.png') +const drill = new ItemMiningTool('drill', 'assets/item_drill.png', 0.5) // Set the items dirtTile.item = dirtItem @@ -20,35 +23,35 @@ stoneTile.item = stoneItem // Register dirt tiles map.register([ - new Tile('DIRT_CORNER_TOP_LEFT', 0, true, dirtItem), - new Tile('DIRT_TOP', 1, true, dirtItem), - new Tile('DIRT_CORNER_TOP_RIGHT', 2, true, dirtItem), - new Tile('DIRT_INNER_BOTTOM_RIGHT', 3, true, dirtItem), - new Tile('DIRT_INNER_BOTTOM_LEFT', 4, true, dirtItem), - new Tile('DIRT_LEFT', 32, true, dirtItem), + new Tile('DIRT_CORNER_TOP_LEFT', 0, true, dirtItem, dirtStrength), + new Tile('DIRT_TOP', 1, true, dirtItem, dirtStrength), + new Tile('DIRT_CORNER_TOP_RIGHT', 2, true, dirtItem, dirtStrength), + new Tile('DIRT_INNER_BOTTOM_RIGHT', 3, true, dirtItem, dirtStrength), + new Tile('DIRT_INNER_BOTTOM_LEFT', 4, true, dirtItem, dirtStrength), + new Tile('DIRT_LEFT', 32, true, dirtItem, dirtStrength), dirtTile, - new Tile('DIRT_RIGHT', 34, true, dirtItem), - new Tile('DIRT_INNER_TOP_RIGHT', 35, true, dirtItem), - new Tile('DIRT_INNER_TOP_LEFT', 36, true, dirtItem), - new Tile('DIRT_CORNER_BOTTOM_LEFT', 64, true, dirtItem), - new Tile('DIRT_BOTTOM', 65, true, dirtItem), - new Tile('DIRT_CORNER_BOTTOM_RIGHT', 66, true, dirtItem) + new Tile('DIRT_RIGHT', 34, true, dirtItem, dirtStrength), + new Tile('DIRT_INNER_TOP_RIGHT', 35, true, dirtItem, dirtStrength), + new Tile('DIRT_INNER_TOP_LEFT', 36, true, dirtItem, dirtStrength), + new Tile('DIRT_CORNER_BOTTOM_LEFT', 64, true, dirtItem, dirtStrength), + new Tile('DIRT_BOTTOM', 65, true, dirtItem, dirtStrength), + new Tile('DIRT_CORNER_BOTTOM_RIGHT', 66, true, dirtItem, dirtStrength) ]) // Register grass tiles map.register([ - new Tile('GRASS_CORNER_TOP_LEFT', 5, true, grassItem), + new Tile('GRASS_CORNER_TOP_LEFT', 5, true, grassItem, dirtStrength), grassTile, - new Tile('GRASS_CORNER_TOP_RIGHT', 7, true, grassItem), - new Tile('GRASS_INNER_BOTTOM_RIGHT', 8, true, grassItem), - new Tile('GRASS_INNER_BOTTOM_LEFT', 9, true, grassItem), - new Tile('GRASS_LEFT', 37, true, grassItem), - new Tile('GRASS_RIGHT', 39, true, grassItem), - new Tile('GRASS_INNER_TOP_RIGHT', 40, true, grassItem), - new Tile('GRASS_INNER_TOP_LEFT', 41, true, grassItem), - new Tile('GRASS_CORNER_BOTTOM_LEFT', 69, true, grassItem), - new Tile('GRASS_BOTTOM', 70, true, grassItem), - new Tile('GRASS_CORNER_BOTTOM_RIGHT', 71, true, grassItem) + new Tile('GRASS_CORNER_TOP_RIGHT', 7, true, grassItem, dirtStrength), + new Tile('GRASS_INNER_BOTTOM_RIGHT', 8, true, grassItem, dirtStrength), + new Tile('GRASS_INNER_BOTTOM_LEFT', 9, true, grassItem, dirtStrength), + new Tile('GRASS_LEFT', 37, true, grassItem, dirtStrength), + new Tile('GRASS_RIGHT', 39, true, grassItem, dirtStrength), + new Tile('GRASS_INNER_TOP_RIGHT', 40, true, grassItem, dirtStrength), + new Tile('GRASS_INNER_TOP_LEFT', 41, true, grassItem, dirtStrength), + new Tile('GRASS_CORNER_BOTTOM_LEFT', 69, true, grassItem, dirtStrength), + new Tile('GRASS_BOTTOM', 70, true, grassItem, dirtStrength), + new Tile('GRASS_CORNER_BOTTOM_RIGHT', 71, true, grassItem, dirtStrength) ]) // Register other tiles diff --git a/src/tiles.js b/src/tiles.js index 86c658a..6eacf46 100644 --- a/src/tiles.js +++ b/src/tiles.js @@ -8,11 +8,12 @@ const cacheFactory = new ResourceCacheFactory() const UPDATE_RADIUS = 6 class Tile { - constructor (name, index, solid = true, item) { + constructor (name, index, solid = true, item, hardness = 0) { this.name = name this.id = index this.solid = solid this.item = item + this.hardness = hardness } } @@ -92,6 +93,7 @@ class TileLayer { this.size = size this.tile = tileSize this.tiles = [] + this.damage = {} } setTile (x, y, i) { @@ -116,7 +118,11 @@ class TileLayer { tileAtXY (x, y) { if (x < 0 || x >= this.size || y < 0 || y >= this.size) return null - return this.tileAt(x + this.size * y) + return this.tileAt(this.toI(x, y)) + } + + toI (x, y) { + return x + this.size * y } toXY (i) { @@ -147,8 +153,38 @@ class TileLayer { } } - update (dt) { + damageTileAt (i, dmg) { + let tile = this.tiles[i] + let tparams = this.map.getTileByID(tile) + if (tile === -1 || !tparams) return false + if (tparams.hardness < 0) return false + if (!this.damage[i]) this.damage[i] = tparams.hardness + this.damage[i] -= dmg + if (this.damage[i] <= 0) return true + return false + } + damageTileAtXY (x, y, dmg) { + return this.damageTileAt(this.toI(x, y), dmg) + } + + update (dt) { + for (let index in this.damage) { + let damage = this.damage[index] + let tilei = parseInt(this.tiles[index]) + let tparams = this.map.getTileByID(tilei) + if (tilei === -1 || !tparams) { + delete this.damage[index] + continue + } + + if (damage < tparams.hardness) { + this.damage[index] += 10 * dt + continue + } + + delete this.damage[index] + } } }