mirror of
https://github.com/He4eT/DotDashPit.git
synced 2026-05-05 01:47:22 +00:00
game: add types
This commit is contained in:
parent
beac3b50c0
commit
ed8f297c7d
1 changed files with 108 additions and 53 deletions
143
game.js
143
game.js
|
|
@ -6,50 +6,100 @@
|
||||||
// version: 0.1
|
// version: 0.1
|
||||||
// script: js
|
// script: js
|
||||||
|
|
||||||
// api: https://github.com/nesbox/TIC-80/wiki/API
|
|
||||||
|
|
||||||
function TIC() {
|
function TIC() {
|
||||||
gameStages[currentStage]()
|
gameStages[currentStage]()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stages
|
/* Stages */
|
||||||
|
|
||||||
|
/** @type Record<string, () => void> */
|
||||||
const gameStages = {
|
const gameStages = {
|
||||||
mainMenu,
|
mainMenu,
|
||||||
gameover,
|
gameover,
|
||||||
gameplay,
|
gameplay,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @type {keyof typeof gameStages} */
|
||||||
let currentStage = 'mainMenu'
|
let currentStage = 'mainMenu'
|
||||||
|
|
||||||
// State
|
/* State */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {{ x: number, y: number }} Point
|
||||||
|
*
|
||||||
|
* @typedef {{
|
||||||
|
* top: number,
|
||||||
|
* right: number,
|
||||||
|
* bottom: number,
|
||||||
|
* left: number,
|
||||||
|
* }} Bounds
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {{
|
||||||
|
* screenPosition: Point,
|
||||||
|
* bounds: Bounds,
|
||||||
|
* spriteHalfSize: number,
|
||||||
|
* }} Arena
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @type {Arena} */
|
||||||
let arena = {
|
let arena = {
|
||||||
// Screen position
|
screenPosition: {
|
||||||
x: 7,
|
x: 7,
|
||||||
y: 7,
|
y: 7,
|
||||||
// Bounds
|
},
|
||||||
|
bounds: {
|
||||||
top: 0,
|
top: 0,
|
||||||
right: 225,
|
right: 225,
|
||||||
bottom: 89,
|
bottom: 89,
|
||||||
left: 0,
|
left: 0,
|
||||||
// Sprite size
|
},
|
||||||
spriteSize: 7,
|
|
||||||
spriteHalfSize: 3,
|
spriteHalfSize: 3,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {{
|
||||||
|
* sprite: number,
|
||||||
|
* speed: number,
|
||||||
|
* position: Point,
|
||||||
|
* }} Player
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @type {Player} */
|
||||||
let player = {
|
let player = {
|
||||||
sprite: 64,
|
sprite: 64,
|
||||||
speed: 1,
|
speed: 1,
|
||||||
|
position: {
|
||||||
x: 0,
|
x: 0,
|
||||||
y: 0,
|
y: 0,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {{
|
||||||
|
* type: 'zombie',
|
||||||
|
* dangerZone: number,
|
||||||
|
* positions: Point[],
|
||||||
|
* }} Enemy
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @type {Enemy[]} */
|
||||||
let enemies = []
|
let enemies = []
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {{
|
||||||
|
* type: 'laser' | 'nuke' | 'verticalLine' | 'horizontalLine' | 'detection',
|
||||||
|
* from: Point,
|
||||||
|
* to: Point,
|
||||||
|
* frames: number[],
|
||||||
|
* }} Effect
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @type {Effect[]} */
|
||||||
let effects = []
|
let effects = []
|
||||||
|
|
||||||
// Main Menu
|
/* Main Menu */
|
||||||
|
|
||||||
function mainMenu() {
|
function mainMenu() {
|
||||||
if ([BTN_A, BTN_B, BTN_X, BTN_Y].map(btn).some(Boolean)) {
|
if ([BTN_A, BTN_B, BTN_X, BTN_Y].map(btn).some(Boolean)) {
|
||||||
|
|
@ -65,7 +115,7 @@ function mainMenu() {
|
||||||
print(instruction, 12, 30, 4)
|
print(instruction, 12, 30, 4)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gameover
|
/* Gameover */
|
||||||
|
|
||||||
function gameover() {
|
function gameover() {
|
||||||
cls(0)
|
cls(0)
|
||||||
|
|
@ -77,7 +127,7 @@ function gameover() {
|
||||||
print(title, 12, 12, 10, false, 2)
|
print(title, 12, 12, 10, false, 2)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gameplay
|
/* Gameplay */
|
||||||
|
|
||||||
function gameplay() {
|
function gameplay() {
|
||||||
checkColisions()
|
checkColisions()
|
||||||
|
|
@ -86,7 +136,7 @@ function gameplay() {
|
||||||
handleMorse()
|
handleMorse()
|
||||||
|
|
||||||
spawn()
|
spawn()
|
||||||
// moveEnemies()
|
/* moveEnemies() */
|
||||||
|
|
||||||
drawInterface()
|
drawInterface()
|
||||||
drawArena()
|
drawArena()
|
||||||
|
|
@ -107,9 +157,16 @@ function handleMoves() {
|
||||||
if (btn(BTN_D)) dy += 1
|
if (btn(BTN_D)) dy += 1
|
||||||
|
|
||||||
const norm = player.speed / ([dx, dy].every((d) => d !== 0) ? Math.SQRT2 : 1)
|
const norm = player.speed / ([dx, dy].every((d) => d !== 0) ? Math.SQRT2 : 1)
|
||||||
|
const { bounds } = arena
|
||||||
|
|
||||||
player.x = Math.max(arena.left, Math.min(arena.right, player.x + dx * norm))
|
player.position.x = Math.max(
|
||||||
player.y = Math.max(arena.top, Math.min(arena.bottom, player.y + dy * norm))
|
bounds.left,
|
||||||
|
Math.min(bounds.right, player.position.x + dx * norm),
|
||||||
|
)
|
||||||
|
player.position.y = Math.max(
|
||||||
|
bounds.top,
|
||||||
|
Math.min(bounds.bottom, player.position.y + dy * norm),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleMorse() {
|
function handleMorse() {
|
||||||
|
|
@ -119,14 +176,8 @@ function handleMorse() {
|
||||||
if (enemies.length > 0) {
|
if (enemies.length > 0) {
|
||||||
effects.unshift({
|
effects.unshift({
|
||||||
type: 'laser',
|
type: 'laser',
|
||||||
from: {
|
from: player.position,
|
||||||
x: player.x,
|
to: enemies[0].positions[0],
|
||||||
y: player.y,
|
|
||||||
},
|
|
||||||
to: {
|
|
||||||
x: enemies[0].x[0],
|
|
||||||
y: enemies[0].y[0],
|
|
||||||
},
|
|
||||||
frames: [1, 2, 3, 4, 7, 7, 7, 6, 5, 4, 3, 2, 1],
|
frames: [1, 2, 3, 4, 7, 7, 7, 6, 5, 4, 3, 2, 1],
|
||||||
})
|
})
|
||||||
enemies.shift()
|
enemies.shift()
|
||||||
|
|
@ -135,14 +186,18 @@ function handleMorse() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enemies
|
/* Enemies */
|
||||||
|
|
||||||
function spawn() {
|
function spawn() {
|
||||||
if (enemies.length === 0) {
|
if (enemies.length === 0) {
|
||||||
enemies = [
|
enemies = [
|
||||||
{
|
{
|
||||||
x: [Math.random() * arena.right],
|
positions: [
|
||||||
y: [Math.random() * arena.bottom],
|
{
|
||||||
|
x: Math.random() * arena.bounds.right,
|
||||||
|
y: Math.random() * arena.bounds.bottom,
|
||||||
|
},
|
||||||
|
],
|
||||||
type: 'zombie',
|
type: 'zombie',
|
||||||
dangerZone: 8,
|
dangerZone: 8,
|
||||||
},
|
},
|
||||||
|
|
@ -152,10 +207,7 @@ function spawn() {
|
||||||
effects.unshift({
|
effects.unshift({
|
||||||
type: 'detection',
|
type: 'detection',
|
||||||
from: {},
|
from: {},
|
||||||
to: {
|
to: enemy.positions[0],
|
||||||
x: enemy.x[0],
|
|
||||||
y: enemy.y[0],
|
|
||||||
},
|
|
||||||
frames: Array(5).fill(4),
|
frames: Array(5).fill(4),
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
@ -167,7 +219,10 @@ function checkColisions() {
|
||||||
enemies
|
enemies
|
||||||
.map((enemy) => [
|
.map((enemy) => [
|
||||||
enemy,
|
enemy,
|
||||||
Math.hypot(player.x - enemy.x[0], player.y - enemy.y[0]),
|
Math.hypot(
|
||||||
|
player.position.x - enemy.positions[0].x,
|
||||||
|
player.position.y - enemy.positions[0].y,
|
||||||
|
),
|
||||||
])
|
])
|
||||||
.some(([enemy, distance]) => distance < enemy.dangerZone)
|
.some(([enemy, distance]) => distance < enemy.dangerZone)
|
||||||
) {
|
) {
|
||||||
|
|
@ -175,12 +230,12 @@ function checkColisions() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw
|
/* Draw */
|
||||||
|
|
||||||
function arenaToScreen({ x, y }) {
|
function arenaToScreen({ x, y }) {
|
||||||
return {
|
return {
|
||||||
x: x + arena.x,
|
x: x + arena.screenPosition.x,
|
||||||
y: y + arena.y,
|
y: y + arena.screenPosition.y,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -214,7 +269,7 @@ function drawFX() {
|
||||||
.forEach((effect) =>
|
.forEach((effect) =>
|
||||||
({
|
({
|
||||||
laser: ({ from, to, frames }) => {
|
laser: ({ from, to, frames }) => {
|
||||||
// [1, 2, 3, 4, 7, 7, 7, 6, 5, 4, 3, 2, 1]
|
/* [1, 2, 3, 4, 7, 7, 7, 6, 5, 4, 3, 2, 1] */
|
||||||
const color = frames.shift()
|
const color = frames.shift()
|
||||||
line(from.x, from.y, to.x, to.y, color)
|
line(from.x, from.y, to.x, to.y, color)
|
||||||
circ(from.x, from.y, frames.length / 3, color)
|
circ(from.x, from.y, frames.length / 3, color)
|
||||||
|
|
@ -222,22 +277,22 @@ function drawFX() {
|
||||||
circb(to.x, to.y, frames.length, color + 3)
|
circb(to.x, to.y, frames.length, color + 3)
|
||||||
},
|
},
|
||||||
nuke: ({ to, frames }) => {
|
nuke: ({ to, frames }) => {
|
||||||
// [6, 5, 4, 3, 2]
|
/* [6, 5, 4, 3, 2] */
|
||||||
const color = frames.shift()
|
const color = frames.shift()
|
||||||
circ(to.x, to.y, Math.pow(frames.length, 5), color)
|
circ(to.x, to.y, Math.pow(frames.length, 5), color)
|
||||||
},
|
},
|
||||||
verticalLine: ({ to, frames }) => {
|
verticalLine: ({ to, frames }) => {
|
||||||
// [4, 5, 6, 7, 7, 6, 5, 4]
|
/* [4, 5, 6, 7, 7, 6, 5, 4] */
|
||||||
const color = frames.shift()
|
const color = frames.shift()
|
||||||
rect(0, to.y - frames.length, SCREEN_W, frames.length * 2, color)
|
rect(0, to.y - frames.length, SCREEN_W, frames.length * 2, color)
|
||||||
},
|
},
|
||||||
horizontalLine: ({ to, frames }) => {
|
horizontalLine: ({ to, frames }) => {
|
||||||
// [4, 5, 6, 7, 7, 6, 5, 4]
|
/* [4, 5, 6, 7, 7, 6, 5, 4] */
|
||||||
const color = frames.shift()
|
const color = frames.shift()
|
||||||
rect(to.x - frames.length, 0, frames.length * 2, SCREEN_W, color)
|
rect(to.x - frames.length, 0, frames.length * 2, SCREEN_W, color)
|
||||||
},
|
},
|
||||||
detection: ({ to, frames }) => {
|
detection: ({ to, frames }) => {
|
||||||
// Array(5).fill(4)]
|
/* Array(5).fill(4)] */
|
||||||
const color = frames.shift()
|
const color = frames.shift()
|
||||||
const w = arena.spriteHalfSize
|
const w = arena.spriteHalfSize
|
||||||
const d = frames.length + 2 * w
|
const d = frames.length + 2 * w
|
||||||
|
|
@ -264,27 +319,27 @@ function drawFX() {
|
||||||
|
|
||||||
function drawEnemies() {
|
function drawEnemies() {
|
||||||
enemies
|
enemies
|
||||||
.map((enemy) => [80, enemy.x[0], enemy.y[0]])
|
.map((enemy) => [80, enemy.positions[0].x, enemy.positions[0].y])
|
||||||
.forEach((spriteData) => drawSprite(...spriteData))
|
.forEach((spriteData) => drawSprite(...spriteData))
|
||||||
}
|
}
|
||||||
|
|
||||||
function drawPlayer() {
|
function drawPlayer() {
|
||||||
drawSprite(player.sprite, player.x, player.y)
|
drawSprite(player.sprite, player.position.x, player.position.y)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Utils
|
/* Utils */
|
||||||
|
|
||||||
function rnd(from, to) {
|
function rnd(from, to) {
|
||||||
return Math.floor(Math.random() * (to - from + 1)) + from
|
return Math.floor(Math.random() * (to - from + 1)) + from
|
||||||
}
|
}
|
||||||
|
|
||||||
// Constants
|
/* Constants */
|
||||||
|
|
||||||
// Screen
|
/* Screen */
|
||||||
const SCREEN_W = 240
|
const SCREEN_W = 240
|
||||||
const SCREEN_H = 136
|
const SCREEN_H = 136
|
||||||
|
|
||||||
// Buttons
|
/* Buttons */
|
||||||
const [BTN_U, BTN_D, BTN_L, BTN_R, BTN_A, BTN_B, BTN_X, BTN_Y] = [
|
const [BTN_U, BTN_D, BTN_L, BTN_R, BTN_A, BTN_B, BTN_X, BTN_Y] = [
|
||||||
...Array(8).keys(),
|
...Array(8).keys(),
|
||||||
]
|
]
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue