坦克大战HTML网页游戏 (永久免费)

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>

相关推荐
—Qeyser5 小时前
用 Deepseek 写的uniapp血型遗传查询工具
前端·javascript·ai·chatgpt·uni-app·deepseek
喜樂的CC7 小时前
[react]Next.js之自适应布局和高清屏幕适配解决方案
javascript·react.js·postcss
天天扭码7 小时前
零基础 | 入门前端必备技巧——使用 DOM 操作插入 HTML 元素
前端·javascript·dom
烛阴8 小时前
手把手教你搭建 Express 日志系统,告别线上事故!
javascript·后端·express
拉不动的猪8 小时前
设计模式之------策略模式
前端·javascript·面试
旭久8 小时前
react+Tesseract.js实现前端拍照获取/选择文件等文字识别OCR
前端·javascript·react.js
uhakadotcom8 小时前
Google Earth Engine 机器学习入门:基础知识与实用示例详解
前端·javascript·面试
麓殇⊙8 小时前
Vue--组件练习案例
前端·javascript·vue.js
outstanding木槿9 小时前
React中 点击事件写法 的注意(this、箭头函数)
前端·javascript·react.js
会点php的前端小渣渣9 小时前
vue的计算属性computed的原理和监听属性watch的原理(新)
前端·javascript·vue.js