mirror of
https://github.com/Xevion/Pac-Man.git
synced 2025-12-08 10:07:51 -06:00
Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 2ae73c3c58 | |||
| adfa2cc737 | |||
| 7c937df002 | |||
| 9fb9c959a3 | |||
| 61ebc8f317 |
10
.gitignore
vendored
10
.gitignore
vendored
@@ -1,7 +1,5 @@
|
|||||||
/target
|
target/
|
||||||
/dist
|
dist/
|
||||||
.idea
|
|
||||||
*.dll
|
|
||||||
rust-sdl2-emscripten/
|
|
||||||
assets/site/build.css
|
|
||||||
emsdk/
|
emsdk/
|
||||||
|
.idea
|
||||||
|
rust-sdl2-emscripten/
|
||||||
|
|||||||
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
|
- Online Scoreboard
|
||||||
- WebAssembly build contains a special API key for communicating with server.
|
- WebAssembly build contains a special API key for communicating with server.
|
||||||
- To prevent abuse, the server will only accept scores from the WebAssembly build.
|
- 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))
|
||||||
|
|||||||
@@ -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::Quit { .. }
|
||||||
| Event::KeyDown {
|
| Event::KeyDown {
|
||||||
keycode: Some(Keycode::Escape) | Some(Keycode::Q),
|
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.
|
/// A unique identifier for a node, represented by its index in the graph's storage.
|
||||||
pub type NodeId = usize;
|
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).
|
/// Represents a directed edge from one node to another with a given weight (e.g., distance).
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub struct Edge {
|
pub struct Edge {
|
||||||
@@ -14,6 +24,8 @@ pub struct Edge {
|
|||||||
pub distance: f32,
|
pub distance: f32,
|
||||||
/// The cardinal direction of this edge.
|
/// The cardinal direction of this edge.
|
||||||
pub direction: Direction,
|
pub direction: Direction,
|
||||||
|
/// Defines who is allowed to traverse this edge.
|
||||||
|
pub permissions: EdgePermissions,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Represents a node in the graph, defined by its position.
|
/// Represents a node in the graph, defined by its position.
|
||||||
@@ -121,8 +133,8 @@ impl Graph {
|
|||||||
return Err("To node does not exist.");
|
return Err("To node does not exist.");
|
||||||
}
|
}
|
||||||
|
|
||||||
let edge_a = self.add_edge(from, to, replace, distance, direction);
|
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());
|
let edge_b = self.add_edge(to, from, replace, distance, direction.opposite(), EdgePermissions::default());
|
||||||
|
|
||||||
if edge_a.is_err() && edge_b.is_err() {
|
if edge_a.is_err() && edge_b.is_err() {
|
||||||
return Err("Failed to connect nodes in both directions.");
|
return Err("Failed to connect nodes in both directions.");
|
||||||
@@ -150,6 +162,7 @@ impl Graph {
|
|||||||
replace: bool,
|
replace: bool,
|
||||||
distance: Option<f32>,
|
distance: Option<f32>,
|
||||||
direction: Direction,
|
direction: Direction,
|
||||||
|
permissions: EdgePermissions,
|
||||||
) -> Result<(), &'static str> {
|
) -> Result<(), &'static str> {
|
||||||
let edge = Edge {
|
let edge = Edge {
|
||||||
target: to,
|
target: to,
|
||||||
@@ -168,6 +181,7 @@ impl Graph {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
direction,
|
direction,
|
||||||
|
permissions,
|
||||||
};
|
};
|
||||||
|
|
||||||
if from >= self.adjacency_list.len() {
|
if from >= self.adjacency_list.len() {
|
||||||
@@ -295,7 +309,10 @@ impl Traverser {
|
|||||||
/// Creates a new traverser starting at the given node ID.
|
/// Creates a new traverser starting at the given node ID.
|
||||||
///
|
///
|
||||||
/// The traverser will immediately attempt to start moving in the initial direction.
|
/// 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 {
|
let mut traverser = Traverser {
|
||||||
position: Position::AtNode(start_node),
|
position: Position::AtNode(start_node),
|
||||||
direction: initial_direction,
|
direction: initial_direction,
|
||||||
@@ -303,7 +320,7 @@ impl Traverser {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// This will kickstart the traverser into motion
|
// This will kickstart the traverser into motion
|
||||||
traverser.advance(graph, 0.0);
|
traverser.advance(graph, 0.0, can_traverse);
|
||||||
|
|
||||||
traverser
|
traverser
|
||||||
}
|
}
|
||||||
@@ -329,7 +346,10 @@ impl Traverser {
|
|||||||
/// - If it reaches a node, it attempts to transition to a new edge based on
|
/// - If it reaches a node, it attempts to transition to a new edge based on
|
||||||
/// the buffered direction or by continuing straight.
|
/// the buffered direction or by continuing straight.
|
||||||
/// - If no valid move is possible, it stops at the node.
|
/// - 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
|
// Decrement the remaining frames for the next direction
|
||||||
if let Some((direction, remaining)) = self.next_direction {
|
if let Some((direction, remaining)) = self.next_direction {
|
||||||
if remaining > 0 {
|
if remaining > 0 {
|
||||||
@@ -344,13 +364,15 @@ impl Traverser {
|
|||||||
// We're not moving, but a buffered direction is available.
|
// We're not moving, but a buffered direction is available.
|
||||||
if let Some((next_direction, _)) = self.next_direction {
|
if let Some((next_direction, _)) = self.next_direction {
|
||||||
if let Some(edge) = graph.find_edge_in_direction(node_id, next_direction) {
|
if let Some(edge) = graph.find_edge_in_direction(node_id, next_direction) {
|
||||||
// Start moving in that direction
|
if can_traverse(edge) {
|
||||||
self.position = Position::BetweenNodes {
|
// Start moving in that direction
|
||||||
from: node_id,
|
self.position = Position::BetweenNodes {
|
||||||
to: edge.target,
|
from: node_id,
|
||||||
traversed: distance.max(0.0),
|
to: edge.target,
|
||||||
};
|
traversed: distance.max(0.0),
|
||||||
self.direction = next_direction;
|
};
|
||||||
|
self.direction = next_direction;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.next_direction = None; // Consume the buffered direction regardless of whether we started moving with it
|
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 we buffered a direction, try to find an edge in that direction
|
||||||
if let Some((next_dir, _)) = self.next_direction {
|
if let Some((next_dir, _)) = self.next_direction {
|
||||||
if let Some(edge) = graph.find_edge_in_direction(to, next_dir) {
|
if let Some(edge) = graph.find_edge_in_direction(to, next_dir) {
|
||||||
self.position = Position::BetweenNodes {
|
if can_traverse(edge) {
|
||||||
from: to,
|
self.position = Position::BetweenNodes {
|
||||||
to: edge.target,
|
from: to,
|
||||||
traversed: overflow,
|
to: edge.target,
|
||||||
};
|
traversed: overflow,
|
||||||
|
};
|
||||||
|
|
||||||
self.direction = next_dir; // Remember our new direction
|
self.direction = next_dir; // Remember our new direction
|
||||||
self.next_direction = None; // Consume the buffered direction
|
self.next_direction = None; // Consume the buffered direction
|
||||||
moved = true;
|
moved = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we didn't move, try to continue in the current direction
|
// If we didn't move, try to continue in the current direction
|
||||||
if !moved {
|
if !moved {
|
||||||
if let Some(edge) = graph.find_edge_in_direction(to, self.direction) {
|
if let Some(edge) = graph.find_edge_in_direction(to, self.direction) {
|
||||||
self.position = Position::BetweenNodes {
|
if can_traverse(edge) {
|
||||||
from: to,
|
self.position = Position::BetweenNodes {
|
||||||
to: edge.target,
|
from: to,
|
||||||
traversed: overflow,
|
to: edge.target,
|
||||||
};
|
traversed: overflow,
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
self.position = Position::AtNode(to);
|
||||||
|
self.next_direction = None;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
self.position = Position::AtNode(to);
|
self.position = Position::AtNode(to);
|
||||||
self.next_direction = None;
|
self.next_direction = None;
|
||||||
@@ -577,6 +606,7 @@ mod tests {
|
|||||||
target: 1,
|
target: 1,
|
||||||
distance: 10.0,
|
distance: 10.0,
|
||||||
direction: Direction::Up,
|
direction: Direction::Up,
|
||||||
|
permissions: EdgePermissions::All,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
intersection.set(
|
intersection.set(
|
||||||
@@ -585,6 +615,7 @@ mod tests {
|
|||||||
target: 2,
|
target: 2,
|
||||||
distance: 15.0,
|
distance: 15.0,
|
||||||
direction: Direction::Right,
|
direction: Direction::Right,
|
||||||
|
permissions: EdgePermissions::All,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -607,6 +638,7 @@ mod tests {
|
|||||||
target: 1,
|
target: 1,
|
||||||
distance: 10.0,
|
distance: 10.0,
|
||||||
direction: Direction::Up,
|
direction: Direction::Up,
|
||||||
|
permissions: EdgePermissions::All,
|
||||||
};
|
};
|
||||||
intersection.set(Direction::Up, edge);
|
intersection.set(Direction::Up, edge);
|
||||||
|
|
||||||
@@ -624,6 +656,7 @@ mod tests {
|
|||||||
target: 1,
|
target: 1,
|
||||||
distance: 10.0,
|
distance: 10.0,
|
||||||
direction: Direction::Left,
|
direction: Direction::Left,
|
||||||
|
permissions: EdgePermissions::All,
|
||||||
};
|
};
|
||||||
|
|
||||||
intersection.set(Direction::Left, edge);
|
intersection.set(Direction::Left, edge);
|
||||||
@@ -687,7 +720,7 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_traverser_new() {
|
fn test_traverser_new() {
|
||||||
let graph = create_test_graph();
|
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);
|
assert_eq!(traverser.direction, Direction::Left);
|
||||||
// The next_direction might be consumed immediately when the traverser starts moving
|
// The next_direction might be consumed immediately when the traverser starts moving
|
||||||
@@ -698,7 +731,7 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_traverser_set_next_direction() {
|
fn test_traverser_set_next_direction() {
|
||||||
let graph = create_test_graph();
|
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);
|
traverser.set_next_direction(Direction::Up);
|
||||||
assert!(traverser.next_direction.is_some());
|
assert!(traverser.next_direction.is_some());
|
||||||
@@ -712,10 +745,10 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_traverser_advance_at_node() {
|
fn test_traverser_advance_at_node() {
|
||||||
let graph = create_test_graph();
|
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
|
// Should start moving in the initial direction
|
||||||
traverser.advance(&graph, 5.0);
|
traverser.advance(&graph, 5.0, &|_| true);
|
||||||
|
|
||||||
match traverser.position {
|
match traverser.position {
|
||||||
Position::BetweenNodes { from, to, traversed } => {
|
Position::BetweenNodes { from, to, traversed } => {
|
||||||
@@ -730,13 +763,13 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_traverser_advance_between_nodes() {
|
fn test_traverser_advance_between_nodes() {
|
||||||
let graph = create_test_graph();
|
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
|
// Move to between nodes
|
||||||
traverser.advance(&graph, 5.0);
|
traverser.advance(&graph, 5.0, &|_| true);
|
||||||
|
|
||||||
// Advance further
|
// Advance further
|
||||||
traverser.advance(&graph, 3.0);
|
traverser.advance(&graph, 3.0, &|_| true);
|
||||||
|
|
||||||
match traverser.position {
|
match traverser.position {
|
||||||
Position::BetweenNodes { from, to, traversed } => {
|
Position::BetweenNodes { from, to, traversed } => {
|
||||||
@@ -754,6 +787,7 @@ mod tests {
|
|||||||
target: 5,
|
target: 5,
|
||||||
distance: 10.5,
|
distance: 10.5,
|
||||||
direction: Direction::Up,
|
direction: Direction::Up,
|
||||||
|
permissions: EdgePermissions::All,
|
||||||
};
|
};
|
||||||
|
|
||||||
assert_eq!(edge.target, 5);
|
assert_eq!(edge.target, 5);
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ use glam::{UVec2, Vec2};
|
|||||||
|
|
||||||
use crate::constants::BOARD_PIXEL_OFFSET;
|
use crate::constants::BOARD_PIXEL_OFFSET;
|
||||||
use crate::entity::direction::Direction;
|
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::helpers::centered_with_size;
|
||||||
use crate::texture::animated::AnimatedTexture;
|
use crate::texture::animated::AnimatedTexture;
|
||||||
use crate::texture::directional::DirectionalAnimatedTexture;
|
use crate::texture::directional::DirectionalAnimatedTexture;
|
||||||
@@ -11,6 +11,10 @@ use sdl2::keyboard::Keycode;
|
|||||||
use sdl2::render::{Canvas, RenderTarget};
|
use sdl2::render::{Canvas, RenderTarget};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
fn can_pacman_traverse(edge: Edge) -> bool {
|
||||||
|
matches!(edge.permissions, EdgePermissions::All)
|
||||||
|
}
|
||||||
|
|
||||||
pub struct Pacman {
|
pub struct Pacman {
|
||||||
pub traverser: Traverser,
|
pub traverser: Traverser,
|
||||||
texture: DirectionalAnimatedTexture,
|
texture: DirectionalAnimatedTexture,
|
||||||
@@ -47,13 +51,13 @@ impl Pacman {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Self {
|
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),
|
texture: DirectionalAnimatedTexture::new(textures, stopped_textures),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn tick(&mut self, dt: f32, graph: &Graph) {
|
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);
|
self.texture.tick(dt);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -281,7 +285,7 @@ mod tests {
|
|||||||
let mut pacman = Pacman::new(&graph, 0, &atlas);
|
let mut pacman = Pacman::new(&graph, 0, &atlas);
|
||||||
|
|
||||||
// Move pacman between nodes - need to advance with a larger distance to ensure movement
|
// 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);
|
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
|
// 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::constants::{MapTile, BOARD_CELL_SIZE, CELL_SIZE};
|
||||||
use crate::entity::direction::{Direction, DIRECTIONS};
|
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::parser::MapTileParser;
|
||||||
use crate::map::render::MapRenderer;
|
use crate::map::render::MapRenderer;
|
||||||
use crate::texture::sprite::{AtlasTile, SpriteAtlas};
|
use crate::texture::sprite::{AtlasTile, SpriteAtlas};
|
||||||
@@ -259,10 +259,29 @@ impl Map {
|
|||||||
// Create the center line
|
// Create the center line
|
||||||
let (center_center_node_id, center_top_node_id) = create_house_line(graph, center_line_center_position);
|
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
|
graph
|
||||||
.connect(house_entrance_node_id, center_top_node_id, false, None, Direction::Down)
|
.add_edge(
|
||||||
.expect("Failed to connect house entrance to top line");
|
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
|
// Create the left line
|
||||||
let (left_center_node_id, _) = create_house_line(
|
let (left_center_node_id, _) = create_house_line(
|
||||||
|
|||||||
@@ -184,6 +184,13 @@ async function main() {
|
|||||||
|
|
||||||
const release = process.env.RELEASE !== "0";
|
const release = process.env.RELEASE !== "0";
|
||||||
const emsdkDir = resolve("./emsdk");
|
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
|
const vars = match(await activateEmsdk(emsdkDir)) // result handling
|
||||||
.with({ vars: P.select() }, (vars) => vars)
|
.with({ vars: P.select() }, (vars) => vars)
|
||||||
.with({ err: P.any }, ({ err }) => {
|
.with({ err: P.any }, ({ err }) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user