diff options
Diffstat (limited to 'src')
67 files changed, 503 insertions, 179 deletions
diff --git a/src/Animation.ts b/src/Animation.ts index 968a57d..9d49ec7 100644 --- a/src/Animation.ts +++ b/src/Animation.ts @@ -4,6 +4,7 @@ import Drawable from "./Drawable"; export default class Anime extends Drawable { i = 0; j = 0; + cb: any | null; constructor(public drawable: Drawable, public frames: Array<string | HTMLImageElement>) { super(drawable._x, drawable._y) @@ -24,6 +25,7 @@ export default class Anime extends Drawable { } catch (e) { debugger } } if (++this.j === 5) { this.i++; this.j = 0; } + if (this.i === this.frames.length && this.cb) this.cb() return this.i !== this.frames.length; } } diff --git a/src/Drawable.ts b/src/Drawable.ts index 375d515..7589c69 100644 --- a/src/Drawable.ts +++ b/src/Drawable.ts @@ -1,4 +1,5 @@ -import { canvas, ctx, PLAYER_SIZE } from "./consts"; +import { canvas, ctx, TOPBAR_HEIGHT } from "./consts"; +import { keys } from "./Events"; import { IMGS } from "./Images"; export default abstract class Drawable { @@ -54,8 +55,8 @@ export default abstract class Drawable { return } // Used only for Player - if (val <= 35) { this._x = 35; this.sprite = IMGS.playerUp } - else if (val + this.width >= canvas.width - 35) { this._x = canvas.width - 35 - this.width; this.sprite = IMGS.playerUp } + if (val <= 25) { this._x = 25; this.sprite = IMGS.playerUp } + else if (val + this.width >= canvas.width - 25) { this._x = canvas.width - 25 - this.width; this.sprite = IMGS.playerUp } else this._x = val } get y() { return this._y } @@ -70,10 +71,12 @@ export default abstract class Drawable { const right = this.sprite === IMGS.playerRight const diff = left ? 1 : (right ? 2 : 0) - if (val <= 15 + 24) this._y = 15 + 24; - // else if (val + this.height >= canvas.height - 15) this._y = canvas.height - 15 - this.height + diff; + const yLimit = 60 + if (val <= yLimit + 24) this._y = yLimit + 24; + // else if (val + this.height >= canvas.height - yLimit) this._y = canvas.height - yLimit - this.height + diff; else if (val + this.height >= canvas.height - 15) { - if (left || right) this._y = canvas.height - 15 - this.height + diff + 1; + if (keys.up && keys.lasty === "up") this._y = val + else if (left || right) this._y = canvas.height - 15 - this.height + diff + 1; else this._y = canvas.height - 15 - this.height + diff; } else this._y = val @@ -85,16 +88,13 @@ export default abstract class Drawable { /// Should be abstract but this is extended by Animation which doesnt move // abstract move(): boolean; move() { return true; }; - isOutsideMap() { return this.x2 < 0 || this.y2 < 0 || this.x > canvas.width || this.y > canvas.height } + isOutsideMap() { return this.x2 < 0 || this.y2 < TOPBAR_HEIGHT || this.x > canvas.width || this.y > canvas.height } } export class Rectangle extends Drawable { sprite = "rgba(128,0,128, 0.5)" constructor(public begetter: Drawable, x?: number, y?: number, width?: number, height?: number) { - if (begetter.width === PLAYER_SIZE) { - console.log(begetter.x, begetter.y, begetter.width, begetter.height); - } x = x ?? 0 y = y ?? 0 super(x, y); diff --git a/src/Events.ts b/src/Events.ts index 2a07ea9..7d925b4 100644 --- a/src/Events.ts +++ b/src/Events.ts @@ -14,6 +14,8 @@ export const keys = { roll: false, repeat: false, fps: 50, + lastx: "", + lasty: "", } // window.onkeydown = window.onkeydown ?? ((e: KeyboardEvent) => e.repeat ? keys.fire = false : setKey(e.key, true)) @@ -21,10 +23,10 @@ window.onkeydown = window.onkeydown ?? ((e: KeyboardEvent) => setKey(e.key, true window.onkeyup = window.onkeyup ?? ((e: KeyboardEvent) => setKey(e.key, false, e.repeat)) function setKey(key: string, val: boolean, repeat: boolean) { - if (["w", "k"].includes(key)) keys.up = val; - else if (["a", "h"].includes(key)) keys.left = val; - else if (["s", "j"].includes(key)) keys.down = val; - else if (["d", "l"].includes(key)) keys.right = val; + if (["w", "k"].includes(key)) { keys.up = val; keys.lasty = "up" } + else if (["a", "h"].includes(key)) { keys.left = val; keys.lastx = "left" } + else if (["s", "j"].includes(key)) { keys.down = val; keys.lasty = "down" } + else if (["d", "l"].includes(key)) { keys.right = val; keys.lastx = "right" } else if (["m", ";", "/"].includes(key)) { keys.fire = val; keys.repeat = repeat } else if ([" "].includes(key)) keys.roll = val; else if (["r"].includes(key)) location.reload(); diff --git a/src/Highscore.ts b/src/Highscore.ts index b70715b..a18fbe6 100644 --- a/src/Highscore.ts +++ b/src/Highscore.ts @@ -4,7 +4,8 @@ import Drawable from "./Drawable"; import { Background } from "./drawables/Background"; import { Selector } from "./drawables/Selector"; import { keys } from "./Events"; -import { IMGS } from "./Images"; +import { startAgain } from "./game"; +import { IMGS, SOUNDS } from "./Images"; import { getPlace, getStorage, Score, setStorage } from "./Storage"; export default class Highscore extends Drawable { @@ -16,6 +17,7 @@ export default class Highscore extends Drawable { _bx = 12 _by = 37 moving = false; + stop = false dx = 32; dy = 26; name = [' ', ' ', ' ']; @@ -66,25 +68,20 @@ export default class Highscore extends Drawable { } } move(): boolean { + if (this.stop) return true if (!this.moving) { - if (+keys.right ^ +keys.left) { - keys.right ? this.bx = this.selector.x + this.dx : this.bx = this.selector.x - this.dx - } else { - this.bx = this.selector.x - } - - if (+keys.up ^ +keys.down) { - keys.down ? this.by = this.selector.y + this.dy : this.by = this.selector.y - this.dy - } else { - this.by = this.selector.y - } - if (keys.fire && Date.now() - this.lastTimestamp > 300) { let [x, y] = [this.selector.x, this.selector.y] x = Math.floor(x / this.dx) y = Math.floor(y / this.dy) - 1 const char = alphabet[x + y * 9]; if (char === "rv") { + SOUNDS.rvCheck.play() + this.stop = true + SOUNDS.rvCheck.onended = () => { + this.stop = false + SOUNDS.rvCheck.onended = null + } for (let i = this.name.length - 1; i >= 0; i--) { if (this.name[i] !== " ") { this.name[i] = ' '; break } } @@ -92,7 +89,7 @@ export default class Highscore extends Drawable { else if (char === "ed") { console.log(this.score, this.name, this.place); if (this.place == null) throw Error("Place is null"); - const place = this.place[0] === 't' ? 1 :parseInt(this.place[0]) + const place = this.place[0] === 't' ? 1 : parseInt(this.place[0]) if (place < 7) { const score = { name: this.name, score: this.score.toString(), world: "01" } as Score; const ns = getStorage() @@ -101,16 +98,39 @@ export default class Highscore extends Drawable { setStorage(ns); } + SOUNDS.name.pause() + startAgain() + return false; } - else if (this.name.filter(a => a !== ' ').length === 3) this.name[2] = char; else { - for (let i = 0; i < this.name.length; i++) { - if (this.name[i] === " ") { this.name[i] = char; break; } + SOUNDS.letterCheck.play() + this.stop = true + SOUNDS.letterCheck.onended = () => { + this.stop = false + SOUNDS.letterCheck.onended = null + } + if (this.name.filter(a => a !== ' ').length === 3) this.name[2] = char; + else { + for (let i = 0; i < this.name.length; i++) { + if (this.name[i] === " ") { this.name[i] = char; break; } + } } } this.lastTimestamp = Date.now() } + if (!this.stop && +keys.right ^ +keys.left) { + keys.right ? this.bx = this.selector.x + this.dx : this.bx = this.selector.x - this.dx + } else { + this.bx = this.selector.x + } + + if (!this.stop && +keys.up ^ +keys.down) { + keys.down ? this.by = this.selector.y + this.dy : this.by = this.selector.y - this.dy + } else { + this.by = this.selector.y + } + } if (this.selector.x !== this.bx || this.selector.y !== this.by) { diff --git a/src/Images.ts b/src/Images.ts index aee7e53..2bc4f50 100644 --- a/src/Images.ts +++ b/src/Images.ts @@ -10,24 +10,51 @@ export const IMGS = { playerUp: {} as HTMLImageElement, playerLeft: {} as HTMLImageElement, playerRight: {} as HTMLImageElement, + playerSmall: {} as HTMLImageElement, + playerRot1: {} as HTMLImageElement, + playerRot2: {} as HTMLImageElement, + playerRot3: {} as HTMLImageElement, + playerRot4: {} as HTMLImageElement, + playerRot5: {} as HTMLImageElement, + playerRot6: {} as HTMLImageElement, + playerRot7: {} as HTMLImageElement, + playerRot8: {} as HTMLImageElement, bigCircleDown: {} as HTMLImageElement, + bigCircleDownRed: {} as HTMLImageElement, bigCircleDownToRight1: {} as HTMLImageElement, + bigCircleDownToRight1Red: {} as HTMLImageElement, bigCircleDownToRight2: {} as HTMLImageElement, + bigCircleDownToRight2Red: {} as HTMLImageElement, bigCircleDownToRight3: {} as HTMLImageElement, + bigCircleDownToRight3Red: {} as HTMLImageElement, bigCircleRight: {} as HTMLImageElement, + bigCircleRightRed: {} as HTMLImageElement, bigCircleRightToUp1: {} as HTMLImageElement, + bigCircleRightToUp1Red: {} as HTMLImageElement, bigCircleRightToUp2: {} as HTMLImageElement, + bigCircleRightToUp2Red: {} as HTMLImageElement, bigCircleRightToUp3: {} as HTMLImageElement, + bigCircleRightToUp3Red: {} as HTMLImageElement, bigCircleUp: {} as HTMLImageElement, + bigCircleUpRed: {} as HTMLImageElement, bigCircleUpToLeft1: {} as HTMLImageElement, + bigCircleUpToLeft1Red: {} as HTMLImageElement, bigCircleUpToLeft2: {} as HTMLImageElement, + bigCircleUpToLeft2Red: {} as HTMLImageElement, bigCircleUpToLeft3: {} as HTMLImageElement, + bigCircleUpToLeft3Red: {} as HTMLImageElement, bigCircleLeft: {} as HTMLImageElement, + bigCircleLeftRed: {} as HTMLImageElement, bigCircleLeftToDown1: {} as HTMLImageElement, + bigCircleLeftToDown1Red: {} as HTMLImageElement, bigCircleLeftToDown2: {} as HTMLImageElement, + bigCircleLeftToDown2Red: {} as HTMLImageElement, bigCircleLeftToDown3: {} as HTMLImageElement, + bigCircleLeftToDown3Red: {} as HTMLImageElement, bigStrangeUp0: {} as HTMLImageElement, + bigStrangeUp0Red: {} as HTMLImageElement, bigStrangeUp1: {} as HTMLImageElement, + bigStrangeUp1Red: {} as HTMLImageElement, simpleDown: {} as HTMLImageElement, simpleRot1: {} as HTMLImageElement, simpleRot2: {} as HTMLImageElement, @@ -103,11 +130,13 @@ export const IMGS = { enemyBullet: {} as HTMLImageElement, planeIcon: {} as HTMLImageElement, rollIcon: {} as HTMLImageElement, - // startScreen0: {} as HTMLImageElement, - // startScreen1: {} as HTMLImageElement, - // startScreen2: {} as HTMLImageElement, - // startScreen3: {} as HTMLImageElement, - // startScreen4: {} as HTMLImageElement, + powerup: {} as HTMLImageElement, + startScreen0: {} as HTMLImageElement, + startScreen1: {} as HTMLImageElement, + startScreen2: {} as HTMLImageElement, + startScreen3: {} as HTMLImageElement, + startScreen4: {} as HTMLImageElement, + restartScreen: {} as HTMLImageElement, font: { white: {} as any, yellow: {} as any, @@ -124,31 +153,34 @@ export const IMGS = { selector: {} as HTMLImageElement, empty: {} as HTMLImageElement, }; +export const URL = "/" // window.IMGS = IMGS; export default async function loadAllImages() { for (const key in IMGS) { if (["empty", "font", "start"].includes(key)) continue; - IMGS[key as keyof typeof IMGS] = await asyncImageLoader("/src/imgs/" + toKebabCase(key) + ".png") as any + IMGS[key as keyof typeof IMGS] = await asyncImageLoader(URL + "src/imgs/" + toKebabCase(key) + ".png") as any } - // for (const color of ['yellow', 'white', 'blue', 'red', 'green', 'purple']) { - for (const color of ['white']) { + for (const color of ['yellow', 'white', 'blue', 'red', 'green', 'purple']) { + // for (const color of ['white', 'yellow']) { for (const char of allChars) { - (((IMGS.font as any)[color] as any)[char]) = await asyncImageLoader("/src/imgs/font/" + color + "/" + encodeURIComponent(char) + ".png") as any + (((IMGS.font as any)[color] as any)[char]) = await asyncImageLoader(URL + "src/imgs/font/" + color + "/" + encodeURIComponent(char) + ".png") as any } } - IMGS.font[' '] = await asyncImageLoader("/src/imgs/font/ .png") - IMGS.font.white[' '] = await asyncImageLoader("/src/imgs/font/ .png") - IMGS.font.yellow[' '] = await asyncImageLoader("/src/imgs/font/ .png") - IMGS.font.blue[' '] = await asyncImageLoader("/src/imgs/font/ .png") - IMGS.font.red[' '] = await asyncImageLoader("/src/imgs/font/ .png") - IMGS.font.green[' '] = await asyncImageLoader("/src/imgs/font/ .png") - IMGS.font.purple[' '] = await asyncImageLoader("/src/imgs/font/ .png") + IMGS.font[' '] = await asyncImageLoader(URL + "src/imgs/font/ .png") + IMGS.font.white[' '] = await asyncImageLoader(URL + "src/imgs/font/ .png") + IMGS.font.white['%'] = await asyncImageLoader(URL + "src/imgs/font/%25.png") + IMGS.font.yellow[' '] = await asyncImageLoader(URL + "src/imgs/font/ .png") + IMGS.font.yellow['='] = await asyncImageLoader(URL + "src/imgs/font/=.png") + IMGS.font.blue[' '] = await asyncImageLoader(URL + "src/imgs/font/ .png") + IMGS.font.red[' '] = await asyncImageLoader(URL + "src/imgs/font/ .png") + IMGS.font.green[' '] = await asyncImageLoader(URL + "src/imgs/font/ .png") + IMGS.font.purple[' '] = await asyncImageLoader(URL + "src/imgs/font/ .png") // Only numbers for (const c of allChars.filter(ch => !alphabet.includes(ch))) { - IMGS.font.small.white[c] = await asyncImageLoader("/src/imgs/font/small/white/" + c + ".png"); + IMGS.font.small.white[c] = await asyncImageLoader(URL + "src/imgs/font/small/white/" + c + ".png"); } for (let i = 1; i <= 215; i++) - IMGS.start[i] = await asyncImageLoader("/src/imgs/start/" + i + ".png"); + IMGS.start[i] = await asyncImageLoader(URL + "src/imgs/start/" + i + ".png"); } async function asyncImageLoader(url: string): Promise<HTMLImageElement> { return new Promise((resolve, reject) => { @@ -158,6 +190,37 @@ async function asyncImageLoader(url: string): Promise<HTMLImageElement> { image.onerror = () => { console.log("img did not load", url); reject() } }) } +async function asyncSoundLoader(url: string): Promise<HTMLAudioElement> { + return new Promise((resolve, reject) => { + const image = new Audio(url) + image.src = url + image.oncanplaythrough = () => resolve(image) + image.onerror = () => { console.log("img did not load", url); reject() } + }) +} +export interface Sound extends HTMLAudioElement { + playFromBegin: () => void; +} +export const SOUNDS = { + enemyDie: {} as Sound, + fire: {} as Sound, + mainTheme: {} as Sound, + name: {} as Sound, + playerDeath: {} as Sound, + startLevel: {} as Sound, + win: {} as Sound, + powerup: {} as Sound, + letterCheck: {} as Sound, + rvCheck: {} as Sound, +} +export async function loadAllSounds() { + for (const key in SOUNDS) { + const toBeSound = await asyncSoundLoader(URL + "src/audios/" + toKebabCase(key) + ".mp3") as Sound + toBeSound.playFromBegin = function() { this.currentTime = 0; this.play() } + if (["mainTheme", "win", "name"].includes(key)) toBeSound.loop = true; + SOUNDS[key as keyof typeof SOUNDS] = toBeSound; + } +} export function getSmallDeathAnim(t: Enemy) { return new Anime(t, [ diff --git a/src/Player.ts b/src/Player.ts index 54dde50..bd74dc8 100644 --- a/src/Player.ts +++ b/src/Player.ts @@ -2,11 +2,14 @@ import Bullet from "./drawables/Bullet"; import { BULLET_VEL, canvas, ctx, FIRE_DELAY, PLAYER_VEL } from "./consts"; import Drawable, { Rectangle } from "./Drawable"; import { keys } from "./Events"; -import { getPlayerDeathAnim, IMGS } from "./Images"; +import { getPlayerDeathAnim, IMGS, SOUNDS } from "./Images"; +import { rolls } from "./game"; export default class Player extends Drawable { static startx = 144; static starty = 122; + // static startx = 250; + // static starty = 150; width = IMGS.playerUp.width; height = IMGS.playerUp.height; @@ -15,8 +18,13 @@ export default class Player extends Drawable { yvel = 0; lastShoot = 0; stopAtBorder = true; - // squares: Rectangle[] = [new Rectangle(this)] - squares: Rectangle[] = [] + autoPilot = false; + landed = false; + rolling = false + ri = 0; + rsi = 1; + squares: Rectangle[] = [new Rectangle(this)] + // squares: Rectangle[] = [] power = 2; alive = true; @@ -26,32 +34,80 @@ export default class Player extends Drawable { } shoot(bullet: Bullet[]) { - if (!keys.fire || keys.repeat) return; + if (!keys.fire || keys.repeat || this.autoPilot || !this.alive) return; if (Date.now() - this.lastShoot < FIRE_DELAY) return; this.lastShoot = Date.now() bullet.push(new Bullet(this.x + 2, this.y + 7, 0, -BULLET_VEL, true, this.power)) + SOUNDS.fire.playFromBegin() } move() { if (!this.alive) return false - if (+keys.right ^ +keys.left) { - keys.right ? this.xvel = PLAYER_VEL : this.xvel = -PLAYER_VEL; - } else { - this.xvel = 0 + if (this.autoPilot) { + // debugger + const tx = 144 + const ty = 87 + const vel = PLAYER_VEL / 2.5 + const xd = Math.abs(this.x - tx) + this.xvel = 0; this.yvel = 0; + if (xd < vel) this.x = tx + else if (this.x !== tx) this.xvel += (this.x > tx ? -1 : 1) * vel + const yd = Math.abs(this.y - ty) + if (yd < vel) this.y = ty + else if (this.y !== ty) this.yvel = -vel } + else { + if (keys.roll && rolls.r > 0 && this.rolling === false) { + this.rolling = true; + this.squares = [] + rolls.r--; + this.rsi = 1; + } - if (+keys.up ^ +keys.down) { - keys.down ? this.yvel = PLAYER_VEL : this.yvel = -PLAYER_VEL; - } else { - this.yvel = 0 - } + if (this.rolling && this.ri++ === 7) { this.rsi++; this.ri = 0; } + if (this.rsi >= 8) { this.rolling = false; this.squares = [new Rectangle(this)] } + if (keys.right || keys.left) { + if (keys.right && keys.left) { + keys.lastx === "right" ? this.xvel = PLAYER_VEL : this.xvel = -PLAYER_VEL; + } else if (keys.right) this.xvel = PLAYER_VEL + else if (keys.left) this.xvel = -PLAYER_VEL + } else { + this.xvel = 0 + } + // if (+keys.right ^ +keys.left) { + // keys.right ? this.xvel = PLAYER_VEL : this.xvel = -PLAYER_VEL; + // } else { + // this.xvel = 0 + // } - if (keys.left && keys.right) this.sprite = IMGS.playerUp - else if (keys.right) this.sprite = IMGS.playerRight - else if (keys.left) this.sprite = IMGS.playerLeft + if (keys.up || keys.down) { + if (keys.up && keys.down) { + keys.lasty === "down" ? this.yvel = PLAYER_VEL : this.yvel = -PLAYER_VEL; + } else if (keys.up) this.yvel = -PLAYER_VEL + else if (keys.down) this.yvel = PLAYER_VEL + } else { + this.yvel = 0 + } + // if (+keys.up ^ +keys.down) { + // keys.down ? this.yvel = PLAYER_VEL : this.yvel = -PLAYER_VEL; + // } else { + // this.yvel = 0 + // } + } + // if (keys.left && keys.right) this.sprite = IMGS.playerUp + // else if (keys.right) this.sprite = IMGS.playerRight + // else if (keys.left) this.sprite = IMGS.playerLeft + // else this.sprite = IMGS.playerUp + // if (this.x + this.xvel <= 35) this.sprite = IMGS.playerUp + // else if (this.x + this.xvel + this.width >= canvas.width - 35) this._x = canvas.width - 35 - this.width; + //@ts-expect-error + if (this.rolling) this.sprite = IMGS["playerRot" + this.rsi] + // else if (this.xvel && this.yvel) this.sprite = IMGS.playerUp + else if (this.xvel > 0) this.sprite = IMGS.playerRight + else if (this.xvel < 0) this.sprite = IMGS.playerLeft else this.sprite = IMGS.playerUp - if (this.x + this.xvel <= 35) this.sprite = IMGS.playerUp - else if (this.x + this.xvel + this.width >= canvas.width - 35) this._x = canvas.width - 35 - this.width; + if (this.x + this.xvel <= 25) this.sprite = IMGS.playerUp + else if (!this.autoPilot && this.x + this.xvel + this.width >= canvas.width - 25) this._x = canvas.width - 25 - this.width; this.width = this.sprite.width; this.height = this.sprite.height; @@ -63,6 +119,12 @@ export default class Player extends Drawable { } draw() { if (!this.alive) return + + if (this.landed) { + this._x = 147 + this._y = 87 + this.sprite = IMGS.playerSmall + } this.sprite = this.sprite ?? IMGS.playerUp; try { ctx.drawImage(this.sprite, this.x, this.y) diff --git a/src/Storage.ts b/src/Storage.ts index 2307846..8f40ed6 100644 --- a/src/Storage.ts +++ b/src/Storage.ts @@ -12,9 +12,10 @@ export function getStorage(): Storage { { name: "...".split(''), score: "35000", world: "02" }, { name: "...".split(''), score: "30000", world: "01" }, { name: "...".split(''), score: "25000", world: "01" }, - { name: "...".split(''), score: "20000", world: "01" }, - { name: "...".split(''), score: "15000", world: "01" }, + { name: "...".split(''), score: "00000", world: "01" }, + { name: "...".split(''), score: "00000", world: "01" }, ] as Storage; + if (s[1] == null) return storage return s; } @@ -29,7 +30,7 @@ export function getHighscore() { export function getPlace(s: number): string { const storage = getStorage(); - let place = 7 + let place = 6 for (let i = 1; i <= storage.length; i++) { let sc = parseInt(storage[i - 1]['score']); if (s > sc) { diff --git a/src/audios/1942-enemy-die.mp3 b/src/audios/1942-enemy-die.mp3 Binary files differdeleted file mode 100644 index cfd1afd..0000000 --- a/src/audios/1942-enemy-die.mp3 +++ /dev/null diff --git a/src/audios/1942-fire.mp3 b/src/audios/1942-fire.mp3 Binary files differdeleted file mode 100644 index a010815..0000000 --- a/src/audios/1942-fire.mp3 +++ /dev/null diff --git a/src/audios/1942-player-death.mp3 b/src/audios/1942-player-death.mp3 Binary files differdeleted file mode 100644 index 30052df..0000000 --- a/src/audios/1942-player-death.mp3 +++ /dev/null diff --git a/src/audios/1942-start-level.mp3 b/src/audios/1942-start-level.mp3 Binary files differdeleted file mode 100644 index 15b85ac..0000000 --- a/src/audios/1942-start-level.mp3 +++ /dev/null diff --git a/src/audios/enemy-die.mp3 b/src/audios/enemy-die.mp3 Binary files differnew file mode 100644 index 0000000..a11b927 --- /dev/null +++ b/src/audios/enemy-die.mp3 diff --git a/src/audios/fire.mp3 b/src/audios/fire.mp3 Binary files differnew file mode 100644 index 0000000..4adc80f --- /dev/null +++ b/src/audios/fire.mp3 diff --git a/src/audios/letter-check.mp3 b/src/audios/letter-check.mp3 Binary files differnew file mode 100644 index 0000000..2f7be69 --- /dev/null +++ b/src/audios/letter-check.mp3 diff --git a/src/audios/1942-main-theme.mp3 b/src/audios/main-theme.mp3 Binary files differindex fcef295..fcef295 100644 --- a/src/audios/1942-main-theme.mp3 +++ b/src/audios/main-theme.mp3 diff --git a/src/audios/1942-name.mp3 b/src/audios/name.mp3 Binary files differindex 197f2f6..197f2f6 100644 --- a/src/audios/1942-name.mp3 +++ b/src/audios/name.mp3 diff --git a/src/audios/player-death.mp3 b/src/audios/player-death.mp3 Binary files differnew file mode 100644 index 0000000..6e86a9e --- /dev/null +++ b/src/audios/player-death.mp3 diff --git a/src/audios/powerup.mp3 b/src/audios/powerup.mp3 Binary files differnew file mode 100644 index 0000000..a5f59d9 --- /dev/null +++ b/src/audios/powerup.mp3 diff --git a/src/audios/rv-check.mp3 b/src/audios/rv-check.mp3 Binary files differnew file mode 100644 index 0000000..ac7e7b8 --- /dev/null +++ b/src/audios/rv-check.mp3 diff --git a/src/audios/start-level.mp3 b/src/audios/start-level.mp3 Binary files differnew file mode 100644 index 0000000..b1ff214 --- /dev/null +++ b/src/audios/start-level.mp3 diff --git a/src/audios/1942-win.mp3 b/src/audios/win.mp3 Binary files differindex b381ad9..b381ad9 100644 --- a/src/audios/1942-win.mp3 +++ b/src/audios/win.mp3 diff --git a/src/consts.ts b/src/consts.ts index 5443a1a..9b67159 100644 --- a/src/consts.ts +++ b/src/consts.ts @@ -3,12 +3,12 @@ export const ctx = canvas.getContext("2d")! ctx.imageSmoothingEnabled = false; export const PLAYER_SIZE = 20; // canvas-dot -export const PLAYER_VEL = 3.5; // canvas-dot / frame -export const BULLET_VEL = 4; // canvas-dot / frame +export const PLAYER_VEL = 3; // canvas-dot / frame +export const BULLET_VEL = 7.5; // canvas-dot / frame export const FIRE_DELAY = 300; // ms export const TOPBAR_HEIGHT = 24; // ms -export const FPS = 1; +// export const FPS = 1; export const alphabet = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '.', '-', '&', '?', '!', 'man', 'woman', 'heart', 'rv', 'ed'] export const allChars = [...alphabet, '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'] diff --git a/src/drawables/AnimStart.ts b/src/drawables/AnimStart.ts index b855b25..fff48e8 100644 --- a/src/drawables/AnimStart.ts +++ b/src/drawables/AnimStart.ts @@ -3,7 +3,7 @@ import Drawable from "../Drawable"; import { IMGS } from "../Images"; export default class AnimStart extends Drawable { - i = 0; + i = 1; draw(): boolean { try { ctx.drawImage(IMGS.start[this.i], 0, TOPBAR_HEIGHT); diff --git a/src/drawables/Background.ts b/src/drawables/Background.ts index 622a608..f6c4cec 100644 --- a/src/drawables/Background.ts +++ b/src/drawables/Background.ts @@ -10,10 +10,11 @@ export class Background extends Drawable { super(0, 0) } // delta = -1751 + 24 + 2693; - delta = 2500 + delta = 0 move() { if (this.delta + 1 > 2580) return true this.delta += 1; + return true; } draw() { diff --git a/src/drawables/Bullet.ts b/src/drawables/Bullet.ts index f121cfa..6420db2 100644 --- a/src/drawables/Bullet.ts +++ b/src/drawables/Bullet.ts @@ -18,7 +18,6 @@ export default class Bullet extends Drawable { this.width = (this.sprite as HTMLImageElement).width this.height = (this.sprite as HTMLImageElement).height this.squares = [new Rectangle(this)] - console.log(this.width, this.height); } move(): boolean { diff --git a/src/drawables/Powerup.ts b/src/drawables/Powerup.ts new file mode 100644 index 0000000..af4df05 --- /dev/null +++ b/src/drawables/Powerup.ts @@ -0,0 +1,14 @@ +import Drawable, { Rectangle } from "../Drawable"; +import { IMGS } from "../Images"; + +export default class Powerup extends Drawable { + sprite = IMGS.powerup + width = IMGS.powerup.width + height = IMGS.powerup.height + squares: Rectangle[] = [new Rectangle(this)] + + move() { + this.y += 1 + return this.isOutsideMap() + } +} diff --git a/src/drawables/Startscreen.ts b/src/drawables/Startscreen.ts index 91f7405..0756fd3 100644 --- a/src/drawables/Startscreen.ts +++ b/src/drawables/Startscreen.ts @@ -31,10 +31,11 @@ export default class Startscreen extends Drawable { if (i === 0) place = "top"; else if (i === 1) place = "2nd"; else if (i === 2) place = "3rd"; - else place = i + "th"; + else place = (i + 1) + "th"; chars.push([...place.split(''), ' ', ...score.score.padStart(7, '0').split(''), ' ', ...score.name, ' ', ...score.world.split('')]) } + if (this.si !== 0 && this.show0 !== true) { let x = 17, y = 40; for (const char of chars) { @@ -67,7 +68,6 @@ export default class Startscreen extends Drawable { } else { //@ts-expect-error this.sprite = IMGS["startScreen" + this.si]; - console.log("startScreen" + this.si); // if (this.i++ === 2) { if (this.i++ === 9) { diff --git a/src/drawables/TopBar.ts b/src/drawables/TopBar.ts index d92db07..4bd525a 100644 --- a/src/drawables/TopBar.ts +++ b/src/drawables/TopBar.ts @@ -10,13 +10,17 @@ export class TopBar extends Drawable { lives = 0; rolls = 0; highscore = 0; + shootedDown = 0; + bgd = 0; constructor() { super(0, 0) } - setData(score: number, lives: number, rolls: number, highscore?: number | string) { + setData(score: number, lives: number, rolls: number, bgd: number, shootedDown: number, highscore?: number | string) { this.score = score this.lives = lives this.rolls = rolls + this.bgd = bgd + this.shootedDown = shootedDown if (highscore) { if (typeof highscore === "string") highscore = parseInt(highscore) this.highscore = highscore @@ -26,7 +30,6 @@ export class TopBar extends Drawable { if (this.sprite.src == null) this.sprite = IMGS.topbar; ctx.drawImage(this.sprite, 0, 0); [...this.score.toString().padStart(7, '0')].forEach((char, i) => { - ctx.imageSmoothingEnabled = false ctx.drawImage(IMGS.font.small.white[char], 24 + i * 8, 8) }); for (let i = 0; i < this.lives; i++) { @@ -36,9 +39,23 @@ export class TopBar extends Drawable { ctx.drawImage(IMGS.rollIcon, 177 + i * 8, 9) } [...this.highscore.toString().padStart(7, '0')].forEach((char, i) => { - ctx.imageSmoothingEnabled = false ctx.drawImage(IMGS.font.small.white[char], 240 + i * 8, 8) }); + if (this.bgd >= 2580) { + // 9 41 + [..."shooting down ".split(''), ...(this.shootedDown / 32).toFixed(0).toString().padStart(3, '0').split(''), '%'].forEach((char, i) => { + ctx.drawImage(IMGS.font.white[char], 9 + i * 17, 41, 15, 8) + }); + [..."bonus".split('')].forEach((char, i) => { + ctx.drawImage(IMGS.font.white[char], 110 + i * 17, 94, 15, 8) + }); + [...(this.lives * 500).toString().padStart(5, '0'), ..." pts".split('')].forEach((char, i) => { + ctx.drawImage(IMGS.font.white[char], 77 + i * 17, 108, 15, 8) + }); + [...'rx1000=', ...(this.rolls * 1000).toString().padStart(4, '0'), ..." pts"].forEach((char, i) => { + ctx.drawImage(IMGS.font.yellow[char], 43 + i * 17, 147, 15, 8) + }); + } } } diff --git a/src/enemies/BigCircle.ts b/src/enemies/BigCircle.ts index 1f9f7dd..b7666f5 100644 --- a/src/enemies/BigCircle.ts +++ b/src/enemies/BigCircle.ts @@ -11,8 +11,11 @@ export default class BigCircle extends Enemy { height = 40 sprite: HTMLImageElement | string = IMGS.bigCircleDown; strSprite = "bigCircleDown" + si = 0; + changeSprite = true; vel = 2 - health = 20 + health = 30 + points = 1100 phase = 0; @@ -229,6 +232,23 @@ export default class BigCircle extends Enemy { break; } + if (this.health < 30 - 20) { + if (this.si++ > 3) { this.changeSprite = !this.changeSprite; this.si = 0; } + } + else if (this.health < 30 - 10) { + if (this.si++ > 8) { this.changeSprite = !this.changeSprite; this.si = 0; } + } + else if (this.health < 30) { + if (this.si++ > 30) { this.changeSprite = !this.changeSprite; this.si = 0; } + } + if (this.changeSprite === true && this.health < 30) + //@ts-expect-error + this.sprite = IMGS[this.strSprite + "Red"] + else + //@ts-expect-error + this.sprite = IMGS[this.strSprite] + + this.x += xShift; this.y += yShift; return this.x2 < 0 || this.y2 < 0 || this.x > canvas.width || this.y > canvas.height diff --git a/src/enemies/Enemy.ts b/src/enemies/Enemy.ts index 224e66c..cebc1d2 100644 --- a/src/enemies/Enemy.ts +++ b/src/enemies/Enemy.ts @@ -5,13 +5,16 @@ import Anime from "../Animation"; export default abstract class Enemy extends Drawable { squares: Array<Rectangle> = [new Rectangle(this)] - points = 5; + points = 50; health = 2 deathAnim!: Anime; + constructor(x: number, y: number) { + super(x, y) + } shoot(bullet: Bullet[]): boolean { if (this.y2 < TOPBAR_HEIGHT) return false - bullet.push(new Bullet(this.x + (this.width / 2) - Bullet.width / 2, this.y2, 0, BULLET_VEL, false)) + bullet.push(new Bullet(this.x + (this.width / 2) - Bullet.width / 2, this.y2, 0, BULLET_VEL / 1.5, false)) return true } } diff --git a/src/enemies/Green1.ts b/src/enemies/Green1.ts index 2510f97..42ff712 100644 --- a/src/enemies/Green1.ts +++ b/src/enemies/Green1.ts @@ -8,7 +8,7 @@ export default class Green1 extends Enemy { sprite = IMGS.greenUp; width = IMGS.greenUp.width; height = IMGS.greenUp.height; - vel = 2 + vel = 2.5 phase = 0; spriteNum = 1; i = 0; diff --git a/src/enemies/Green2.ts b/src/enemies/Green2.ts index a6adb74..1987499 100644 --- a/src/enemies/Green2.ts +++ b/src/enemies/Green2.ts @@ -16,6 +16,8 @@ export default class Green2 extends Enemy { constructor(x: number, y: number, public left: boolean) { super(x, y) + this.height = IMGS.greenDown.height; + this._y = y - this.height } move() { diff --git a/src/enemies/Red1.ts b/src/enemies/Red1.ts index 9c50820..18fdb6f 100644 --- a/src/enemies/Red1.ts +++ b/src/enemies/Red1.ts @@ -6,7 +6,7 @@ export default class Red1 extends Enemy { sprite = IMGS.redRight; width = IMGS.redRight.width; height = IMGS.redRight.height; - vel = 3 + vel = 3.5 phase = 0; spriteNum = 1; i = 0; @@ -190,6 +190,6 @@ export default class Red1 extends Enemy { this.squares = [new Rectangle(this, 2, 2, this.width - 4, this.height - 4)] return this.isOutsideMap() } - shoot(): boolean { return false } + shoot() { return false } deathAnim = getSmallDeathAnim(this) } diff --git a/src/enemies/Red2.ts b/src/enemies/Red2.ts index ced55cd..de79845 100644 --- a/src/enemies/Red2.ts +++ b/src/enemies/Red2.ts @@ -6,13 +6,15 @@ export default class Red2 extends Enemy { sprite = IMGS.redDown; width = IMGS.redDown.width; height = IMGS.redDown.height; - vel = 2; + vel = 2.5; phase = 0; i = 0; squares: Rectangle[] = [new Rectangle(this, 2, 2, this.width - 2, this.height - 2)] constructor(x: number, y: number, public left: boolean) { super(x, y) + this.height = IMGS.redDown.height; + this._y = y - this.height } move() { diff --git a/src/enemies/Straight.ts b/src/enemies/Straight.ts index 7bc82f9..f57d6f3 100644 --- a/src/enemies/Straight.ts +++ b/src/enemies/Straight.ts @@ -9,11 +9,19 @@ export default class Straight extends Enemy { sprite = IMGS.simpleDown; width = IMGS.simpleDown.width; height = IMGS.simpleDown.height; - vel = 2 + vel = 2.5 phase = 0; spriteNum = 1; i = 0; - squares: Rectangle[] = [new Rectangle(this, 2, 2, this.width - 2, this.height - 2)] + squares: Rectangle[] = [new Rectangle(this, 2, 2, this.width - 4, this.height - 4)] + drop = false + + constructor(x: number, y: number, drop?: boolean) { + super(x, y) + if (drop) this.drop = drop + this.height = IMGS.simpleDown.height; + this._y = y - this.height + } move() { let dy = 0; @@ -35,7 +43,7 @@ export default class Straight extends Enemy { this.y += dy; this.width = this.sprite.width this.height = this.sprite.height - this.squares = [new Rectangle(this, 2, 2, this.width - 2, this.height - 2)] + this.squares = [new Rectangle(this, 2, 2, this.width - 4, this.height - 4)] return this.y + this.height < 0 } diff --git a/src/enemies/Strange.ts b/src/enemies/Strange.ts index 036409a..d130326 100644 --- a/src/enemies/Strange.ts +++ b/src/enemies/Strange.ts @@ -12,9 +12,13 @@ export default class Strange extends Enemy { vel = 1 phase = 0; spriteCounter = 0; + si = 0; + changeSprite = true; spriteNum = 1; i = 0; squares: Rectangle[] = [new Rectangle(this, 2, 2, this.width - 2, this.height - 2)] + health = 30 + points = 2100 move() { let dx = 0, dy = 0; @@ -82,10 +86,26 @@ export default class Strange extends Enemy { break; } + if (this.spriteCounter++ === 3) { this.spriteNum ^= 1; this.spriteCounter = 0; } + let strSprite = "bigStrangeUp" + this.spriteNum; + if (this.health < 30 - 20) { + if (this.si++ > 3) { this.changeSprite = !this.changeSprite; this.si = 0; } + } + else if (this.health < 30 - 10) { + if (this.si++ > 8) { this.changeSprite = !this.changeSprite; this.si = 0; } + } + else if (this.health < 30) { + if (this.si++ > 30) { this.changeSprite = !this.changeSprite; this.si = 0; } + } + if (this.changeSprite === true && this.health < 30) + //@ts-expect-error + this.sprite = IMGS[strSprite + "Red"] + else + //@ts-expect-error + this.sprite = IMGS[strSprite] + this.x += dx; this.y += dy; - //@ts-expect-error - if (this.spriteCounter++ === 3) { this.spriteNum ^= 1; this.sprite = IMGS["bigStrangeUp" + this.spriteNum]; this.spriteCounter = 0; } // this.width = this.sprite.width // this.height = this.sprite.height // this.squares = [new Rectangle(this, 2, 2, this.width - 2, this.height - 2)] @@ -96,10 +116,10 @@ export default class Strange extends Enemy { if (this.y2 < TOPBAR_HEIGHT) return false if (random(0.01)) { if (random(0.5)) { - bullets.push(new Bullet(this.x + (this.width / 2) - Bullet.width / 2, this.y2, 0, BULLET_VEL, false)) + bullets.push(new Bullet(this.x + (this.width / 2) - Bullet.width / 2, this.y2, 0, BULLET_VEL / 2, false)) } else { - if (random(0.5)) bullets.push(new Bullet(this.x + (this.width / 2) - Bullet.width / 2, this.y2, BULLET_VEL - 1, BULLET_VEL - 1, false)) - else bullets.push(new Bullet(this.x + (this.width / 2) - Bullet.width / 2, this.y2, -BULLET_VEL + 1, BULLET_VEL - 1, false)) + if (random(0.5)) bullets.push(new Bullet(this.x + (this.width / 2) - Bullet.width / 2, this.y2, BULLET_VEL / 2, BULLET_VEL / 2, false)) + else bullets.push(new Bullet(this.x + (this.width / 2) - Bullet.width / 2, this.y2, -BULLET_VEL / 2, BULLET_VEL / 2, false)) } } diff --git a/src/enemies/White.ts b/src/enemies/White.ts index e5b22ae..768300d 100644 --- a/src/enemies/White.ts +++ b/src/enemies/White.ts @@ -1,4 +1,6 @@ import { Rectangle } from "../Drawable"; +import Bullet from "../drawables/Bullet"; +import { random } from "../helpers"; import { getSmallDeathAnim, IMGS } from "../Images"; import Enemy from "./Enemy"; @@ -15,6 +17,8 @@ export default class White extends Enemy { constructor(x: number, y: number, public left: boolean) { super(x, y) + this.height = IMGS.whiteDown.height; + this._y = y - this.height } move() { @@ -65,7 +69,15 @@ export default class White extends Enemy { return this.isOutsideMap() } - shoot(): boolean { return false } + hasShooted = false; + shoot(bullets: Bullet[]): boolean { + if (this.sprite !== IMGS.whiteDown || this.hasShooted) return false; + if (random(0.008)) { + if (super.shoot(bullets)) + this.hasShooted = true + } + return true; + } deathAnim = getSmallDeathAnim(this) } diff --git a/src/game.ts b/src/game.ts index 4e1db38..07988fa 100644 --- a/src/game.ts +++ b/src/game.ts @@ -7,7 +7,7 @@ import Straight from "./enemies/Straight"; import Red1 from "./enemies/Red1"; import Red2 from "./enemies/Red2"; import Enemy from "./enemies/Enemy"; -import { clearCtx, sleep } from "./helpers"; +import { clearCtx, randomInteger, sleep } from "./helpers"; import Player from "./Player"; import { TopBar } from "./drawables/TopBar"; import { keys } from "./Events"; @@ -19,25 +19,33 @@ import White from "./enemies/White"; import Startscreen from "./drawables/Startscreen"; import { getHighscore } from "./Storage"; import AnimStart from "./drawables/AnimStart"; +import { IMGS, SOUNDS } from "./Images"; +import Powerup from "./drawables/Powerup"; let p = new Player() let pLifes = 3; -let score = 25004; +// pLifes = 1; +let score = 0; let highscore = getHighscore(); -let rolls = 3; +export const rolls = { r: 3 } +// let rolls = 3; let bullets = [] as Bullet[] const playerBullets = () => bullets.filter(b => b.players) const enemyBullets = () => bullets.filter(b => !b.players) let enemies = [] as Enemy[] +let enemShooted = 0; let animations = [] as Anime[] let intervalId = 0; let rafId = 0; -let showMenu = false +let showMenu = true let showAnimStart = true -const bg = new Background() -const tb = new TopBar() -const hg = new Highscore() -const animStart = new AnimStart(0, TOPBAR_HEIGHT) +// showMenu = false +// showAnimStart = false +let bg = new Background() +let tb = new TopBar() +let hg = new Highscore() +let animStart = new AnimStart(0, TOPBAR_HEIGHT) +let pu: Powerup | null = null // const ss = new Startscreen(); export async function start() { @@ -45,43 +53,53 @@ export async function start() { bullets = [] as Bullet[] enemies = [] as Enemy[] animations = [] as Anime[] - // enemies.push(new BigCircle(25, -20)) - // enemies.push(new Straight(20, 0)) - // enemies.push(new Red1(0, 51)) - // enemies.push(new Green1(115, canvas.height, true), new Green1(170, canvas.height, false)) - // enemies.push(new Strange(160, canvas.height)) - // enemies.push(new White(60, 0, true), new White(230, 0, false)) - // enemies.push(new Red2(100, 0, true), new Red2(180, 0, false)) - // enemies.push(new Green2(100, 0, true), new Green2(180, 0, false)) newTimeout() rafId = requestAnimationFrame(gpuLoop) } export function cpuLoop() { if (showMenu) { + SOUNDS.mainTheme.play() cpuMenu() newTimeout() return } + if (showAnimStart) { + return + } if (hg.show) { - hg.move(); - tb.setData(score, pLifes, rolls, highscore) - newTimeout() + SOUNDS.mainTheme.pause() + SOUNDS.name.play() + tb.setData(score, pLifes, rolls.r, bg.delta, enemShooted, highscore) + if (hg.move()) newTimeout() return; } + // hg.show = true + if (bg.delta > 2375) { p.autoPilot = true; p.stopAtBorder = false; } + if (bg.delta === 2580) { + SOUNDS.mainTheme.pause() + SOUNDS.win.play() + p.landed = true + } p.move() p.shoot(bullets) bg.move() spawnEnemies() - tb.setData(score, pLifes, rolls, highscore) + tb.setData(score, pLifes, rolls.r, bg.delta, enemShooted, highscore) // enemies = enemies.filter(e => !bullets.some(b => b.collides(e))) enemies.forEach(e => e.shoot(bullets)) enemies = enemies.filter(e => !e.move()) bullets = bullets.filter(b => !b.move()) + if (pu && pu.move()) pu = null const enemCollPlay = enemies.filter(e => p.collides([e])); const bullCollPlay = enemyBullets().filter(b => p.collides([b])); + if (pu && p.collides([pu])) { + pu = null + p.power = 3 + SOUNDS.powerup.play() + } bullets = bullets.filter(b => !bullCollPlay.includes(b)) // const enemiesToDie = enemies.filter(e => e.collides(bullets)) @@ -94,8 +112,12 @@ export function cpuLoop() { if (e.health < 1) { animations.push(e.deathAnim) score += e.points + enemShooted++; + SOUNDS.enemyDie.play() + if (e instanceof Straight && e.drop) pu = new Powerup(e.x, e.y) return false - } + } else if (e instanceof BigCircle) score += 100; + else if (e instanceof Strange) score += 100; } return true; }) @@ -110,15 +132,20 @@ export function cpuLoop() { export function gpuLoop() { rafId = requestAnimationFrame(gpuLoop) - clearCtx() + clearCtx(); + if (showMenu) { + gpuMenu(); + return; + } if (showAnimStart) { + SOUNDS.mainTheme.pause() + SOUNDS.startLevel.play() + SOUNDS.startLevel.onended = () => { SOUNDS.mainTheme.currentTime = 4.0; SOUNDS.mainTheme.play() } + tb.draw() showAnimStart = animStart.draw() - return - } - if (showMenu) { - gpuMenu() - return + if (showAnimStart) newTimeout() + return; } if (hg.show) { hg.drawHg(bg, score) @@ -127,48 +154,52 @@ export function gpuLoop() { } bg.draw() + if (pu) pu.draw() bullets.forEach(b => b.draw()) - bullets.forEach(b => b.squares.forEach(s => s.draw())) - p.squares.forEach(s => s.draw()) p.draw() - enemies.forEach(e => { - e.draw() - e.squares.forEach(s => s.draw()) - if (e instanceof BigCircle) { - e.squares.forEach(s => s.draw()) - } - }) + enemies.forEach(e => e.draw()) animations = animations.filter(a => a.draw()) tb.draw() } -export async function playerDied(_enemy: Enemy[]) { - animations.push(p.deathAnimation) +export function playerDied(_enemy: Enemy[]) { p.alive = false p.squares = [] - // clearTimeout(intervalId) - // cancelAnimationFrame(rafId) - // pLifes -= 1; - // if (pLifes !== 0) { - // await drawRestartScreen(); - // start() - // } else { - // hg.show = true - // newTimeout() - // requestAnimationFrame(gpuLoop) - // } + SOUNDS.playerDeath.play() + const da = p.deathAnimation; + da.cb = () => afterPlayerDeathAnim() + animations.push(p.deathAnimation) +} +export async function afterPlayerDeathAnim() { + clearTimeout(intervalId) + cancelAnimationFrame(rafId) + pLifes -= 1; + rolls.r = 3 + if (pLifes !== 0) { + await drawRestartScreen(); + start() + } else { + hg.show = true + newTimeout() + requestAnimationFrame(gpuLoop) + } } export async function drawRestartScreen() { clearCtx() - ctx.fillStyle = "yellow" - ctx.fillRect(0, 0, canvas.width, canvas.height) + tb.setData(score, pLifes, rolls.r, bg.delta, enemShooted, highscore) + tb.draw() + ctx.drawImage(IMGS.restartScreen, 0, TOPBAR_HEIGHT) + ctx.drawImage(IMGS.font.white[pLifes], 245, 29 + TOPBAR_HEIGHT, 15, 8) + Player.startx = 143 + Player.starty = 98 + TOPBAR_HEIGHT await sleep(2000) + bg.delta = 150 } -const startscreen = new Startscreen() -tb.setData(score, pLifes, rolls, highscore) +let startscreen = new Startscreen() +tb.setData(score, pLifes, rolls.r, 0, 0, highscore) function cpuMenu() { startscreen.move() if (keys.fire === true) showMenu = false; @@ -177,35 +208,62 @@ function gpuMenu() { tb.draw() startscreen.draw() } +export function startAgain() { + clearTimeout(intervalId) + cancelAnimationFrame(rafId) + Player.startx = 144; + Player.starty = 122; + bg.delta = 0 + pLifes = 3; + score = 0 + highscore = getHighscore(); + rolls.r = 3 + showMenu = true + showAnimStart = true + bg = new Background() + tb = new TopBar() + hg = new Highscore() + animStart = new AnimStart(0, TOPBAR_HEIGHT) + startscreen = new Startscreen() + whichStraight = randomInteger(0, 2) + tb.setData(score, pLifes, rolls.r, 0, 0, highscore) + SOUNDS.mainTheme.currentTime = 0 + SOUNDS.win.currentTime = 0 + SOUNDS.startLevel.currentTime = 0 + keys.fire = false + start() +} const newTimeout = (f = cpuLoop) => { clearTimeout(intervalId); intervalId = setTimeout(f, 1000 / keys.fps) } +let whichStraight = randomInteger(0, 2) function spawnEnemies() { - if (bg.delta === 180) enemies.push(new Straight(80, 0)); - if (bg.delta === 180 + 20) enemies.push(new Straight(110, 0)); - if (bg.delta === 180 + 20 + 30) enemies.push(new Straight(160, 0)); - if (bg.delta === 180 + 20 + 30 + 25) enemies.push(new Straight(210, 0)); - if (bg.delta === 180 + 20 + 30 + 25 + 80) enemies.push(new Straight(130, 0)); - if (bg.delta === 180 + 20 + 30 + 25 + 80 + 50) enemies.push(new Straight(90, 0)); - if (bg.delta === 180 + 20 + 30 + 25 + 80 + 50 + 32) enemies.push(new Straight(220, 0)); - if (bg.delta === 630) enemies.push(new BigCircle(16, TOPBAR_HEIGHT - 40)) - if (bg.delta === 630 + 38) enemies.push(new Straight(90, 0), new Straight(266, 0)) - if (bg.delta === 630 + 38 + 38) enemies.push(new Straight(140, 0)) - if (bg.delta === 630 + 38 + 38 + 70) enemies.push(new Straight(30, 0)) - if (bg.delta === 630 + 38 + 38 + 70 + 30) enemies.push(new Straight(266, 0)) - if (bg.delta === 1016 + 21 * 0) enemies.push(new Red1(-20, 52)) - if (bg.delta === 1016 + 21 * 1) enemies.push(new Red1(-20, 52)) - if (bg.delta === 1016 + 21 * 2) enemies.push(new Red1(-20, 52)) - if (bg.delta === 1016 + 21 * 3) enemies.push(new Red1(-20, 52)) - if (bg.delta === 1016 + 21 * 4) enemies.push(new Red1(-20, 52)) - if (bg.delta === 1120) enemies.push(new Green1(110, canvas.height, true), new Green1(170, canvas.height, false)) - if (bg.delta === 1498) enemies.push(new Strange(160, canvas.height)) - if (bg.delta === 1498 + 45) enemies.push(new Red2(100, 0, true), new Red2(180, 0, false)) - if (bg.delta === 1498 + 45 + 90) enemies.push(new Green2(100, 0, true), new Green2(180, 0, false)) - if (bg.delta === 2000 + 85 * 0) enemies.push(new White(60, 0, true), new White(230, 0, false)) - if (bg.delta === 2000 + 85 * 1) enemies.push(new White(60, 0, true), new White(230, 0, false)) - if (bg.delta === 2000 + 85 * 2) enemies.push(new White(60, 0, true), new White(230, 0, false)) - if (bg.delta === 2000 + 85 * 3) enemies.push(new White(60, 0, true)) + + ;;;; if (bg.delta === 190) enemies.push(new Straight(80, TOPBAR_HEIGHT)); + else if (bg.delta === 190 + 20) enemies.push(new Straight(110, TOPBAR_HEIGHT)); + else if (bg.delta === 190 + 20 + 30) enemies.push(new Straight(160, TOPBAR_HEIGHT)); + else if (bg.delta === 190 + 20 + 30 + 25) enemies.push(new Straight(210, TOPBAR_HEIGHT)); + else if (bg.delta === 190 + 20 + 30 + 25 + 80) enemies.push(new Straight(130, TOPBAR_HEIGHT, whichStraight === 0)); + else if (bg.delta === 190 + 20 + 30 + 25 + 80 + 50) enemies.push(new Straight(90, TOPBAR_HEIGHT, whichStraight === 1)); + else if (bg.delta === 190 + 20 + 30 + 25 + 80 + 50 + 32) enemies.push(new Straight(220, TOPBAR_HEIGHT, whichStraight === 2)); + else if (bg.delta === 640) enemies.push(new BigCircle(16, TOPBAR_HEIGHT - 40)) + else if (bg.delta === 640 + 38) enemies.push(new Straight(90, TOPBAR_HEIGHT), new Straight(266, TOPBAR_HEIGHT)) + else if (bg.delta === 640 + 38 + 38) enemies.push(new Straight(140, TOPBAR_HEIGHT)) + else if (bg.delta === 640 + 38 + 38 + 70) enemies.push(new Straight(30, TOPBAR_HEIGHT)) + else if (bg.delta === 640 + 38 + 38 + 70 + 30) enemies.push(new Straight(266, TOPBAR_HEIGHT)) + else if (bg.delta === 1026 + 21 * 0) enemies.push(new Red1(-24, 52)) + else if (bg.delta === 1026 + 21 * 1) enemies.push(new Red1(-24, 52)) + else if (bg.delta === 1026 + 21 * 2) enemies.push(new Red1(-24, 52)) + else if (bg.delta === 1026 + 21 * 3) enemies.push(new Red1(-24, 52)) + else if (bg.delta === 1026 + 21 * 4) enemies.push(new Red1(-24, 52)) + else if (bg.delta === 1120) enemies.push(new Green1(110, canvas.height, true), new Green1(170, canvas.height, false)) + else if (bg.delta === 1498) enemies.push(new Strange(160, canvas.height)) + else if (bg.delta === 1508 + 45) enemies.push(new Red2(100, TOPBAR_HEIGHT, true), new Red2(180, TOPBAR_HEIGHT, false)) + else if (bg.delta === 1508 + 45 + 90) enemies.push(new Green2(100, TOPBAR_HEIGHT, true), new Green2(180, TOPBAR_HEIGHT, false)) + else if (bg.delta === 2010 + 85 * 0) enemies.push(new White(60, TOPBAR_HEIGHT, true), new White(230, TOPBAR_HEIGHT, false)) + else if (bg.delta === 2010 + 85 * 1) enemies.push(new White(60, TOPBAR_HEIGHT, true), new White(230, TOPBAR_HEIGHT, false)) + else if (bg.delta === 2010 + 85 * 2) enemies.push(new White(60, TOPBAR_HEIGHT, true), new White(230, TOPBAR_HEIGHT, false)) + else if (bg.delta === 2010 + 85 * 3) enemies.push(new White(60, TOPBAR_HEIGHT, true)) // if (bg.delta > 2200) // console.log(bg.delta); diff --git a/src/helpers.ts b/src/helpers.ts index 9bb1eac..a867b1e 100644 --- a/src/helpers.ts +++ b/src/helpers.ts @@ -11,3 +11,8 @@ export function random(p: number): boolean { if (p < 0 || p > 1) throw Error("Wrong probability - " + p) return Math.random() < p; } +export function randomInteger(min: number, max: number) { + min = Math.ceil(min); + max = Math.floor(max); + return Math.floor(Math.random() * (max - min + 1)) + min; +} diff --git a/src/imgs/big-circle-down-red.png b/src/imgs/big-circle-down-red.png Binary files differnew file mode 100644 index 0000000..8fab31f --- /dev/null +++ b/src/imgs/big-circle-down-red.png diff --git a/src/imgs/big-circle-down-to-right1-red.png b/src/imgs/big-circle-down-to-right1-red.png Binary files differnew file mode 100644 index 0000000..5a62794 --- /dev/null +++ b/src/imgs/big-circle-down-to-right1-red.png diff --git a/src/imgs/big-circle-down-to-right2-red.png b/src/imgs/big-circle-down-to-right2-red.png Binary files differnew file mode 100644 index 0000000..7e54b25 --- /dev/null +++ b/src/imgs/big-circle-down-to-right2-red.png diff --git a/src/imgs/big-circle-down-to-right3-red.png b/src/imgs/big-circle-down-to-right3-red.png Binary files differnew file mode 100644 index 0000000..8a47f0f --- /dev/null +++ b/src/imgs/big-circle-down-to-right3-red.png diff --git a/src/imgs/big-circle-left-red.png b/src/imgs/big-circle-left-red.png Binary files differnew file mode 100644 index 0000000..acc5743 --- /dev/null +++ b/src/imgs/big-circle-left-red.png diff --git a/src/imgs/big-circle-left-to-down1-red.png b/src/imgs/big-circle-left-to-down1-red.png Binary files differnew file mode 100644 index 0000000..1d1e96e --- /dev/null +++ b/src/imgs/big-circle-left-to-down1-red.png diff --git a/src/imgs/big-circle-left-to-down2-red.png b/src/imgs/big-circle-left-to-down2-red.png Binary files differnew file mode 100644 index 0000000..47f56e5 --- /dev/null +++ b/src/imgs/big-circle-left-to-down2-red.png diff --git a/src/imgs/big-circle-left-to-down3-red.png b/src/imgs/big-circle-left-to-down3-red.png Binary files differnew file mode 100644 index 0000000..ebaaa3a --- /dev/null +++ b/src/imgs/big-circle-left-to-down3-red.png diff --git a/src/imgs/big-circle-right-red.png b/src/imgs/big-circle-right-red.png Binary files differnew file mode 100644 index 0000000..670c769 --- /dev/null +++ b/src/imgs/big-circle-right-red.png diff --git a/src/imgs/big-circle-right-to-up1-red.png b/src/imgs/big-circle-right-to-up1-red.png Binary files differnew file mode 100644 index 0000000..acdf91f --- /dev/null +++ b/src/imgs/big-circle-right-to-up1-red.png diff --git a/src/imgs/big-circle-right-to-up2-red.png b/src/imgs/big-circle-right-to-up2-red.png Binary files differnew file mode 100644 index 0000000..9d51a75 --- /dev/null +++ b/src/imgs/big-circle-right-to-up2-red.png diff --git a/src/imgs/big-circle-right-to-up3-red.png b/src/imgs/big-circle-right-to-up3-red.png Binary files differnew file mode 100644 index 0000000..e75fc7a --- /dev/null +++ b/src/imgs/big-circle-right-to-up3-red.png diff --git a/src/imgs/big-circle-up-red.png b/src/imgs/big-circle-up-red.png Binary files differnew file mode 100644 index 0000000..97dc92a --- /dev/null +++ b/src/imgs/big-circle-up-red.png diff --git a/src/imgs/big-circle-up-to-left1-red.png b/src/imgs/big-circle-up-to-left1-red.png Binary files differnew file mode 100644 index 0000000..f1d9bed --- /dev/null +++ b/src/imgs/big-circle-up-to-left1-red.png diff --git a/src/imgs/big-circle-up-to-left2-red.png b/src/imgs/big-circle-up-to-left2-red.png Binary files differnew file mode 100644 index 0000000..b89f2c2 --- /dev/null +++ b/src/imgs/big-circle-up-to-left2-red.png diff --git a/src/imgs/big-circle-up-to-left3-red.png b/src/imgs/big-circle-up-to-left3-red.png Binary files differnew file mode 100644 index 0000000..9a0fb3a --- /dev/null +++ b/src/imgs/big-circle-up-to-left3-red.png diff --git a/src/imgs/big-strange-up0-red.png b/src/imgs/big-strange-up0-red.png Binary files differnew file mode 100644 index 0000000..c25a49f --- /dev/null +++ b/src/imgs/big-strange-up0-red.png diff --git a/src/imgs/big-strange-up1-red.png b/src/imgs/big-strange-up1-red.png Binary files differnew file mode 100644 index 0000000..34d540a --- /dev/null +++ b/src/imgs/big-strange-up1-red.png diff --git a/src/imgs/font/%.png b/src/imgs/font/%.png Binary files differnew file mode 100644 index 0000000..783ff20 --- /dev/null +++ b/src/imgs/font/%.png diff --git a/src/imgs/font/=.png b/src/imgs/font/=.png Binary files differnew file mode 100644 index 0000000..0d36036 --- /dev/null +++ b/src/imgs/font/=.png diff --git a/src/imgs/player-rot5.png b/src/imgs/player-rot5.png Binary files differindex 6a02d70..a64f878 100644 --- a/src/imgs/player-rot5.png +++ b/src/imgs/player-rot5.png diff --git a/src/imgs/player-rot6.png b/src/imgs/player-rot6.png Binary files differindex 914c3e0..6a02d70 100644 --- a/src/imgs/player-rot6.png +++ b/src/imgs/player-rot6.png diff --git a/src/imgs/player-rot7.png b/src/imgs/player-rot7.png Binary files differindex 2244d62..914c3e0 100644 --- a/src/imgs/player-rot7.png +++ b/src/imgs/player-rot7.png diff --git a/src/imgs/player-rot8.png b/src/imgs/player-rot8.png Binary files differnew file mode 100644 index 0000000..2244d62 --- /dev/null +++ b/src/imgs/player-rot8.png diff --git a/src/imgs/player-small.png b/src/imgs/player-small.png Binary files differnew file mode 100644 index 0000000..49e73ff --- /dev/null +++ b/src/imgs/player-small.png diff --git a/src/imgs/powerup.png b/src/imgs/powerup.png Binary files differnew file mode 100644 index 0000000..f63858c --- /dev/null +++ b/src/imgs/powerup.png diff --git a/src/imgs/restart-screen.png b/src/imgs/restart-screen.png Binary files differnew file mode 100644 index 0000000..3e502dc --- /dev/null +++ b/src/imgs/restart-screen.png diff --git a/src/main.ts b/src/main.ts index 91e23ec..e20e14f 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,12 +1,25 @@ import "./style.css"; import "./Events"; -import loadAllImages from "./Images"; +import loadAllImages, { loadAllSounds, SOUNDS } from "./Images"; import { start } from "./game"; -import { IMGS } from "./Images" +const btn = document.createElement("button"); async function init() { + await loadAllSounds(); await loadAllImages(); - console.log(IMGS.startScreen0); - start(); + try { + SOUNDS.win.volume = 0; + await SOUNDS.win.play() + SOUNDS.win.pause() + SOUNDS.win.volume = 1 + SOUNDS.win.currentTime = 0; + start(); + } catch (error) { + console.log(error); + + btn.innerText = "Start da game" + btn.onclick = () => { btn.remove(); start(); } + document.body.appendChild(btn) + } } document.body.onload = init; |
