← back to Model Arena
data/artifacts/035b7009e366/gemma3-12b.html
339 lines
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Designer Wallcoverings - Endless Runner</title>
<style>
:root {
--bg: #faf8f4;
--surface: #ffffff;
--text: #1c1a17;
--muted: #9b948a;
--accent: #b0472e;
--line: #dcdcdc;
--shadow: rgba(0, 0, 0, 0.12);
--ease: cubic-bezier(.22,1,.36,1);
}
body {
margin: 0;
overflow: hidden;
background-color: var(--bg);
font-family: 'apple-system', 'Segoe UI', 'Helvetica Neue', Arial, sans-serif;
color: var(--text);
display: flex;
flex-direction: column;
height: 100vh;
}
.top-bar {
background-color: var(--surface);
padding: 24px;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
display: flex;
align-items: center;
}
.wordmark {
font-family: 'Playfair Display', Georgia, serif;
font-size: 48px; /*Adjust size to fit*/
letter-spacing: .18em;
text-transform: uppercase;
display: inline-block;
}
canvas {
background-color: var(--surface);
display: block;
}
.game-over-screen, .win-screen {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(255, 255, 255, 0.9);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
z-index: 10;
}
.game-over-screen h1, .win-screen h1 {
font-family: 'Playfair Display', Georgia, serif;
font-size: 48px;
margin-bottom: 24px;
text-align: center;
}
.game-over-screen p, .win-screen p{
font-size: 16px;
text-align: center;
margin-bottom: 32px;
}
.restart-button, .continue-button {
background-color: var(--accent);
color: white;
padding: 12px 24px;
border: none;
font-size: 14px;
text-transform: uppercase;
letter-spacing: .15em;
cursor: pointer;
margin-top: 32px;
width: 200px; /* Fixed width */
}
.score-board {
position: fixed;
bottom: 16px;
right: 16px;
background-color: rgba(255, 255, 255, 0.8);
padding: 8px 16px;
border-radius: 8px;
box-shadow: 0 2px 4px var(--shadow);
font-size: 12px;
text-transform: uppercase;
letter-spacing: .15em;
}
</style>
</head>
<body>
<div class="top-bar">
<div class="wordmark">DESIGNER WALLCOVERINGS</div>
</div>
<canvas id="gameCanvas" width="400" height="600"></canvas>
<div class="score-board" id="scoreboard">SCORE: 0 | BEST: 0</div>
<div class="game-over-screen" id="gameOverScreen">
<h1>GAME OVER</h1>
<p>Your wallcovering design journey has ended.</p>
<button class="restart-button" onclick="restartGame()">RESTART</button>
</div>
<div class="win-screen" id="winScreen" style="display:none;">
<h1>YOU WIN!</h1>
<p>Your wallcovering design is a masterpiece!</p>
<button class="continue-button" onclick="restartGame()">CONTINUE</button>
</div>
<script>
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
let rollerX = 50;
let rollerY = canvas.height - 100;
const rollerWidth = 30;
const rollerHeight = 40;
let rollerVelocityY = 0;
const gravity = 0.6;
const jumpForce = -15;
let wallpaperRolls = [];
const wallpaperSpeed = 5;
let score = 0;
let bestScore = localStorage.getItem('bestScore') || 0;
let obstacles = [];
const obstacleSpawnRate = 120; // Frames per spawn (adjust for difficulty)
let obstacleTimer = 0;
const wallpaperStyles = ['floral', 'geometric', 'abstract', 'striped']; //For visual distinction
function createWallpaperRoll() {
const styleIndex = Math.floor(Math.random() * wallpaperStyles.length);
wallpaperRolls.push({
x: canvas.width,
y: rollerY - 20,
style: wallpaperStyles[styleIndex]
});
}
function createObstacle() {
const obstacleType = Math.random() < 0.5 ? 'pillar' : 'beam'; // Randomize obstacle type
obstacles.push({
x: canvas.width,
y: rollerY - 30,
type: obstacleType
});
}
function updateScoreboard(){
document.getElementById('scoreboard').innerText = `SCORE: ${score} | BEST: ${bestScore}`;
}
function restartGame() {
rollerX = 50;
rollerY = canvas.height - 100;
rollerVelocityY = 0;
wallpaperRolls = [];
obstacles = [];
score = 0;
updateScoreboard();
document.getElementById('gameOverScreen').style.display = 'none';
document.getElementById('winScreen').style.display = 'none';
animate(); // Restart the animation loop
}
function drawWallpaperRoll(roll) {
let styleImage;
switch (roll.style){
case "floral": styleImage="url('data:image/svg+xml,%3Csvg width%3D20 height%3D20 viewBox%3D0 0 20 20 fill%3Dnone xmlns%3Dhttp://www.w3.org/2000/svg%3E%3Cpath d%3D\"M10 4a2 2 0 01-2 0q0 1.1111107-0.8888929 1.6111071L5.6111071 11.388893a2 2 0 01-2 0l-4.22222-4.22222q-.8888929 0-1.6111071-.8888929L2 7.22222a2 2 0 010-4l3.5555556-3.5555556q.8888929 0 1.6111071.8888929L10 4Z\" fill%3D#c9a961/0.3%3E%3C/path%3E%3C/svg%3E')"; break;
case "geometric": styleImage="url('data:image/svg+xml,%3Csvg width%3D20 height%3D20 viewBox%3D0 0 20 20 fill%3Dnone xmlns%3Dhttp://www.w3.org/2000/svg%3E%3Crect x%3D4 y%3D4 width%3D12 height%3D12 stroke%3D#c9a961 stroke-width%3D2%3E%3C/rect%3E%3C/svg%3E')"; break;
case "abstract": styleImage="url('data:image/svg+xml,%3Csvg width%3D20 height%3D20 viewBox%3D0 0 20 20 fill%3Dnone xmlns%3Dhttp://www.w3.org/2000/svg%3E%3Ccircle cx%3D10 cy%3D10 r%3D8 fill%3D#c9a961/0.5%3E%3C/circle%3E%3C/svg%3E')"; break;
case "striped": styleImage="url('data:image/svg+xml,%3Csvg width%3D20 height%3D20 viewBox%3D0 0 20 20 fill%3Dnone xmlns%3Dhttp://www.w3.org/2000/svg%3E%3Crect x%3D0 y%3D0 width%3D20 height%3D5 style%3D\"fill:%23c9a961;\"%3E%3C/rect%3E%3Crect x%3D0 y%3D5 width%3D20 height%3D5 style%3D\"fill:%23faf8f4;\"%3E%3C/rect%3E%3Crect x%3D0 y%3D10 width%3D20 height%3D5 style%3D\"fill:%23c9a961;\"%3E%3C/rect%3E%3C/svg%3E')"; break;
}
ctx.drawImage(new Image(), 0, 0, 20, 20); //This is a placeholder to get the css working. Replace with loadStyleImage
}
function drawObstacle(obstacle) {
if (obstacle.type === 'pillar') {
ctx.fillStyle = '#a1c4d3'; // Blue pillar color
ctx.fillRect(obstacle.x, obstacle.y, 20, 50);
} else if (obstacle.type === 'beam') {
ctx.strokeStyle = '#a1c4d3'; // Blue beam color
ctx.lineWidth = 5;
ctx.beginPath();
ctx.moveTo(obstacle.x, obstacle.y + 20);
ctx.lineTo(obstacle.x + 30, obstacle.y + 20);
ctx.stroke();
}
}
function animate() {
requestAnimationFrame(animate);
ctx.clearRect(0, 0, canvas.width, canvas.height);
// Roller Movement
rollerVelocityY += gravity;
rollerY += rollerVelocityY;
if (rollerY > canvas.height - rollerHeight) {
rollerY = canvas.height - rollerHeight;
rollerVelocityY = 0;
}
// Wallpaper Rolls
for (let i = 0; i < wallpaperRolls.length; i++) {
drawWallpaperRoll(wallpaperRolls[i]);
wallpaperRolls[i].x -= wallpaperSpeed;
if (wallpaperRolls[i].x < 0) {
wallpaperRolls.splice(i, 1);
score++;
}
if (rollerX > wallpaperRolls[i].x -15 && rollerX < wallpaperRolls[i].x + 15 && rollerY < wallpaperRolls[i].y + 20 && rollerY > wallpaperRolls[i].y - 20) {
// Collision with wallpaper roll (collect!)
wallpaperRolls.splice(i, 1); // Remove collected roll
}
}
// Obstacles
for (let i = 0; i < obstacles.length; i++) {
drawObstacle(obstacles[i]);
obstacles[i].x -= wallpaperSpeed;
if (obstacles[i].x < 0) {
obstacles.splice(i, 1);
}
if (rollerX > obstacles[i].x -15 && rollerX < obstacles[i].x + 15 && rollerY < obstacles[i].y + 30 && rollerY > obstacles[i].y - 30) {
// Collision with obstacle (game over!)
showGameOverScreen();
return; // End the game
}
}
if(score > bestScore){
bestScore = score;
localStorage.setItem('bestScore', bestScore);
updateScoreboard()
}
// Create new wallpaper rolls and obstacles
if (obstacleTimer % obstacleSpawnRate === 0) {
createObstacle();
}
if(wallpaperRolls.length < 3){ //Limit number of rolls on screen to avoid clutter
if(Math.random() < .15){
createWallpaperRoll();
}
}
ctx.fillText(`Score: ${score}`, 10, 20);
// Draw the roller
ctx.fillStyle = '#c9a961';
ctx.fillRect(rollerX, rollerY, rollerWidth, rollerHeight);
}
function showGameOverScreen() {
document.getElementById('gameOverScreen').style.display = 'flex';
}
// Initial game setup
let animationFrameId;
function startGame(){
animationFrameId = requestAnimationFrame(animate);
updateScoreboard();
}
window.addEventListener('keydown', (e) => {
if (e.code === 'Space' || e.code === 'ArrowUp') {
if (rollerY > canvas.height - rollerHeight) {
rollerVelocityY = jumpForce;
}
}
});
canvas.addEventListener('click', () => { // Mobile Tap support
if (rollerY > canvas.height - rollerHeight) {
rollerVelocityY = jumpForce;
}
});
startGame();
</script>
</body>
</html>