Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: All sprites in vector are moving in the exact same pattern  (Read 2396 times)

0 Members and 1 Guest are viewing this topic.

ThatOneGuyThatDoesStuff

  • Newbie
  • *
  • Posts: 28
    • View Profile
    • Email
All sprites in vector are moving in the exact same pattern
« on: February 14, 2020, 10:45:51 pm »
I have been bashing my head against the wall for the last 4 days trying to figure out where in the name of holy pasta salad I'm going wrong here. I cannot begin to vent my frustration.

class AnimalObj{
    sf::Sprite animalSprite;
    void MoveAnimal(int direction){
        //Moves in the appropriate direction
        if (direction == 1){
            //Go up
            if (animalSprite.getPosition().y - animalMoveDist >= 0){
                animalSprite.move(0.0, -animalMoveDist);
                AnimateAnimal(1, 1);
                previousMove = 1;
            }
        }else if (direction == 3){
            //Go down
            if (animalSprite.getPosition().y + animalMoveDist <= 800){
                animalSprite.move(0.0, animalMoveDist);
                AnimateAnimal(3, 3);
                previousMove = 3;
            }
        }else if (direction == 2){
            //Go right
            if (animalSprite.getPosition().x + animalMoveDist <= 1000){
                animalSprite.move(animalMoveDist, 0.0);
                AnimateAnimal(2, 2);
                previousMove = 2;
            }
        }else if (direction == 4){
            //Go left
            if (animalSprite.getPosition().x - animalMoveDist >= 0){
                animalSprite.move(-animalMoveDist, 0.0);
                AnimateAnimal(4, 4);
                previousMove = 4;
            }
        }else{
            AnimateAnimal(0, 0);
            previousMove = 0;
        }
    }

std::vector<Chicken> animalArr;
int main{
    AnimalObj NewChicken;
    NewAnimal.animalSprite.setTexture(henTex);
    NewAnimal.animalSprite.setPosition(400, 400);

    AnimalObj new_chicken;
    NewAnimal.animalSprite.setTexture(roosterTex);
    animalArr.push_back(new_chicken);

    while (renderWindow.isOpen()){
        for(int animal = 0; animal < animalArr.size(); animal++){
            animalArr[animal].MoveAnimal(RandomDirection()); //RandomDirection returns a random direction
            renderWindow.draw(animalArr[animal].animalSprite);
        }
    }
}
 

I hope I didn't post too much code. I purged as much as I could that I thought was surplus/unnecessary.

The problem is that each sprite will move in the same direction, regardless of where they are going. If one goes left, all sprites go left. If it goes right... all of them go right. At first I thought it was an issue with my random number generation, but I programmed in instructions to move to a particular position for one of the sprites, and all sprites would then move in the appropriate direction, regardless of where they are spawned. Once the first sprite arrives at location, it stops moving. I've pretty much narrowed down the error to the MoveAnimal function that I posted above, but I have no idea why it's doing that. It seems that the .move() function is causing all sprites in the vector to move in the same direction despite them being told to move randomly I checked, the appropriate MoveAnimal are receiving instructions to move randomly, but are ignoring them in favor of following the direction of the first sprite until it arrives at location, then all the rest continue to move in sync.

I don't know if I'm just being incredibly dense here, but any help will be greatly appreciated. Seriously. I'd like to stop banging my head on the table, so if anyone can help me put an end to that, that would be great.

Zel

  • Newbie
  • *
  • Posts: 8
    • View Profile
Re: All sprites in vector are moving in the exact same pattern
« Reply #1 on: February 15, 2020, 03:54:52 am »
Okay so couple of possibilities.

Are you using the same instance of the random number generator function for all the animals? If yes, then all the animals are receiving the same information. If no make sure you are reseeding the the generator between each instance. You random number generator can be doing exactly what it is supposed to but if you are using it in a fashion that results in the same simulation , or are using the same result across multiple objects you won't get any randomness. 

ThatOneGuyThatDoesStuff

  • Newbie
  • *
  • Posts: 28
    • View Profile
    • Email
Re: All sprites in vector are moving in the exact same pattern
« Reply #2 on: February 15, 2020, 06:56:21 am »
Hmm. The seeding is done at object creation. I have no idea how I would go about reseeding with each iteration.

class AnimalObj{
private:
    //std::random_device rd; Commented out because it returns error "use of deleted function that I can't fix
    std::mt19937 mt;
    std::uniform_int_distribution<int> dist;
public:
    AnimalObj : mt(), dist(0, 4);
 

Zel

  • Newbie
  • *
  • Posts: 8
    • View Profile
Re: All sprites in vector are moving in the exact same pattern
« Reply #3 on: February 15, 2020, 10:33:25 pm »
Something like this may produce some more favorable results.  Please note that rand() is not guaranteed to produce purely random numbers to begin with.


class RANDOMIZER
        {
         public:
         int random_value;
         int getRandomNumber()  //return random number
            {
            srand((int)time(0));//seed randomizer with current time
            random_value=rand() % 100+1; //get psuedo-random result between 1 and 100
            //***Important*** The numbers returned will be integers representing a percentage of 100 IE 1% though 100%
            return(random_value);
            }
        };
 

ThatOneGuyThatDoesStuff

  • Newbie
  • *
  • Posts: 28
    • View Profile
    • Email
Re: All sprites in vector are moving in the exact same pattern
« Reply #4 on: February 16, 2020, 06:56:46 am »
Hi Zel. I've already attempted that method, and used rand(). I really do not believe the problem to be a randomizing error. As I said, even if one of the sprites is given specific instructions to got to a specific location, no random numbers involved, ALL the sprites follow in the same direction, despite their own instructions to flit about randomly.

Josh_M

  • Newbie
  • *
  • Posts: 11
    • View Profile
    • Email
Re: All sprites in vector are moving in the exact same pattern
« Reply #5 on: February 26, 2020, 09:57:43 am »
It's because you don't understand how the random functions are intended to be used. They're quite over-complicated for simple uses because they're intended to be useful for scientists and statisticians.

The previous poster is also wrong, you shouldn't keep reseeding every call, as if you call more than once in a second you'll keep getting the same result (by design)!

Consider the following code snippet, similar to yours:
// Example program
#include <iostream>
#include <string>
#include <random>

class Test
{
private:
    std::mt19937 mt;
    std::uniform_int_distribution<int> dist;
public:
    Test() : mt(time(0)), dist(0, 4)
    {
    }

    int genRandom()
    {
        return dist(mt);
    }
};

int main()
{  
    Test t1{};
    Test t2{};
   
    for(int i = 0; i < 3; i++)
    {
        std::cout << "iteration #" << i << "\n";
        std::cout << t1.genRandom() << "\n";
        std::cout << t2.genRandom() << "\n";
    }
}

The output is:
iteration #0
3
3
iteration #1
1
1
iteration #2
0
0

This is because we seed two random generators with the same seed at the same time, then call them at the same times! You should only seed a random generator once in your entire application, then call it everywhere, unless you have very exotic needs.

Put it in a static method with a lazy initializer would be my recommendation, like:
class Random
{
public:
    static int getRandomInt(int min, int max)
    {
        // static so it's only created once, then every other call reuses it (forever)
        // if you need multiple types of random functions you'd need to make it a private member
        // and reuse it instead
        static std::mt19937 mt(time(0));
       
        auto dist = std::uniform_int_distribution<int>(min, max);
        return dist(mt);
    }
};

And call it like this (anywhere):
Random::getRandomInt(0, 4)

Good luck.