Skip to content

Instantly share code, notes, and snippets.

@EncodeTheCode
Created May 10, 2025 04:13
Show Gist options
  • Save EncodeTheCode/dbff0f90e67d6b3a7c577c42747944d5 to your computer and use it in GitHub Desktop.
Save EncodeTheCode/dbff0f90e67d6b3a7c577c42747944d5 to your computer and use it in GitHub Desktop.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Top-down Shadows with Transparent Bottom Gradient</title>
<style>
body { margin: 0; background: #222; }
canvas { display: block; margin: auto; background: #333; }
</style>
</head>
<body>
<canvas id="gameCanvas" width="800" height="600"></canvas>
<script>
const canvas = document.getElementById("gameCanvas");
const ctx = canvas.getContext("2d");
const lightDir = { x: 1, y: 1 }; // Diagonal light direction
const shadowLength = 60;
const player = { x: 200, y: 200, w: 32, h: 32, color: 'blue' };
const walls = [
{ x: 300, y: 100, w: 100, h: 40 },
{ x: 500, y: 300, w: 120, h: 50 },
{ x: 200, y: 400, w: 80, h: 60 }
];
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
// Draw shadows first
for (let obj of [...walls, player]) {
drawShadow(obj);
}
// Draw walls and player on top
for (let wall of walls) {
ctx.fillStyle = "gray";
ctx.fillRect(wall.x, wall.y, wall.w, wall.h);
}
ctx.fillStyle = player.color;
ctx.fillRect(player.x, player.y, player.w, player.h);
requestAnimationFrame(draw);
}
function drawShadow(obj) {
const { x, y, w, h } = obj;
const dx = lightDir.x * shadowLength;
const dy = lightDir.y * shadowLength;
const faces = [
// Bottom face shadow (cast down and to the right)
{
corners: [
{ x: x, y: y + h },
{ x: x + w, y: y + h },
{ x: x + w + dx, y: y + h + dy },
{ x: x + dx, y: y + h + dy }
]
},
// Right face shadow (cast down and to the right)
{
corners: [
{ x: x + w, y: y },
{ x: x + w, y: y + h },
{ x: x + w + dx, y: y + h + dy },
{ x: x + w + dx, y: y + dy }
]
}
];
for (let face of faces) {
const [p1, p2, p3, p4] = face.corners;
// Compute center for gradient direction (fading from top to bottom)
const gx0 = (p1.x + p2.x) / 3;
const gy0 = (p1.y + p2.y) / 2;
const gx1 = (p3.x + p4.x) / 2;
const gy1 = (p3.y + p4.y) / 2;
// Create gradient that fades from black (top) to transparent (bottom)
const gradient = ctx.createLinearGradient(gx0, gy0, gx1, gy1);
gradient.addColorStop(0, "rgba(0,0,0,0.35)"); // Fully opaque at the top
gradient.addColorStop(1, "rgba(0,0,0,0)"); // Fully transparent at the bottom
ctx.fillStyle = gradient;
ctx.beginPath();
ctx.moveTo(p1.x, p1.y);
ctx.lineTo(p2.x, p2.y);
ctx.lineTo(p3.x, p3.y);
ctx.lineTo(p4.x, p4.y);
ctx.closePath();
ctx.fill();
}
}
draw();
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment