Files
biff-bolton-ep1/js/update.js
T
2023-02-19 01:05:41 +01:00

469 lines
11 KiB
JavaScript

//-------------------------------------------------------------------------
// 3. UPDATE LOOP
//-------------------------------------------------------------------------
function update(dt) {
updatePlayer(dt)
updateBullets(dt)
updateMonsters(dt)
updateVehicles(dt)
checkTreasure()
checkPickups()
checkLiquids()
// updateDoors(dt)
checkDoors()
// ! Vielleicht eigene update Funktion für Musik schreiben
// theme.level1.play()
}
function updatePlayer(dt) {
updateEntity(player, dt)
}
function updateVehicles(dt) {
var n, max
for (n = 0, max = vehicles.length; n < max; n++)
updateVehicle(vehicles[n], dt)
}
function updateVehicle(vehicle, dt) {
updateEntity(vehicle, dt)
if (
overlap(player.x, player.y, TILE, TILE, vehicle.x, vehicle.y, TILE, TILE)
) {
if (player.dy > 0 && vehicle.y - player.y > TILE / 2)
// ! Wie mache ich hier den collision check? Achtung, die height und width des Vehicles ist immer noch 16x16
console.log('log collision vehicle!')
}
}
function updateMonsters(dt) {
var n, max
for (n = 0, max = monsters.length; n < max; n++)
updateMonster(monsters[n], dt)
}
function updateMonster(monster, dt) {
// monster.slimeMonster && console.log('log monster ', monster)
if (!monster.dead) {
updateEntity(monster, dt)
if (
overlap(player.x, player.y, TILE, TILE, monster.x, monster.y, TILE, TILE)
) {
if (player.dy > 0 && monster.y - player.y > TILE / 2) killMonster(monster)
else if (player.vul) {
reduceHitpoints(player, 1)
}
}
}
}
function shoot(player) {
//globalObject.ammo > 0 ? sfx.shoot.play() : sfx.click.play()
if (player.shooting) return
player.shooting = true
const bulletX = player.x
const bulletY = player.y
const direction = player.flipped
const weaponType = player?.currentWeapon || 'simpleGun'
if (globalObject.ammo > 0) {
sfx.shoot.play()
globalObject.ammo--
bullets.push({
bullet: true,
width: 4,
height: 4,
flipped: player.flipped,
originX: bulletX,
originY: bulletY,
x: bulletX,
y: bulletY + player.height / 2,
directionLeft: direction,
ammoType: weaponType,
damage: 1,
})
} else {
sfx.click.play()
}
setTimeout(() => {
player.shooting = false
}, 200)
}
function updateBullets(dt) {
var n, max
for (n = 0, max = bullets.length; n < max; n++) updateBullet(bullets[n], dt)
}
function updateBullet(bullet, dt) {
if (!!bullet) {
if (bullet.directionLeft) {
bullet.x = bullet.x - ammoType.velocity
} else {
bullet.x = bullet.x + ammoType.velocity
}
var n, max, monster, thisBullet
for (n = 0, max = monsters.length; n < max; n++) {
monster = monsters[n]
thisBullet = bullet
if (!monster.dead) {
if (
overlap(
thisBullet.x,
thisBullet.y,
ammoType.width,
ammoType.height,
monster.x,
monster.y,
TILE,
TILE
)
)
reduceHitpoints(monster, bullet.damage),
sfx.explode.play(),
destroyBullet(bullet)
}
}
if (
(!bullet.directionLeft &&
bullet.x > bullet.originX + ammoType.distance) ||
(bullet.directionLeft && bullet.x < bullet.originX - ammoType.distance)
) {
destroyBullet(bullet)
}
}
}
function destroyBullet(bullet) {
const index = bullets.indexOf(bullet)
if (index > -1) {
bullets.splice(index, 1)
}
}
function checkTreasure() {
var n, max, t
for (n = 0, max = treasure.length; n < max; n++) {
t = treasure[n]
if (
!t.collected &&
overlap(player.x, player.y, TILE, TILE, t.x, t.y, TILE, TILE)
)
collectTreasure(t)
}
}
function checkPickups() {
var n, max, p
for (n = 0, max = pickups.length; n < max; n++) {
p = pickups[n]
if (
!p.collected &&
overlap(player.x, player.y, TILE, TILE, p.x, p.y, TILE, TILE)
)
collectPickup(p)
}
}
function collectPickup(p) {
// console.log('log pickup ', p)
if (p.extralife) {
addExtraLife(p)
}
if (p.ammo) {
addAmmo(p)
}
if (p.health) {
addHitPoints(p)
}
}
function addExtraLife(p) {
globalObject.lifes++
p.collected = true
sfx.smb_powerup.play()
}
function addHitPoints(p) {
if (globalObject.hitpoints < globalObject.maxHitpoints) {
globalObject.hitpoints++
p.collected = true
sfx.stomp.play()
}
}
function addAmmo(p) {
if (globalObject.ammo < globalObject.maxAmmo) {
globalObject.ammo++
p.collected = true
sfx.kick.play()
}
}
// * Check if Player is Swimming or Diving
function checkLiquids() {
var n, max, l
for (n = 0, max = liquids.length; n < max; n++) {
l = liquids[n]
if (overlap(player.x, player.y, TILE, TILE, l.x, l.y, l.width, l.height)) {
!player.swimming && sfx.splash.play()
player.dy = player.dy / 1.15
if (!player.swimming) player.jumping = false
player.swimming = true
} else {
player.swimming = false
}
if (
overlap(
player.x,
player.y - player.height,
TILE,
TILE,
l.x,
l.y,
l.width,
l.height
)
) {
player.diving = true
reduceOxygen(4)
} else {
player.diving = false
replenishOxygen(16)
}
}
}
// * Reduce & Replenish Oxygen Functions
function reduceOxygen(rate) {
if (player.diving && globalObject.oxygen >= 0) {
globalObject.oxygen -= rate / 100
} else if (player.vul) {
reduceHitpoints(player, 1, 2000)
}
}
function replenishOxygen(rate) {
if (globalObject.oxygen <= globalObject.maxOxygen) {
globalObject.oxygen += rate / 100
}
}
function checkDoors() {
// ! Hier habe ich rudimentär einen Levelwechsel eingebaut.
// ! Was noch fehlt ist, dass ein globales Player-Objekt beibehalten wird.
var n, max, t
for (n = 0, max = doors.length; n < max; n++) {
t = doors[n]
if (
overlap(
player.x,
player.y,
TILE * 2,
TILE * 2,
t.x,
t.y,
TILE * 2,
TILE * 2
)
)
player.interact && useDoor(t)
}
}
function useDoor(t) {
let leadsTo
switch (t.leadsTo) {
case 'level1':
leadsTo = levelObject.level1
break
case 'level2':
leadsTo = levelObject.level2
break
case 'level3':
leadsTo = levelObject.level3
break
}
sfx.openDoor.play()
levelTransition(leadsTo)
}
function levelTransition(level) {
setTimeout(() => {
_initLevel(level)
}, 800)
}
function killMonster(monster) {
globalObject.killed++
monster.dead = true
sfx.killMonster.play()
}
// * Take Damage Function
function reduceHitpoints(entity, damage, timeout) {
const milliceconds = timeout || 1500
if (
entity.player ? globalObject.hitpoints > 1 : entity.currentHitpoints > 1
) {
entity.player
? (globalObject.hitpoints -= damage)
: (entity.currentHitpoints -= damage)
entity.vul = false
entity.hurt = true
sfx.takeDamage.play()
setTimeout(() => {
entity.vul = true
entity.hurt = false
}, milliceconds)
} else killEntity(entity)
}
function killEntity(entity) {
// console.log('killEntity: ', entity)
if (entity.player === true) {
killPlayer(entity)
}
if (entity.monster === true) {
killMonster(entity)
}
}
function killPlayer(player) {
sfx.die.play()
player.x = player.start.x
player.y = player.start.y
player.dx = player.dy = 0
globalObject.hitpoints = player.maxHitpoints
globalObject.oxygen = globalObject.maxOxygen
globalObject.lifes--
// console.log('log globalObject: ', globalObject.lifes)
}
function collectTreasure(t) {
globalObject.collected++
t.collected = true
sfx.pickup.play()
}
function updateEntity(entity, dt) {
entity.vehicle && console.log('log entity ', entity)
var wasleft = entity.dx < 0,
wasright = entity.dx > 0,
falling = entity.falling,
swimming = entity.swimming || false,
friction =
entity.friction * (falling && !swimming ? 0.5 : swimming ? 0.1 : 1),
impulse = entity.impulse,
swimImpulse = entity.impulse / 3,
accel = entity.accel * (falling && !swimming ? 0.5 : swimming ? 0.1 : 1),
gravity = swimming ? METER * 8 : METER * GRAVITY
entity.ddx = 0
entity.ddy = gravity // ! Hier wir gravity angewandt
// * Hier wird die Entity bewegt.
if (entity.left) (entity.ddx = entity.ddx - accel), (entity.flipped = true)
else if (wasleft) entity.ddx = entity.ddx + friction
if (entity.right) (entity.ddx = entity.ddx + accel), (entity.flipped = false)
else if (wasright) entity.ddx = entity.ddx - friction
if (entity.jump) {
if (!entity.jumping && !falling && !swimming) {
jump(entity)
} else if (!entity.jumping && swimming) {
swim(entity)
}
}
function jump(entity) {
sfx.jump.play()
entity.ddy = entity.ddy - impulse // an instant big force impulse
entity.jumping = true
}
function swim(entity) {
sfx.swim.play()
entity.ddy = entity.down
? entity.ddy + swimImpulse
: entity.up
? entity.ddy - swimImpulse * 2
: entity.ddy - swimImpulse
entity.jumping = true
setTimeout(() => {
entity.jumping = false
}, 400)
}
// ! "dt" ist hier identisch mit "step", was in der index.js in die update() gegeben wird. Konstant bei ca. 0.01666
//console.log('log entity.x + dt * entity.dx: ', player.x + dt * player.dx)
entity.x = entity.x + dt * entity.dx
entity.y = entity.y + dt * entity.dy
entity.dx = bound(entity.dx + dt * entity.ddx, -entity.maxdx, entity.maxdx)
entity.dy = bound(entity.dy + dt * entity.ddy, -entity.maxdy, entity.maxdy)
if ((wasleft && entity.dx > 0) || (wasright && entity.dx < 0)) {
entity.dx = 0 // clamp at zero to prevent friction from making us jiggle side to side
}
var tx = p2t(entity.x),
ty = p2t(entity.y),
nx = entity.x % TILE,
ny = entity.y % TILE,
cell = tcell(tx, ty, mapWidth), //! Was ist das hier?
cellright = tcell(tx + 1, ty, mapWidth),
celldown = tcell(tx, ty + 1, mapWidth),
celldiag = tcell(tx + 1, ty + 1, mapWidth)
// ? Ist das hier der Collision Check?
if (entity.dy > 0) {
if ((celldown && !cell) || (celldiag && !cellright && nx)) {
entity.y = t2p(ty)
entity.dy = 0
entity.falling = false
entity.jumping = false
ny = 0
}
} else if (entity.dy < 0) {
if ((cell && !celldown) || (cellright && !celldiag && nx)) {
entity.y = t2p(ty + 1)
entity.dy = 0
cell = celldown
cellright = celldiag
ny = 0
}
}
if (entity.dx > 0) {
if ((cellright && !cell) || (celldiag && !celldown && ny)) {
entity.x = t2p(tx)
entity.dx = 0
}
} else if (entity.dx < 0) {
if ((cell && !cellright) || (celldown && !celldiag && ny)) {
entity.x = t2p(tx + 1)
entity.dx = 0
}
}
if (entity.monster || entity.slimeMonster) {
if (entity.left && (cell || !celldown)) {
entity.left = false
entity.right = true
} else if (entity.right && (cellright || !celldiag)) {
entity.right = false
entity.left = true
}
}
entity.falling = !(celldown || (nx && celldiag))
}