Liveweave: Generative AI Web Editor & HTML/CSS/JS Playground
Initializing
Liveweave
Web
expand_more
home
Home
Palette
Color Explorer
arrow_outward
Polyline
Graphics Editor
arrow_outward
frame_source
Python Playground
arrow_outward
build
Tools
expand_more
restart_alt
Load "Hello Weaver!"
post_add
Generate Lorem ipsum...
code
Format HTML
code_blocks
Format CSS
data_object
Format JavaScript
library_add
Library
expand_more
A
Algolia JS
Animate CSS
Apex Charts JS
B
Bulma CSS
Bootstrap
C
Chart JS
Chartist
Create JS
D
D3
Dojo
F
Foundation
Fullpage JS
G
Granim JS
Google Charts
H
Halfmoon
J
jQuery
M
Materialize
Moment JS
Masonry JS
Milligram CSS
P
Pure CSS
Primer CSS
Popper JS
Pattern CSS
Picnic CSS
R
React JS
Raphael JS
Raisin CSS
S
Semantic UI
Skeleton CSS
Spectre CSS
Tachyons CSS
T
Tailwind
Three JS
U
UI Kit
Vis JS
W
Water CSS
download
Download
expand_more
developer_mode
Download as HTML
folder_zip
Download as .ZIP
cloud_upload
Fork
account_circle
Login
settings
Settings
expand_more
Editor font
14
px
A
A
Night mode
Line number
Mini map
Word wrap
sync_alt
Reset Settings
smart_display
Run
left_panel_close
AI Assistant
dashboard
All
HTML
CSS
JS
visibility
Preview
bolt
Live Preview
terminal
JS Console
<!DOCTYPE html> <html> <head> <title>Frog snack game</title> </head> <body> <!-- Start your code here --> <div class="game"> <div class="hud"> <div> <span class="hud-label">SCORE</span> <strong id="score">0</strong> </div> <div class="title"> 🐸 FROG SNACK </div> <div class="lives" id="lives"> ❤️ ❤️ ❤️ </div> </div> <div class="sky"> <div class="cloud cloud-1"> <i></i><i></i><i></i> </div> <div class="cloud cloud-2"> <i></i><i></i><i></i> </div> </div> <div class="mountains"> <div class="mountain m1"></div> <div class="mountain m2"></div> <div class="mountain m3"></div> </div> <div class="pond"> <div class="water-lines"></div> <div class="lily lily-1"></div> <div class="lily lily-2"></div> <div class="lily lily-3"></div> <div class="flower"> <span>🌸</span> </div> </div> <div id="objects"></div> <!-- FROG --> <div class="frog" id="frog"> <div class="frog-shadow"></div> <div class="frog-body"> <div class="leg left-leg"></div> <div class="leg right-leg"></div> <div class="frog-head"> <div class="eye eye-left"> <div class="eyeball"> <div class="pupil"></div> </div> </div> <div class="eye eye-right"> <div class="eyeball"> <div class="pupil"></div> </div> </div> <div class="cheek cheek-left"></div> <div class="cheek cheek-right"></div> <div class="mouth"></div> <div class="tongue" id="tongue"></div> </div> <div class="belly"></div> </div> </div> <div class="grass"></div> <div class="instructions"> ← → or A D • SPACE = tongue </div> <div class="overlay" id="overlay"> <div class="game-card"> <div class="big-frog">🐸</div> <h1>Frog Snack!</h1> <p> Help Froggy catch tasty flies. <br> But don't eat the bees! </p> <button id="startButton"> START GAME </button> <small> Arrow keys / A D to move <br> Space to catch </small> </div> </div> </div> <!-- End your code here --> </body> </html>
* { box-sizing: border-box; } html, body { margin: 0; width: 100%; height: 100%; overflow: hidden; } body { font-family: "Trebuchet MS", Arial, sans-serif; background: #bdefff; } /* ============================= GAME ============================= */ .game { position: relative; width: 100vw; height: 100vh; min-height: 560px; overflow: hidden; background: linear-gradient( #83dcff 0%, #c8f4ff 55%, #f3fdff 100% ); } /* ============================= HUD ============================= */ .hud { position: absolute; z-index: 50; top: 18px; left: 25px; right: 25px; display: flex; justify-content: space-between; align-items: center; color: #184638; } .hud > div:first-child { display: flex; flex-direction: column; } .hud-label { font-size: 10px; letter-spacing: 2px; } #score { font-size: 28px; } .title { padding: 8px 18px; border-radius: 30px; background: rgba(255,255,255,.55); backdrop-filter: blur(6px); font-weight: bold; letter-spacing: 2px; box-shadow: 0 4px 12px rgba(0,0,0,.08); } .lives { font-size: 18px; } /* ============================= CLOUDS ============================= */ .cloud { position: absolute; width: 130px; height: 40px; border-radius: 50px; background: rgba(255,255,255,.75); animation: cloudMove 25s linear infinite; } .cloud i { position: absolute; display: block; border-radius: 50%; background: inherit; } .cloud i:nth-child(1) { width: 55px; height: 55px; left: 20px; bottom: 10px; } .cloud i:nth-child(2) { width: 70px; height: 70px; left: 50px; bottom: 5px; } .cloud i:nth-child(3) { width: 45px; height: 45px; right: 5px; bottom: 7px; } .cloud-1 { top: 120px; left: -150px; } .cloud-2 { top: 210px; left: -300px; transform: scale(.65); opacity: .7; animation-delay: -12s; } @keyframes cloudMove { from { translate: 0; } to { translate: calc(100vw + 450px); } } /* ============================= MOUNTAINS ============================= */ .mountains { position: absolute; left: 0; right: 0; bottom: 32%; height: 220px; opacity: .45; } .mountain { position: absolute; bottom: 0; width: 400px; height: 230px; clip-path: polygon( 50% 0, 100% 100%, 0 100% ); background: #65a89a; } .m1 { left: -100px; } .m2 { left: 30%; height: 180px; background: #79b5a5; } .m3 { right: -80px; height: 250px; background: #5d9d90; } /* ============================= POND ============================= */ .pond { position: absolute; left: 0; right: 0; bottom: 0; height: 36%; overflow: hidden; background: linear-gradient( #67d8d2, #29aeb5 ); } .water-lines { position: absolute; inset: 0; opacity: .25; background: repeating-linear-gradient( 175deg, transparent 0, transparent 28px, rgba(255,255,255,.5) 30px, transparent 33px ); animation: waterMove 5s linear infinite; } @keyframes waterMove { to { background-position: 100px 0; } } /* ============================= LILY PADS ============================= */ .lily { position: absolute; width: 100px; height: 42px; border-radius: 50%; background: #3eaa63; box-shadow: inset -10px -6px 0 rgba(0,0,0,.08); transform: rotate(-5deg); } .lily::after { content: ""; position: absolute; right: 2px; top: 5px; width: 45px; height: 30px; background: #3bb3b8; clip-path: polygon( 100% 0, 0 50%, 100% 100% ); } .lily-1 { left: 8%; top: 45%; } .lily-2 { right: 9%; top: 25%; transform: scale(.7); } .lily-3 { left: 60%; bottom: 8%; transform: scale(.55); } /* ============================= FLOWER ============================= */ .flower { position: absolute; right: 17%; top: 10%; font-size: 40px; animation: flowerFloat 3s ease-in-out infinite; } @keyframes flowerFloat { 50% { transform: translateY(-5px) rotate(5deg); } } /* ============================= GRASS ============================= */ .grass { position: absolute; z-index: 10; left: 0; right: 0; bottom: 0; height: 65px; background: linear-gradient( #68c95c, #398f48 ); clip-path: polygon( 0 30%, 2% 0, 3% 30%, 5% 10%, 7% 35%, 9% 0, 11% 30%, 14% 5%, 16% 30%, 18% 0, 20% 35%, 23% 5%, 25% 30%, 28% 0, 30% 30%, 33% 10%, 35% 35%, 38% 0, 40% 30%, 43% 5%, 46% 35%, 49% 0, 52% 30%, 55% 8%, 58% 35%, 61% 0, 64% 30%, 67% 7%, 70% 35%, 73% 0, 76% 30%, 79% 8%, 82% 35%, 85% 0, 88% 30%, 91% 5%, 94% 35%, 97% 0, 100% 30%, 100% 100%, 0 100% ); } /* ============================= FROG ============================= */ .frog { position: absolute; z-index: 20; left: 50%; bottom: 42px; width: 150px; height: 145px; transform: translateX(-50%); transition: left .08s linear; } .frog-body { position: absolute; bottom: 5px; left: 50%; width: 105px; height: 90px; transform: translateX(-50%); border-radius: 55% 55% 40% 40%; background: #5fcf65; box-shadow: inset -9px -8px 0 rgba(0,0,0,.08); } /* HEAD */ .frog-head { position: absolute; left: 50%; top: -45px; width: 130px; height: 90px; transform: translateX(-50%); border-radius: 50% 50% 45% 45%; background: #67d96d; } /* ============================= EYES ============================= */ .eye { position: absolute; top: -24px; width: 49px; height: 49px; border-radius: 50%; background: #62cf68; } .eye-left { left: 8px; } .eye-right { right: 8px; } .eyeball { position: absolute; left: 7px; top: 5px; width: 36px; height: 36px; border-radius: 50%; background: #fffdf3; } .pupil { position: absolute; left: 12px; top: 10px; width: 15px; height: 18px; border-radius: 50%; background: #193829; } .pupil::after { content: ""; position: absolute; left: 3px; top: 2px; width: 5px; height: 5px; border-radius: 50%; background: white; } /* ============================= CHEEKS ============================= */ .cheek { position: absolute; top: 51px; width: 21px; height: 12px; border-radius: 50%; background: rgba(255,113,126,.45); } .cheek-left { left: 13px; } .cheek-right { right: 13px; } /* ============================= MOUTH ============================= */ .mouth { position: absolute; left: 50%; top: 53px; width: 36px; height: 18px; transform: translateX(-50%); border-bottom: 4px solid #276947; border-radius: 0 0 50% 50%; } /* ============================= BELLY ============================= */ .belly { position: absolute; left: 50%; top: 32px; width: 66px; height: 54px; transform: translateX(-50%); border-radius: 50%; background: #b8eb7a; } /* ============================= LEGS ============================= */ .leg { position: absolute; bottom: -4px; width: 54px; height: 28px; border-radius: 50%; background: #49b95c; } .left-leg { left: -25px; transform: rotate(-15deg); } .right-leg { right: -25px; transform: rotate(15deg); } /* ============================= SHADOW ============================= */ .frog-shadow { position: absolute; bottom: 0; left: 50%; width: 125px; height: 20px; transform: translateX(-50%); border-radius: 50%; background: rgba(0,0,0,.15); } /* ============================= TONGUE ============================= */ .tongue { position: absolute; z-index: -1; left: 50%; bottom: 25px; width: 13px; height: 0; transform: translateX(-50%); border-radius: 10px 10px 0 0; background: #ff7792; transform-origin: bottom center; transition: height .12s ease-out; } .tongue.active { height: 230px; } /* ============================= FLY ============================= */ .fly, .bee { position: absolute; z-index: 15; width: 45px; height: 45px; font-size: 32px; display: flex; align-items: center; justify-content: center; filter: drop-shadow( 0 4px 3px rgba(0,0,0,.15) ); } .fly { animation: bugWobble .35s ease-in-out infinite alternate; } .bee { animation: bugWobble .18s ease-in-out infinite alternate; } @keyframes bugWobble { from { transform: rotate(-10deg) translateX(-4px); } to { transform: rotate(10deg) translateX(4px); } } /* ============================= POP SCORE ============================= */ .point-pop { position: absolute; z-index: 100; color: #246b42; font-size: 24px; font-weight: bold; pointer-events: none; animation: pointPop .7s ease-out forwards; } @keyframes pointPop { from { transform: translateY(0) scale(.7); opacity: 1; } to { transform: translateY(-60px) scale(1.3); opacity: 0; } } /* ============================= INSTRUCTIONS ============================= */ .instructions { position: absolute; z-index: 30; left: 50%; bottom: 14px; transform: translateX(-50%); color: rgba(255,255,255,.85); font-size: 11px; letter-spacing: 2px; } /* ============================= START / GAME OVER ============================= */ .overlay { position: absolute; z-index: 200; inset: 0; display: flex; align-items: center; justify-content: center; background: rgba(24,82,79,.28); backdrop-filter: blur(5px); } .game-card { width: 320px; padding: 28px 30px; text-align: center; border: 4px solid white; border-radius: 30px; background: #fffbe9; color: #255c42; box-shadow: 0 18px 50px rgba(22,78,73,.25); } .big-frog { font-size: 65px; animation: frogBounce 1.4s ease-in-out infinite; } @keyframes frogBounce { 50% { transform: translateY(-8px); } } .game-card h1 { margin: 5px 0 10px; font-size: 32px; } .game-card p { line-height: 1.6; color: #568069; } .game-card button { display: block; width: 100%; margin: 20px 0 15px; padding: 14px; border: 0; border-radius: 30px; cursor: pointer; background: #54c966; color: white; font-size: 14px; font-weight: bold; letter-spacing: 2px; box-shadow: 0 6px 0 #319b4a; transition: .15s; } .game-card button:hover { transform: translateY(-2px); background: #60d873; } .game-card button:active { transform: translateY(4px); box-shadow: 0 2px 0 #319b4a; } .game-card small { color: #88a692; line-height: 1.5; } /* ============================= MOBILE ============================= */ @media (max-width: 600px) { .title { display: none; } .frog { transform: translateX(-50%) scale(.85); transform-origin: bottom center; } }
const frog = document.getElementById("frog"); const tongue = document.getElementById("tongue"); const objects = document.getElementById("objects"); const scoreDisplay = document.getElementById("score"); const livesDisplay = document.getElementById("lives"); const overlay = document.getElementById("overlay"); const startButton = document.getElementById("startButton"); let frogX = 50; let score = 0; let lives = 3; let gameRunning = false; let tongueActive = false; let spawnTimer; let spawnSpeed = 1100; /* ========================= START GAME ========================= */ startButton.addEventListener( "click", startGame ); function startGame() { score = 0; lives = 3; frogX = 50; spawnSpeed = 1100; gameRunning = true; scoreDisplay.textContent = score; updateLives(); frog.style.left = frogX + "%"; objects.replaceChildren(); overlay.style.display = "none"; clearInterval(spawnTimer); spawnTimer = setInterval( spawnBug, spawnSpeed ); } /* ========================= MOVEMENT ========================= */ document.addEventListener( "keydown", function(event) { if (!gameRunning) { return; } const key = event.key.toLowerCase(); if ( key === "arrowleft" || key === "a" ) { frogX -= 5; } if ( key === "arrowright" || key === "d" ) { frogX += 5; } frogX = Math.max( 7, Math.min( 93, frogX ) ); frog.style.left = frogX + "%"; if ( event.code === "Space" ) { event.preventDefault(); shootTongue(); } } ); /* ========================= TONGUE ========================= */ function shootTongue() { if (tongueActive) { return; } tongueActive = true; tongue.classList.add( "active" ); checkTongueHit(); setTimeout( function() { tongue.classList.remove( "active" ); tongueActive = false; }, 220 ); } /* ========================= CREATE BUG ========================= */ function spawnBug() { if (!gameRunning) { return; } const bug = document.createElement( "div" ); const isBee = Math.random() < .25; bug.className = isBee ? "bee" : "fly"; bug.textContent = isBee ? "\uD83D\uDC1D" : "\uD83E\uDEB0"; const x = 8 + Math.random() * 84; bug.style.left = x + "%"; bug.style.top = "-50px"; objects.appendChild( bug ); fallBug( bug, isBee ); } /* ========================= BUG FALL ========================= */ function fallBug( bug, isBee ) { let y = -50; const baseSpeed = 2.2 + score * .025; const speed = baseSpeed + Math.random() * 1.5; function fall() { if ( !gameRunning || !bug.isConnected ) { return; } y += speed; bug.style.top = y + "px"; if ( tongueActive && collision( tongue, bug ) ) { catchBug( bug, isBee ); return; } if ( y > window.innerHeight ) { bug.remove(); return; } requestAnimationFrame( fall ); } requestAnimationFrame( fall ); } /* ========================= COLLISION ========================= */ function collision( a, b ) { const A = a.getBoundingClientRect(); const B = b.getBoundingClientRect(); return !( A.right < B.left || A.left > B.right || A.bottom < B.top || A.top > B.bottom ); } /* ========================= CHECK HIT ========================= */ function checkTongueHit() { const bugs = document.querySelectorAll( ".fly, .bee" ); bugs.forEach( function(bug) { if ( collision( tongue, bug ) ) { catchBug( bug, bug.classList.contains( "bee" ) ); } } ); } /* ========================= CATCH BUG ========================= */ function catchBug( bug, isBee ) { if (!bug.isConnected) { return; } const rect = bug.getBoundingClientRect(); bug.remove(); if (isBee) { lives--; updateLives(); showPoint( rect.left, rect.top, "-1 \u2764\uFE0F" ); if (lives <= 0) { endGame(); } } else { score++; scoreDisplay.textContent = score; showPoint( rect.left, rect.top, "+1" ); if ( score > 0 && score % 8 === 0 ) { increaseDifficulty(); } } } /* ========================= POINT POPUP ========================= */ function showPoint( x, y, text ) { const point = document.createElement( "div" ); point.className = "point-pop"; point.textContent = text; point.style.left = x + "px"; point.style.top = y + "px"; document .querySelector(".game") .appendChild(point); setTimeout( function() { point.remove(); }, 700 ); } /* ========================= LIVES ========================= */ function updateLives() { let hearts = ""; for ( let i = 0; i < lives; i++ ) { hearts += "\u2764\uFE0F "; } livesDisplay.textContent = hearts; } /* ========================= DIFFICULTY ========================= */ function increaseDifficulty() { spawnSpeed = Math.max( 450, spawnSpeed - 100 ); clearInterval( spawnTimer ); spawnTimer = setInterval( spawnBug, spawnSpeed ); } /* ========================= GAME OVER ========================= */ function endGame() { gameRunning = false; clearInterval( spawnTimer ); objects.replaceChildren(); overlay.style.display = "flex"; const card = document.querySelector(".game-card"); card.replaceChildren(); function addCardItem(tag, text, className) { const item = document.createElement(tag); item.textContent = text; if (className) item.className = className; card.appendChild(item); return item; } addCardItem("div", "\uD83D\uDC38", "big-frog"); addCardItem("h1", "Game Over!"); addCardItem("p", "Froggy ate too many bees!"); addCardItem("h2", "Score: " + score); const restart = addCardItem("button", "PLAY AGAIN"); restart.id = "restartButton"; restart.type = "button"; addCardItem("small", "Flies are tasty. Bees are definitely not."); document .getElementById( "restartButton" ) .addEventListener( "click", function() { location.reload(); } ); }
terminal
JavaScript Console
Preview
Clear
close
›
Run