Revamp sistema de assets para que cargue imagenes antes de iniciar el juego

This commit is contained in:
Nulo 2021-06-28 20:28:26 +00:00
parent da92f24ca6
commit 0a20e26554
7 changed files with 79 additions and 47 deletions

View file

@ -8,16 +8,6 @@
<title>Salvá la costanera</title>
</head>
<body>
<div style="display: none">
<!-- Cargar imágenes -->
<img id="img-boton-jugar" src="./src/assets/boton_jugar.png">
<img id="img-vereda" src="./src/assets/piso.png">
<img id="img-fondo" src="./src/assets/fondo.png">
<img id="img-larreta" src="./src/assets/larreta.png">
<img id="img-jugadorx" src="./src/assets/eli.png">
<img id="img-semilla" src="./src/assets/semilla.png">
<img id="img-arbol" src="./src/assets/arbol.png">
</div>
<canvas id="juego" width="1280" height="720"></canvas>
<script type="module" src="/src/main.ts"></script>
</body>

34
src/assets.ts Normal file
View file

@ -0,0 +1,34 @@
import botonJugarImg from "./assets/boton_jugar.png"
import larretaImg from "./assets/larreta.png"
import veredaImg from "./assets/piso.png"
import fondoImg from "./assets/fondo.png"
import jugadorxImg from "./assets/eli.png"
import semillaImg from "./assets/semilla.png"
import arbolImg from "./assets/arbol.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
})
}
export const assetUrls = {
botonJugar: botonJugarImg,
larreta: larretaImg,
vereda: veredaImg,
fondo: fondoImg,
jugadorx: jugadorxImg,
semilla: semillaImg,
arbol: arbolImg,
}
export type Assets = { [key in keyof typeof assetUrls]: HTMLImageElement }
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
}

View file

