html
<!DOCTYPE html>
<html>
<head>
<title>Advanced Tank War with Ally</title>
<style>
canvas { border: 1px solid black; }
#info { position: absolute; left: 620px; top: 10px; width: 200px; }
</style>
</head>
<body>
<canvas id="gameCanvas" width="800" height="600"></canvas>
<div id="info"></div>
<script>
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
const INFO_HTML = `
<h3>操作说明</h3>
方向键:移动<br>
空格:射击(冷却时间)<br>
鼠标:瞄准<br>
<h3>单位类型</h3>
绿色:玩家坦克<br>
蓝色:友方AI坦克<br>
浅红:普通敌人<br>
深红:重型敌人<br>
最红:精英敌人(会拦截射击)`;
let gameState = {
player: {
x: 400, y: 300, size: 30, color: '#0f0',
speed: 5, hp: 10, angle: 0,
fireCooldown: 0, fireCooldownTime: 20
},
ally: {
x: 200, y: 200, size: 30, color: '#00f',
speed: 4, hp: 3, angle: 0,
fireCooldown: 0, fireCooldownTime: 10,
target: null, state: 'patrol', patrolTimer: 0
},
enemies: [],
bullets: [],
level: 1,
aimAngle: {x: 400, y: 300},
gameOver: false,
totalEnemies: 0,
escapedEnemies: 0
};
function initGame() {
alert(INFO_HTML);
generateEnemies();
}
function generateEnemies() {
const count = gameState.level * 3 + 2;
gameState.totalEnemies = count;
gameState.escapedEnemies = 0;
for (let i = 0; i < count; i++) {
const red = 150 + Math.random() * 105;
const type = red > 240 ? 'elite' : red > 180 ? 'heavy' : 'normal';
gameState.enemies.push({
x: -50,
y: Math.random() * 550 + 25,
size: 30,
color: `rgb(${red},0,0)`,
speed: type === 'elite' ? 1.5 : 3 - (red-150)/50,
hp: Math.ceil((red-150)/35),
angle: 0,
targetAngle: 0,
type: type,
fireCooldown: 0
});
}
}
function checkCollision(rect1, rect2) {
return rect1.x < rect2.x + rect2.size &&
rect1.x + rect1.size > rect2.x &&
rect1.y < rect2.y + rect2.size &&
rect1.y + rect1.size > rect2.y;
}
function gameLoop() {
if (gameState.gameOver) return;
ctx.clearRect(0, 0, canvas.width, canvas.height);
updateGame();
drawPlayer();
drawAlly();
drawEnemies();
drawBullets();
drawAim();
drawUI();
requestAnimationFrame(gameLoop);
}
function updateGame() {
// 更新友方AI
updateAlly();
// 更新敌人状态
for (let i = gameState.enemies.length - 1; i >= 0; i--) {
const enemy = gameState.enemies[i];
// 精英坦克逻辑
if (enemy.type === 'elite') {
const targetX = gameState.player.x + 300;
const targetY = gameState.player.y;
if (enemy.x < targetX - 50) {
enemy.x += enemy.speed * 1.2;
} else {
// 瞄准射击
const dx = gameState.player.x - enemy.x;
const dy = gameState.player.y - enemy.y;
enemy.targetAngle = Math.atan2(dy, dx);
if (enemy.fireCooldown <= 0) {
gameState.bullets.push({
x: enemy.x + 15,
y: enemy.y + 15,
angle: enemy.targetAngle,
size: 6,
isEnemy: true
});
enemy.fireCooldown = 80;
} else {
enemy.fireCooldown--;
}
}
} else {
enemy.x += enemy.speed;
}
// 逃逸检测
if (enemy.x > 800) {
gameState.escapedEnemies++;
gameState.enemies.splice(i, 1);
}
}
// 更新子弹
for (let i = gameState.bullets.length - 1; i >= 0; i--) {
const bullet = gameState.bullets[i];
bullet.x += Math.cos(bullet.angle) * 10;
bullet.y += Math.sin(bullet.angle) * 10;
// 边界检测
if (bullet.x < 0 || bullet.x > 800 || bullet.y < 0 || bullet.y > 600) {
gameState.bullets.splice(i, 1);
continue;
}
// 碰撞检测
if (bullet.isEnemy) {
if (checkCollision(bullet, gameState.player)) {
gameState.player.hp--;
gameState.bullets.splice(i, 1);
if (gameState.player.hp <= 0) gameOver(false);
} else if (checkCollision(bullet, gameState.ally)) {
gameState.ally.hp--;
gameState.bullets.splice(i, 1);
if (gameState.ally.hp <= 0) {
alert("友军坦克被摧毁!");
gameState.ally.hp = 3; // 友军重生
}
}
} else {
for (let j = gameState.enemies.length - 1; j >= 0; j--) {
if (checkCollision(bullet, gameState.enemies[j])) {
gameState.enemies[j].hp--;
if (gameState.enemies[j].hp <= 0) {
gameState.enemies.splice(j, 1);
}
gameState.bullets.splice(i, 1);
break;
}
}
}
}
// 关卡状态检测
if (gameState.escapedEnemies > gameState.totalEnemies * 0.5) {
alert(`超过50%敌人逃脱!关卡${gameState.level}失败!`);
generateEnemies();
return;
}
if (gameState.enemies.length === 0) {
gameState.level++;
if (gameState.level > 3) {
gameOver(true);
return;
}
generateEnemies();
}
// 更新玩家冷却
if (gameState.player.fireCooldown > 0) {
gameState.player.fireCooldown--;
}
}
function updateAlly() {
const ally = gameState.ally;
// 优先寻找重型或精英坦克
if (!ally.target || ally.target.hp <= 0 || ally.patrolTimer > 90) {
ally.target = findPriorityTarget();
ally.patrolTimer = 0;
}
if (ally.target) {
// 攻击模式
const dx = ally.target.x - ally.x;
const dy = ally.target.y - ally.y;
const dist = Math.sqrt(dx*dx + dy*dy);
// 动态移动策略
if (dist > 250) {
// 快速接近目标
ally.x += (dx/dist) * ally.speed * 1.2;
ally.y += (dy/dist) * ally.speed * 1.2;
} else if (dist < 150) {
// 保持安全距离
ally.x -= (dx/dist) * ally.speed * 0.8;
ally.y -= (dy/dist) * ally.speed * 0.8;
} else {
// 侧向移动避免直线冲锋
const sideMove = Math.sin(Date.now()/500) * 50;
ally.x += (dy/dist) * sideMove * 0.1;
ally.y -= (dx/dist) * sideMove * 0.1;
}
// 瞄准射击
ally.angle = Math.atan2(dy, dx);
if (ally.fireCooldown <= 0 && dist < 300) {
gameState.bullets.push({
x: ally.x + 15,
y: ally.y + 15,
angle: ally.angle,
size: 6,
isEnemy: false
});
ally.fireCooldown = ally.fireCooldownTime;
}
} else {
// 没有目标时的巡逻行为
ally.patrolTimer++;
if (ally.patrolTimer > 120) {
ally.x += (Math.random() - 0.5) * 50;
ally.y += (Math.random() - 0.5) * 50;
ally.patrolTimer = 0;
}
// 向玩家靠拢但保持一定距离
const px = gameState.player.x - ally.x;
const py = gameState.player.y - ally.y;
const pDist = Math.sqrt(px*px + py*py);
if (pDist > 200) {
ally.x += (px/pDist) * ally.speed * 0.5;
ally.y += (py/pDist) * ally.speed * 0.5;
}
}
// 边界检查
ally.x = Math.max(0, Math.min(770, ally.x));
ally.y = Math.max(0, Math.min(570, ally.y));
// 冷却更新
if (ally.fireCooldown > 0) {
ally.fireCooldown--;
}
}
// 寻找优先目标(重型/精英坦克)
function findPriorityTarget() {
let priorityTarget = null;
let minDist = Infinity;
gameState.enemies.forEach(enemy => {
// 优先选择重型或精英坦克
if (enemy.type === 'heavy' || enemy.type === 'elite') {
const dist = Math.sqrt(
Math.pow(enemy.x - gameState.ally.x, 2) +
Math.pow(enemy.y - gameState.ally.y, 2)
);
if (dist < minDist) {
minDist = dist;
priorityTarget = enemy;
}
}
});
// 如果没有优先目标,选择最近的普通坦克
if (!priorityTarget && gameState.enemies.length > 0) {
gameState.enemies.forEach(enemy => {
const dist = Math.sqrt(
Math.pow(enemy.x - gameState.ally.x, 2) +
Math.pow(enemy.y - gameState.ally.y, 2)
);
if (dist < minDist) {
minDist = dist;
priorityTarget = enemy;
}
});
}
return priorityTarget;
}
function gameOver(isWin) {
gameState.gameOver = true;
alert(isWin ? "最终胜利!" : "游戏失败!");
location.reload();
}
function drawPlayer() {
drawTank(gameState.player);
}
function drawAlly() {
drawTank(gameState.ally);
// 绘制友军状态指示器
ctx.fillStyle = gameState.ally.state === 'attack' ? '#f00' : '#0a0';
ctx.beginPath();
ctx.arc(gameState.ally.x + 15, gameState.ally.y - 10, 5, 0, Math.PI*2);
ctx.fill();
}
function drawEnemies() {
gameState.enemies.forEach(enemy => {
drawTank(enemy);
if (enemy.type === 'elite') {
ctx.beginPath();
ctx.arc(enemy.x+15, enemy.y+15, 40, 0, Math.PI*2);
ctx.strokeStyle = 'rgba(255,0,0,0.3)';
ctx.stroke();
}
});
}
function drawTank(tank) {
ctx.save();
ctx.translate(tank.x + tank.size/2, tank.y + tank.size/2);
ctx.rotate(tank.angle);
ctx.fillStyle = tank.color;
ctx.fillRect(-tank.size/2, -tank.size/2, tank.size, tank.size);
ctx.strokeStyle = '#333';
ctx.lineWidth = 4;
ctx.beginPath();
ctx.moveTo(0, 0);
ctx.lineTo(tank.size/2, 0);
ctx.stroke();
ctx.restore();
}
function drawBullets() {
ctx.fillStyle = '#000';
gameState.bullets.forEach(bullet => {
ctx.beginPath();
ctx.arc(bullet.x, bullet.y, 3, 0, Math.PI*2);
ctx.fill();
});
}
function drawAim() {
ctx.strokeStyle = '#f00';
ctx.beginPath();
ctx.arc(gameState.aimAngle.x, gameState.aimAngle.y, 10, 0, Math.PI*2);
ctx.stroke();
}
function drawUI() {
const cdPercent = (gameState.player.fireCooldown / gameState.player.fireCooldownTime) * 100;
document.getElementById('info').innerHTML = `
关卡:${gameState.level}<br>
玩家HP:${gameState.player.hp}<br>
友军HP:${gameState.ally.hp}<br>
逃脱敌人:${gameState.escapedEnemies}/${gameState.totalEnemies}
<div style="background:#ddd; width:100px; height:10px">
<div style="background:#f00; width:${cdPercent}%; height:10px"></div>
</div>`;
}
document.addEventListener('keydown', (e) => {
const p = gameState.player;
if (e.key === 'ArrowUp') p.y = Math.max(0, p.y - p.speed);
if (e.key === 'ArrowDown') p.y = Math.min(570, p.y + p.speed);
if (e.key === 'ArrowLeft') p.x = Math.max(0, p.x - p.speed);
if (e.key === 'ArrowRight') p.x = Math.min(770, p.x + p.speed);
if (e.code === 'Space' && p.fireCooldown <= 0) {
const angle = Math.atan2(
gameState.aimAngle.y - p.y -15,
gameState.aimAngle.x - p.x -15
);
gameState.bullets.push({
x: p.x + 15, y: p.y + 15, angle, size: 6
});
p.fireCooldown = p.fireCooldownTime;
}
});
canvas.addEventListener('mousemove', (e) => {
const rect = canvas.getBoundingClientRect();
gameState.aimAngle.x = e.clientX - rect.left;
gameState.aimAngle.y = e.clientY - rect.top;
});
initGame();
gameLoop();
</script>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<title>Advanced Tank War with Ally</title>
<style>
canvas { border: 1px solid black; }
#info { position: absolute; left: 620px; top: 10px; width: 200px; }
</style>
</head>
<body>
<canvas id="gameCanvas" width="800" height="600"></canvas>
<div id="info"></div>
<script>
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
const INFO_HTML = `
<h3>操作说明</h3>
方向键:移动<br>
空格:射击(冷却时间)<br>
鼠标:瞄准<br>
<h3>单位类型</h3>
绿色:玩家坦克<br>
蓝色:友方AI坦克<br>
浅红:普通敌人<br>
深红:重型敌人<br>
最红:精英敌人(会拦截射击)`;
let gameState = {
player: {
x: 400, y: 300, size: 30, color: '#0f0',
speed: 5, hp: 10, angle: 0,
fireCooldown: 0, fireCooldownTime: 20
},
ally: {
x: 200, y: 200, size: 30, color: '#00f',
speed: 4, hp: 3, angle: 0,
fireCooldown: 0, fireCooldownTime: 10,
target: null, state: 'patrol', patrolTimer: 0
},
enemies: [],
bullets: [],
level: 1,
aimAngle: {x: 400, y: 300},
gameOver: false,
totalEnemies: 0,
escapedEnemies: 0
};
function initGame() {
alert(INFO_HTML);
generateEnemies();
}
function generateEnemies() {
const count = gameState.level * 3 + 2;
gameState.totalEnemies = count;
gameState.escapedEnemies = 0;
for (let i = 0; i < count; i++) {
const red = 150 + Math.random() * 105;
const type = red > 240 ? 'elite' : red > 180 ? 'heavy' : 'normal';
gameState.enemies.push({
x: -50,
y: Math.random() * 550 + 25,
size: 30,
color: `rgb(${red},0,0)`,
speed: type === 'elite' ? 1.5 : 3 - (red-150)/50,
hp: Math.ceil((red-150)/35),
angle: 0,
targetAngle: 0,
type: type,
fireCooldown: 0
});
}
}
function checkCollision(rect1, rect2) {
return rect1.x < rect2.x + rect2.size &&
rect1.x + rect1.size > rect2.x &&
rect1.y < rect2.y + rect2.size &&
rect1.y + rect1.size > rect2.y;
}
function gameLoop() {
if (gameState.gameOver) return;
ctx.clearRect(0, 0, canvas.width, canvas.height);
updateGame();
drawPlayer();
drawAlly();
drawEnemies();
drawBullets();
drawAim();
drawUI();
requestAnimationFrame(gameLoop);
}
function updateGame() {
// 更新友方AI
updateAlly();
// 更新敌人状态
for (let i = gameState.enemies.length - 1; i >= 0; i--) {
const enemy = gameState.enemies[i];
// 精英坦克逻辑
if (enemy.type === 'elite') {
const targetX = gameState.player.x + 300;
const targetY = gameState.player.y;
if (enemy.x < targetX - 50) {
enemy.x += enemy.speed * 1.2;
} else {
// 瞄准射击
const dx = gameState.player.x - enemy.x;
const dy = gameState.player.y - enemy.y;
enemy.targetAngle = Math.atan2(dy, dx);
if (enemy.fireCooldown <= 0) {
gameState.bullets.push({
x: enemy.x + 15,
y: enemy.y + 15,
angle: enemy.targetAngle,
size: 6,
isEnemy: true
});
enemy.fireCooldown = 80;
} else {
enemy.fireCooldown--;
}
}
} else {
enemy.x += enemy.speed;
}
// 逃逸检测
if (enemy.x > 800) {
gameState.escapedEnemies++;
gameState.enemies.splice(i, 1);
}
}
// 更新子弹
for (let i = gameState.bullets.length - 1; i >= 0; i--) {
const bullet = gameState.bullets[i];
bullet.x += Math.cos(bullet.angle) * 10;
bullet.y += Math.sin(bullet.angle) * 10;
// 边界检测
if (bullet.x < 0 || bullet.x > 800 || bullet.y < 0 || bullet.y > 600) {
gameState.bullets.splice(i, 1);
continue;
}
// 碰撞检测
if (bullet.isEnemy) {
if (checkCollision(bullet, gameState.player)) {
gameState.player.hp--;
gameState.bullets.splice(i, 1);
if (gameState.player.hp <= 0) gameOver(false);
} else if (checkCollision(bullet, gameState.ally)) {
gameState.ally.hp--;
gameState.bullets.splice(i, 1);
if (gameState.ally.hp <= 0) {
alert("友军坦克被摧毁!");
gameState.ally.hp = 3; // 友军重生
}
}
} else {
for (let j = gameState.enemies.length - 1; j >= 0; j--) {
if (checkCollision(bullet, gameState.enemies[j])) {
gameState.enemies[j].hp--;
if (gameState.enemies[j].hp <= 0) {
gameState.enemies.splice(j, 1);
}
gameState.bullets.splice(i, 1);
break;
}
}
}
}
// 关卡状态检测
if (gameState.escapedEnemies > gameState.totalEnemies * 0.5) {
alert(`超过50%敌人逃脱!关卡${gameState.level}失败!`);
generateEnemies();
return;
}
if (gameState.enemies.length === 0) {
gameState.level++;
if (gameState.level > 3) {
gameOver(true);
return;
}
generateEnemies();
}
// 更新玩家冷却
if (gameState.player.fireCooldown > 0) {
gameState.player.fireCooldown--;
}
}
function updateAlly() {
const ally = gameState.ally;
// 优先寻找重型或精英坦克
if (!ally.target || ally.target.hp <= 0 || ally.patrolTimer > 90) {
ally.target = findPriorityTarget();
ally.patrolTimer = 0;
}
if (ally.target) {
// 攻击模式
const dx = ally.target.x - ally.x;
const dy = ally.target.y - ally.y;
const dist = Math.sqrt(dx*dx + dy*dy);
// 动态移动策略
if (dist > 250) {
// 快速接近目标
ally.x += (dx/dist) * ally.speed * 1.2;
ally.y += (dy/dist) * ally.speed * 1.2;
} else if (dist < 150) {
// 保持安全距离
ally.x -= (dx/dist) * ally.speed * 0.8;
ally.y -= (dy/dist) * ally.speed * 0.8;
} else {
// 侧向移动避免直线冲锋
const sideMove = Math.sin(Date.now()/500) * 50;
ally.x += (dy/dist) * sideMove * 0.1;
ally.y -= (dx/dist) * sideMove * 0.1;
}
// 瞄准射击
ally.angle = Math.atan2(dy, dx);
if (ally.fireCooldown <= 0 && dist < 300) {
gameState.bullets.push({
x: ally.x + 15,
y: ally.y + 15,
angle: ally.angle,
size: 6,
isEnemy: false
});
ally.fireCooldown = ally.fireCooldownTime;
}
} else {
// 没有目标时的巡逻行为
ally.patrolTimer++;
if (ally.patrolTimer > 120) {
ally.x += (Math.random() - 0.5) * 50;
ally.y += (Math.random() - 0.5) * 50;
ally.patrolTimer = 0;
}
// 向玩家靠拢但保持一定距离
const px = gameState.player.x - ally.x;
const py = gameState.player.y - ally.y;
const pDist = Math.sqrt(px*px + py*py);
if (pDist > 200) {
ally.x += (px/pDist) * ally.speed * 0.5;
ally.y += (py/pDist) * ally.speed * 0.5;
}
}
// 边界检查
ally.x = Math.max(0, Math.min(770, ally.x));
ally.y = Math.max(0, Math.min(570, ally.y));
// 冷却更新
if (ally.fireCooldown > 0) {
ally.fireCooldown--;
}
}
// 寻找优先目标(重型/精英坦克)
function findPriorityTarget() {
let priorityTarget = null;
let minDist = Infinity;
gameState.enemies.forEach(enemy => {
// 优先选择重型或精英坦克
if (enemy.type === 'heavy' || enemy.type === 'elite') {
const dist = Math.sqrt(
Math.pow(enemy.x - gameState.ally.x, 2) +
Math.pow(enemy.y - gameState.ally.y, 2)
);
if (dist < minDist) {
minDist = dist;
priorityTarget = enemy;
}
}
});
// 如果没有优先目标,选择最近的普通坦克
if (!priorityTarget && gameState.enemies.length > 0) {
gameState.enemies.forEach(enemy => {
const dist = Math.sqrt(
Math.pow(enemy.x - gameState.ally.x, 2) +
Math.pow(enemy.y - gameState.ally.y, 2)
);
if (dist < minDist) {
minDist = dist;
priorityTarget = enemy;
}
});
}
return priorityTarget;
}
function gameOver(isWin) {
gameState.gameOver = true;
alert(isWin ? "最终胜利!" : "游戏失败!");
location.reload();
}
function drawPlayer() {
drawTank(gameState.player);
}
function drawAlly() {
drawTank(gameState.ally);
// 绘制友军状态指示器
ctx.fillStyle = gameState.ally.state === 'attack' ? '#f00' : '#0a0';
ctx.beginPath();
ctx.arc(gameState.ally.x + 15, gameState.ally.y - 10, 5, 0, Math.PI*2);
ctx.fill();
}
function drawEnemies() {
gameState.enemies.forEach(enemy => {
drawTank(enemy);
if (enemy.type === 'elite') {
ctx.beginPath();
ctx.arc(enemy.x+15, enemy.y+15, 40, 0, Math.PI*2);
ctx.strokeStyle = 'rgba(255,0,0,0.3)';
ctx.stroke();
}
});
}
function drawTank(tank) {
ctx.save();
ctx.translate(tank.x + tank.size/2, tank.y + tank.size/2);
ctx.rotate(tank.angle);
ctx.fillStyle = tank.color;
ctx.fillRect(-tank.size/2, -tank.size/2, tank.size, tank.size);
ctx.strokeStyle = '#333';
ctx.lineWidth = 4;
ctx.beginPath();
ctx.moveTo(0, 0);
ctx.lineTo(tank.size/2, 0);
ctx.stroke();
ctx.restore();
}
function drawBullets() {
ctx.fillStyle = '#000';
gameState.bullets.forEach(bullet => {
ctx.beginPath();
ctx.arc(bullet.x, bullet.y, 3, 0, Math.PI*2);
ctx.fill();
});
}
function drawAim() {
ctx.strokeStyle = '#f00';
ctx.beginPath();
ctx.arc(gameState.aimAngle.x, gameState.aimAngle.y, 10, 0, Math.PI*2);
ctx.stroke();
}
function drawUI() {
const cdPercent = (gameState.player.fireCooldown / gameState.player.fireCooldownTime) * 100;
document.getElementById('info').innerHTML = `
关卡:${gameState.level}<br>
玩家HP:${gameState.player.hp}<br>
友军HP:${gameState.ally.hp}<br>
逃脱敌人:{gameState.escapedEnemies}/{gameState.totalEnemies}
<div style="background:#ddd; width:100px; height:10px">
<div style="background:#f00; width:${cdPercent}%; height:10px"></div>
</div>`;
}
document.addEventListener('keydown', (e) => {
const p = gameState.player;
if (e.key === 'ArrowUp') p.y = Math.max(0, p.y - p.speed);
if (e.key === 'ArrowDown') p.y = Math.min(570, p.y + p.speed);
if (e.key === 'ArrowLeft') p.x = Math.max(0, p.x - p.speed);
if (e.key === 'ArrowRight') p.x = Math.min(770, p.x + p.speed);
if (e.code === 'Space' && p.fireCooldown <= 0) {
const angle = Math.atan2(
gameState.aimAngle.y - p.y -15,
gameState.aimAngle.x - p.x -15
);
gameState.bullets.push({
x: p.x + 15, y: p.y + 15, angle, size: 6
});
p.fireCooldown = p.fireCooldownTime;
}
});
canvas.addEventListener('mousemove', (e) => {
const rect = canvas.getBoundingClientRect();
gameState.aimAngle.x = e.clientX - rect.left;
gameState.aimAngle.y = e.clientY - rect.top;
});
initGame();
gameLoop();
</script>
</body>
</html>