修复一部分bug

This commit is contained in:
2025-09-25 22:21:26 +08:00
parent 7153ac9b97
commit 072b074b28
7 changed files with 94 additions and 22 deletions

View File

@@ -116,13 +116,13 @@ public class SimpleFighter {
if (!isAttacking) {
if (keycode == Input.Keys.Z || keycode == Input.Keys.J) {
attack("light");
NetworkManager.getInstance().sendAttack("light");
NetworkManager.getInstance().sendAttack("light", getFacingDir());
} else if (keycode == Input.Keys.X || keycode == Input.Keys.K) {
attack("heavy");
NetworkManager.getInstance().sendAttack("heavy");
NetworkManager.getInstance().sendAttack("heavy", getFacingDir());
} else if (keycode == Input.Keys.SHIFT_LEFT || keycode == Input.Keys.SHIFT_RIGHT) {
attack("special");
NetworkManager.getInstance().sendAttack("special");
NetworkManager.getInstance().sendAttack("special", getFacingDir());
}
}
} else {
@@ -172,6 +172,14 @@ public class SimpleFighter {
return isFacingRight;
}
public void setFacingRight(boolean facingRight) {
this.isFacingRight = facingRight;
}
public String getFacingDir() {
return isFacingRight ? "R" : "L";
}
private void updateAttackbox(String attackType) {
float offsetX, offsetY = 20, width = 80, height = 80;
switch (attackType) {
@@ -209,14 +217,21 @@ public class SimpleFighter {
}
public void takeHit(int damage) {
takeHit(damage, 0);
}
public void takeHit(int damage, int dirSign) {
if (invulnerableTimer > 0 || health <= 0)
return; // 无敌或已死亡
health = Math.max(0, health - damage);
changeAction(health > 0 ? Action.HIT : Action.DEAD);
// 设置无敌 & 击退
invulnerableTimer = INVULNERABLE_DURATION;
// 击退方向与幅度
knockbackX = isFacingRight ? -600f : 600f;
// dirSign: -1 表示从右向左击中(目标向左被推), 1 表示从左向右击中(目标向右被推)
if (dirSign == 0) { // 没有提供方向则沿用基于自身面向的旧逻辑
knockbackX = isFacingRight ? -600f : 600f;
} else {
knockbackX = dirSign * 600f;
}
knockbackTimer = KNOCKBACK_DURATION;
}
@@ -292,4 +307,16 @@ public class SimpleFighter {
public float getAttackTimer() {
return attackTimer;
}
// 重生时重置状态
public void resetForRespawn() {
health = 100;
isAttacking = false;
attackTimer = 0f;
attackJustStarted = false;
changeAction(Action.IDLE);
invulnerableTimer = 0f;
knockbackTimer = 0f;
knockbackX = 0f;
}
}

View File

@@ -91,13 +91,17 @@ public class GameScreen extends ScreenAdapter {
}
// 处理远程攻击同步:触发远程角色的攻击动画
Map<String, String> attacks = NetworkManager.getInstance().getPlayerAttacks();
Map<String, String> dirs = NetworkManager.getInstance().getPlayerAttackDirs();
for (Map.Entry<String, String> atk : attacks.entrySet()) {
SimpleFighter remoteAtk = otherPlayers.get(atk.getKey());
if (remoteAtk != null) {
String dir = dirs.getOrDefault(atk.getKey(), "R");
remoteAtk.setFacingRight("R".equals(dir));
remoteAtk.attack(atk.getValue());
}
}
attacks.clear();
dirs.clear();
}
// 主机执行碰撞检测并广播伤害
if (NetworkManager.getInstance().isHost()) {
@@ -109,7 +113,9 @@ public class GameScreen extends ScreenAdapter {
&& player.getAttackbox().overlaps(target.getHitbox())) {
// 使用攻击类型伤害
int dmg = player.getDamageForAttack(player.getLastAttackType());
NetworkManager.getInstance().sendDamage(e.getKey(), dmg);
// 方向:本地玩家在左侧击中右侧 -> dirSign = 1 (目标被推向右);我们定义 dirSign = 攻击者面向 ? 1 : -1
int dirSign = player.isFacingRight() ? 1 : -1;
NetworkManager.getInstance().sendDamage(e.getKey(), dmg, dirSign);
player.markDamageApplied();
}
}
@@ -120,7 +126,9 @@ public class GameScreen extends ScreenAdapter {
if (attacker.isAttacking() && attacker.canDealDamage() && player.isAlive()
&& attacker.getAttackbox().overlaps(player.getHitbox())) {
int dmg = attacker.getDamageForAttack(attacker.getLastAttackType());
NetworkManager.getInstance().sendDamage(NetworkManager.getInstance().getLocalPlayerId(), dmg);
int dirSign = attacker.isFacingRight() ? 1 : -1;
NetworkManager.getInstance().sendDamage(NetworkManager.getInstance().getLocalPlayerId(), dmg,
dirSign);
attacker.markDamageApplied();
}
}
@@ -150,20 +158,23 @@ public class GameScreen extends ScreenAdapter {
}
// 应用收到的伤害事件
Map<String, Integer> damageEvents = NetworkManager.getInstance().getDamageEvents();
Map<String, Integer> damageDirs = NetworkManager.getInstance().getDamageDirs();
if (!damageEvents.isEmpty()) {
for (Map.Entry<String, Integer> dmg : damageEvents.entrySet()) {
String targetId = dmg.getKey();
int amount = dmg.getValue();
int dirSign = damageDirs.getOrDefault(targetId, 0);
if (targetId.equals(NetworkManager.getInstance().getLocalPlayerId())) {
player.takeHit(amount);
player.takeHit(amount, dirSign);
} else {
SimpleFighter remote = otherPlayers.get(targetId);
if (remote != null) {
remote.takeHit(amount);
remote.takeHit(amount, dirSign);
}
}
}
damageEvents.clear();
damageDirs.clear();
}
// 处理重生事件
Map<String, float[]> respawns = NetworkManager.getInstance().getRespawnEvents();
@@ -173,13 +184,12 @@ public class GameScreen extends ScreenAdapter {
float[] p = r.getValue();
if (pid.equals(NetworkManager.getInstance().getLocalPlayerId())) {
player.setPosition(p[0], p[1]);
// 简单复活:重置血量字段(需访问)
// 由于 health 私有且无 setter可在 SimpleFighter 新增 resetForRespawn 方法(后续可优化)
// 临时通过反射或改造:这里暂时忽略直接血量恢复(若需要我可再补)
player.resetForRespawn();
} else {
SimpleFighter remote = otherPlayers.get(pid);
if (remote != null) {
remote.setPosition(p[0], p[1]);
remote.resetForRespawn();
}
}
}

View File

@@ -16,8 +16,12 @@ public class NetworkManager {
private final Map<String, String> playerCharacters = new HashMap<>();
// 存储远程玩家的攻击类型attackType
private final Map<String, String> playerAttacks = new HashMap<>();
// 攻击方向playerId -> "R" 或 "L"
private final Map<String, String> playerAttackDirs = new HashMap<>();
// 伤害事件targetId -> 累积伤害(本帧内可能多次)
private final Map<String, Integer> damageEvents = new HashMap<>();
// 伤害方向targetId -> dirSign (-1 / 0 / 1)
private final Map<String, Integer> damageDirs = new HashMap<>();
private final Map<String, float[]> respawnEvents = new HashMap<>();
public static NetworkManager getInstance() {
@@ -99,11 +103,14 @@ public class NetworkManager {
Gdx.app.log("Network", "收到准备信号");
} else if (message.startsWith("ATTACK:")) {
String[] parts = message.substring(7).split(",");
if (parts.length == 2) {
// ATTACK:playerId,attackType,dir
if (parts.length >= 2) {
String playerId = parts[0];
String attackType = parts[1];
String dir = parts.length >= 3 ? parts[2] : "R"; // 兼容旧版本无方向
playerAttacks.put(playerId, attackType);
Gdx.app.log("Network", "攻击同步: " + playerId + " -> " + attackType);
playerAttackDirs.put(playerId, dir);
Gdx.app.log("Network", "攻击同步: " + playerId + " -> " + attackType + " dir=" + dir);
} else {
Gdx.app.error("Network", "攻击消息格式错误: " + message);
}
@@ -115,9 +122,15 @@ public class NetworkManager {
try {
int amount = Integer.parseInt(parts[1]);
damageEvents.merge(targetId, amount, Integer::sum);
// 第三个参数方向目前不存储,只为击退逻辑可扩展
Gdx.app.log("Network",
"收到伤害: " + targetId + " -" + amount + (parts.length >= 3 ? (" dir=" + parts[2]) : ""));
int dir = 0;
if (parts.length >= 3) {
try {
dir = Integer.parseInt(parts[2]);
} catch (NumberFormatException ignore) {
}
damageDirs.put(targetId, dir);
}
Gdx.app.log("Network", "收到伤害: " + targetId + " -" + amount + (dir != 0 ? (" dir=" + dir) : ""));
} catch (NumberFormatException e) {
Gdx.app.error("Network", "伤害数值解析失败: " + message);
}
@@ -156,13 +169,17 @@ public class NetworkManager {
return playerAttacks;
}
public Map<String, String> getPlayerAttackDirs() {
return playerAttackDirs;
}
/**
* 发送攻击消息给其他玩家
*/
public void sendAttack(String attackType) {
public void sendAttack(String attackType, String dir) {
if (localPlayerId == null)
return;
String msg = "ATTACK:" + localPlayerId + "," + attackType;
String msg = "ATTACK:" + localPlayerId + "," + attackType + "," + dir; // 新格式包含方向
Gdx.app.log("Network", "发送攻击消息: " + msg);
if (isHost && server != null) {
server.broadcastToOthers(null, msg);
@@ -172,6 +189,11 @@ public class NetworkManager {
}
}
// 兼容旧代码(若仍有地方调用)默认使用 R
public void sendAttack(String attackType) {
sendAttack(attackType, "R");
}
public Map<String, String> getPlayerCharacters() {
return playerCharacters;
}
@@ -180,8 +202,12 @@ public class NetworkManager {
return damageEvents;
}
public void sendDamage(String targetId, int amount) {
String msg = "DAMAGE:" + targetId + "," + amount; // 不含方向
public Map<String, Integer> getDamageDirs() {
return damageDirs;
}
public void sendDamage(String targetId, int amount, int dirSign) {
String msg = "DAMAGE:" + targetId + "," + amount + "," + dirSign; // 含方向
if (isHost && server != null) {
server.broadcastToOthers(null, msg);
receiveMessage(msg); // 本地也应用
@@ -190,6 +216,11 @@ public class NetworkManager {
}
}
// 兼容旧调用不带方向使用0表示沿用被击者朝向逻辑
public void sendDamage(String targetId, int amount) {
sendDamage(targetId, amount, 0);
}
public void sendRespawn(String playerId, float x, float y) {
String msg = "RESPAWN:" + playerId + "," + x + "," + y;
if (isHost && server != null) {
@@ -221,6 +252,10 @@ public class NetworkManager {
}
playerPositions.clear();
playerCharacters.clear();
playerAttacks.clear();
playerAttackDirs.clear();
damageEvents.clear();
damageDirs.clear();
Gdx.app.log("Network", "已断开连接");
}
}

Binary file not shown.