前端 jQuery 简单实现一个网页格斗游戏示例

article/2025/8/23 5:19:10

 效果图

 

 

 源代码:

<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>简易格斗游戏</title><script src="https://cdn.tailwindcss.com"></script><script src="https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.min.js"></script><link href="https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css" rel="stylesheet"><script>tailwind.config = {theme: {extend: {colors: {primary: '#3B82F6',secondary: '#10B981',danger: '#EF4444',warning: '#F59E0B',dark: '#1E293B',light: '#F8FAFC'},fontFamily: {sans: ['Inter', 'system-ui', 'sans-serif'],gaming: ['Rajdhani', 'sans-serif']}}}}</script><style type="text/tailwindcss">@layer utilities {.content-auto {content-visibility: auto;}.fighter {position: absolute;transition: transform 0.1s ease-out;transform-origin: center bottom;}.fighter-1 {background-color: #3B82F6;box-shadow: 0 0 15px rgba(59, 130, 246, 0.7);}.fighter-2 {background-color: #EF4444;box-shadow: 0 0 15px rgba(239, 68, 68, 0.7);}.health-bar {height: 10px;transition: width 0.3s ease-in-out;}.punch {animation: punch 0.2s ease-in-out;}.kick {animation: kick 0.2s ease-in-out;}.block {animation: block 0.3s ease-in-out;}.hurt {animation: hurt 0.2s ease-in-out;}.jump {animation: jump 0.5s ease-in-out;}@keyframes punch {0% { transform: translateX(0); }50% { transform: translateX(15px); }100% { transform: translateX(0); }}@keyframes kick {0% { transform: translateY(0); }50% { transform: translateY(-10px) rotateZ(-5deg); }100% { transform: translateY(0); }}@keyframes block {0% { transform: scale(1); opacity: 1; }50% { transform: scale(1.05); opacity: 0.8; }100% { transform: scale(1); opacity: 1; }}@keyframes hurt {0% { transform: translateX(0); background-color: inherit; }50% { transform: translateX(-10px); background-color: white; }100% { transform: translateX(0); background-color: inherit; }}@keyframes jump {0% { transform: translateY(0); }50% { transform: translateY(-50px); }100% { transform: translateY(0); }}.arena {background-image: linear-gradient(to bottom, #374151, #1F2937);position: relative;overflow: hidden;}.arena-floor {background-image: linear-gradient(to right, #4B5563, #6B7280);height: 20px;width: 100%;position: absolute;bottom: 0;}.control-btn {@apply w-16 h-16 flex items-center justify-center rounded-full bg-primary/20 text-primary transition-all duration-200 hover:bg-primary/40 active:scale-95;}}</style><link href="https://fonts.googleapis.com/css2?family=Rajdhani:wght@400;500;600;700&display=swap" rel="stylesheet">
</head>
<body class="bg-gradient-to-br from-light to-gray-200 min-h-screen flex flex-col items-center justify-center p-4 font-sans"><div class="max-w-3xl w-full mx-auto"><!-- 游戏标题 --><h1 class="text-[clamp(1.8rem,5vw,2.5rem)] font-bold text-center text-dark mb-4 font-gaming tracking-wider"><span class="text-primary">格斗</span><span class="text-danger">竞技场</span></h1><!-- 游戏状态和控制区 --><div class="flex flex-wrap justify-between items-center mb-4"><div class="flex items-center gap-4 w-full md:w-auto"><div class="bg-white p-3 rounded-lg shadow-md w-full md:w-48"><div class="flex justify-between items-center mb-1"><p class="text-sm font-medium text-gray-700">玩家1</p><p id="player1Score" class="text-lg font-bold text-primary">0</p></div><div class="w-full bg-gray-200 rounded-full h-3 overflow-hidden"><div id="player1Health" class="health-bar bg-primary rounded-full" style="width: 100%"></div></div></div><div class="bg-white p-3 rounded-lg shadow-md w-full md:w-48"><div class="flex justify-between items-center mb-1"><p class="text-sm font-medium text-gray-700">玩家2</p><p id="player2Score" class="text-lg font-bold text-danger">0</p></div><div class="w-full bg-gray-200 rounded-full h-3 overflow-hidden"><div id="player2Health" class="health-bar bg-danger rounded-full" style="width: 100%"></div></div></div></div><div class="flex gap-2 mt-4 md:mt-0"><button id="startBtn" class="px-4 py-2 bg-primary text-white rounded-lg shadow-md hover:bg-primary/90 transition-all duration-200"><i class="fa fa-play mr-1"></i>开始</button><button id="resetBtn" class="px-4 py-2 bg-gray-600 text-white rounded-lg shadow-md hover:bg-gray-700 transition-all duration-200"><i class="fa fa-refresh mr-1"></i>重置</button></div></div><!-- 游戏区域 --><div class="relative"><div id="arena" class="arena aspect-[16/9] rounded-lg shadow-xl border-4 border-dark"><!-- 玩家1 --><div id="player1" class="fighter fighter-1 w-16 h-32 rounded-t-lg" style="left: 15%; bottom: 20px;"></div><!-- 玩家2 --><div id="player2" class="fighter fighter-2 w-16 h-32 rounded-t-lg" style="right: 15%; bottom: 20px;"></div><!-- 地面 --><div class="arena-floor"></div><!-- 游戏开始遮罩 --><div id="startScreen" class="absolute inset-0 bg-dark/80 flex flex-col items-center justify-center z-10"><h2 class="text-3xl font-bold text-white mb-4 font-gaming">格斗竞技场</h2><p class="text-gray-300 mb-6 max-w-md text-center">使用 WASD 控制玩家1,使用方向键控制玩家2。<br>空格键出拳,X键踢腿,C键防御。率先获得3分获胜!</p><button id="playBtn" class="px-6 py-3 bg-primary text-white rounded-lg shadow-lg hover:bg-primary/90 transition-all duration-200 transform hover:scale-105 font-gaming text-lg"><i class="fa fa-play-circle mr-2"></i>开始战斗</button></div><!-- 回合结束遮罩 --><div id="roundOverScreen" class="absolute inset-0 bg-dark/80 flex flex-col items-center justify-center z-10 hidden"><h2 id="roundWinner" class="text-3xl font-bold text-white mb-4 font-gaming"></h2><button id="nextRoundBtn" class="px-6 py-3 bg-primary text-white rounded-lg shadow-lg hover:bg-primary/90 transition-all duration-200 transform hover:scale-105 font-gaming text-lg mt-4"><i class="fa fa-forward mr-2"></i>下一回合</button></div><!-- 游戏结束遮罩 --><div id="gameOverScreen" class="absolute inset-0 bg-dark/80 flex flex-col items-center justify-center z-10 hidden"><h2 id="gameWinner" class="text-3xl font-bold text-white mb-2 font-gaming"></h2><p class="text-xl text-white mb-6">最终比分: <span id="finalScore" class="font-bold"></span></p><button id="newGameBtn" class="px-6 py-3 bg-primary text-white rounded-lg shadow-lg hover:bg-primary/90 transition-all duration-200 transform hover:scale-105 font-gaming text-lg"><i class="fa fa-refresh mr-2"></i>新游戏</button></div><!-- 倒计时 --><div id="countdown" class="absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 text-[clamp(3rem,15vw,8rem)] font-bold text-white font-gaming opacity-0 transition-opacity 0.5s"></div></div><!-- 移动端控制按钮 --><div class="mt-6 grid grid-cols-5 gap-2 max-w-2xl mx-auto md:hidden"><div class="col-span-5 flex justify-center gap-4 mb-2"><button id="mobileP1Punch" class="control-btn bg-primary/30 text-primary"><i class="fa fa-hand-rock-o text-xl"></i></button><button id="mobileP1Kick" class="control-btn bg-danger/30 text-danger"><i class="fa fa-shoe-prints text-xl"></i></button><button id="mobileP1Block" class="control-btn bg-gray-600/30 text-gray-600"><i class="fa fa-shield text-xl"></i></button></div><div class="col-span-5 flex justify-center gap-4"><button id="mobileP2Punch" class="control-btn bg-primary/30 text-primary"><i class="fa fa-hand-rock-o text-xl"></i></button><button id="mobileP2Kick" class="control-btn bg-danger/30 text-danger"><i class="fa fa-shoe-prints text-xl"></i></button><button id="mobileP2Block" class="control-btn bg-gray-600/30 text-gray-600"><i class="fa fa-shield text-xl"></i></button></div><div></div><button id="mobileP1Up" class="control-btn mx-auto"><i class="fa fa-chevron-up text-xl"></i></button><div></div><button id="mobileP1Left" class="control-btn"><i class="fa fa-chevron-left text-xl"></i></button><button id="mobileP1Down" class="control-btn mx-auto"><i class="fa fa-chevron-down text-xl"></i></button><button id="mobileP1Right" class="control-btn"><i class="fa fa-chevron-right text-xl"></i></button><div></div><button id="mobileP2Up" class="control-btn mx-auto"><i class="fa fa-chevron-up text-xl"></i></button><div></div><button id="mobileP2Left" class="control-btn"><i class="fa fa-chevron-left text-xl"></i></button><button id="mobileP2Down" class="control-btn mx-auto"><i class="fa fa-chevron-down text-xl"></i></button><button id="mobileP2Right" class="control-btn"><i class="fa fa-chevron-right text-xl"></i></button><div></div></div></div><!-- 游戏说明 --><div class="mt-6 p-4 bg-white rounded-lg shadow-md"><h3 class="font-semibold text-lg mb-2 text-dark">操作说明</h3><div class="grid grid-cols-1 md:grid-cols-2 gap-4"><div><h4 class="font-medium text-primary mb-2">玩家1 (蓝色)</h4><ul class="text-gray-600 space-y-1"><li><i class="fa fa-keyboard-o mr-1"></i> <kbd class="px-2 py-1 bg-gray-100 rounded text-sm">W</kbd> - 跳跃</li><li><i class="fa fa-keyboard-o mr-1"></i> <kbd class="px-2 py-1 bg-gray-100 rounded text-sm">A</kbd> - 向左移动</li><li><i class="fa fa-keyboard-o mr-1"></i> <kbd class="px-2 py-1 bg-gray-100 rounded text-sm">D</kbd> - 向右移动</li><li><i class="fa fa-keyboard-o mr-1"></i> <kbd class="px-2 py-1 bg-gray-100 rounded text-sm">空格</kbd> - 出拳</li><li><i class="fa fa-keyboard-o mr-1"></i> <kbd class="px-2 py-1 bg-gray-100 rounded text-sm">X</kbd> - 踢腿</li><li><i class="fa fa-keyboard-o mr-1"></i> <kbd class="px-2 py-1 bg-gray-100 rounded text-sm">C</kbd> - 防御</li></ul></div><div><h4 class="font-medium text-danger mb-2">玩家2 (红色)</h4><ul class="text-gray-600 space-y-1"><li><i class="fa fa-keyboard-o mr-1"></i> <kbd class="px-2 py-1 bg-gray-100 rounded text-sm">↑</kbd> - 跳跃</li><li><i class="fa fa-keyboard-o mr-1"></i> <kbd class="px-2 py-1 bg-gray-100 rounded text-sm">←</kbd> - 向左移动</li><li><i class="fa fa-keyboard-o mr-1"></i> <kbd class="px-2 py-1 bg-gray-100 rounded text-sm">→</kbd> - 向右移动</li><li><i class="fa fa-keyboard-o mr-1"></i> <kbd class="px-2 py-1 bg-gray-100 rounded text-sm">L</kbd> - 出拳</li><li><i class="fa fa-keyboard-o mr-1"></i> <kbd class="px-2 py-1 bg-gray-100 rounded text-sm">.</kbd> - 踢腿</li><li><i class="fa fa-keyboard-o mr-1"></i> <kbd class="px-2 py-1 bg-gray-100 rounded text-sm">/</kbd> - 防御</li></ul></div></div></div></div><script>$(document).ready(function() {// 游戏配置const config = {arenaWidth: $('#arena').width(),arenaHeight: $('#arena').height(),fighterWidth: 64, // 玩家宽度 (像素)fighterHeight: 128, // 玩家高度 (像素)moveSpeed: 5, // 移动速度 (像素/帧)jumpHeight: 100, // 跳跃高度 (像素)punchDamage: 10, // 拳伤害kickDamage: 15, // 踢伤害blockEfficiency: 0.3, // 防御效率 (0-1)scoreToWin: 3, // 获胜所需分数roundTime: 90, // 每回合时间 (秒)gravity: 2, // 重力加速度jumpPower: 18, // 跳跃力度knockback: 15, // 击退距离cooldown: 300, // 攻击冷却时间 (毫秒)};// 游戏状态const gameState = {isRunning: false,isPaused: false,round: 1,player1: {element: $('#player1'),x: 15, // 百分比位置y: 0, // 垂直位置 (0是地面)direction: 1, // 1 = 右, -1 = 左health: 100,score: 0,isJumping: false,velocityY: 0,isBlocking: false,lastAttackTime: 0,controls: {up: 87, // Wleft: 65, // Aright: 68, // Dpunch: 32, // 空格kick: 88, // Xblock: 67 // C}},player2: {element: $('#player2'),x: 85, // 百分比位置y: 0,direction: -1, // 面向玩家1health: 100,score: 0,isJumping: false,velocityY: 0,isBlocking: false,lastAttackTime: 0,controls: {up: 38, // 上箭头left: 37, // 左箭头right: 39, // 右箭头punch: 76, // Lkick: 190, // .block: 191 // /}},keys: {}, // 当前按下的键gameLoop: null,roundTime: config.roundTime,timeDisplay: null,countdown: 3,countdownTimer: null};// DOM元素const $arena = $('#arena');const $player1 = $('#player1');const $player2 = $('#player2');const $player1Health = $('#player1Health');const $player2Health = $('#player2Health');const $player1Score = $('#player1Score');const $player2Score = $('#player2Score');const $startBtn = $('#startBtn');const $resetBtn = $('#resetBtn');const $startScreen = $('#startScreen');const $roundOverScreen = $('#roundOverScreen');const $roundWinner = $('#roundWinner');const $nextRoundBtn = $('#nextRoundBtn');const $gameOverScreen = $('#gameOverScreen');const $gameWinner = $('#gameWinner');const $finalScore = $('#finalScore');const $newGameBtn = $('#newGameBtn');const $playBtn = $('#playBtn');const $countdown = $('#countdown');// 更新竞技场尺寸function updateArenaDimensions() {config.arenaWidth = $arena.width();config.arenaHeight = $arena.height();}// 设置玩家位置function setPlayerPosition(player) {// 计算像素位置const x = (player.x / 100) * (config.arenaWidth - config.fighterWidth);const y = config.arenaHeight - config.fighterHeight - 20 - player.y; // 20是地面高度// 应用位置player.element.css({left: `${x}px`,bottom: `${y}px`,transform: `scaleX(${player.direction})`});}// 初始化玩家function initPlayers() {gameState.player1.x = 15;gameState.player1.y = 0;gameState.player1.direction = 1;gameState.player1.health = 100;gameState.player1.isJumping = false;gameState.player1.velocityY = 0;gameState.player1.isBlocking = false;gameState.player2.x = 85;gameState.player2.y = 0;gameState.player2.direction = -1;gameState.player2.health = 100;gameState.player2.isJumping = false;gameState.player2.velocityY = 0;gameState.player2.isBlocking = false;updateHealthBars();setPlayerPosition(gameState.player1);setPlayerPosition(gameState.player2);}// 更新生命值条function updateHealthBars() {$player1Health.css('width', `${gameState.player1.health}%`);$player2Health.css('width', `${gameState.player2.health}%`);}// 更新分数显示function updateScores() {$player1Score.text(gameState.player1.score);$player2Score.text(gameState.player2.score);}// 检查碰撞function checkCollision(player1, player2) {// 计算像素位置const p1X = (player1.x / 100) * (config.arenaWidth - config.fighterWidth);const p2X = (player2.x / 100) * (config.arenaWidth - config.fighterWidth);// 碰撞检测 (简化版)const collisionDistance = config.fighterWidth * 0.7; // 稍微缩小碰撞范围return Math.abs(p1X - p2X) < collisionDistance;}// 应用攻击function applyAttack(attacker, defender, damage) {const now = Date.now();// 检查冷却时间if (now - attacker.lastAttackTime < config.cooldown) {return false;}// 记录攻击时间attacker.lastAttackTime = now;// 检查是否碰撞if (!checkCollision(attacker, defender)) {return false;}// 检查是否防御if (defender.isBlocking) {damage *= config.blockEfficiency; // 减少伤害// 防御动画defender.element.addClass('block');setTimeout(() => defender.element.removeClass('block'), 300);} else {// 受伤动画defender.element.addClass('hurt');setTimeout(() => defender.element.removeClass('hurt'), 200);// 击退效果const knockbackDir = attacker.direction;defender.x += knockbackDir * config.knockback / (config.arenaWidth / 100);// 确保不超出边界defender.x = Math.max(0, Math.min(100, defender.x));}// 减少生命值defender.health = Math.max(0, defender.health - damage);updateHealthBars();// 检查是否生命值归零if (defender.health <= 0) {endRound(attacker);}return true;}// 玩家移动function movePlayers() {// 玩家1移动const p1 = gameState.player1;if (gameState.keys[p1.controls.left]) {p1.x = Math.max(0, p1.x - config.moveSpeed / (config.arenaWidth / 100));p1.direction = -1;}if (gameState.keys[p1.controls.right]) {p1.x = Math.min(100, p1.x + config.moveSpeed / (config.arenaWidth / 100));p1.direction = 1;}if (gameState.keys[p1.controls.up] && !p1.isJumping) {p1.isJumping = true;p1.velocityY = -config.jumpPower;p1.element.addClass('jump');setTimeout(() => p1.element.removeClass('jump'), 500);}if (gameState.keys[p1.controls.block]) {p1.isBlocking = true;} else {p1.isBlocking = false;}if (gameState.keys[p1.controls.punch]) {if (applyAttack(p1, gameState.player2, config.punchDamage)) {p1.element.addClass('punch');setTimeout(() => p1.element.removeClass('punch'), 200);}}if (gameState.keys[p1.controls.kick]) {if (applyAttack(p1, gameState.player2, config.kickDamage)) {p1.element.addClass('kick');setTimeout(() => p1.element.removeClass('kick'), 200);}}// 玩家2移动const p2 = gameState.player2;if (gameState.keys[p2.controls.left]) {p2.x = Math.max(0, p2.x - config.moveSpeed / (config.arenaWidth / 100));p2.direction = -1;}if (gameState.keys[p2.controls.right]) {p2.x = Math.min(100, p2.x + config.moveSpeed / (config.arenaWidth / 100));p2.direction = 1;}if (gameState.keys[p2.controls.up] && !p2.isJumping) {p2.isJumping = true;p2.velocityY = -config.jumpPower;p2.element.addClass('jump');setTimeout(() => p2.element.removeClass('jump'), 500);}if (gameState.keys[p2.controls.block]) {p2.isBlocking = true;} else {p2.isBlocking = false;}if (gameState.keys[p2.controls.punch]) {if (applyAttack(p2, gameState.player1, config.punchDamage)) {p2.element.addClass('punch');setTimeout(() => p2.element.removeClass('punch'), 200);}}if (gameState.keys[p2.controls.kick]) {if (applyAttack(p2, gameState.player1, config.kickDamage)) {p2.element.addClass('kick');setTimeout(() => p2.element.removeClass('kick'), 200);}}// 应用重力applyGravity(p1);applyGravity(p2);// 更新位置setPlayerPosition(p1);setPlayerPosition(p2);}// 应用重力function applyGravity(player) {if (player.isJumping) {player.velocityY += config.gravity;player.y += player.velocityY;// 落地检测if (player.y >= 0) {player.y = 0;player.velocityY = 0;player.isJumping = false;}}}// 开始倒计时function startCountdown() {$countdown.text(gameState.countdown);$countdown.css('opacity', '1');gameState.countdownTimer = setInterval(() => {gameState.countdown--;$countdown.text(gameState.countdown);if (gameState.countdown <= 0) {clearInterval(gameState.countdownTimer);$countdown.css('opacity', '0');startRound();}}, 1000);}// 开始回合function startRound() {initPlayers();gameState.isRunning = true;gameState.roundTime = config.roundTime;// 开始游戏循环if (gameState.gameLoop) {clearInterval(gameState.gameLoop);}gameState.gameLoop = setInterval(gameLoop, 16); // 约60FPS// 开始倒计时if (gameState.timeDisplay) {clearInterval(gameState.timeDisplay);}gameState.timeDisplay = setInterval(updateRoundTime, 1000);}// 结束回合function endRound(winner) {gameState.isRunning = false;clearInterval(gameState.gameLoop);clearInterval(gameState.timeDisplay);// 增加分数winner.score++;updateScores();// 显示回合结束屏幕$roundWinner.text(`${winner === gameState.player1 ? '玩家1' : '玩家2'} 获胜!`);$roundOverScreen.removeClass('hidden');// 检查是否有玩家达到获胜分数if (gameState.player1.score >= config.scoreToWin || gameState.player2.score >= config.scoreToWin) {setTimeout(endGame, 1000);}}// 结束游戏function endGame() {$roundOverScreen.addClass('hidden');// 确定获胜者const winner = gameState.player1.score > gameState.player2.score ? gameState.player1 : gameState.player2;$gameWinner.text(`${winner === gameState.player1 ? '玩家1' : '玩家2'} 赢得比赛!`);$finalScore.text(`${gameState.player1.score} - ${gameState.player2.score}`);// 显示游戏结束屏幕$gameOverScreen.removeClass('hidden');}// 更新回合时间function updateRoundTime() {gameState.roundTime--;// 时间到,结束回合if (gameState.roundTime <= 0) {// 确定生命值较高的玩家获胜const winner = gameState.player1.health > gameState.player2.health ? gameState.player1 : gameState.player2;endRound(winner);}}// 游戏主循环function gameLoop() {if (!gameState.isRunning || gameState.isPaused) return;movePlayers();}// 开始新游戏function startGame() {gameState.round = 1;gameState.player1.score = 0;gameState.player2.score = 0;updateScores();$startScreen.addClass('hidden');$gameOverScreen.addClass('hidden');startCountdown();}// 重置游戏function resetGame() {clearInterval(gameState.gameLoop);clearInterval(gameState.timeDisplay);clearInterval(gameState.countdownTimer);gameState.isRunning = false;gameState.isPaused = false;gameState.countdown = 3;initPlayers();$startScreen.removeClass('hidden');$roundOverScreen.addClass('hidden');$gameOverScreen.addClass('hidden');}// 初始化游戏function initGame() {updateArenaDimensions();initPlayers();// 绑定事件$(document).keydown((e) => {gameState.keys[e.keyCode] = true;});$(document).keyup((e) => {gameState.keys[e.keyCode] = false;});$startBtn.click(startGame);$resetBtn.click(resetGame);$playBtn.click(startGame);$nextRoundBtn.click(() => {$roundOverScreen.addClass('hidden');gameState.countdown = 3;startCountdown();});$newGameBtn.click(resetGame);// 移动端控制$('#mobileP1Up').mousedown(() => gameState.keys[gameState.player1.controls.up] = true).mouseup(() => gameState.keys[gameState.player1.controls.up] = false);$('#mobileP1Left').mousedown(() => gameState.keys[gameState.player1.controls.left] = true).mouseup(() => gameState.keys[gameState.player1.controls.left] = false);$('#mobileP1Right').mousedown(() => gameState.keys[gameState.player1.controls.right] = true).mouseup(() => gameState.keys[gameState.player1.controls.right] = false);$('#mobileP1Punch').mousedown(() => gameState.keys[gameState.player1.controls.punch] = true).mouseup(() => gameState.keys[gameState.player1.controls.punch] = false);$('#mobileP1Kick').mousedown(() => gameState.keys[gameState.player1.controls.kick] = true).mouseup(() => gameState.keys[gameState.player1.controls.kick] = false);$('#mobileP1Block').mousedown(() => gameState.keys[gameState.player1.controls.block] = true).mouseup(() => gameState.keys[gameState.player1.controls.block] = false);$('#mobileP2Up').mousedown(() => gameState.keys[gameState.player2.controls.up] = true).mouseup(() => gameState.keys[gameState.player2.controls.up] = false);$('#mobileP2Left').mousedown(() => gameState.keys[gameState.player2.controls.left] = true).mouseup(() => gameState.keys[gameState.player2.controls.left] = false);$('#mobileP2Right').mousedown(() => gameState.keys[gameState.player2.controls.right] = true).mouseup(() => gameState.keys[gameState.player2.controls.right] = false);$('#mobileP2Punch').mousedown(() => gameState.keys[gameState.player2.controls.punch] = true).mouseup(() => gameState.keys[gameState.player2.controls.punch] = false);$('#mobileP2Kick').mousedown(() => gameState.keys[gameState.player2.controls.kick] = true).mouseup(() => gameState.keys[gameState.player2.controls.kick] = false);$('#mobileP2Block').mousedown(() => gameState.keys[gameState.player2.controls.block] = true).mouseup(() => gameState.keys[gameState.player2.controls.block] = false);// 窗口大小改变时更新竞技场尺寸$(window).resize(updateArenaDimensions);}// 启动游戏initGame();});</script>
</body>
</html>

 

这个格斗游戏示例具有以下特点:

  1. 双人对战系统 - 支持两名玩家同时控制角色进行对战
  2. 完整的动作系统 - 包含移动、跳跃、出拳、踢腿和防御等动作
  3. 回合制游戏 - 先获得 3 分的玩家获胜
  4. 生命值和计分系统 - 显示玩家生命值和得分
  5. 键盘和触屏控制 - 支持键盘操作和移动端触屏按钮
  6. 物理系统 - 包含重力和碰撞检测
  7. 视觉反馈 - 攻击、防御和受伤都有相应的动画效果
  8. 游戏状态管理 - 包含倒计时、回合结束和游戏结束状态

玩家 1 使用 WASD 控制移动,空格键出拳,X 键踢腿,C 键防御;玩家 2 使用方向键控制移动,L 键出拳,. 键踢腿,/ 键防御。游戏中先获得 3 分的玩家获胜。

这个格斗游戏使用了以下外部资源和插件:

  1. Tailwind CSS

    • 版本:v3
    • 通过 CDN 引入:https://cdn.tailwindcss.com
    • 作用:提供工具类 CSS,用于快速构建响应式布局和视觉效果
  2. Font Awesome

    • 版本:v4.7.0
    • 通过 CDN 引入:https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css
    • 作用:提供游戏中使用的各种图标(如按钮图标、控制说明图标)
  3. jQuery

    • 版本:v3.6.0
    • 通过 CDN 引入:https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.min.js
    • 作用:简化 DOM 操作和事件处理,实现游戏逻辑
  4. Rajdhani 字体

    • 通过 Google Fonts 引入:https://fonts.googleapis.com/css2?family=Rajdhani:wght@400;500;600;700&display=swap
    • 作用:提供游戏标题和界面的专用字体,增强游戏风格

这些资源都是通过 CDN 直接引入的,无需额外安装,确保了游戏的快速加载和兼容性。游戏的核心逻辑完全基于原生 JavaScript 实现,没有使用其他游戏引擎或框架。

 


http://www.hkcw.cn/article/KmRoXCRamX.shtml

相关文章

stm32 + ads1292心率检测报警设置上下限

这个项目是在做心率检测的时候一个小伙伴提出来的&#xff0c;今年五一的时候提出来的想法&#xff0c;五一假期的时候没时间&#xff0c;也没心情做这个&#xff0c;就把这个事情搁置了&#xff0c;在月中做工作计划的时候&#xff0c;就把这个小项目排进来了&#xff0c;五一…

git+svn+sourcetree客户端下载和安装教程

1.引言 本文带来git、svn、sourcetree的软件的下载链接和安装介绍。git、svn是文件版本控制工具&#xff0c;电脑安装后需要使用cmd命令来提交或拉取文件。非常麻烦&#xff0c;推荐使用sourcetree等工具来提交代码 sourcetree界面 压缩包内容&#xff0c;git、svn、svn汉化工…

华为湖南总部大楼刷新马栏山风景线:已经进入内部装修阶段

华为湖南总部大楼刷新马栏山风景线。5月29日,航拍镜头下的位于马栏山视频文创产业园的华为湖南总部大楼项目大楼十分引人注目,三栋楼体采用金色线条和玻璃元素,成为拔节生长的马栏山里一道亮丽的风景。从现场施工来看,该项目园林绿化已经完成,已经进入内部装修阶段。该项目…

小学生捡到手机后交给民警被送锦旗:失主准备了一面“哪吒锦旗”

小学生捡到手机后交给民警被送锦旗。近日,四川成都。7岁的小学生廖元祎在路边捡到一部手机,送到了派出所。巧合的是,就在廖元祎走进派出所不久,失主也来到派出所报失。看到手机物归原主,廖元祎开心地跳起来。为了给廖元祎一个表扬,失主准备了一面“哪吒锦旗”,和民警一起…

王力宏称为癌症研究者哥哥感到骄傲

王力宏称为癌症研究者哥哥感到骄傲。5月29日下午,知名歌手王力宏在社交媒体晒出哥哥王力德的演讲视频,以及和哥哥的合影。王力宏表示:“为我哥哥王力德博士感到骄傲!他在香港举行的ASGH亚洲医疗健康高峰会上发表演讲,思路清晰、充满远见。哥哥介绍了自己在希望之城实验室的…

风云二号 F 星:地球静止轨道上的气象先锋

风云二号卫星是我国第一代地球静止轨道气象卫星&#xff0c;从 1986 年国家正式批复风云二号气象卫星工程以来&#xff0c;经过多年的研制与发展。风云二号 F 星作为 03 批的首发星&#xff0c;其成功发射进一步提高了我国静止气象卫星的观测能力和技术水平&#xff0c;对于确保…

论文笔记:DreamDiffusion

【初中生也能看得懂的讲解】 想象一下&#xff0c;我们能不能直接用“脑子想”来画画&#xff1f;比如你想到一只猫&#xff0c;电脑就能画出一只猫。这听起来是不是很酷&#xff1f;科学家们一直在努力实现这个“意念画画”的梦想。 以前&#xff0c;科学家们可能会用一种叫…

输电线路的“智慧之眼”:全天候可视化监测如何赋能电网安全运维

在电力需求持续攀升、电网规模日益庞大的今天&#xff0c;输电线路的安全稳定运行面临着前所未有的挑战。线路跨越地形复杂多变&#xff0c;尤其是在偏远山区、铁路沿线及恶劣天气条件下&#xff0c;传统的人工巡检方式显得力不从心——效率低、风险高、覆盖有限。如何实现更智…

通过域名访问k8s-pod方案

针对一些特殊业务需要通过pod名称或域名直接访问pod内部服务。本文主要提供一种暴露pod域名到公司内网的方案。 01 技术方案 1、使用coredns基于etcd的域名解析插件 2、单独部署一套server&#xff0c;该server负责接收agent发来的域名记录请求&#xff0c;并将数据写到etcd。 …

【C++高级主题】命令空间(三):未命名的命名空间

目录 一、未命名的命名空间的基本概念 1.1 定义与特点 1.2 基本语法 1.3 访问方式 1.4 未命名的命名空间的作用 二、未命名的命名空间与静态声明的比较 2.1 静态声明的作用 2.2 未命名的命名空间的优势 2.3 示例代码比较 2.4. 未命名的命名空间的作用域和链接属性 三…

生成式人工智能:重构软件开发的范式革命与未来生态

引言 生成式人工智能&#xff08;GenAI&#xff09;正以颠覆性力量重塑软件开发的底层逻辑。从代码生成到业务逻辑设计&#xff0c;从数据分析到用户交互&#xff0c;GenAI通过其强大的推理能力与场景适应性&#xff0c;将传统开发流程的“复杂工程”转化为“敏捷实验”&#…

石宇奇称需要重视伤病:近期因治疗胃病导致腹部皮肤被烫出水泡

石宇奇称需要重视伤病。5月27日,在2025年新加坡羽毛球公开赛男单首轮比赛中,中国名将石宇奇以2比0战胜印尼选手郑加恒,顺利晋级十六强。赛后他透露,近期因治疗胃病导致腹部皮肤被烫出水泡。据了解,石宇奇长期受胃部不适和消化问题困扰,尤其2025年全英赛后症状加重,苏迪曼…

Attention Is All You Need论文阅读笔记

Attention is All You Need是如今机器学习研究者必读的论文&#xff0c;该文章提出的Transformer架构是如今很多机器学习项目的基础&#xff0c;说该文章极大推动了机器学习领域的研究也不为过。 但这么重要&#xff0c;也是必读的文章对初学者来说其实并不友好&#xff0c;很多…

持续12年的股权争夺战即将落幕 75%股权归属终见分晓

持续12年的股权争夺战即将落幕 75%股权归属终见分晓。一场持续12年的股权争夺战即将落幕。胡绪峰表示相信二审能公正判决,75%的股权归属问题即将揭晓。这场股权争夺战涉及陕西省公安厅厅长批示、最高人民法院判决,并影响了2000多户购房人的居住问题。2025年5月27日,王坚与陕…

Linux入门

环境配置&#xff1a; linux安装 https://old-releases.ubuntu.com/releases/14.04.4/ubuntu-14.04-server-amd64.isohttps://www.releases.ubuntu.com/14.04/下载后vmware打开iso文件 配置linux开机设置ssh与samba xshell:使用ip链接linux &#xff1a;linux获取ip&#xff…

黄仁勋终于告别股价下跌魔咒!

黄仁勋终于告别股价下跌魔咒。在很长的一段时间里,英伟达财报一发,股价就跌。不是因为业绩不行,而是因为只是超预期还不够。市场一面期待英伟达不仅是超预期增长,还要远超预期。一面期待英伟达高歌猛进的同时,抚平外界对其高增长可持续性的种种疑虑。这次终于不同了。当地…

云渲染农场行业需求,如何搭建,有什么用途?

云渲染农场是以云计算技术为基础&#xff0c;向用户提供高性能算力以解决三维设计任务本地渲染慢的问题。云渲染农场通过集群管理软件管理数万台服务器&#xff0c;用户只需要将3D效果图和动画渲染任务通过客户端提交&#xff0c;云渲染农场就可以将任务分配至空闲的高配服务器…

Ant Design Pro简单模版的搭建步骤

1.在电脑创建一个文件夹 2.在创建的目录下打开cmd 3.输入npm i ant-design/pro-cli -g来安装脚手架 npm i ant-design/pro-cli -g 4.输入pro create 项目名 选择simple 5. 下载完成以后进到目录中 cd reactAdmin 6. 安装依赖 yarn install 7. 安装完以后&#xff0c;启动…

美国联邦法官叫停禁止哈佛大学招收国际学生政策

美国马萨诸塞州联邦地区法院一名法官当地时间5月29日批准了哈佛大学对法院提出的发布初步禁令请求,“叫停”特朗普政府取消哈佛大学招收外国学生资质的政策。该法院法官艾莉森伯勒斯当天就该案举行听证会。法院网站最新信息显示,此前发布的临时限制令将继续有效,待各方协商并…

低代码——表单生成器Form Generator详解(二)——从JSON配置项到动态渲染表单渲染

在设计低代码表单生成器之前&#xff0c;需要了解组件库相关内容的基础内容 ElementUI中Layout布局与Form表单详解 核心流程 表单生成器从 JSON 配置到动态渲染表单的核心流程如下&#xff1a; 解析 JSON 配置&#xff1a;构建表单的结构和规则组件映射与渲染&#xff1a;将…