2016-02-21 4 views
0

Это игра, сделанная в LibGDX. Пользователь может порождать овец, которые затем должны бродить случайно. Есть две проблемы.LibGDX/Java странное поведение

  1. Овцы не всегда меняют свою «правую» переменную.
  2. Они, кажется, всегда движутся одинаково, что не должно происходить.

Вот код классов MainClass и Entity. Остальные не должны быть причиной этой ошибки.

Главная:

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); 
    } 
} 

Entity:

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, но не соответствуют их движению. Пример: овца движется вправо, а затем случайным образом поворачивает налево, все еще двигаясь вправо и т. Д.

Любая помощь будет принята с благодарностью, спасибо!

ответ

2

Во-первых, вы никогда не должны говорить, что 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 
} 
+0

Я не обязательно утверждал, что это была ошибка Java/LibGDX, просто это казалось странным, потому что это не имело никакого смысла, но мне жаль, если вы так поступили. Кроме того, причина, по которой MathUtils.random равна 1000, заключается в том, что овцы могут продвигаться вперед в течение нескольких секунд (потому что их цельPos не изменяется), а затем изменить их направление, а не просто идти немного влево и вправо, что не похож на блуждание. Но даже установка его с 1 на 4 не решит проблему, я уверен. – RontoKing

+0

Ну, скажем так, ваш выбор слов неудачен. Если возможно, попробуйте задать вопрос без какого-либо другого шума здесь, на SO. Поскольку вы уверены, что можете захотеть проверить, чтобы убедиться, что меньше всего вы можете сделать, если кто-то прилагает усилия, чтобы помочь вам. Я понимаю, что вы имеете в виду, прямо сейчас rand должен быть 1 каждые 16 секунд, если вы выполняете 60 кадров в секунду. 16 секунд довольно длинный, и если ваше «неудачное» это может быть легко минут. Вы также можете сделать 'MainClass.rand' int. Вы все равно вкладываете в него int, и вы сравниваете vs int, поэтому нет причин иметь его как float. – Madmenyo

+0

Неужели заявления всегда срабатывают? Вы попробовали отладить его? Я тестировал ваш рандомизатор, и все они срабатывают, иногда требуется немного времени. Если вы хотите, чтобы что-то простаивало или гуляло прямо, просто используйте мой метод или даже установите таймер со случайным значением, чтобы пропустить все заявления. – Madmenyo

0

В вашем изменении класса Entity это if(MainClass.aiStr == "Wander") к MainClass.aiStr.equals("Wander").

Когда вы сравниваете строки, вы всегда должны делать это таким образом. Используя ==, вы сравниваете ссылку, но хотите сравнить фактическое содержимое строки. Код между оператором if скорее всего не выполняется, поскольку вы сравниваете ссылки.

+0

Я изменил его, но он по-прежнему ведет себя одинаково. – RontoKing

1

Прежде всего, вы acessing переменные на статически, как

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

так что все бараны собираются использовать эту же величину и двигаться, как то же самое, просто сделать эти звонки по одному экземпляру.

Если вы являетесь математическим rand 1000 и сравниваете, если значение равно 1 его шансу на 0,1% на каждый фрейм, если ваша игра заблокирована на 30fps, шансы на ее запуск очень, очень низки.

Вы проверяете дважды , если (! 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); 
     } 

Не могли бы вы предоставить дополнительную информацию о классе EntityType? Таким образом, мы можем узнать, что вы делаете, когда настраиваете перемещение на сущности.

[Edit] как указано в mbrlabs, всегда использует .equals для сравнения строк, потому что даже они выглядят одинаково, они фактически представляют собой два разных объекта в памяти, содержащих один и тот же текст, поэтому использование == никогда не будет истинным.

+0

Здесь вы можете увидеть список всех классов: http://www.badlogicgames.com/forum/viewtopic.php?f=11&t=21900 Вот исполняемый файл .jar: https://www.mediafire.com/ ? orad0hjdkqseylr MainClass.rand изменяется каждый раз, прежде чем он используется, поэтому они не используют одинаковые номера. Я пытался сделать все не статическим, это имело тот же эффект. Статика не вызывает проблемы. Он не заблокирован на 30, и даже если бы это было неважно. Когда он получает правильный номер, он меняет направление. Имея более низкий шанс, он действительно продвигается вперед некоторое время, прежде чем оборачиваться. Он дважды переворачивается для сброса текстуры. – RontoKing

Смежные вопросы