import Rect from "./Rect.js"; | import Rect from "./Rect.js"; | ||||
import Vec2 from "./Vec2.js"; | |||||
export class Trait { | export class Trait { | ||||
constructor(entity, name, deps = []) { | constructor(entity, name, deps = []) { | ||||
constructor(level, layerName) { | constructor(level, layerName) { | ||||
this.layerName = layerName; | this.layerName = layerName; | ||||
this.level = level; | this.level = level; | ||||
this.bounds = new Rect(); | |||||
this.pos = new Vec2(); | |||||
this.bounds = new Rect(this.pos); | |||||
this.time = 0; | this.time = 0; | ||||
this.traitOrder = [ | this.traitOrder = [ | ||||
"platform", | "platform", | ||||
"wall", | "wall", | ||||
"keyboardController", | "keyboardController", | ||||
"behavior", | |||||
"physics", | "physics", | ||||
]; | ]; | ||||
this.t = { | this.t = { | ||||
platform: null, | platform: null, | ||||
wall: null, | wall: null, | ||||
keyboardController: null, | keyboardController: null, | ||||
behavior: null, | |||||
physics: null, | physics: null, | ||||
}; | }; | ||||
trait.update(dt); | trait.update(dt); | ||||
} | } | ||||
this.update(dt); | |||||
this.time += dt; | this.time += dt; | ||||
} | } | ||||
if (trait.enabled) | if (trait.enabled) | ||||
trait.postUpdate(dt); | trait.postUpdate(dt); | ||||
} | } | ||||
this.postUpdate(dt); | |||||
} | } | ||||
init() {} | init() {} | ||||
update(dt) {} | |||||
postUpdate(dt) {} | |||||
draw(ctx) {} | draw(ctx) {} | ||||
has(name) { | has(name) { |
} | } | ||||
spawnEntity(ent, x, y) { | spawnEntity(ent, x, y) { | ||||
ent.bounds.pos.set(x, y); | |||||
ent.pos.set(x, y); | |||||
let layerIdx = this.layerOrder[ent.layerName]; | let layerIdx = this.layerOrder[ent.layerName]; | ||||
console.log(ent.layerName, this.layerOrder, layerIdx); | |||||
if (layerIdx == null) | if (layerIdx == null) | ||||
throw new Error("Unknown layer name: "+ent.layerName); | throw new Error("Unknown layer name: "+ent.layerName); | ||||
} | } | ||||
spawnStructure(structure, x, y) { | spawnStructure(structure, x, y) { | ||||
structure.bounds.pos.set(x, y); | |||||
structure.pos.set(x, y); | |||||
this.structures.push(structure); | this.structures.push(structure); | ||||
structure.init(); | structure.init(); | ||||
} | } | ||||
return; | return; | ||||
this.colliders.forEach(ent => { | this.colliders.forEach(ent => { | ||||
let bounds = s.collidesWith(ent.bounds); | |||||
if (!bounds) | |||||
if (!s.bounds.intersects(ent.bounds)) | |||||
return; | return; | ||||
ent.t.collider.collideStructure(s, bounds); | |||||
ent.t.collider.collideStructure(s); | |||||
}); | }); | ||||
}); | }); | ||||
return rightOrBelow(r1, r2) || rightOrBelow(r2, r1); | return rightOrBelow(r1, r2) || rightOrBelow(r2, r1); | ||||
} | } | ||||
function findGeometry(bounds, arr, geometry) { | |||||
let allBounds = []; | |||||
arr.forEach(e => { | |||||
let eBounds = new Rect(bounds.pos.clone()); | |||||
eBounds.pos.pixelX += e.x * assets.tiles.tileWidth; | |||||
eBounds.pos.pixelY += e.y * assets.tiles.tileWidth; | |||||
eBounds.size.pixelX = assets.tiles.tileWidth; | |||||
eBounds.size.pixelY = assets.tiles.tileWidth; | |||||
allBounds.push(eBounds); | |||||
}); | |||||
function runPass() { | |||||
if (allBounds.lenght === 1) { | |||||
geometry.push(allBounds[0]); | |||||
allBounds.splice(0, 1); | |||||
return; | |||||
} | |||||
// Find continuous bounds | |||||
let changed = false; | |||||
geometry.forEach((g, gi) => { | |||||
allBounds.forEach((b, bi) => { | |||||
if (continuous(g, b)) { | |||||
if (b.left < g.left) | |||||
g.pixelResizeLeftTo(b.pixelLeft); | |||||
if (b.right > g.right) | |||||
g.pixelResizeRightTo(b.pixelRight); | |||||
if (b.top < g.top) | |||||
g.pixelResizeTopTo(b.pixelTop); | |||||
if (b.bottom > g.bottom) | |||||
g.pixelResizeBottomTo(b.pixelBottom); | |||||
allBounds.splice(bi, 1); | |||||
changed = true; | |||||
} | |||||
}); | |||||
}); | |||||
// If no continuous blocks were found, we need a new rectangle | |||||
if (!changed) { | |||||
geometry.push(allBounds[0]); | |||||
allBounds.splice(0, 1); | |||||
} | |||||
} | |||||
while (allBounds.length > 0) { | |||||
runPass(); | |||||
} | |||||
} | |||||
function flattened(arr, newArr = []) { | function flattened(arr, newArr = []) { | ||||
arr.forEach(e => { | arr.forEach(e => { | ||||
if (e instanceof Array) | if (e instanceof Array) | ||||
this.setAttr(a); | this.setAttr(a); | ||||
this.nestedArr = nestedArr; | this.nestedArr = nestedArr; | ||||
this.bounds = new Rect(); | |||||
this.geometry = []; | |||||
this.pos = new Vec2(); | |||||
this.bounds = new Rect(this.pos); | |||||
} | } | ||||
init() { | init() { | ||||
var arr = flattened(this.nestedArr); | var arr = flattened(this.nestedArr); | ||||
findBounds(arr, this.bounds); | findBounds(arr, this.bounds); | ||||
if (this.attrs.wall || this.attrs.platform) { | |||||
findGeometry(this.bounds, arr, this.geometry); | |||||
} | |||||
} | } | ||||
draw(ctx) { | draw(ctx) { | ||||
this.texture.draw(ctx, this.bounds.pos.pixelX, this.bounds.pos.pixelY); | |||||
this.texture.draw(ctx, this.pos.pixelX, this.pos.pixelY); | |||||
} | } | ||||
setAttr(attr) { | setAttr(attr) { | ||||
this.attrs[attr] = true; | this.attrs[attr] = true; | ||||
return this; | return this; | ||||
} | } | ||||
collidesWith(rect) { | |||||
if (!this.bounds.intersects(rect)) | |||||
return null; | |||||
for (let bounds of this.geometry) { | |||||
if (bounds.intersects(rect)) | |||||
return bounds; | |||||
} | |||||
return null; | |||||
} | |||||
} | } |
} | } | ||||
} | } | ||||
Tile.createLine = function(width, name, x = 0, y = 0) { | |||||
if (width <= 1) { | |||||
return [ new Tile(x, y, name+"-lr") ]; | |||||
function realNames(base, override = {}) { | |||||
return { | |||||
topLeft: override.topLeft || base+"-top-l", | |||||
top: override.top || base+"-top", | |||||
topRight: override.topRight || base+"-top-r", | |||||
topBoth: override.topBoth || base+"-top-lr", | |||||
left: override.left || base+"-l", | |||||
mid: override.mid || base, | |||||
right: override.right || base+"-r", | |||||
both: override.both || base+"-lr", | |||||
bottomLeft: override.bottomLeft || base+"-bottom-l", | |||||
bottom: override.bottom || base+"-bottom", | |||||
bottomRight: override.bottomRight || base+"-bottom-r", | |||||
bottomBoth: override.bottomBoth || base+"-bottom-lr", | |||||
}; | |||||
} | |||||
function getName(x, y, size, names) { | |||||
let name = null; | |||||
if (size.x <= 1) { | |||||
if (y === 0) | |||||
name = names.topBoth; | |||||
else if (y === size.y - 1) | |||||
name = names.bottomBoth; | |||||
else | |||||
name = names.both; | |||||
} else { | } else { | ||||
return [ | |||||
new Tile(x, y, name+"-l"), | |||||
Array.from({ length: width - 2 }, (_, i) => | |||||
new Tile(x + i + 1, y, name)), | |||||
new Tile(x + width - 1, y, name+"-r"), | |||||
]; | |||||
if (y === 0) { | |||||
if (x === 0) | |||||
name = names.topLeft; | |||||
else if (x === size.x - 1) | |||||
name = names.topRight; | |||||
else | |||||
name = names.top; | |||||
} else if (y === size.y - 1) { | |||||
if (x === 0) | |||||
name = names.bottomLeft; | |||||
else if (x === size.x - 1) | |||||
name = names.bottomRight; | |||||
else | |||||
name = names.bottom; | |||||
} else { | |||||
if (x === 0) | |||||
name = names.left; | |||||
else if (x === size.x - 1) | |||||
name = names.right; | |||||
else | |||||
name = names.mid; | |||||
} | |||||
} | } | ||||
if (!name) | |||||
name = "--invalid-"+x+"-"+y+"--"; | |||||
return name; | |||||
} | } | ||||
Tile.createBox = function(width, height, nameTop, nameMid, nameBottom) { | |||||
if (height <= 1) { | |||||
return Tile.createLine(width, nameTop); | |||||
} else if (height <= 2) { | |||||
return [ | |||||
Tile.createLine(width, nameTop), | |||||
Tile.createLine(width, nameBottom), | |||||
]; | |||||
} else { | |||||
return [ | |||||
Tile.createLine(width, nameTop), | |||||
Array.from({ length: height - 2 }, (_, i) => | |||||
Tile.createLine(width, nameMid, 0, i + 1)), | |||||
Tile.createLine(width, nameBottom, 0, height - 1), | |||||
]; | |||||
Tile.createBox = function(pos, size, base, names) { | |||||
names = realNames(base, names); | |||||
let arr = []; | |||||
for (let x = 0; x < size.x; ++x) { | |||||
for (let y = 0; y < size.y; ++y) { | |||||
arr.push(new Tile( | |||||
pos.x + x, pos.y + y, getName(x, y, size, names))); | |||||
} | |||||
} | } | ||||
return arr; | |||||
} | |||||
function getNameLine(x, width, names) { | |||||
if (width === 1) | |||||
return names.both; | |||||
else if (x === 0) | |||||
return names.left; | |||||
else if (x === width - 1) | |||||
return names.right; | |||||
else | |||||
return names.mid; | |||||
} | |||||
Tile.createLine = function(pos, width, base, names) { | |||||
names = realNames(base, names); | |||||
let arr = []; | |||||
for (let x = 0; x < width; ++x) { | |||||
arr.push(new Tile( | |||||
pos.x + x, pos.y, getNameLine(x, width, names))); | |||||
} | |||||
return arr; | |||||
} | } |
this.y = Math.floor(y) / meter; | this.y = Math.floor(y) / meter; | ||||
} | } | ||||
} | } | ||||
Vec2.zero = new Vec2(); |
.defineTile("broken-platform-lr", 3, 3), | .defineTile("broken-platform-lr", 3, 3), | ||||
entities: new SpriteSheet("assets/entities.png", 19, 32, 2) | entities: new SpriteSheet("assets/entities.png", 19, 32, 2) | ||||
.defineTile("player-head", 0, 0), | |||||
.defineTile("player", 0, 0), | |||||
} | } |
import Entity from "../Entity.js"; | import Entity from "../Entity.js"; | ||||
import {Trait} from "../Entity.js"; | |||||
import Texture from "../Texture.js"; | import Texture from "../Texture.js"; | ||||
import Tile from "../Tile.js"; | import Tile from "../Tile.js"; | ||||
import Shaker from "../Shaker.js"; | import Shaker from "../Shaker.js"; | ||||
import Vec2 from "../Vec2.js"; | |||||
import assets from "../assets.js"; | import assets from "../assets.js"; | ||||
import TPlatform from "../traits/TPlatform.js"; | import TPlatform from "../traits/TPlatform.js"; | ||||
import TCollider from "../traits/TCollider.js"; | import TCollider from "../traits/TCollider.js"; | ||||
import TPhysics from "../traits/TPhysics.js"; | import TPhysics from "../traits/TPhysics.js"; | ||||
export default class BrokenPlatform extends Entity { | |||||
constructor(level, width = 5) { | |||||
super(level, "platform"); | |||||
this.bounds.size.set(width, 0.5); | |||||
this.addTrait(new TCollider(this)); | |||||
this.addTrait(new TPlatform(this)); | |||||
this.addTrait(new TPhysics(this)); | |||||
this.texture = new Texture(assets.tiles, | |||||
Tile.createLine(this.bounds.size.x, "broken-platform")); | |||||
class Behavior extends Trait { | |||||
constructor(entity) { | |||||
super(entity, "behavior"); | |||||
this.shaker = new Shaker(); | this.shaker = new Shaker(); | ||||
this.shake = 0; | this.shake = 0; | ||||
this.shakeAccel = 14; | this.shakeAccel = 14; | ||||
this.shaking = false; | |||||
this.floating = true; | |||||
this.reliableTime = 1; | this.reliableTime = 1; | ||||
this.resetTime = 4; | this.resetTime = 4; | ||||
this.state = 0; | |||||
this.timer = 0; | |||||
} | } | ||||
init() { | init() { | ||||
this.initialPos = this.bounds.pos.clone(); | |||||
this.initialPos = this.entity.pos.clone(); | |||||
} | } | ||||
reset() { | reset() { | ||||
this.shake = 0; | this.shake = 0; | ||||
this.shaking = false; | |||||
this.floating = true; | |||||
this.t.physics.velocity.set(0, 0); | |||||
this.bounds.pos.set(this.initialPos.x, this.initialPos.y); | |||||
} | |||||
startShake() { | |||||
this.shake = 0; | |||||
this.shaking = true | |||||
setTimeout(() => { | |||||
this.floating = false; | |||||
this.shaking = false; | |||||
this.entity.t.physics.velocity.set(0, 0); | |||||
this.entity.pos.set(this.initialPos.x, this.initialPos.y); | |||||
this.entity.t.physics.moved = true; | |||||
setTimeout(() => { | |||||
this.reset(); | |||||
}, this.resetTime * 1000); | |||||
}, this.reliableTime * 1000); | |||||
this.state = 0; | |||||
this.timer = 0; | |||||
} | } | ||||
update(dt) { | update(dt) { | ||||
if (!this.shaking && !this.falling) { | |||||
this.t.collider.entities.forEach(e => { | |||||
if (this.state === 0) { | |||||
this.entity.t.collider.entities.forEach(e => { | |||||
let fall = | let fall = | ||||
e.has("physics") && | e.has("physics") && | ||||
e.bounds.intersectSide(this.bounds) === "top"; | |||||
e.bounds.intersectSide(this.entity.bounds) === "top"; | |||||
if (fall) { | if (fall) { | ||||
this.startShake(); | |||||
this.timer = this.reliableTime; | |||||
this.state = 1; | |||||
} | } | ||||
}); | }); | ||||
} | } | ||||
if (this.floating) | |||||
this.t.physics.velocity.y -= this.t.physics.gravity * dt; | |||||
if (this.shaking) { | |||||
if (this.state !== 2) | |||||
this.entity.t.physics.velocity.y -= | |||||
this.entity.t.physics.gravity * dt; | |||||
if (this.state === 1) { | |||||
this.shaker.shake(this.shake); | this.shaker.shake(this.shake); | ||||
this.shake += this.shakeAccel * dt; | this.shake += this.shakeAccel * dt; | ||||
this.timer -= dt; | |||||
if (this.timer <= 0) { | |||||
this.state = 2; | |||||
this.timer = this.resetTime; | |||||
} | |||||
} else if (this.state === 2) { | |||||
this.timer -= dt; | |||||
if (this.timer <= 0) { | |||||
this.reset(); | |||||
} | |||||
} | } | ||||
this.shaker.update(dt); | this.shaker.update(dt); | ||||
} | } | ||||
} | |||||
export default class BrokenPlatform extends Entity { | |||||
constructor(level, width = 5) { | |||||
super(level, "platform"); | |||||
this.bounds.size.set(width, 0.5); | |||||
this.addTrait(new TCollider(this)); | |||||
this.addTrait(new TPlatform(this)); | |||||
this.addTrait(new TPhysics(this)); | |||||
this.addTrait(new Behavior(this)); | |||||
this.texture = new Texture(assets.tiles, Tile.createLine( | |||||
Vec2.zero, this.bounds.size.x, | |||||
"broken-platform")); | |||||
} | |||||
draw(ctx) { | draw(ctx) { | ||||
let shaker = this.t.behavior.shaker; | |||||
this.texture.draw( | this.texture.draw( | ||||
ctx, | ctx, | ||||
this.bounds.pos.pixelX + this.shaker.vec.pixelX, | |||||
this.bounds.pos.pixelY + this.shaker.vec.pixelY); | |||||
this.pos.pixelX + shaker.vec.pixelX, | |||||
this.pos.pixelY + shaker.vec.pixelY); | |||||
} | } | ||||
} | } |
this.addTrait(new TPhysics(this)); | this.addTrait(new TPhysics(this)); | ||||
this.texture = new Texture(assets.tiles, | this.texture = new Texture(assets.tiles, | ||||
Tile.createLine(this.bounds.size.x, "platform")); | |||||
Tile.createSidedLine(this.bounds.size.x, "platform")); | |||||
this.targetSpeed = 3; | this.targetSpeed = 3; | ||||
this.accel = 5; | this.accel = 5; | ||||
} | } | ||||
init() { | init() { | ||||
this.targetTop = this.bounds.pos.y; | |||||
this.targetTop = this.pos.y; | |||||
this.targetBottom = this.targetTop + this.distance; | this.targetBottom = this.targetTop + this.distance; | ||||
this.t.physics.gravity = 0; | this.t.physics.gravity = 0; | ||||
update(dt) { | update(dt) { | ||||
let phys = this.t.physics; | let phys = this.t.physics; | ||||
if (this.bounds.pos.y <= this.targetTop) | |||||
if (this.pos.y <= this.targetTop) | |||||
this.dir = 1; | this.dir = 1; | ||||
else if (this.bounds.pos.y >= this.targetBottom) | |||||
else if (this.pos.y >= this.targetBottom) | |||||
this.dir = -1; | this.dir = -1; | ||||
if (this.dir == 1) { | if (this.dir == 1) { | ||||
} | } | ||||
draw(ctx) { | draw(ctx) { | ||||
this.texture.drawAt(ctx, this.bounds.pos); | |||||
this.texture.drawAt(ctx, this.pos); | |||||
} | } | ||||
} | } |
this.addTrait(new TPhysics(this)); | this.addTrait(new TPhysics(this)); | ||||
this.texture = new Texture(assets.entities, [ | this.texture = new Texture(assets.entities, [ | ||||
new Tile(0, 0, "player-head"), | |||||
new Tile(0, 0, "player"), | |||||
]); | ]); | ||||
} | } | ||||
draw(ctx) { | draw(ctx) { | ||||
let x = | let x = | ||||
this.bounds.pos.pixelX - | |||||
this.pos.pixelX - | |||||
assets.entities.scale * 1.5 - | assets.entities.scale * 1.5 - | ||||
this.bounds.size.pixelX / 2 | this.bounds.size.pixelX / 2 | ||||
this.texture.draw(ctx, x, this.bounds.pos.pixelY); | |||||
this.texture.draw(ctx, x, this.pos.pixelY); | |||||
} | } | ||||
} | } |
let level = new Level(canvas); | let level = new Level(canvas); | ||||
level.spawnEntity(new Player(level), 10, 1); | level.spawnEntity(new Player(level), 10, 1); | ||||
level.spawnEntity(new FloatingPlatform(level), 16, 4); | |||||
level.spawnStructure(structures.floor(8, 6), 4, 4); | |||||
level.spawnEntity(new BrokenPlatform(level), 27, 4); | |||||
level.spawnStructure(structures.ground(new Vec2(22, 6)), 8, 8); | |||||
level.spawnStructure(structures.groundPillar(new Vec2(2, 3)), 14, 6); | |||||
level.spawnStructure(structures.groundPillar(new Vec2(1, 5)), 20, 4); | |||||
level.spawnEntity(new BrokenPlatform(level), 22, 6); | |||||
level.start(); | level.start(); | ||||
import Structure from "./Structure.js"; | import Structure from "./Structure.js"; | ||||
import Vec2 from "./Vec2.js"; | |||||
import Tile from "./Tile.js"; | import Tile from "./Tile.js"; | ||||
export default { | export default { | ||||
floor: (width, height = 1)=> new Structure( | |||||
ground: size => new Structure( | |||||
[ "wall" ], | [ "wall" ], | ||||
Tile.createBox(width, height, "ground-top", "ground", "ground")), | |||||
Tile.createBox( | |||||
Vec2.zero, size, "ground", { | |||||
bottomLeft: "ground-l", | |||||
bottom: "ground", | |||||
bottomRight: "ground-r", | |||||
bottomBoth: "ground", | |||||
})), | |||||
groundPillar: size => new Structure( | |||||
[ "wall" ], | |||||
Tile.createBox( | |||||
Vec2.zero, size, "ground", { | |||||
bottomLeft: "ground", | |||||
bottom: "ground", | |||||
bottomRight: "ground", | |||||
bottomBoth: "ground", | |||||
})), | |||||
}; | }; |
this.entities.push(e); | this.entities.push(e); | ||||
} | } | ||||
collideStructure(s, b) { | |||||
collideStructure(s) { | |||||
this.collides = true; | this.collides = true; | ||||
this.structures.push(s); | this.structures.push(s); | ||||
this.structureBounds.push(b); | |||||
} | } | ||||
postUpdate() { | postUpdate() { | ||||
this.entities.length = 0; | this.entities.length = 0; | ||||
this.structures.length = 0; | this.structures.length = 0; | ||||
this.structureBounds.length = 0; | |||||
this.collides = false; | this.collides = false; | ||||
} | } | ||||
} | } |
this.jump = 8; | this.jump = 8; | ||||
this.jumpTimeMax = 0.4; | this.jumpTimeMax = 0.4; | ||||
this.updrift = 100; | |||||
this.jumpLeeway = 0.2; | |||||
this.updrift = 87; | |||||
this.jumpLeeway = 0.1; | |||||
this.map = { | this.map = { | ||||
KeyA: 'left', | KeyA: 'left', | ||||
if (this.pressed.jump && canJump) { | if (this.pressed.jump && canJump) { | ||||
phys.velocity.y -= this.jump; | phys.velocity.y -= this.jump; | ||||
this.entity.bounds.pos.y += phys.velocity.y * dt; | |||||
this.entity.pos.y += phys.velocity.y * dt; | |||||
this.jumpTime = this.jumpTimeMax; | this.jumpTime = this.jumpTimeMax; | ||||
this.jumping = true; | this.jumping = true; | ||||
this.jumped = true; | this.jumped = true; |
import {Trait} from "../Entity.js"; | import {Trait} from "../Entity.js"; | ||||
import Vec2 from "../Vec2.js"; | import Vec2 from "../Vec2.js"; | ||||
let zeroVector = new Vec2(0, 0); | |||||
export default class TPhysics extends Trait { | export default class TPhysics extends Trait { | ||||
constructor(entity) { | constructor(entity) { | ||||
super(entity, "physics"); | super(entity, "physics"); | ||||
this.onGround = false; | this.onGround = false; | ||||
this.groundBounds = null; | this.groundBounds = null; | ||||
this.groundVelocity = null; | this.groundVelocity = null; | ||||
this.moved = false; | |||||
} | } | ||||
collideTop(bounds, velocity) { | collideTop(bounds, velocity) { | ||||
collideWall(bounds, velocity) { | collideWall(bounds, velocity) { | ||||
let side = this.entity.bounds.intersectSide(bounds); | let side = this.entity.bounds.intersectSide(bounds); | ||||
if (side === "top") | |||||
return this.collideTop(bounds, velocity); | |||||
if (side === "top") { | |||||
this.collideTop(bounds, velocity); | |||||
} else if (side === "left" && this.velocity.x > velocity.x) { | |||||
this.velocity.x = velocity.x; | |||||
this.entity.bounds.right = bounds.left; | |||||
} else if (side === "right" && this.velocity.x < velocity.x) { | |||||
this.velocity.x = velocity.x; | |||||
this.entity.bounds.left = bounds.right; | |||||
} | |||||
} | } | ||||
collidePlatform(bounds, velocity) { | collidePlatform(bounds, velocity) { | ||||
update(dt) { | update(dt) { | ||||
// Collide | // Collide | ||||
if (this.entity.has("collider")) { | |||||
if (this.entity.has("collider") && !this.moved) { | |||||
let collider = this.entity.t.collider; | let collider = this.entity.t.collider; | ||||
this.groundBounds = null; | this.groundBounds = null; | ||||
this.groundVelocity = null; | this.groundVelocity = null; | ||||
collider.entities.forEach(e => { | collider.entities.forEach(e => { | ||||
let vel = zeroVector; | |||||
let vel = Vec2.zero; | |||||
if (e.has("physics")) | if (e.has("physics")) | ||||
vel = e.t.physics.velocity; | vel = e.t.physics.velocity; | ||||
else if (e.has("platform")) | else if (e.has("platform")) | ||||
this.collidePlatform(e.bounds, vel); | this.collidePlatform(e.bounds, vel); | ||||
}); | }); | ||||
collider.structures.forEach((s, i) => { | |||||
let bounds = collider.structureBounds[i]; | |||||
collider.structures.forEach((s) => { | |||||
if (s.attrs.wall) | if (s.attrs.wall) | ||||
this.collideWall(bounds, zeroVector); | |||||
this.collideWall(s.bounds, Vec2.zero); | |||||
else if (s.attrs.platform) | else if (s.attrs.platform) | ||||
this.collidePlatform(bounds, zeroVector); | |||||
this.collidePlatform(s.bounds, Vec2.zero); | |||||
}); | }); | ||||
} | } | ||||
this.onGround = | this.onGround = | ||||
(this.groundVelocity && this.velocity.y >= this.groundVelocity.y); | |||||
this.groundVelocity && this.velocity.y >= this.groundVelocity.y; | |||||
if (this.onGround) { | |||||
if (this.onGround && !this.moved) { | |||||
this.timeLastOnGround = this.entity.time; | this.timeLastOnGround = this.entity.time; | ||||
this.velocity.y = this.groundVelocity.y; | this.velocity.y = this.groundVelocity.y; | ||||
} | } | ||||
postUpdate(dt) { | postUpdate(dt) { | ||||
// Move | // Move | ||||
this.entity.bounds.pos.x += this.velocity.x * dt; | |||||
this.entity.bounds.pos.y += this.velocity.y * dt; | |||||
this.entity.pos.x += this.velocity.x * dt; | |||||
this.entity.pos.y += this.velocity.y * dt; | |||||
if (this.onGround) | |||||
if (this.onGround && !this.moved) | |||||
this.entity.bounds.bottom = this.groundBounds.top; | this.entity.bounds.bottom = this.groundBounds.top; | ||||
this.moved = false; | |||||
} | } | ||||
} | } |