修复一部分bug
This commit is contained in:
@@ -116,13 +116,13 @@ public class SimpleFighter {
|
|||||||
if (!isAttacking) {
|
if (!isAttacking) {
|
||||||
if (keycode == Input.Keys.Z || keycode == Input.Keys.J) {
|
if (keycode == Input.Keys.Z || keycode == Input.Keys.J) {
|
||||||
attack("light");
|
attack("light");
|
||||||
NetworkManager.getInstance().sendAttack("light");
|
NetworkManager.getInstance().sendAttack("light", getFacingDir());
|
||||||
} else if (keycode == Input.Keys.X || keycode == Input.Keys.K) {
|
} else if (keycode == Input.Keys.X || keycode == Input.Keys.K) {
|
||||||
attack("heavy");
|
attack("heavy");
|
||||||
NetworkManager.getInstance().sendAttack("heavy");
|
NetworkManager.getInstance().sendAttack("heavy", getFacingDir());
|
||||||
} else if (keycode == Input.Keys.SHIFT_LEFT || keycode == Input.Keys.SHIFT_RIGHT) {
|
} else if (keycode == Input.Keys.SHIFT_LEFT || keycode == Input.Keys.SHIFT_RIGHT) {
|
||||||
attack("special");
|
attack("special");
|
||||||
NetworkManager.getInstance().sendAttack("special");
|
NetworkManager.getInstance().sendAttack("special", getFacingDir());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -172,6 +172,14 @@ public class SimpleFighter {
|
|||||||
return isFacingRight;
|
return isFacingRight;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setFacingRight(boolean facingRight) {
|
||||||
|
this.isFacingRight = facingRight;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFacingDir() {
|
||||||
|
return isFacingRight ? "R" : "L";
|
||||||
|
}
|
||||||
|
|
||||||
private void updateAttackbox(String attackType) {
|
private void updateAttackbox(String attackType) {
|
||||||
float offsetX, offsetY = 20, width = 80, height = 80;
|
float offsetX, offsetY = 20, width = 80, height = 80;
|
||||||
switch (attackType) {
|
switch (attackType) {
|
||||||
@@ -209,14 +217,21 @@ public class SimpleFighter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void takeHit(int damage) {
|
public void takeHit(int damage) {
|
||||||
|
takeHit(damage, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void takeHit(int damage, int dirSign) {
|
||||||
if (invulnerableTimer > 0 || health <= 0)
|
if (invulnerableTimer > 0 || health <= 0)
|
||||||
return; // 无敌或已死亡
|
return; // 无敌或已死亡
|
||||||
health = Math.max(0, health - damage);
|
health = Math.max(0, health - damage);
|
||||||
changeAction(health > 0 ? Action.HIT : Action.DEAD);
|
changeAction(health > 0 ? Action.HIT : Action.DEAD);
|
||||||
// 设置无敌 & 击退
|
|
||||||
invulnerableTimer = INVULNERABLE_DURATION;
|
invulnerableTimer = INVULNERABLE_DURATION;
|
||||||
// 击退方向与幅度
|
// dirSign: -1 表示从右向左击中(目标向左被推), 1 表示从左向右击中(目标向右被推)
|
||||||
knockbackX = isFacingRight ? -600f : 600f;
|
if (dirSign == 0) { // 没有提供方向则沿用基于自身面向的旧逻辑
|
||||||
|
knockbackX = isFacingRight ? -600f : 600f;
|
||||||
|
} else {
|
||||||
|
knockbackX = dirSign * 600f;
|
||||||
|
}
|
||||||
knockbackTimer = KNOCKBACK_DURATION;
|
knockbackTimer = KNOCKBACK_DURATION;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -292,4 +307,16 @@ public class SimpleFighter {
|
|||||||
public float getAttackTimer() {
|
public float getAttackTimer() {
|
||||||
return attackTimer;
|
return attackTimer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 重生时重置状态
|
||||||
|
public void resetForRespawn() {
|
||||||
|
health = 100;
|
||||||
|
isAttacking = false;
|
||||||
|
attackTimer = 0f;
|
||||||
|
attackJustStarted = false;
|
||||||
|
changeAction(Action.IDLE);
|
||||||
|
invulnerableTimer = 0f;
|
||||||
|
knockbackTimer = 0f;
|
||||||
|
knockbackX = 0f;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -91,13 +91,17 @@ public class GameScreen extends ScreenAdapter {
|
|||||||
}
|
}
|
||||||
// 处理远程攻击同步:触发远程角色的攻击动画
|
// 处理远程攻击同步:触发远程角色的攻击动画
|
||||||
Map<String, String> attacks = NetworkManager.getInstance().getPlayerAttacks();
|
Map<String, String> attacks = NetworkManager.getInstance().getPlayerAttacks();
|
||||||
|
Map<String, String> dirs = NetworkManager.getInstance().getPlayerAttackDirs();
|
||||||
for (Map.Entry<String, String> atk : attacks.entrySet()) {
|
for (Map.Entry<String, String> atk : attacks.entrySet()) {
|
||||||
SimpleFighter remoteAtk = otherPlayers.get(atk.getKey());
|
SimpleFighter remoteAtk = otherPlayers.get(atk.getKey());
|
||||||
if (remoteAtk != null) {
|
if (remoteAtk != null) {
|
||||||
|
String dir = dirs.getOrDefault(atk.getKey(), "R");
|
||||||
|
remoteAtk.setFacingRight("R".equals(dir));
|
||||||
remoteAtk.attack(atk.getValue());
|
remoteAtk.attack(atk.getValue());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
attacks.clear();
|
attacks.clear();
|
||||||
|
dirs.clear();
|
||||||
}
|
}
|
||||||
// 主机执行碰撞检测并广播伤害
|
// 主机执行碰撞检测并广播伤害
|
||||||
if (NetworkManager.getInstance().isHost()) {
|
if (NetworkManager.getInstance().isHost()) {
|
||||||
@@ -109,7 +113,9 @@ public class GameScreen extends ScreenAdapter {
|
|||||||
&& player.getAttackbox().overlaps(target.getHitbox())) {
|
&& player.getAttackbox().overlaps(target.getHitbox())) {
|
||||||
// 使用攻击类型伤害
|
// 使用攻击类型伤害
|
||||||
int dmg = player.getDamageForAttack(player.getLastAttackType());
|
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();
|
player.markDamageApplied();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -120,7 +126,9 @@ public class GameScreen extends ScreenAdapter {
|
|||||||
if (attacker.isAttacking() && attacker.canDealDamage() && player.isAlive()
|
if (attacker.isAttacking() && attacker.canDealDamage() && player.isAlive()
|
||||||
&& attacker.getAttackbox().overlaps(player.getHitbox())) {
|
&& attacker.getAttackbox().overlaps(player.getHitbox())) {
|
||||||
int dmg = attacker.getDamageForAttack(attacker.getLastAttackType());
|
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();
|
attacker.markDamageApplied();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -150,20 +158,23 @@ public class GameScreen extends ScreenAdapter {
|
|||||||
}
|
}
|
||||||
// 应用收到的伤害事件
|
// 应用收到的伤害事件
|
||||||
Map<String, Integer> damageEvents = NetworkManager.getInstance().getDamageEvents();
|
Map<String, Integer> damageEvents = NetworkManager.getInstance().getDamageEvents();
|
||||||
|
Map<String, Integer> damageDirs = NetworkManager.getInstance().getDamageDirs();
|
||||||
if (!damageEvents.isEmpty()) {
|
if (!damageEvents.isEmpty()) {
|
||||||
for (Map.Entry<String, Integer> dmg : damageEvents.entrySet()) {
|
for (Map.Entry<String, Integer> dmg : damageEvents.entrySet()) {
|
||||||
String targetId = dmg.getKey();
|
String targetId = dmg.getKey();
|
||||||
int amount = dmg.getValue();
|
int amount = dmg.getValue();
|
||||||
|
int dirSign = damageDirs.getOrDefault(targetId, 0);
|
||||||
if (targetId.equals(NetworkManager.getInstance().getLocalPlayerId())) {
|
if (targetId.equals(NetworkManager.getInstance().getLocalPlayerId())) {
|
||||||
player.takeHit(amount);
|
player.takeHit(amount, dirSign);
|
||||||
} else {
|
} else {
|
||||||
SimpleFighter remote = otherPlayers.get(targetId);
|
SimpleFighter remote = otherPlayers.get(targetId);
|
||||||
if (remote != null) {
|
if (remote != null) {
|
||||||
remote.takeHit(amount);
|
remote.takeHit(amount, dirSign);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
damageEvents.clear();
|
damageEvents.clear();
|
||||||
|
damageDirs.clear();
|
||||||
}
|
}
|
||||||
// 处理重生事件
|
// 处理重生事件
|
||||||
Map<String, float[]> respawns = NetworkManager.getInstance().getRespawnEvents();
|
Map<String, float[]> respawns = NetworkManager.getInstance().getRespawnEvents();
|
||||||
@@ -173,13 +184,12 @@ public class GameScreen extends ScreenAdapter {
|
|||||||
float[] p = r.getValue();
|
float[] p = r.getValue();
|
||||||
if (pid.equals(NetworkManager.getInstance().getLocalPlayerId())) {
|
if (pid.equals(NetworkManager.getInstance().getLocalPlayerId())) {
|
||||||
player.setPosition(p[0], p[1]);
|
player.setPosition(p[0], p[1]);
|
||||||
// 简单复活:重置血量字段(需访问)
|
player.resetForRespawn();
|
||||||
// 由于 health 私有且无 setter,可在 SimpleFighter 新增 resetForRespawn 方法(后续可优化)
|
|
||||||
// 临时通过反射或改造:这里暂时忽略直接血量恢复(若需要我可再补)
|
|
||||||
} else {
|
} else {
|
||||||
SimpleFighter remote = otherPlayers.get(pid);
|
SimpleFighter remote = otherPlayers.get(pid);
|
||||||
if (remote != null) {
|
if (remote != null) {
|
||||||
remote.setPosition(p[0], p[1]);
|
remote.setPosition(p[0], p[1]);
|
||||||
|
remote.resetForRespawn();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,8 +16,12 @@ public class NetworkManager {
|
|||||||
private final Map<String, String> playerCharacters = new HashMap<>();
|
private final Map<String, String> playerCharacters = new HashMap<>();
|
||||||
// 存储远程玩家的攻击类型(attackType)
|
// 存储远程玩家的攻击类型(attackType)
|
||||||
private final Map<String, String> playerAttacks = new HashMap<>();
|
private final Map<String, String> playerAttacks = new HashMap<>();
|
||||||
|
// 攻击方向:playerId -> "R" 或 "L"
|
||||||
|
private final Map<String, String> playerAttackDirs = new HashMap<>();
|
||||||
// 伤害事件:targetId -> 累积伤害(本帧内可能多次)
|
// 伤害事件:targetId -> 累积伤害(本帧内可能多次)
|
||||||
private final Map<String, Integer> damageEvents = new HashMap<>();
|
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<>();
|
private final Map<String, float[]> respawnEvents = new HashMap<>();
|
||||||
|
|
||||||
public static NetworkManager getInstance() {
|
public static NetworkManager getInstance() {
|
||||||
@@ -99,11 +103,14 @@ public class NetworkManager {
|
|||||||
Gdx.app.log("Network", "收到准备信号");
|
Gdx.app.log("Network", "收到准备信号");
|
||||||
} else if (message.startsWith("ATTACK:")) {
|
} else if (message.startsWith("ATTACK:")) {
|
||||||
String[] parts = message.substring(7).split(",");
|
String[] parts = message.substring(7).split(",");
|
||||||
if (parts.length == 2) {
|
// ATTACK:playerId,attackType,dir
|
||||||
|
if (parts.length >= 2) {
|
||||||
String playerId = parts[0];
|
String playerId = parts[0];
|
||||||
String attackType = parts[1];
|
String attackType = parts[1];
|
||||||
|
String dir = parts.length >= 3 ? parts[2] : "R"; // 兼容旧版本无方向
|
||||||
playerAttacks.put(playerId, attackType);
|
playerAttacks.put(playerId, attackType);
|
||||||
Gdx.app.log("Network", "攻击同步: " + playerId + " -> " + attackType);
|
playerAttackDirs.put(playerId, dir);
|
||||||
|
Gdx.app.log("Network", "攻击同步: " + playerId + " -> " + attackType + " dir=" + dir);
|
||||||
} else {
|
} else {
|
||||||
Gdx.app.error("Network", "攻击消息格式错误: " + message);
|
Gdx.app.error("Network", "攻击消息格式错误: " + message);
|
||||||
}
|
}
|
||||||
@@ -115,9 +122,15 @@ public class NetworkManager {
|
|||||||
try {
|
try {
|
||||||
int amount = Integer.parseInt(parts[1]);
|
int amount = Integer.parseInt(parts[1]);
|
||||||
damageEvents.merge(targetId, amount, Integer::sum);
|
damageEvents.merge(targetId, amount, Integer::sum);
|
||||||
// 第三个参数方向目前不存储,只为击退逻辑可扩展
|
int dir = 0;
|
||||||
Gdx.app.log("Network",
|
if (parts.length >= 3) {
|
||||||
"收到伤害: " + targetId + " -" + amount + (parts.length >= 3 ? (" dir=" + parts[2]) : ""));
|
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) {
|
} catch (NumberFormatException e) {
|
||||||
Gdx.app.error("Network", "伤害数值解析失败: " + message);
|
Gdx.app.error("Network", "伤害数值解析失败: " + message);
|
||||||
}
|
}
|
||||||
@@ -156,13 +169,17 @@ public class NetworkManager {
|
|||||||
return playerAttacks;
|
return playerAttacks;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Map<String, String> getPlayerAttackDirs() {
|
||||||
|
return playerAttackDirs;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 发送攻击消息给其他玩家
|
* 发送攻击消息给其他玩家
|
||||||
*/
|
*/
|
||||||
public void sendAttack(String attackType) {
|
public void sendAttack(String attackType, String dir) {
|
||||||
if (localPlayerId == null)
|
if (localPlayerId == null)
|
||||||
return;
|
return;
|
||||||
String msg = "ATTACK:" + localPlayerId + "," + attackType;
|
String msg = "ATTACK:" + localPlayerId + "," + attackType + "," + dir; // 新格式包含方向
|
||||||
Gdx.app.log("Network", "发送攻击消息: " + msg);
|
Gdx.app.log("Network", "发送攻击消息: " + msg);
|
||||||
if (isHost && server != null) {
|
if (isHost && server != null) {
|
||||||
server.broadcastToOthers(null, msg);
|
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() {
|
public Map<String, String> getPlayerCharacters() {
|
||||||
return playerCharacters;
|
return playerCharacters;
|
||||||
}
|
}
|
||||||
@@ -180,8 +202,12 @@ public class NetworkManager {
|
|||||||
return damageEvents;
|
return damageEvents;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendDamage(String targetId, int amount) {
|
public Map<String, Integer> getDamageDirs() {
|
||||||
String msg = "DAMAGE:" + targetId + "," + amount; // 不含方向
|
return damageDirs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void sendDamage(String targetId, int amount, int dirSign) {
|
||||||
|
String msg = "DAMAGE:" + targetId + "," + amount + "," + dirSign; // 含方向
|
||||||
if (isHost && server != null) {
|
if (isHost && server != null) {
|
||||||
server.broadcastToOthers(null, msg);
|
server.broadcastToOthers(null, msg);
|
||||||
receiveMessage(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) {
|
public void sendRespawn(String playerId, float x, float y) {
|
||||||
String msg = "RESPAWN:" + playerId + "," + x + "," + y;
|
String msg = "RESPAWN:" + playerId + "," + x + "," + y;
|
||||||
if (isHost && server != null) {
|
if (isHost && server != null) {
|
||||||
@@ -221,6 +252,10 @@ public class NetworkManager {
|
|||||||
}
|
}
|
||||||
playerPositions.clear();
|
playerPositions.clear();
|
||||||
playerCharacters.clear();
|
playerCharacters.clear();
|
||||||
|
playerAttacks.clear();
|
||||||
|
playerAttackDirs.clear();
|
||||||
|
damageEvents.clear();
|
||||||
|
damageDirs.clear();
|
||||||
Gdx.app.log("Network", "已断开连接");
|
Gdx.app.log("Network", "已断开连接");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user