英文:
float variable beign changed without beign explicitely atributted
问题
我甚至不知道如何描述我现在遇到的这种奇怪行为,但问题是:
我有一个名为 Player.java 的类,其中有一个私有的浮点数 life,非常基础。
这个浮点数有它自己的设置器/获取器,没有其他方式可以在不使用获取器/设置器的情况下检索/赋值这个变量。
另外,我在每个获取器/设置器中都放了一个 println,以便我可以得到这个变量被检索时的反馈,以及何时被赋值,我在我的控制台上看到了这个:
我不认为堆栈跟踪在任何情况下都有用,但如果你想要的话,我可以粘贴堆栈跟踪后面的代码。
无论如何,如果你还没有注意到,这里有一个检索 life = 61,后面是一个检索 life = 70,完全没有将这个变量回归到 70 的任何赋值。
另外,我不知道这是否有用,但这是打印 "1 damaged 0, broadcasting to clients - Sent" 的代码:
它总结如下:
- 减少玩家生命值
- 如果玩家死亡,标记为死亡并进行其他小的效果处理
- 发送事件到 Google Analytics
- 在所有这些操作之后,如果游戏是服务器,则向所有客户端广播伤害事件
public void takeDamage(float amount, Player owner, boolean showBlood, boolean local) {
if (local && KambojaMain.getInstance().multiplayerConnection && !KambojaMain.getInstance().isServer) return;
if (imunity <= 0) {
//new Exception().printStackTrace();
setLife(getLife() - amount * def);
if (owner != null) {
owner.score += amount * def;
}
if (showBlood)
state.showBlood(body.getWorldCenter());
System.out.println(" - DAMAGE DETECTED from " + owner.getId() + " to " + getId() + " with value " + amount + ", it was a local? " + local + ", and show blood is: " + showBlood);
System.out.println("target life is now at " + getLife());
hitTimer = 1f;
if (getLife() <= 0) {
if (!isDead()) {
deaths++;
if (owner != null) {
owner.kills++;
owner.ghosts.add(new Ghost(getId(), getPosition()));
owner.score += 100;
}
setDead(true);
body.getFixtureList().get(0).setSensor(true);
getState().showSkull(body.getWorldCenter(), getAngle());
String playerType = "controller";
if (isKeyboard()) {
playerType = "keyboard";
}
if (this instanceof BetterBot) {
playerType = "bot";
}
HashMap<String, String> customs = new HashMap<String, String>();
customs.put("cd1", KambojaMain.getMapName());
customs.put("cd3", getWeapon().getClass().getSimpleName());
customs.put("cd4", "player_" + playerType);
String ow = "Suicide";
if (owner != null)
ow = owner.getWeapon().getClass().getSimpleName();
KambojaMain.event("game", "player_kill", ow, customs);
}
}
if (gruntTimer < 0) {
if (GameState.SFX)
grunt[(int) (Math.random() * 5)].play();
gruntTimer = 0.5f;
}
if (KambojaMain.getInstance().multiplayerConnection && KambojaMain.getInstance().isServer) {
KambojaPacket kp = new KambojaPacket(PacketType.PLAYER_DAMAGE);
PlayerDamage pd = new PlayerDamage();
pd.damage = amount;
pd.showBlood = showBlood;
pd.owner = owner.getId();
pd.target = getId();
kp.data = pd;
System.out.print(pd.owner + " damaged " + pd.target + ", broadcasting to clients - ");
KambojaMain.getInstance().broadcast(kp, Protocol.TCP);
System.out.println("Sent");
}
}
}
注意:我正在使用多线程环境,因为这是一个局域网多人游戏,这个变量可以在不同于主线程的其他线程中检索。
我已经尝试过使用 volatile 关键字、原子类(没有 AtomicFloat,尝试使用 AtomicInt 实现它作为位数据),但这些都不能防止这种情况发生,我不知道这种行为是什么以及是什么原因导致的。
有人能帮帮我吗?我不知道还能搜索什么。
英文:
I don't event know how to describe this weird behaviour i'm dealing with right now, but the thing is:
I have a class Player.java that has a private float life, pretty basic.
this float has its setter / getter and there is NO other way of retrieving / attributing this variable without using the getter / setter.
also, i have put a println in each, so i can have a feedback of when this variable is being retrieved, and when is beign attributed, and i get THIS on my console:
i don't think the stack trace is usefull in any way, but if you want to, i can paste the code behind the stack trace too
anyway, if you haven't notice, there is a retrieve of life = 61, FOLLOWED by a retriving of life = 70, with NO attribution WHATSOEVER of this variable back to 70.
also, i dont know if this is useful, but here is the code that prints the "1 damaged 0, broadcasting to clients - Sent":
it resume in:
- decreases the player life
- if it has died, mark as dead and do other little effect things
- send event to google analytics
- after all that, if the game is a server, broadcast the damage event to all clients
public void takeDamage(float amount, Player owner, boolean showBlood, boolean local){
if(local && KambojaMain.getInstance().multiplayerConnection && !KambojaMain.getInstance().isServer) return;
if(imunity <= 0){
//new Exception().printStackTrace();
setLife(getLife() - amount * def);
if(owner != null) {
owner.score += amount*def;
}
if(showBlood)
state.showBlood(body.getWorldCenter());
System.out.println(" - DAMAGE DETECTED from " + owner.getId() + " to " + getId() + " with value " + amount + ", it was a local? " + local + ", and show blood is: " + showBlood);
System.out.println("target life is now at " + getLife());
hitTimer = 1f;
if(getLife() <= 0){
if(!isDead()){
deaths++;
if(owner != null){
owner.kills ++;
owner.ghosts.add(new Ghost(getId(), getPosition()));
owner.score += 100;
}
setDead(true);
body.getFixtureList().get(0).setSensor(true);
getState().showSkull(body.getWorldCenter(), getAngle());
String playerType = "controller";
if(isKeyboard()) {
playerType = "keyboard";
}
if(this instanceof BetterBot) {
playerType = "bot";
}
HashMap<String, String> customs = new HashMap<String, String>();
customs.put("cd1", KambojaMain.getMapName());
customs.put("cd3", getWeapon().getClass().getSimpleName());
customs.put("cd4", "player_" + playerType);
String ow = "Suicide";
if(owner != null)
ow = owner.getWeapon().getClass().getSimpleName();
KambojaMain.event("game", "player_kill", ow, customs);
}
}
if(gruntTimer < 0){
if(GameState.SFX)
grunt[(int)(Math.random()*5)].play();
gruntTimer = 0.5f;
}
if(KambojaMain.getInstance().multiplayerConnection && KambojaMain.getInstance().isServer) {
KambojaPacket kp = new KambojaPacket(PacketType.PLAYER_DAMAGE);
PlayerDamage pd = new PlayerDamage();
pd.damage = amount;
pd.showBlood = showBlood;
pd.owner = owner.getId();
pd.target = getId();
kp.data = pd;
System.out.print(pd.owner + " damaged " + pd.target + ", broadcasting to clients - ");
KambojaMain.getInstance().broadcast(kp, Protocol.TCP);
System.out.println("Sent");
}
}
}
note: i AM using multi threading environment because this is a lan multiplayer game, and this variable can be retrieved in other threads different from the main thread.
I have searched about the volatile keyword, Atomic classes (AtomicFloat dont exist, and the implementation of it using AtomicInt as a bit data also was used), but none of this could prevent this from happening and i have NO idea of what is this behaviour and what is causing it
can someone please help me? i don't know what to search anymore
答案1
得分: 0
尝试将你的方法设为synchronized
(这将确保只有一个线程可以在类的实例上运行此方法)。
public synchronized void takeDamage(.... // 与之前相同的代码
查看这篇帖子,其中有一个类似的问题,提供了有关以原子方式运行代码块的更多信息。
英文:
Try making your method synchronized
(this would make sure only one thread can be running this method, on an instance of your class).
public synchronized void takeDamage(.... // same as before
Check out this post, it has a similar question with more info about running blocks of code atomically.
专注分享java语言的经验与见解,让所有开发者获益!
评论