diff options
Diffstat (limited to 'centipede/js/game/objects')
-rw-r--r-- | centipede/js/game/objects/bullet.js | 11 | ||||
-rw-r--r-- | centipede/js/game/objects/centipede.js | 105 | ||||
-rw-r--r-- | centipede/js/game/objects/explosion.js | 14 | ||||
-rw-r--r-- | centipede/js/game/objects/flea.js | 49 | ||||
-rw-r--r-- | centipede/js/game/objects/mushroom.js | 43 | ||||
-rw-r--r-- | centipede/js/game/objects/player.js | 63 | ||||
-rw-r--r-- | centipede/js/game/objects/scorpion.js | 32 | ||||
-rw-r--r-- | centipede/js/game/objects/spider.js | 45 |
8 files changed, 362 insertions, 0 deletions
diff --git a/centipede/js/game/objects/bullet.js b/centipede/js/game/objects/bullet.js new file mode 100644 index 0000000..5791aca --- /dev/null +++ b/centipede/js/game/objects/bullet.js @@ -0,0 +1,11 @@ +game.Bullet = (spec) => { + const object = game.Object(spec); + const parentUpdate = object.update; + object.update = (elapsedTime) => { + parentUpdate(elapsedTime); + if (object.y < 0) { + object.alive = false; + } + }; + return object; +}
\ No newline at end of file diff --git a/centipede/js/game/objects/centipede.js b/centipede/js/game/objects/centipede.js new file mode 100644 index 0000000..7e4c8f6 --- /dev/null +++ b/centipede/js/game/objects/centipede.js @@ -0,0 +1,105 @@ +game.CentipedePiece = (spec) => { + const object = game.Object(spec); + object.poisonedTimer = 1000; + const parentUpdate = object.update; + object.turningState = { + turning: false, + turnDirectionY: 1, + objectStateBeforeTurn: null, + }; + object.turn = () => { + object.turningState.objectStateBeforeTurn = {dx: object.dx, dy: object.dy, x: object.x, y: object.y}; + object.turningState.turning = true; + if (object.y >= game.height - object.height) { + object.turningState.turnDirectionY = -1; + } + if (object.y <= 0) { + object.turningState.turnDirectionY = 1; + } + }; + object.update = (elapsedTime) => { + if (object.poisoned) { + object.turningState.turning = false; + } + else if ((object.x+object.width > game.width || object.x < 0) && !object.turningState.turning) { + object.x = Math.min(Math.max(object.x, 0), game.width - object.width); + object.turn(); + } + if (object.turningState.turning) { + object.dx = 0; + object.dy = Math.abs(object.turningState.objectStateBeforeTurn.dx) * object.turningState.turnDirectionY; + object.rot = object.dy > 0 ? -90 : 90; + if (Math.abs(object.turningState.objectStateBeforeTurn.y - object.y) >= object.height) { + object.y = object.turningState.objectStateBeforeTurn.y + object.height * object.turningState.turnDirectionY; + object.dx = -object.turningState.objectStateBeforeTurn.dx; + object.rot = object.dx > 0 ? 180 : 0; + object.dy = 0; + object.turningState.turning = false; + } + } + parentUpdate(elapsedTime); + object.y = Math.min(Math.max(object.y, 0), game.height - object.height); + }; + object.onMushroomCollision = (mushroom) => { + if (mushroom.poisoned && object.dy === 0) { + object.poison(); + return; + } + if (!object.turningState.turning) { + if (mushroom.x < object.x && object.dx > 0) { + return; + } + object.turn(); + } + } + return object; +} + +game.Centipede = (spec) => { + const segments = [ + ...Array(spec.segments).fill(0).map((_, i) => game.CentipedePiece({...spec, x: spec.startX - spec.width*(i+1), y: spec.startY, sprite: game.sprites.centipedeBody})), + game.CentipedePiece({...spec, x: spec.startX, y: spec.startY, sprite: game.sprites.centipedeHead}), + ]; + + const update = (elapsedTime) => { + segments.map((segment) => segment.update(elapsedTime)); + } + + const draw = (elapsedTime) => { + segments.map((segment) => segment.draw(elapsedTime)); + } + + const intersects = (object) => { + return segments.filter((segment) => segment.intersects(object)).length; + } + + const onBulletCollision = (bullet) => { + if (bullet.alive) { + const segment = segments.find((segment) => segment.intersects(bullet)); + const segmentIndex = segments.indexOf(segment); + + const {mushX, mushY} = game.Mushroom.toMushCoords(segment); + game.explosions.push(game.Explosion({...game.Mushroom.toGameCoords({mushX, mushY}), width: segment.width, height: segment.height, sprite: game.sprites.explosionSmall})); + if (!game.mushrooms.find((mushroom) => mushroom.mushX === mushX && mushroom.mushY === mushY)) { + game.mushrooms.push(game.Mushroom({mushX, mushY, ...game.mushroomDims})); + } + game.score += segment.sprite === game.sprites.centipedeHead ? 20 : 5; + game.sounds.enemy_hit.load(); + game.sounds.enemy_hit.play(); + segments.splice(segmentIndex, 1); + } + bullet.alive = false; + } + + const onMushroomCollision = (mushroom) => { + segments.find((segment) => segment.intersects(mushroom)).onMushroomCollision(mushroom); + } + + const onPlayerCollision = (player) => { + player.kill(); + } + + const alive = () => segments.length ? true : false; + + return {update, draw, segments, intersects, onBulletCollision, onMushroomCollision, onPlayerCollision, alive}; +}
\ No newline at end of file diff --git a/centipede/js/game/objects/explosion.js b/centipede/js/game/objects/explosion.js new file mode 100644 index 0000000..f38d820 --- /dev/null +++ b/centipede/js/game/objects/explosion.js @@ -0,0 +1,14 @@ +game.Explosion = (spec) => { + const object = game.Object(spec); + let explosionTime = 0; + const parentUpdate = object.update; + object.update = (elapsedTime) => { + parentUpdate(elapsedTime); + explosionTime += elapsedTime; + + if (explosionTime > (object.sprite.numFrames * object.sprite.timePerFrame)) { + object.alive = false; + } + } + return object; +}
\ No newline at end of file diff --git a/centipede/js/game/objects/flea.js b/centipede/js/game/objects/flea.js new file mode 100644 index 0000000..23479cc --- /dev/null +++ b/centipede/js/game/objects/flea.js @@ -0,0 +1,49 @@ +game.Flea = (spec) => { + const object = game.Object(spec); + const parentUpdate = object.update; + object.mushroomCoords = game.Mushroom.toMushCoords(object); + object.update = (elapsedTime) => { + const newMushroomCoords = game.Mushroom.toMushCoords(object); + if (newMushroomCoords.mushY !== object.mushroomCoords.mushY || newMushroomCoords.mushX !== object.mushroomCoords.mushX) { + if (Math.random() < Math.min(0.15 + 0.05*game.level, 0.7)) { + if (!game.mushrooms.find((mushroom) => mushroom.mushX === newMushroomCoords.mushX && mushroom.mushY === newMushroomCoords.mushY)) { + game.mushrooms.push(game.Mushroom({...newMushroomCoords, ...game.mushroomDims})); + } + } + object.mushroomCoords = newMushroomCoords; + } + parentUpdate(elapsedTime); + }; + + object.onMushroomCollision = (mushroom) => { + if (mushroom.poisoned) { + mushroom.state = 0; + object.poison(); + } + } + + object.explode = () => { + game.explosions.push(game.Explosion({x: object.x, y: object.y, width: object.width, height: object.height, sprite: game.sprites.explosionSmall})); + game.sounds.enemy_hit.load(); + game.sounds.enemy_hit.play(); + } + + object.onBulletCollision = (bullet) => { + game.score += 20; + object.alive = false; + object.explode(); + } + + object.onPlayerCollision = (player) => { + object.alive = false; + player.kill(); + object.explode(); + } + + object.onBulletCollision = (bullet) => { + object.explode(); + object.alive = false; + } + + return object; +}
\ No newline at end of file diff --git a/centipede/js/game/objects/mushroom.js b/centipede/js/game/objects/mushroom.js new file mode 100644 index 0000000..b1f4787 --- /dev/null +++ b/centipede/js/game/objects/mushroom.js @@ -0,0 +1,43 @@ +game.Mushroom = (spec) => { + spec.state = spec.state ?? 4; + const {mushX, mushY} = spec; + const objectSpec = {...spec}; + objectSpec.x = mushX * objectSpec.width; + objectSpec.y = mushY * objectSpec.height; + const object = {...spec, ...game.Object(objectSpec)}; + object.onBulletCollision = (bullet) => { + if (bullet.alive) { + object.state--; + game.score += 5; + game.sounds.mushroom_hit.load(); + game.sounds.mushroom_hit.play(); + } + bullet.alive = false; + }; + object.draw = (elapsedTime) => { + if (object.state) { + object.sprite = object.poisoned ? game.sprites.poisonMushrooms[object.state-1] : game.sprites.regularMushrooms[object.state-1]; + object.sprite.draw(elapsedTime, object); + } + } + return object; +}; + +game.Mushroom.toMushCoords = (coords) => { + return {mushX: Math.ceil(coords.x / game.mushroomDims.width), mushY: Math.ceil(coords.y / game.mushroomDims.height)}; +} + +game.Mushroom.toGameCoords = (mushCoords) => { + return {x: mushCoords.mushX * game.mushroomDims.width, y: mushCoords.mushY * game.mushroomDims.height}; +} + +game.Mushroom.generateMushrooms = (mushroomSpec) => { + const mushPositions = new Set(); + for (let i = 0; i < Math.max(Math.random(), 0.05) * game.height / mushroomSpec.height * game.width / mushroomSpec.width * game.level * 0.5; i++) { + mushPositions.add(JSON.stringify([Math.floor(Math.random() * game.width / mushroomSpec.width), Math.max(1, Math.floor(Math.random() * (game.height / mushroomSpec.height - 3)))])); + } + return Array.from(mushPositions).map((pos) => { + const [mushX, mushY] = JSON.parse(pos); + return game.Mushroom({...mushroomSpec, mushX, mushY}); + }); +} diff --git a/centipede/js/game/objects/player.js b/centipede/js/game/objects/player.js new file mode 100644 index 0000000..a1f6ea0 --- /dev/null +++ b/centipede/js/game/objects/player.js @@ -0,0 +1,63 @@ +game.Player = (spec) => { + const object = game.Object(spec); + object.poisonedTimer = 4000; + object.elapsedPoisonedTimer = 0; + object.poisoned = false; + object.bulletTimer = spec.bulletTimer ?? 150; + object.maxPlayerHeight = spec.maxPlayerHeight ?? game.height - object.height*6; + object.elapsedBulletTimer = 0; + object.lives = spec.lives ?? 3; + + const parentUpdate = object.update; + object.update = (elapsedTime) => { + parentUpdate(elapsedTime); + object.x = Math.max(0, Math.min(object.x, game.width - object.width)); + object.y = Math.max(object.maxPlayerHeight, Math.min(object.y, game.height - object.height)); + object.dx = object.dy = 0; + object.elapsedBulletTimer += elapsedTime; + }; + object.moveUp = () => { + object.dy = -0.75; + } + object.moveDown = () => { + object.dy = 0.75; + } + object.moveLeft = () => { + object.dx = -0.5; + } + object.moveRight = () => { + object.dx = 0.5; + } + + object.shoot = () => { + if (object.elapsedBulletTimer > object.bulletTimer) { + object.elapsedBulletTimer = 0; + game.bullets.push(game.Bullet({x: object.x + object.width/2 - 5, y: object.y-object.height/2, dx: 0, dy: -1.5, width: 5, height: 50, sprite: game.sprites.bullet})); + game.sounds.laser.load(); + game.sounds.laser.play(); + } + } + + object.onMushroomCollision = (mushroom) => { + if (mushroom.poisoned) { + mushroom.state = 0; + object.poison(); + } + if (mushroom.x > object.x) { + object.x = mushroom.x - mushroom.width; + } + if (mushroom.x < object.x) { + object.x = mushroom.x + mushroom.width; + } + } + + object.kill = () => { + object.lives--; + game.resetObjects(); + if (object.lives == 0) { + game.gameOver(); + } + } + + return object; +}
\ No newline at end of file diff --git a/centipede/js/game/objects/scorpion.js b/centipede/js/game/objects/scorpion.js new file mode 100644 index 0000000..036db14 --- /dev/null +++ b/centipede/js/game/objects/scorpion.js @@ -0,0 +1,32 @@ +game.Scorpion = (spec) => { + const object = game.Object(spec); + + const parentUpdate = object.update; + object.update = (elapsedTime) => { + parentUpdate(elapsedTime); + }; + + object.explode = () => { + game.explosions.push(game.Explosion({x: object.x, y: object.y, width: object.width, height: object.height, sprite: game.sprites.explosionBig})); + game.sounds.enemy_hit.load(); + game.sounds.enemy_hit.play(); + } + + object.onBulletCollision = (bullet) => { + game.score += 100; + object.alive = false; + object.explode(); + } + + object.onPlayerCollision = (player) => { + object.alive = false; + player.kill(); + object.explode(); + } + + object.onMushroomCollision = (mushroom) => { + mushroom.poisoned = true; + } + + return object; +}
\ No newline at end of file diff --git a/centipede/js/game/objects/spider.js b/centipede/js/game/objects/spider.js new file mode 100644 index 0000000..732c0a3 --- /dev/null +++ b/centipede/js/game/objects/spider.js @@ -0,0 +1,45 @@ +game.Spider = (spec) => { + const object = game.Object(spec); + + const parentUpdate = object.update; + + object.randomizeVel = () => { + object.dx = Math.min(Math.random(), 0.25 + 0.05*game.level) * (Math.random() > 0.5 ? 1 : -1); + object.dy = Math.min(Math.random(), 0.25 + 0.05*game.level) * (Math.random() > 0.5 ? 1 : -1); + } + + object.update = (elapsedTime) => { + if (Math.random() < 0.01*game.level) { + object.randomizeVel(); + } + if (object.x < 0 || object.x > game.width - object.width) { + object.dx = -object.dx; + } + if (object.y < 0 || object.y > game.height - object.height) { + object.dy = -object.dy; + } + object.x = Math.max(0, Math.min(game.width - object.width, object.x)); + object.y = Math.max(0, Math.min(game.height - object.height, object.y)); + parentUpdate(elapsedTime); + }; + + object.explode = () => { + game.explosions.push(game.Explosion({x: object.x, y: object.y, width: object.width, height: object.height, sprite: game.sprites.explosionBig})); + game.sounds.enemy_hit.load(); + game.sounds.enemy_hit.play(); + } + + object.onBulletCollision = (bullet) => { + game.score += 150; + object.alive = false; + object.explode(); + } + + object.onPlayerCollision = (player) => { + object.alive = false; + player.kill(); + object.explode(); + } + + return object; +}
\ No newline at end of file |