relay steps input

This commit is contained in:
nadiarvi 2025-05-08 00:21:56 +09:00
parent 4384e4eeb3
commit b4ddfaa6be
9 changed files with 436 additions and 116 deletions

159
src/_cat.js Normal file
View File

@ -0,0 +1,159 @@
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;
this.velocity = 24;
this.count = 0;
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) return;
console.log(`updating sprite...`);
this.sprite.position.x = this.x;
this.sprite.position.y = this.y;
if (kb.pressing('left')) {
console.log("accepting pressed kb");
this.sprite.vel.x = -1;
} else if (kb.pressing('right')) {
this.sprite.vel.x = 1;
} else {
this.sprite.vel.x = 0; // Stop the hero if no keys are pressed
}
};
draw() {
if (!this.sprite) return;
// this.sprite.draw();
this.sprite.update();
};
changeAni(key) {
if (!this.sprite) return;
switch (key) {
case 'w':
this.sprite.changeAni("walk");
break;
case 'j':
this.sprite.changeAni("jump");
break;
case 'i':
this.sprite.changeAni("idle");
break;
case 'h':
this.sprite.changeAni("hurt");
break;
case 'd':
this.sprite.changeAni("death");
break;
default:
break;
};
};
setPosition(x, y) {
if (this.sprite) {
this.sprite.position.x = x;
this.sprite.position.y = y;
};
};
keyPressed(key) {
if (key === 'ArrowRight') {
this.moveRight();
}
}
remove() {
if (!this.sprite) return;
this.sprite.remove();
this.sprite = null;
}
/// i want to add this part to move sprite across the canvas when user presses right arrow
// if (kb.presses('right')) {
// this.move(30, 'right', 3)
// }
move(direction){
if (!direction) return;
console.log(`entered move method`);
if (direction == "right") this.moveRight();
if (direction == "up") this.moveUp();
}
moveRight(){
console.log(`${this.count}`);
this.changeAni('w')
this.sprite.vel.x = 1;
this.count += 1;
}
moveUp(){
console.log(`sprite should move up...`);
this.changeAni('j')
}
runCat(steps){
steps.forEach(element => {
setTimeout(() => {
console.log(element)
}, 1000);
});
}
// helper
_getSpritePosition(){
console.log(`sprite's actual position: ${this.sprite.x}, ${this.sprite.y}`);
return (this.sprite.x, this.sprite.y);
}
_translate(step){
switch (step) {
case 'up':
console.log('move: up');
return 'jump'
break;
case 'right':
console.log('move: down');
return 'walk'
break;
case 'down':
console.log('move: up');
return 'jump'
break;
default:
break;
}
}
}

View File

