screens cleanup
This commit is contained in:
155
README.md
155
README.md
@@ -1,141 +1,34 @@
|
||||
# P5.js-vite Starter Template 🚀
|
||||
# Untitled Maze Game - ID30011 Midterm Project README
|
||||
|
||||
[](https://opensource.org/licenses/MIT)
|
||||
- **Name:** Bumgyu Suh
|
||||
- **Student ID:** 20240905
|
||||
- **Student Email:** bumgyu@kaist.ac.kr
|
||||
- **Repository URL:** https://git.prototyping.id/20240905/???
|
||||
- **Video URL:** youtube.com
|
||||
|
||||
[Vite](https://vitejs.dev/) starter template to scaffold a new [p5.js](https://p5js.org) project.
|
||||
## The Game
|
||||
A description of the game - how it works and what the user has to do
|
||||
|
||||
This is an unopinionated template; aside from P5.js and Vite, the rest of your project's tools are entirely up to you.
|
||||
WASD, V to switch view
|
||||
|
||||
## Live demo
|
||||
## Code Documentation
|
||||
A description of the organization of your code. Feel free to use diagrams, UML, or others. What are the main functions/classes? If you used patterns, what did you use them for, and how do different parts of your code speak to each other?
|
||||
Highlight any issue you want us to know about or whether the code has any known bug. If there are special features you want us to know about, write them here
|
||||
|
||||
For a live demo please [visit this page](https://p5js-vite-demo.surge.sh).
|
||||
Acknowledge any help or resource you used
|
||||
Writing style might be considered in grading (not the grammar, but rather the clarity of your writing)
|
||||
Be visual so use images and tables
|
||||
Try to be complete in your explanation - you do not need to write a lot, but the professor and the TA should be able to understand your documentation and your code by reading this file.
|
||||
|
||||
## Installation
|
||||
## Help from AI
|
||||
I got help from AI in criticizing my original plan in structuring my code. For example, although I originally planned to have a single 2D array that stores both the "static" information (the generated maze), and the state of whether the chests have been open or not, but chatgpt suggested that separating these two (one static, one dynamically changing during gameplay) is better as it prevents everything being coupled to this array.
|
||||
It also suggested ot
|
||||
|
||||
Pull the template files with [degit](https://github.com/Rich-Harris/degit) and install dependencies.
|
||||
The game can be played through the multi_sketch.html
|
||||
"Start run" to generate first leve, etc, seed,
|
||||
left0click chests
|
||||
|
||||
```
|
||||
npx degit makinteract/p5js-vite my-project
|
||||
How well and complete is your documentation? Your documentation should contain the following information:
|
||||
|
||||
cd my-project
|
||||
npm install
|
||||
npm run dev
|
||||
```
|
||||
Write a README.md file that contains the following information.
|
||||
|
||||
## npm scripts
|
||||
|
||||
- `npm run dev` - Starts the development server at port [3000](http://localhost:3000/)
|
||||
- `npm run build` - Builds the application in a `dist` folder
|
||||
- `npm run preview` - Serves the build files (`dist` folder) locally at port [5000](http://localhost:3000/)
|
||||
|
||||
Note that if after this last command you do not see anything, you can use instead this other command:
|
||||
|
||||
- `npm run preview --host` - You should then be able to see your files locally at port [5000](http://localhost:3000/)
|
||||
|
||||
## A single p5.js sketch
|
||||
|
||||
```js
|
||||
import '../css/style.css';
|
||||
import { sketch } from 'p5js-wrapper';
|
||||
|
||||
sketch.setup = function () {
|
||||
createCanvas(800, 600);
|
||||
};
|
||||
|
||||
sketch.draw = function () {
|
||||
background(127); // grey
|
||||
fill(255, 0, 0); // red
|
||||
noStroke();
|
||||
rectMode(CENTER);
|
||||
rect(width / 2, height / 2, 50, 50);
|
||||
};
|
||||
|
||||
sketch.mousePressed = function () {
|
||||
console.log(`I am here at ${mouseX}:${mouseY}`);
|
||||
};
|
||||
```
|
||||
|
||||
And here the body of the html file:
|
||||
|
||||
```html
|
||||
<body>
|
||||
<script type="module" src="/src/single_sketch.js"></script>
|
||||
</body>
|
||||
```
|
||||
|
||||
## Multiple p5.js sketches
|
||||
|
||||
If you want to use multiple sketches, you need to use a different syntax.
|
||||
|
||||
```js
|
||||
import '../css/style.css';
|
||||
import { p5 } from 'p5js-wrapper';
|
||||
|
||||
let sketch1 = new p5((p) => {
|
||||
p.setup = () => {
|
||||
const one = document.getElementById('one');
|
||||
p.createCanvas(one.clientWidth, one.clientHeight);
|
||||
};
|
||||
|
||||
p.draw = () => {
|
||||
p.background(100);
|
||||
};
|
||||
}, 'one');
|
||||
|
||||
// Sketch2
|
||||
let sketch2 = new p5((p) => {
|
||||
p.setup = () => {
|
||||
const two = document.getElementById('two');
|
||||
p.createCanvas(two.clientWidth, two.clientHeight);
|
||||
};
|
||||
|
||||
p.draw = () => {
|
||||
p.background(170);
|
||||
};
|
||||
}, 'two');
|
||||
```
|
||||
|
||||
This file is expecting two divs in the html file:
|
||||
|
||||
```html
|
||||
<body>
|
||||
<script type="module" src="/src/multi_sketch.js"></script>
|
||||
<div id="one"></div>
|
||||
<div id="two"></div>
|
||||
</body>
|
||||
```
|
||||
|
||||
## Adding sound
|
||||
|
||||
Sound is an [experimental feature](https://github.com/makinteract/p5js-wrapper/blob/main/README_SOUND.md).
|
||||
|
||||
Examples usage:
|
||||
|
||||
```js
|
||||
import { sketch } from 'p5js-wrapper';
|
||||
import 'p5js-wrapper/sound';
|
||||
|
||||
import mysound from './mysound.mp3';
|
||||
|
||||
let soundEffect;
|
||||
|
||||
sketch.setup = function () {
|
||||
createCanvas(100, 100);
|
||||
soundEffect = loadSound(mysound);
|
||||
};
|
||||
|
||||
sketch.draw = function () {
|
||||
background('#eeeeee');
|
||||
};
|
||||
|
||||
// Play sound on click
|
||||
sketch.mousePressed = function () {
|
||||
soundEffect.play();
|
||||
};
|
||||
```
|
||||
|
||||
This example assumes you have a file _mysound.mp3_ in the _src_ folder.
|
||||
|
||||
## License
|
||||
|
||||
This project is open source and available under the [MIT License](LICENSE).
|
||||
|
||||
@@ -20,12 +20,19 @@ canvas {
|
||||
}
|
||||
|
||||
.maze-layout {
|
||||
width: min(1200px, calc(100vw - 24px));
|
||||
margin: 12px auto 20px;
|
||||
width: 100vw;
|
||||
margin: 0;
|
||||
display: grid;
|
||||
grid-template-columns: 2fr 1fr;
|
||||
gap: 16px;
|
||||
grid-template-columns: 1fr;
|
||||
gap: 0;
|
||||
align-items: start;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.maze-layout > .panel:first-child {
|
||||
margin: 12px;
|
||||
border-radius: 16px;
|
||||
height: calc(100vh - 24px);
|
||||
}
|
||||
|
||||
.panel {
|
||||
@@ -162,6 +169,25 @@ canvas {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.p5-start-panel {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 20px;
|
||||
background: rgba(0, 0, 0, 0.95);
|
||||
z-index: 9999;
|
||||
}
|
||||
|
||||
.p5-start-panel[hidden] {
|
||||
display: none;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.p5-sketch-container {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
@@ -224,6 +250,19 @@ canvas {
|
||||
max-height: 400px;
|
||||
}
|
||||
|
||||
#control-panel-section {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
border-radius: 16px 16px 0 0;
|
||||
max-height: 40vh;
|
||||
overflow-y: auto;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
.control-group {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
BIN
img/img_start.png
Normal file
BIN
img/img_start.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.8 MiB |
10
index.html
10
index.html
@@ -22,16 +22,18 @@
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="p5-game-over-panel" class="panel p5-game-over-panel" hidden>
|
||||
<div class="panel-label">GAME OVER</div>
|
||||
<section id="p5-start-panel" class="p5-start-panel">
|
||||
<div id="p5-start-container" class="p5-sketch-container"></div>
|
||||
</section>
|
||||
|
||||
<section id="p5-game-over-panel" class="p5-game-over-panel" hidden>
|
||||
<div id="p5-sketch-container" class="p5-sketch-container"></div>
|
||||
<div class="game-over-info">
|
||||
<div class="game-over-text">Game Over</div>
|
||||
<div class="game-over-subtext">Press R to play again</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="panel">
|
||||
<section class="panel" id="control-panel-section" hidden>
|
||||
<div class="panel-label">Game Controls</div>
|
||||
<div id="control-panel" class="control-panel">
|
||||
<div class="control-group">
|
||||
|
||||
@@ -3,7 +3,7 @@ import { sharedState } from "./game/state.js";
|
||||
import { seededRng, generateMazeGrid, findDeadEnds } from "./game/maze.js";
|
||||
import { gridCellToWorld, isWalkableCell } from "./game/grid.js";
|
||||
import { playSfx, primeSfx } from "./game/sfx.js";
|
||||
import { startParticleSketch, stopParticleSketch } from "./p5_particles.js";
|
||||
import { startParticleSketch, stopParticleSketch, startStartScreenSketch, stopStartScreenSketch } from "./p5_particles.js";
|
||||
import chestTextureUrl from "../img/img_chest.png";
|
||||
import wallTextureUrl from "../img/img_wall.png";
|
||||
import groundTextureUrl from "../img/img_ground.png";
|
||||
@@ -17,6 +17,9 @@ const canvasTime = document.getElementById("canvas-time");
|
||||
const canvasKey = document.getElementById("canvas-key");
|
||||
const canvasRounds = document.getElementById("canvas-rounds");
|
||||
const p5GameOverPanel = document.getElementById("p5-game-over-panel");
|
||||
const p5StartPanel = document.getElementById("p5-start-panel");
|
||||
const controlPanelSection = document.getElementById("control-panel-section");
|
||||
let controlsVisible = false;
|
||||
|
||||
const scene = new BABYLON.Scene(engine);
|
||||
scene.clearColor = new BABYLON.Color4(0.05, 0.07, 0.1, 1);
|
||||
@@ -134,11 +137,19 @@ function switchCameraMode() {
|
||||
}
|
||||
|
||||
window.addEventListener("keydown", (event) => {
|
||||
if (event.code === "KeyW" || event.code === "KeyA" || event.code === "KeyS" || event.code === "KeyD" || event.code === "KeyV" || event.code === "KeyR") {
|
||||
if (event.code === "KeyW" || event.code === "KeyA" || event.code === "KeyS" || event.code === "KeyV" || event.code === "KeyR") {
|
||||
primeSfx();
|
||||
}
|
||||
if (event.code === "KeyR" && gameOverActive) {
|
||||
if (event.code === "KeyB") {
|
||||
toggleControlsPanel();
|
||||
return;
|
||||
}
|
||||
if (event.code === "KeyR") {
|
||||
if (gameOverActive) {
|
||||
restartRunFromGameOver();
|
||||
} else if (!sharedState.runtime.runActive && p5StartPanel && !p5StartPanel.hidden) {
|
||||
startRunFromStartScreen();
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (event.code === "KeyV") {
|
||||
@@ -532,5 +543,38 @@ scene.registerBeforeRender(() => {
|
||||
}
|
||||
});
|
||||
|
||||
function toggleControlsPanel() {
|
||||
controlsVisible = !controlsVisible;
|
||||
if (controlPanelSection) {
|
||||
controlPanelSection.hidden = !controlsVisible;
|
||||
}
|
||||
}
|
||||
|
||||
function startRunFromStartScreen() {
|
||||
if (p5StartPanel && !p5StartPanel.hidden) {
|
||||
p5StartPanel.hidden = true;
|
||||
stopStartScreenSketch();
|
||||
}
|
||||
sharedState.runtime.runActive = true;
|
||||
sharedState.runtime.hasKey = false;
|
||||
sharedState.runtime.roundsCompleted = 0;
|
||||
sharedState.runtime.elapsedSeconds = ROUND_TIME_SECONDS;
|
||||
sharedState.runtime.message = "Game started.";
|
||||
sharedState.config.level = 1;
|
||||
generateLevel();
|
||||
primeSfx();
|
||||
playSfx("click", 0.7);
|
||||
}
|
||||
|
||||
// Initialize start screen on page load
|
||||
window.addEventListener("load", () => {
|
||||
if (p5StartPanel && !p5StartPanel.hidden) {
|
||||
const startContainer = document.getElementById("p5-start-container");
|
||||
if (startContainer) {
|
||||
startStartScreenSketch(startContainer);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Export shared state for p5 to use
|
||||
export { sharedState };
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import p5 from "p5";
|
||||
import gameOverImageUrl from "../img/img_jobapplication.png";
|
||||
import startImageUrl from "../img/img_start.png";
|
||||
|
||||
let sketch;
|
||||
|
||||
@@ -118,3 +119,57 @@ export function stopParticleSketch() {
|
||||
sketch = null;
|
||||
}
|
||||
}
|
||||
|
||||
let startSketch;
|
||||
|
||||
export function startStartScreenSketch(containerElement) {
|
||||
if (startSketch) {
|
||||
startSketch.remove();
|
||||
}
|
||||
|
||||
startSketch = new p5((p) => {
|
||||
let startImg;
|
||||
|
||||
p.setup = async function() {
|
||||
const width = containerElement.clientWidth || 800;
|
||||
const height = containerElement.clientHeight || 600;
|
||||
console.log("p5 start screen setup:", { width, height });
|
||||
|
||||
const canv = p.createCanvas(width, height);
|
||||
canv.parent(containerElement);
|
||||
|
||||
// Load image asynchronously
|
||||
try {
|
||||
startImg = await p.loadImage(startImageUrl);
|
||||
console.log("Start image loaded:", startImg.width, "x", startImg.height);
|
||||
} catch (err) {
|
||||
console.error("Failed to load start image:", err);
|
||||
}
|
||||
};
|
||||
|
||||
p.draw = function() {
|
||||
// Draw background image full screen
|
||||
if (startImg) {
|
||||
p.imageMode(p.CORNER);
|
||||
p.image(startImg, 0, 0, p.width, p.height);
|
||||
}
|
||||
};
|
||||
|
||||
p.windowResized = function() {
|
||||
if (containerElement && containerElement.offsetParent !== null) {
|
||||
const width = containerElement.clientWidth;
|
||||
const height = containerElement.clientHeight;
|
||||
if (width > 0 && height > 0) {
|
||||
p.resizeCanvas(width, height);
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
export function stopStartScreenSketch() {
|
||||
if (startSketch) {
|
||||
startSketch.remove();
|
||||
startSketch = null;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user