LibGDX / Java奇怪的行为

  • 本文关键字:Java LibGDX java libgdx
  • 更新时间 :
  • 英文 :


这是一个用LibGDX制作的游戏。用户可以生成绵羊,然后它们应该随机四处游荡。有两个问题。

  1. 绵羊并不总是改变它们的"正确"变量。
  2. 它们似乎总是以相同的方式移动,这不应该发生。

下面是主类和实体类的代码。其他不应该是此错误的原因。

主要:

package com.god.game;
import com.badlogic.gdx.*;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import com.badlogic.gdx.input.GestureDetector;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.math.Vector3;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
public class MainClass extends ApplicationAdapter {
    public static final int width = 1600;
    public static final int height = 1000;
    public static final String title = "God Game";
    public static EntityType[] entityTypes;
    public static float rand, cameraSpeed;
    public static Comparator<Entity> layerComp;
    public static int selectedId;
    public static String aiStr;
    public static InputMultiplexer input;
    SpriteBatch batch;
    public static ArrayList<Entity> entities;
    public static OrthographicCamera camera;
    public static Vector3 mousePos;
    @Override
    public void create () {
        input = new InputMultiplexer();
        input.addProcessor(new com.god.game.Input());
        input.addProcessor(new GestureDetector(new Gestures()));
        Gdx.input.setInputProcessor(input);
        entityTypes = new EntityType[]{new EntityType("Sheep", new Vector2(55, 38), new TextureAtlas(Gdx.files.internal("Textures/sheep.atlas")), 20, new AI(new String[]{"Wander"}))};
        entities = new ArrayList<Entity>();
        layerComp = new Comparator<Entity>() {
            @Override
            public int compare(Entity e1, Entity e2) {
                if (e1.getPosition().y > e2.getPosition().y)
                    return -1;
                if (e1.getPosition().y < e2.getPosition().y)
                    return 1;
                return 0;
            }
        };
        camera = new OrthographicCamera(width, height);
        cameraSpeed = 500;
        selectedId = 0;
        batch = new SpriteBatch();
    }
    public void update(float deltaTime){
        handleInput(deltaTime);
        for(Entity e : entities){
            e.update(deltaTime);
        }
        Collections.sort(entities, layerComp);
        camera.update();
    }
    @Override
    public void render () {
        update(Gdx.graphics.getDeltaTime());
        Gdx.gl.glClearColor(0, 0.8f, 0, 1);
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
        batch.setProjectionMatrix(camera.combined);
        batch.begin();
        for(Entity e : entities){
            if(!e.isRight())
                entityTypes[e.getId()].getAtlas().findRegion(e.getFrame()).flip(true, false);
            batch.draw(entityTypes[e.getId()].getAtlas().findRegion(e.getFrame()), e.getPosition().x, e.getPosition().y);
            if(!e.isRight())
                entityTypes[e.getId()].getAtlas().findRegion(e.getFrame()).flip(true, false);
        }
        batch.end();
    }
    @Override
    public void dispose(){
        batch.dispose();
        for(EntityType e : entityTypes)
            e.dispose();
    }
    public void handleInput(float deltaTime){
        mousePos = new Vector3(Gdx.input.getX(), Gdx.input.getY(), 0);
        camera.unproject(mousePos);
        if(Gdx.input.isKeyPressed(Input.Keys.W))
            camera.translate(0, cameraSpeed*deltaTime);
        if(Gdx.input.isKeyPressed(Input.Keys.A))
            camera.translate(-cameraSpeed*deltaTime, 0);
        if(Gdx.input.isKeyPressed(Input.Keys.S))
            camera.translate(0, -cameraSpeed*deltaTime);
        if(Gdx.input.isKeyPressed(Input.Keys.D))
            camera.translate(cameraSpeed*deltaTime, 0);
    }
}

实体:

package com.god.game;
import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.math.Vector2;
public class Entity {
    private int id;
    private Vector2 position, goalPos;
    private boolean right;
    private String frame;
    private float animationTimer;
    public Entity(int id, Vector2 position) {
        this.id = id;
        this.position = position;
        this.right = true;
        this.frame = "stand";
        this.animationTimer = 0;
        this.goalPos = Vector2.Zero;
    }
    public void update(float deltaTime){
        MainClass.aiStr = MainClass.entityTypes[id].getAi().getBrainList()[0];
        if(MainClass.aiStr == "Wander"){
            MainClass.rand = MathUtils.random(1000);
            if(MainClass.rand == 1){
                goalPos.x = -1;
                right = false;
            }
            else if(MainClass.rand == 2)
                goalPos.x = 0;
            else if(MainClass.rand == 3){
                goalPos.x = 1;
                right = true;
            }
            MainClass.rand = MathUtils.random(1000);
            if(MainClass.rand == 1)
                goalPos.y = -1;
            else if(MainClass.rand == 2)
                goalPos.y = 0;
            else if(MainClass.rand == 3)
                goalPos.y = 1;
            moveForward(deltaTime);
        }
        else{
            frame = "stand";
            animationTimer = 0;
        }
        animationTimer += deltaTime;
    }
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public Vector2 getPosition() {
        return position;
    }
    public void setPosition(Vector2 position) {
        this.position = position;
    }
    public boolean isRight() {
        return right;
    }
    public void setRight(boolean right) {
        this.right = right;
    }
    public String getFrame() {
        return frame;
    }
    public void setFrame(String frame) {
        this.frame = frame;
    }
    public float getAnimationTimer() {
        return animationTimer;
    }
    public void setAnimationTimer(float animationTimer) {
        this.animationTimer = animationTimer;
    }
    public Vector2 getGoalPos() {
        return goalPos;
    }
    public void setGoalPos(Vector2 goalPos) {
        this.goalPos = goalPos;
    }
    public void moveForward(float deltaTime){
        position.x += MainClass.entityTypes[id].getMoveSpeed() * deltaTime * goalPos.x;
        position.y += MainClass.entityTypes[id].getMoveSpeed() * deltaTime * goalPos.y;
        if(goalPos.x == 0 && goalPos.y == 0){
            frame = "stand";
            animationTimer = 0;
        }
        else if(animationTimer >= 0.2f){
            if(frame.equals("stand"))
                frame = "move";
            else
                frame = "stand";
            animationTimer = 0;
        }
    }
}
羊每次将

