item entities
This commit is contained in:
parent
5a2ba57115
commit
71eaa328a4
@ -24,7 +24,8 @@ class Debugging {
|
||||
ctx.fillText('active ' + world._active.length, 4, 16 * 7)
|
||||
// Mouse
|
||||
let mpos = Input.mouse.pos
|
||||
let mpin = world.pickMouse(vp, mpos)
|
||||
let mabs = { x: mpos.x + vp.x, y: mpos.y + vp.y }
|
||||
let mpin = world.gridPosition(mabs)
|
||||
ctx.fillText('mouse (x: ' + mpos.x + '; y: ' + mpos.y + ')', 4, 16 * 9)
|
||||
if (mpin.chunk) {
|
||||
ctx.fillText('mouse-in-chunk (x: ' + mpin.chunk.x + '; y: ' + mpin.chunk.y + ')', 4, 16 * 10)
|
||||
|
214
src/entity.js
Normal file
214
src/entity.js
Normal file
@ -0,0 +1,214 @@
|
||||
import { ctx } from './canvas'
|
||||
import { ItemRegistry, ItemStack } from './items'
|
||||
|
||||
class PhysicsEntity {
|
||||
constructor (x, y, w, h) {
|
||||
this.x = x
|
||||
this.y = y
|
||||
|
||||
this.width = w
|
||||
this.height = h
|
||||
|
||||
this.mX = 0
|
||||
this.mY = 0
|
||||
|
||||
this.grounded = false
|
||||
|
||||
this.speed = 8
|
||||
this.gravity = 1
|
||||
this.jumpPower = 20
|
||||
|
||||
this.dead = false
|
||||
}
|
||||
|
||||
moveAndSlide (collider) {
|
||||
// y collision
|
||||
if (this.mY !== 0) {
|
||||
let oldY = this.y
|
||||
this.y += this.mY
|
||||
if (oldY !== this.y && collider.collide(this)) {
|
||||
if (this.y > oldY) this.grounded = true
|
||||
this.y = oldY
|
||||
this.mY = 0
|
||||
} else {
|
||||
this.grounded = false
|
||||
}
|
||||
}
|
||||
|
||||
// x collision
|
||||
if (this.mX !== 0) {
|
||||
let oldX = this.x
|
||||
this.x += this.mX
|
||||
if (oldX !== this.x && collider.collide(this)) {
|
||||
this.mX = this.mX < 0 ? -1 : 1
|
||||
this.x = oldX + this.mX
|
||||
if (collider.collide(this)) {
|
||||
this.x = oldX
|
||||
this.mX = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
update (dt, vp, world) {
|
||||
this.mY += this.gravity
|
||||
|
||||
this.moveAndSlide(world)
|
||||
}
|
||||
|
||||
draw (vp) {
|
||||
ctx.fillStyle = '#f00'
|
||||
ctx.fillRect(this.x - vp.x, this.y - vp.y, this.width, this.height)
|
||||
}
|
||||
|
||||
collide (ent) {
|
||||
if (!(ent instanceof PhysicsEntity)) return null
|
||||
|
||||
// Intersection check
|
||||
if (this.x > ent.x + ent.width || this.x + this.width < ent.x ||
|
||||
this.y > ent.y + ent.height || this.y + this.height < ent.y) return false
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
distance (ent) {
|
||||
if (!(ent instanceof PhysicsEntity)) return null
|
||||
let d1 = { x: ent.x + ent.width / 2, y: ent.y + ent.height / 2 }
|
||||
let d2 = { x: this.x + this.width / 2, y: this.y + this.height / 2 }
|
||||
let dist = Math.floor(Math.sqrt(Math.pow(d1.x - d2.x, 2) + Math.pow(d1.y - d2.y, 2)))
|
||||
return dist
|
||||
}
|
||||
}
|
||||
|
||||
const ITEM_LIFE = 120
|
||||
const ITEM_MERGE_DISTANCE = 60
|
||||
const ITEM_BOB_FACTOR = 5
|
||||
|
||||
class ItemEntity extends PhysicsEntity {
|
||||
constructor (istr, x, y) {
|
||||
super(x, y, 16, 16)
|
||||
this.istr = istr
|
||||
|
||||
this._mergeTick = 0
|
||||
this._life = 0
|
||||
}
|
||||
|
||||
get name () {
|
||||
if (this.istr === '') return ''
|
||||
return this.istr.split(' ')[0]
|
||||
}
|
||||
|
||||
get count () {
|
||||
if (this.istr === '') return ''
|
||||
let c = parseInt(this.istr.split(' ')[1])
|
||||
return isNaN(c) ? 0 : c
|
||||
}
|
||||
|
||||
get item () {
|
||||
let itm = ItemRegistry.get(this.name)
|
||||
return itm
|
||||
}
|
||||
|
||||
static new (itemStack, x, y) {
|
||||
if (!(itemStack instanceof ItemStack)) return null
|
||||
return new ItemEntity(itemStack.toString(), x, y)
|
||||
}
|
||||
|
||||
mergeNearby (vp, world) {
|
||||
let entLayer = world.getLayer('ents')
|
||||
if (!entLayer) return
|
||||
let active = entLayer.getActiveEntities(vp, world)
|
||||
for (let i in active) {
|
||||
let ent = active[i]
|
||||
if (ent.dead) continue
|
||||
if (ent === this) continue
|
||||
if (!(ent instanceof ItemEntity)) continue
|
||||
if (ent.name !== this.name) continue
|
||||
let dist = Math.floor(Math.sqrt(Math.pow(ent.x - this.x, 2) + Math.pow(ent.y - this.y, 2)))
|
||||
if (dist > ITEM_MERGE_DISTANCE) continue
|
||||
this.istr = this.name + ' ' + (this.count + ent.count)
|
||||
this._life = 0
|
||||
ent.dead = true
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
update (dt, vp, world) {
|
||||
if (this.dead) return
|
||||
this._mergeTick++
|
||||
this._life += 1 * dt
|
||||
if (this._mergeTick >= 60) {
|
||||
this._mergeTick = 0
|
||||
this.mergeNearby(vp, world)
|
||||
}
|
||||
if (this._life > ITEM_LIFE) {
|
||||
this.dead = true
|
||||
return
|
||||
}
|
||||
|
||||
super.update(dt, vp, world)
|
||||
}
|
||||
|
||||
draw (vp, world) {
|
||||
let i = this.item
|
||||
let b = Math.sin((this._life / ITEM_BOB_FACTOR) / Math.PI * 180)
|
||||
if (!i) return
|
||||
ctx.drawImage(i.image, this.x - vp.x, this.y - vp.y + b, this.width, this.height)
|
||||
}
|
||||
}
|
||||
|
||||
class EntityLayer {
|
||||
constructor (name) {
|
||||
this.name = name
|
||||
this.entities = []
|
||||
}
|
||||
|
||||
getActiveEntities (vp, world, cleanup = false) {
|
||||
let active = []
|
||||
let alive = []
|
||||
for (let i in this.entities) {
|
||||
let ent = this.entities[i]
|
||||
if (ent.dead) {
|
||||
continue
|
||||
} else if (cleanup) {
|
||||
alive.push(ent)
|
||||
}
|
||||
let entInChunk = world.gridPosition(vp, ent)
|
||||
if (!entInChunk || !entInChunk.chunk) continue
|
||||
let entChunk
|
||||
for (let i in world._active) {
|
||||
let chunk = world._active[i]
|
||||
if (chunk.x === entInChunk.chunk.x && chunk.y === entInChunk.chunk.y) {
|
||||
entChunk = chunk
|
||||
break
|
||||
}
|
||||
}
|
||||
if (!entChunk) continue
|
||||
ent._chunk = entChunk
|
||||
active.push(ent)
|
||||
}
|
||||
if (cleanup) this.entities = alive
|
||||
return active
|
||||
}
|
||||
|
||||
// Update active entities and clean up dead ones
|
||||
update (dt, vp, world) {
|
||||
let active = this.getActiveEntities(vp, world, true)
|
||||
for (let i in active) {
|
||||
let ent = active[i]
|
||||
ent.update(dt, vp, world, ent._chunk)
|
||||
}
|
||||
}
|
||||
|
||||
draw (vp, world) {
|
||||
let active = this.getActiveEntities(vp, world)
|
||||
for (let i in active) {
|
||||
let ent = active[i]
|
||||
if (ent.x > vp.x + vp.width + ent.width || ent.x + ent._chunk.fullSize < vp.x - ent.width ||
|
||||
ent.y > vp.y + vp.height + ent.height || ent.y + ent._chunk.fullSize < vp.y - ent.height) continue
|
||||
ent.draw(vp, world)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export { ItemEntity, PhysicsEntity, EntityLayer }
|
93
src/index.js
93
src/index.js
@ -1,14 +1,14 @@
|
||||
/* global requestAnimationFrame */
|
||||
import { canvas, ctx } from './canvas'
|
||||
import { Tile, TileMap, World } from './tiles'
|
||||
import { ItemPlaceable } from './items'
|
||||
import { Inventory } from './inventory'
|
||||
import { World } from './tiles'
|
||||
// import { ItemPlaceable } from './items'
|
||||
import { HeightMap } from './heightmap'
|
||||
import Debug from './debug'
|
||||
import Player from './player'
|
||||
import Input from './input'
|
||||
import Viewport from './viewport'
|
||||
import RES from './resource'
|
||||
import map from './register'
|
||||
|
||||
let playing = false
|
||||
let frameTime = 0
|
||||
@ -17,111 +17,24 @@ let fps = 0
|
||||
|
||||
let vp = new Viewport(0, 0)
|
||||
let p = new Player(800, 1200, 32, 64)
|
||||
let inv = new Inventory(9)
|
||||
|
||||
let height = new HeightMap(0, 32, 16, 0)
|
||||
let map = new TileMap('assets/ground.png', 32)
|
||||
|
||||
const chunkSize = 32
|
||||
const tileSize = 16
|
||||
|
||||
const dirtTile = new Tile('DIRT', 33)
|
||||
const grassTile = new Tile('GRASS_TOP', 6)
|
||||
const stoneTile = new Tile('STONE', 10)
|
||||
|
||||
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')
|
||||
|
||||
dirtTile.item = dirtItem
|
||||
grassTile.item = grassItem
|
||||
stoneTile.item = stoneItem
|
||||
|
||||
// Define 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),
|
||||
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)
|
||||
])
|
||||
|
||||
// Define grass tiles
|
||||
map.register([
|
||||
new Tile('GRASS_CORNER_TOP_LEFT', 5, true, dirtItem),
|
||||
grassTile,
|
||||
new Tile('GRASS_CORNER_TOP_RIGHT', 7, true, dirtItem),
|
||||
new Tile('GRASS_INNER_BOTTOM_RIGHT', 8, true, dirtItem),
|
||||
new Tile('GRASS_INNER_BOTTOM_LEFT', 9, true, dirtItem),
|
||||
new Tile('GRASS_LEFT', 37, true, dirtItem),
|
||||
new Tile('GRASS_RIGHT', 39, true, dirtItem),
|
||||
new Tile('GRASS_INNER_TOP_RIGHT', 40, true, dirtItem),
|
||||
new Tile('GRASS_INNER_TOP_LEFT', 41, true, dirtItem),
|
||||
new Tile('GRASS_CORNER_BOTTOM_LEFT', 69, true, dirtItem),
|
||||
new Tile('GRASS_BOTTOM', 70, true, dirtItem),
|
||||
new Tile('GRASS_CORNER_BOTTOM_RIGHT', 71, true, dirtItem)
|
||||
])
|
||||
|
||||
// Define other tiles
|
||||
map.register([
|
||||
new Tile('AIR', -1, false),
|
||||
stoneTile
|
||||
])
|
||||
|
||||
let world = new World(height, { GROUND: map }, chunkSize, tileSize, 32, 64)
|
||||
|
||||
function update (dt) {
|
||||
world.update(dt, vp)
|
||||
p.update(dt, vp, world)
|
||||
vp.update(dt, world)
|
||||
|
||||
for (let i = 0; i < inv.size; i++) {
|
||||
let pressed = Input.isPressed(i + 1)
|
||||
if (pressed) {
|
||||
inv.selected = i
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if (Input.mouse['btn0']) {
|
||||
let mpin = world.pickMouse(vp, Input.mouse.pos)
|
||||
if (mpin.chunk) {
|
||||
if (inv.isEmpty(inv.selected)) return
|
||||
let tile = mpin.chunk.getTile('fg', mpin.tile)
|
||||
if (tile !== -1) return
|
||||
let itm = inv.getItem(inv.selected)
|
||||
if (itm && itm.item.placeable) {
|
||||
let success = mpin.chunk.setTile('fg', mpin.tile, itm.item.placeable.id)
|
||||
if (success) {
|
||||
inv.takeItem(inv.selected, 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (Input.mouse['btn2']) {
|
||||
let mpin = world.pickMouse(vp, Input.mouse.pos)
|
||||
if (mpin.chunk) {
|
||||
let tile = mpin.chunk.getTile('fg', mpin.tile)
|
||||
if (tile === -1) return
|
||||
let itile = map.getTileByID(tile)
|
||||
let success = mpin.chunk.setTile('fg', mpin.tile, map.indexOf('AIR'))
|
||||
if (success) inv.addItem(itile.item)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function draw () {
|
||||
world.draw(vp)
|
||||
p.draw(vp)
|
||||
Debug.draw(vp, world, fps)
|
||||
inv.draw()
|
||||
}
|
||||
|
||||
function step () {
|
||||
|
16
src/items.js
16
src/items.js
@ -36,16 +36,22 @@ class ItemPlaceable extends Item {
|
||||
}
|
||||
}
|
||||
|
||||
class ItemTool extends Item {
|
||||
use (dt, world, player) {}
|
||||
|
||||
useSecondary (dt, world, player) {}
|
||||
}
|
||||
|
||||
class ItemStack {
|
||||
static fromIString (str) {
|
||||
if (typeof str !== 'string') return
|
||||
let strpl = str.split(' ')
|
||||
let iname = strpl[0]
|
||||
let count = strpl[1]
|
||||
let count = parseInt(strpl[1])
|
||||
let item = ItemRegistry.get(iname)
|
||||
let istack = new ItemStack()
|
||||
istack.item = item
|
||||
istack.count = count || 1
|
||||
istack.count = isNaN(count) ? 1 : count
|
||||
return istack
|
||||
}
|
||||
|
||||
@ -82,6 +88,10 @@ class ItemStack {
|
||||
a.count = c
|
||||
return a
|
||||
}
|
||||
|
||||
toString () {
|
||||
return this.name + ' ' + this.count + (this.metadata ? ' ' + JSON.stringify(this.metadata) : '')
|
||||
}
|
||||
}
|
||||
|
||||
export { Item, ItemPlaceable, ItemStack, ItemRegistry, MAX_STACK_SIZE }
|
||||
export { Item, ItemPlaceable, ItemTool, ItemStack, ItemRegistry, MAX_STACK_SIZE }
|
||||
|
107
src/player.js
107
src/player.js
@ -1,50 +1,54 @@
|
||||
import { ctx } from './canvas'
|
||||
import { PhysicsEntity, ItemEntity } from './entity'
|
||||
import { ItemStack } from './items'
|
||||
import { Inventory } from './inventory'
|
||||
import Input from './input'
|
||||
|
||||
class Player {
|
||||
class Player extends PhysicsEntity {
|
||||
constructor (x, y, w, h) {
|
||||
this.x = x
|
||||
this.y = y
|
||||
|
||||
this.width = w
|
||||
this.height = h
|
||||
|
||||
this.mX = 0
|
||||
this.mY = 0
|
||||
|
||||
this.grounded = false
|
||||
super(x, y, w, h)
|
||||
|
||||
this.speed = 8
|
||||
this.gravity = 1
|
||||
this.jumpPower = 20
|
||||
|
||||
this.inv = new Inventory(9)
|
||||
this.itemPickUpDistance = 40
|
||||
}
|
||||
|
||||
moveAndSlide (collider) {
|
||||
// y collision
|
||||
let oldY = this.y
|
||||
this.y += this.mY
|
||||
if (oldY !== this.y && collider.collide(this)) {
|
||||
if (this.y > oldY) this.grounded = true
|
||||
this.y = oldY
|
||||
this.mY = 0
|
||||
} else {
|
||||
this.grounded = false
|
||||
}
|
||||
|
||||
// x collision
|
||||
let oldX = this.x
|
||||
this.x += this.mX
|
||||
if (oldX !== this.x && collider.collide(this)) {
|
||||
this.mX = this.mX < 0 ? -1 : 1
|
||||
this.x = oldX + this.mX
|
||||
if (collider.collide(this)) {
|
||||
this.x = oldX
|
||||
this.mX = 0
|
||||
handleTool (dt, 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 (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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
update (dt, vp, world) {
|
||||
handleMovement (dt, vp, world) {
|
||||
this.mY += this.gravity
|
||||
if (Input.isDown('a')) {
|
||||
this.mX = -this.speed
|
||||
@ -64,9 +68,46 @@ class Player {
|
||||
vp.y = parseInt(this.y - vp.height / 2)
|
||||
}
|
||||
|
||||
handleInventory () {
|
||||
for (let i = 0; i < this.inv.size; i++) {
|
||||
let pressed = Input.isPressed(i + 1)
|
||||
if (pressed) {
|
||||
this.inv.selected = i
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pickUp (itemEntity) {
|
||||
let istr = itemEntity.istr
|
||||
let istack = ItemStack.new(istr)
|
||||
this.inv.addItem(istack)
|
||||
itemEntity.dead = true
|
||||
}
|
||||
|
||||
handleWorldEntities (dt, vp, world) {
|
||||
let entities = world.getLayer('ents')
|
||||
if (!entities) return
|
||||
let active = entities.getActiveEntities(vp, world)
|
||||
for (let i in active) {
|
||||
let ent = active[i]
|
||||
if (!(ent instanceof ItemEntity)) continue
|
||||
if (ent.distance(this) > this.itemPickUpDistance) continue
|
||||
this.pickUp(ent)
|
||||
}
|
||||
}
|
||||
|
||||
update (dt, vp, world) {
|
||||
this.handleTool(dt, vp, world)
|
||||
this.handleWorldEntities(dt, vp, world)
|
||||
this.handleInventory()
|
||||
this.handleMovement(dt, vp, world)
|
||||
}
|
||||
|
||||
draw (vp) {
|
||||
ctx.fillStyle = '#f00'
|
||||
ctx.fillRect(this.x - vp.x, this.y - vp.y, this.width, this.height)
|
||||
this.inv.draw()
|
||||
}
|
||||
}
|
||||
|
||||
|
60
src/register.js
Normal file
60
src/register.js
Normal file
@ -0,0 +1,60 @@
|
||||
import { Tile, TileMap } from './tiles'
|
||||
import { ItemPlaceable } from './items'
|
||||
|
||||
const map = new TileMap('assets/ground.png', 32)
|
||||
|
||||
// Basic tiles
|
||||
const dirtTile = new Tile('DIRT', 33)
|
||||
const grassTile = new Tile('GRASS_TOP', 6)
|
||||
const stoneTile = new Tile('STONE', 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')
|
||||
|
||||
// Set the items
|
||||
dirtTile.item = dirtItem
|
||||
grassTile.item = grassItem
|
||||
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),
|
||||
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)
|
||||
])
|
||||
|
||||
// Register grass tiles
|
||||
map.register([
|
||||
new Tile('GRASS_CORNER_TOP_LEFT', 5, true, grassItem),
|
||||
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)
|
||||
])
|
||||
|
||||
// Register other tiles
|
||||
map.register([
|
||||
new Tile('AIR', -1, false),
|
||||
stoneTile
|
||||
])
|
||||
|
||||
export default map
|
35
src/tiles.js
35
src/tiles.js
@ -2,6 +2,7 @@ import { ctx, ResourceCacheFactory } from './canvas'
|
||||
import { distanceTo } from './utils'
|
||||
import Resource from './resource'
|
||||
import Debug from './debug'
|
||||
import { EntityLayer } from './entity'
|
||||
|
||||
const cacheFactory = new ResourceCacheFactory()
|
||||
const UPDATE_RADIUS = 6
|
||||
@ -365,6 +366,7 @@ class World {
|
||||
this.tileSize = tileSize
|
||||
this.tileMaps = tileMaps
|
||||
this.chunks = []
|
||||
this.layers = []
|
||||
this.height = height
|
||||
this.width = width
|
||||
|
||||
@ -376,6 +378,9 @@ class World {
|
||||
this._lastDrawCount = 0
|
||||
this._lastUpdateCount = 0
|
||||
this._active = []
|
||||
|
||||
// Create world layers
|
||||
this.layers.push(new EntityLayer('ents'))
|
||||
}
|
||||
|
||||
getChunk (x, y) {
|
||||
@ -386,6 +391,14 @@ class World {
|
||||
return null
|
||||
}
|
||||
|
||||
getLayer (name) {
|
||||
for (let i in this.layers) {
|
||||
let layer = this.layers[i]
|
||||
if (layer.name === name) return layer
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
update (dt, vp) {
|
||||
this._active = []
|
||||
let posPoint = vp.chunkIn(this.chunkSize * this.tileSize)
|
||||
@ -403,6 +416,7 @@ class World {
|
||||
}
|
||||
}
|
||||
|
||||
// Update chunks
|
||||
for (let i in this.chunks) {
|
||||
this.chunks[i].update(dt)
|
||||
}
|
||||
@ -416,22 +430,26 @@ class World {
|
||||
let chunk = this.chunks[i]
|
||||
let pos = chunk.absPos
|
||||
let distance = distanceTo(vp.adjustCentered, pos)
|
||||
if (distance <= chunk.fullSize * UPDATE_RADIUS) {
|
||||
if (distance <= chunk.fullSize * UPDATE_RADIUS || chunk.modified) {
|
||||
// Keep chunk
|
||||
keep.push(chunk)
|
||||
}
|
||||
}
|
||||
this.chunks = keep
|
||||
}
|
||||
|
||||
// Update layers
|
||||
for (let i in this.layers) {
|
||||
this.layers[i].update(dt, vp, this)
|
||||
}
|
||||
}
|
||||
|
||||
pickMouse (vp, mousePos) {
|
||||
gridPosition (pos) {
|
||||
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 chunk = { x: Math.floor(pos.x / a), y: Math.floor(pos.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)
|
||||
x: Math.floor(pos.x / this.tileSize - chunk.x * this.chunkSize),
|
||||
y: Math.floor(pos.y / this.tileSize - chunk.y * this.chunkSize)
|
||||
}
|
||||
return { chunk: this.getChunk(chunk.x, chunk.y), tile }
|
||||
}
|
||||
@ -449,6 +467,11 @@ class World {
|
||||
if (chunk._updated) this._lastUpdateCount++
|
||||
this._lastDrawCount++
|
||||
}
|
||||
|
||||
// Draw layers
|
||||
for (let i in this.layers) {
|
||||
this.layers[i].draw(vp, this)
|
||||
}
|
||||
}
|
||||
|
||||
collide (obj) {
|
||||
|
Loading…
Reference in New Issue
Block a user