@ -8,6 +8,15 @@ export class Cat {
this.loaded = false;
this.velocity = 24;
this.steps = [];
this.currentStepIndex = 0;
this.isMoving = false;
this.stepTimer = 0;
this.stepDuration = 40; // frames to complete one movement
this.moveDirection = null;
loadImage('assets/cat.webp', (img) => {
this.sprite = new Sprite(this.x, this.y, this.size, this.size);
this.sprite.spriteSheet = img;
@ -30,20 +39,87 @@ export class Cat {
}
update() {
if (this.sprite) {
this.sprite.position.x = this.x;
this.sprite.position.y = this.y;
// if (!this.sprite) return;
if (!this.sprite || this.steps.length === 0) return;
console.log(`updating sprite...`);
if (this.isMoving) {
this._continueMovement();
} else if (this.currentStepIndex < this.steps.length) {
this._startMovement(this.steps[this.currentStepIndex]);
}
this.sprite.position.x = this.x;
this.sprite.position.y = this.y;
// console.log(`steps to run: ${this.steps}`);
this._handleInput();
};
update() {
if (!this.sprite || this.steps.length === 0) return;
if (this.isMoving) {
this._continueMovement();
} else if (this.currentStepIndex < this.steps.length) {
this._startMovement(this.steps[this.currentStepIndex]);
}
this.sprite.position.x = this.x;
this.sprite.position.y = this.y;
}
run(steps) {
this.steps = steps.map(e => e.direction);
this.currentStepIndex = 0;
this.isMoving = false;
}
_startMovement(direction) {
this.moveDirection = direction;
this.stepTimer = 0;
this.isMoving = true;
if (direction === 'right') {
this.changeAni('w');
} else if (direction === 'up' || direction === 'down') {
this.changeAni('j');
}
}
_continueMovement() {
this.stepTimer++;
const delta = this.velocity / this.stepDuration;
if (this.moveDirection === 'right') this.x += delta;
if (this.moveDirection === 'up') this.y -= delta;
if (this.moveDirection === 'down') this.y += delta;
if (this.stepTimer >= this.stepDuration) {
this.isMoving = false;
this.currentStepIndex++;
this.changeAni('i'); // back to idle after each move
}
}
keyPressed(key) {
console.log(`receiving keyboard input: ${key}`);
}
draw() {
if (this.sprite) this.sprite.draw();
if (!this.sprite) return;
this.update();
this.sprite.update();
};
changeAni(key) {
if (!this.sprite) return;
console.log('changing animation...');
console.log(key);
switch (key) {
case 'w':
this.sprite.changeAni("walk");
@ -72,37 +148,44 @@ export class Cat {
};
};
moveRight() {
if (this.x + this.targetSize >= width) {
this.x = width - this.targetSize; // Ensure it doesn't go beyond the boundary
this.setPosition(this.x, this.y);
this.changeAni('i'); // Optionally change to idle if boundary reached
return;
}
this.x += this.velocity; // Keep moving
this.setPosition(this.x, this.y);
console.log(`sprite's actual position: ${this._getSpritePosition()}`)
this.changeAni('w'); // Keep walking animation
}
keyPressed(key) {
if (key === 'ArrowRight') {
this.moveRight();
}
}
remove() {
if (!this.sprite) return;
this.sprite.remove();
this.sprite = null;
}
moveUp(){
console.log(`sprite should move up...`);
this.changeAni('j')
}
// helper
_getSpritePosition(){
console.log(`sprite's actual position: ${this.sprite.x}, ${this.sprite.y}`);
return (this.sprite.x, this.sprite.y);
}
_translate(step){
switch (step) {
case 'up':
console.log('move: up');
return 'jump'
break;
case 'right':
console.log('move: down');
return 'walk'
break;
case 'down':
console.log('move: up');
return 'jump'
break;
default:
break;
}
}
_handleInput(){
console.log('assume i have something....');
}
}

View File

@ -1,47 +1,72 @@
import { colors } from "../utils/theme";
export class ClickableArrow {
static images = {};
static images = {};
static preload() {
ClickableArrow.images.up = loadImage('/assets/up.png');
ClickableArrow.images.down = loadImage('/assets/down.png');
ClickableArrow.images.left = loadImage('/assets/left.png');
ClickableArrow.images.right = loadImage('/assets/right.png');
ClickableArrow.images.empty = loadImage('/assets/empty.png');
}
constructor(direction, clickable=false) {
this.direction = direction;
this.image = ClickableArrow.images[direction];
this.clickable = clickable;
// this.onClick = onClick | null;
this.x = 0;
this.y = 0;
this.width = 40;
this.height = 40;
}
draw(x, y) {
this.x = x;
this.y = y;
stroke(255);
image(this.image, x, y, 40, 40);
}
handleClick(mouseX, mouseY) {
if (this._isMouseOver(mouseX, mouseY) && this._onClick) {
this._onClick();
}
}
//helpers
_onClick(){
console.log('clicked!');
}
_isMouseOver(mouseX, mouseY) {
return mouseX > this.x && mouseX < this.x + this.width &&
mouseY > this.y && mouseY < this.y + this.height;
}
static preload() {
ClickableArrow.images.up = loadImage('/assets/up.png');
ClickableArrow.images.down = loadImage('/assets/down.png');
ClickableArrow.images.left = loadImage('/assets/left.png');
ClickableArrow.images.right = loadImage('/assets/right.png');
ClickableArrow.images.empty = loadImage('/assets/empty.png');
}
constructor(direction, clickable = false) {
console.log(`constructing a new clickable arrow....`);
this.direction = direction;
this.image = ClickableArrow.images[direction];
this.clickable = clickable;
this.selected = false;
this.x = 0;
this.y = 0;
this.width = 40;
this.height = 40;
}
draw(x, y) {
this.x = x;
this.y = y;
stroke(255);
fill(200);
if (this.selected) {
fill(colors.tertiary);
} else {
fill(255);
}
rect(x, y, 40, 40);
image(this.image, x, y, 40, 40);
}
handleClick(mouseX, mouseY) {
if (this._isMouseOver(mouseX, mouseY) && this._onClick) {
this._onClick();
}
}
set(direction){
this.direction = direction;
this.image = ClickableArrow.images[direction];
}
select(){
this.selected = true;
}
unselect(){
this.selected = false;
}
//helpers
_onClick(){
if (!this.clickable) return;
console.log('clicked!');
}
_isMouseOver(mouseX, mouseY) {
return mouseX > this.x && mouseX < this.x + this.width &&
mouseY > this.y && mouseY < this.y + this.height;
}
}

View File

@ -11,15 +11,14 @@ export class ControlPanel {
this.boxWidth = 48;
this.boxHeight = 48;
this.boxSpacing = 8;
this.contents = Array(numBoxes).fill(null);
this.empty = new Arrow('empty');
this.contents = Array(numBoxes).fill(null).map(() => new ClickableArrow('empty', true));
this.empty = new ClickableArrow('empty', true);
this.fontSize = 20;
this.gap = this.fontSize;
}
setContents(contents){
this.contents = contents;
console.log(this.contents);
}
updateBox(index, content) {

View File

@ -8,6 +8,7 @@ let mgr;
function setup(){
createCanvas(windowWidth, windowHeight);
console.log(`window size: ${windowWidth}x${windowHeight}`);
textFont('Pixelify Sans', 'sans-serif');
textAlign(CENTER);
textSize(128);
@ -21,6 +22,9 @@ function setup(){
function draw(){
background(colors.primary);
mgr.draw();
// custom event handler, manually called
// mgr.handleEvent('keyPressing');
};
function windowResized() {
@ -28,10 +32,8 @@ function windowResized() {
mgr.handleEvent('onResize');
};
function mousePressed(){
mgr.handleEvent('mousePressed');
gameScene.handleClick(mouseX, mouseY);
};
function preload(){
@ -43,9 +45,10 @@ function keyPressed(){
mgr.handleEvent('keyPressed');
}
window.setup = setup;
window.draw = draw;
// window.windowResized = windowResized;
window.mousePressed = mousePressed;
window.preload = preload;
window.keyPressed = keyPressed;
window.keyPressed = keyPressed;

View File

@ -8,6 +8,11 @@ import { ControlPanel } from '../components/controlPanel.js';
export default function GameScene() {
const groundHeight = 100;
const worldHeight = windowHeight - groundHeight;
const catSize = 150;
const worldBlockSize = 100;
let cat;
let runButton;
let blocks;
@ -15,6 +20,22 @@ export default function GameScene() {
let loops;
let clickArrow;
let clicked;
let selectedStepIndex = null;
const buildingBlocks = [
new ClickableArrow('up', false),
new ClickableArrow('right', false),
];
// changed on user input
let selectedSteps;
let selectedBlock;
// selectedSteps = ['up', 'right', 'up', 'up', 'right', 'down'];
// selectedSteps = selectedSteps.map((e) => new ClickableArrow(e, true));
const slots = {
blocks: 2,
steps: 6,
@ -24,10 +45,7 @@ export default function GameScene() {
this.name = "GameScene";
this.setup = () => {
cat = new Cat(width / 6, height - 167.5, 150);
// test
clickArrow = new ClickableArrow('up', true);
cat = new Cat(width / 4, height - 175 - 2, catSize);
runButton = new MyButton({
x: width / 32 * 28.5,
@ -35,9 +53,7 @@ export default function GameScene() {
text: "run >>",
mode: "CORNER",
style: buttonS,
onPress: () => {
console.log("Run button pressed");
}
onPress: () => cat.run(steps.contents),
});
blocks = new ControlPanel({
@ -46,6 +62,7 @@ export default function GameScene() {
y: height / 32,
numBoxes: 2
});
blocks.setContents(buildingBlocks);
steps = new ControlPanel({
name: 'steps',
@ -53,21 +70,14 @@ export default function GameScene() {
y: height / 32,
numBoxes: 6
});
loops = new ControlPanel({
name: 'loop',
x: width / 32 * 7 + 48 * (slots.blocks + slots.steps + 2.75),
y: height / 32,
numBoxes: 4
});
blocks.setContents([
new Arrow('right'),
// new Arrow('up')
new ClickableArrow('up', true),
]);
// loops = new ControlPanel({
// name: 'loop',
// x: width / 32 * 7 + 48 * (slots.blocks + slots.steps + 2.75),
// y: height / 32,
// numBoxes: 4
// });
};
this.draw = () => {
@ -78,22 +88,38 @@ export default function GameScene() {
stroke(colors.secondary);
strokeWeight(7);
textAlign(LEFT, TOP);
text('lvl.3', width / 32, height /32 - 4);
text('lvl.1', width / 32, height /32 - 4);
// Ground
rectMode(CENTER);
rectMode(CORNER);
fill(colors.secondary);
rect(width / 2, height - 100 / 2, width, 80);
rect(0, height - groundHeight, width, groundHeight);
console.log(`ground is drawn at (0, ${height - groundHeight}) with size of ${width}x${groundHeight}`)
// Obstacle
console.log(`world size: ${windowWidth}, ${windowHeight}`);
for (let y = windowHeight - groundHeight - 2; y > 0; y -= worldBlockSize) {
for (let x = 0; x < width ; x += worldBlockSize) {
stroke(0)
strokeWeight(1)
noFill()
rect(x, y, worldBlockSize, worldBlockSize);
textSize(24);
const x_cnt = Math.floor(x / worldBlockSize);
const y_cnt = Math.floor(y / worldBlockSize);
const txt = `${x_cnt}, ${y_cnt}`;
text(txt, x + 8, y + 8);
}
}
runButton.draw();
blocks.draw();
steps.draw();
loops.draw();
// loops.draw();
// Sprite
camera.on();
cat.draw();
camera.off();
};
this.onResize = () => {
@ -104,20 +130,45 @@ export default function GameScene() {
}
this.keyPressed = () => {
console.log(`key: ${key}, keyCode: ${keyCode}`);
const _key = key;
console.log(`key passed: ${_key}`);
if (_key == "ArrowRight") {
cat.keyPressed(_key);
if (keyCode === ESCAPE) {
// Deselect the currently selected arrow if any
if (selectedStepIndex !== null && steps.contents[selectedStepIndex]) {
steps.contents[selectedStepIndex].selected = false;
}
selectedStepIndex = null;
} else {
cat.changeAni(_key);
cat.keyPressed(key);
}
}
this.handleClick = function(mx, my) {
this.arrows.forEach(arrow => {
if (arrow.clickable) {
arrow.handleClick(mx, my);
this.mousePressed = function() {
console.log(`canvas clicked at ${mouseX}, ${mouseY}`);
steps.contents.forEach((arrow, index) => {
if (arrow._isMouseOver(mouseX, mouseY)) {
selectedStepIndex = index;
steps.contents.forEach(a => a.selected = false);
arrow.select();
}
});
}
blocks.contents.forEach((arrow) => {
if (arrow._isMouseOver(mouseX, mouseY)) {
// console.log("Clicked arrow", arrow.direction);
if (selectedStepIndex !== null) {
const selectedArrow = steps.contents[selectedStepIndex];
selectedArrow.set(arrow.direction);
selectedArrow.clickable = true;
selectedArrow.selected = false;
selectedStepIndex = null;
}
}
});
};
}

View File

@ -1,5 +1,5 @@
import { colors } from '../utils/theme.js';
import { Cat } from '../cat.js';
import { Cat } from '../_cat.js';
import { buttonL } from '../utils/theme.js';
import GameScene from './gameScene.js';

View File

@ -6,9 +6,9 @@ body {
}
body {
color: #333;
margin: 0;
padding: 8px;
/* 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; */

0
src/utils/world_1.js Normal file
View File