Usar prettier
This commit is contained in:
parent
b9e404bf29
commit
080513daf6
14 changed files with 594 additions and 445 deletions
6
.prettierignore
Normal file
6
.prettierignore
Normal file
|
@ -0,0 +1,6 @@
|
|||
node_modules
|
||||
.DS_Store
|
||||
dist
|
||||
dist-ssr
|
||||
*.local
|
||||
pnpm-lock.yaml
|
1
.prettierrc.json
Normal file
1
.prettierrc.json
Normal file
|
@ -0,0 +1 @@
|
|||
{}
|
|
@ -4,9 +4,11 @@
|
|||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vite build --base=./",
|
||||
"serve": "vite preview"
|
||||
"serve": "vite preview",
|
||||
"format": "prettier --write ."
|
||||
},
|
||||
"devDependencies": {
|
||||
"prettier": "2.3.2",
|
||||
"typescript": "^4.3.4",
|
||||
"vite": "^2.3.8"
|
||||
}
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
lockfileVersion: 5.3
|
||||
|
||||
specifiers:
|
||||
prettier: 2.3.2
|
||||
typescript: ^4.3.4
|
||||
vite: ^2.3.8
|
||||
|
||||
devDependencies:
|
||||
prettier: 2.3.2
|
||||
typescript: 4.3.4
|
||||
vite: 2.3.8
|
||||
|
||||
|
@ -63,6 +65,12 @@ packages:
|
|||
source-map-js: 0.6.2
|
||||
dev: true
|
||||
|
||||
/prettier/2.3.2:
|
||||
resolution: {integrity: sha512-lnJzDfJ66zkMy58OL5/NY5zp70S7Nz6KqcKkXYzn2tMVrNxvbqaBpg7H3qHaLxCJ5lNMsGuM8+ohS7cZrthdLQ==}
|
||||
engines: {node: '>=10.13.0'}
|
||||
hasBin: true
|
||||
dev: true
|
||||
|
||||
/resolve/1.20.0:
|
||||
resolution: {integrity: sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==}
|
||||
dependencies:
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
import botonJugarImg from "./assets/boton_jugar.png"
|
||||
import larretaImg from "./assets/Millonario Malo.png"
|
||||
import fondoImg from "./assets/CieloRioCalle.png"
|
||||
import edificiosImg from "./assets/Edificios.png"
|
||||
import jugadorxImg from "./assets/ProtagonistaCorriendo_1.png"
|
||||
import baldosaImg from "./assets/Baldosa.png"
|
||||
import semillaImg from "./assets/Semilla.png"
|
||||
import arbol1Img from "./assets/Árbol 1.png"
|
||||
import arbol2Img from "./assets/Árbol 2.png"
|
||||
import botonJugarImg from "./assets/boton_jugar.png";
|
||||
import larretaImg from "./assets/Millonario Malo.png";
|
||||
import fondoImg from "./assets/CieloRioCalle.png";
|
||||
import edificiosImg from "./assets/Edificios.png";
|
||||
import jugadorxImg from "./assets/ProtagonistaCorriendo_1.png";
|
||||
import baldosaImg from "./assets/Baldosa.png";
|
||||
import semillaImg from "./assets/Semilla.png";
|
||||
import arbol1Img from "./assets/Árbol 1.png";
|
||||
import arbol2Img from "./assets/Árbol 2.png";
|
||||
|
||||
function loadImage(url: string): Promise<HTMLImageElement> {
|
||||
return new Promise((resolve, reject) => {
|
||||
let img = new Image()
|
||||
img.onload = () => resolve(img)
|
||||
img.onerror = e => reject(e)
|
||||
img.src = url
|
||||
})
|
||||
let img = new Image();
|
||||
img.onload = () => resolve(img);
|
||||
img.onerror = (e) => reject(e);
|
||||
img.src = url;
|
||||
});
|
||||
}
|
||||
|
||||
export const assetUrls = {
|
||||
|
@ -27,12 +27,16 @@ export const assetUrls = {
|
|||
semilla: semillaImg,
|
||||
arbol1: arbol1Img,
|
||||
arbol2: arbol2Img,
|
||||
}
|
||||
export type Assets = { [key in keyof typeof assetUrls]: HTMLImageElement }
|
||||
};
|
||||
export type Assets = { [key in keyof typeof assetUrls]: HTMLImageElement };
|
||||
|
||||
const assets = Object.fromEntries(Object.entries(assetUrls).map(([name, url]) => [name, loadImage(url)]))
|
||||
const assets = Object.fromEntries(
|
||||
Object.entries(assetUrls).map(([name, url]) => [name, loadImage(url)])
|
||||
);
|
||||
|
||||
export async function loadAssets() {
|
||||
const imgs = await Promise.all(Object.values(assets))
|
||||
return Object.fromEntries(imgs.map((img, i) => [Object.keys(assetUrls)[i], img])) as Assets
|
||||
const imgs = await Promise.all(Object.values(assets));
|
||||
return Object.fromEntries(
|
||||
imgs.map((img, i) => [Object.keys(assetUrls)[i], img])
|
||||
) as Assets;
|
||||
}
|
||||
|
|
228
src/jugando.ts
228
src/jugando.ts
|
@ -1,26 +1,26 @@
|
|||
import { Juego } from './main'
|
||||
import { Sprite } from './sprite'
|
||||
import { Box, boxCollision, drawText, randomFromArray } from './utils'
|
||||
import { Juego } from "./main";
|
||||
import { Sprite } from "./sprite";
|
||||
import { Box, boxCollision, drawText, randomFromArray } from "./utils";
|
||||
|
||||
const ENEMIES_NUM = 12
|
||||
const SEED_COOLDOWN = 300
|
||||
const MAP_MIN = 1000
|
||||
const MAP_MAX = 5000
|
||||
const MAP_SIZE = MAP_MAX - MAP_MIN
|
||||
const TREES_TO_WIN = 30
|
||||
const TIME = 2 * 60 * 1000
|
||||
const ENEMIES_NUM = 12;
|
||||
const SEED_COOLDOWN = 300;
|
||||
const MAP_MIN = 1000;
|
||||
const MAP_MAX = 5000;
|
||||
const MAP_SIZE = MAP_MAX - MAP_MIN;
|
||||
const TREES_TO_WIN = 30;
|
||||
const TIME = 2 * 60 * 1000;
|
||||
|
||||
export type State = {
|
||||
current: "jugando"
|
||||
pos: { x: number }
|
||||
view: { x: number }
|
||||
side: "left" | "right"
|
||||
enemies: { x: number }[]
|
||||
seeds: { x: number; velocity: { x: number } }[]
|
||||
trees: { x: number, sprite: Sprite }[]
|
||||
time: number,
|
||||
seedCooldown: number,
|
||||
}
|
||||
current: "jugando";
|
||||
pos: { x: number };
|
||||
view: { x: number };
|
||||
side: "left" | "right";
|
||||
enemies: { x: number }[];
|
||||
seeds: { x: number; velocity: { x: number } }[];
|
||||
trees: { x: number; sprite: Sprite }[];
|
||||
time: number;
|
||||
seedCooldown: number;
|
||||
};
|
||||
|
||||
export function createJugandoState(): State {
|
||||
return {
|
||||
|
@ -33,138 +33,146 @@ export function createJugandoState(): State {
|
|||
trees: [],
|
||||
time: TIME,
|
||||
seedCooldown: 0,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export function update(juego: Juego<State>, dt: number) {
|
||||
juego.state.time -= dt
|
||||
juego.state.time -= dt;
|
||||
if (juego.state.time < 0) {
|
||||
(juego as Juego<any>).state = { current: "lose" }
|
||||
return
|
||||
(juego as Juego<any>).state = { current: "lose" };
|
||||
return;
|
||||
}
|
||||
|
||||
const playerSpeed = juego.canvas.width * 0.15
|
||||
const enemySpeed = juego.canvas.width * 0.05
|
||||
const playerSpeed = juego.canvas.width * 0.15;
|
||||
const enemySpeed = juego.canvas.width * 0.05;
|
||||
if (juego.keyboard.keys.d || juego.keyboard.keys.ArrowRight) {
|
||||
juego.state.side = "right"
|
||||
juego.state.pos.x += (dt / 1000) * playerSpeed
|
||||
juego.state.side = "right";
|
||||
juego.state.pos.x += (dt / 1000) * playerSpeed;
|
||||
}
|
||||
if (juego.keyboard.keys.a || juego.keyboard.keys.ArrowLeft) {
|
||||
juego.state.side = "left"
|
||||
juego.state.pos.x -= (dt / 1000) * playerSpeed
|
||||
juego.state.side = "left";
|
||||
juego.state.pos.x -= (dt / 1000) * playerSpeed;
|
||||
}
|
||||
|
||||
if (juego.state.pos.x < MAP_MIN) juego.state.pos.x = MAP_MIN
|
||||
if (juego.state.pos.x > MAP_MAX) juego.state.pos.x = MAP_MAX
|
||||
if (juego.state.pos.x < MAP_MIN) juego.state.pos.x = MAP_MIN;
|
||||
if (juego.state.pos.x > MAP_MAX) juego.state.pos.x = MAP_MAX;
|
||||
|
||||
juego.state.seedCooldown -= dt
|
||||
if (juego.keyboard.keys[' '] && juego.state.seedCooldown < 0) {
|
||||
const seedSpeed = juego.canvas.width * 0.7
|
||||
juego.state.seedCooldown -= dt;
|
||||
if (juego.keyboard.keys[" "] && juego.state.seedCooldown < 0) {
|
||||
const seedSpeed = juego.canvas.width * 0.7;
|
||||
juego.state.seeds.push({
|
||||
x: juego.state.pos.x,
|
||||
velocity: { x: juego.state.side === "left" ? -seedSpeed : seedSpeed },
|
||||
})
|
||||
juego.state.seedCooldown = SEED_COOLDOWN
|
||||
});
|
||||
juego.state.seedCooldown = SEED_COOLDOWN;
|
||||
}
|
||||
for (const seed of juego.state.seeds) {
|
||||
seed.x += (dt / 1000) * seed.velocity.x
|
||||
seed.velocity.x *= 0.97
|
||||
seed.x += (dt / 1000) * seed.velocity.x;
|
||||
seed.velocity.x *= 0.97;
|
||||
for (const enemy of juego.state.enemies) {
|
||||
if (boxCollision({
|
||||
if (
|
||||
boxCollision(
|
||||
{
|
||||
x: seed.x,
|
||||
y: getFloorY(juego) - juego.sprites.semilla.getHeight(juego),
|
||||
width: juego.sprites.semilla.getWidth(juego),
|
||||
height: juego.sprites.semilla.getHeight(juego),
|
||||
}, {
|
||||
},
|
||||
{
|
||||
x: enemy.x,
|
||||
y: getFloorY(juego) - juego.sprites.larreta.getHeight(juego),
|
||||
width: juego.sprites.larreta.getWidth(juego),
|
||||
height: juego.sprites.larreta.getHeight(juego),
|
||||
})) {
|
||||
juego.state.seeds = juego.state.seeds.filter(s => s.x !== seed.x)
|
||||
juego.state.enemies = juego.state.enemies.filter(e => e.x !== enemy.x)
|
||||
}
|
||||
)
|
||||
) {
|
||||
juego.state.seeds = juego.state.seeds.filter((s) => s.x !== seed.x);
|
||||
juego.state.enemies = juego.state.enemies.filter(
|
||||
(e) => e.x !== enemy.x
|
||||
);
|
||||
juego.state.trees.push({
|
||||
x: enemy.x,
|
||||
sprite: randomFromArray([juego.sprites.arbol1, juego.sprites.arbol2]),
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
if (Math.abs(seed.velocity.x) < 100)
|
||||
juego.state.seeds = juego.state.seeds.filter(s => s.velocity.x !== seed.velocity.x)
|
||||
juego.state.seeds = juego.state.seeds.filter(
|
||||
(s) => s.velocity.x !== seed.velocity.x
|
||||
);
|
||||
}
|
||||
|
||||
if (juego.state.trees.length >= TREES_TO_WIN) {
|
||||
(juego as Juego<any>).state = { current: "win" }
|
||||
return
|
||||
(juego as Juego<any>).state = { current: "win" };
|
||||
return;
|
||||
}
|
||||
|
||||
while (juego.state.enemies.length < ENEMIES_NUM) {
|
||||
const x = Math.random() * MAP_SIZE + MAP_MIN
|
||||
const x = Math.random() * MAP_SIZE + MAP_MIN;
|
||||
// Don't spawn enemies too close
|
||||
if (Math.abs(juego.state.pos.x - x) < 300) continue
|
||||
juego.state.enemies.push({ x })
|
||||
if (Math.abs(juego.state.pos.x - x) < 300) continue;
|
||||
juego.state.enemies.push({ x });
|
||||
}
|
||||
|
||||
for (const enemy of juego.state.enemies) {
|
||||
const distance = enemy.x - juego.state.pos.x
|
||||
const distance = enemy.x - juego.state.pos.x;
|
||||
if (distance < 0) {
|
||||
enemy.x += (dt / 1000) * enemySpeed
|
||||
enemy.x += (dt / 1000) * enemySpeed;
|
||||
} else {
|
||||
enemy.x -= (dt / 1000) * enemySpeed
|
||||
enemy.x -= (dt / 1000) * enemySpeed;
|
||||
}
|
||||
}
|
||||
|
||||
juego.state.view.x = -juego.state.pos.x + juego.canvas.width / 2 - juego.sprites.jugadorx.getWidth(juego) / 2
|
||||
juego.state.view.x =
|
||||
-juego.state.pos.x +
|
||||
juego.canvas.width / 2 -
|
||||
juego.sprites.jugadorx.getWidth(juego) / 2;
|
||||
}
|
||||
|
||||
function drawJugadorx(juego: Juego<State>) {
|
||||
const floorY = getFloorY(juego)
|
||||
const floorY = getFloorY(juego);
|
||||
juego.sprites.jugadorx.draw(
|
||||
juego,
|
||||
juego.state.pos.x + juego.state.view.x,
|
||||
floorY - juego.sprites.jugadorx.getHeight(juego),
|
||||
0,
|
||||
juego.state.side === "left",
|
||||
)
|
||||
juego.state.side === "left"
|
||||
);
|
||||
}
|
||||
|
||||
function drawTrees(juego: Juego<State>) {
|
||||
const floorY = getFloorY(juego)
|
||||
const floorY = getFloorY(juego);
|
||||
for (const tree of juego.state.trees) {
|
||||
const height = tree.sprite.getHeight(juego)
|
||||
tree.sprite.draw(
|
||||
juego,
|
||||
tree.x + juego.state.view.x,
|
||||
floorY - height,
|
||||
)
|
||||
const height = tree.sprite.getHeight(juego);
|
||||
tree.sprite.draw(juego, tree.x + juego.state.view.x, floorY - height);
|
||||
}
|
||||
}
|
||||
function drawEnemies(juego: Juego<State>) {
|
||||
const height = juego.sprites.larreta.getHeight(juego)
|
||||
const floorY = getFloorY(juego)
|
||||
const height = juego.sprites.larreta.getHeight(juego);
|
||||
const floorY = getFloorY(juego);
|
||||
for (const enemy of juego.state.enemies) {
|
||||
juego.sprites.larreta.draw(
|
||||
juego,
|
||||
enemy.x + juego.state.view.x,
|
||||
floorY - height,
|
||||
)
|
||||
floorY - height
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function drawSeeds(juego: Juego<State>) {
|
||||
const height = juego.sprites.semilla.getHeight(juego)
|
||||
const floorY = getFloorY(juego)
|
||||
const height = juego.sprites.semilla.getHeight(juego);
|
||||
const floorY = getFloorY(juego);
|
||||
for (const seed of juego.state.seeds) {
|
||||
juego.sprites.semilla.draw(
|
||||
juego,
|
||||
seed.x + juego.state.view.x,
|
||||
floorY - height,
|
||||
)
|
||||
floorY - height
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function getFloorY(juego: Juego<State>): number {
|
||||
return juego.canvas.height * 65 / 96
|
||||
return (juego.canvas.height * 65) / 96;
|
||||
}
|
||||
|
||||
function drawBackground(
|
||||
|
@ -172,50 +180,76 @@ function drawBackground(
|
|||
y: number,
|
||||
height: number,
|
||||
img: HTMLImageElement,
|
||||
sourceBox?: Box,
|
||||
sourceBox?: Box
|
||||
) {
|
||||
const aspect = img.width / img.height
|
||||
const width = height * aspect
|
||||
const aspect = img.width / img.height;
|
||||
const width = height * aspect;
|
||||
for (let i = 0; i < 10; i++) {
|
||||
if (sourceBox) {
|
||||
juego.ctx.drawImage(
|
||||
img,
|
||||
sourceBox.x, sourceBox.y, sourceBox.width, sourceBox.height,
|
||||
i * (width - 1) + juego.state.view.x, y, width, height,
|
||||
)
|
||||
sourceBox.x,
|
||||
sourceBox.y,
|
||||
sourceBox.width,
|
||||
sourceBox.height,
|
||||
i * (width - 1) + juego.state.view.x,
|
||||
y,
|
||||
width,
|
||||
height
|
||||
);
|
||||
} else {
|
||||
juego.ctx.drawImage(img, i * (width - 1) + juego.state.view.x, y, width, height)
|
||||
juego.ctx.drawImage(
|
||||
img,
|
||||
i * (width - 1) + juego.state.view.x,
|
||||
y,
|
||||
width,
|
||||
height
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function draw(juego: Juego<State>, timestamp: number) {
|
||||
drawBackground(juego, 0, juego.canvas.height, juego.assets.fondo)
|
||||
drawBackground(
|
||||
juego, 0, getFloorY(juego), juego.assets.edificios,
|
||||
{ x: 0, y: 0, width: 89, height: 48 })
|
||||
drawBackground(juego, 0, juego.canvas.height, juego.assets.fondo);
|
||||
drawBackground(juego, 0, getFloorY(juego), juego.assets.edificios, {
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: 89,
|
||||
height: 48,
|
||||
});
|
||||
|
||||
drawTrees(juego)
|
||||
drawEnemies(juego)
|
||||
drawTrees(juego);
|
||||
drawEnemies(juego);
|
||||
|
||||
drawJugadorx(juego)
|
||||
drawSeeds(juego)
|
||||
drawJugadorx(juego);
|
||||
drawSeeds(juego);
|
||||
|
||||
juego.ctx.fillStyle = "white"
|
||||
drawText(juego, 'Usá las flechitas para moverte, y espacio para "disparar" semillas.', { x: 0, y: 100 }, {})
|
||||
juego.ctx.fillStyle = "white";
|
||||
drawText(
|
||||
juego,
|
||||
'Usá las flechitas para moverte, y espacio para "disparar" semillas.',
|
||||
{ x: 0, y: 100 },
|
||||
{}
|
||||
);
|
||||
|
||||
const arbolesBox = drawText(
|
||||
juego, `Arboles: ${juego.state.trees.length}/${TREES_TO_WIN}`,
|
||||
juego,
|
||||
`Arboles: ${juego.state.trees.length}/${TREES_TO_WIN}`,
|
||||
{ x: juego.canvas.width - 10, y: 10 },
|
||||
{ bold: true, align: 'right' })
|
||||
{ bold: true, align: "right" }
|
||||
);
|
||||
|
||||
const tiempoBox = drawText(
|
||||
juego, `Tiempo restante`,
|
||||
juego,
|
||||
`Tiempo restante`,
|
||||
{ x: 10, y: 10 },
|
||||
{ bold: false, align: 'left' })
|
||||
{ bold: false, align: "left" }
|
||||
);
|
||||
|
||||
juego.ctx.fillRect(
|
||||
10, tiempoBox.y + tiempoBox.height,
|
||||
10,
|
||||
tiempoBox.y + tiempoBox.height,
|
||||
(juego.canvas.width - arbolesBox.width - 20) * (juego.state.time / TIME),
|
||||
30)
|
||||
30
|
||||
);
|
||||
}
|
||||
|
|
22
src/lose.ts
22
src/lose.ts
|
@ -1,18 +1,20 @@
|
|||
import { Juego } from './main'
|
||||
import { drawText } from './utils'
|
||||
import { Juego } from "./main";
|
||||
import { drawText } from "./utils";
|
||||
|
||||
export type State = {
|
||||
current: "lose"
|
||||
}
|
||||
current: "lose";
|
||||
};
|
||||
|
||||
export function update(juego: Juego<State>, dt: number) {
|
||||
}
|
||||
export function update(juego: Juego<State>, dt: number) {}
|
||||
|
||||
export function draw(juego: Juego<State>, timestamp: number) {
|
||||
drawText(juego, '¡Te convirtieron en baldosa!',
|
||||
drawText(
|
||||
juego,
|
||||
"¡Te convirtieron en baldosa!",
|
||||
{ x: juego.canvas.width / 2, y: 100 },
|
||||
{ bold: true, size: 3, align: 'center' })
|
||||
{ bold: true, size: 3, align: "center" }
|
||||
);
|
||||
|
||||
const width = juego.sprites.baldosa.getWidth(juego)
|
||||
juego.sprites.baldosa.draw(juego, juego.canvas.width / 2 - width / 2, 100)
|
||||
const width = juego.sprites.baldosa.getWidth(juego);
|
||||
juego.sprites.baldosa.draw(juego, juego.canvas.width / 2 - width / 2, 100);
|
||||
}
|
||||
|
|
208
src/main.ts
208
src/main.ts
|
@ -1,88 +1,126 @@
|
|||
import './style.css'
|
||||
import "./style.css";
|
||||
|
||||
import * as welcome from "./welcome"
|
||||
import * as jugando from "./jugando"
|
||||
import * as win from "./win"
|
||||
import * as lose from "./lose"
|
||||
import { Assets, loadAssets } from './assets'
|
||||
import { loadSprite, Sprite } from './sprite'
|
||||
import * as welcome from "./welcome";
|
||||
import * as jugando from "./jugando";
|
||||
import * as win from "./win";
|
||||
import * as lose from "./lose";
|
||||
import { Assets, loadAssets } from "./assets";
|
||||
import { loadSprite, Sprite } from "./sprite";
|
||||
|
||||
export type State = welcome.State | jugando.State | win.State | lose.State
|
||||
export type State = welcome.State | jugando.State | win.State | lose.State;
|
||||
|
||||
export type Juego<T extends State> = {
|
||||
canvas: HTMLCanvasElement
|
||||
ctx: CanvasRenderingContext2D
|
||||
assets: Assets
|
||||
sprites: { [key in "jugadorx" | "baldosa" | "larreta" | "semilla" | "arbol1" | "arbol2"]: Sprite }
|
||||
mouse: { x: number; y: number, down: boolean }
|
||||
keyboard: { keys: { [key: string]: boolean } }
|
||||
state: T
|
||||
}
|
||||
canvas: HTMLCanvasElement;
|
||||
ctx: CanvasRenderingContext2D;
|
||||
assets: Assets;
|
||||
sprites: {
|
||||
[key in
|
||||
| "jugadorx"
|
||||
| "baldosa"
|
||||
| "larreta"
|
||||
| "semilla"
|
||||
| "arbol1"
|
||||
| "arbol2"]: Sprite;
|
||||
};
|
||||
mouse: { x: number; y: number; down: boolean };
|
||||
keyboard: { keys: { [key: string]: boolean } };
|
||||
state: T;
|
||||
};
|
||||
|
||||
function update(juego: Juego<any>, dt: number) {
|
||||
switch (juego.state.current) {
|
||||
case "welcome":
|
||||
welcome.update(juego, dt)
|
||||
break
|
||||
welcome.update(juego, dt);
|
||||
break;
|
||||
case "jugando":
|
||||
jugando.update(juego, dt)
|
||||
break
|
||||
jugando.update(juego, dt);
|
||||
break;
|
||||
case "win":
|
||||
win.update(juego, dt)
|
||||
break
|
||||
win.update(juego, dt);
|
||||
break;
|
||||
case "lose":
|
||||
lose.update(juego, dt)
|
||||
break
|
||||
lose.update(juego, dt);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function draw(juego: Juego<any>, timestamp: number) {
|
||||
const { width, height } = juego.canvas
|
||||
const { width, height } = juego.canvas;
|
||||
|
||||
juego.ctx.fillStyle = "white"
|
||||
juego.ctx.fillRect(0, 0, width, height)
|
||||
juego.ctx.fillStyle = "black"
|
||||
juego.ctx.fillStyle = "white";
|
||||
juego.ctx.fillRect(0, 0, width, height);
|
||||
juego.ctx.fillStyle = "black";
|
||||
switch (juego.state.current) {
|
||||
case "welcome":
|
||||
welcome.draw(juego, timestamp)
|
||||
break
|
||||
welcome.draw(juego, timestamp);
|
||||
break;
|
||||
case "jugando":
|
||||
jugando.draw(juego, timestamp)
|
||||
break
|
||||
jugando.draw(juego, timestamp);
|
||||
break;
|
||||
case "win":
|
||||
win.draw(juego, timestamp)
|
||||
break
|
||||
win.draw(juego, timestamp);
|
||||
break;
|
||||
case "lose":
|
||||
lose.draw(juego, timestamp)
|
||||
break
|
||||
lose.draw(juego, timestamp);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function resizeCanvas(canvas: HTMLCanvasElement) {
|
||||
canvas.width = canvas.clientWidth
|
||||
canvas.height = canvas.clientHeight
|
||||
canvas.width = canvas.clientWidth;
|
||||
canvas.height = canvas.clientHeight;
|
||||
}
|
||||
|
||||
async function initJuego() {
|
||||
const canvas = document.querySelector<HTMLCanvasElement>("#juego")!
|
||||
const canvas = document.querySelector<HTMLCanvasElement>("#juego")!;
|
||||
const ctx = canvas.getContext("2d", {
|
||||
alpha: false,
|
||||
desynchronized: true,
|
||||
})!
|
||||
})!;
|
||||
|
||||
window.addEventListener("resize", () => resizeCanvas(canvas), false)
|
||||
resizeCanvas(canvas)
|
||||
window.addEventListener("resize", () => resizeCanvas(canvas), false);
|
||||
resizeCanvas(canvas);
|
||||
|
||||
const assets = await loadAssets()
|
||||
const assets = await loadAssets();
|
||||
|
||||
const sprites = {
|
||||
jugadorx: loadSprite(assets.jugadorx, 65, 94, juego => juego.canvas.height / 4),
|
||||
baldosa: loadSprite(assets.baldosa, 72, 72, juego => juego.canvas.height * 0.8),
|
||||
larreta: loadSprite(assets.larreta, 50, 71, juego => juego.canvas.height / 4),
|
||||
semilla: loadSprite(assets.semilla, 72, 73, juego => juego.canvas.height / 8),
|
||||
arbol1: loadSprite(assets.arbol1, 72, 68, juego => juego.canvas.height / 3),
|
||||
arbol2: loadSprite(assets.arbol2, 72, 56, juego => juego.canvas.height / 4),
|
||||
}
|
||||
jugadorx: loadSprite(
|
||||
assets.jugadorx,
|
||||
65,
|
||||
94,
|
||||
(juego) => juego.canvas.height / 4
|
||||
),
|
||||
baldosa: loadSprite(
|
||||
assets.baldosa,
|
||||
72,
|
||||
72,
|
||||
(juego) => juego.canvas.height * 0.8
|
||||
),
|
||||
larreta: loadSprite(
|
||||
assets.larreta,
|
||||
50,
|
||||
71,
|
||||
(juego) => juego.canvas.height / 4
|
||||
),
|
||||
semilla: loadSprite(
|
||||
assets.semilla,
|
||||
72,
|
||||
73,
|
||||
(juego) => juego.canvas.height / 8
|
||||
),
|
||||
arbol1: loadSprite(
|
||||
assets.arbol1,
|
||||
72,
|
||||
68,
|
||||
(juego) => juego.canvas.height / 3
|
||||
),
|
||||
arbol2: loadSprite(
|
||||
assets.arbol2,
|
||||
72,
|
||||
56,
|
||||
(juego) => juego.canvas.height / 4
|
||||
),
|
||||
};
|
||||
|
||||
let juego: Juego<welcome.State> = {
|
||||
canvas,
|
||||
|
@ -95,37 +133,49 @@ async function initJuego() {
|
|||
current: "welcome",
|
||||
},
|
||||
};
|
||||
(window as any).juego = juego
|
||||
juego.ctx.imageSmoothingEnabled = false
|
||||
(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
|
||||
})
|
||||
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;
|
||||
});
|
||||
|
||||
let lastRender = 0
|
||||
const loop: FrameRequestCallback = timestamp => {
|
||||
const progress = timestamp - lastRender
|
||||
let lastRender = 0;
|
||||
const loop: FrameRequestCallback = (timestamp) => {
|
||||
const progress = timestamp - lastRender;
|
||||
|
||||
update(juego, progress)
|
||||
draw(juego, timestamp)
|
||||
update(juego, progress);
|
||||
draw(juego, timestamp);
|
||||
|
||||
lastRender = timestamp
|
||||
window.requestAnimationFrame(loop)
|
||||
lastRender = timestamp;
|
||||
window.requestAnimationFrame(loop);
|
||||
};
|
||||
|
||||
window.requestAnimationFrame(loop);
|
||||
}
|
||||
|
||||
window.requestAnimationFrame(loop)
|
||||
}
|
||||
initJuego()
|
||||
initJuego();
|
||||
|
|
|
@ -1,39 +1,54 @@
|
|||
import { Juego } from "./main"
|
||||
import { Juego } from "./main";
|
||||
|
||||
export type Sprite = {
|
||||
getWidth: (juego: Juego<any>) => number;
|
||||
getHeight: (juego: Juego<any>) => number;
|
||||
draw: (juego: Juego<any>, x: number, y: number, spriteIndex?: number, flipped?: boolean) => void;
|
||||
draw: (
|
||||
juego: Juego<any>,
|
||||
x: number,
|
||||
y: number,
|
||||
spriteIndex?: number,
|
||||
flipped?: boolean
|
||||
) => void;
|
||||
width: number;
|
||||
height: number;
|
||||
}
|
||||
};
|
||||
|
||||
// Sprites are image assets that have a grid of tiles to animate
|
||||
export function loadSprite(
|
||||
img: HTMLImageElement,
|
||||
// The size of each tile
|
||||
width: number, height: number,
|
||||
width: number,
|
||||
height: number,
|
||||
// Calculates the size of the sprite when rendering
|
||||
getHeight: (juego: Juego<any>) => number,
|
||||
getHeight: (juego: Juego<any>) => number
|
||||
): Sprite {
|
||||
const aspect = width / height
|
||||
const rowSize = Math.floor(img.width / width)
|
||||
const aspect = width / height;
|
||||
const rowSize = Math.floor(img.width / width);
|
||||
if (img.width / width !== rowSize) {
|
||||
console.warn(`The sprite grid for ${img.src} has extra space after rows, are you sure the width/height of each tile is right?`)
|
||||
console.warn(
|
||||
`The sprite grid for ${img.src} has extra space after rows, are you sure the width/height of each tile is right?`
|
||||
);
|
||||
}
|
||||
|
||||
function getWidth(juego: Juego<any>) {
|
||||
return getHeight(juego) * aspect
|
||||
return getHeight(juego) * aspect;
|
||||
}
|
||||
|
||||
function draw(juego: Juego<any>, x: number, y: number, spriteIndex = 0, flipped = false) {
|
||||
const drawHeight = getHeight(juego)
|
||||
const drawWidth = getWidth(juego)
|
||||
const tileX = spriteIndex % rowSize
|
||||
const tileY = Math.floor(spriteIndex / rowSize)
|
||||
function draw(
|
||||
juego: Juego<any>,
|
||||
x: number,
|
||||
y: number,
|
||||
spriteIndex = 0,
|
||||
flipped = false
|
||||
) {
|
||||
const drawHeight = getHeight(juego);
|
||||
const drawWidth = getWidth(juego);
|
||||
const tileX = spriteIndex % rowSize;
|
||||
const tileY = Math.floor(spriteIndex / rowSize);
|
||||
if (flipped) {
|
||||
juego.ctx.save()
|
||||
juego.ctx.scale(-1, 1)
|
||||
juego.ctx.save();
|
||||
juego.ctx.scale(-1, 1);
|
||||
juego.ctx.drawImage(
|
||||
img,
|
||||
tileX * width,
|
||||
|
@ -43,9 +58,9 @@ export function loadSprite(
|
|||
-x - drawWidth,
|
||||
y,
|
||||
drawWidth,
|
||||
drawHeight,
|
||||
)
|
||||
juego.ctx.restore()
|
||||
drawHeight
|
||||
);
|
||||
juego.ctx.restore();
|
||||
} else {
|
||||
juego.ctx.drawImage(
|
||||
img,
|
||||
|
@ -56,10 +71,10 @@ export function loadSprite(
|
|||
x,
|
||||
y,
|
||||
drawWidth,
|
||||
drawHeight,
|
||||
)
|
||||
drawHeight
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return { getWidth, getHeight, draw, width, height }
|
||||
return { getWidth, getHeight, draw, width, height };
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
html, body {
|
||||
html,
|
||||
body {
|
||||
font-family: Avenir, Helvetica, Arial, sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
|
|
61
src/utils.ts
61
src/utils.ts
|
@ -1,47 +1,62 @@
|
|||
import { Juego } from "./main";
|
||||
|
||||
export type Pos = {
|
||||
x: number, y: number,
|
||||
x: number;
|
||||
y: number;
|
||||
};
|
||||
export type Box = Pos & {
|
||||
width: number, height: number,
|
||||
}
|
||||
width: number;
|
||||
height: number;
|
||||
};
|
||||
|
||||
export function posInBox(box: Box, pos: Pos) {
|
||||
return pos.x > box.x && pos.x < box.x + box.width
|
||||
&& pos.y > box.y && pos.y < box.y + box.height
|
||||
return (
|
||||
pos.x > box.x &&
|
||||
pos.x < box.x + box.width &&
|
||||
pos.y > box.y &&
|
||||
pos.y < box.y + box.height
|
||||
);
|
||||
}
|
||||
export function boxCollision(box1: Box, box2: Box) {
|
||||
// http://stackoverflow.com/questions/2440377/ddg#7301852
|
||||
return !(
|
||||
((box1.y + box1.height) < (box2.y)) ||
|
||||
(box1.y > (box2.y + box2.height)) ||
|
||||
((box1.x + box1.width) < box2.x) ||
|
||||
(box1.x > (box2.x + box2.width))
|
||||
)
|
||||
box1.y + box1.height < box2.y ||
|
||||
box1.y > box2.y + box2.height ||
|
||||
box1.x + box1.width < box2.x ||
|
||||
box1.x > box2.x + box2.width
|
||||
);
|
||||
}
|
||||
|
||||
export function drawText(juego: Juego<any>, text: string, pos: Pos, {
|
||||
export function drawText(
|
||||
juego: Juego<any>,
|
||||
text: string,
|
||||
pos: Pos,
|
||||
{
|
||||
bold = false,
|
||||
size = 2,
|
||||
align = "left",
|
||||
baseline = "top",
|
||||
}: {
|
||||
align?: CanvasTextAlign,
|
||||
baseline?: CanvasTextBaseline,
|
||||
bold?: boolean,
|
||||
align?: CanvasTextAlign;
|
||||
baseline?: CanvasTextBaseline;
|
||||
bold?: boolean;
|
||||
// in rem
|
||||
size?: number,
|
||||
}): Box {
|
||||
juego.ctx.font = `${bold ? 'bold ' : ''}${size}rem sans-serif`
|
||||
juego.ctx.textAlign = align
|
||||
juego.ctx.textBaseline = baseline
|
||||
juego.ctx.fillText(text, pos.x, pos.y)
|
||||
size?: number;
|
||||
}
|
||||
): Box {
|
||||
juego.ctx.font = `${bold ? "bold " : ""}${size}rem sans-serif`;
|
||||
juego.ctx.textAlign = align;
|
||||
juego.ctx.textBaseline = baseline;
|
||||
juego.ctx.fillText(text, pos.x, pos.y);
|
||||
|
||||
const measure = juego.ctx.measureText(text)
|
||||
return { ...pos, width: measure.width, height: measure.actualBoundingBoxDescent }
|
||||
const measure = juego.ctx.measureText(text);
|
||||
return {
|
||||
...pos,
|
||||
width: measure.width,
|
||||
height: measure.actualBoundingBoxDescent,
|
||||
};
|
||||
}
|
||||
|
||||
export function randomFromArray<T>(array: T[]): T {
|
||||
return array[Math.floor(Math.random() * array.length)]
|
||||
return array[Math.floor(Math.random() * array.length)];
|
||||
}
|
||||
|
|
|
@ -1,29 +1,38 @@
|
|||
import { posInBox } from './utils'
|
||||
import { createJugandoState } from './jugando'
|
||||
import { Juego } from './main'
|
||||
import { posInBox } from "./utils";
|
||||
import { createJugandoState } from "./jugando";
|
||||
import { Juego } from "./main";
|
||||
|
||||
export type State = {
|
||||
current: "welcome"
|
||||
}
|
||||
current: "welcome";
|
||||
};
|
||||
|
||||
function startButton(juego: Juego<State>) {
|
||||
const [width, height] = [juego.assets.botonJugar.width / 4, juego.assets.botonJugar.height / 4]
|
||||
const [width, height] = [
|
||||
juego.assets.botonJugar.width / 4,
|
||||
juego.assets.botonJugar.height / 4,
|
||||
];
|
||||
return {
|
||||
x: juego.canvas.width - width - 30,
|
||||
y: juego.canvas.height - height - 30,
|
||||
width,
|
||||
height,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export function update(juego: Juego<State>, dt: number) {
|
||||
const btn = startButton(juego)
|
||||
const btn = startButton(juego);
|
||||
if (juego.mouse.down && posInBox(btn, juego.mouse)) {
|
||||
(juego as Juego<any>).state = createJugandoState()
|
||||
(juego as Juego<any>).state = createJugandoState();
|
||||
}
|
||||
}
|
||||
|
||||
export function draw(juego: Juego<State>, timestamp: number) {
|
||||
const btn = startButton(juego)
|
||||
juego.ctx.drawImage(juego.assets.botonJugar, btn.x, btn.y, btn.width, btn.height)
|
||||
const btn = startButton(juego);
|
||||
juego.ctx.drawImage(
|
||||
juego.assets.botonJugar,
|
||||
btn.x,
|
||||
btn.y,
|
||||
btn.width,
|
||||
btn.height
|
||||
);
|
||||
}
|
||||
|
|
18
src/win.ts
18
src/win.ts
|
@ -1,15 +1,17 @@
|
|||
import { Juego } from './main'
|
||||
import { drawText } from './utils'
|
||||
import { Juego } from "./main";
|
||||
import { drawText } from "./utils";
|
||||
|
||||
export type State = {
|
||||
current: "win"
|
||||
}
|
||||
current: "win";
|
||||
};
|
||||
|
||||
export function update(juego: Juego<State>, dt: number) {
|
||||
}
|
||||
export function update(juego: Juego<State>, dt: number) {}
|
||||
|
||||
export function draw(juego: Juego<State>, timestamp: number) {
|
||||
drawText(juego, '¡Salvaste la costanera!',
|
||||
drawText(
|
||||
juego,
|
||||
"¡Salvaste la costanera!",
|
||||
{ x: juego.canvas.width / 2, y: 100 },
|
||||
{ bold: true, size: 3, align: 'center' })
|
||||
{ bold: true, size: 3, align: "center" }
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue