- BC20270270's blog
拳王
- 2025-6-7 19:17:05 @
角色选择系统:
三位不同风格的拳击手(闪电李、重炮王、火焰拳)
每个角色有独特的速度和力量属性
战斗系统:
四种攻击方式:刺拳、勾拳、上勾拳、必杀技
不同攻击造成不同范围的伤害
对手会随机选择攻击方式反击
视觉效果:
动态生命值条
打击特效动画
拳击台场景绘制
响应式设计适应不同屏幕尺寸
控制方式:
鼠标点击按钮攻击
键盘快捷键(Q、W、E、R)控制攻击
游戏状态:
生命值系统
胜负判定
游戏结束提示
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>拳王争霸赛</title>
<link href="https://fonts.googleapis.com/css2?family=Orbitron:wght@700&family=Roboto:wght@400;700&display=swap" rel="stylesheet">
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Roboto', sans-serif;
background: linear-gradient(135deg, #1a1a2e, #16213e);
color: #fff;
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
padding: 20px;
overflow-x: hidden;
}
header {
text-align: center;
margin: 20px 0;
width: 100%;
}
h1 {
font-family: 'Orbitron', sans-serif;
font-size: 3.5rem;
text-transform: uppercase;
background: linear-gradient(to right, #ff512f, #f09819);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
text-shadow: 0 0 10px rgba(240, 152, 25, 0.5);
margin-bottom: 10px;
letter-spacing: 3px;
}
.subtitle {
font-size: 1.2rem;
color: #e6e6e6;
max-width: 800px;
margin: 0 auto;
line-height: 1.6;
}
.game-container {
display: flex;
flex-direction: column;
width: 100%;
max-width: 1000px;
background: rgba(10, 15, 35, 0.7);
border-radius: 15px;
padding: 20px;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5);
margin: 20px 0;
backdrop-filter: blur(5px);
border: 1px solid rgba(255, 255, 255, 0.1);
}
.game-stats {
display: flex;
justify-content: space-between;
padding: 15px;
background: rgba(0, 0, 0, 0.4);
border-radius: 10px;
margin-bottom: 20px;
}
.player-stats, .opponent-stats {
display: flex;
flex-direction: column;
align-items: center;
width: 45%;
}
.player-name, .opponent-name {
font-size: 1.8rem;
font-weight: bold;
margin-bottom: 10px;
text-transform: uppercase;
}
.player-name {
color: #4ecdc4;
}
.opponent-name {
color: #ff6b6b;
}
.health-bar {
width: 100%;
height: 30px;
background: #333;
border-radius: 15px;
overflow: hidden;
margin-bottom: 10px;
border: 2px solid #444;
}
.health-fill {
height: 100%;
transition: width 0.3s ease;
}
.player-health {
background: linear-gradient(to right, #4ecdc4, #1a936f);
width: 100%;
}
.opponent-health {
background: linear-gradient(to right, #ff6b6b, #ff2e63);
width: 100%;
}
.health-text {
font-size: 1.2rem;
font-weight: bold;
}
.game-area {
display: flex;
justify-content: space-between;
height: 400px;
position: relative;
background: linear-gradient(to bottom, #2c3e50, #1c2833);
border-radius: 10px;
overflow: hidden;
margin: 20px 0;
border: 3px solid #34495e;
}
canvas {
width: 100%;
height: 100%;
}
.controls {
display: flex;
justify-content: center;
gap: 15px;
margin-top: 20px;
flex-wrap: wrap;
}
.btn {
padding: 14px 30px;
font-size: 1.1rem;
font-weight: bold;
border: none;
border-radius: 50px;
cursor: pointer;
transition: all 0.3s ease;
text-transform: uppercase;
letter-spacing: 1px;
outline: none;
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3);
}
.btn:hover {
transform: translateY(-3px);
box-shadow: 0 8px 20px rgba(0, 0, 0, 0.4);
}
.btn:active {
transform: translateY(1px);
}
.jab {
background: linear-gradient(to right, #3498db, #2980b9);
color: white;
}
.hook {
background: linear-gradient(to right, #e74c3c, #c0392b);
color: white;
}
.uppercut {
background: linear-gradient(to right, #f39c12, #d35400);
color: white;
}
.special {
background: linear-gradient(to right, #9b59b6, #8e44ad);
color: white;
}
.game-message {
text-align: center;
font-size: 1.8rem;
font-weight: bold;
height: 60px;
margin: 20px 0;
padding: 10px;
color: #f1c40f;
text-shadow: 0 0 10px rgba(241, 196, 15, 0.7);
}
.character-selection {
display: flex;
justify-content: space-around;
margin: 20px 0;
flex-wrap: wrap;
gap: 20px;
}
.character {
display: flex;
flex-direction: column;
align-items: center;
cursor: pointer;
padding: 15px;
border-radius: 10px;
transition: all 0.3s ease;
width: 180px;
background: rgba(30, 40, 60, 0.6);
border: 2px solid transparent;
}
.character:hover {
background: rgba(50, 70, 100, 0.8);
transform: translateY(-5px);
}
.character.selected {
border-color: #f1c40f;
background: rgba(60, 90, 130, 0.8);
box-shadow: 0 0 20px rgba(241, 196, 15, 0.5);
}
.character-img {
width: 120px;
height: 120px;
border-radius: 50%;
margin-bottom: 10px;
background: #34495e;
display: flex;
align-items: center;
justify-content: center;
font-size: 3rem;
}
.character-name {
font-size: 1.3rem;
font-weight: bold;
margin-bottom: 5px;
}
.character-stats {
font-size: 0.9rem;
color: #bbb;
text-align: center;
}
.instructions {
background: rgba(0, 0, 0, 0.4);
padding: 20px;
border-radius: 10px;
margin-top: 20px;
width: 100%;
max-width: 1000px;
}
.instructions h2 {
color: #f1c40f;
margin-bottom: 15px;
text-align: center;
}
.instructions ul {
padding-left: 20px;
line-height: 1.8;
}
.instructions li {
margin-bottom: 8px;
}
@media (max-width: 768px) {
h1 {
font-size: 2.5rem;
}
.game-area {
height: 300px;
}
.character {
width: 140px;
}
.character-img {
width: 90px;
height: 90px;
font-size: 2rem;
}
.btn {
padding: 12px 20px;
font-size: 1rem;
}
}
@media (max-width: 480px) {
h1 {
font-size: 2rem;
}
.game-stats {
flex-direction: column;
align-items: center;
gap: 20px;
}
.player-stats, .opponent-stats {
width: 100%;
}
.controls {
gap: 10px;
}
.btn {
padding: 10px 15px;
font-size: 0.9rem;
}
}
.punch-effect {
position: absolute;
width: 100px;
height: 100px;
background: radial-gradient(circle, rgba(255,255,255,0.8) 0%, rgba(255,200,0,0) 70%);
border-radius: 50%;
pointer-events: none;
animation: punch 0.3s forwards;
z-index: 10;
}
@keyframes punch {
0% { transform: scale(0.3); opacity: 1; }
100% { transform: scale(1.5); opacity: 0; }
}
</style>
</head>
<body>
<header>
<h1>拳王争霸赛</h1>
<p class="subtitle">选择你的拳击手,击败强大的对手,成为新一代拳王!使用不同的攻击组合来战胜对手,注意你的生命值!</p>
</header>
<div class="game-container">
<div class="game-stats">
<div class="player-stats">
<div class="player-name" id="player-name">拳击手</div>
<div class="health-bar">
<div class="health-fill player-health" id="player-health"></div>
</div>
<div class="health-text">生命值: <span id="player-health-text">100</span></div>
</div>
<div class="opponent-stats">
<div class="opponent-name" id="opponent-name">钢铁迈克</div>
<div class="health-bar">
<div class="health-fill opponent-health" id="opponent-health"></div>
</div>
<div class="health-text">生命值: <span id="opponent-health-text">100</span></div>
</div>
</div>
<div class="game-message" id="game-message">选择角色开始比赛!</div>
<div class="character-selection">
<div class="character" data-id="1">
<div class="character-img">🥊</div>
<div class="character-name">闪电李</div>
<div class="character-stats">速度: ⭐⭐⭐⭐<br>力量: ⭐⭐</div>
</div>
<div class="character" data-id="2">
<div class="character-img">💥</div>
<div class="character-name">重炮王</div>
<div class="character-stats">速度: ⭐⭐<br>力量: ⭐⭐⭐⭐</div>
</div>
<div class="character" data-id="3">
<div class="character-img">🔥</div>
<div class="character-name">火焰拳</div>
<div class="character-stats">速度: ⭐⭐⭐<br>力量: ⭐⭐⭐</div>
</div>
</div>
<div class="game-area" id="game-area">
<canvas id="game-canvas"></canvas>
</div>
<div class="controls">
<button class="btn jab" id="jab">刺拳 (Q)</button>
<button class="btn hook" id="hook">勾拳 (W)</button>
<button class="btn uppercut" id="uppercut">上勾拳 (E)</button>
<button class="btn special" id="special">必杀技 (R)</button>
</div>
</div>
<div class="instructions">
<h2>游戏指南</h2>
<ul>
<li>从三位拳击手中选择一位开始比赛</li>
<li>使用四个攻击按钮或键盘按键(Q, W, E, R)发动攻击</li>
<li>不同的攻击方式造成不同的伤害:刺拳(5-8), 勾拳(8-12), 上勾拳(10-15), 必杀技(15-25)</li>
<li>对手也会反击,注意你的生命值!</li>
<li>击败对手成为拳王!</li>
</ul>
</div>
<script>
document.addEventListener('DOMContentLoaded', () => {
// 游戏状态
const gameState = {
playerHealth: 100,
opponentHealth: 100,
selectedCharacter: null,
gameActive: false,
playerX: 150,
opponentX: 650,
punchPosition: {x: 0, y: 0}
};
// DOM 元素
const playerHealthEl = document.getElementById('player-health');
const opponentHealthEl = document.getElementById('opponent-health');
const playerHealthText = document.getElementById('player-health-text');
const opponentHealthText = document.getElementById('opponent-health-text');
const gameMessage = document.getElementById('game-message');
const canvas = document.getElementById('game-canvas');
const ctx = canvas.getContext('2d');
const gameArea = document.getElementById('game-area');
// 设置Canvas尺寸
function setupCanvas() {
canvas.width = gameArea.clientWidth;
canvas.height = gameArea.clientHeight;
}
// 初始化
setupCanvas();
window.addEventListener('resize', setupCanvas);
// 绘制游戏场景
function drawGameScene() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
// 绘制背景
const gradient = ctx.createLinearGradient(0, 0, 0, canvas.height);
gradient.addColorStop(0, "#2c3e50");
gradient.addColorStop(1, "#1c2833");
ctx.fillStyle = gradient;
ctx.fillRect(0, 0, canvas.width, canvas.height);
// 绘制拳击台
ctx.fillStyle = '#8b0000';
ctx.fillRect(50, 50, canvas.width - 100, canvas.height - 100);
ctx.strokeStyle = '#ffffff';
ctx.lineWidth = 3;
ctx.strokeRect(50, 50, canvas.width - 100, canvas.height - 100);
// 绘制中线
ctx.beginPath();
ctx.moveTo(canvas.width/2, 50);
ctx.lineTo(canvas.width/2, canvas.height - 50);
ctx.strokeStyle = '#ffffff';
ctx.lineWidth = 2;
ctx.setLineDash([10, 10]);
ctx.stroke();
ctx.setLineDash([]);
// 绘制选手
drawFighter(gameState.playerX, 200, '#3498db', 'left');
drawFighter(gameState.opponentX, 200, '#e74c3c', 'right');
}
// 绘制拳击手
function drawFighter(x, y, color, direction) {
// 身体
ctx.fillStyle = color;
ctx.beginPath();
ctx.arc(x, y, 40, 0, Math.PI * 2);
ctx.fill();
// 头部
ctx.fillStyle = '#ffdbac';
ctx.beginPath();
ctx.arc(x, y - 70, 30, 0, Math.PI * 2);
ctx.fill();
// 眼睛
ctx.fillStyle = '#000';
const eyeOffset = direction === 'left' ? -10 : 10;
ctx.beginPath();
ctx.arc(x + eyeOffset, y - 75, 5, 0, Math.PI * 2);
ctx.fill();
// 嘴巴
ctx.strokeStyle = '#000';
ctx.lineWidth = 2;
ctx.beginPath();
ctx.arc(x, y - 65, 10, 0, Math.PI);
ctx.stroke();
// 手臂
ctx.fillStyle = color;
ctx.fillRect(x - 50, y - 40, 100, 20);
// 拳头
ctx.fillStyle = '#ffdbac';
if (direction === 'left') {
ctx.beginPath();
ctx.arc(x - 60, y - 30, 15, 0, Math.PI * 2);
ctx.fill();
} else {
ctx.beginPath();
ctx.arc(x + 60, y - 30, 15, 0, Math.PI * 2);
ctx.fill();
}
// 腿
ctx.fillStyle = color;
ctx.fillRect(x - 15, y + 40, 30, 60);
}
// 选择角色
const characters = document.querySelectorAll('.character');
characters.forEach(char => {
char.addEventListener('click', () => {
if (gameState.gameActive) return;
characters.forEach(c => c.classList.remove('selected'));
char.classList.add('selected');
gameState.selectedCharacter = char.dataset.id;
gameState.gameActive = true;
gameState.playerHealth = 100;
gameState.opponentHealth = 100;
gameMessage.textContent = "比赛开始!击败对手!";
updateHealthBars();
});
});
// 更新生命条
function updateHealthBars() {
playerHealthEl.style.width = `${gameState.playerHealth}%`;
opponentHealthEl.style.width = `${gameState.opponentHealth}%`;
playerHealthText.textContent = gameState.playerHealth;
opponentHealthText.textContent = gameState.opponentHealth;
// 检查游戏结束条件
if (gameState.playerHealth <= 0) {
gameState.playerHealth = 0;
gameState.gameActive = false;
gameMessage.textContent = "你被击败了!再试一次!";
setTimeout(resetGame, 3000);
} else if (gameState.opponentHealth <= 0) {
gameState.opponentHealth = 0;
gameState.gameActive = false;
gameMessage.textContent = "恭喜!你成为了新拳王!";
setTimeout(resetGame, 3000);
}
}
// 重置游戏
function resetGame() {
gameState.gameActive = false;
gameMessage.textContent = "选择角色开始比赛!";
characters.forEach(c => c.classList.remove('selected'));
}
// 攻击功能
function attack(type) {
if (!gameState.gameActive) return;
// 计算伤害
let damage = 0;
switch(type) {
case 'jab':
damage = Math.floor(Math.random() * 4) + 5;
gameState.punchPosition = {x: gameState.playerX + 100, y: 170};
break;
case 'hook':
damage = Math.floor(Math.random() * 5) + 8;
gameState.punchPosition = {x: gameState.playerX + 120, y: 170};
break;
case 'uppercut':
damage = Math.floor(Math.random() * 6) + 10;
gameState.punchPosition = {x: gameState.playerX + 110, y: 150};
break;
case 'special':
damage = Math.floor(Math.random() * 11) + 15;
gameState.punchPosition = {x: gameState.playerX + 130, y: 140};
break;
}
// 创建打击效果
createPunchEffect(gameState.punchPosition.x, gameState.punchPosition.y);
// 应用伤害
gameState.opponentHealth -= damage;
if (gameState.opponentHealth < 0) gameState.opponentHealth = 0;
gameMessage.textContent = `你使用了${getAttackName(type)},造成${damage}点伤害!`;
updateHealthBars();
// 对手反击
setTimeout(() => {
if (gameState.gameActive) {
opponentAttack();
}
}, 1000);
}
// 获取攻击名称
function getAttackName(type) {
const names = {
'jab': '刺拳',
'hook': '勾拳',
'uppercut': '上勾拳',
'special': '必杀技'
};
return names[type];
}
// 对手攻击
function opponentAttack() {
if (!gameState.gameActive) return;
const attacks = ['jab', 'hook', 'uppercut'];
const attackType = attacks[Math.floor(Math.random() * attacks.length)];
let damage = 0;
switch(attackType) {
case 'jab':
damage = Math.floor(Math.random() * 4) + 4;
gameState.punchPosition = {x: gameState.opponentX - 100, y: 170};
break;
case 'hook':
damage = Math.floor(Math.random() * 5) + 7;
gameState.punchPosition = {x: gameState.opponentX - 120, y: 170};
break;
case 'uppercut':
damage = Math.floor(Math.random() * 6) + 9;
gameState.punchPosition = {x: gameState.opponentX - 110, y: 150};
break;
}
createPunchEffect(gameState.punchPosition.x, gameState.punchPosition.y);
gameState.playerHealth -= damage;
if (gameState.playerHealth < 0) gameState.playerHealth = 0;
gameMessage.textContent = `对手使用了${getAttackName(attackType)},造成${damage}点伤害!`;
updateHealthBars();
}
// 创建打击效果
function createPunchEffect(x, y) {
const effect = document.createElement('div');
effect.classList.add('punch-effect');
effect.style.left = `${x - 50}px`;
effect.style.top = `${y - 50}px`;
gameArea.appendChild(effect);
setTimeout(() => {
effect.remove();
}, 300);
}
// 绑定攻击按钮
document.getElementById('jab').addEventListener('click', () => attack('jab'));
document.getElementById('hook').addEventListener('click', () => attack('hook'));
document.getElementById('uppercut').addEventListener('click', () => attack('uppercut'));
document.getElementById('special').addEventListener('click', () => attack('special'));
// 键盘控制
document.addEventListener('keydown', (e) => {
if (!gameState.gameActive) return;
switch(e.key.toLowerCase()) {
case 'q':
attack('jab');
break;
case 'w':
attack('hook');
break;
case 'e':
attack('uppercut');
break;
case 'r':
attack('special');
break;
}
});
// 动画循环
function gameLoop() {
drawGameScene();
requestAnimationFrame(gameLoop);
}
// 启动游戏循环
gameLoop();
});
</script>
</body>
</html>