@ -2,19 +2,6 @@ import { loadSprite } from './sprite'
import { Juego } from './main'
import { boxCollision } from './utils'
const larretaImg = document.getElementById("img-larreta") as HTMLImageElement
const inmobiliariaImg = document.getElementById("img-inmobiliaria") as HTMLImageElement
const veredaImg = document.getElementById("img-vereda") as HTMLImageElement
const fondoImg = document.getElementById("img-fondo") as HTMLImageElement
const jugadorxImg = document.getElementById("img-jugadorx") as HTMLImageElement
const semillaImg = document.getElementById("img-semilla") as HTMLImageElement
const arbolImg = document.getElementById("img-arbol") as HTMLImageElement
const jugadorxSprite = loadSprite(jugadorxImg, 133, 266, juego => juego.canvas.height / 4)
const larretaSprite = loadSprite(larretaImg, 800, 1069, juego => juego.canvas.height / 4)
const semillaSprite = loadSprite(semillaImg, 480, 640, juego => juego.canvas.height / 8)
const arbolSprite = loadSprite(arbolImg, 80, 150, juego => juego.canvas.height / 4)
const ENEMIES_NUM = 20
const ENEMY_SPEED = 40
const PLAYER_SPEED = 200
@ -75,14 +62,14 @@ export function update(juego: Juego<State>, dt: number) {
for (const enemy of juego.state.enemies) {
if (boxCollision({
x: seed.x,
y: getFloorY(juego) - semillaSprite.getHeight(juego),
width: semillaSprite.getWidth(juego),
height: semillaSprite.getHeight(juego),
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) - larretaSprite.getHeight(juego),
width: larretaSprite.getWidth(juego),
height: larretaSprite.getHeight(juego),
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)
@ -109,7 +96,7 @@ export function update(juego: Juego<State>, dt: number) {
}
}
juego.state.view.x = -juego.state.pos.x + juego.canvas.width / 2 - jugadorxSprite.getWidth(juego) / 2
juego.state.view.x = -juego.state.pos.x + juego.canvas.width / 2 - juego.sprites.jugadorx.getWidth(juego) / 2
}
function drawBackground(
@ -127,20 +114,20 @@ function drawBackground(
function drawJugadorx(juego: Juego<State>) {
const floorY = getFloorY(juego)
jugadorxSprite.draw(
juego.sprites.jugadorx.draw(
juego,
juego.state.pos.x + juego.state.view.x,
floorY - jugadorxSprite.getHeight(juego),
floorY - juego.sprites.jugadorx.getHeight(juego),
0,
juego.state.side === "left",
)
}
function drawTrees(juego: Juego<State>) {
const height = arbolSprite.getHeight(juego)
const height = juego.sprites.arbol.getHeight(juego)
const floorY = getFloorY(juego)
for (const tree of juego.state.trees) {
arbolSprite.draw(
juego.sprites.arbol.draw(
juego,
tree.x + juego.state.view.x,
floorY - height,
@ -148,10 +135,10 @@ function drawTrees(juego: Juego<State>) {
}
}
function drawEnemies(juego: Juego<State>) {
const height = larretaSprite.getHeight(juego)
const height = juego.sprites.larreta.getHeight(juego)
const floorY = getFloorY(juego)
for (const enemy of juego.state.enemies) {
larretaSprite.draw(
juego.sprites.larreta.draw(
juego,
enemy.x + juego.state.view.x,
floorY - height,
@ -160,10 +147,10 @@ function drawEnemies(juego: Juego<State>) {
}
function drawSeeds(juego: Juego<State>) {
const height = semillaSprite.getHeight(juego)
const height = juego.sprites.semilla.getHeight(juego)
const floorY = getFloorY(juego)
for (const seed of juego.state.seeds) {
semillaSprite.draw(
juego.sprites.semilla.draw(
juego,
seed.x + juego.state.view.x,
floorY - height,
@ -178,8 +165,8 @@ function getFloorY(juego: Juego<State>): number {
export function draw(juego: Juego<State>, timestamp: number) {
const { height } = juego.canvas
drawBackground(juego, 0, (height / 3) * 2, fondoImg)
drawBackground(juego, getFloorY(juego), height / 3, veredaImg)
drawBackground(juego, 0, (height / 3) * 2, juego.assets.fondo)
drawBackground(juego, getFloorY(juego), height / 3, juego.assets.vereda)
drawTrees(juego)
drawEnemies(juego)

View file

@ -2,6 +2,8 @@ import './style.css'
import * as welcome from "./welcome"
import * as jugando from "./jugando"
import { Assets, loadAssets } from './assets'
import { loadSprite, Sprite } from './sprite'
function update(juego: Juego<any>, dt: number) {
switch (juego.state.current) {
@ -38,21 +40,34 @@ export type State = welcome.State | jugando.State
export type Juego<T extends State> = {
canvas: HTMLCanvasElement
ctx: CanvasRenderingContext2D
assets: Assets
sprites: { [key in "jugadorx" | "larreta" | "semilla" | "arbol"]: Sprite }
mouse: { x: number; y: number, down: boolean }
keyboard: { keys: { [key: string]: boolean } }
state: T
}
function initJuego() {
async function initJuego() {
const canvas = document.querySelector<HTMLCanvasElement>("#juego")!
const ctx = canvas.getContext("2d")!
window.addEventListener("resize", () => resizeCanvas(canvas), false)
resizeCanvas(canvas)
const assets = await loadAssets()
const sprites = {
jugadorx: loadSprite(assets.jugadorx, 133, 266, juego => juego.canvas.height / 4),
larreta: loadSprite(assets.larreta, 800, 1069, juego => juego.canvas.height / 4),
semilla: loadSprite(assets.semilla, 480, 640, juego => juego.canvas.height / 8),
arbol: loadSprite(assets.arbol, 80, 150, juego => juego.canvas.height / 4),
}
let juego: Juego<welcome.State> = {
canvas,
ctx,
assets,
sprites,
mouse: { x: 0, y: 0, down: false },
keyboard: { keys: {} },
state: {

View file

@ -1,5 +1,13 @@
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;
width: number;
height: number;
}
// Sprites are image assets that have a grid of tiles to animate
export function loadSprite(
img: HTMLImageElement,
@ -7,8 +15,7 @@ export function loadSprite(
width: number, height: number,
// Calculates the size of the sprite when rendering
getHeight: (juego: Juego<any>) => number,
) {
): Sprite {
const aspect = width / height
const rowSize = Math.floor(img.width / width)
if (img.width / width !== rowSize) {

1
src/vite-env.d.ts vendored Normal file
View file

@ -0,0 +1 @@
/// <reference types="vite/client" />

View file

@ -2,14 +2,12 @@ import { posInBox } from './utils'
import { createJugandoState } from './jugando'
import { Juego } from './main'
const img = document.getElementById("img-boton-jugar") as HTMLImageElement
export type State = {
current: "welcome"
}
function startButton(juego: Juego<State>) {
const [width, height] = [img.width / 4, img.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,
@ -27,5 +25,5 @@ export function update(juego: Juego<State>, dt: number) {
export function draw(juego: Juego<State>, timestamp: number) {
const btn = startButton(juego)
juego.ctx.drawImage(img, btn.x, btn.y, btn.width, btn.height)
juego.ctx.drawImage(juego.assets.botonJugar, btn.x, btn.y, btn.width, btn.height)
}