This commit is contained in:
2026-05-03 22:58:17 +02:00
parent 5c82e6727b
commit bcda3b8d32
2 changed files with 47 additions and 18 deletions

View File

@ -3,4 +3,4 @@ Isometric frog jump to lilypad game, vibecoded and inspired by Vtech camera buil
## TODO ## TODO
[X] Add frog like loud burping on jump [X] Add frog like loud burping on jump
[ ] Make fg look like frog [X] Make frog look like frog

View File

@ -2,7 +2,7 @@
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<title>Frugg</title> <title>frugg</title>
<style> <style>
body { margin: 0; background: #222; overflow: hidden; } body { margin: 0; background: #222; overflow: hidden; }
canvas { display: block; margin: auto; background: #4aa3d8; } canvas { display: block; margin: auto; background: #4aa3d8; }
@ -30,7 +30,7 @@ let score = 0;
// --- Camera --- // --- Camera ---
let camera = { x: 0, y: 0 }; let camera = { x: 0, y: 0 };
// --- YOUR SETTINGS --- // --- SETTINGS ---
const GRAVITY = 0.25; const GRAVITY = 0.25;
const MAX_CHARGE = 25; const MAX_CHARGE = 25;
const JUMP_POWER = 0.5; const JUMP_POWER = 0.5;
@ -39,7 +39,7 @@ const HORIZONTAL_SCALE = 0.0010;
// --- Sound --- // --- Sound ---
const jumpSound = document.getElementById("jumpSound"); const jumpSound = document.getElementById("jumpSound");
// --- Create lily pads --- // --- Generate pads ---
function generatePads() { function generatePads() {
pads = [{ x: 0, y: 0 }]; pads = [{ x: 0, y: 0 }];
for (let i = 1; i < 30; i++) { for (let i = 1; i < 30; i++) {
@ -74,7 +74,7 @@ window.addEventListener("keyup", e => {
} }
}); });
// --- Jump physics --- // --- Jump ---
let velocity = { x: 0, y: 0, z: 0 }; let velocity = { x: 0, y: 0, z: 0 };
let jumping = false; let jumping = false;
@ -94,7 +94,6 @@ function jump() {
jumping = true; jumping = true;
charge = 0; charge = 0;
// play sound starting at 0.25s
jumpSound.currentTime = 0.25; jumpSound.currentTime = 0.25;
jumpSound.play(); jumpSound.play();
} }
@ -120,12 +119,11 @@ function update() {
} }
} }
// camera follow
camera.x += (pads[currentPad].x - camera.x) * 0.1; camera.x += (pads[currentPad].x - camera.x) * 0.1;
camera.y += (pads[currentPad].y - camera.y) * 0.1; camera.y += (pads[currentPad].y - camera.y) * 0.1;
} }
// --- Landing check --- // --- Landing ---
function checkLanding() { function checkLanding() {
const next = pads[currentPad + 1]; const next = pads[currentPad + 1];
if (!next) return; if (!next) return;
@ -142,7 +140,7 @@ function checkLanding() {
resetFrog(); resetFrog();
} }
// --- Isometric projection --- // --- Iso ---
function iso(x, y, z = 0) { function iso(x, y, z = 0) {
const sx = x - camera.x; const sx = x - camera.x;
const sy = y - camera.y; const sy = y - camera.y;
@ -166,14 +164,30 @@ function drawFrog() {
ctx.ellipse(base.x, base.y, 15 * scale, 8 * scale, 0, 0, Math.PI * 2); ctx.ellipse(base.x, base.y, 15 * scale, 8 * scale, 0, 0, Math.PI * 2);
ctx.fill(); ctx.fill();
// frog // body
ctx.fillStyle = "lime"; ctx.fillStyle = "#3bd16f";
ctx.beginPath(); ctx.beginPath();
ctx.arc(p.x, p.y - 10, 15, 0, Math.PI * 2); ctx.ellipse(p.x, p.y, 18, 14, 0, 0, Math.PI * 2);
ctx.fill();
// eyes
const eyeOffsetX = 8;
const eyeOffsetY = -10;
ctx.fillStyle = "white";
ctx.beginPath();
ctx.arc(p.x - eyeOffsetX, p.y + eyeOffsetY, 5, 0, Math.PI * 2);
ctx.arc(p.x + eyeOffsetX, p.y + eyeOffsetY, 5, 0, Math.PI * 2);
ctx.fill();
ctx.fillStyle = "black";
ctx.beginPath();
ctx.arc(p.x - eyeOffsetX, p.y + eyeOffsetY, 2, 0, Math.PI * 2);
ctx.arc(p.x + eyeOffsetX, p.y + eyeOffsetY, 2, 0, Math.PI * 2);
ctx.fill(); ctx.fill();
} }
// --- Trajectory + landing marker --- // --- Trajectory ---
function drawTrajectory() { function drawTrajectory() {
if (!charging || jumping) return; if (!charging || jumping) return;
@ -211,14 +225,13 @@ function drawTrajectory() {
ctx.lineTo(p.x, p.y); ctx.lineTo(p.x, p.y);
lastPoint = { x: tx, y: ty }; lastPoint = { x: tx, y: ty };
steps++; steps++;
} }
ctx.stroke(); ctx.stroke();
ctx.setLineDash([]); ctx.setLineDash([]);
// --- Landing marker --- // landing marker
if (lastPoint) { if (lastPoint) {
const p = iso(lastPoint.x, lastPoint.y, 0); const p = iso(lastPoint.x, lastPoint.y, 0);
@ -234,7 +247,7 @@ function drawTrajectory() {
} }
} }
// --- Depth sorted scene --- // --- Scene ---
function drawScene() { function drawScene() {
let objects = []; let objects = [];
@ -263,6 +276,22 @@ function drawScene() {
ctx.ellipse(p.x, p.y, 50, 25, 0, 0, Math.PI * 2); ctx.ellipse(p.x, p.y, 50, 25, 0, 0, Math.PI * 2);
ctx.fill(); ctx.fill();
// notch
ctx.globalCompositeOperation = "destination-out";
ctx.beginPath();
ctx.moveTo(p.x, p.y);
ctx.arc(p.x, p.y, 50, -0.3, 0.3);
ctx.closePath();
ctx.fill();
ctx.globalCompositeOperation = "source-over";
// vein
ctx.strokeStyle = "rgba(0,0,0,0.15)";
ctx.beginPath();
ctx.moveTo(p.x, p.y);
ctx.lineTo(p.x + 40, p.y);
ctx.stroke();
} else { } else {
drawFrog(); drawFrog();
} }
@ -273,7 +302,7 @@ function drawScene() {
function drawUI() { function drawUI() {
ctx.fillStyle = "white"; ctx.fillStyle = "white";
ctx.font = "20px Arial"; ctx.font = "20px Arial";
ctx.fillText("Score: " + score, 20, 30); ctx.fillText("frugg | Score: " + score, 20, 30);
} }
// --- Loop --- // --- Loop ---