frugg
This commit is contained in:
@ -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
|
||||||
|
|||||||
63
index.html
63
index.html
@ -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;
|
||||||
|
|
||||||
@ -196,7 +210,7 @@ function drawTrajectory() {
|
|||||||
|
|
||||||
ctx.strokeStyle = "red";
|
ctx.strokeStyle = "red";
|
||||||
ctx.lineWidth = 2;
|
ctx.lineWidth = 2;
|
||||||
ctx.setLineDash([6, 6]);
|
ctx.setLineDash([6,6]);
|
||||||
ctx.beginPath();
|
ctx.beginPath();
|
||||||
|
|
||||||
let lastPoint = null;
|
let lastPoint = null;
|
||||||
@ -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 ---
|
||||||
|
|||||||
Reference in New Issue
Block a user