Member 14074655 Ответов: 2

Одно из значений моего класса продолжает возвращаться к своему первоначальному значению


Здравствуйте, я довольно новичок в C++ и пытаюсь имитировать естественный отбор, похожий на это видео - https://www.youtube.com/watch?v=0ZGbIKd0XrM . Я пытаюсь добавить случайное движение в свою игру через случайные углы и скорость перемещения на расстояние до этого угла. Однако в случае приведенного ниже кода, сделанного с использованием C++ и OpenGL, вы увидите, что я консольно регистрирую x и y, однако они в конечном итоге по умолчанию равны 300 после одного изменения(300-это оба их первоначальных значения). Есть ли решение для этого, и если да, то что я делал не так? Спасибо.
#include <iostream>
#include <vector>
#include <random>
#include <cmath>
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <cmath>

int width  = 600;
int height = 600;

/*class V2D
{
  public:
    V2D(){}
    V2D(float _x, float _y)
    {
      x = _x;
      y = _y;
    }
    float x;
    float y;
};
*/
class Survivor
{
  public:
    float x;
    float y;
    float energy;
    int foodInPossession;
    float speed;
    //float size;
    float sense;
    float angleOfSense = -1;
    Survivor();
    Survivor(float _x, float _y, float _speed, float _sense)
    {
      x = _x;
      y = _y;
      speed             = _speed;
      energy            = 100;
      foodInPossession  = 0;
      //size              = _size;
      sense             = _sense;
    }
    void update()
    {
      float LO = 0;
      float HI = 360;
      float aom;
      if(angleOfSense==-1)
        aom = LO + static_cast <float> (rand()) /( static_cast <float> (RAND_MAX/(HI-LO)));
      else
        aom = angleOfSense;
      std::cout<<x<<" "<<y<<std::endl;
      x+= speed * sin(aom);
      y+= speed * cos(aom);
      std::cout<<x<<" "<<y<<std::endl;
    }
    bool onBorder()
    {
      return x == 0 || x == width || y == 0 || y == height;
    }
};
int main()
{
  std::vector<Survivor> survivors;
  survivors.push_back(Survivor(300, 300, 10, 1));
  GLFWwindow* window;
  if (!glfwInit())
    return 1;
  window = glfwCreateWindow(width, height, "Window", NULL, NULL);
  if (!window) {
    glfwTerminate();
    return 1;
  }
  glfwMakeContextCurrent(window);
  if(glewInit()!=GLEW_OK)
    std::cout<<"Error"<<std::endl;
  glEnable(GL_DEPTH_TEST);
  glMatrixMode(GL_PROJECTION);
  glfwGetFramebufferSize(window, &width, &height);
  glOrtho(0, width*(width/height), height, 0, -2, 2);
  while(!glfwWindowShouldClose(window)) {
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
    glClearColor(0.11, 0.14, 0.17, 1);
    
    for(Survivor i : survivors)
    {
      if(!i.onBorder())
      {
        i.update();
      }
      glBegin(GL_QUADS);
      glColor3f(1, 1, 1);
      glVertex2f(i.x, i.y);
      glVertex2f(i.x + 1, i.y);
      glVertex2f(i.x + 1, i.y + 1);
      glVertex2f(i.x, i.y + 1);
      glEnd();
    }

    glfwSwapBuffers(window);
    glfwPollEvents();
  }
  glfwTerminate();
}


Что я уже пробовал:

До сих пор я ничего не пробовал, так как не смог даже найти корень проблемы.

2 Ответов

Рейтинг:
2

Stefan_Lang

Помимо того, что Карло сказал в решении 1, есть еще две проблемы:

Цитата:
return x == 0 || x == width || y == 0 || y == height;

Никогда не сравнивайте переменные с плавающей запятой, используя == или != . Эти значения подвержены тонким колебаниям из-за эффекта округления, и поэтому прямое сравнение почти всегда будет неудачным, даже если математически оно должно быть успешным.

Тем не менее, поскольку вы добавляете случайные значения к x и y, вы, вероятно, никогда не закончите точно на границе - вместо этого вы будете двигаться прямо мимо нее! Поэтому вместо того, чтобы проверять, находитесь ли вы на границе, вы должны проверить, находитесь ли вы снаружи! В качестве альтернативы вы должны исправить метод обновления, чтобы остановиться на границе.

Во-вторых:
for(Survivor i : survivors)

Этот код создаст копию векторного элемента. Поэтому обновление не изменит ни один векторный элемент, только его копию. Возможно, вы захотите попробовать
for(Survivor& i : survivors)
вместо этого, или просто
for(auto& i : survivors)


Рейтинг:
1

CPallini

Корень проблемы в этом фрагменте кода:

Цитата:
если(angleOfSense==-1)
аом = ЛО + метод static_cast &ЛТ;поплавок&ГТ; (слчис()) /( метод static_cast &ЛТ;поплавок&ГТ; (RAND_MAX/(привет-ЛО)));
еще
аом = angleOfSense;
Он вычисляет случайный угол только в первый раз он исполняется (когда angleOfSense равно его значению инициализации, то есть -1).

Кроме того, обратите внимание sin и cos функции принимают углы в радианах, в то время как ваши передают Градусы.