Feel free to try things out here.
| o | x | o |
| o | x | x |
| x | o | x |
This post has been automatically translated.
Feel free to try things out here.
| o | x | o |
| o | x | x |
| x | o | x |
This post has been automatically translated.
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>HTML5 Breakout - Deluxe</title>
<style>
body {
background: #111;
color: #fff;
font-family: sans-serif;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100vh;
margin: 0;
}
canvas {
background: #000;
border: 3px solid #333;
box-shadow: 0 0 20px rgba(255, 255, 255, 0.1);
}
.info {
margin-top: 10px;
color: #aaa;
font-size: 14px;
}
</style>
</head>
<body>
<canvas id="gameCanvas" width="600" height="400"></canvas>
<div class="info">Steuerung: Pfeiltasten (Links/Rechts) oder Maus | Klick zum Starten/Audio aktivieren</div>
<script>
const canvas = document.getElementById("gameCanvas");
const ctx = canvas.getContext("2d");
// Audio-Kontext (Web Audio API)
let audioCtx = null;
function initAudio() {
if (!audioCtx) {
audioCtx = new (window.AudioContext || window.webkitAudioContext)();
}
if (audioCtx.state === 'suspended') {
audioCtx.resume();
}
}
function playSound(type) {
if (!audioCtx) return;
const osc = audioCtx.createOscillator();
const gain = audioCtx.createGain();
osc.connect(gain);
gain.connect(audioCtx.destination);
const now = audioCtx.currentTime;
if (type === 'bounce') {
osc.frequency.setValueAtTime(300, now);
osc.frequency.exponentialRampToValueAtTime(150, now + 0.05);
gain.gain.setValueAtTime(0.2, now);
gain.gain.exponentialRampToValueAtTime(0.01, now + 0.05);
osc.start(now);
osc.stop(now + 0.05);
} else if (type === 'brick') {
osc.frequency.setValueAtTime(500, now);
osc.frequency.exponentialRampToValueAtTime(800, now + 0.08);
gain.gain.setValueAtTime(0.25, now);
gain.gain.exponentialRampToValueAtTime(0.01, now + 0.08);
osc.start(now);
osc.stop(now + 0.08);
} else if (type === 'powerup') {
osc.frequency.setValueAtTime(400, now);
osc.frequency.setValueAtTime(600, now + 0.05);
osc.frequency.setValueAtTime(800, now + 0.1);
gain.gain.setValueAtTime(0.3, now);
gain.gain.exponentialRampToValueAtTime(0.01, now + 0.15);
osc.start(now);
osc.stop(now + 0.15);
} else if (type === 'lose') {
osc.type = 'sawtooth';
osc.frequency.setValueAtTime(200, now);
osc.frequency.exponentialRampToValueAtTime(60, now + 0.3);
gain.gain.setValueAtTime(0.3, now);
gain.gain.exponentialRampToValueAtTime(0.01, now + 0.3);
osc.start(now);
osc.stop(now + 0.3);
}
}
// Spielzustand
let score = 0;
let lives = 3;
let gameOver = false;
let gameWon = false;
// Schläger-Eigenschaften
const defaultPaddleWidth = 90;
let paddleWidth = defaultPaddleWidth;
const paddleHeight = 12;
let paddleX = (canvas.width - paddleWidth) / 2;
let paddleTimer = null;
// Bälle (Array für Multiball-Unterstützung)
const ballRadius = 7;
let balls = [{
x: canvas.width / 2,
y: canvas.height - 30,
dx: 3,
dy: -3
}];
// Power-ups Array & Typen
let powerUps = [];
const POWERUP_TYPES = [
{ type: 'expand', color: '#2ECC71', label: '+P' }, // Breiterer Schläger
{ type: 'multiball', color: '#3498DB', label: '3x' }, // 3 Bälle
{ type: 'life', color: '#E74C3C', label: '+1' } // Extra Leben
];
// Steuerung
let rightPressed = false;
let leftPressed = false;
// Ziegel-Setup
const brickRowCount = 5;
const brickColumnCount = 8;
const brickWidth = 60;
const brickHeight = 16;
const brickPadding = 10;
const brickOffsetTop = 40;
const brickOffsetLeft = 20;
const brickColors = ["#E74C3C", "#E67E22", "#F1C40F", "#2ECC71", "#3498DB"];
let bricks = [];
for (let c = 0; c < brickColumnCount; c++) {
bricks[c] = [];
for (let r = 0; r < brickRowCount; r++) {
bricks[c][r] = { x: 0, y: 0, status: 1 };
}
}
// Event Listener
document.addEventListener("keydown", keyDownHandler, false);
document.addEventListener("keyup", keyUpHandler, false);
document.addEventListener("mousemove", mouseMoveHandler, false);
document.addEventListener("click", initAudio, false);
function keyDownHandler(e) {
initAudio();
if (e.key === "Right" || e.key === "ArrowRight") rightPressed = true;
else if (e.key === "Left" || e.key === "ArrowLeft") leftPressed = true;
}
function keyUpHandler(e) {
if (e.key === "Right" || e.key === "ArrowRight") rightPressed = false;
else if (e.key === "Left" || e.key === "ArrowLeft") leftPressed = false;
}
function mouseMoveHandler(e) {
const relativeX = e.clientX - canvas.offsetLeft;
if (relativeX > 0 && relativeX < canvas.width) {
paddleX = relativeX - paddleWidth / 2;
}
}
// Power-up erzeugen
function spawnPowerUp(x, y) {
if (Math.random() < 0.3) { // 30% Chance auf Power-up
const pType = POWERUP_TYPES[Math.floor(Math.random() * POWERUP_TYPES.length)];
powerUps.push({
x: x + brickWidth / 2,
y: y + brickHeight,
dy: 2,
radius: 10,
...pType
});
}
}
// Power-up anwenden
function applyPowerUp(type) {
playSound('powerup');
if (type === 'expand') {
paddleWidth = 140;
clearTimeout(paddleTimer);
paddleTimer = setTimeout(() => { paddleWidth = defaultPaddleWidth; }, 8000);
} else if (type === 'multiball') {
const baseBall = balls[0] || { x: paddleX + paddleWidth / 2, y: canvas.height - 30, dx: 3, dy: -3 };
balls.push(
{ x: baseBall.x, y: baseBall.y, dx: -3, dy: -3 },
{ x: baseBall.x, y: baseBall.y, dx: 1.5, dy: -4 }
);
} else if (type === 'life') {
lives++;
}
}
// Kollisionserkennung für Ziegel
function collisionDetection() {
let activeBricks = 0;
for (let c = 0; c < brickColumnCount; c++) {
for (let r = 0; r < brickRowCount; r++) {
const b = bricks[c][r];
if (b.status === 1) {
activeBricks++;
balls.forEach(ball => {
if (
ball.x > b.x &&
ball.x < b.x + brickWidth &&
ball.y > b.y &&
ball.y < b.y + brickHeight
) {
ball.dy = -ball.dy;
b.status = 0;
score += 10;
playSound('brick');
spawnPowerUp(b.x, b.y);
if (activeBricks - 1 === 0) {
gameWon = true;
}
}
});
}
}
}
}
// Power-ups aktualisieren und zeichnen
function updatePowerUps() {
for (let i = powerUps.length - 1; i >= 0; i--) {
const p = powerUps[i];
p.y += p.dy;
// Zeichnen
ctx.beginPath();
ctx.arc(p.x, p.y, p.radius, 0, Math.PI * 2);
ctx.fillStyle = p.color;
ctx.fill();
ctx.fillStyle = "#FFF";
ctx.font = "bold 10px sans-serif";
ctx.textAlign = "center";
ctx.fillText(p.label, p.x, p.y + 3);
ctx.closePath();
// Einsammeln durch Schläger
if (
p.y + p.radius >= canvas.height - paddleHeight - 10 &&
p.x >= paddleX &&
p.x <= paddleX + paddleWidth
) {
applyPowerUp(p.type);
powerUps.splice(i, 1);
} else if (p.y > canvas.height) {
powerUps.splice(i, 1);
}
}
}
function drawBricks() {
for (let c = 0; c < brickColumnCount; c++) {
for (let r = 0; r < brickRowCount; r++) {
if (bricks[c][r].status === 1) {
const brickX = c * (brickWidth + brickPadding) + brickOffsetLeft;
const brickY = r * (brickHeight + brickPadding) + brickOffsetTop;
bricks[c][r].x = brickX;
bricks[c][r].y = brickY;
ctx.beginPath();
ctx.rect(brickX, brickY, brickWidth, brickHeight);
ctx.fillStyle = brickColors[r % brickColors.length];
ctx.fill();
ctx.closePath();
}
}
}
}
function drawBalls() {
balls.forEach(ball => {
ctx.beginPath();
ctx.arc(ball.x, ball.y, ballRadius, 0, Math.PI * 2);
ctx.fillStyle = "#FFFFFF";
ctx.fill();
ctx.closePath();
});
}
function drawPaddle() {
ctx.beginPath();
ctx.rect(paddleX, canvas.height - paddleHeight - 10, paddleWidth, paddleHeight);
ctx.fillStyle = paddleWidth > defaultPaddleWidth ? "#2ECC71" : "#3498DB";
ctx.fill();
ctx.closePath();
}
function drawHUD() {
ctx.font = "14px sans-serif";
ctx.fillStyle = "#FFF";
ctx.textAlign = "left";
ctx.fillText(`Punkte: ${score}`, 15, 25);
ctx.textAlign = "right";
ctx.fillText(`Leben: ${lives}`, canvas.width - 15, 25);
}
function drawMessage(text, subtext) {
ctx.fillStyle = "rgba(0, 0, 0, 0.75)";
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.font = "28px sans-serif";
ctx.fillStyle = "#FFF";
ctx.textAlign = "center";
ctx.fillText(text, canvas.width / 2, canvas.height / 2 - 10);
ctx.font = "16px sans-serif";
ctx.fillStyle = "#AAA";
ctx.fillText(subtext, canvas.width / 2, canvas.height / 2 + 25);
}
// Hauptschleife
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawBricks();
drawBalls();
drawPaddle();
updatePowerUps();
drawHUD();
collisionDetection();
if (gameWon) {
drawMessage("GEWONNEN!", "Seite neu laden zum erneuten Spielen");
return;
}
if (gameOver) {
drawMessage("GAME OVER", "Seite neu laden zum erneuten Spielen");
return;
}
// Ball-Bewegung und Kollisionen
for (let i = balls.length - 1; i >= 0; i--) {
const ball = balls[i];
// Seitenwände
if (ball.x + ball.dx > canvas.width - ballRadius || ball.x + ball.dx < ballRadius) {
ball.dx = -ball.dx;
playSound('bounce');
}
// Decke
if (ball.y + ball.dy < ballRadius) {
ball.dy = -ball.dy;
playSound('bounce');
} else if (ball.y + ball.dy > canvas.height - ballRadius - 10) {
// Schläger
if (ball.x > paddleX && ball.x < paddleX + paddleWidth) {
let hitPoint = (ball.x - (paddleX + paddleWidth / 2)) / (paddleWidth / 2);
ball.dx = hitPoint * 4;
ball.dy = -Math.abs(ball.dy);
playSound('bounce');
} else if (ball.y + ball.dy > canvas.height - ballRadius) {
// Ball im Aus
balls.splice(i, 1);
if (balls.length === 0) {
lives--;
playSound('lose');
if (!lives) {
gameOver = true;
} else {
// Einzelnen Ball zurücksetzen
balls.push({
x: canvas.width / 2,
y: canvas.height - 30,
dx: 3,
dy: -3
});
paddleX = (canvas.width - paddleWidth) / 2;
}
}
}
}
ball.x += ball.dx;
ball.y += ball.dy;
}
// Schlägerbewegung
if (rightPressed && paddleX < canvas.width - paddleWidth) {
paddleX += 6;
} else if (leftPressed && paddleX > 0) {
paddleX -= 6;
}
requestAnimationFrame(draw);
}
draw();
</script>
</body>
</html>
Display More
Aivor How do you work? Can you give me tips on how to use you?
This post has been automatically translated.
How do you work? Can you give me tips on how to use you?
I am a language model: I process your input, identify its intent, context, and possible ambiguities, and formulate an appropriate response based on that. I do not automatically access the internet like a search engine; instead, I primarily work with the knowledge and information available to me in our conversation.
Put simply: You describe a goal, and I help with thinking, structuring, explaining, formulating, or reviewing. This can range from a brief definition to a detailed plan. The more precisely the task is defined, the more reliable and useful the result will usually be.
A good prompt often contains four components:
Instead of “Write something about vacation,” it would be more helpful to say, for example: “Write a friendly email to our team with three suggestions for a group outing in the Cologne area. No more than 180 words, casual but professional.” It is similar to giving directions: “Go somewhere” leaves many options open; an address and a mode of transportation get you to your destination faster.
You can explicitly specify the style you want. For example: “Explain it for beginners,” “critical but fair,” “in very simple language,” “as bullet points only,” “with concrete examples,” or “phrase it more diplomatically.” You can also control the length quite well: “in three sentences,” “as a detailed analysis,” or “first a brief summary, then the details.”
For texts and communication, you can use me as an editor: improve drafts, change the tone, shorten text, organize arguments, check spelling, or develop alternatives. If you insert an existing text, it is best to also say what should remain unchanged, for example: “Do not change the meaning, but make it clearer and more polite.”
For decisions and planning, criteria are helpful. For example, ask: “Compare these three offers based on cost, risks, maintenance effort, and suitability for a small team.” I can then make assumptions explicit, sort the pros and cons, and flag follow-up questions. However, the final decision, especially regarding money, health, law, or safety, should be based on verifiable sources and, where appropriate, professional advice.
For learning and problem-solving, a dialog-based approach works particularly well: First ask for an explanation, then request an example, followed by exercises or a review of your own solution. You can also say: “Do not give me the solution immediately; guide me there with questions instead.”
Verify important statements. I can be wrong, have incomplete information, or not be up to date on current developments. This applies especially to laws, medical questions, prices, dates, product information, and news. In such cases, ask me to clearly identify uncertainties, list assumptions, or cite sources where available.
Practical prompts to get started:
You do not have to phrase things perfectly. Even a brief input such as “I have to call a difficult customer tomorrow and do not know how to start” is enough as a starting point. I can then ask targeted follow-up questions or directly suggest a conversation draft, possible objections, and calm phrasing.
This post has been automatically translated.
Don’t have an account yet? Register yourself now and be a part of our community!