CAR / index.html
VIATEUR-AI's picture
Update index.html
1405201 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>Desert Road Runner</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
@import url('https://fonts.googleapis.com/css2?family=Press+Start+2P&display=swap');
body {
margin: 0;
padding: 0;
overflow: hidden;
font-family: 'Press Start 2P', cursive;
background-color: #f7f7f7;
}
#game-container {
position: relative;
width: 100vw;
height: 100vh;
background: linear-gradient(to bottom, #87CEEB 0%, #E6E6FA 50%, #F5DEB3 100%);
overflow: hidden;
}
#road {
position: absolute;
bottom: 0;
width: 100%;
height: 120px;
background-color: #333;
z-index: 5;
}
.road-marking {
position: absolute;
bottom: 45px;
width: 50px;
height: 10px;
background-color: #fff;
z-index: 6;
}
#car {
position: absolute;
bottom: 0px;
left: 40px;
width: 200px;
height: 200px;
background-image: url('https://www.chennaipainter.in/wp-content/uploads/2025/04/car-1024x434.png');
background-size: contain;
background-repeat: no-repeat;
z-index: 15;
transform: scale(0.7);
}
.obstacle {
position: absolute;
bottom: 80px;
width: 80px;
height: 70px;
background-image: url('https://www.chennaipainter.in/wp-content/uploads/2025/04/obstacle-150x150.png');
background-size: contain;
background-repeat: no-repeat;
z-index: 5;
}
.cloud {
position: absolute;
width: 100px;
height: 60px;
background-image: url('https://www.chennaipainter.in/wp-content/uploads/2025/04/cloud-300x300.png');
background-size: contain;
background-repeat: no-repeat;
opacity: 0.8;
z-index: 2;
}
.cactus {
position: absolute;
bottom: 118px;
width: 200px;
height: 500px;
background-image: url('https://www.chennaipainter.in/wp-content/uploads/2025/04/tree-150x150.png');
background-size: contain;
background-repeat: no-repeat;
z-index: 4;
}
#score {
position: absolute;
top: 20px;
right: 20px;
font-size: 20px;
color: #333;
z-index: 20;
background-color: rgba(255, 255, 255, 0.7);
padding: 10px 15px;
border-radius: 10px;
}
#game-over {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
font-size: 40px;
color: #ff3333;
text-align: center;
display: none;
z-index: 20;
background-color: rgba(255, 255, 255, 0.8);
padding: 30px;
border-radius: 20px;
box-shadow: 0 0 20px rgba(0, 0, 0, 0.3);
}
#start-screen {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(240, 230, 210, 0.9);
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
z-index: 30;
text-align: center;
}
#start-button {
margin-top: 20px;
padding: 15px 40px;
font-size: 20px;
background-color: #4CAF50;
color: white;
border: none;
border-radius: 10px;
cursor: pointer;
font-family: 'Press Start 2P', cursive;
transition: all 0.3s;
box-shadow: 0 5px 0 #2E7D32;
}
#start-button:hover {
background-color: #45a049;
transform: translateY(-2px);
}
#start-button:active {
transform: translateY(3px);
box-shadow: 0 2px 0 #2E7D32;
}
.controls {
margin-top: 30px;
display: flex;
gap: 20px;
}
.control-key {
background-color: #333;
color: white;
padding: 10px 15px;
border-radius: 5px;
font-size: 16px;
}
.sun {
position: absolute;
width: 80px;
height: 80px;
background: radial-gradient(circle, #FFD700 30%, #FFA500 70%);
border-radius: 50%;
box-shadow: 0 0 40px #FFD700;
z-index: 1;
}
@keyframes birdFly {
0% { transform: translateX(0) translateY(0); }
50% { transform: translateX(0) translateY(-10px); }
100% { transform: translateX(0) translateY(0); }
}
.bird {
animation: birdFly 1s infinite ease-in-out;
}
</style>
</head>
<body>
<div id="game-container">
<div class="sun" style="top: 50px; right: 100px;"></div>
<div id="road"></div>
<div id="score">0</div>
<div id="game-over">
GAME OVER<br>
<span id="final-score">0</span><br>
<div class="mt-4 text-xl">Press Space to Restart</div>
<div class="mt-4 text-sm">Or tap the screen on mobile</div>
</div>
<div id="start-screen">
<h1 class="text-4xl md:text-6xl mb-6 text-orange-600">play with Viateur AI</h1>
<p class="mb-8 text-lg md:text-xl max-w-2xl px-4">Avoid the obstacles and survive as long as you can in this endless desert adventure!</p>
<button id="start-button">START GAME to Viateur AI</button>
<div class="controls mt-8">
<div class="control-key"><i class="fas fa-arrow-up"></i> JUMP</div>
</div>
<div class="mt-8 text-sm text-gray-600">
<i class="fas fa-mobile-alt"></i> Tap the screen to jump on mobile
</div>
</div>
<div id="car"></div>
</div>
<script>
const gameContainer = document.getElementById('game-container');
const car = document.getElementById('car');
const scoreEl = document.getElementById('score');
const gameOverEl = document.getElementById('game-over');
const finalScoreEl = document.getElementById('final-score');
const startScreen = document.getElementById('start-screen');
const startButton = document.getElementById('start-button');
let gameSpeed = 5;
let score = 0;
let isJumping = false;
let isGameOver = false;
let gameStarted = false;
let jumpStart = 0;
let animationId;
const obstacles = [];
const clouds = [];
const birds = [];
const cacti = [];
const mountains = [];
const roadMarkings = [];
// Create initial road markings
for (let i = 0; i < 10; i++) {
const mark = document.createElement('div');
mark.className = 'road-marking';
mark.style.left = (i * 200) + 'px';
gameContainer.appendChild(mark);
roadMarkings.push({ el: mark, x: i * 200 });
}
// Create initial clouds
for (let i = 0; i < 5; i++) {
createCloud(Math.random() * window.innerWidth, Math.random() * 200);
}
// Create initial desert scenery
for (let i = 0; i < 3; i++) {
createCactus(window.innerWidth + (i * 400), Math.random() * 50 + 50);
}
for (let i = 0; i < 2; i++) {
createMountain(window.innerWidth + (i * 600), Math.random() * 100);
}
function startGame() {
gameStarted = true;
isGameOver = false;
score = 0;
gameSpeed = 5;
scoreEl.textContent = '0';
startScreen.style.display = 'none';
gameOverEl.style.display = 'none';
// Clear all game elements
obstacles.forEach(o => o.el.remove());
clouds.forEach(c => c.el.remove());
birds.forEach(b => b.el.remove());
cacti.forEach(c => c.el.remove());
mountains.forEach(m => m.el.remove());
obstacles.length = clouds.length = birds.length = cacti.length = mountains.length = 0;
// Create initial elements
for (let i = 0; i < 5; i++) {
createCloud(Math.random() * window.innerWidth, Math.random() * 200);
}
for (let i = 0; i < 3; i++) {
createCactus(window.innerWidth + (i * 400), Math.random() * 50 + 50);
}
for (let i = 0; i < 2; i++) {
createMountain(window.innerWidth + (i * 600), Math.random() * 100);
}
animationId = requestAnimationFrame(gameLoop);
}
function gameLoop() {
if (isGameOver) return cancelAnimationFrame(animationId);
score += 0.1;
scoreEl.textContent = Math.floor(score);
if (Math.floor(score) % 500 === 0) gameSpeed += 0.5;
updateCarPosition();
updateObstacles();
updateClouds();
updateBirds();
updateCacti();
updateMountains();
updateRoadMarks();
detectCollisions();
animationId = requestAnimationFrame(gameLoop);
}
function updateCarPosition() {
if (!isJumping) return;
const jumpDuration = 700;
const t = (Date.now() - jumpStart) / jumpDuration;
if (t >= 1) {
car.style.bottom = '0px';
isJumping = false;
} else {
const height = Math.round(220 * Math.sin(Math.PI * t));
car.style.bottom = height + 'px';
}
}
function updateObstacles() {
if (Math.random() < 0.0025 * gameSpeed) {
if (obstacles.length === 0 || obstacles[obstacles.length - 1].x < window.innerWidth - 400) {
createObstacle();
}
}
obstacles.forEach((obj, idx) => {
obj.x -= gameSpeed;
obj.el.style.left = obj.x + 'px';
if (obj.x < -200) {
obj.el.remove();
obstacles.splice(idx, 1);
}
});
}
function updateClouds() {
if (Math.random() < 0.002) createCloud(window.innerWidth, Math.random() * 200);
clouds.forEach((c, idx) => {
c.x -= gameSpeed * 0.5;
c.el.style.left = c.x + 'px';
if (c.x < -100) {
c.el.remove();
clouds.splice(idx, 1);
}
});
}
function updateBirds() {
if (Math.random() < 0.0005 * gameSpeed) createBird(window.innerWidth, Math.random() * 150 + 50);
birds.forEach((b, idx) => {
b.x -= gameSpeed * 0.8;
b.el.style.left = b.x + 'px';
if (b.x < -100) {
b.el.remove();
birds.splice(idx, 1);
}
});
}
function updateCacti() {
if (Math.random() < 0.0008 * gameSpeed) createCactus(window.innerWidth, Math.random() * 50 + 50);
cacti.forEach((c, idx) => {
c.x -= gameSpeed * 0.3;
c.el.style.left = c.x + 'px';
if (c.x < -100) {
c.el.remove();
cacti.splice(idx, 1);
}
});
}
function updateMountains() {
if (mountains.length < 2 || mountains[mountains.length - 1].x < window.innerWidth - 400) {
createMountain(window.innerWidth, Math.random() * 100);
}
mountains.forEach((m, idx) => {
m.x -= gameSpeed * 0.2;
m.el.style.left = m.x + 'px';
if (m.x < -300) {
m.el.remove();
mountains.splice(idx, 1);
}
});
}
function updateRoadMarks() {
roadMarkings.forEach(mark => {
mark.x -= gameSpeed;
if (mark.x < -50) mark.x = window.innerWidth;
mark.el.style.left = mark.x + 'px';
});
}
function detectCollisions() {
const carRect = car.getBoundingClientRect();
// Fine-tuned shrink values
const shrinkLeft = 30;
const shrinkRight = 30;
const shrinkTop = 10;
const shrinkBottom = 10;
const carBox = {
left: carRect.left + shrinkLeft,
right: carRect.right - shrinkRight,
top: carRect.top + shrinkTop,
bottom: carRect.bottom - shrinkBottom,
};
for (let obj of obstacles) {
const r = obj.el.getBoundingClientRect();
const obstacleBox = {
left: r.left + 20,
right: r.right - 20,
top: r.top + 20,
bottom: r.bottom - 20,
};
if (
carBox.left < obstacleBox.right &&
carBox.right > obstacleBox.left &&
carBox.top < obstacleBox.bottom &&
carBox.bottom > obstacleBox.top
) {
return triggerGameOver();
}
}
}
function triggerGameOver() {
isGameOver = true;
finalScoreEl.textContent = Math.floor(score);
gameOverEl.style.display = 'block';
}
function createObstacle() {
const el = document.createElement('div');
el.className = 'obstacle';
el.style.left = window.innerWidth + 'px';
gameContainer.appendChild(el);
obstacles.push({ el, x: window.innerWidth });
}
function createCloud(x, y) {
const el = document.createElement('div');
el.className = 'cloud';
el.style.left = x + 'px';
el.style.top = y + 'px';
gameContainer.appendChild(el);
clouds.push({ el, x });
}
function createBird(x, y) {
const el = document.createElement('div');
el.className = 'bird';
el.style.left = x + 'px';
el.style.top = y + 'px';
gameContainer.appendChild(el);
birds.push({ el, x });
}
function createCactus(x, height) {
const el = document.createElement('div');
el.className = 'cactus';
el.style.left = x + 'px';
el.style.height = height + 'px';
gameContainer.appendChild(el);
cacti.push({ el, x });
}
function createMountain(x, height) {
const el = document.createElement('div');
el.className = 'mountain';
el.style.left = x + 'px';
el.style.height = (150 + height) + 'px';
gameContainer.appendChild(el);
mountains.push({ el, x });
}
function jump() {
if (!gameStarted || isGameOver || isJumping) return;
isJumping = true;
jumpStart = Date.now();
}
document.addEventListener('keydown', e => {
if ((e.code === 'Space' || e.key === 'ArrowUp') && !gameStarted) return startGame();
if ((e.code === 'Space' || e.key === 'ArrowUp') && isGameOver) return startGame();
if ((e.code === 'Space' || e.key === 'ArrowUp')) return jump();
});
startButton.addEventListener('click', startGame);
document.addEventListener('touchstart', (e) => {
e.preventDefault();
if (!gameStarted || isGameOver) return startGame();
jump();
});
// Prevent scrolling on mobile when touching the game area
document.addEventListener('touchmove', (e) => {
if (gameStarted) e.preventDefault();
}, { passive: false });
</script>
</body>
</html>