1
\$\begingroup\$
#include <iostream> 
#include <time.h> 
#include <iomanip> 
#include <SDL.h> 
#include <stdlib.h> 
#include <string.h> 
#include "screen.h" 
#include "Stars.h" 
#include "Allstars.h" 


int main(int argc, char* argv[]) {

    //seeding random number generator


    srand(time(NULL));

    //------------------------------------------------------------------------------
    /***CREATING SDL WINDOW***/
    /***CREATING RENDERER & TEXTURE***/
    /***CREATING A BUFFER***/

    Screen screen1;
    screen1.init();

    //-----------------------------------------------------------------------------
    /***GAME LOOP***/

    /*UPDATING buffer with texture information*/

    Allstars allstars1;

    while (true) {
        int num=0;
        screen1.screenClear();
        allstars1.updateStarPosition();


        // Allstars class to retrieve  m_pstars from the Allstars class into the main function.

        const Stars * const pStars = allstars1.getStars();

        for (int i = 0; i < allstars1.NSTARS; i++) {
            Stars star = pStars[i];

            // here is where i tried to loop each star back to the bottom of the screen  when they reached the top of the screen.

            if(num>3 && star.m_y_star<-0.97 && star.m_y_star>-1){

                    star.m_y_star=0.99;
                    star.m_x_star= star.m_x_star;

                }

//each star is given a random location by giving co-ordinates: m_x_star & m_y_star a random value using a function in Stars.h
// You can't get negative co-ordinates on the screen so we map from [-1,1] to [0 to SCREEN_WIDTH and 0 to SCREEN_HEIGHT]

            int x = (star.m_x_star + 1) * ((Screen::SCREEN_WIDTH) / 2);
            int y = (star.m_y_star + 1) * ((Screen::SCREEN_HEIGHT) / 2);
            screen1.setPixel(x, y, 128, 0, 255);
        }

        /*UPDATED USED TO UPDATE TEXTURE and RENDERER and PRESENT DRAWING ON SCREEN*/
        screen1.update();

        /* Check for messages and events
         */

        //Quitting SDL through clicking 'x' button event
        if (screen1.processEvents() == false) {
            break;

        }
        num++;
    }
    //-----------------------------------------------------------------------------
    /***FREEING MEMORY & QUITTING SDL***/
    screen1.close();
    return 0;
}
//------------------------------END OF MAIN----------------------------------------

I tried to get use a for loop to change the vertical position of the star once it draws close to the top of the window but that doesn't seem to influence the program. Stars (purple dots) seem to drift off the screen and don't appear from the bottom of the screen again. No errors occur and i have incorporated checks to prevent the stars being plotted off of the screen. Can someone help me make these purple dots loop infinitely without the need for scrolling.

enter image description here

\$\endgroup\$
8
  • \$\begingroup\$ What's the purpose of num? \$\endgroup\$ Jan 11, 2017 at 18:28
  • \$\begingroup\$ Also the condition of star.m_y_star<-0.97 && star.m_y_star>-1 seems weird to me - why this range? What does it stand for? And is it ever true? What does debugging tell you? \$\endgroup\$ Jan 11, 2017 at 18:30
  • \$\begingroup\$ /num/ counts the number of loops in the game loop to give a time lag so that the inital positions of the trailing dots dont get overwritten (Num can be ignored). \$\endgroup\$
    – The Ace
    Jan 11, 2017 at 18:38
  • \$\begingroup\$ the range of m_y_star and m_x_star is [-1 to 1] as they are there positions are given by the equation m_x/y_ star= (2*rand()/RAND_MAX)-1. This is then mapped to the screen width and height in the main() function. -1 is technically off the top of the screen so i used -0.79 as a cut off point. The speed at which each dot is moving is 0.001 in both co-ordinates. This was acheived by creating the updateStarPosition() method. \$\endgroup\$
    – The Ace
    Jan 11, 2017 at 18:44
  • \$\begingroup\$ I produced this code by using the following tutorial: youtube.com/watch?v=cyAvUaPcvss \$\endgroup\$
    – The Ace
    Jan 11, 2017 at 18:48

1 Answer 1

0
\$\begingroup\$

I assume two things:

  1. The constructor of Allstars allstars1; initializes the random positions of all the Stars contained therein.
  2. allstars1.updateStarPosition(); translates the current set of stars vertically in the range [-1, 1] by some very small amount, say 0.001, as you say.

From there, as I understand it, you want to loop through all your stars snapping the y-position of any in the range (-0.97, -1) to 0.99 while maintaining their x-position.


First, move the declaration and initialization of int num = 0 out of the while(true) loop because setting it to 0 each loop means:

if(num>3 && star.m_y_star<-0.97 && star.m_y_star>-1)

is always false. However, if you still want to use it then reset num = 0; inside that num>3 y-position range check. Although I do see in your comments that you've since changed the condition for the better.


The constant pointer to constant data means that nothing pStars points to can be changed.

const Stars * const pStars = allstars1.getStars();

Moreover,

Stars star = pStars[i];

makes a copy of your allstars1 element, which means anything you do to it will not affect anything in allstars1

Both these statements together mean any y-position snapping you do in the for loop only affects the copies of allstars1 elements, and therefore the results only last one frame. This is why you only see a line of stars along the bottom of the screen instead of scrolling stars.


The quick and dirty solution is simply to remove the constant-data qualifier, that is change:

const Stars * const pStars = allstars1.getStars();

to this:

Stars * const pStars = allstars1.getStars();

Then instead of instantiating a copy for each pStar[i] element, just use it directly:

if(num>3 && pStar[i].m_y_star<-0.97 && pStar[i].m_y_star>-1){
    pStar[i].m_y_star=0.99;
//  pStar[i].m_x_star= pStar[i].m_x_star;    // unnecessary self-assignment
}

The self-assignment line is unnecessary; the x-coordinate is constant whether or not you self-assign it.

The same applies here too:

int x = (pStar[i].m_x_star + 1) * ((Screen::SCREEN_WIDTH) / 2);
int y = (pStar[i].m_y_star + 1) * ((Screen::SCREEN_HEIGHT) / 2);

Given that you are using a constant raw pointer to non-constant data you might as well move your pStars pointer outside your while(true) loop. That will save you an assignment each frame.


As a general note look into SDL_GetTicks() instead of <time.h>. Also look into c++ passing by reference, and operator[] overloading, they'll save you a lot of pointer debugging headaches in the future.

\$\endgroup\$
2
  • \$\begingroup\$ Thanks TOM, i've just seen your reply now. I got the code to work yesterday by moving my ''if-statement' within the allstars1.updateStarPosition method. This updates the position of every star before they are re-instantiated in the main function. I think putting the if-statement within the game loop meant that the m_y_star values would keep take that value but not be updated. From what you have pointed out, the code i've written is somewhat inefficient. I'll make these changes and report on the results. \$\endgroup\$
    – The Ace
    Jan 12, 2017 at 12:46
  • \$\begingroup\$ Good solution @The Ace, you get a cleaner main loop, and better object encapsulation. Also consider mapping Stars x and y coordinates to screen coordinates on their initialization. That allows changing the (-0.97, -1) check/snap to that of screen dimensions, saving hundreds of x,y calculations each frame. Plus, it allows for int instead of float or double when translating the star position without worrying about rounding errors using 0.001 increments, which will happen using SDL_RenderDrawPoint which takes ints. I'm glad you solved it, there's no need to report on further results \$\endgroup\$
    – TOM__
    Jan 12, 2017 at 14:37

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .