init commit: migrate to vanilla js

This commit is contained in:
nadiarvi 2025-04-30 02:13:33 +09:00
parent 96a8352caa
commit ba3779b7d4
16 changed files with 34170 additions and 0 deletions

24
.gitignore vendored Normal file
View File

@ -0,0 +1,24 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
dist
dist-ssr
*.local
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

22
index.html Normal file
View File

@ -0,0 +1,22 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/png" href="/assets/icon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>rUn ThE cAT!</title>
<!-- Google Fonts -->
<link href="https://fonts.googleapis.com/css2?family=Pixelify+Sans:wght@400..700&display=swap" rel="stylesheet">
<!-- p5.js + p5.play -->
<script src="https://cdn.jsdelivr.net/npm/p5@1.9.0/lib/p5.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/p5@1.9.0/lib/addons/p5.sound.min.js"></script>
<script src="https://p5play.org/v3/planck.min.js"></script>
<script src="https://p5play.org/v3/p5play.js"></script>
<script src="/lib/scenemanager.js"></script>
</head>
<body>
<script defer type="module" src="/src/main.js"></script>
</body>
</html>

32582
lib/p5.js Normal file

File diff suppressed because it is too large Load Diff

204
lib/scenemanager.js Normal file
View File

@ -0,0 +1,204 @@
//
// p5 SceneManager helps you create p5.js sketches with multiple states / scenes
// Each scene is a like a sketch within the main sketch. You focus on creating
// the scene like a regular sketch and SceneManager ensure scene switching
// routing the main setup(), draw(), mousePressed(), etc. events to the
// appropriate current scene.
//
// Author: Marian Veteanu
// http://github.com/mveteanu
//
function SceneManager(p)
{
this.scenes = [];
this.scene = null;
// Wire relevant p5.js events, except setup()
// If you don't call this method, you need to manually wire events
this.wire = function()
{
const P5Events = [ "mouseClicked",
"mousePressed",
"mouseReleased",
"mouseMoved",
"mouseDragged",
"doubleClicked",
"mouseWheel",
"keyPressed",
"keyReleased",
"keyTyped",
"touchStarted",
"touchMoved",
"touchEnded",
"deviceMoved",
"deviceTurned",
"deviceShaken" ];
var me = this;
var o = p != null ? p : window;
// Wire draw manually for speed reasons...
o.draw = function(){ me.draw(); };
// This loop will wire automatically all P5 events to each scene like this:
// o.mouseClicked = function() { me.handleEvent("mouseClicked"); }
for(var i = 0; i < P5Events.length; i++)
{
let sEvent = P5Events[i]; // let is necesary to set the scope at the level of for
o[sEvent] = function() { me.handleEvent(sEvent) };
}
return me;
}
// Add a scene to the collection
// You need to add all the scenes if intend to call .showNextScene()
this.addScene = function( fnScene )
{
var oScene = new fnScene(p);
// inject p as a property of the scene
this.p = p;
// inject sceneManager as a property of the scene
oScene.sceneManager = this;
var o = { fnScene: fnScene,
oScene: oScene,
hasSetup : "setup" in oScene,
hasEnter : "enter" in oScene,
hasDraw : "draw" in oScene,
setupExecuted : false,
enterExecuted : false };
this.scenes.push(o);
return o;
}
// Return the index of a scene in the internal collection
this.findSceneIndex = function( fnScene )
{
for(var i = 0; i < this.scenes.length; i++)
{
var o = this.scenes[i];
if ( o.fnScene == fnScene )
return i;
}
return -1;
}
// Return a scene object wrapper
this.findScene = function( fnScene )
{
var i = this.findSceneIndex( fnScene );
return i >= 0 ? this.scenes[i] : null;
}
// Returns true if the current displayed scene is fnScene
this.isCurrent = function ( fnScene )
{
if ( this.scene == null )
return false;
return this.scene.fnScene == fnScene;
}
// Show a scene based on the function name
// Optionally you can send arguments to the scene
// Arguments will be retrieved in the scene via .sceneArgs property
this.showScene = function( fnScene, sceneArgs )
{
var o = this.findScene( fnScene );
if ( o == null )
o = this.addScene( fnScene );
// Re-arm the enter function at each show of the scene
o.enterExecuted = false;
this.scene = o;
// inject sceneArgs as a property of the scene
o.oScene.sceneArgs = sceneArgs;
}
// Show the next scene in the collection
// Useful if implementing demo applications
// where you want to advance scenes automatically
this.showNextScene = function( sceneArgs )
{
if ( this.scenes.length == 0 )
return;
var nextSceneIndex = 0;
if ( this.scene != null )
{
// search current scene...
// can be optimized to avoid searching current scene...
var i = this.findSceneIndex( this.scene.fnScene );
nextSceneIndex = i < this.scenes.length - 1 ? i + 1 : 0;
}
var nextScene = this.scenes[nextSceneIndex];
this.showScene( nextScene.fnScene, sceneArgs );
}
// This is the SceneManager .draw() method
// This will dispatch the main draw() to the
// current scene draw() method
this.draw = function()
{
// take the current scene in a variable to protect it in case
// it gets changed by the user code in the events such as setup()...
var currScene = this.scene;
if ( currScene == null )
return;
if ( currScene.hasSetup && !currScene.setupExecuted )
{
currScene.oScene.setup();
currScene.setupExecuted = true;
}
if ( currScene.hasEnter && !currScene.enterExecuted )
{
currScene.oScene.enter();
currScene.enterExecuted = true;
}
if ( currScene.hasDraw )
{
currScene.oScene.draw();
}
}
// Handle a certain event for a scene...
// It is used by the anonymous functions from the wire() function
this.handleEvent = function(sEvent)
{
if ( this.scene == null || this.scene.oScene == null )
return;
var fnSceneEvent = this.scene.oScene[sEvent];
if (fnSceneEvent)
fnSceneEvent.call(this.scene.oScene);
}
// Legacy method... preserved for maintaining compatibility
this.mousePressed = function()
{
this.handleEvent("mousePressed");
}
// Legacy method... preserved for maintaining compatibility
this.keyPressed = function()
{
this.handleEvent("keyPressed");
}
}

97
lib/scenemanager_.js Normal file
View File

@ -0,0 +1,97 @@
//
// Draft test of using SceneManager to run multiple scenes in parallel
//
function SceneManager_()
{
this.scenes = [];
this.visibleScenes = [];
this.addScene = function( fnScene )
{
var oScene = new fnScene( this );
var scene = { fnScene: fnScene,
oScene: oScene,
hasSetup: oScene.hasOwnProperty("setup"),
hasDraw: oScene.hasOwnProperty("draw"),
hasMousePressed: oScene.hasOwnProperty("mousePressed"),
setupExecuted: false
};
this.scenes.push( scene );
return scene;
}
this.findScene = function( fnScene )
{
for(var i = 0; i < this.scenes.length; i++)
{
var o = this.scenes[i];
if ( o.fnScene == fnScene )
return o;
}
return null;
}
this.showScene = function( fnScene )
{
this.showScenes( [fnScene] );
}
this.showScenes = function( arFnScenes )
{
this.visibleScenes = [];
for(var i = 0; i < arFnScenes.length; i++)
{
var fnScene = arFnScenes[i];
var scene = this.findScene( fnScene );
if ( scene == null )
scene = this.addScene( fnScene );
this.visibleScenes.push( scene );
}
}
this.draw = function()
{
if ( this.visibleScenes.length == 0 )
return;
for(var i = 0; i < this.visibleScenes.length; i++ )
{
var scene = this.visibleScenes[i];
if ( scene.hasSetup && !scene.setupExecuted )
{
scene.oScene.setup();
scene.setupExecuted = true;
}
if ( scene.hasDraw )
{
scene.oScene.draw();
}
}
}
this.mousePressed = function()
{
if ( this.visibleScenes.length == 0 )
return;
for(var i = 0; i < this.visibleScenes.length; i++ )
{
var scene = this.visibleScenes[i];
if ( scene.hasMousePressed )
{
scene.oScene.mousePressed();
}
}
}
}

1008
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

14
package.json Normal file
View File

@ -0,0 +1,14 @@
{
"name": "run-the-cat",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview"
},
"devDependencies": {
"vite": "^6.3.1"
}
}

BIN
public/assets/cat.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

BIN
public/assets/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 728 B

53
src/cat.js Normal file
View File

@ -0,0 +1,53 @@
export class Cat {
constructor(x, y, targetSize) {
this.x = x;
this.y = y;
this.size = 171;
this.targetSize = targetSize;
this.sprite = null;
this.loaded = false;
loadImage('assets/cat.webp', (img) => {
this.sprite = new Sprite(this.x, this.y, this.size, this.size);
this.sprite.spriteSheet = img;
this.sprite.anis.offset.y = 3;
this.sprite.anis.frameDelay = 8;
this.sprite.friction = 0;
this.sprite.addAnis({
jump: { row: 0, frames: 4 },
death: { row: 1, frames: 4 },
hurt: { row: 2, frames: 2 },
idle: { row: 3, frames: 4 },
walk: { row: 4, frames: 6 }
});
this.sprite.changeAni('idle');
const scaleFactor = this.targetSize / 171;
this.sprite.scale = scaleFactor;
this.loaded = true;
});
}
update() {
if (this.sprite) {
this.sprite.position.x = this.x;
this.sprite.position.y = this.y;
}
};
draw() {
if (this.sprite) this.sprite.draw();
};
changeAni(name) {
if (this.sprite) this.sprite.changeAni(name);
};
setPosition(x, y) {
if (this.sprite) {
this.sprite.position.x = x;
this.sprite.position.y = y;
};
};
}

41
src/main.js Normal file
View File

@ -0,0 +1,41 @@
console.log("start fresh :)");
import { colors } from './theme.js';
import StartScene from './scenes/startScene.js';
import GameScene from './scenes/gameScene.js';
let mgr;
function setup(){
createCanvas(windowWidth, windowHeight);
textFont('Pixelify Sans', 'sans-serif');
textAlign(CENTER);
textSize(128);
mgr = new SceneManager();
mgr.addScene(StartScene);
mgr.addScene(GameScene);
mgr.showScene(StartScene);
};
function draw(){
background(colors.primary);
mgr.draw();
};
function windowResized() {
resizeCanvas(windowWidth, windowHeight);
mgr.handleEvent('onResize');
};
function mousePressed(){
mgr.handleEvent('mousePressed');
};
window.setup = setup;
window.draw = draw;
window.windowResized = windowResized;
window.mousePressed = mousePressed;

17
src/scenes/gameScene.js Normal file
View File

@ -0,0 +1,17 @@
import { colors } from '../theme.js';
import { draw as drawWorld, groundHeight } from '../world.js';
import { Cat } from '../cat.js';
export default function GameScene(p) {
let cat;
this.setup = () => {
cat = new Cat(width / 2, height - 200, 200);
};
this.draw = () => {
// drawWorld(p, groundHeight);
cat.update();
cat.draw();
};
}

70
src/scenes/startScene.js Normal file
View File

@ -0,0 +1,70 @@
import { colors } from '../theme.js';
import { Cat } from '../cat.js';
export default function StartScene() {
let cat;
let button = {
x: 0,
y: 0,
width: 0,
height: 0,
};
this.setup = () => {
cat = new Cat(width / 2, height - 200, 200);
};
this.draw = () => {
background(colors.primary);
fill(colors.tertiary);
textSize(128);
stroke(colors.secondary);
strokeWeight(7);
text('rUn ThE cAT!', width / 2, height / 2 - 100);
// Button
fill(colors.tertiary);
stroke(colors.secondary);
strokeWeight(3);
rectMode(CENTER);
rect(width / 2, height / 2 + 50, 300, 75, 10);
button.x = width / 2 - 300 / 2;
button.y = height / 2 + 50 - 75 / 2;
button.width = 300;
button.height = 75;
fill(colors.secondary);
noStroke();
textSize(32);
text('Start', width / 2, height / 2 + 60);
// Ground
fill(colors.secondary);
rect(width / 2, height - 100 / 2, width, 100);
// Sprite
cat.draw();
};
this.onResize = () => {
if (cat) {
cat.setPosition(width / 2, height - 200);
}
}
this.mousePressed = function (){
const x = mouseX;
const y = mouseY;
if (x < button.x || x > button.x + button.width) return;
if (y < button.y || y > button.y + button.height) return;
this.sceneManager.showNextScene();
};
}

20
src/style.css Normal file
View File

@ -0,0 +1,20 @@
html,
body {
position: relative;
width: 100%;
height: 100%;
}
body {
color: #333;
margin: 0;
padding: 8px;
box-sizing: border-box;
/* font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif; */
font-family: "Pixelify Sans", sans-serif;
}
button {
font-family: "Pixelify Sans", sans-serif;
}

10
src/theme.js Normal file
View File

@ -0,0 +1,10 @@
const colors = {
primary: "#a6d1ff",
secondary: "#ff4f64",
tertiary: "#fff29d",
accent: "#a4e4b6"
};
export {
colors
}

8
src/world.js Normal file
View File

@ -0,0 +1,8 @@
import { colors } from './theme.js';
export const groundHeight = 100;
export function draw(p, groundHeight) {
fill(colors.secondary);
rect(0, height - groundHeight, width, groundHeight);
}