goalPos.x更改为-1或1时都应该将正确的变量设置为true/false,但它们似乎没有这样做。它们似乎也不是独立移动的,相反,它们就像一个阵型,每次都朝着同一个方向移动。他们确实独立地将正确的变量设置为真/假,但这与他们的运动不匹配。例如:一只羊向右移动,然后随机向左转,同时仍然向右移动,等等。

任何帮助将不胜感激,谢谢!

首先,你永远不应该说Java的行为很奇怪,而应该说你的代码没有按照你的预期表现。如果你把你的错误归咎于一些内部的Java功能,你永远不会找到它们。现在让我们来看看如果你的 ai 设置为 wander 会发生什么。

if(MainClass.aiStr == "Wander"){
        MainClass.rand = MathUtils.random(1000);
//Random number in the range of 0 to 1000.
        if(MainClass.rand == 1){ //happens .1% of the time
            goalPos.x = -1;
            right = false;
        }
        else if(MainClass.rand == 2) //happens .1% of the time
            goalPos.x = 0;
        else if(MainClass.rand == 3){ //happens .1% of the time
            goalPos.x = 1;
            right = true;
        }
 //since there is no else nothing happens 99.7% of the time.
    }

我的猜测是,您的代码的行为符合您的预期,并且您的计算机内部没有黑色巫毒教。所以将来责怪自己并检查你的代码,它真的不是那么多代码,你发布的内容中只有一小部分负责指导你的实体。

现在你可能想要的是这样的东西MathUtils.random(1, 4)因为最大值是排他性的。或者MathUtils.random(1, 5),如果你希望25%的时间什么都不发生。

就机会而言,一种更具可扩展性的方式,我总是喜欢这样的东西:

int randomNumber = MathUtils.random(1, 101);
if (randomNumber <= 33)
{
  //do something 33% of the time
}
else if (randomNumber <= 66)
{
  //do something 33% of the time
}
else
{
  //do something 34% of the time
}

现在这更容易更改,因为您需要做的就是更改百分比,然后可以轻松添加另一个案例。

if (randomNumber <= 20)
{
  //do something 20% of the time
}
else if (randomNumber <= 60)
{
  //do something 40% of the time
}
else if (randomNumber <= 58)
{
  //do something 18% of the time
}
else
{
  //do something 22% of the time
}

首先,您正在以静态方式生成变量,例如

         [...]
    MainClass.aiStr = MainClass.entityTypes[id].getAi().getBrainList()[0];
         [...]
    MainClass.rand = MathUtils.random(1000);
         [...]

所以所有的羊都将使用相同的值并像相同的一样移动,只需在同一实例上进行这些调用。

如果你是数学兰特 1000 并且比较值是否为 1,则每帧的几率为 0,1%,如果你的游戏被锁定在 30fps 上,它触发的机会非常非常低。

你在渲染方法上检查两次if(!e.isRight()),所以它会翻转两次。

 for(Entity e : entities){
            if(!e.isRight())
                entityTypes[e.getId()].getAtlas().findRegion(e.getFrame()).flip(true, false);
            batch.draw(entityTypes[e.getId()].getAtlas().findRegion(e.getFrame()), e.getPosition().x, e.getPosition().y);
            if(!e.isRight())
                entityTypes[e.getId()].getAtlas().findRegion(e.getFrame()).flip(true, false);
        }

您能否提供有关实体类型类的更多信息?因此,当您在实体上设置移动速度时,我们可以了解您在做什么。

[编辑] 正如 mbrlabs 所述,总是使用 .equals 来比较字符串,因为即使它们看起来相同,它们实际上是内存上包含相同文本的 2 个不同对象,因此使用 == 永远不会是真的。

在实体类中将此if(MainClass.aiStr == "Wander")更改为 MainClass.aiStr.equals("Wander")

比较字符串时,应始终以这种方式执行此操作。通过使用 ==,您正在比较引用,但您希望比较字符串的实际内容。if 语句之间的代码很可能永远不会执行,因为您正在比较引用。

最新更新