salva-la-costanera/src/main.ts

329 lines
8.5 KiB
TypeScript
Raw Normal View History

2021-06-30 23:16:45 +00:00
import "./style.css";
2021-06-28 18:01:45 +00:00
2021-07-05 15:49:06 +00:00
import * as logo from "./logo";
2021-06-30 23:16:45 +00:00
import * as welcome from "./welcome";
import * as jugando from "./jugando";
import { Assets, loadAssets } from "./assets";
import { loadSprite, Sprite } from "./sprite";
2021-07-05 15:49:06 +00:00
import { drawText } from "./utils";
2021-06-28 18:01:45 +00:00
2021-07-05 16:13:36 +00:00
export type State = logo.State | welcome.State | jugando.State;
2021-06-30 16:34:26 +00:00
export type Juego<T extends State> = {
2021-06-30 23:16:45 +00:00
canvas: HTMLCanvasElement;
ctx: CanvasRenderingContext2D;
assets: Assets;
sprites: {
[key in
2021-07-05 15:49:06 +00:00
| "botonSiguiente"
| "botonComenzar"
2021-07-06 17:09:21 +00:00
| "botonCompartirPerdiste"
| "botonCompartirFelicitaciones"
2021-07-06 23:07:17 +00:00
| "instagram"
| "twitter"
| "facebook"
2021-07-05 15:49:06 +00:00
| "logoFPGFDTBlanco"
| "logoSalvaLaCostaneraGrande"
| "logoSalvaLaCostaneraCostado"
| "instrucciones1"
| "instrucciones2"
| "instrucciones3"
2021-07-05 16:13:36 +00:00
| "placaPerdiste"
| "placaFelicitaciones"
2021-07-06 17:58:08 +00:00
| "dialogoFirma"
2021-07-01 22:33:51 +00:00
| "flecha"
2021-06-30 23:16:45 +00:00
| "jugadorx"
2021-07-05 15:49:06 +00:00
| "jugadorxPresentando"
2021-06-30 23:16:45 +00:00
| "baldosa"
| "larreta"
2021-07-01 20:45:37 +00:00
| "millonarioMalo"
2021-06-30 23:16:45 +00:00
| "semilla"
| "arbol1"
2021-07-02 18:17:35 +00:00
| "arbol2"
| "ciudadanx1"
| "ciudadanx2"
| "ciudadanx3"]: Sprite;
2021-06-30 23:16:45 +00:00
};
mouse: { x: number; y: number; down: boolean };
2021-07-01 22:33:51 +00:00
touches: TouchList | null;
2021-06-30 23:16:45 +00:00
keyboard: { keys: { [key: string]: boolean } };
state: T;
};
2021-06-30 16:34:26 +00:00
function needsRotation(juego: Juego<any>): boolean {
return juego.canvas.width < juego.canvas.height;
}
2021-06-28 18:01:45 +00:00
function update(juego: Juego<any>, dt: number) {
if (needsRotation(juego)) return;
2021-06-30 23:16:45 +00:00
switch (juego.state.current) {
2021-07-05 15:49:06 +00:00
case "logo":
logo.update(juego, dt);
break;
2021-06-30 23:16:45 +00:00
case "welcome":
welcome.update(juego, dt);
break;
case "jugando":
jugando.update(juego, dt);
break;
}
2021-06-28 18:01:45 +00:00
}
function draw(juego: Juego<any>, timestamp: number) {
2021-06-30 23:16:45 +00:00
const { width, height } = juego.canvas;
2021-07-01 21:18:44 +00:00
juego.ctx.imageSmoothingEnabled = false;
2021-06-30 23:16:45 +00:00
juego.ctx.fillStyle = "white";
juego.ctx.fillRect(0, 0, width, height);
juego.ctx.fillStyle = "black";
if (needsRotation(juego)) {
drawText(
juego,
"¡Por favor rotá el dispositivo!",
{ x: juego.canvas.width / 2, y: juego.canvas.height / 2 },
{ align: "center", maxWidth: juego.canvas.width }
);
return;
}
2021-06-30 23:16:45 +00:00
switch (juego.state.current) {
2021-07-05 15:49:06 +00:00
case "logo":
logo.draw(juego, timestamp);
break;
2021-06-30 23:16:45 +00:00
case "welcome":
welcome.draw(juego, timestamp);
break;
case "jugando":
jugando.draw(juego, timestamp);
break;
}
2021-06-28 18:01:45 +00:00
}
function resizeCanvas(canvas: HTMLCanvasElement) {
2021-06-30 23:16:45 +00:00
canvas.width = canvas.clientWidth;
canvas.height = canvas.clientHeight;
2021-06-28 18:01:45 +00:00
}
2021-07-01 22:33:51 +00:00
function touchListener(juego: Juego<any>, event: TouchEvent) {
juego.touches = event.touches;
}
async function initJuego() {
2021-06-30 23:16:45 +00:00
const canvas = document.querySelector<HTMLCanvasElement>("#juego")!;
const ctx = canvas.getContext("2d", {
alpha: false,
desynchronized: true,
})!;
window.addEventListener("resize", () => resizeCanvas(canvas), false);
resizeCanvas(canvas);
const assets = await loadAssets();
const sprites = {
2021-07-05 15:49:06 +00:00
botonComenzar: loadSprite(assets.botonComenzar, {
height: (juego) => juego.canvas.height / 8,
}),
botonSiguiente: loadSprite(assets.botonSiguiente, {
height: (juego) => juego.canvas.height / 8,
}),
2021-07-06 17:09:21 +00:00
botonCompartirPerdiste: loadSprite(assets.botonCompartirPerdiste, {
height: (juego) => juego.canvas.height / 8,
}),
botonCompartirFelicitaciones: loadSprite(
assets.botonCompartirFelicitaciones,
{
height: (juego) => juego.canvas.height / 8,
}
),
2021-07-06 23:07:17 +00:00
instagram: loadSprite(assets.instagram, {
height: (juego) => juego.canvas.height * 0.1,
}),
facebook: loadSprite(assets.facebook, {
height: (juego) => juego.canvas.height * 0.1,
}),
twitter: loadSprite(assets.twitter, {
height: (juego) => juego.canvas.height * 0.1,
}),
2021-07-05 15:49:06 +00:00
logoFPGFDTBlanco: loadSprite(assets.logoFPGFDTBlanco, {
height: (juego) => juego.canvas.height / 6,
}),
logoSalvaLaCostaneraGrande: loadSprite(assets.logoSalvaLaCostanera, {
height: (juego) => juego.canvas.height * 0.45,
}),
logoSalvaLaCostaneraCostado: loadSprite(
assets.logoSalvaLaCostaneraCostado,
{ height: (juego) => juego.canvas.height / 4 }
2021-07-01 22:33:51 +00:00
),
2021-07-05 15:49:06 +00:00
instrucciones1: loadSprite(assets.instrucciones1, {
2021-07-06 15:39:21 +00:00
width: (juego) => juego.canvas.width * 0.5,
2021-07-05 15:49:06 +00:00
}),
instrucciones2: loadSprite(assets.instrucciones2, {
2021-07-06 15:39:21 +00:00
width: (juego) => juego.canvas.width * 0.5,
2021-07-05 15:49:06 +00:00
}),
instrucciones3: loadSprite(assets.instrucciones3, {
2021-07-06 15:39:21 +00:00
width: (juego) => juego.canvas.width * 0.5,
2021-07-05 15:49:06 +00:00
}),
2021-07-05 16:13:36 +00:00
placaPerdiste: loadSprite(assets.placaPerdiste, {
2021-07-06 15:39:21 +00:00
height: (juego) => juego.canvas.height * 0.6,
2021-07-05 16:13:36 +00:00
}),
placaFelicitaciones: loadSprite(assets.placaFelicitaciones, {
2021-07-06 15:39:21 +00:00
height: (juego) => juego.canvas.height * 0.6,
2021-07-05 16:13:36 +00:00
}),
2021-07-06 17:58:08 +00:00
dialogoFirma: loadSprite(assets.dialogoFirma, {
height: (juego) => juego.canvas.height / 8,
}),
2021-07-05 15:49:06 +00:00
flecha: loadSprite(assets.flecha, {
height: (juego) => juego.canvas.height / 6,
}),
2021-06-30 23:16:45 +00:00
jugadorx: loadSprite(
assets.jugadorx,
2021-07-05 15:49:06 +00:00
{ height: (juego) => juego.canvas.height / 4 },
{
2021-07-06 17:58:08 +00:00
width: 56,
2021-07-05 15:49:06 +00:00
height: 94,
}
2021-06-30 23:16:45 +00:00
),
2021-07-05 15:49:06 +00:00
jugadorxPresentando: loadSprite(assets.jugadorxPresentando, {
height: (juego) => juego.canvas.height * 0.8,
}),
baldosa: loadSprite(assets.baldosa, {
2021-07-06 18:12:35 +00:00
height: (juego) => juego.canvas.height * 0.2,
2021-07-05 15:49:06 +00:00
}),
2021-06-30 23:16:45 +00:00
larreta: loadSprite(
assets.larreta,
2021-07-05 15:49:06 +00:00
{ height: (juego) => juego.canvas.height / 4 },
{
width: 83,
height: 131,
}
2021-07-01 20:45:37 +00:00
),
millonarioMalo: loadSprite(
assets.millonarioMalo,
2021-07-05 15:49:06 +00:00
{ height: (juego) => juego.canvas.height / 4 },
{ width: 50, height: 71 }
2021-06-30 23:16:45 +00:00
),
2021-07-05 15:49:06 +00:00
semilla: loadSprite(assets.semilla, {
height: (juego) => juego.canvas.height / 8,
}),
2021-06-30 23:16:45 +00:00
arbol1: loadSprite(
assets.arbol1,
2021-07-05 15:49:06 +00:00
{ height: (juego) => juego.canvas.height / 3 },
{
width: 72,
height: 68,
}
2021-06-30 23:16:45 +00:00
),
arbol2: loadSprite(
assets.arbol2,
2021-07-05 15:49:06 +00:00
{ height: (juego) => juego.canvas.height / 4 },
{
width: 72,
height: 56,
}
2021-06-30 23:16:45 +00:00
),
2021-07-02 18:17:35 +00:00
ciudadanx1: loadSprite(
assets.ciudadanx1,
2021-07-05 15:49:06 +00:00
{
height: (juego) => juego.canvas.height / 4,
},
{ width: 45, height: 88 }
2021-07-02 18:17:35 +00:00
),
ciudadanx2: loadSprite(
assets.ciudadanx2,
2021-07-05 15:49:06 +00:00
{
height: (juego) => juego.canvas.height / 4,
},
{ width: 45, height: 88 }
2021-07-02 18:17:35 +00:00
),
ciudadanx3: loadSprite(
assets.ciudadanx3,
2021-07-05 15:49:06 +00:00
{
height: (juego) => juego.canvas.height / 4,
},
{ width: 45, height: 86 }
2021-07-02 18:17:35 +00:00
),
2021-06-30 23:16:45 +00:00
};
2021-07-05 15:49:06 +00:00
let juego: Juego<logo.State> = {
2021-06-30 23:16:45 +00:00
canvas,
ctx,
assets,
sprites,
mouse: { x: 0, y: 0, down: false },
2021-07-01 22:33:51 +00:00
touches: null,
2021-06-30 23:16:45 +00:00
keyboard: { keys: {} },
2021-07-05 15:49:06 +00:00
state: logo.createState(),
2021-06-30 23:16:45 +00:00
};
(window as any).juego = juego;
juego.ctx.imageSmoothingEnabled = false;
canvas.addEventListener(
"mousemove",
(e) => {
juego.mouse.x = e.clientX;
juego.mouse.y = e.clientY;
},
false
);
canvas.addEventListener(
"mousedown",
() => {
juego.mouse.down = true;
},
false
);
canvas.addEventListener(
"mouseup",
() => {
juego.mouse.down = false;
},
false
);
window.addEventListener("keydown", (e) => {
juego.keyboard.keys[e.key] = true;
});
window.addEventListener("keyup", (e) => {
juego.keyboard.keys[e.key] = false;
});
2021-07-01 22:33:51 +00:00
window.addEventListener("touchstart", (e) => touchListener(juego, e));
window.addEventListener("touchend", (e) => touchListener(juego, e));
window.addEventListener("touchcancel", (e) => touchListener(juego, e));
window.addEventListener("touchmove", (e) => touchListener(juego, e));
2021-06-30 23:16:45 +00:00
let lastRender = 0;
const loop: FrameRequestCallback = (timestamp) => {
const progress = timestamp - lastRender;
update(juego, progress);
draw(juego, timestamp);
lastRender = timestamp;
window.requestAnimationFrame(loop);
};
window.requestAnimationFrame(loop);
console.log(
"%c¡Hola curiosx! Podés ver el código completo en https://gitea.nulo.in/Nulo/salva-la-costanera. ¡Suerte!",
"color:green;font-size:3rem;font-weight:bold"
);
2021-06-28 18:01:45 +00:00
}
const fullscreenEl = document.getElementById("full-screen")!;
if ("requestFullscreen" in document.documentElement) {
fullscreenEl.addEventListener("click", async () => {
document.documentElement.requestFullscreen &&
(await document.documentElement.requestFullscreen({
navigationUI: "hide",
}));
await screen.orientation.lock("landscape");
});
} else {
fullscreenEl.hidden = true;
}
2021-06-30 23:16:45 +00:00
initJuego();