1
\$\begingroup\$

I have 15 background images for a 2D horizontal scrolling shooter game and I have been wondering how to insert programmatically those background images in the first level room, as I want them to be displayed one after the other looking as they were one large background image, repeating the last four ones until the boss is defeated.

enter image description here

I have seen that in Game Maker: Studio only 8 background slots are available in each room, so how could I achieve doing what I need here?

\$\endgroup\$
4
\$\begingroup\$

To dynamically scroll through a very large background made up of smaller frames, there are many different solution; the main idea though is quite the same.

The main idea
Think of your fifteen background frames as sort of "panels", which you draw one along the other so that they fit the current view width: if your view is 1280 pixels wide, and each background is 960 pixels wide, then you need at least three backgrounds per time to fit the current view; this looks obvious if one of the "panels" fits within the current view:

enter image description here

Cycling through panels
With this setup, we expect background 1 in the image to disappear as soon as it lies completely out of our view borders; later, when background 3 find itself completely within the view borders, we need to draw the new background 4 following the number 3 seamlessly.

Make it simpler
We can tear down the global complexity of our solution by making some considerations:

  • We can use a fixed number of scrolling panels (backgrounds) as long as they fit the view range, as showed ealier, in number equal to or greater that the minimum required;
  • In GM:S, since we have a limited number of available backgrounds, instead of loosing past backgrounds and allocating new ones (not possible because background indices are fixed in GM:S), we can just shift the background_indexes in a proper way to make the whole bigger background be drawn seamlessly.

All this realizes as follow. First, we draw the first n backgrounds; when the n-th background lies within the view borders, thus we now need to draw the n+1-th background, we shift the n backgrounds back (for example, along the positive direction of x axis) of value n*background_width; finally, we make the n-th background equal to the first - so that it will actually be drawn in the same previous position regarding the room view - and then assign the new backgrounds to the indices to follow.

If we make n = 5, we reach the following:

  • Starting cycle: backgrounds 1 to 5;
  • First iteration: backgrounds 5 to 9;
  • Second iteration: backgrounds 9 to 13;
  • Boss iterations: backgrounds 13, 14, 15, 12, 13

The "boss iteration" will occur through the same backgrounds continuously and seamlessly, thanks to a useful choice of numbers.

Implementation
Have one object to control directly the background movement.

In its Create Event, you assign the backgrounds and their offsets:

// Assign background indices
background_index[0] = bgFrame0;
background_index[1] = bgFrame1;
background_index[2] = bgFrame2;
background_index[3] = bgFrame3;
background_index[4] = bgFrame4;

// Shift backgrounds (otherwise they will be overlapped)
for (var i=1; i<5; i++)               // bkgr0 starts at (0,0)
    background_x[i] += i*bk_width;    // bk_width is the width of single backgrounds

Then, in the Step Event (or similar):

// Update backgrounds' relative positions
for (var i=0; i<5; i++)
    background_x[i] -= 5;                 // an alternative to background_hspeed[]

// Change the backgrounds stack when needed
if (background_x[4]<=0)                   // if the last background lies within the view
{
    for (var i=0; i<5; i++)               // push back all five backgrounds
        background_x[i] += bk_width;      // (maintaining their relative offsets)
    background_index[0] = background_index[4]; // last panel becomes the first one

    // change other backgrounds here
}

Final touch
Where I commented // change other backgrounds here, you can implement a switch statement that changes background_index[1] to background_index[4] upon looking up a counter variable telling you which background cycle to draw (starting, first, second, or boss).

Important thing is, before changing these background_indexes, you must always execute background_index[0] = background_index[4] to make the transition seamless.

\$\endgroup\$
  • \$\begingroup\$ Thank you very much for this. Sadly though it doesn't work for me. It works fine until background[4]'s x reaches 0 (here probably "if (background_x[4]<=0)") and the it changes background[4] abruptly to background[3] and those 2 cycle that way perpetually. I'm trying to find a fix \$\endgroup\$ – konkrz Nov 12 '17 at 19:38
1
\$\begingroup\$

I figured out a workaround. As i posted before, I don't know for sure if the code above works but if it doesn't you can try this one out.It is based on the one above but I also put variables in case you want to change the number of backgrounds. My workaround needs the duplication of the last bg.

Create Event:


bgNum = 6  //The total number of bgs plus 1(the duplicate)

background_index[0] = bg0 //the bg you want to appear LAST
background_index[1] = bg1 //The ACTUAL bg you want to see FIRST
background_index[2] = bg2
background_index[3] = bg3
background_index[4] = bg4

background_index[bgNum-1] = background_index[0] //the duplicate last bg

bk_width = 3840 //my width is double my view's width but you can try your         own

var i;           //fill array

i = bgNum-1;
repeat(bgNum)
   {
   background_x[i] = 0
   i -= 1;
   }

// Shift backgrounds (otherwise they will be overlapped)

for (var i=1; i<bgNum; i++)   // bkgr0 starts at (0,0)
{
background_x[i] += i*bk_width;
}

for (var i=0; i<bgNum; i++) 
{
background_x[i] -= bk_width; //move to the one you want first
}

Step Event:

// Update backgrounds' relative positions

for (var i=0; i<bgNum; i++)
background_x[i] -= key;    // an alternative to background_hspeed[]

//when the last bg reaches 0
if (background_x[bgNum-1]<=-0)  // if the last background lies within the     view

{
for (var i=0; i<bgNum; i++)  //push back all backgrounds so that bg0 replaces
{                                //the last bg which has the same sprite
background_x[i] += bk_width*(bgNum-1); //so the transition is seamless
}
}

Big thanx to liggiorgio who posted the original code it was really helpful and sorry for the poor formating

\$\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.