salva-la-costanera/src/jugando.ts

258 lines
6.6 KiB
TypeScript
Raw Normal View History

2021-06-30 23:16:45 +00:00
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;
2021-06-28 18:01:45 +00:00
export type State = {
2021-06-30 23:16:45 +00:00
current: "jugando";
pos: { x: number };
view: { x: number };
side: "left" | "right";
2021-07-01 20:45:37 +00:00
enemies: { x: number; sprite: Sprite }[];
2021-06-30 23:16:45 +00:00
seeds: { x: number; velocity: { x: number } }[];
trees: { x: number; sprite: Sprite }[];
time: number;
seedCooldown: number;
};
2021-06-28 18:01:45 +00:00
export function createJugandoState(): State {
2021-06-30 23:16:45 +00:00
return {
current: "jugando",
pos: { x: MAP_MIN + MAP_SIZE / 2 },
view: { x: 0 },
side: "right",
enemies: [],
seeds: [],
trees: [],
time: TIME,
seedCooldown: 0,
};
2021-06-28 18:01:45 +00:00
}
export function update(juego: Juego<State>, dt: number) {
2021-06-30 23:16:45 +00:00
juego.state.time -= dt;
if (juego.state.time < 0) {
(juego as Juego<any>).state = { current: "lose" };
return;
}
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;
}
if (juego.keyboard.keys.a || juego.keyboard.keys.ArrowLeft) {
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;
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;
}
for (const seed of juego.state.seeds) {
seed.x += (dt / 1000) * seed.velocity.x;
seed.velocity.x *= 0.97;
for (const enemy of juego.state.enemies) {
2021-06-30 23:16:45 +00:00
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.trees.push({
x: enemy.x,
sprite: randomFromArray([juego.sprites.arbol1, juego.sprites.arbol2]),
});
}
}
2021-06-30 23:16:45 +00:00
if (Math.abs(seed.velocity.x) < 100)
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;
}
while (juego.state.enemies.length < ENEMIES_NUM) {
const x = Math.random() * MAP_SIZE + MAP_MIN;
// Don't spawn enemies too close
if (Math.abs(juego.state.pos.x - x) < 300) continue;
2021-07-01 20:45:37 +00:00
juego.state.enemies.push({
x,
sprite: randomFromArray([
juego.sprites.larreta,
juego.sprites.millonarioMalo,
]),
});
2021-06-30 23:16:45 +00:00
}
for (const enemy of juego.state.enemies) {
const distance = enemy.x - juego.state.pos.x;
if (distance < 0) {
enemy.x += (dt / 1000) * enemySpeed;
} else {
enemy.x -= (dt / 1000) * enemySpeed;
}
}
2021-06-30 23:16:45 +00:00
juego.state.view.x =
-juego.state.pos.x +
juego.canvas.width / 2 -
juego.sprites.jugadorx.getWidth(juego) / 2;
2021-06-28 18:01:45 +00:00
}
2021-06-28 19:02:12 +00:00
function drawJugadorx(juego: Juego<State>) {
2021-06-30 23:16:45 +00:00
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"
);
2021-06-28 18:01:45 +00:00
}
2021-06-28 19:35:49 +00:00
function drawTrees(juego: Juego<State>) {
2021-06-30 23:16:45 +00:00
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);
}
2021-06-28 19:35:49 +00:00
}
2021-06-28 19:02:12 +00:00
function drawEnemies(juego: Juego<State>) {
2021-06-30 23:16:45 +00:00
const floorY = getFloorY(juego);
for (const enemy of juego.state.enemies) {
2021-07-01 20:45:37 +00:00
const height = enemy.sprite.getHeight(juego);
enemy.sprite.draw(juego, enemy.x + juego.state.view.x, floorY - height);
2021-06-30 23:16:45 +00:00
}
2021-06-28 18:01:45 +00:00
}
2021-06-28 19:02:12 +00:00
function drawSeeds(juego: Juego<State>) {
2021-06-30 23:16:45 +00:00
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
);
}
2021-06-28 19:02:12 +00:00
}
function getFloorY(juego: Juego<State>): number {
2021-06-30 23:16:45 +00:00
return (juego.canvas.height * 65) / 96;
2021-06-28 19:02:12 +00:00
}
function drawBackground(
2021-06-30 23:16:45 +00:00
juego: Juego<State>,
y: number,
height: number,
img: HTMLImageElement,
sourceBox?: Box
) {
2021-06-30 23:16:45 +00:00
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
);
} else {
juego.ctx.drawImage(
img,
i * (width - 1) + juego.state.view.x,
y,
width,
height
);
}
2021-06-30 23:16:45 +00:00
}
}
2021-06-28 18:01:45 +00:00
export function draw(juego: Juego<State>, timestamp: number) {
2021-06-30 23:16:45 +00:00
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);
drawJugadorx(juego);
drawSeeds(juego);
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}`,
{ x: juego.canvas.width - 10, y: 10 },
{ bold: true, align: "right" }
);
const tiempoBox = drawText(
juego,
`Tiempo restante`,
{ x: 10, y: 10 },
{ bold: false, align: "left" }
);
juego.ctx.fillRect(
10,
tiempoBox.y + tiempoBox.height,
(juego.canvas.width - arbolesBox.width - 20) * (juego.state.time / TIME),
30
);
2021-06-28 18:01:45 +00:00
}