mirror of
https://github.com/Xevion/Pac-Man.git
synced 2025-12-07 16:07:54 -06:00
Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9d5ca54234 | |||
| 2ae73c3c58 | |||
| adfa2cc737 | |||
| 7c937df002 | |||
| 9fb9c959a3 | |||
| 61ebc8f317 |
7
.gitignore
vendored
7
.gitignore
vendored
@@ -1,7 +1,6 @@
|
||||
/target
|
||||
/dist
|
||||
target/
|
||||
dist/
|
||||
emsdk/
|
||||
.idea
|
||||
*.dll
|
||||
rust-sdl2-emscripten/
|
||||
assets/site/build.css
|
||||
emsdk/
|
||||
|
||||
12
README.md
12
README.md
@@ -50,3 +50,15 @@ Built with SDL2 for cross-platform graphics and audio, this implementation can r
|
||||
- Online Scoreboard
|
||||
- WebAssembly build contains a special API key for communicating with server.
|
||||
- To prevent abuse, the server will only accept scores from the WebAssembly build.
|
||||
|
||||
## Build Notes
|
||||
|
||||
- Install `cargo-vcpkg` with `cargo install cargo-vcpkg`, then run `cargo vcpkg build` to build the requisite dependencies via vcpkg.
|
||||
- For the WASM build, you need to have the Emscripten SDK cloned; you can do so with `git clone https://github.com/emscripten-core/emsdk.git`
|
||||
- The first time you clone, you'll need to install the appropriate SDK version with `./emsdk install 3.1.43` and then activate it with `./emsdk activate 3.1.43`. On Windows, use `./emsdk/emsdk.ps1` instead.
|
||||
- You can then activate the Emscripten SDK with `source ./emsdk/emsdk_env.sh` or `./emsdk/emsdk_env.ps1` or `./emsdk/emsdk_env.bat` depending on your OS/terminal.
|
||||
- While using the `web.build.ts` is not technically required, it simplifies the build process and is very helpful.
|
||||
- It is intended to be run with `bun`, which you can acquire at [bun.sh](https://bun.sh/)
|
||||
- Tip: You can launch a fileserver with `python` or `caddy` to serve the files in the `dist` folder.
|
||||
- `python3 -m http.server 8080 -d dist`
|
||||
- `caddy file-server --root dist` (install with `[sudo apt|brew|choco] install caddy` or [a dozen other ways](https://caddyserver.com/docs/install))
|
||||
|
||||
@@ -2,12 +2,25 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Pac-Man Arcade</title>
|
||||
<title>Pac-Man in Rust</title>
|
||||
<link rel="stylesheet" href="build.css" />
|
||||
<style>
|
||||
/* Minimal fallback to prevent white flash and canvas pop-in before CSS loads */
|
||||
html,
|
||||
body {
|
||||
background: #000;
|
||||
color: #facc15;
|
||||
margin: 0;
|
||||
text-align: center;
|
||||
}
|
||||
#canvas {
|
||||
display: block;
|
||||
margin: 1.5rem auto;
|
||||
background: #000;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body class="bg-black text-yellow-400 text-center">
|
||||
<body class="bg-black text-yellow-400 text-center min-h-screen">
|
||||
<a
|
||||
href="https://github.com/Xevion/Pac-Man"
|
||||
class="absolute top-0 right-0"
|
||||
@@ -17,7 +30,7 @@
|
||||
width="80"
|
||||
height="80"
|
||||
viewBox="0 0 250 250"
|
||||
class="fill-yellow-400 text-black"
|
||||
class="fill-yellow-400 text-white"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path>
|
||||
@@ -31,33 +44,54 @@
|
||||
></path>
|
||||
</svg>
|
||||
</a>
|
||||
<h1 class="text-4xl mt-10 scaled-text">Pac-Man Arcade</h1>
|
||||
<p class="text-lg mt-5 scaled-text">
|
||||
Welcome to the Pac-Man Arcade! Use the controls below to play.
|
||||
</p>
|
||||
<canvas
|
||||
id="canvas"
|
||||
class="block mx-auto mt-5"
|
||||
width="800"
|
||||
height="600"
|
||||
></canvas>
|
||||
<div class="mt-10">
|
||||
<span
|
||||
class="inline-block mx-2 px-4 py-2 bg-yellow-400 text-black rounded scaled-text"
|
||||
>← ↑ → ↓ Move</span
|
||||
>
|
||||
<span
|
||||
class="inline-block mx-2 px-4 py-2 bg-yellow-400 text-black rounded scaled-text"
|
||||
>Space Change Sprite</span
|
||||
>
|
||||
<span
|
||||
class="inline-block mx-2 px-4 py-2 bg-yellow-400 text-black rounded scaled-text"
|
||||
>Shift + ↑↓ Change Volume</span
|
||||
>
|
||||
|
||||
<div class="min-h-screen flex flex-col">
|
||||
<header class="pt-10">
|
||||
<h1 class="text-4xl arcade-title scaled-text">Pac-Man in Rust</h1>
|
||||
</header>
|
||||
|
||||
<main class="flex-1 flex items-center justify-center px-4">
|
||||
<div class="w-full max-w-5xl">
|
||||
<canvas
|
||||
id="canvas"
|
||||
class="block mx-auto bg-black w-full max-w-[90vw] h-auto mt-5 rounded-xl shadow-[inset_0_0_0_2px_rgba(255,255,255,0.12),0_10px_30px_rgba(0,0,0,0.8)]"
|
||||
></canvas>
|
||||
|
||||
<div
|
||||
class="mt-8 flex flex-wrap gap-3 justify-center items-center text-sm"
|
||||
>
|
||||
<span class="code">← ↑ → ↓</span>
|
||||
<span class="opacity-70">Move</span>
|
||||
|
||||
<span class="mx-2 opacity-30">|</span>
|
||||
|
||||
<span class="code">Space</span>
|
||||
<span class="opacity-70">Toggle Debug</span>
|
||||
|
||||
<span class="mx-2 opacity-30">|</span>
|
||||
|
||||
<span class="code">P</span>
|
||||
<span class="opacity-70">Pause / Unpause</span>
|
||||
|
||||
<span class="mx-2 opacity-30">|</span>
|
||||
|
||||
<span class="code">M</span>
|
||||
<span class="opacity-70">Mute / Unmute</span>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
<script type="text/javascript">
|
||||
const canvas = document.getElementById("canvas");
|
||||
var Module = {
|
||||
canvas: document.getElementById("canvas"),
|
||||
canvas: canvas,
|
||||
preRun: [
|
||||
() => {
|
||||
[...canvas.classList]
|
||||
.filter((className) => className.includes("shadow-"))
|
||||
.forEach((className) => canvas.classList.remove(className));
|
||||
},
|
||||
],
|
||||
};
|
||||
</script>
|
||||
<script type="text/javascript" src="pacman.js"></script>
|
||||
|
||||
28
assets/site/styles.css
Normal file
28
assets/site/styles.css
Normal file
@@ -0,0 +1,28 @@
|
||||
@import "tailwindcss";
|
||||
|
||||
@font-face {
|
||||
font-family: "TerminalVector";
|
||||
src: url("TerminalVector.ttf");
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
/* Key badge styling */
|
||||
.code {
|
||||
@apply px-3 py-1 rounded-md font-mono text-[0.9em] lowercase inline-block align-middle;
|
||||
background: rgba(250, 204, 21, 0.08); /* yellow-400 at low opacity */
|
||||
border: 1px solid rgba(250, 204, 21, 0.25);
|
||||
color: #fde68a; /* lighter yellow for readability */
|
||||
font-family: "TerminalVector", ui-monospace, Consolas, "Courier New",
|
||||
monospace;
|
||||
}
|
||||
|
||||
/* Title styling */
|
||||
.arcade-title {
|
||||
font-family: "TerminalVector", ui-monospace, Consolas, "Courier New",
|
||||
monospace;
|
||||
letter-spacing: 0.08em;
|
||||
text-shadow: 0 0 18px rgba(250, 204, 21, 0.15),
|
||||
0 0 2px rgba(255, 255, 255, 0.25);
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
@font-face {
|
||||
font-family: "Liberation Mono";
|
||||
src:
|
||||
url("LiberationMono.woff2") format("woff2"),
|
||||
url("LiberationMono.woff") format("woff");
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
canvas {
|
||||
@apply w-full h-[65vh] min-h-[200px] block mx-auto bg-black;
|
||||
}
|
||||
|
||||
.code {
|
||||
@apply px-1 rounded font-mono bg-zinc-900 border border-zinc-700 lowercase;
|
||||
}
|
||||
@@ -92,6 +92,8 @@ impl App<'_> {
|
||||
}
|
||||
_ => {}
|
||||
},
|
||||
// It doesn't really make sense to have this available in the browser
|
||||
#[cfg(not(target_os = "emscripten"))]
|
||||
Event::Quit { .. }
|
||||
| Event::KeyDown {
|
||||
keycode: Some(Keycode::Escape) | Some(Keycode::Q),
|
||||
|
||||
@@ -5,6 +5,16 @@ use super::direction::Direction;
|
||||
/// A unique identifier for a node, represented by its index in the graph's storage.
|
||||
pub type NodeId = usize;
|
||||
|
||||
/// Defines who can traverse a given edge.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
|
||||
pub enum EdgePermissions {
|
||||
/// Anyone can use this edge.
|
||||
#[default]
|
||||
All,
|
||||
/// Only ghosts can use this edge.
|
||||
GhostsOnly,
|
||||
}
|
||||
|
||||
/// Represents a directed edge from one node to another with a given weight (e.g., distance).
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct Edge {
|
||||
@@ -14,6 +24,8 @@ pub struct Edge {
|
||||
pub distance: f32,
|
||||
/// The cardinal direction of this edge.
|
||||
pub direction: Direction,
|
||||
/// Defines who is allowed to traverse this edge.
|
||||
pub permissions: EdgePermissions,
|
||||
}
|
||||
|
||||
/// Represents a node in the graph, defined by its position.
|
||||
@@ -121,8 +133,8 @@ impl Graph {
|
||||
return Err("To node does not exist.");
|
||||
}
|
||||
|
||||
let edge_a = self.add_edge(from, to, replace, distance, direction);
|
||||
let edge_b = self.add_edge(to, from, replace, distance, direction.opposite());
|
||||
let edge_a = self.add_edge(from, to, replace, distance, direction, EdgePermissions::default());
|
||||
let edge_b = self.add_edge(to, from, replace, distance, direction.opposite(), EdgePermissions::default());
|
||||
|
||||
if edge_a.is_err() && edge_b.is_err() {
|
||||
return Err("Failed to connect nodes in both directions.");
|
||||
@@ -150,6 +162,7 @@ impl Graph {
|
||||
replace: bool,
|
||||
distance: Option<f32>,
|
||||
direction: Direction,
|
||||
permissions: EdgePermissions,
|
||||
) -> Result<(), &'static str> {
|
||||
let edge = Edge {
|
||||
target: to,
|
||||
@@ -168,6 +181,7 @@ impl Graph {
|
||||
}
|
||||
},
|
||||
direction,
|
||||
permissions,
|
||||
};
|
||||
|
||||
if from >= self.adjacency_list.len() {
|
||||
@@ -295,7 +309,10 @@ impl Traverser {
|
||||
/// Creates a new traverser starting at the given node ID.
|
||||
///
|
||||
/// The traverser will immediately attempt to start moving in the initial direction.
|
||||
pub fn new(graph: &Graph, start_node: NodeId, initial_direction: Direction) -> Self {
|
||||
pub fn new<F>(graph: &Graph, start_node: NodeId, initial_direction: Direction, can_traverse: &F) -> Self
|
||||
where
|
||||
F: Fn(Edge) -> bool,
|
||||
{
|
||||
let mut traverser = Traverser {
|
||||
position: Position::AtNode(start_node),
|
||||
direction: initial_direction,
|
||||
@@ -303,7 +320,7 @@ impl Traverser {
|
||||
};
|
||||
|
||||
// This will kickstart the traverser into motion
|
||||
traverser.advance(graph, 0.0);
|
||||
traverser.advance(graph, 0.0, can_traverse);
|
||||
|
||||
traverser
|
||||
}
|
||||
@@ -329,7 +346,10 @@ impl Traverser {
|
||||
/// - If it reaches a node, it attempts to transition to a new edge based on
|
||||
/// the buffered direction or by continuing straight.
|
||||
/// - If no valid move is possible, it stops at the node.
|
||||
pub fn advance(&mut self, graph: &Graph, distance: f32) {
|
||||
pub fn advance<F>(&mut self, graph: &Graph, distance: f32, can_traverse: &F)
|
||||
where
|
||||
F: Fn(Edge) -> bool,
|
||||
{
|
||||
// Decrement the remaining frames for the next direction
|
||||
if let Some((direction, remaining)) = self.next_direction {
|
||||
if remaining > 0 {
|
||||
@@ -344,13 +364,15 @@ impl Traverser {
|
||||
// We're not moving, but a buffered direction is available.
|
||||
if let Some((next_direction, _)) = self.next_direction {
|
||||
if let Some(edge) = graph.find_edge_in_direction(node_id, next_direction) {
|
||||
// Start moving in that direction
|
||||
self.position = Position::BetweenNodes {
|
||||
from: node_id,
|
||||
to: edge.target,
|
||||
traversed: distance.max(0.0),
|
||||
};
|
||||
self.direction = next_direction;
|
||||
if can_traverse(edge) {
|
||||
// Start moving in that direction
|
||||
self.position = Position::BetweenNodes {
|
||||
from: node_id,
|
||||
to: edge.target,
|
||||
traversed: distance.max(0.0),
|
||||
};
|
||||
self.direction = next_direction;
|
||||
}
|
||||
}
|
||||
|
||||
self.next_direction = None; // Consume the buffered direction regardless of whether we started moving with it
|
||||
@@ -382,26 +404,33 @@ impl Traverser {
|
||||
// If we buffered a direction, try to find an edge in that direction
|
||||
if let Some((next_dir, _)) = self.next_direction {
|
||||
if let Some(edge) = graph.find_edge_in_direction(to, next_dir) {
|
||||
self.position = Position::BetweenNodes {
|
||||
from: to,
|
||||
to: edge.target,
|
||||
traversed: overflow,
|
||||
};
|
||||
if can_traverse(edge) {
|
||||
self.position = Position::BetweenNodes {
|
||||
from: to,
|
||||
to: edge.target,
|
||||
traversed: overflow,
|
||||
};
|
||||
|
||||
self.direction = next_dir; // Remember our new direction
|
||||
self.next_direction = None; // Consume the buffered direction
|
||||
moved = true;
|
||||
self.direction = next_dir; // Remember our new direction
|
||||
self.next_direction = None; // Consume the buffered direction
|
||||
moved = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If we didn't move, try to continue in the current direction
|
||||
if !moved {
|
||||
if let Some(edge) = graph.find_edge_in_direction(to, self.direction) {
|
||||
self.position = Position::BetweenNodes {
|
||||
from: to,
|
||||
to: edge.target,
|
||||
traversed: overflow,
|
||||
};
|
||||
if can_traverse(edge) {
|
||||
self.position = Position::BetweenNodes {
|
||||
from: to,
|
||||
to: edge.target,
|
||||
traversed: overflow,
|
||||
};
|
||||
} else {
|
||||
self.position = Position::AtNode(to);
|
||||
self.next_direction = None;
|
||||
}
|
||||
} else {
|
||||
self.position = Position::AtNode(to);
|
||||
self.next_direction = None;
|
||||
@@ -577,6 +606,7 @@ mod tests {
|
||||
target: 1,
|
||||
distance: 10.0,
|
||||
direction: Direction::Up,
|
||||
permissions: EdgePermissions::All,
|
||||
},
|
||||
);
|
||||
intersection.set(
|
||||
@@ -585,6 +615,7 @@ mod tests {
|
||||
target: 2,
|
||||
distance: 15.0,
|
||||
direction: Direction::Right,
|
||||
permissions: EdgePermissions::All,
|
||||
},
|
||||
);
|
||||
|
||||
@@ -607,6 +638,7 @@ mod tests {
|
||||
target: 1,
|
||||
distance: 10.0,
|
||||
direction: Direction::Up,
|
||||
permissions: EdgePermissions::All,
|
||||
};
|
||||
intersection.set(Direction::Up, edge);
|
||||
|
||||
@@ -624,6 +656,7 @@ mod tests {
|
||||
target: 1,
|
||||
distance: 10.0,
|
||||
direction: Direction::Left,
|
||||
permissions: EdgePermissions::All,
|
||||
};
|
||||
|
||||
intersection.set(Direction::Left, edge);
|
||||
@@ -687,7 +720,7 @@ mod tests {
|
||||
#[test]
|
||||
fn test_traverser_new() {
|
||||
let graph = create_test_graph();
|
||||
let traverser = Traverser::new(&graph, 0, Direction::Left);
|
||||
let traverser = Traverser::new(&graph, 0, Direction::Left, &|_| true);
|
||||
|
||||
assert_eq!(traverser.direction, Direction::Left);
|
||||
// The next_direction might be consumed immediately when the traverser starts moving
|
||||
@@ -698,7 +731,7 @@ mod tests {
|
||||
#[test]
|
||||
fn test_traverser_set_next_direction() {
|
||||
let graph = create_test_graph();
|
||||
let mut traverser = Traverser::new(&graph, 0, Direction::Left);
|
||||
let mut traverser = Traverser::new(&graph, 0, Direction::Left, &|_| true);
|
||||
|
||||
traverser.set_next_direction(Direction::Up);
|
||||
assert!(traverser.next_direction.is_some());
|
||||
@@ -712,10 +745,10 @@ mod tests {
|
||||
#[test]
|
||||
fn test_traverser_advance_at_node() {
|
||||
let graph = create_test_graph();
|
||||
let mut traverser = Traverser::new(&graph, 0, Direction::Right);
|
||||
let mut traverser = Traverser::new(&graph, 0, Direction::Right, &|_| true);
|
||||
|
||||
// Should start moving in the initial direction
|
||||
traverser.advance(&graph, 5.0);
|
||||
traverser.advance(&graph, 5.0, &|_| true);
|
||||
|
||||
match traverser.position {
|
||||
Position::BetweenNodes { from, to, traversed } => {
|
||||
@@ -730,13 +763,13 @@ mod tests {
|
||||
#[test]
|
||||
fn test_traverser_advance_between_nodes() {
|
||||
let graph = create_test_graph();
|
||||
let mut traverser = Traverser::new(&graph, 0, Direction::Right);
|
||||
let mut traverser = Traverser::new(&graph, 0, Direction::Right, &|_| true);
|
||||
|
||||
// Move to between nodes
|
||||
traverser.advance(&graph, 5.0);
|
||||
traverser.advance(&graph, 5.0, &|_| true);
|
||||
|
||||
// Advance further
|
||||
traverser.advance(&graph, 3.0);
|
||||
traverser.advance(&graph, 3.0, &|_| true);
|
||||
|
||||
match traverser.position {
|
||||
Position::BetweenNodes { from, to, traversed } => {
|
||||
@@ -754,6 +787,7 @@ mod tests {
|
||||
target: 5,
|
||||
distance: 10.5,
|
||||
direction: Direction::Up,
|
||||
permissions: EdgePermissions::All,
|
||||
};
|
||||
|
||||
assert_eq!(edge.target, 5);
|
||||
|
||||
@@ -2,7 +2,7 @@ use glam::{UVec2, Vec2};
|
||||
|
||||
use crate::constants::BOARD_PIXEL_OFFSET;
|
||||
use crate::entity::direction::Direction;
|
||||
use crate::entity::graph::{Graph, NodeId, Position, Traverser};
|
||||
use crate::entity::graph::{Edge, EdgePermissions, Graph, NodeId, Position, Traverser};
|
||||
use crate::helpers::centered_with_size;
|
||||
use crate::texture::animated::AnimatedTexture;
|
||||
use crate::texture::directional::DirectionalAnimatedTexture;
|
||||
@@ -11,6 +11,10 @@ use sdl2::keyboard::Keycode;
|
||||
use sdl2::render::{Canvas, RenderTarget};
|
||||
use std::collections::HashMap;
|
||||
|
||||
fn can_pacman_traverse(edge: Edge) -> bool {
|
||||
matches!(edge.permissions, EdgePermissions::All)
|
||||
}
|
||||
|
||||
pub struct Pacman {
|
||||
pub traverser: Traverser,
|
||||
texture: DirectionalAnimatedTexture,
|
||||
@@ -47,13 +51,13 @@ impl Pacman {
|
||||
}
|
||||
|
||||
Self {
|
||||
traverser: Traverser::new(graph, start_node, Direction::Left),
|
||||
traverser: Traverser::new(graph, start_node, Direction::Left, &can_pacman_traverse),
|
||||
texture: DirectionalAnimatedTexture::new(textures, stopped_textures),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn tick(&mut self, dt: f32, graph: &Graph) {
|
||||
self.traverser.advance(graph, dt * 60.0 * 1.125);
|
||||
self.traverser.advance(graph, dt * 60.0 * 1.125, &can_pacman_traverse);
|
||||
self.texture.tick(dt);
|
||||
}
|
||||
|
||||
@@ -281,7 +285,7 @@ mod tests {
|
||||
let mut pacman = Pacman::new(&graph, 0, &atlas);
|
||||
|
||||
// Move pacman between nodes - need to advance with a larger distance to ensure movement
|
||||
pacman.traverser.advance(&graph, 5.0); // Larger advance to ensure movement
|
||||
pacman.traverser.advance(&graph, 5.0, &can_pacman_traverse); // Larger advance to ensure movement
|
||||
|
||||
let pos = pacman.get_pixel_pos(&graph);
|
||||
// Should be between (0,0) and (16,0), but not exactly at (8,0) due to advance distance
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
use crate::constants::{MapTile, BOARD_CELL_SIZE, CELL_SIZE};
|
||||
use crate::entity::direction::{Direction, DIRECTIONS};
|
||||
use crate::entity::graph::{Graph, Node, NodeId};
|
||||
use crate::entity::graph::{EdgePermissions, Graph, Node, NodeId};
|
||||
use crate::map::parser::MapTileParser;
|
||||
use crate::map::render::MapRenderer;
|
||||
use crate::texture::sprite::{AtlasTile, SpriteAtlas};
|
||||
@@ -259,10 +259,29 @@ impl Map {
|
||||
// Create the center line
|
||||
let (center_center_node_id, center_top_node_id) = create_house_line(graph, center_line_center_position);
|
||||
|
||||
// Connect the house entrance to the top line
|
||||
// Create a ghost-only, two-way connection for the house door.
|
||||
// This prevents Pac-Man from entering or exiting through the door.
|
||||
graph
|
||||
.connect(house_entrance_node_id, center_top_node_id, false, None, Direction::Down)
|
||||
.expect("Failed to connect house entrance to top line");
|
||||
.add_edge(
|
||||
house_entrance_node_id,
|
||||
center_top_node_id,
|
||||
false,
|
||||
None,
|
||||
Direction::Down,
|
||||
EdgePermissions::GhostsOnly,
|
||||
)
|
||||
.expect("Failed to create ghost-only entrance to house");
|
||||
|
||||
graph
|
||||
.add_edge(
|
||||
center_top_node_id,
|
||||
house_entrance_node_id,
|
||||
false,
|
||||
None,
|
||||
Direction::Up,
|
||||
EdgePermissions::GhostsOnly,
|
||||
)
|
||||
.expect("Failed to create ghost-only exit from house");
|
||||
|
||||
// Create the left line
|
||||
let (left_center_node_id, _) = create_house_line(
|
||||
|
||||
21
web.build.ts
21
web.build.ts
@@ -43,7 +43,7 @@ async function build(release: boolean, env: Record<string, string>) {
|
||||
}`.env(env);
|
||||
|
||||
log("Generating CSS");
|
||||
await $`pnpx postcss-cli ./assets/site/styles.scss -o ./assets/site/build.css`;
|
||||
await $`npx @tailwindcss/cli -i ./assets/site/styles.css -o ./assets/site/build.css`;
|
||||
|
||||
const buildType = release ? "release" : "debug";
|
||||
const siteFolder = resolve("assets/site");
|
||||
@@ -52,11 +52,13 @@ async function build(release: boolean, env: Record<string, string>) {
|
||||
|
||||
// The files to copy into 'dist'
|
||||
const files = [
|
||||
...["index.html", "favicon.ico", "build.css"].map((file) => ({
|
||||
src: join(siteFolder, file),
|
||||
dest: join(dist, file),
|
||||
optional: false,
|
||||
})),
|
||||
...["index.html", "favicon.ico", "build.css", "TerminalVector.ttf"].map(
|
||||
(file) => ({
|
||||
src: join(siteFolder, file),
|
||||
dest: join(dist, file),
|
||||
optional: false,
|
||||
})
|
||||
),
|
||||
...["pacman.wasm", "pacman.js", "deps/pacman.data"].map((file) => ({
|
||||
src: join(outputFolder, file),
|
||||
dest: join(dist, file.split("/").pop() || file),
|
||||
@@ -184,6 +186,13 @@ async function main() {
|
||||
|
||||
const release = process.env.RELEASE !== "0";
|
||||
const emsdkDir = resolve("./emsdk");
|
||||
// Ensure the emsdk directory exists before attempting to activate or use it
|
||||
if (!(await fs.exists(emsdkDir))) {
|
||||
log(
|
||||
`Emscripten SDK directory not found at ${emsdkDir}. Please install or clone 'emsdk' and try again.`
|
||||
);
|
||||
process.exit(1);
|
||||
}
|
||||
const vars = match(await activateEmsdk(emsdkDir)) // result handling
|
||||
.with({ vars: P.select() }, (vars) => vars)
|
||||
.with({ err: P.any }, ({ err }) => {
|
||||
|
||||
Reference in New Issue
Block a user