浮点变量在没有明确赋值的情况下被改变。

huangapple 未分类评论64阅读模式
英文:

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:

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 &amp;&amp; KambojaMain.getInstance().multiplayerConnection &amp;&amp; !KambojaMain.getInstance().isServer) return;
		if(imunity &lt;= 0){
			//new Exception().printStackTrace();
			setLife(getLife() - amount * def);
			
			if(owner != null) {
				owner.score += amount*def;
			}
						
			if(showBlood)
			state.showBlood(body.getWorldCenter());

			System.out.println(&quot; - DAMAGE DETECTED from &quot; + owner.getId() + &quot; to &quot; + getId() + &quot; with value &quot; + amount + &quot;, it was a local? &quot; + local + &quot;, and show blood is: &quot; + showBlood);
			System.out.println(&quot;target life is now at &quot; + getLife());
			
			hitTimer = 1f;
			if(getLife() &lt;= 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 = &quot;controller&quot;;
					if(isKeyboard()) {
						playerType = &quot;keyboard&quot;;
					}
					if(this instanceof BetterBot) {
						playerType = &quot;bot&quot;;
					}
					
					HashMap&lt;String, String&gt; customs = new HashMap&lt;String, String&gt;();
					customs.put(&quot;cd1&quot;, KambojaMain.getMapName());
					customs.put(&quot;cd3&quot;, getWeapon().getClass().getSimpleName());
					customs.put(&quot;cd4&quot;, &quot;player_&quot; + playerType);
					
					String ow = &quot;Suicide&quot;;
					
					if(owner != null)
						ow = owner.getWeapon().getClass().getSimpleName();
					
					KambojaMain.event(&quot;game&quot;, &quot;player_kill&quot;,  ow, customs);
				}
			}
			if(gruntTimer &lt; 0){
				if(GameState.SFX)
				grunt[(int)(Math.random()*5)].play();
				gruntTimer = 0.5f;
			}
			
			if(KambojaMain.getInstance().multiplayerConnection &amp;&amp; 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 + &quot; damaged &quot; + pd.target + &quot;, broadcasting to clients - &quot;);
				KambojaMain.getInstance().broadcast(kp, Protocol.TCP);
				System.out.println(&quot;Sent&quot;);
			}
		}
	}

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.

huangapple
  • 本文由 发表于 2020年4月5日 08:30:33
  • 转载请务必保留本文链接:https://java.coder-hub.com/61036591.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定