diff options
author | niliara-edu <nil.jimeno@estudiant.fjaverianas.com> | 2024-12-23 18:32:29 +0100 |
---|---|---|
committer | niliara-edu <nil.jimeno@estudiant.fjaverianas.com> | 2024-12-23 18:32:29 +0100 |
commit | a840990bdcabf45fb0d377478ba0ab27222434ae (patch) | |
tree | 030a6c3a6befce284733f5643d3972e3a1504bb2 /src |
initial commit
Diffstat (limited to 'src')
-rw-r--r-- | src/assets.js | 22 | ||||
-rw-r--r-- | src/engine.js | 34 | ||||
-rw-r--r-- | src/engine/clock.js | 26 | ||||
-rw-r--r-- | src/engine/keyboard.js | 23 | ||||
-rw-r--r-- | src/engine/screen.js | 87 | ||||
-rw-r--r-- | src/engine/vector.js | 47 | ||||
-rw-r--r-- | src/entities/boshy.js | 65 | ||||
-rw-r--r-- | src/entities/boshybullet.js | 30 | ||||
-rw-r--r-- | src/entities/entity.js | 23 | ||||
-rw-r--r-- | src/main.js | 38 | ||||
-rw-r--r-- | src/scenes.js | 30 | ||||
-rw-r--r-- | src/scenes/game.js | 13 | ||||
-rw-r--r-- | src/scenes/prequel.js | 13 |
13 files changed, 451 insertions, 0 deletions
diff --git a/src/assets.js b/src/assets.js new file mode 100644 index 0000000..4a51716 --- /dev/null +++ b/src/assets.js @@ -0,0 +1,22 @@ +export const BOSHY = { + NORMAL: "./assets/sprites/boshy1.png", + DAMAGED:"./assets/sprites/boshy2.png", + BULLET: "./assets/sprites/boshy_bullet.png", + + SOUNDS: { + SHOOT: "./assets/sounds/shoot.ogg", + INTRO: "./assets/sounds/ItsBOSHYtime.ogg", + } +} + +export const BACKGROUND = { + DEFAULT: "./assets/sprites/black_background.png", + DARK_SUN: "./assets/sprites/black_sun_background.png", +} + +export const MUSIC = { + SOLGRYN: './assets/music/Ace Combat Megalith.ogg', + DEATH: './assets/music/loludied.ogg', + PREQUEL: './assets/music/terranigma-theunderworld.ogg', + +} diff --git a/src/engine.js b/src/engine.js new file mode 100644 index 0000000..a7bb8a5 --- /dev/null +++ b/src/engine.js @@ -0,0 +1,34 @@ +import { start, update, draw } from "./main.js" +import { Screen } from "./engine/screen.js" +import { keys, setUpKeyboard } from "./engine/keyboard.js" +import { startClock } from "./engine/clock.js" + +export class Engine { + static frame = 0 + static audio + static screen = new Screen() + static keys = keys + static bgm + + static startEngine() { + setUpKeyboard() + start() + + startClock() + } + + static updateEngine() { + update() + draw() + } + + static playSound(file) { + let audio = new Audio(file) + audio.play() + } + + static playMusic(file) { + this.bgm = new Audio(file) + this.bgm.play() + } +} diff --git a/src/engine/clock.js b/src/engine/clock.js new file mode 100644 index 0000000..e817863 --- /dev/null +++ b/src/engine/clock.js @@ -0,0 +1,26 @@ +import { Engine } from "../engine.js" + +export { Engine } from "../engine.js" +const fps = 60 + +/* cap the game's fps */ +let msPrev = window.performance.now() +const msPerFrame = 1000 / fps +function tick() { + window.requestAnimationFrame(tick) + + const msNow = window.performance.now() + const msPassed = msNow - msPrev + + if (msPassed < msPerFrame) return + + const excessTime = msPassed % msPerFrame + msPrev = msNow - excessTime + + Engine.frame++ + Engine.updateEngine() +} + +export function startClock() { + tick() +} diff --git a/src/engine/keyboard.js b/src/engine/keyboard.js new file mode 100644 index 0000000..d634519 --- /dev/null +++ b/src/engine/keyboard.js @@ -0,0 +1,23 @@ +export function setUpKeyboard() { + document.addEventListener("keyup", k => trigger(k)) + document.addEventListener("keydown", k => trigger(k)) +} + +export const keys = { + right: false, + left: false, + up: false, + down: false, + shoot: false, +} + +function trigger(event) { + let on = event.type == "keydown" + switch (event.key) { + case "ArrowRight": keys.right = on; break; + case "ArrowLeft": keys.left = on; break; + case "ArrowUp": keys.up = on; break; + case "ArrowDown": keys.down = on; break; + case "z": case "Z": keys.shoot = on; break; + } +} diff --git a/src/engine/screen.js b/src/engine/screen.js new file mode 100644 index 0000000..2d32b62 --- /dev/null +++ b/src/engine/screen.js @@ -0,0 +1,87 @@ +import { Vector } from "./vector.js" +import { BACKGROUND } from "../assets.js" + +export class Screen { + viewport = new Vector(650, 500) + + ///////////////////// START ////////////////////// + constructor() { + this.createHTMLElements() + this.setUpTriggers() + this.resize() + } + + createHTMLElements() { + this.div + this.background + this.spawn + + /* create main div */ + this.div = document.createElement("div") + this.div.id = "screen" + this.div.style.backgroundColor = "black" + + /* create background image */ + this.background = document.createElement("img") + this.background.className = "background" + this.background.src = `${BACKGROUND.DEFAULT}` + this.background.style.visibility = "hidden" + this.div.appendChild(this.background) + + /* create relative div to append children */ + this.spawn = document.createElement("div") + this.div.appendChild(this.spawn) + document.body.appendChild(this.div) + } + + setUpTriggers() { + addEventListener("resize", () => { this.resize() }); + } + + + ///////////////////// RESIZE ////////////////////// + real_position = new Vector(0, 0) + real_size = new Vector(0, 0) + scale = new Vector(0, 0) + + resize() { + let w = new Vector(window.innerWidth, window.innerHeight) + + /* get max size keeping aspect ratio */ + if (w.y / this.viewport.y > w.x / this.viewport.x) { + this.real_size.x = w.x + this.real_size.y = Math.floor(w.x / this.viewport.x * this.viewport.y) + } else { + this.real_size.y = w.y + this.real_size.x = Math.floor(w.y / this.viewport.y * this.viewport.x) + } + this.div.style.width = `${this.real_size.x}px` + this.div.style.height = `${this.real_size.y}px` + + /* get centered position */ + this.real_position.x = w.x / 2 - this.real_size.x / 2 + this.real_position.y = w.y / 2 - this.real_size.y / 2 + this.real_position.floor() + + this.div.style.left = `${this.real_position.x}px` + this.div.style.top = `${this.real_position.y}px` + + /* set scale */ + this.scale = this.real_size.x / this.viewport.x + } + + + ///////////////////// COMMANDS ////////////////////// + append(element) { this.spawn.appendChild(element) } + + draw(span, position, size, /* rotation = 0 */) { + span.style.width = `${size.x * this.scale}px` + span.style.height = `${size.y * this.scale}px` + span.style.top = `${(position.y - size.x / 2) * this.scale}px` + span.style.left = `${(position.x - size.y / 2) * this.scale}px` + } + + setBackground(img) { this.background.src = img } + showBackground() { this.background.visibility = "visible" } + hideBackground() { this.background.visibility = "hidden" } +} diff --git a/src/engine/vector.js b/src/engine/vector.js new file mode 100644 index 0000000..452e47b --- /dev/null +++ b/src/engine/vector.js @@ -0,0 +1,47 @@ +export class Vector { + constructor(x=0, y=0) { + this.x = x + this.y = y + } + + add(newVector) { + this.x += newVector.x + this.y += newVector.y + return this + } + + normalize() { + if (this.x != 0 && 0 != this.y) { + let hyp = Math.abs(this.x) + let cSquared = Math.pow(hyp, 2) / 2 + let c = Math.sqrt(cSquared, 2) + + this.x = this.x / Math.abs(this.x) * c + this.y = this.y / Math.abs(this.x) * c + } + return this + } + + multiply(multiplier) { + this.x *= multiplier + this.y *= multiplier + return this + } + + clone() { + return new Vector(this.x, this.y) + } + + static division(vector_a, vector_b) { + return new Vector( + vector_a.x / vector_b.x, + vector_a.y / vector_b.y + ) + } + + floor() { + this.x = Math.floor(this.x) + this.y = Math.floor(this.y) + return this + } +} diff --git a/src/entities/boshy.js b/src/entities/boshy.js new file mode 100644 index 0000000..ea6068d --- /dev/null +++ b/src/entities/boshy.js @@ -0,0 +1,65 @@ +import { BOSHY } from "../assets.js" +import { Vector } from "../engine/vector.js" +import { Engine } from "../engine.js" +import { BoshyBullet } from "./boshybullet.js" +import { Entity } from "./entity.js" + +export class Boshy extends Entity { + reloadTime = 6 + lastShot = 0 + speed = 5 + + constructor() { + super({ + size: new Vector(30, 30), + position: new Vector(325, 400), + sprite: BOSHY.NORMAL, + }) + + Engine.playSound(BOSHY.SOUNDS.INTRO) + } + + update() { + let keys = Engine.keys + let viewport = Engine.screen.viewport + + /* get movement direction */ + let move = new Vector() + let speed = this.speed + if (keys.right) move.x += 1 + if (keys.left) move.x -= 1 + if (keys.up) move.y -= 1 + if (keys.down) move.y += 1 + if (keys.shoot) this.shoot() + + /* apply movement */ + move.normalize() + move.multiply(speed) + this.position.add(move) + + /* check limits */ + if (this.position.x < 0) this.position.x = 0 + if (this.position.y < 0) this.position.y = 0 + if (this.position.x > viewport.x) this.position.x = viewport.x + if (this.position.y > viewport.y) this.position.y = viewport.y + } + + shoot() { + /* check if it can shoot */ + if (Engine.frame < this.lastShot + this.reloadTime) { + return + } + + this.lastShot = Engine.frame /*(reset reload)*/ + + let bullet_a_position = this.position.clone() + let bullet_b_position = this.position.clone() + + bullet_a_position.x = bullet_a_position.x + 5 + bullet_b_position.x = bullet_b_position.x - 5 + + new BoshyBullet(bullet_a_position) + new BoshyBullet(bullet_b_position) + Engine.playSound(BOSHY.SOUNDS.SHOOT) + } +} diff --git a/src/entities/boshybullet.js b/src/entities/boshybullet.js new file mode 100644 index 0000000..ed91ede --- /dev/null +++ b/src/entities/boshybullet.js @@ -0,0 +1,30 @@ +import { BOSHY } from "../assets.js" +import { Vector } from "../engine/vector.js" +import { bullets } from "../main.js" +import { Entity } from "./entity.js" + +export class BoshyBullet extends Entity { + speed = 20 + + constructor(position = new Vector(0,0)) { + super({ + size: new Vector(5, 5), + position: position.floor(), + sprite: BOSHY.BULLET, + }) + + bullets.list.push(this) + } + + update() { + this.position.y -= this.speed + if (this.position.y < 0) { + this.span.remove() + bullets.remove(this) + } + } + + remove() { + this.span.remove() + } +} diff --git a/src/entities/entity.js b/src/entities/entity.js new file mode 100644 index 0000000..ac14d4b --- /dev/null +++ b/src/entities/entity.js @@ -0,0 +1,23 @@ +import { Vector } from "../engine/vector.js" +import { Engine } from "../engine.js" + +export class Entity { + constructor({ + size, + hitbox = size, + sprite, + position = new Vector(0,0), + }) { + this.size = size + this.hitbox = hitbox + this.position = position + + this.span = document.createElement("img") + this.span.src = sprite + Engine.screen.append(this.span) + } + + draw() { + Engine.screen.draw(this.span, this.position, this.size) + } +} diff --git a/src/main.js b/src/main.js new file mode 100644 index 0000000..6822351 --- /dev/null +++ b/src/main.js @@ -0,0 +1,38 @@ +///////////////////// IMPORTS ////////////////////// +import { Boshy } from "./entities/boshy.js" +import { SCENE, SCENES } from "./scenes.js" + + +///////////////////// GLOBALS ////////////////////// +export let boshy +export const bullets = { + list: [], + remove: instance => { bullets.list = bullets.list.filter(b => b != instance) }, + clear: _ => { bullets.list.forEach(b => b.remove()) } +} + +///////////////////// GAME LOGIC ////////////////////// +export function start() { + console.log("game start") + changeScene(SCENES.PREQUEL) +} + +export function update() { + boshy.update() + bullets.list.forEach((bullet) => bullet.update()) + SCENE.update() +} + +export function draw() { + boshy.draw() + bullets.list.forEach((bullet) => bullet.draw()) + SCENE.draw() +} + + +///////////////////// SCENE METHODS ////////////////////// +export function changeScene(scene) { + SCENE.load(scene) + bullets.clear() + boshy = new Boshy() +} diff --git a/src/scenes.js b/src/scenes.js new file mode 100644 index 0000000..09ea493 --- /dev/null +++ b/src/scenes.js @@ -0,0 +1,30 @@ +import * as PREQUEL from "./scenes/prequel.js" +import * as GAME from "./scenes/game.js" + +export const SCENES = { + PREQUEL: "prequel", + GAME: "game", +} + +export const SCENE = { + load: loadScene, + update: null, + draw: null, +} + +let currentScene + +function loadScene(scene) { + currentScene = scene + if (currentScene == SCENES.PREQUEL) { + PREQUEL.start() + SCENE.update = PREQUEL.update + SCENE.draw = PREQUEL.draw + } + + if (currentScene == SCENES.GAME) { + GAME.start() + SCENE.update = GAME.update + SCENE.draw = GAME.draw + } +} diff --git a/src/scenes/game.js b/src/scenes/game.js new file mode 100644 index 0000000..1640aa5 --- /dev/null +++ b/src/scenes/game.js @@ -0,0 +1,13 @@ +import { Engine } from "../engine.js" +import { MUSIC } from "../assets.js" + +export function start() { + Engine.playMusic(MUSIC.SOLGRYN) +} + + +export function update() { +} + +export function draw() { +} diff --git a/src/scenes/prequel.js b/src/scenes/prequel.js new file mode 100644 index 0000000..f24ef99 --- /dev/null +++ b/src/scenes/prequel.js @@ -0,0 +1,13 @@ +import { Engine } from "../engine.js" +import { MUSIC } from "../assets.js" + +export function start() { + Engine.playMusic(MUSIC.PREQUEL) +} + + +export function update() { +} + +export function draw() { +} |