迁移证esc
This commit is contained in:
@@ -54,7 +54,10 @@ export class GameEngine {
|
||||
[WEAPONS.PISTOL]: Infinity, // 手枪无限弹药
|
||||
[WEAPONS.MACHINE_GUN]: 100,
|
||||
[WEAPONS.SHOTGUN]: 20,
|
||||
[WEAPONS.GRENADE]: 10
|
||||
[WEAPONS.GRENADE]: 10,
|
||||
[WEAPONS.MOLOTOV]: 5,
|
||||
[WEAPONS.NUT_WALL]: 3,
|
||||
[WEAPONS.AUTO_TURRET]: 2
|
||||
}
|
||||
|
||||
// 手雷蓄力相关
|
||||
@@ -217,8 +220,8 @@ export class GameEngine {
|
||||
const localPlayer = this.players.get(this.localPlayerId)
|
||||
if (localPlayer) {
|
||||
this.scene.updateCamera(localPlayer.x, localPlayer.y)
|
||||
// 手雷瞄准指示器
|
||||
if (this.isChargingGrenade && this.currentWeaponIndex === 3) {
|
||||
// 投掷武器瞄准指示器(手雷/燃烧瓶)
|
||||
if (this.isChargingGrenade && (this.currentWeaponIndex === 3 || this.currentWeaponIndex === 4)) {
|
||||
this.scene.showGrenadeTarget(localPlayer.x, localPlayer.y,
|
||||
this.input.mouse.groundX || 0, this.input.mouse.groundY || 0,
|
||||
this.grenadeChargePercent)
|
||||
@@ -260,11 +263,16 @@ export class GameEngine {
|
||||
// 应用本地预测(客户端预测)
|
||||
this._applyLocalPrediction(inputState)
|
||||
|
||||
// 添加手雷相关数据到输入状态
|
||||
// 添加蓄力武器相关数据到输入状态(手雷/燃烧瓶)
|
||||
inputState.grenadeCharge = this.grenadeChargePercent
|
||||
inputState.grenadeReleased = this.grenadeReleased
|
||||
// 手雷释放前不发火
|
||||
inputState.firing = this.currentWeaponIndex === 3 ? false : inputState.firing
|
||||
// 蓄力武器释放前不发火
|
||||
const weaponList7 = [WEAPONS.PISTOL, WEAPONS.MACHINE_GUN, WEAPONS.SHOTGUN, WEAPONS.GRENADE, WEAPONS.MOLOTOV, WEAPONS.NUT_WALL, WEAPONS.AUTO_TURRET]
|
||||
const currentWeaponId = weaponList7[this.currentWeaponIndex]
|
||||
const currentConfig = WEAPON_CONFIG[currentWeaponId]
|
||||
if (currentConfig && currentConfig.chargeable) {
|
||||
inputState.firing = false
|
||||
}
|
||||
|
||||
// 保存输入以便进行客户端预测校正
|
||||
this.pendingInputs.push(inputState)
|
||||
@@ -287,10 +295,11 @@ export class GameEngine {
|
||||
* 手雷需要长按鼠标蓄力,松开释放
|
||||
*/
|
||||
_handleGrenadeCharge(inputState) {
|
||||
const weaponList = [WEAPONS.PISTOL, WEAPONS.MACHINE_GUN, WEAPONS.SHOTGUN, WEAPONS.GRENADE]
|
||||
const currentWeapon = weaponList[this.currentWeaponIndex]
|
||||
const weaponList7 = [WEAPONS.PISTOL, WEAPONS.MACHINE_GUN, WEAPONS.SHOTGUN, WEAPONS.GRENADE, WEAPONS.MOLOTOV, WEAPONS.NUT_WALL, WEAPONS.AUTO_TURRET]
|
||||
const currentWeapon = weaponList7[this.currentWeaponIndex]
|
||||
const config = WEAPON_CONFIG[currentWeapon]
|
||||
|
||||
if (currentWeapon === WEAPONS.GRENADE && WEAPON_CONFIG[WEAPONS.GRENADE].chargeable) {
|
||||
if (config && config.chargeable) {
|
||||
// 开始蓄力
|
||||
if (inputState.firing && !this.isChargingGrenade) {
|
||||
this.isChargingGrenade = true
|
||||
@@ -298,13 +307,13 @@ export class GameEngine {
|
||||
} else if (inputState.firing && this.isChargingGrenade) {
|
||||
// 蓄力中,计算蓄力百分比
|
||||
const elapsed = Date.now() - this.grenadeChargeStart
|
||||
this.grenadeChargePercent = Math.min(1, elapsed / WEAPON_CONFIG[WEAPONS.GRENADE].maxCharge)
|
||||
this.grenadeChargePercent = Math.min(1, elapsed / config.maxCharge)
|
||||
} else if (!inputState.firing && this.isChargingGrenade) {
|
||||
// 释放手雷
|
||||
// 释放
|
||||
this.grenadeReleased = true
|
||||
this.isChargingGrenade = false
|
||||
const elapsed = Date.now() - this.grenadeChargeStart
|
||||
this.grenadeChargePercent = Math.min(1, elapsed / WEAPON_CONFIG[WEAPONS.GRENADE].maxCharge)
|
||||
this.grenadeChargePercent = Math.min(1, elapsed / config.maxCharge)
|
||||
}
|
||||
} else {
|
||||
this.isChargingGrenade = false
|
||||
@@ -417,9 +426,9 @@ export class GameEngine {
|
||||
// 新增子弹
|
||||
this.bullets.set(bs.id, { ...bs })
|
||||
this.scene.addBullet(bs)
|
||||
// 枪口火焰特效(手雷除外)
|
||||
// 枪口火焰特效(投掷类武器除外)
|
||||
const player = this.players.get(bs.ownerId)
|
||||
if (player && bs.weapon !== WEAPONS.GRENADE) {
|
||||
if (player && bs.weaponIndex !== 3 && bs.weaponIndex !== 4) {
|
||||
this.scene.addMuzzleFlash(player.x, player.y, bs.angle || 0)
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -556,22 +556,30 @@ export class GameScene {
|
||||
*/
|
||||
addBullet(bullet) {
|
||||
const group = new THREE.Group()
|
||||
const isGrenade = bullet.weapon === WEAPONS.GRENADE
|
||||
// weaponIndex: 0=pistol, 1=machinegun, 2=shotgun, 3=grenade, 4=molotov
|
||||
const wIdx = bullet.weaponIndex
|
||||
const isGrenade = wIdx === 3
|
||||
const isMolotov = wIdx === 4
|
||||
const isThrown = isGrenade || isMolotov
|
||||
const z = bullet.z || 0.5
|
||||
|
||||
if (isGrenade) {
|
||||
// 手雷:球体 + 发光 + 拖尾
|
||||
if (isThrown) {
|
||||
// 投掷物:球体 + 发光 + 拖尾
|
||||
const bodyColor = isMolotov ? 0xff6600 : 0x44ff44
|
||||
const glowColor = isMolotov ? 0xff4400 : 0x22cc22
|
||||
const trailColor = isMolotov ? 0xff8844 : 0x88ff88
|
||||
|
||||
const geo = new THREE.SphereGeometry(0.12, 8, 8)
|
||||
const mat = new THREE.MeshBasicMaterial({ color: 0x44ff44 })
|
||||
const mat = new THREE.MeshBasicMaterial({ color: bodyColor })
|
||||
const mesh = new THREE.Mesh(geo, mat)
|
||||
mesh.position.set(bullet.x, z, bullet.y)
|
||||
group.add(mesh)
|
||||
|
||||
const glowGeo = new THREE.SphereGeometry(0.18, 8, 8)
|
||||
const glowMat = new THREE.MeshBasicMaterial({
|
||||
color: 0x22cc22,
|
||||
color: glowColor,
|
||||
transparent: true,
|
||||
opacity: 0.4
|
||||
opacity: 0.5
|
||||
})
|
||||
const glow = new THREE.Mesh(glowGeo, glowMat)
|
||||
glow.position.set(bullet.x, z, bullet.y)
|
||||
@@ -580,7 +588,7 @@ export class GameScene {
|
||||
// 拖尾线
|
||||
const trailGeo = new THREE.BufferGeometry()
|
||||
const trailMat = new THREE.LineBasicMaterial({
|
||||
color: 0x88ff88,
|
||||
color: trailColor,
|
||||
transparent: true,
|
||||
opacity: 0.6
|
||||
})
|
||||
@@ -598,14 +606,8 @@ export class GameScene {
|
||||
const angle = bullet.angle || 0
|
||||
|
||||
// 根据武器类型调整大小
|
||||
switch (bullet.weapon) {
|
||||
case WEAPONS.MACHINE_GUN:
|
||||
bulletSize = 0.05
|
||||
break
|
||||
case WEAPONS.SHOTGUN:
|
||||
bulletSize = 0.04
|
||||
break
|
||||
}
|
||||
if (wIdx === 1) bulletSize = 0.05 // 机枪
|
||||
else if (wIdx === 2) bulletSize = 0.04 // 霰弹枪
|
||||
|
||||
// 拖尾
|
||||
const trailLength = 2.5
|
||||
@@ -651,9 +653,10 @@ export class GameScene {
|
||||
x: bullet.x,
|
||||
y: bullet.y,
|
||||
z: z,
|
||||
weapon: bullet.weapon,
|
||||
weaponIndex: wIdx,
|
||||
angle: bullet.angle || 0,
|
||||
isGrenade
|
||||
isGrenade,
|
||||
isMolotov
|
||||
})
|
||||
}
|
||||
|
||||
@@ -695,7 +698,7 @@ export class GameScene {
|
||||
child.position.z = y
|
||||
}
|
||||
// 更新拖尾位置
|
||||
if (child.isLine && !bullet.isGrenade) {
|
||||
if (child.isLine && !bullet.isGrenade && !bullet.isMolotov) {
|
||||
const trailLength = 2.5
|
||||
const positions = child.geometry.attributes.position.array
|
||||
positions[0] = x - Math.sin(angle) * trailLength
|
||||
@@ -1083,7 +1086,7 @@ export class GameScene {
|
||||
|
||||
// 更新子弹拖尾
|
||||
for (const bullet of this.bullets) {
|
||||
if (!bullet.isGrenade && bullet.trail) {
|
||||
if (!bullet.isGrenade && !bullet.isMolotov && bullet.trail) {
|
||||
const positions = bullet.trail.geometry.attributes.position.array
|
||||
positions[0] = bullet.x - Math.sin(bullet.angle) * 1.5
|
||||
positions[1] = 0.5
|
||||
|
||||
@@ -28,7 +28,7 @@ export class HUD {
|
||||
this.weaponPanel.className = 'hud-weapon-panel'
|
||||
|
||||
// 武器列表
|
||||
const weaponList = [WEAPONS.PISTOL, WEAPONS.MACHINE_GUN, WEAPONS.SHOTGUN, WEAPONS.GRENADE]
|
||||
const weaponList = [WEAPONS.PISTOL, WEAPONS.MACHINE_GUN, WEAPONS.SHOTGUN, WEAPONS.GRENADE, WEAPONS.MOLOTOV, WEAPONS.NUT_WALL, WEAPONS.AUTO_TURRET]
|
||||
this.weaponSlots = []
|
||||
for (let i = 0; i < weaponList.length; i++) {
|
||||
const slot = document.createElement('div')
|
||||
@@ -135,7 +135,7 @@ export class HUD {
|
||||
* @param {Object} ammo 各武器弹药数
|
||||
*/
|
||||
updateWeapons(currentIndex, ammo) {
|
||||
const weaponList = [WEAPONS.PISTOL, WEAPONS.MACHINE_GUN, WEAPONS.SHOTGUN, WEAPONS.GRENADE]
|
||||
const weaponList = [WEAPONS.PISTOL, WEAPONS.MACHINE_GUN, WEAPONS.SHOTGUN, WEAPONS.GRENADE, WEAPONS.MOLOTOV, WEAPONS.NUT_WALL, WEAPONS.AUTO_TURRET]
|
||||
for (let i = 0; i < this.weaponSlots.length; i++) {
|
||||
const slot = this.weaponSlots[i]
|
||||
// 高亮当前武器
|
||||
|
||||
@@ -17,7 +17,10 @@ export class SettingsUI {
|
||||
weapon1: 'Digit1',
|
||||
weapon2: 'Digit2',
|
||||
weapon3: 'Digit3',
|
||||
weapon4: 'Digit4'
|
||||
weapon4: 'Digit4',
|
||||
weapon5: 'Digit5',
|
||||
weapon6: 'Digit6',
|
||||
weapon7: 'Digit7'
|
||||
}
|
||||
this.bindings = { ...this.defaultBindings }
|
||||
}
|
||||
@@ -68,7 +71,10 @@ export class SettingsUI {
|
||||
weapon1: 'Weapon 1 (Pistol)',
|
||||
weapon2: 'Weapon 2 (MG)',
|
||||
weapon3: 'Weapon 3 (Shotgun)',
|
||||
weapon4: 'Weapon 4 (Grenade)'
|
||||
weapon4: 'Weapon 4 (Grenade)',
|
||||
weapon5: 'Weapon 5 (Molotov)',
|
||||
weapon6: 'Weapon 6 (Wall)',
|
||||
weapon7: 'Weapon 7 (Turret)'
|
||||
}
|
||||
|
||||
// 生成每种操作的按键配置行
|
||||
|
||||
@@ -23,7 +23,10 @@ export const WEAPONS = {
|
||||
PISTOL: 'pistol', // 手枪
|
||||
MACHINE_GUN: 'machine_gun', // 机枪
|
||||
SHOTGUN: 'shotgun', // 霰弹枪
|
||||
GRENADE: 'grenade' // 手雷
|
||||
GRENADE: 'grenade', // 手雷
|
||||
MOLOTOV: 'molotov', // 燃烧瓶
|
||||
NUT_WALL: 'nut_wall', // 坚果墙体
|
||||
AUTO_TURRET: 'auto_turret' // 自动机枪塔
|
||||
}
|
||||
|
||||
// ========== 武器配置 ==========
|
||||
@@ -84,7 +87,51 @@ export const WEAPON_CONFIG = {
|
||||
auto: false,
|
||||
chargeable: true, // 可蓄力
|
||||
maxCharge: 2000, // 最大蓄力时间(毫秒)
|
||||
explosionRadius: 3 // 爆炸半径
|
||||
explosionRadius: 3 // 爆炸半径
|
||||
},
|
||||
// 燃烧瓶配置
|
||||
[WEAPONS.MOLOTOV]: {
|
||||
name: 'Molotov',
|
||||
damage: 80,
|
||||
fireRate: 2000,
|
||||
ammo: 5,
|
||||
maxAmmo: 5,
|
||||
speed: 12,
|
||||
spread: 0,
|
||||
pellets: 1,
|
||||
range: 12,
|
||||
auto: false,
|
||||
chargeable: true, // 可蓄力
|
||||
maxCharge: 2000,
|
||||
explosionRadius: 2
|
||||
},
|
||||
// 坚果墙体配置
|
||||
[WEAPONS.NUT_WALL]: {
|
||||
name: 'Wall',
|
||||
damage: 0,
|
||||
fireRate: 1000,
|
||||
ammo: 3,
|
||||
maxAmmo: 3,
|
||||
speed: 0,
|
||||
spread: 0,
|
||||
pellets: 0,
|
||||
range: 0,
|
||||
auto: false,
|
||||
chargeable: false
|
||||
},
|
||||
// 自动机枪塔配置
|
||||
[WEAPONS.AUTO_TURRET]: {
|
||||
name: 'Turret',
|
||||
damage: 0,
|
||||
fireRate: 2000,
|
||||
ammo: 2,
|
||||
maxAmmo: 2,
|
||||
speed: 0,
|
||||
spread: 0,
|
||||
pellets: 0,
|
||||
range: 0,
|
||||
auto: false,
|
||||
chargeable: false
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,7 +18,10 @@ export class InputManager {
|
||||
weapon1: 'Digit1',
|
||||
weapon2: 'Digit2',
|
||||
weapon3: 'Digit3',
|
||||
weapon4: 'Digit4'
|
||||
weapon4: 'Digit4',
|
||||
weapon5: 'Digit5',
|
||||
weapon6: 'Digit6',
|
||||
weapon7: 'Digit7'
|
||||
}
|
||||
|
||||
// 待处理的输入序列(用于客户端预测)
|
||||
@@ -100,13 +103,16 @@ export class InputManager {
|
||||
|
||||
/**
|
||||
* 获取当前选择的武器
|
||||
* @returns {number} 武器索引(0-3),无选择返回-1
|
||||
* @returns {number} 武器索引(0-6),无选择返回-1
|
||||
*/
|
||||
getSelectedWeapon() {
|
||||
if (this.keys[this.keyBindings.weapon1]) return 0
|
||||
if (this.keys[this.keyBindings.weapon2]) return 1
|
||||
if (this.keys[this.keyBindings.weapon3]) return 2
|
||||
if (this.keys[this.keyBindings.weapon4]) return 3
|
||||
if (this.keys[this.keyBindings.weapon5]) return 4
|
||||
if (this.keys[this.keyBindings.weapon6]) return 5
|
||||
if (this.keys[this.keyBindings.weapon7]) return 6
|
||||
return -1
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user