इंटरैक्टिव उछलता हुआ बहुभुज जिसमें आकार बदलने की क्षमता है
Wikiprompt से, मुफ्त प्रॉम्प्ट विश्वकोश
इंटरैक्टिव उछलता हुआ बहुभुज जिसमें आकार बदलने की क्षमता है एक इंटरैक्टिव एनीमेशन बनाने के लिए प्रॉम्प्ट जहां एक बहुभुज आकारों के बीच रूपांतरित होता है और एक गेंद भौतिकी के साथ उसके अंदर उछलती है।
प्रॉम्प्ट सामग्रीसहेजें
🌐
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>shape morph · bouncing ball</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
background: #0b1a2f;
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
font-family: 'Segoe UI', system-ui, sans-serif;
}
.container {
background: #0f263b;
padding: 1.5rem 2rem 2rem;
border-radius: 3rem 3rem 2rem 2rem;
box-shadow: 0 20px 30px rgba(0,0,0,0.6), inset 0 0 0 1px #3e6d9c;
display: flex;
flex-direction: column;
align-items: center;
}
canvas {
display: block;
width: 520px;
height: 520px;
border-radius: 2.5rem;
background: radial-gradient(circle at 20% 20%, #1d3b55, #0a1622);
box-shadow: inset 0 0 40px rgba(0,0,0,0.7), 0 10px 20px rgba(0,0,0,0.5);
border: 2px solid #2f5f8a;
}
.status {
margin-top: 1rem;
color: #b6d9f0;
font-weight: 500;
letter-spacing: 1px;
background: #0d1f30;
padding: 0.5rem 1.8rem;
border-radius: 40px;
border: 1px solid #2f6a9b;
box-shadow: inset 0 2px 5px rgba(0,0,0,0.5);
font-size: 1.2rem;
display: flex;
align-items: center;
gap: 0.6rem;
}
.status span {
color: #ffd966;
font-weight: 700;
text-transform: uppercase;
}
.badge {
background: #1e4a6e;
padding: 0.2rem 0.8rem;
border-radius: 30px;
color: #eaf6ff;
font-size: 0.9rem;
}
</style>
</head>
<body>
<div class="container">
<canvas id="morphCanvas" width="520" height="520"></canvas>
<div class="status">
<span id="shapeName">pentagon</span>
<span class="badge">⚡ 5s morph</span>
</div>
</div>
<script>
(function() {
const canvas = document.getElementById('morphCanvas');
const ctx = canvas.getContext('2d');
const shapeLabel = document.getElementById('shapeName');
// ---------- fixed parameters ----------
const W = 520, H = 520;
const CENTER_X = W / 2;
const CENTER_Y = H / 2;
const BASE_RADIUS = 200; // outer radius for all shapes
// ---------- ball state ----------
let ball = {
x: 350, y: 180,
vx: 2.2, vy: -1.8,
radius: 12
};
// physics constants (gravity & friction)
const GRAVITY = 0.25;
const FRICTION = 0.998; // per frame damping
// ---------- shape sequence ----------
const SHAPES = ['triangle', 'square', 'pentagon', 'hexagon', 'octagon'];
let shapeIndex = 2; // start with pentagon
let currentShape = SHAPES[shapeIndex];
// time control
let lastMorphTime = performance.now();
const MORPH_INTERVAL = 5000; // 5 seconds
// ---------- shape vertex generation (regular polygon, centered) ----------
function getVertices(shape, radius = BASE_RADIUS) {
let n;
switch (shape) {
case 'triangle': n = 3; break;
case 'square': n = 4; break;
case 'pentagon': n = 5; break;
case 'hexagon': n = 6; break;
case 'octagon': n = 8; break;
default: n = 5;
}
const vertices = [];
// start angle: -90° (top) for aesthetic, but any rotation works
const startAngle = -Math.PI / 2;
for (let i = 0; i < n; i++) {
const angle = startAngle + (i * 2 * Math.PI / n);
const x = CENTER_X + radius * Math.cos(angle);
const y = CENTER_Y + radius * Math.sin(angle);
vertices.push({ x, y });
}
return vertices;
}
// ---------- point-in-polygon (ray casting) ----------
function isPointInsidePolygon(px, py, vertices) {
let inside = false;
const n = vertices.length;
for (let i = 0, j = n - 1; i < n; j = i++) {
const xi = vertices[i].x, yi = vertices[i].y;
const xj = vertices[j].x, yj = vertices[j].y;
if (((yi > py) !== (yj > py)) && (px < (xj - xi) * (py - yi) / (yj - yi) + xi)) {
inside = !inside;
}
}
return inside;
}
// ---------- closest point on segment (for collision) ----------
function closestPointOnSegment(px, py, ax, ay, bx, by) {
const dx = bx - ax;
const dy = by - ay;
const lenSq = dx * dx + dy * dy;
if (lenSq === 0) return { x: ax, y: ay };
let t = ((px - ax) * dx + (py - ay) * dy) / lenSq;
t = Math.max(0, Math.min(1, t));
return { x: ax + t * dx, y: ay + t * dy };
}
// ---------- reflect velocity against a normal ----------
function reflect(vx, vy, nx, ny) {
const dot = vx * nx + vy * ny;
return { vx: vx - 2 * dot * nx, vy: vy - 2 * dot * ny };
}
// ---------- physics + collision resolution ----------
function updateBall(vertices) {
// apply gravity
ball.vy += GRAVITY;
// apply friction (air resistance)
ball.vx *= FRICTION;
ball.vy *= FRICTION;
// tentative move
let newX = ball.x + ball.vx;
let newY = ball.y + ball.vy;
// first: check if new position is inside polygon
if (isPointInsidePolygon(newX, newY, vertices)) {
ball.x = newX;
ball.y = newY;
return; // all good
}
// otherwise: we need to slide/reflect along the polygon edges
// robust approach: move in small steps (subdivision) to avoid tunneling
const steps = 8;
const subX = (newX - ball.x) / steps;
const subY = (newY - ball.y) / steps;
let tempX = ball.x;
let tempY = ball.y;
for (let s = 0; s < steps; s++) {
const nextX = tempX + subX;
const nextY = tempY + subY;
if (isPointInsidePolygon(nextX, nextY, vertices)) {
tempX = nextX;
tempY = nextY;
continue;
}
// collision with edge(s) -> find closest point on any segment
let closestDist = Infinity;
let closestPoint = null;
let edgeNormal = null;
const n = vertices.length;
for (let i = 0; i < n; i++) {
const A = vertices[i];
const B = vertices[(i + 1) % n];
const cp = closestPointOnSegment(nextX, nextY, A.x, A.y, B.x, B.y);
const dist = Math.hypot(nextX - cp.x, nextY - cp.y);
if (dist < closestDist) {
closestDist = dist;
closestPoint = cp;
// edge vector
const ex = B.x - A.x;
const ey = B.y - A.y;
// normal (perpendicular) pointing inward (towards center)
let nx = -(ey);
let ny = ex;
// ensure normal points toward polygon center
const toCenterX = CENTER_X - cp.x;
const toCenterY = CENTER_Y - cp.y;
if (nx * toCenterX + ny * toCenterY < 0) {
nx = -nx;
ny = -ny;
}
// normalize
const len = Math.hypot(nx, ny);
if (len > 0.0001) {
nx /= len;
ny /= len;
}
edgeNormal = { x: nx, y: ny };
}
}
if (closestPoint && edgeNormal) {
// push ball out of the polygon (along normal)
const overlap = ball.radius - closestDist;
if (overlap > 0) {
tempX = closestPoint.x + edgeNormal.x * ball.radius;
tempY = closestPoint.y + edgeNormal.y * ball.radius;
} else {
tempX = closestPoint.x + edgeNormal.x * ball.radius;
tempY = closestPoint.y + edgeNormal.y * ball.radius;
}
// reflect velocity
const reflected = reflect(ball.vx, ball.vy, edgeNormal.x, edgeNormal.y);
ball.vx = reflected.vx * 0.98; // slight energy loss
ball.vy = reflected.vy * 0.98;
// after reflection, try to move again (but avoid infinite loop)
// we break and let next frame handle further movement
// but we also need to ensure the ball is inside after reflection
if (!isPointInsidePolygon(tempX, tempY, vertices)) {
// fallback: place at closest point + normal * radius
tempX = closestPoint.x + edgeNormal.x * ball.radius;
tempY = closestPoint.y + edgeNormal.y * ball.radius;
}
// break out of substep loop, we handled collision
break;
} else {
// fallback: just move (should not happen)
tempX = nextX;
tempY = nextY;
}
}
// final safety: if still outside, force inside (project to center)
if (!isPointInsidePolygon(tempX, tempY, vertices)) {
// find nearest point on any edge and place inside
let bestDist = Infinity;
let bestPoint = null;
for (let i = 0; i < vertices.length; i++) {
const A = vertices[i];
const B = vertices[(i + 1) % vertices.length];
const cp = closestPointOnSegment(tempX, tempY, A.x, A.y, B.x, B.y);
const d = Math.hypot(tempX - cp.x, tempY - cp.y);
if (d < bestDist) {
bestDist = d;
bestPoint = cp;
}
}
if (bestPoint) {
// push inward
const dirX = CENTER_X - bestPoint.x;
const dirY = CENTER_Y - bestPoint.y;
const len = Math.hypot(dirX, dirY);
if (len > 0.001) {
tempX = bestPoint.x + (dirX / len) * ball.radius;
tempY = bestPoint.y + (dirY / len) * ball.radius;
} else {
tempX = CENTER_X;
tempY = CENTER_Y - ball.radius;
}
} else {
tempX = CENTER_X;
tempY = CENTER_Y;
}
}
ball.x = tempX;
ball.y = tempY;
// extra safety: clamp velocity to avoid explosion
const maxSpeed = 12;
const speed = Math.hypot(ball.vx, ball.vy);
if (speed > maxSpeed) {
ball.vx = (ball.vx / speed) * maxSpeed;
ball.vy = (ball.vy / speed) * maxSpeed;
}
}
// ---------- drawing ----------
function draw(vertices) {
ctx.clearRect(0, 0, W, H);
// draw shape (filled + stroke)
ctx.beginPath();
ctx.moveTo(vertices[0].x, vertices[0].y);
for (let i = 1; i < vertices.length; i++) {
ctx.lineTo(vertices[i].x, vertices[i].y);
}
ctx.closePath();
ctx.fillStyle = 'rgba(30, 80, 130, 0.25)';
ctx.fill();
ctx.strokeStyle = '#7fc8ff';
ctx.lineWidth = 4;
ctx.shadowColor = '#4a9eff';
ctx.shadowBlur = 18;
ctx.stroke();
ctx.shadowBlur = 0;
// draw vertices (subtle)
ctx.fillStyle = '#b8e2ff';
for (let v of vertices) {
ctx.beginPath();
ctx.arc(v.x, v.y, 4, 0, 2 * Math.PI);
ctx.fill();
}
// draw ball
ctx.shadowColor = '#f0b840';
ctx.shadowBlur = 20;
ctx.beginPath();
ctx.arc(ball.x, ball.y, ball.radius, 0, 2 * Math.PI);
ctx.fillStyle = '#ffb347';
ctx.fill();
ctx.shadowBlur = 0;
ctx.strokeStyle = '#fff3d1';
ctx.lineWidth = 2;
ctx.stroke();
// small highlight
ctx.beginPath();
ctx.arc(ball.x - 3, ball.y - 3, 3, 0, 2 * Math.PI);
ctx.fillStyle = 'rgba(255,255,255,0.5)';
ctx.fill();
}
// ---------- morph check ----------
function checkMorph(now) {
if (now - lastMorphTime >= MORPH_INTERVAL) {
shapeIndex = (shapeIndex + 1) % SHAPES.length;
currentShape = SHAPES[shapeIndex];
shapeLabel.textContent = currentShape;
lastMorphTime = now;
}
}
// ---------- animation loop ----------
function animate(now) {
checkMorph(now);
// get current vertices
const vertices = getVertices(currentShape);
// update physics (collision with current shape)
updateBall(vertices);
// draw everything
draw(vertices);
requestAnimationFrame(animate);
}
// ---------- initialise ----------
// set initial ball position inside pentagon (safe)
ball.x = CENTER_X + 40;
ball.y = CENTER_Y - 40;
ball.vx = 2.5;
ball.vy = -2.0;
// start animation
requestAnimationFrame(animate);
})();
</script>
</body>
</html>
पूरा प्रॉम्प्ट देखने के लिए साइन इन करें
Continue with:
By logging in, you agree to our Terms of Use and Privacy Policy
उपयोग
यह प्रॉम्प्ट coding के साथ उपयोग के लिए डिज़ाइन किया गया है। ऊपर प्रॉम्प्ट सामग्री कॉपी करें और अपने पसंदीदा AI टूल में पेस्ट करें।
सर्वोत्तम परिणामों के लिए, आप अपनी विशिष्ट आवश्यकताओं के अनुसार प्लेसहोल्डर (वर्ग कोष्ठक या बड़े अक्षरों में दर्शाए गए) को अनुकूलित कर सकते हैं।
चर्चा
0 टिप्पणियाँ