6
\$\begingroup\$

I am new to AndEngine and trying to code a basic sidescroller game using the ParallaxLayer class from this example. (I followed the example and it works.)

How would I display multiple images sequentially? For example, I'd like 3 images (Sun_Stage.png, Moon_Stage.png and Dark_stage.png) to form the scrolling background. (First the background scrolls through Sun_stage.png then when it's finished scroll through Moon_Stage.png, et cetera.)

I basically just want to code a never-ending sidescroller with a changing scrolling background.

\$\endgroup\$
3
\$\begingroup\$

I can't speak to using AndEngine, but the logic for an infinite scrolling backdrop is pretty engine-agnostic. Let's simplify and imagine the case where you are alternating between two images (it doesn't really matter how many you have).

Imagine a number line for x, from zero to infinity. Now imagine that your first image (image 0) is placed on that line such that its left edge (assuming you're scrolling right) is at x = 0. Its right hand edge will then be at x = w0, where w0 is the width of image 0. Then your next image is placed so that its left edge is at x = w0, and its right edge is at x = w0+w1. Then the first image is placed so that its left edge is at x = w0+w1 and its right edge is at x = w0+w1+w0. From the end of the second image on it repeats, and once you know w (the sum of w0 and w1; i.e. the combined width of all the images), you can figure out which image should be where without iteration.

This generalises to a simple function, which can say for any given x, what backdrop to use. That's because the answer for x is the same as x modulus w. You basically get:

function ImageAndOffsetFromPosition(x, out imageIndex, out offsetWithinImage)
{
    offsetFromLeftEdgeOfFirstImage = x % WidthOfAllImages();

    imageLeftEdge = 0;
    for (imageIndex = 0; imageIndex < imageCount; ++imageIndex)
    {
        imageRightEdge = imageLeftEdge + WidthOfImage(imageIndex);

        if ((offsetFromLeftEdge >= imageLeftEdge) && (offsetFromLeftEdge < imageRightEdge)
        {
            offsetWithinImage = offsetFromLeftEdge - imageLeftEdge;
            return;
        }

        imageLeftEdge = imageRightEdge; //Increment this so the next image is placed properly
    }

    //In theory you should never get here, because the position must lie within the range of all of the images
    // (because of the x % WidthOfAllImages() line).
    //In practice, you might get WidthOfAllImages() wrong, or you might ask for 
    // the extreme right edge (x == WidthOfAllImages()).
    //So you should assert if you get to this point in the function.
}

This gives you, for any input position of x, what image should be underneath that position, and how far from the left of the image that position will be.

When you're scrolling to the right, what you're really doing is moving a sliding virtual window along this infinite number-line, so that at any given point in time, your camera is showing the region between x = leftEdge and x = leftEdge + screenWidth.

What you actually need is to know which backdrops are visible given your current camera position, and where they are relative to the screen. So you still need to iterate over the set of images you have, even once you know the starting position.

ImageAndOffsetFromPosition(cameraOffset, out leftmostImageIndex, out offsetWithinImage);

currentLeftEdge = -offsetWithinImage; //Shift the image partly to the left so that the part of it at the left screen edge is offsetWithImage pixels in. NB: this value is in screen relative co-ordinates, so 0 would be the left edge, -ve numbers are offscreen to the left, and +ve numbers are on-screen 
currentImageIndex = leftmostImageIndex;

while (currentLeftEdge < screenWidth)
{
    Draw(currentImageIndex, currentLeftEdge);

    currentImageIndex = (currentImageIndex + 1) % imageCount;
    currentLeftEdge += WidthOfImage(currentImageIndex);
}

The only inputs into this section of code are the screen width and the cameraOffset. As you continually run right, cameraOffset will increase. To begin with, leftmostImageIndex will remain 0, and offsetWithinImage will increase. Once offsetWithinImage reaches the width of the first image it will reset to 0, and leftmostImageIndex will increment. This pattern will repeat until you reach the right-hand edge of the last image in the set, at which point it will start again with 0 and 0. It can increase forever, and the modulus logic will make sure there are always images underneath the camera.

NB: this code will work even if the backdrop images are smaller than one screen in width, because it will loop and draw as many images as it needs to, even if they repeat, until it has moved past the right screen edge. If the backdrop images are larger than the screen width, then this loop will at most go round twice (when the boundary between images is on-screen), and usually only once.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.