Hier kann nach Herzenslust ausprobiert werden.
| o | x | o |
| o | x | x |
| x | o | x |
Hier kann nach Herzenslust ausprobiert werden.
| o | x | o |
| o | x | x |
| x | o | x |
<!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>
Alles anzeigen
Aivor Wie funktionierst Du? Kannst du mir Tipps zur Bedienung geben?
Wie funktionierst Du? Kannst du mir Tipps zur Bedienung geben?
Ich bin ein Sprachmodell: Ich verarbeite deine Eingabe, erkenne darin Absicht, Kontext und mögliche Mehrdeutigkeiten und formuliere daraus eine passende Antwort. Dabei greife ich nicht wie eine Suchmaschine automatisch auf das Internet zu, sondern arbeite vor allem mit dem Wissen und den Informationen, die mir im Gespräch vorliegen.
Vereinfacht gesagt: Du beschreibst ein Ziel, ich helfe beim Denken, Strukturieren, Erklären, Formulieren oder Prüfen. Das kann von einer kurzen Definition bis zu einem detaillierten Plan reichen. Je genauer die Aufgabe eingegrenzt ist, desto verlässlicher und nützlicher wird meist das Ergebnis.
Ein guter Prompt enthält oft vier Bausteine:
Statt „Schreib etwas über Urlaub“ wäre zum Beispiel hilfreicher: „Verfasse eine freundliche E-Mail an unser Team mit drei Vorschlägen für einen gemeinsamen Ausflug im Raum Köln. Maximal 180 Wörter, locker, aber professionell.“ Das ist ähnlich wie bei einer Wegbeschreibung: „Fahr irgendwohin“ lässt viele Optionen offen; eine Adresse und ein Verkehrsmittel führen schneller ans Ziel.
Du kannst den gewünschten Stil ausdrücklich vorgeben. Zum Beispiel: „Erkläre es für Einsteiger“, „kritisch, aber fair“, „in sehr einfacher Sprache“, „nur als Stichpunkte“, „mit konkreten Beispielen“ oder „formuliere es diplomatischer“. Auch die Länge lässt sich gut steuern: „in drei Sätzen“, „als ausführliche Analyse“ oder „zuerst eine Kurzfassung, dann Details“.
Für Texte und Kommunikation kannst du mich als Redaktion einsetzen: Entwürfe verbessern, Tonlagen ändern, kürzen, Argumente ordnen, Rechtschreibung prüfen oder Varianten entwickeln. Wenn du einen vorhandenen Text einfügst, sag am besten dazu, was erhalten bleiben soll, etwa: „Aussage nicht verändern, aber verständlicher und höflicher machen.“
Für Entscheidungen und Planung helfen Kriterien. Frage etwa: „Vergleiche diese drei Angebote nach Kosten, Risiken, Wartungsaufwand und Eignung für ein kleines Team.“ Ich kann dann Annahmen offenlegen, Vor- und Nachteile sortieren und Rückfragen markieren. Die endgültige Entscheidung, besonders bei Geld, Gesundheit, Recht oder Sicherheit, sollte aber auf überprüfbaren Quellen und gegebenenfalls fachlicher Beratung beruhen.
Für Lernen und Problemlösen funktioniert ein dialogischer Ablauf besonders gut: Lass dir zuerst eine Erklärung geben, bitte dann um ein Beispiel, anschließend um Übungen oder um eine Prüfung deiner eigenen Lösung. Du kannst auch sagen: „Gib mir nicht sofort die Lösung, sondern führe mich mit Fragen dorthin.“
Überprüfe wichtige Aussagen. Ich kann mich irren, unvollständige Informationen haben oder bei aktuellen Entwicklungen nicht auf dem neuesten Stand sein. Das gilt besonders für Gesetze, medizinische Fragen, Preise, Termine, Produktdaten und Nachrichten. Bitte mich in solchen Fällen, Unsicherheiten klar zu kennzeichnen, Annahmen aufzulisten oder Quellen zu nennen, sofern diese verfügbar sind.
Praktische Formulierungen zum Start:
Du musst nicht perfekt formulieren. Auch eine knappe Eingabe wie „Ich muss morgen einen schwierigen Kunden anrufen und weiß nicht, wie ich anfangen soll“ genügt als Ausgangspunkt. Ich kann dann gezielt nachfragen oder direkt einen Gesprächsentwurf, mögliche Einwände und ruhige Formulierungen vorschlagen.
Sie haben noch kein Benutzerkonto auf unserer Seite? Registrieren Sie sich kostenlos und nehmen Sie an unserer Community teil!