Untitled
unknown
plain_text
a month ago
10 kB
5
Indexable
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Retro Baseball Bros Arcade</title>
<style>
body {
margin: 0;
background-color: #222;
color: white;
font-family: 'Arial', sans-serif;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100vh;
overflow: hidden;
}
h1 {
margin: 5px 0;
font-size: 24px;
text-transform: uppercase;
letter-spacing: 2px;
color: #ffcc00;
}
#gameContainer {
position: relative;
box-shadow: 0 10px 30px rgba(0,0,0,0.5);
}
canvas {
background-color: #3e8e41; /* Field green */
border: 4px solid #fff;
display: block;
}
.controls {
margin-top: 10px;
font-size: 14px;
color: #aaa;
text-align: center;
}
span.key {
background: #444;
color: #fff;
padding: 2px 6px;
border-radius: 4px;
border: 1px solid #666;
font-weight: bold;
}
</style>
</head>
<body>
<h1>Baseball Bros Arcade</h1>
<div id="gameContainer">
<canvas id="gameCanvas" width="500" height="600"></canvas>
</div>
<div class="controls">
<p>As Batter: Press <span class="key">SPACEBAR</span> to Swing | As Pitcher: Press <span class="key">SPACEBAR</span> to Throw</p>
</div>
<script>
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
// Game States: 'PITCHING', 'BALL_IN_AIR', 'HIT', 'OUT', 'HOMERUN', 'STRIKE'
let gameState = 'PITCHING';
let score = 0;
let strikes = 0;
let outs = 0;
let feedbackText = "PRESS SPACE TO PITCH";
let feedbackTimer = 0;
// Pitcher properties
const pitcher = { x: 250, y: 180, radius: 15, color: '#3357FF' };
// Batter properties
const batter = { x: 250, y: 500, radius: 15, color: '#FF3333', isSwinging: false, swingTimer: 0 };
// Ball properties
const ball = { x: 250, y: 180, radius: 6, vx: 0, vy: 0, active: false, speed: 7, curve: 0 };
// Home plate zone marker
const homePlateY = 500;
// Event listener for user interactions
window.addEventListener('keydown', function(e) {
if (e.code === 'Space') {
handleAction();
}
});
function handleAction() {
if (gameState === 'PITCHING') {
// Pitch the ball with a slight random break/curve trajectory
ball.x = pitcher.x;
ball.y = pitcher.y;
ball.vy = ball.speed + (Math.random() * 3); // Variable velocity
ball.vx = (Math.random() - 0.5) * 2; // Slight horizontal movement
ball.active = true;
gameState = 'BALL_IN_AIR';
feedbackText = "";
} else if (gameState === 'BALL_IN_AIR' && !batter.isSwinging) {
// Trigger bat swing
batter.isSwinging = true;
batter.swingTimer = 8; // Frames the swing remains active
// Detect hit based on precise collision window near home plate
let distanceToBat = Math.abs(ball.y - homePlateY);
if (distanceToBat < 25 && ball.active) {
processHit();
}
} else if (gameState === 'OUT' || gameState === 'HOMERUN' || gameState === 'STRIKE') {
// Reset state for next pitch sequence
resetPitch();
}
}
function processHit() {
gameState = 'HIT';
ball.vy = -(ball.speed + 5 + Math.random() * 5); // Launch ball up field
ball.vx = (Math.random() - 0.5) * 10; // Spray angle left/right
// Power calculation determined by perfect timing sweet-spot
let timingAccuracy = Math.abs(ball.y - homePlateY);
if (timingAccuracy < 8) {
gameState = 'HOMERUN';
score += 1;
triggerFeedback("HOME RUN! +1 POINT");
} else {
// Randomly assign standard safe hit or field out
if (Math.random() > 0.4) {
score += 1;
triggerFeedback("BASE HIT!");
setTimeout(() => { resetPitch(); }, 1500);
} else {
gameState = 'OUT';
outs += 1;
triggerFeedback("FLY OUT!");
}
}
}
function triggerFeedback(text) {
feedbackText = text;
feedbackTimer = 90; // Frame duration text displays
}
function resetPitch() {
ball.active = false;
ball.x = pitcher.x;
ball.y = pitcher.y;
ball.vx = 0;
ball.vy = 0;
batter.isSwinging = false;
if (outs >= 3) {
// Reset game session details upon 3 outs
feedbackText = "GAME OVER! FINAL SCORE: " + score;
score = 0;
strikes = 0;
outs = 0;
gameState = 'PITCHING';
} else {
gameState = 'PITCHING';
feedbackText = "PRESS SPACE TO PITCH";
}
}
// Main game logic update loop
function update() {
if (gameState === 'BALL_IN_AIR') {
ball.y += ball.vy;
ball.x += ball.vx;
// Check for missed swing / strike zone exit boundary
if (ball.y > 550) {
strikes += 1;
if (strikes >= 3) {
outs += 1;
strikes = 0;
gameState = 'OUT';
triggerFeedback("STRIKE 3! YOU'RE OUT");
} else {
gameState = 'STRIKE';
triggerFeedback("STRIKE!");
}
}
}
if (gameState === 'HIT' || gameState === 'HOMERUN') {
ball.y += ball.vy;
ball.x += ball.vx;
// Keep hit balls within boundary walls or handle out of bounds flight paths
if (ball.y < -10 || ball.x < 0 || ball.x > canvas.width) {
if (gameState !== 'HOMERUN') resetPitch();
}
}
// Handle swinging animation cycles
if (batter.isSwinging) {
batter.swingTimer--;
if (batter.swingTimer <= 0) {
batter.isSwinging = false;
}
}
if (feedbackTimer > 0) feedbackTimer--;
}
// Visual asset rendering loop
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
// Draw baseball diamond field elements
ctx.strokeStyle = "rgba(255,255,255,0.6)";
ctx.lineWidth = 3;
ctx.beginPath();
ctx.moveTo(250, 520); // Home Plate apex
ctx.lineTo(80, 350); // 3rd Base line
ctx.lineTo(250, 180); // 2nd Base center
ctx.lineTo(420, 350); // 1st Base line
ctx.closePath();
ctx.stroke();
// Draw Outfield Warning Track Arc
ctx.beginPath();
ctx.arc(250, 520, 480, Math.PI, 2 * Math.PI);
ctx.strokeStyle = "#e67e22";
ctx.lineWidth = 8;
ctx.stroke();
// Render Pitcher Mound
ctx.beginPath();
ctx.arc(pitcher.x, pitcher.y, pitcher.radius, 0, Math.PI * 2);
ctx.fillStyle = pitcher.color;
ctx.fill();
ctx.closePath();
// Render Batter Box Position
ctx.beginPath();
ctx.arc(batter.x, batter.y, batter.radius, 0, Math.PI * 2);
ctx.fillStyle = batter.color;
ctx.fill();
ctx.closePath();
// Render active bat swing visual indicator
if (batter.isSwinging) {
ctx.beginPath();
ctx.arc(batter.x, batter.y, batter.radius + 18, 0, Math.PI, true);
ctx.strokeStyle = '#ffff00';
ctx.lineWidth = 5;
ctx.stroke();
}
// Render Baseball
if (ball.active || gameState === 'HIT' || gameState === 'HOMERUN') {
ctx.beginPath();
ctx.arc(ball.x, ball.y, ball.radius, 0, Math.PI * 2);
ctx.fillStyle = '#ffffff';
ctx.fill();
ctx.strokeStyle = '#e74c3c';
ctx.lineWidth = 1;
ctx.stroke();
ctx.closePath();
}
// Onscreen HUD (Heads-Up Display) Data
ctx.fillStyle = "#ffffff";
ctx.font = "bold 16px Arial";
ctx.fillText("SCORE: " + score, 20, 30);
ctx.fillText("STRIKES: " + "X".repeat(strikes), 20, 55);
ctx.fillText("OUTS: " + "●".repeat(outs) + "○".repeat(3 - outs), 20, 80);
// Large center UI text updates
if (feedbackText && (feedbackTimer > 0 || gameState === 'PITCHING')) {
ctx.fillStyle = (gameState === 'HOMERUN') ? '#ffcc00' : '#ffffff';
ctx.font = "bold 24px Arial";
ctx.textAlign = "center";
ctx.fillText(feedbackText, canvas.width / 2, canvas.height / 2 + 50);
ctx.textAlign = "start"; // Reset orientation
}
}
// Native browser core game execution loop
function gameLoop() {
update();
draw();
requestAnimationFrame(gameLoop);
}
// Launch operational instances
gameLoop();
</script>
</body>
</html>
Editor is loading...
Leave a Comment