<style>
#gameContainer {
background-color: #ff0000 !important;
border-color: #fff !important;
}
#score {
color: #fff !important;
}
#startButton {
background-color: #000 !important;
color: #fff !important;
}
.paddle {
background-color: #fff !important;
}
.ball {
background-color: #fff !important;
}
.centerLine {
border-color: #fff !important;
}
#gameCanvas {
background-color: #ff0000 !important;
width: 100% !important;
height: 500px !important;
}
canvas {
background-color: #ff0000 !important;
}
#gameContainer {
margin: 0;
padding: 10px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
background-color: #000;
font-family: 'PixelFont', sans-serif;
position: relative;
border: 2px solid #fff;
}
#gameCanvas {
background-color: #000;
display: block;
}
#score {
color: #fff;
font-size: 24px;
position: absolute;
top: 20px;
font-family: 'PixelFont', sans-serif;
}
#startButton {
color: #fff;
font-size: 24px;
font-family: 'PixelFont', sans-serif;
animation: blink 1s infinite;
position: absolute;
}
@keyframes blink {
50% {
opacity: 0;
}
}
#colorForm {
position: relative;
background: black;
padding: 10px;
border-radius: 0px;
}
#mobileControls {
position: absolute;
bottom: 10px;
display: flex;
gap: 10px;
}
#mobileControls button {
padding: 10px;
font-size: 18px;
font-family: 'PixelFont', sans-serif;
}
</style>
<div id="gameContainer">
<div id="score">0 - 0</div>
<canvas id="gameCanvas"></canvas>
<button id="startButton" style="background:black !important; color: #fff !important;">START</button>
<div id="mobileControls" style="display: none;">
<button id="moveUpButton">Up</button>
<button id="moveDownButton">Down</button>
</div>
</div>
<!--- GAME JS --->
<script>
let canvasColor = '#000';
let paddleColor = '#fff';
let textColor = '#fff';
let ballColor = '#fff';
let borderColor = '#fff';
let centerLineColor = '#fff';
const watermarkBase64 = 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyBpZD0iYiIgZGF0YS1uYW1lPSJMYXllciAyIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI3My4yNzIiIGhlaWdodD0iMjEuMjQ4IiB2aWV3Qm94PSIwIDAgNzMuMjcyIDIxLjI0OCI+CiAgPGcgaWQ9ImMiIGRhdGEtbmFtZT0iTGF5ZXIgMSI+CiAgICA8ZyBvcGFjaXR5PSIuNiI+CiAgICAgIDxwb2x5Z29uIHBvaW50cz0iMTcuMzIzIDAgMTcuMjM4IDEuMTU1IDE4LjUzNiAxLjE1NSAxOC4yOTIgNC42ODQgMTYuOTc2IDQuNjg0IDE3LjA2NCAzLjQ5NiAxNC40NDQgMy40OTYgMTQuNTQzIDIuMzIgMTAuNjI4IDIuMzIgMTAuNTEyIDMuNDk2IDEzLjEzMiAzLjQ5NiAxMy4wMjYgNC42ODQgMTQuMzQ1IDQuNjg0IDE0LjI0NCA1Ljg4MSAxMS41OTggNS44ODEgMTEuNDg0IDcuMDg5IDE1LjQ3IDcuMDg5IDE1LjU2NiA1Ljg4MSAxOC4yMDkgNS44ODEgMTguMDQxIDguMzEgMTYuNzA3IDguMzEgMTYuNjE2IDkuNTQgOC41NzIgOS41NCA4LjY5OSA4LjMxIDcuMzY2IDguMzEgNy42MyA1Ljg4MSA4Ljk1MiA1Ljg4MSA5LjA3NiA0LjY4NCA3Ljc2IDQuNjg0IDguMTQ0IDEuMTU1IDkuNDQyIDEuMTU1IDkuNTYyIDAgMTcuMzIzIDAiIGZpbGw9IiNmZmYiIHN0cm9rZS13aWR0aD0iMCIvPgogICAgICA8cGF0aCBkPSJNNjQuNDk1LDUuODgxaC0xLjMyMmwuMTE5LDEuMjA4aDEuMzI4bC4xMjcsMS4yMjFoMS4zMzdsLjEzNCwxLjIzaC00LjAyMmwtLjExNi0xLjIzaC0xLjMzN2wtLjEwOS0xLjIyMWgtMS4zMjhsLjIwNiwyLjQ1MWgtNC4wMjJsLS4xNy0yLjQ1MWgxLjMzMWwtLjM1NC00Ljc2OWgtMS4zMDdMNTQuODMsMGg3Ljc2MWwuMTE0LDEuMTU1aDEuMjk4bC4xMjEsMS4xNjVoMS4zMDdsLjI1NywyLjM2NGgtMS4zMTlsLjEyNCwxLjE5N1pNNjEuNjI3LDMuNDk2aDEuMzFsLS4xMTYtMS4xNzZoLTMuOTE1bC4xOTksMi4zNjRoMi42MzRsLS4xMTItMS4xODkiIGZpbGw9IiNmZmYiIHN0cm9rZS13aWR0aD0iMCIvPgogICAgICA8cGF0aCBkPSJNNDAuNjkxLDUuODgxaC0xLjMyMmwuMDEyLDEuMjA4aDEuMzI4bC4wMTgsMS4yMjFoMS4zMzRsLjAyNCwxLjIzaC00LjAxOWwtLjAwNi0xLjIzaC0xLjMzN3YtMS4yMjFoLTEuMzI4bC0uMDEyLDIuNDUxaC00LjAyMmwuMDQ4LTIuNDUxaDEuMzNsLjA3MS00Ljc2OWgtMS4zMDdMMzEuNTUsMGg3Ljc2MWwuMDExLDEuMTU1aDEuMjk4bC4wMTcsMS4xNjVoMS4zMDRsLjA0NywyLjM2NGgtMS4zMTZsLjAxOCwxLjE5N1pNMzguMDM2LDMuNDk2aDEuMzFsLS4wMTItMS4xNzZoLTMuOTE1bC0uMDEyLDIuMzY0aDIuNjM0bC0uMDA2LTEuMTg5IiBmaWxsPSIjZmZmIiBzdHJva2Utd2lkdGg9IjAiLz4KICAgICAgPHBhdGggZD0iTTI4Ljc5LDUuODgxaC0xLjMyNWwtLjA0MiwxLjIwOGgxLjMzMWwtLjAzNiwxLjIyMWgxLjMzNGwtLjAzLDEuMjNoLTQuMDIybC4wNDktMS4yM2gtMS4zMzRsLjA1NC0xLjIyMWgtMS4zMjhsLS4xMjEsMi40NTFoLTQuMDIybC4xNTgtMi40NTFoMS4zMjhsLjI4My00Ljc2OWgtMS4zMDRMMTkuOTExLDBoNy43NThsLS4wNCwxLjE1NWgxLjMwMWwtLjAzNSwxLjE2NWgxLjMwNGwtLjA1OCwyLjM2NGgtMS4zMTZsLS4wMzUsMS4xOTdaTTI2LjIzOSwzLjQ5NmgxLjMxbC4wNDEtMS4xNzZoLTMuOTEybC0uMTE3LDIuMzY0aDIuNjMxbC4wNDctMS4xODkiIGZpbGw9IiNmZmYiIHN0cm9rZS13aWR0aD0iMCIvPgogICAgICA8cGF0aCBkPSJNNTIuMzgzLDIuMzJoMS4zMDRsLjM4NSw1Ljk5aC0xLjMzNGwuMDczLDEuMjNoLTYuNzA0bC0uMDQzLTEuMjNoLTEuMzM0bC0uMDM2LTEuMjIxaC0xLjMyOGwtLjE0Ny01LjkzNGgxLjI5OEw0NC40ODQsMGg2LjQ2NmwuMDYzLDEuMTU1aDEuMzAxbC4wNjksMS4xNjVaTTUxLjI3LDUuODgxbC0uMDY1LTEuMTk3aC0xLjMxNmwtLjA1OS0xLjE4OWgtMS4zMWwtLjA1Mi0xLjE3NmgtMS4zMDRsLjA0NywxLjE3NmgtMS4zMTNsLjA0MSwxLjE4OWgxLjMxOWwuMDQ3LDEuMTk3aDEuMzIybC4wNTQsMS4yMDhoMS4zMjhsLS4wNi0xLjIwOGgxLjMyMiIgZmlsbD0iI2ZmZiIgc3Ryb2tlLXdpZHRoPSIwIi8+CiAgICAgIDxwb2x5Z29uIHBvaW50cz0iNzAuNzU0IDEwLjg4MyA3MC45MSAxMi4xMzYgNzIuMjYzIDEyLjEzNiA3Mi43NiAxNS45NjkgNzEuMzg5IDE1Ljk2OSA3MS4yMjggMTQuNjggNjguNDk1IDE0LjY4IDY4LjM0OCAxMy40MDEgNjQuMjcxIDEzLjQwMSA2NC40IDE0LjY4IDY3LjEzIDE0LjY4IDY3LjI3MiAxNS45NjkgNjguNjQzIDE1Ljk2OSA2OC43OTMgMTcuMjY5IDY2LjAzNyAxNy4yNjkgNjYuMTc1IDE4LjU4NSA3MC4zMzEgMTguNTg1IDcwLjE3NCAxNy4yNjkgNzIuOTI5IDE3LjI2OSA3My4yNzIgMTkuOTExIDcxLjg4MSAxOS45MTEgNzIuMDQ5IDIxLjI0OCA2My42NTcgMjEuMjQ4IDYzLjUzIDE5LjkxMSA2Mi4xMzkgMTkuOTExIDYxLjkgMTcuMjY5IDYzLjI3OCAxNy4yNjkgNjMuMTU0IDE1Ljk2OSA2MS43ODMgMTUuOTY5IDYxLjQzNyAxMi4xMzYgNjIuNzg5IDEyLjEzNiA2Mi42NyAxMC44ODMgNzAuNzU0IDEwLjg4MyIgZmlsbD0iI2ZmZiIgc3Ryb2tlLXdpZHRoPSIwIi8+CiAgICAgIDxwb2x5Z29uIHBvaW50cz0iMzUuMDI1IDEwLjg4MyAzNS4wMTcgMTIuMTM2IDM2LjM3MyAxMi4xMzYgMzYuMzY4IDE1Ljk2OSAzNC45OTQgMTUuOTY5IDM1LjAwMiAxNC42OCAzMy42MzcgMTQuNjggMzMuNjUxIDEzLjQwMSAyOS41NzEgMTMuNDAxIDI5LjUzOCAxNC42OCAyOC4xNzMgMTQuNjggMjguMDkzIDE3LjI2OSAyOS40NzEgMTcuMjY5IDI5LjQzNyAxOC41ODUgMzMuNTkzIDE4LjU4NSAzMy42MDggMTcuMjY5IDM2LjM2NiAxNy4yNjkgMzYuMzY1IDE4LjU4NSAzNC45NzcgMTguNTg1IDM0Ljk2OSAxOS45MTEgMzMuNTc4IDE5LjkxMSAzMy41NjMgMjEuMjQ4IDI3Ljk3IDIxLjI0OCAyOC4wMTEgMTkuOTExIDI2LjYyIDE5LjkxMSAyNi42NjggMTguNTg1IDI1LjI4IDE4LjU4NSAyNS40OTIgMTMuNDAxIDI2Ljg1NCAxMy40MDEgMjYuODk5IDEyLjEzNiAyOC4yNTIgMTIuMTM2IDI4LjI5MSAxMC44ODMgMzUuMDI1IDEwLjg4MyIgZmlsbD0iI2ZmZiIgc3Ryb2tlLXdpZHRoPSIwIi8+CiAgICAgIDxwYXRoIGQ9Ik0yMi41NzgsMTcuMjY5aC0xLjM3OGwtLjA3MywxLjMxNmgxLjM4NGwtLjA2NywxLjMyNWgxLjM5MWwtLjA2MSwxLjMzOGgtNC4xOTZsLjA4MS0xLjMzOGgtMS4zOTFsLjA4Ny0xLjMyNWgtMS4zODRsLS4xODgsMi42NjNoLTQuMTk2bC4yMjctMi42NjNoMS4zODRsLjQxNy01LjE4NGgtMS4zNTlsLjIxNS0yLjUxOGg4LjA4NGwtLjA3LDEuMjUzaDEuMzUzbC0uMDY0LDEuMjY1aDEuMzU5bC0uMTE4LDIuNTY4aC0xLjM3MWwtLjA2NiwxLjMwMVpNMTkuOTc2LDE0LjY4aDEuMzY4bC4wNzEtMS4yNzloLTQuMDc5bC0uMTgxLDIuNTY4aDIuNzQzbC4wNzgtMS4yODkiIGZpbGw9IiNmZmYiIHN0cm9rZS13aWR0aD0iMCIvPgogICAgICA8cGF0aCBkPSJNNTguODMzLDEzLjQwMWgxLjM1OWwuNTU2LDYuNTFoLTEuMzkxbC4xMDgsMS4zMzhoLTkuNzg5bC0uMTgyLTMuOTc5aDEuMzc4bC0uMTk2LTMuODY5aC0xLjM1OWwtLjExNS0yLjUxOGg4LjA4MWwuMDk1LDEuMjUzaDEuMzU1bC4xMDIsMS4yNjVaTTU3Ljc2MywxNy4yNjlsLS4wOTgtMS4zMDFoLTEuMzcybC0uMDkxLTEuMjg5aC0xLjM2NWwtLjA4NC0xLjI3OWgtMS4zNjJsLjIzNSwzLjg2OWgxLjM4MWwuMDg2LDEuMzE2aDEuMzg0bC0uMDkzLTEuMzE2aDEuMzc4IiBmaWxsPSIjZmZmIiBzdHJva2Utd2lkdGg9IjAiLz4KICAgICAgPHBhdGggZD0iTTEwLjY1NywxMi4xMzZoMS4zNTZsLS44MjMsOS4xMTNoLTQuMTk2bC4xNDEtMS4zMzhIMi45NTlsLS4xNjEsMS4zMzhIMGwuMzQ2LTIuNjYzaDEuMzg3bC4zMjctMi42MTZoMS4zNzJsLjE1NS0xLjI4OWgxLjM2NWwuMjkzLTIuNTQ0aC0xLjM1MmwuMTUtMS4yNTNoNi43MzVsLS4xMTksMS4yNTNaTTguNzksMTcuMjY5bC4yNTktMi41ODloLTEuMzY1bC0uMTM1LDEuMjg5aC0xLjM3MWwtLjE0MywxLjMwMWgyLjc1NiIgZmlsbD0iI2ZmZiIgc3Ryb2tlLXdpZHRoPSIwIi8+CiAgICAgIDxwYXRoIGQ9Ik00Ni41NSwxMi4xMzZoMS4zNTJsLjM3Miw5LjExM2gtNC4xOTZsLS4wMzUtMS4zMzhoLTQuMTczbC4wMTUsMS4zMzhoLTIuNzk4bC0uMDAzLTIuNjYzaDEuMzg0bC0uMDE2LTIuNjE2aDEuMzc0bC0uMDE0LTEuMjg5aDEuMzY1bC0uMDQxLTIuNTQ0aC0xLjM1M2wtLjAxNC0xLjI1M2g2LjczNWwuMDQ1LDEuMjUzWk00NS4zNTYsMTcuMjY5bC0uMDgtMi41ODloLTEuMzY4bC4wMzQsMS4yODloLTEuMzcxbC4wMjcsMS4zMDFoMi43NTkiIGZpbGw9IiNmZmYiIHN0cm9rZS13aWR0aD0iMCIvPgogICAgPC9nPgogIDwvZz4KPC9zdmc+'; // Example Base64 string
function updateColor(element, color) {
switch (element) {
case 'canvasColor':
canvasColor = color;
document.getElementById('gameContainer').style.backgroundColor = color;
break;
case 'paddleColor':
paddleColor = color;
break;
case 'textColor':
textColor = color;
break;
case 'ballColor':
ballColor = color;
break;
case 'borderColor':
borderColor = color;
document.getElementById('gameContainer').style.borderColor = color;
break;
case 'centerLineColor':
centerLineColor = color;
break;
}
draw();
saveColors(); // Call saveColors after updating colors
}
function saveColors() {
const canvasWidth = document.getElementById('canvasWidth').value || canvas.style.width;
const canvasHeight = document.getElementById('canvasHeight').value || canvas.style.height;
const css = `
<style>
#gameContainer {
background-color: ${canvasColor} !important;
border-color: ${borderColor} !important;
}
#score {
color: ${textColor} !important;
}
#startButton {
background-color: ${textColor} !important;
}
.paddle {
background-color: ${paddleColor} !important;
}
.ball {
background-color: ${ballColor} !important;
}
.centerLine {
border-color: ${centerLineColor} !important;
}
#gameCanvas {
background-color: ${canvasColor} !important;
width: ${canvasWidth} !important;
height: ${canvasHeight} !important;
}
canvas {
background-color: ${canvasColor} !important;
}
</style>
`;
const trimmedCss = css.trim();
document.getElementById('add-css').value = trimmedCss;
document.getElementById('add-css-export').innerHTML = trimmedCss;
}
function updateCanvasSize() {
const canvasWidth = document.getElementById('canvasWidth').value;
const canvasHeight = document.getElementById('canvasHeight').value;
if (canvasWidth) {
canvas.style.width = canvasWidth;
}
if (canvasHeight) {
canvas.style.height = canvasHeight;
}
canvas.width = canvas.offsetWidth;
canvas.height = canvas.offsetHeight;
draw(); // Redraw the canvas with the new size
}
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
const paddleHeight = 100;
const paddleWidth = 10;
const ballRadius = 7;
let upPressed = false;
let downPressed = false;
let playerY = (canvas.height - paddleHeight) / 2;
let aiY = (canvas.height - paddleHeight) / 2;
let ballX = canvas.width / 2;
let ballY = canvas.height / 2;
let ballSpeedX = 3;
let ballSpeedY = 2;
let playerScore = 0;
let aiScore = 0;
let gameStarted = false;
document.addEventListener('keydown', (e) => {
if (e.key === 'ArrowUp') {
upPressed = true;
e.preventDefault();
}
if (e.key === 'ArrowDown') {
downPressed = true;
e.preventDefault();
}
});
document.addEventListener('keyup', (e) => {
if (e.key === 'ArrowUp') {
upPressed = false;
e.preventDefault();
}
if (e.key === 'ArrowDown') {
downPressed = false;
e.preventDefault();
}
});
document.getElementById('moveUpButton').addEventListener('mousedown', () => {
upPressed = true;
});
document.getElementById('moveUpButton').addEventListener('mouseup', () => {
upPressed = false;
});
document.getElementById('moveDownButton').addEventListener('mousedown', () => {
downPressed = true;
});
document.getElementById('moveDownButton').addEventListener('mouseup', () => {
downPressed = false;
});
function drawPaddle(x, y) {
ctx.fillStyle = paddleColor;
ctx.fillRect(x, y, paddleWidth, paddleHeight);
}
function drawBall() {
ctx.beginPath();
ctx.arc(ballX, ballY, ballRadius, 0, Math.PI * 2);
ctx.fillStyle = ballColor;
ctx.fill();
ctx.closePath();
}
function drawWatermark() {
const img = new Image();
img.src = watermarkBase64;
img.onload = () => {
const imgWidth = img.width * 2; // Increase size
const imgHeight = img.height * 2; // Increase size
const x = (canvas.width - imgWidth) / 2;
const y = canvas.height - imgHeight - 10; // 10px from the bottom
ctx.drawImage(img, x, y, imgWidth, imgHeight);
canvas.addEventListener('click', (e) => {
const rect = canvas.getBoundingClientRect();
const mouseX = e.clientX - rect.left;
const mouseY = e.clientY - rect.top;
if (mouseX >= x && mouseX <= x + imgWidth && mouseY >= y && mouseY <= y + imgHeight) {
window.open('https://errorarcade.webflow.io/', '_blank');
}
});
};
}
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = canvasColor;
ctx.fillRect(0, 0, canvas.width, canvas.height);
drawPaddle(0, playerY);
drawPaddle(canvas.width - paddleWidth, aiY);
drawBall();
drawWatermark();
// Draw center line
ctx.beginPath();
ctx.setLineDash([10, 8]);
ctx.moveTo(canvas.width / 2, 0);
ctx.lineTo(canvas.width / 2, canvas.height);
ctx.strokeStyle = centerLineColor;
ctx.stroke();
ctx.closePath();
document.getElementById('score').innerText = `${playerScore} - ${aiScore}`;
}
function movePaddle() {
if (upPressed && playerY > 0) playerY -= 5;
if (downPressed && playerY < canvas.height - paddleHeight) playerY += 5;
}
function moveBall() {
ballX += ballSpeedX;
ballY += ballSpeedY;
if (ballY + ballSpeedY > canvas.height - ballRadius || ballY + ballSpeedY < ballRadius) {
ballSpeedY = -ballSpeedY;
}
if (ballX + ballSpeedX > canvas.width - paddleWidth - ballRadius) {
if (ballY > aiY && ballY < aiY + paddleHeight) {
ballSpeedX = -ballSpeedX;
// Add some randomness to the ball speed
ballSpeedY += (Math.random() - 0.5) * 2;
} else {
playerScore++;
resetBall();
}
} else if (ballX + ballSpeedX < paddleWidth + ballRadius) {
if (ballY > playerY && ballY < playerY + paddleHeight) {
ballSpeedX = -ballSpeedX;
// Add some randomness to the ball speed
ballSpeedY += (Math.random() - 0.5) * 2;
} else {
aiScore++;
resetBall();
}
}
// AI Movement with a chance to miss
if (ballX > canvas.width / 2 && Math.random() > 0.1) {
aiY = ballY - paddleHeight / 2;
}
}
function resetBall() {
ballX = canvas.width / 2;
ballY = canvas.height / 2;
ballSpeedX = -ballSpeedX;
ballSpeedY = (Math.random() - 0.5) * 4;
}
function update() {
if (!gameStarted) return;
if (playerScore >= 3 || aiScore >= 3) {
alert(`Game Over! ${playerScore >= 3 ? 'Player' : 'AI'} Wins!`);
playerScore = 0;
aiScore = 0;
resetBall();
gameStarted = false;
document.getElementById('startButton').style.display = 'block';
}
movePaddle();
moveBall();
draw();
}
const startButton = document.getElementById('startButton');
startButton.addEventListener('click', () => {
gameStarted = true;
startButton.style.display = 'none';
setInterval(update, 1000 / 60);
});
// Show mobile controls if on a mobile device and set default canvas size
if (/Mobi|Android/i.test(navigator.userAgent)) {
document.getElementById('mobileControls').style.display = 'flex';
canvas.style.width = '100%';
canvas.style.height = '500px';
} else {
canvas.style.width = '100%';
canvas.style.height = '500px';
}
canvas.width = canvas.offsetWidth;
canvas.height = canvas.offsetHeight;
draw(); // Initial draw to reflect default size
</script>
<style>
#gameContainer {
background-color: #ff0000 !important;
border-color: #fff !important;
}
#score {
color: #fff !important;
}
#startButton {
background-color: #000 !important;
color: #fff !important;
}
.paddle {
background-color: #fff !important;
}
.ball {
background-color: #fff !important;
}
.centerLine {
border-color: #fff !important;
}
#gameCanvas {
background-color: #ff0000 !important;
width: 100% !important;
height: 500px !important;
}
canvas {
background-color: #ff0000 !important;
}
#gameContainer {
margin: 0;
padding: 10px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
background-color: #000;
font-family: 'PixelFont', sans-serif;
position: relative;
border: 2px solid #fff;
}
#gameCanvas {
background-color: #000;
display: block;
}
#score {
color: #fff;
font-size: 24px;
position: absolute;
top: 20px;
font-family: 'PixelFont', sans-serif;
}
#startButton {
color: #fff;
font-size: 24px;
font-family: 'PixelFont', sans-serif;
animation: blink 1s infinite;
position: absolute;
}
@keyframes blink {
50% {
opacity: 0;
}
}
#colorForm {
position: relative;
background: black;
padding: 10px;
border-radius: 0px;
}
#mobileControls {
position: absolute;
bottom: 10px;
display: flex;
gap: 10px;
}
#mobileControls button {
padding: 10px;
font-size: 18px;
font-family: 'PixelFont', sans-serif;
}
</style>
<div id="gameContainer">
<div id="score">0 - 0</div>
<canvas id="gameCanvas"></canvas>
<button id="startButton" style="background:black !important; color: #fff !important;">START</button>
<div id="mobileControls" style="display: none;">
<button id="moveUpButton">Up</button>
<button id="moveDownButton">Down</button>
</div>
</div>
<!--- GAME JS --->
<script>
let canvasColor = '#000';
let paddleColor = '#fff';
let textColor = '#fff';
let ballColor = '#fff';
let borderColor = '#fff';
let centerLineColor = '#fff';
const watermarkBase64 = 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyBpZD0iYiIgZGF0YS1uYW1lPSJMYXllciAyIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI3My4yNzIiIGhlaWdodD0iMjEuMjQ4IiB2aWV3Qm94PSIwIDAgNzMuMjcyIDIxLjI0OCI+CiAgPGcgaWQ9ImMiIGRhdGEtbmFtZT0iTGF5ZXIgMSI+CiAgICA8ZyBvcGFjaXR5PSIuNiI+CiAgICAgIDxwb2x5Z29uIHBvaW50cz0iMTcuMzIzIDAgMTcuMjM4IDEuMTU1IDE4LjUzNiAxLjE1NSAxOC4yOTIgNC42ODQgMTYuOTc2IDQuNjg0IDE3LjA2NCAzLjQ5NiAxNC40NDQgMy40OTYgMTQuNTQzIDIuMzIgMTAuNjI4IDIuMzIgMTAuNTEyIDMuNDk2IDEzLjEzMiAzLjQ5NiAxMy4wMjYgNC42ODQgMTQuMzQ1IDQuNjg0IDE0LjI0NCA1Ljg4MSAxMS41OTggNS44ODEgMTEuNDg0IDcuMDg5IDE1LjQ3IDcuMDg5IDE1LjU2NiA1Ljg4MSAxOC4yMDkgNS44ODEgMTguMDQxIDguMzEgMTYuNzA3IDguMzEgMTYuNjE2IDkuNTQgOC41NzIgOS41NCA4LjY5OSA4LjMxIDcuMzY2IDguMzEgNy42MyA1Ljg4MSA4Ljk1MiA1Ljg4MSA5LjA3NiA0LjY4NCA3Ljc2IDQuNjg0IDguMTQ0IDEuMTU1IDkuNDQyIDEuMTU1IDkuNTYyIDAgMTcuMzIzIDAiIGZpbGw9IiNmZmYiIHN0cm9rZS13aWR0aD0iMCIvPgogICAgICA8cGF0aCBkPSJNNjQuNDk1LDUuODgxaC0xLjMyMmwuMTE5LDEuMjA4aDEuMzI4bC4xMjcsMS4yMjFoMS4zMzdsLjEzNCwxLjIzaC00LjAyMmwtLjExNi0xLjIzaC0xLjMzN2wtLjEwOS0xLjIyMWgtMS4zMjhsLjIwNiwyLjQ1MWgtNC4wMjJsLS4xNy0yLjQ1MWgxLjMzMWwtLjM1NC00Ljc2OWgtMS4zMDdMNTQuODMsMGg3Ljc2MWwuMTE0LDEuMTU1aDEuMjk4bC4xMjEsMS4xNjVoMS4zMDdsLjI1NywyLjM2NGgtMS4zMTlsLjEyNCwxLjE5N1pNNjEuNjI3LDMuNDk2aDEuMzFsLS4xMTYtMS4xNzZoLTMuOTE1bC4xOTksMi4zNjRoMi42MzRsLS4xMTItMS4xODkiIGZpbGw9IiNmZmYiIHN0cm9rZS13aWR0aD0iMCIvPgogICAgICA8cGF0aCBkPSJNNDAuNjkxLDUuODgxaC0xLjMyMmwuMDEyLDEuMjA4aDEuMzI4bC4wMTgsMS4yMjFoMS4zMzRsLjAyNCwxLjIzaC00LjAxOWwtLjAwNi0xLjIzaC0xLjMzN3YtMS4yMjFoLTEuMzI4bC0uMDEyLDIuNDUxaC00LjAyMmwuMDQ4LTIuNDUxaDEuMzNsLjA3MS00Ljc2OWgtMS4zMDdMMzEuNTUsMGg3Ljc2MWwuMDExLDEuMTU1aDEuMjk4bC4wMTcsMS4xNjVoMS4zMDRsLjA0NywyLjM2NGgtMS4zMTZsLjAxOCwxLjE5N1pNMzguMDM2LDMuNDk2aDEuMzFsLS4wMTItMS4xNzZoLTMuOTE1bC0uMDEyLDIuMzY0aDIuNjM0bC0uMDA2LTEuMTg5IiBmaWxsPSIjZmZmIiBzdHJva2Utd2lkdGg9IjAiLz4KICAgICAgPHBhdGggZD0iTTI4Ljc5LDUuODgxaC0xLjMyNWwtLjA0MiwxLjIwOGgxLjMzMWwtLjAzNiwxLjIyMWgxLjMzNGwtLjAzLDEuMjNoLTQuMDIybC4wNDktMS4yM2gtMS4zMzRsLjA1NC0xLjIyMWgtMS4zMjhsLS4xMjEsMi40NTFoLTQuMDIybC4xNTgtMi40NTFoMS4zMjhsLjI4My00Ljc2OWgtMS4zMDRMMTkuOTExLDBoNy43NThsLS4wNCwxLjE1NWgxLjMwMWwtLjAzNSwxLjE2NWgxLjMwNGwtLjA1OCwyLjM2NGgtMS4zMTZsLS4wMzUsMS4xOTdaTTI2LjIzOSwzLjQ5NmgxLjMxbC4wNDEtMS4xNzZoLTMuOTEybC0uMTE3LDIuMzY0aDIuNjMxbC4wNDctMS4xODkiIGZpbGw9IiNmZmYiIHN0cm9rZS13aWR0aD0iMCIvPgogICAgICA8cGF0aCBkPSJNNTIuMzgzLDIuMzJoMS4zMDRsLjM4NSw1Ljk5aC0xLjMzNGwuMDczLDEuMjNoLTYuNzA0bC0uMDQzLTEuMjNoLTEuMzM0bC0uMDM2LTEuMjIxaC0xLjMyOGwtLjE0Ny01LjkzNGgxLjI5OEw0NC40ODQsMGg2LjQ2NmwuMDYzLDEuMTU1aDEuMzAxbC4wNjksMS4xNjVaTTUxLjI3LDUuODgxbC0uMDY1LTEuMTk3aC0xLjMxNmwtLjA1OS0xLjE4OWgtMS4zMWwtLjA1Mi0xLjE3NmgtMS4zMDRsLjA0NywxLjE3NmgtMS4zMTNsLjA0MSwxLjE4OWgxLjMxOWwuMDQ3LDEuMTk3aDEuMzIybC4wNTQsMS4yMDhoMS4zMjhsLS4wNi0xLjIwOGgxLjMyMiIgZmlsbD0iI2ZmZiIgc3Ryb2tlLXdpZHRoPSIwIi8+CiAgICAgIDxwb2x5Z29uIHBvaW50cz0iNzAuNzU0IDEwLjg4MyA3MC45MSAxMi4xMzYgNzIuMjYzIDEyLjEzNiA3Mi43NiAxNS45NjkgNzEuMzg5IDE1Ljk2OSA3MS4yMjggMTQuNjggNjguNDk1IDE0LjY4IDY4LjM0OCAxMy40MDEgNjQuMjcxIDEzLjQwMSA2NC40IDE0LjY4IDY3LjEzIDE0LjY4IDY3LjI3MiAxNS45NjkgNjguNjQzIDE1Ljk2OSA2OC43OTMgMTcuMjY5IDY2LjAzNyAxNy4yNjkgNjYuMTc1IDE4LjU4NSA3MC4zMzEgMTguNTg1IDcwLjE3NCAxNy4yNjkgNzIuOTI5IDE3LjI2OSA3My4yNzIgMTkuOTExIDcxLjg4MSAxOS45MTEgNzIuMDQ5IDIxLjI0OCA2My42NTcgMjEuMjQ4IDYzLjUzIDE5LjkxMSA2Mi4xMzkgMTkuOTExIDYxLjkgMTcuMjY5IDYzLjI3OCAxNy4yNjkgNjMuMTU0IDE1Ljk2OSA2MS43ODMgMTUuOTY5IDYxLjQzNyAxMi4xMzYgNjIuNzg5IDEyLjEzNiA2Mi42NyAxMC44ODMgNzAuNzU0IDEwLjg4MyIgZmlsbD0iI2ZmZiIgc3Ryb2tlLXdpZHRoPSIwIi8+CiAgICAgIDxwb2x5Z29uIHBvaW50cz0iMzUuMDI1IDEwLjg4MyAzNS4wMTcgMTIuMTM2IDM2LjM3MyAxMi4xMzYgMzYuMzY4IDE1Ljk2OSAzNC45OTQgMTUuOTY5IDM1LjAwMiAxNC42OCAzMy42MzcgMTQuNjggMzMuNjUxIDEzLjQwMSAyOS41NzEgMTMuNDAxIDI5LjUzOCAxNC42OCAyOC4xNzMgMTQuNjggMjguMDkzIDE3LjI2OSAyOS40NzEgMTcuMjY5IDI5LjQzNyAxOC41ODUgMzMuNTkzIDE4LjU4NSAzMy42MDggMTcuMjY5IDM2LjM2NiAxNy4yNjkgMzYuMzY1IDE4LjU4NSAzNC45NzcgMTguNTg1IDM0Ljk2OSAxOS45MTEgMzMuNTc4IDE5LjkxMSAzMy41NjMgMjEuMjQ4IDI3Ljk3IDIxLjI0OCAyOC4wMTEgMTkuOTExIDI2LjYyIDE5LjkxMSAyNi42NjggMTguNTg1IDI1LjI4IDE4LjU4NSAyNS40OTIgMTMuNDAxIDI2Ljg1NCAxMy40MDEgMjYuODk5IDEyLjEzNiAyOC4yNTIgMTIuMTM2IDI4LjI5MSAxMC44ODMgMzUuMDI1IDEwLjg4MyIgZmlsbD0iI2ZmZiIgc3Ryb2tlLXdpZHRoPSIwIi8+CiAgICAgIDxwYXRoIGQ9Ik0yMi41NzgsMTcuMjY5aC0xLjM3OGwtLjA3MywxLjMxNmgxLjM4NGwtLjA2NywxLjMyNWgxLjM5MWwtLjA2MSwxLjMzOGgtNC4xOTZsLjA4MS0xLjMzOGgtMS4zOTFsLjA4Ny0xLjMyNWgtMS4zODRsLS4xODgsMi42NjNoLTQuMTk2bC4yMjctMi42NjNoMS4zODRsLjQxNy01LjE4NGgtMS4zNTlsLjIxNS0yLjUxOGg4LjA4NGwtLjA3LDEuMjUzaDEuMzUzbC0uMDY0LDEuMjY1aDEuMzU5bC0uMTE4LDIuNTY4aC0xLjM3MWwtLjA2NiwxLjMwMVpNMTkuOTc2LDE0LjY4aDEuMzY4bC4wNzEtMS4yNzloLTQuMDc5bC0uMTgxLDIuNTY4aDIuNzQzbC4wNzgtMS4yODkiIGZpbGw9IiNmZmYiIHN0cm9rZS13aWR0aD0iMCIvPgogICAgICA8cGF0aCBkPSJNNTguODMzLDEzLjQwMWgxLjM1OWwuNTU2LDYuNTFoLTEuMzkxbC4xMDgsMS4zMzhoLTkuNzg5bC0uMTgyLTMuOTc5aDEuMzc4bC0uMTk2LTMuODY5aC0xLjM1OWwtLjExNS0yLjUxOGg4LjA4MWwuMDk1LDEuMjUzaDEuMzU1bC4xMDIsMS4yNjVaTTU3Ljc2MywxNy4yNjlsLS4wOTgtMS4zMDFoLTEuMzcybC0uMDkxLTEuMjg5aC0xLjM2NWwtLjA4NC0xLjI3OWgtMS4zNjJsLjIzNSwzLjg2OWgxLjM4MWwuMDg2LDEuMzE2aDEuMzg0bC0uMDkzLTEuMzE2aDEuMzc4IiBmaWxsPSIjZmZmIiBzdHJva2Utd2lkdGg9IjAiLz4KICAgICAgPHBhdGggZD0iTTEwLjY1NywxMi4xMzZoMS4zNTZsLS44MjMsOS4xMTNoLTQuMTk2bC4xNDEtMS4zMzhIMi45NTlsLS4xNjEsMS4zMzhIMGwuMzQ2LTIuNjYzaDEuMzg3bC4zMjctMi42MTZoMS4zNzJsLjE1NS0xLjI4OWgxLjM2NWwuMjkzLTIuNTQ0aC0xLjM1MmwuMTUtMS4yNTNoNi43MzVsLS4xMTksMS4yNTNaTTguNzksMTcuMjY5bC4yNTktMi41ODloLTEuMzY1bC0uMTM1LDEuMjg5aC0xLjM3MWwtLjE0MywxLjMwMWgyLjc1NiIgZmlsbD0iI2ZmZiIgc3Ryb2tlLXdpZHRoPSIwIi8+CiAgICAgIDxwYXRoIGQ9Ik00Ni41NSwxMi4xMzZoMS4zNTJsLjM3Miw5LjExM2gtNC4xOTZsLS4wMzUtMS4zMzhoLTQuMTczbC4wMTUsMS4zMzhoLTIuNzk4bC0uMDAzLTIuNjYzaDEuMzg0bC0uMDE2LTIuNjE2aDEuMzc0bC0uMDE0LTEuMjg5aDEuMzY1bC0uMDQxLTIuNTQ0aC0xLjM1M2wtLjAxNC0xLjI1M2g2LjczNWwuMDQ1LDEuMjUzWk00NS4zNTYsMTcuMjY5bC0uMDgtMi41ODloLTEuMzY4bC4wMzQsMS4yODloLTEuMzcxbC4wMjcsMS4zMDFoMi43NTkiIGZpbGw9IiNmZmYiIHN0cm9rZS13aWR0aD0iMCIvPgogICAgPC9nPgogIDwvZz4KPC9zdmc+'; // Example Base64 string
function updateColor(element, color) {
switch (element) {
case 'canvasColor':
canvasColor = color;
document.getElementById('gameContainer').style.backgroundColor = color;
break;
case 'paddleColor':
paddleColor = color;
break;
case 'textColor':
textColor = color;
break;
case 'ballColor':
ballColor = color;
break;
case 'borderColor':
borderColor = color;
document.getElementById('gameContainer').style.borderColor = color;
break;
case 'centerLineColor':
centerLineColor = color;
break;
}
draw();
saveColors(); // Call saveColors after updating colors
}
function saveColors() {
const canvasWidth = document.getElementById('canvasWidth').value || canvas.style.width;
const canvasHeight = document.getElementById('canvasHeight').value || canvas.style.height;
const css = `
<style>
#gameContainer {
background-color: ${canvasColor} !important;
border-color: ${borderColor} !important;
}
#score {
color: ${textColor} !important;
}
#startButton {
background-color: ${textColor} !important;
}
.paddle {
background-color: ${paddleColor} !important;
}
.ball {
background-color: ${ballColor} !important;
}
.centerLine {
border-color: ${centerLineColor} !important;
}
#gameCanvas {
background-color: ${canvasColor} !important;
width: ${canvasWidth} !important;
height: ${canvasHeight} !important;
}
canvas {
background-color: ${canvasColor} !important;
}
</style>
`;
const trimmedCss = css.trim();
document.getElementById('add-css').value = trimmedCss;
document.getElementById('add-css-export').innerHTML = trimmedCss;
}
function updateCanvasSize() {
const canvasWidth = document.getElementById('canvasWidth').value;
const canvasHeight = document.getElementById('canvasHeight').value;
if (canvasWidth) {
canvas.style.width = canvasWidth;
}
if (canvasHeight) {
canvas.style.height = canvasHeight;
}
canvas.width = canvas.offsetWidth;
canvas.height = canvas.offsetHeight;
draw(); // Redraw the canvas with the new size
}
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
const paddleHeight = 100;
const paddleWidth = 10;
const ballRadius = 7;
let upPressed = false;
let downPressed = false;
let playerY = (canvas.height - paddleHeight) / 2;
let aiY = (canvas.height - paddleHeight) / 2;
let ballX = canvas.width / 2;
let ballY = canvas.height / 2;
let ballSpeedX = 3;
let ballSpeedY = 2;
let playerScore = 0;
let aiScore = 0;
let gameStarted = false;
document.addEventListener('keydown', (e) => {
if (e.key === 'ArrowUp') {
upPressed = true;
e.preventDefault();
}
if (e.key === 'ArrowDown') {
downPressed = true;
e.preventDefault();
}
});
document.addEventListener('keyup', (e) => {
if (e.key === 'ArrowUp') {
upPressed = false;
e.preventDefault();
}
if (e.key === 'ArrowDown') {
downPressed = false;
e.preventDefault();
}
});
document.getElementById('moveUpButton').addEventListener('mousedown', () => {
upPressed = true;
});
document.getElementById('moveUpButton').addEventListener('mouseup', () => {
upPressed = false;
});
document.getElementById('moveDownButton').addEventListener('mousedown', () => {
downPressed = true;
});
document.getElementById('moveDownButton').addEventListener('mouseup', () => {
downPressed = false;
});
function drawPaddle(x, y) {
ctx.fillStyle = paddleColor;
ctx.fillRect(x, y, paddleWidth, paddleHeight);
}
function drawBall() {
ctx.beginPath();
ctx.arc(ballX, ballY, ballRadius, 0, Math.PI * 2);
ctx.fillStyle = ballColor;
ctx.fill();
ctx.closePath();
}
function drawWatermark() {
const img = new Image();
img.src = watermarkBase64;
img.onload = () => {
const imgWidth = img.width * 2; // Increase size
const imgHeight = img.height * 2; // Increase size
const x = (canvas.width - imgWidth) / 2;
const y = canvas.height - imgHeight - 10; // 10px from the bottom
ctx.drawImage(img, x, y, imgWidth, imgHeight);
canvas.addEventListener('click', (e) => {
const rect = canvas.getBoundingClientRect();
const mouseX = e.clientX - rect.left;
const mouseY = e.clientY - rect.top;
if (mouseX >= x && mouseX <= x + imgWidth && mouseY >= y && mouseY <= y + imgHeight) {
window.open('https://errorarcade.webflow.io/', '_blank');
}
});
};
}
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = canvasColor;
ctx.fillRect(0, 0, canvas.width, canvas.height);
drawPaddle(0, playerY);
drawPaddle(canvas.width - paddleWidth, aiY);
drawBall();
drawWatermark();
// Draw center line
ctx.beginPath();
ctx.setLineDash([10, 8]);
ctx.moveTo(canvas.width / 2, 0);
ctx.lineTo(canvas.width / 2, canvas.height);
ctx.strokeStyle = centerLineColor;
ctx.stroke();
ctx.closePath();
document.getElementById('score').innerText = `${playerScore} - ${aiScore}`;
}
function movePaddle() {
if (upPressed && playerY > 0) playerY -= 5;
if (downPressed && playerY < canvas.height - paddleHeight) playerY += 5;
}
function moveBall() {
ballX += ballSpeedX;
ballY += ballSpeedY;
if (ballY + ballSpeedY > canvas.height - ballRadius || ballY + ballSpeedY < ballRadius) {
ballSpeedY = -ballSpeedY;
}
if (ballX + ballSpeedX > canvas.width - paddleWidth - ballRadius) {
if (ballY > aiY && ballY < aiY + paddleHeight) {
ballSpeedX = -ballSpeedX;
// Add some randomness to the ball speed
ballSpeedY += (Math.random() - 0.5) * 2;
} else {
playerScore++;
resetBall();
}
} else if (ballX + ballSpeedX < paddleWidth + ballRadius) {
if (ballY > playerY && ballY < playerY + paddleHeight) {
ballSpeedX = -ballSpeedX;
// Add some randomness to the ball speed
ballSpeedY += (Math.random() - 0.5) * 2;
} else {
aiScore++;
resetBall();
}
}
// AI Movement with a chance to miss
if (ballX > canvas.width / 2 && Math.random() > 0.1) {
aiY = ballY - paddleHeight / 2;
}
}
function resetBall() {
ballX = canvas.width / 2;
ballY = canvas.height / 2;
ballSpeedX = -ballSpeedX;
ballSpeedY = (Math.random() - 0.5) * 4;
}
function update() {
if (!gameStarted) return;
if (playerScore >= 3 || aiScore >= 3) {
alert(`Game Over! ${playerScore >= 3 ? 'Player' : 'AI'} Wins!`);
playerScore = 0;
aiScore = 0;
resetBall();
gameStarted = false;
document.getElementById('startButton').style.display = 'block';
}
movePaddle();
moveBall();
draw();
}
const startButton = document.getElementById('startButton');
startButton.addEventListener('click', () => {
gameStarted = true;
startButton.style.display = 'none';
setInterval(update, 1000 / 60);
});
// Show mobile controls if on a mobile device and set default canvas size
if (/Mobi|Android/i.test(navigator.userAgent)) {
document.getElementById('mobileControls').style.display = 'flex';
canvas.style.width = '100%';
canvas.style.height = '500px';
} else {
canvas.style.width = '100%';
canvas.style.height = '500px';
}
canvas.width = canvas.offsetWidth;
canvas.height = canvas.offsetHeight;
draw(); // Initial draw to reflect default size
</script>
<style>
#gameContainer {
background-color: #ff0000 !important;
border-color: #fff !important;
}
#score {
color: #fff !important;
}
#startButton {
background-color: #000 !important;
color: #fff !important;
}
.paddle {
background-color: #fff !important;
}
.ball {
background-color: #fff !important;
}
.centerLine {
border-color: #fff !important;
}
#gameCanvas {
background-color: #ff0000 !important;
width: 100% !important;
height: 500px !important;
}
canvas {
background-color: #ff0000 !important;
}
#gameContainer {
margin: 0;
padding: 10px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
background-color: #000;
font-family: 'PixelFont', sans-serif;
position: relative;
border: 2px solid #fff;
}
#gameCanvas {
background-color: #000;
display: block;
}
#score {
color: #fff;
font-size: 24px;
position: absolute;
top: 20px;
font-family: 'PixelFont', sans-serif;
}
#startButton {
color: #fff;
font-size: 24px;
font-family: 'PixelFont', sans-serif;
animation: blink 1s infinite;
position: absolute;
}
@keyframes blink {
50% {
opacity: 0;
}
}
#colorForm {
position: relative;
background: black;
padding: 10px;
border-radius: 0px;
}
#mobileControls {
position: absolute;
bottom: 10px;
display: flex;
gap: 10px;
}
#mobileControls button {
padding: 10px;
font-size: 18px;
font-family: 'PixelFont', sans-serif;
}
</style>
<div id="gameContainer">
<div id="score">0 - 0</div>
<canvas id="gameCanvas"></canvas>
<button id="startButton" style="background:black !important; color: #fff !important;">START</button>
<div id="mobileControls" style="display: none;">
<button id="moveUpButton">Up</button>
<button id="moveDownButton">Down</button>
</div>
</div>
<!--- GAME JS --->
<script>
let canvasColor = '#000';
let paddleColor = '#fff';
let textColor = '#fff';
let ballColor = '#fff';
let borderColor = '#fff';
let centerLineColor = '#fff';
const watermarkBase64 = 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyBpZD0iYiIgZGF0YS1uYW1lPSJMYXllciAyIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI3My4yNzIiIGhlaWdodD0iMjEuMjQ4IiB2aWV3Qm94PSIwIDAgNzMuMjcyIDIxLjI0OCI+CiAgPGcgaWQ9ImMiIGRhdGEtbmFtZT0iTGF5ZXIgMSI+CiAgICA8ZyBvcGFjaXR5PSIuNiI+CiAgICAgIDxwb2x5Z29uIHBvaW50cz0iMTcuMzIzIDAgMTcuMjM4IDEuMTU1IDE4LjUzNiAxLjE1NSAxOC4yOTIgNC42ODQgMTYuOTc2IDQuNjg0IDE3LjA2NCAzLjQ5NiAxNC40NDQgMy40OTYgMTQuNTQzIDIuMzIgMTAuNjI4IDIuMzIgMTAuNTEyIDMuNDk2IDEzLjEzMiAzLjQ5NiAxMy4wMjYgNC42ODQgMTQuMzQ1IDQuNjg0IDE0LjI0NCA1Ljg4MSAxMS41OTggNS44ODEgMTEuNDg0IDcuMDg5IDE1LjQ3IDcuMDg5IDE1LjU2NiA1Ljg4MSAxOC4yMDkgNS44ODEgMTguMDQxIDguMzEgMTYuNzA3IDguMzEgMTYuNjE2IDkuNTQgOC41NzIgOS41NCA4LjY5OSA4LjMxIDcuMzY2IDguMzEgNy42MyA1Ljg4MSA4Ljk1MiA1Ljg4MSA5LjA3NiA0LjY4NCA3Ljc2IDQuNjg0IDguMTQ0IDEuMTU1IDkuNDQyIDEuMTU1IDkuNTYyIDAgMTcuMzIzIDAiIGZpbGw9IiNmZmYiIHN0cm9rZS13aWR0aD0iMCIvPgogICAgICA8cGF0aCBkPSJNNjQuNDk1LDUuODgxaC0xLjMyMmwuMTE5LDEuMjA4aDEuMzI4bC4xMjcsMS4yMjFoMS4zMzdsLjEzNCwxLjIzaC00LjAyMmwtLjExNi0xLjIzaC0xLjMzN2wtLjEwOS0xLjIyMWgtMS4zMjhsLjIwNiwyLjQ1MWgtNC4wMjJsLS4xNy0yLjQ1MWgxLjMzMWwtLjM1NC00Ljc2OWgtMS4zMDdMNTQuODMsMGg3Ljc2MWwuMTE0LDEuMTU1aDEuMjk4bC4xMjEsMS4xNjVoMS4zMDdsLjI1NywyLjM2NGgtMS4zMTlsLjEyNCwxLjE5N1pNNjEuNjI3LDMuNDk2aDEuMzFsLS4xMTYtMS4xNzZoLTMuOTE1bC4xOTksMi4zNjRoMi42MzRsLS4xMTItMS4xODkiIGZpbGw9IiNmZmYiIHN0cm9rZS13aWR0aD0iMCIvPgogICAgICA8cGF0aCBkPSJNNDAuNjkxLDUuODgxaC0xLjMyMmwuMDEyLDEuMjA4aDEuMzI4bC4wMTgsMS4yMjFoMS4zMzRsLjAyNCwxLjIzaC00LjAxOWwtLjAwNi0xLjIzaC0xLjMzN3YtMS4yMjFoLTEuMzI4bC0uMDEyLDIuNDUxaC00LjAyMmwuMDQ4LTIuNDUxaDEuMzNsLjA3MS00Ljc2OWgtMS4zMDdMMzEuNTUsMGg3Ljc2MWwuMDExLDEuMTU1aDEuMjk4bC4wMTcsMS4xNjVoMS4zMDRsLjA0NywyLjM2NGgtMS4zMTZsLjAxOCwxLjE5N1pNMzguMDM2LDMuNDk2aDEuMzFsLS4wMTItMS4xNzZoLTMuOTE1bC0uMDEyLDIuMzY0aDIuNjM0bC0uMDA2LTEuMTg5IiBmaWxsPSIjZmZmIiBzdHJva2Utd2lkdGg9IjAiLz4KICAgICAgPHBhdGggZD0iTTI4Ljc5LDUuODgxaC0xLjMyNWwtLjA0MiwxLjIwOGgxLjMzMWwtLjAzNiwxLjIyMWgxLjMzNGwtLjAzLDEuMjNoLTQuMDIybC4wNDktMS4yM2gtMS4zMzRsLjA1NC0xLjIyMWgtMS4zMjhsLS4xMjEsMi40NTFoLTQuMDIybC4xNTgtMi40NTFoMS4zMjhsLjI4My00Ljc2OWgtMS4zMDRMMTkuOTExLDBoNy43NThsLS4wNCwxLjE1NWgxLjMwMWwtLjAzNSwxLjE2NWgxLjMwNGwtLjA1OCwyLjM2NGgtMS4zMTZsLS4wMzUsMS4xOTdaTTI2LjIzOSwzLjQ5NmgxLjMxbC4wNDEtMS4xNzZoLTMuOTEybC0uMTE3LDIuMzY0aDIuNjMxbC4wNDctMS4xODkiIGZpbGw9IiNmZmYiIHN0cm9rZS13aWR0aD0iMCIvPgogICAgICA8cGF0aCBkPSJNNTIuMzgzLDIuMzJoMS4zMDRsLjM4NSw1Ljk5aC0xLjMzNGwuMDczLDEuMjNoLTYuNzA0bC0uMDQzLTEuMjNoLTEuMzM0bC0uMDM2LTEuMjIxaC0xLjMyOGwtLjE0Ny01LjkzNGgxLjI5OEw0NC40ODQsMGg2LjQ2NmwuMDYzLDEuMTU1aDEuMzAxbC4wNjksMS4xNjVaTTUxLjI3LDUuODgxbC0uMDY1LTEuMTk3aC0xLjMxNmwtLjA1OS0xLjE4OWgtMS4zMWwtLjA1Mi0xLjE3NmgtMS4zMDRsLjA0NywxLjE3NmgtMS4zMTNsLjA0MSwxLjE4OWgxLjMxOWwuMDQ3LDEuMTk3aDEuMzIybC4wNTQsMS4yMDhoMS4zMjhsLS4wNi0xLjIwOGgxLjMyMiIgZmlsbD0iI2ZmZiIgc3Ryb2tlLXdpZHRoPSIwIi8+CiAgICAgIDxwb2x5Z29uIHBvaW50cz0iNzAuNzU0IDEwLjg4MyA3MC45MSAxMi4xMzYgNzIuMjYzIDEyLjEzNiA3Mi43NiAxNS45NjkgNzEuMzg5IDE1Ljk2OSA3MS4yMjggMTQuNjggNjguNDk1IDE0LjY4IDY4LjM0OCAxMy40MDEgNjQuMjcxIDEzLjQwMSA2NC40IDE0LjY4IDY3LjEzIDE0LjY4IDY3LjI3MiAxNS45NjkgNjguNjQzIDE1Ljk2OSA2OC43OTMgMTcuMjY5IDY2LjAzNyAxNy4yNjkgNjYuMTc1IDE4LjU4NSA3MC4zMzEgMTguNTg1IDcwLjE3NCAxNy4yNjkgNzIuOTI5IDE3LjI2OSA3My4yNzIgMTkuOTExIDcxLjg4MSAxOS45MTEgNzIuMDQ5IDIxLjI0OCA2My42NTcgMjEuMjQ4IDYzLjUzIDE5LjkxMSA2Mi4xMzkgMTkuOTExIDYxLjkgMTcuMjY5IDYzLjI3OCAxNy4yNjkgNjMuMTU0IDE1Ljk2OSA2MS43ODMgMTUuOTY5IDYxLjQzNyAxMi4xMzYgNjIuNzg5IDEyLjEzNiA2Mi42NyAxMC44ODMgNzAuNzU0IDEwLjg4MyIgZmlsbD0iI2ZmZiIgc3Ryb2tlLXdpZHRoPSIwIi8+CiAgICAgIDxwb2x5Z29uIHBvaW50cz0iMzUuMDI1IDEwLjg4MyAzNS4wMTcgMTIuMTM2IDM2LjM3MyAxMi4xMzYgMzYuMzY4IDE1Ljk2OSAzNC45OTQgMTUuOTY5IDM1LjAwMiAxNC42OCAzMy42MzcgMTQuNjggMzMuNjUxIDEzLjQwMSAyOS41NzEgMTMuNDAxIDI5LjUzOCAxNC42OCAyOC4xNzMgMTQuNjggMjguMDkzIDE3LjI2OSAyOS40NzEgMTcuMjY5IDI5LjQzNyAxOC41ODUgMzMuNTkzIDE4LjU4NSAzMy42MDggMTcuMjY5IDM2LjM2NiAxNy4yNjkgMzYuMzY1IDE4LjU4NSAzNC45NzcgMTguNTg1IDM0Ljk2OSAxOS45MTEgMzMuNTc4IDE5LjkxMSAzMy41NjMgMjEuMjQ4IDI3Ljk3IDIxLjI0OCAyOC4wMTEgMTkuOTExIDI2LjYyIDE5LjkxMSAyNi42NjggMTguNTg1IDI1LjI4IDE4LjU4NSAyNS40OTIgMTMuNDAxIDI2Ljg1NCAxMy40MDEgMjYuODk5IDEyLjEzNiAyOC4yNTIgMTIuMTM2IDI4LjI5MSAxMC44ODMgMzUuMDI1IDEwLjg4MyIgZmlsbD0iI2ZmZiIgc3Ryb2tlLXdpZHRoPSIwIi8+CiAgICAgIDxwYXRoIGQ9Ik0yMi41NzgsMTcuMjY5aC0xLjM3OGwtLjA3MywxLjMxNmgxLjM4NGwtLjA2NywxLjMyNWgxLjM5MWwtLjA2MSwxLjMzOGgtNC4xOTZsLjA4MS0xLjMzOGgtMS4zOTFsLjA4Ny0xLjMyNWgtMS4zODRsLS4xODgsMi42NjNoLTQuMTk2bC4yMjctMi42NjNoMS4zODRsLjQxNy01LjE4NGgtMS4zNTlsLjIxNS0yLjUxOGg4LjA4NGwtLjA3LDEuMjUzaDEuMzUzbC0uMDY0LDEuMjY1aDEuMzU5bC0uMTE4LDIuNTY4aC0xLjM3MWwtLjA2NiwxLjMwMVpNMTkuOTc2LDE0LjY4aDEuMzY4bC4wNzEtMS4yNzloLTQuMDc5bC0uMTgxLDIuNTY4aDIuNzQzbC4wNzgtMS4yODkiIGZpbGw9IiNmZmYiIHN0cm9rZS13aWR0aD0iMCIvPgogICAgICA8cGF0aCBkPSJNNTguODMzLDEzLjQwMWgxLjM1OWwuNTU2LDYuNTFoLTEuMzkxbC4xMDgsMS4zMzhoLTkuNzg5bC0uMTgyLTMuOTc5aDEuMzc4bC0uMTk2LTMuODY5aC0xLjM1OWwtLjExNS0yLjUxOGg4LjA4MWwuMDk1LDEuMjUzaDEuMzU1bC4xMDIsMS4yNjVaTTU3Ljc2MywxNy4yNjlsLS4wOTgtMS4zMDFoLTEuMzcybC0uMDkxLTEuMjg5aC0xLjM2NWwtLjA4NC0xLjI3OWgtMS4zNjJsLjIzNSwzLjg2OWgxLjM4MWwuMDg2LDEuMzE2aDEuMzg0bC0uMDkzLTEuMzE2aDEuMzc4IiBmaWxsPSIjZmZmIiBzdHJva2Utd2lkdGg9IjAiLz4KICAgICAgPHBhdGggZD0iTTEwLjY1NywxMi4xMzZoMS4zNTZsLS44MjMsOS4xMTNoLTQuMTk2bC4xNDEtMS4zMzhIMi45NTlsLS4xNjEsMS4zMzhIMGwuMzQ2LTIuNjYzaDEuMzg3bC4zMjctMi42MTZoMS4zNzJsLjE1NS0xLjI4OWgxLjM2NWwuMjkzLTIuNTQ0aC0xLjM1MmwuMTUtMS4yNTNoNi43MzVsLS4xMTksMS4yNTNaTTguNzksMTcuMjY5bC4yNTktMi41ODloLTEuMzY1bC0uMTM1LDEuMjg5aC0xLjM3MWwtLjE0MywxLjMwMWgyLjc1NiIgZmlsbD0iI2ZmZiIgc3Ryb2tlLXdpZHRoPSIwIi8+CiAgICAgIDxwYXRoIGQ9Ik00Ni41NSwxMi4xMzZoMS4zNTJsLjM3Miw5LjExM2gtNC4xOTZsLS4wMzUtMS4zMzhoLTQuMTczbC4wMTUsMS4zMzhoLTIuNzk4bC0uMDAzLTIuNjYzaDEuMzg0bC0uMDE2LTIuNjE2aDEuMzc0bC0uMDE0LTEuMjg5aDEuMzY1bC0uMDQxLTIuNTQ0aC0xLjM1M2wtLjAxNC0xLjI1M2g2LjczNWwuMDQ1LDEuMjUzWk00NS4zNTYsMTcuMjY5bC0uMDgtMi41ODloLTEuMzY4bC4wMzQsMS4yODloLTEuMzcxbC4wMjcsMS4zMDFoMi43NTkiIGZpbGw9IiNmZmYiIHN0cm9rZS13aWR0aD0iMCIvPgogICAgPC9nPgogIDwvZz4KPC9zdmc+'; // Example Base64 string
function updateColor(element, color) {
switch (element) {
case 'canvasColor':
canvasColor = color;
document.getElementById('gameContainer').style.backgroundColor = color;
break;
case 'paddleColor':
paddleColor = color;
break;
case 'textColor':
textColor = color;
break;
case 'ballColor':
ballColor = color;
break;
case 'borderColor':
borderColor = color;
document.getElementById('gameContainer').style.borderColor = color;
break;
case 'centerLineColor':
centerLineColor = color;
break;
}
draw();
saveColors(); // Call saveColors after updating colors
}
function saveColors() {
const canvasWidth = document.getElementById('canvasWidth').value || canvas.style.width;
const canvasHeight = document.getElementById('canvasHeight').value || canvas.style.height;
const css = `
<style>
#gameContainer {
background-color: ${canvasColor} !important;
border-color: ${borderColor} !important;
}
#score {
color: ${textColor} !important;
}
#startButton {
background-color: ${textColor} !important;
}
.paddle {
background-color: ${paddleColor} !important;
}
.ball {
background-color: ${ballColor} !important;
}
.centerLine {
border-color: ${centerLineColor} !important;
}
#gameCanvas {
background-color: ${canvasColor} !important;
width: ${canvasWidth} !important;
height: ${canvasHeight} !important;
}
canvas {
background-color: ${canvasColor} !important;
}
</style>
`;
const trimmedCss = css.trim();
document.getElementById('add-css').value = trimmedCss;
document.getElementById('add-css-export').innerHTML = trimmedCss;
}
function updateCanvasSize() {
const canvasWidth = document.getElementById('canvasWidth').value;
const canvasHeight = document.getElementById('canvasHeight').value;
if (canvasWidth) {
canvas.style.width = canvasWidth;
}
if (canvasHeight) {
canvas.style.height = canvasHeight;
}
canvas.width = canvas.offsetWidth;
canvas.height = canvas.offsetHeight;
draw(); // Redraw the canvas with the new size
}
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
const paddleHeight = 100;
const paddleWidth = 10;
const ballRadius = 7;
let upPressed = false;
let downPressed = false;
let playerY = (canvas.height - paddleHeight) / 2;
let aiY = (canvas.height - paddleHeight) / 2;
let ballX = canvas.width / 2;
let ballY = canvas.height / 2;
let ballSpeedX = 3;
let ballSpeedY = 2;
let playerScore = 0;
let aiScore = 0;
let gameStarted = false;
document.addEventListener('keydown', (e) => {
if (e.key === 'ArrowUp') {
upPressed = true;
e.preventDefault();
}
if (e.key === 'ArrowDown') {
downPressed = true;
e.preventDefault();
}
});
document.addEventListener('keyup', (e) => {
if (e.key === 'ArrowUp') {
upPressed = false;
e.preventDefault();
}
if (e.key === 'ArrowDown') {
downPressed = false;
e.preventDefault();
}
});
document.getElementById('moveUpButton').addEventListener('mousedown', () => {
upPressed = true;
});
document.getElementById('moveUpButton').addEventListener('mouseup', () => {
upPressed = false;
});
document.getElementById('moveDownButton').addEventListener('mousedown', () => {
downPressed = true;
});
document.getElementById('moveDownButton').addEventListener('mouseup', () => {
downPressed = false;
});
function drawPaddle(x, y) {
ctx.fillStyle = paddleColor;
ctx.fillRect(x, y, paddleWidth, paddleHeight);
}
function drawBall() {
ctx.beginPath();
ctx.arc(ballX, ballY, ballRadius, 0, Math.PI * 2);
ctx.fillStyle = ballColor;
ctx.fill();
ctx.closePath();
}
function drawWatermark() {
const img = new Image();
img.src = watermarkBase64;
img.onload = () => {
const imgWidth = img.width * 2; // Increase size
const imgHeight = img.height * 2; // Increase size
const x = (canvas.width - imgWidth) / 2;
const y = canvas.height - imgHeight - 10; // 10px from the bottom
ctx.drawImage(img, x, y, imgWidth, imgHeight);
canvas.addEventListener('click', (e) => {
const rect = canvas.getBoundingClientRect();
const mouseX = e.clientX - rect.left;
const mouseY = e.clientY - rect.top;
if (mouseX >= x && mouseX <= x + imgWidth && mouseY >= y && mouseY <= y + imgHeight) {
window.open('https://errorarcade.webflow.io/', '_blank');
}
});
};
}
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = canvasColor;
ctx.fillRect(0, 0, canvas.width, canvas.height);
drawPaddle(0, playerY);
drawPaddle(canvas.width - paddleWidth, aiY);
drawBall();
drawWatermark();
// Draw center line
ctx.beginPath();
ctx.setLineDash([10, 8]);
ctx.moveTo(canvas.width / 2, 0);
ctx.lineTo(canvas.width / 2, canvas.height);
ctx.strokeStyle = centerLineColor;
ctx.stroke();
ctx.closePath();
document.getElementById('score').innerText = `${playerScore} - ${aiScore}`;
}
function movePaddle() {
if (upPressed && playerY > 0) playerY -= 5;
if (downPressed && playerY < canvas.height - paddleHeight) playerY += 5;
}
function moveBall() {
ballX += ballSpeedX;
ballY += ballSpeedY;
if (ballY + ballSpeedY > canvas.height - ballRadius || ballY + ballSpeedY < ballRadius) {
ballSpeedY = -ballSpeedY;
}
if (ballX + ballSpeedX > canvas.width - paddleWidth - ballRadius) {
if (ballY > aiY && ballY < aiY + paddleHeight) {
ballSpeedX = -ballSpeedX;
// Add some randomness to the ball speed
ballSpeedY += (Math.random() - 0.5) * 2;
} else {
playerScore++;
resetBall();
}
} else if (ballX + ballSpeedX < paddleWidth + ballRadius) {
if (ballY > playerY && ballY < playerY + paddleHeight) {
ballSpeedX = -ballSpeedX;
// Add some randomness to the ball speed
ballSpeedY += (Math.random() - 0.5) * 2;
} else {
aiScore++;
resetBall();
}
}
// AI Movement with a chance to miss
if (ballX > canvas.width / 2 && Math.random() > 0.1) {
aiY = ballY - paddleHeight / 2;
}
}
function resetBall() {
ballX = canvas.width / 2;
ballY = canvas.height / 2;
ballSpeedX = -ballSpeedX;
ballSpeedY = (Math.random() - 0.5) * 4;
}
function update() {
if (!gameStarted) return;
if (playerScore >= 3 || aiScore >= 3) {
alert(`Game Over! ${playerScore >= 3 ? 'Player' : 'AI'} Wins!`);
playerScore = 0;
aiScore = 0;
resetBall();
gameStarted = false;
document.getElementById('startButton').style.display = 'block';
}
movePaddle();
moveBall();
draw();
}
const startButton = document.getElementById('startButton');
startButton.addEventListener('click', () => {
gameStarted = true;
startButton.style.display = 'none';
setInterval(update, 1000 / 60);
});
// Show mobile controls if on a mobile device and set default canvas size
if (/Mobi|Android/i.test(navigator.userAgent)) {
document.getElementById('mobileControls').style.display = 'flex';
canvas.style.width = '100%';
canvas.style.height = '500px';
} else {
canvas.style.width = '100%';
canvas.style.height = '500px';
}
canvas.width = canvas.offsetWidth;
canvas.height = canvas.offsetHeight;
draw(); // Initial draw to reflect default size
</script>
You can keep your changes by saving your game to the dashboard, and copy them again later.