class Player { constructor() { this.x = 130; this.groundY = GROUND_Y; this.speed = 3.5; this.dir = 1; // 1=right, -1=left this.moving = false; this.stepT = 0; // --- sprite animation state --- this.anim = "idle"; this.prevAnim = "idle"; this.frameIdx = 0; this.frameTimer = 0; // frames per p5 tick each animation holds a frame this.frameLengths = { idle: 40, walk: 8 }; this.totalFrames = { idle: 2, walk: 4 }; this.sprites = null; // set via setSprites() when images are ready } // Call this once real PNGs are ready: // player.setSprites({ idle: [img0, img1], walk: [img0, img1, img2, img3] }) setSprites(map) { this.sprites = map; } update() { this.moving = false; if (keys[LEFT_ARROW]) { this.x -= this.speed; this.dir = -1; this.moving = true; } if (keys[RIGHT_ARROW]) { this.x += this.speed; this.dir = 1; this.moving = true; } this.x = constrain(this.x, 50, width - 50); this.anim = this.moving ? "walk" : "idle"; // reset frame when animation changes if (this.anim !== this.prevAnim) { this.frameIdx = 0; this.frameTimer = 0; this.prevAnim = this.anim; } // advance frame this.frameTimer++; if (this.frameTimer >= this.frameLengths[this.anim]) { this.frameTimer = 0; this.frameIdx = (this.frameIdx + 1) % this.totalFrames[this.anim]; } if (this.moving) this.stepT += 0.22; } draw() { let bobY = this.moving ? sin(this.stepT) * 3 : sin(frameCount * 0.05) * 1.5; push(); translate(this.x, this.groundY + bobY); scale(this.dir, 1); if (this.sprites) { this._drawSprite(); } else { this._drawDummy(); } pop(); } _drawSprite() { let img = this.sprites[this.anim][this.frameIdx]; imageMode(CENTER); // adjust (0, -60, 80, 120) to match actual sprite dimensions image(img, 0, -60, 80, 120); } _drawDummy() { rectMode(CENTER); noStroke(); // shadow fill(0, 0, 0, 25); ellipse(0, 6, 42, 11); // body placeholder — green=walk, blue=idle fill(this.anim === "walk" ? color(80, 200, 120) : color(90, 150, 255)); rect(0, -38, 40, 64, 12); // head fill(255, 220, 170); ellipse(0, -80, 48, 48); // eyes fill(40, 24, 14); ellipse(-11, -82, 7, 8); ellipse(11, -82, 7, 8); // frame number — confirms animation is cycling fill(255); textAlign(CENTER, CENTER); textSize(20); text(this.frameIdx, 0, -38); // anim label textSize(9); fill(255, 255, 255, 180); text(this.anim, 0, -20); } }