Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <title>Reaction Rumble: Red vs Blue</title>
- <style>
- body {
- margin: 0;
- display: flex;
- flex-direction: column;
- align-items: center;
- justify-content: center;
- height: 100vh;
- background-color: #e0e0e0;
- font-family: 'Segoe UI', Arial, sans-serif;
- overflow: hidden;
- }
- #gameContainer {
- text-align: center;
- background: #fff;
- padding: 20px;
- border-radius: 10px;
- box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
- }
- #gameCanvas {
- border: 2px solid #333;
- border-radius: 5px;
- }
- #title {
- font-size: 2em;
- margin-bottom: 10px;
- color: #333;
- }
- #status, #reactionTime {
- margin: 10px 0;
- font-size: 1.2em;
- color: #444;
- }
- #status { font-weight: bold; }
- .highlight-red { box-shadow: 0 0 20px 5px rgba(255, 0, 0, 0.7); }
- .highlight-blue { box-shadow: 0 0 20px 5px rgba(0, 0, 255, 0.7); }
- #startScreen {
- position: absolute;
- top: 50%;
- left: 50%;
- transform: translate(-50%, -50%);
- background: rgba(255, 255, 255, 0.9);
- padding: 20px;
- border-radius: 10px;
- box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
- text-align: center;
- }
- #startScreen button {
- padding: 10px 20px;
- font-size: 1.2em;
- background-color: #4CAF50;
- color: white;
- border: none;
- border-radius: 5px;
- cursor: pointer;
- }
- #startScreen button:hover { background-color: #45a049; }
- </style>
- </head>
- <body>
- <div id="gameContainer">
- <div id="title">Reaction Rumble</div>
- <canvas id="gameCanvas" width="600" height="400" aria-label="Game canvas showing red and blue camps"></canvas>
- <div id="status" aria-live="polite">Press 'A' (Red) or 'L' (Blue) to push back! 'Space' to restart.</div>
- <div id="reactionTime" aria-live="polite">Reaction Time: -- ms</div>
- </div>
- <div id="startScreen">
- <h2>Welcome to Reaction Rumble</h2>
- <p>Red ('A') defends left, Blue ('L') defends right.<br>Push back the line when it moves toward you!<br>Press 'Space' to restart anytime.</p>
- <button id="startButton">Start Game</button>
- </div>
- <script>
- // Configuration
- const CONFIG = {
- WIDTH: 600,
- HEIGHT: 400,
- MAX_WAIT_TIME: 1500, // Changed from 3000ms to 1500ms (< 1.5s)
- KEY_COOLDOWN: 200,
- LINE_SPEED: 200, // Pixels per second
- HIGHLIGHT_DURATION: 500,
- };
- // DOM elements
- const canvas = document.getElementById('gameCanvas');
- const ctx = canvas.getContext('2d');
- const status = document.getElementById('status');
- const reactionTimeDisplay = document.getElementById('reactionTime');
- const startScreen = document.getElementById('startScreen');
- const startButton = document.getElementById('startButton');
- // Game state
- class Game {
- constructor() {
- this.reset();
- this.lastTime = performance.now();
- this.animationFrameId = null;
- }
- reset() {
- this.linePosition = CONFIG.WIDTH / 2;
- this.lineSpeed = CONFIG.LINE_SPEED;
- this.direction = 0;
- this.waiting = true;
- this.redPressCount = 0;
- this.bluePressCount = 0;
- this.gameOver = false;
- this.moveStartTime = 0;
- this.lastKeyPressTime = 0;
- canvas.classList.remove('highlight-red', 'highlight-blue');
- status.textContent = "Press 'A' (Red) or 'L' (Blue) to push back! 'Space' to restart.";
- reactionTimeDisplay.textContent = 'Reaction Time: -- ms';
- if (this.animationFrameId) cancelAnimationFrame(this.animationFrameId);
- }
- startWait() {
- this.waiting = true;
- this.direction = 0;
- const waitTime = Math.random() * CONFIG.MAX_WAIT_TIME;
- setTimeout(() => {
- if (!this.gameOver) {
- this.waiting = false;
- this.direction = Math.random() < 0.5 ? -1 : 1;
- this.moveStartTime = performance.now();
- this.highlightActiveSide();
- }
- }, waitTime);
- }
- highlightActiveSide() {
- canvas.classList.remove('highlight-red', 'highlight-blue');
- if (this.direction === -1) {
- canvas.classList.add('highlight-red');
- setTimeout(() => canvas.classList.remove('highlight-red'), CONFIG.HIGHLIGHT_DURATION);
- } else if (this.direction === 1) {
- canvas.classList.add('highlight-blue');
- setTimeout(() => canvas.classList.remove('highlight-blue'), CONFIG.HIGHLIGHT_DURATION);
- }
- }
- handlePress(player, intendedDirection) {
- const halfCamp = CONFIG.WIDTH / 2;
- if (this.waiting) {
- if (this.linePosition > halfCamp && player === 'red') {
- this.linePosition = CONFIG.WIDTH - this.linePosition;
- } else if (this.linePosition < halfCamp && player === 'blue') {
- this.linePosition = CONFIG.WIDTH - this.linePosition;
- }
- return;
- }
- const pressCount = player === 'red' ? this.redPressCount : this.bluePressCount;
- if (this.direction === intendedDirection) {
- const reactionTime = Math.round(performance.now() - this.moveStartTime);
- reactionTimeDisplay.textContent = `Reaction Time: ${reactionTime} ms`;
- this.direction = 0;
- this.waiting = true;
- this.startWait();
- if (pressCount === 3) this.lineSpeed = CONFIG.LINE_SPEED;
- } else {
- if (this.linePosition > halfCamp && player === 'red') {
- this.linePosition = CONFIG.WIDTH - this.linePosition;
- } else if (this.linePosition < halfCamp && player === 'blue') {
- this.linePosition = CONFIG.WIDTH - this.linePosition;
- }
- }
- if (pressCount === 2) this.lineSpeed = CONFIG.LINE_SPEED * 2;
- else if (pressCount > 3) {
- if (player === 'red') this.redPressCount = 0;
- else this.bluePressCount = 0;
- }
- }
- update(timestamp) {
- const deltaTime = (timestamp - this.lastTime) / 1000; // Seconds
- this.lastTime = timestamp;
- if (!this.waiting && !this.gameOver) {
- this.linePosition += this.direction * this.lineSpeed * deltaTime;
- if (this.linePosition <= 0) {
- this.gameOver = true;
- status.textContent = 'Blue Wins! Red camp overtaken. Press Space to restart.';
- reactionTimeDisplay.textContent = 'Reaction Time: Game Over';
- } else if (this.linePosition >= CONFIG.WIDTH) {
- this.gameOver = true;
- status.textContent = 'Red Wins! Blue camp overtaken. Press Space to restart.';
- reactionTimeDisplay.textContent = 'Reaction Time: Game Over';
- }
- }
- this.draw();
- this.animationFrameId = requestAnimationFrame(this.update.bind(this));
- }
- draw() {
- ctx.clearRect(0, 0, CONFIG.WIDTH, CONFIG.HEIGHT);
- // Draw red camp from left (0) to linePosition
- ctx.fillStyle = '#ff5555';
- ctx.fillRect(0, 0, this.linePosition, CONFIG.HEIGHT);
- // Draw blue camp from linePosition to right (CONFIG.WIDTH)
- ctx.fillStyle = '#5555ff';
- ctx.fillRect(this.linePosition, 0, CONFIG.WIDTH - this.linePosition, CONFIG.HEIGHT);
- // Draw dividing line
- ctx.fillStyle = 'black';
- ctx.fillRect(this.linePosition - 2, 0, 4, CONFIG.HEIGHT);
- }
- }
- // Game instance
- const game = new Game();
- // Event handlers
- document.addEventListener('keydown', (e) => {
- const now = performance.now();
- if (now - game.lastKeyPressTime < CONFIG.KEY_COOLDOWN) return;
- game.lastKeyPressTime = now;
- const key = e.key.toLowerCase();
- if (key === ' ') {
- game.reset();
- game.startWait();
- game.update(now);
- return;
- }
- if (game.gameOver) return;
- if (key === 'a') {
- game.redPressCount++;
- game.handlePress('red', -1);
- } else if (key === 'l') {
- game.bluePressCount++;
- game.handlePress('blue', 1);
- }
- });
- startButton.addEventListener('click', () => {
- startScreen.style.display = 'none';
- game.startWait();
- game.update(performance.now());
- });
- // Initial state
- game.draw(); // Draw initial canvas
- </script>
- </body>
- </html>
Advertisement
Add Comment
Please, Sign In to add comment