Build an Endless Runner Game From Scratch: Background Motion

Build an Endless Runner Game From Scratch: Background Motion

Tutorial Details
  • Technology: Corona SDK
  • Difficulty: Beginner
  • Completion Time: 1 Hour
This entry is part 2 of 10 in the series Build an Endless Runner Game From Scratch

Welcome to the second tutorial in our series on building a running-game from scratch with the Corona SDK. In this section, we are going to go over how to quickly get a basic background-scrolling level up and running. Open your text editor and let’s get started!


Prerequisites

If you haven’t already seen the first tutorial in this series, check it out really quickly before moving on to this one. If you have a little bit of experience coding, then you will be fine skipping quickly through the entire first tut, but if you haven’t, then it should be worth your time to look at some of the basics of programming working with Lua and the Corona SDK.


Project Setup

So the first thing that we need to cover is the build.settings file. This is a file that needs to go in the same folder as the main.lua file, and is what we use to set some of our application specifications. Now, depending on what platform you are working with (Android or iOS), your build.settings file will be used to set different things. For example, Android developers have to deal with their applications manifest file and their permissions, while iOS developers have their *.plist file to worry about. The build.settings file is where a lot of those application level settings will be handled. One of the nice things about the Corona SDK is that we are able to combine our Android and iOS build.settings information into the same build.settings file. This way, if you are working on both types of devices, you don’t have to manage multiple build.settings files. For our purposes right now we are only going to be using the build.settings file for setting our device orientation. So, make a new file called build.settings in the same folder that you are going to have your main.lua file and put this code into it:

--Notice you can use comments in this section as well
settings = {
orientation = {
default = "landscapeRight",
supported = {
"landscapeRight", "landscapeLeft"
},
},
}

This gives us a landscape oriented device on both iOS and Android devices. The code is fairly straight forward and we will go over more settings that you will want to use in future tutorials, but for now this should be all we need to move forward. If you want to dig deeper on your own, you can find all of the build.settings options here. To make sure that the file worked, let’s do a quick test in the simulator. Open up your main.lua file and put this code in there:

--This line will remove the status bar at the top of screen,
--some apps you might want to keep it in, but not for games!
display.setStatusBar(display.HiddenStatusBar)
local testRect = display.newRect(0,0,50,50)
testRect:setFillColor(150,0,0);

So, after putting all of that together, if your build.settings is in the correct place you should have something that looks like this:

Landscape Orientation

If the device is upright(portrait mode), and not laying on its side like above (landscape mode), then something has gone wrong. However, hopefully that is not the case as the code above is all there is to it. So, now that that is out of the way we can move on to getting our game up and running. The goal for each of the tutorials is for us to have a new working section. Each will build on the last, but after every iteration you will have something that should be playable.


Adding a background

The first thing we are going to want to do is to get our level moving. We are going to have several layers in our game that are going to be scrolling at different levels of speed. This is going to give us the illusion of what we like to call parallax scrolling. When you are running the program in the simulator go ahead and select iPhone for now (if you haven’t already done so). Change this by going to Window > View As > iPhone in the simulator. The assets have been designed for a device running at a resolution of 480x320px. There are, of course, ways to make sure it works for all resolutions, but for our testing purposes now just stick with the iPhone simulator. Go ahead and put this code in your program:

--takes away the display bar at the top of the screen
display.setStatusBar(display.HiddenStatusBar)
--adds an image to our game centered at x and y coordinates
local backbackground = display.newImage("images/background.png")
backbackground.x = 240
backbackground.y = 160
local backgroundfar = display.newImage("images/bgfar1.png")
backgroundfar.x = 480
backgroundfar.y = 160

For this to work go ahead and use the images I provided. In order for the code to work ‘as is’, you will need to place the images in a folder called images. The images folder should be in the same folder as your main.lua and build.settings file. Once you do that you should get a screen that looks like this:

Notice how the backgroundfar image is in front of backbackground? Imagine stacking several plates on top of each other. The more you stack on, the more you have covering that first plate you stacked everything on to begin with. This is also true with images and text that you put in your code. Everytime you want to add something to the screen, unless directed otherwise, that added element will cover everything you have already stacked on. Let’s go ahead and stack a few more things on to our screen. Add this to your code below the other lines:

local backgroundnear1 = display.newImage("images/bgnear2.png")
backgroundnear1.x = 240
backgroundnear1.y = 160
local backgroundnear2 = display.newImage("images/bgnear2.png")
backgroundnear2.x = 760
backgroundnear2.y = 160

Now, we should have another layer stacked on top like so:

Now, when you look at this you are going to notice that even though we added 2 instances of bgnear2.png, only one of them shows up on the screen. The reason we do things this will become a bit more obvious when we start moving everything around. For now, go ahead and switch your view from iPhone to iPhone 4 the same way we did before. Because we designed our images around the resolution of a non-retina iPhone (e.g. 480x320px), if we switch to a higher resolution such as the iPhone 4 (e.g. 960x640px), everything shrinks down and we can see more of what is going on. Change to the iPhone 4 resolution and you should see this now:

Whenever we want to see what is going on, switching to the larger view will be very helpful. Notice that just because you can’t see something, doesn’t mean that nothing is happening. Now that we have those background images on there let’s make them move. As I go through the tutorials, I will try to document everything that is happening inside of the code itself, so if you ever aren’t sure about what something does be sure to read the comments in the code! Now, below the code added previously add this:

--the update function will control most everything that happens in our game
--this will be called every frame(30 frames per second in our case, which is the Corona SDK default)
local function update( event )
--updateBackgrounds will call a function made specifically to handle the background movement
updateBackgrounds()
end
function updateBackgrounds()
--far background movement
backgroundfar.x = backgroundfar.x - (.25)
--near background movement
backgroundnear1.x = backgroundnear1.x - (3)
--if the sprite has moved off the screen move it back to the
--other side so it will move back on
if(backgroundnear1.x < -239) then
backgroundnear1.x = 760
end
backgroundnear2.x = backgroundnear2.x - (3)
if(backgroundnear2.x < -239) then
backgroundnear2.x = 760
end
end
--this is how we call the update function, make sure that this line comes after the
--actual function or it will not be able to find it
--timer.performWithDelay(how often it will run in milliseconds, function to call,
--how many times to call(-1 means forever))
timer.performWithDelay(1, update, -1)

When you run this run it first while still in the iPhone 4 view. This will let you see what is actually happening with all of the different sprites that we are moving around. Once you have looked at it in this view go ahead and switch back to the normal iPhone view so you can see what it really looks like. With all of that in there you should now have everything moving! Now a couple things to look at before we move on. Notice how there is only one instance of backgroundfar, but there are two instances of backgroundnear? This is something that is completely up to you. The reason there is two there is because for the closer background (e.g. trees flying by), we want that to repeat over and over again. For the far background, I wanted it to be something that will pass by very slowly and not repeat itself (e.g. you will usually only do this for backgrounds that are far back, it gives levels a unique feel). This is something you would do when your scrolling level is going to have an end to it. If you really wanted a never ending scroller, you would want to take the same approach that you did for the near background and put two side by side. By placing two side by side, or three, or however many you want, it let’s you create seemingly large worlds with very minimal assets. The only thing we have to do is move the sprite back to the other side of the screen.

The next thing we are going to do is add the ground. This is going to take a couple more steps, but we will go slow and make sure everything gets put in the right place. If you didn’t do the first tutorial and don’t understand how to use groups or understand what they are, now would be a good time to check it out. Here is the code to plop in (put it right underneath the code where we setup backgroundnear2, before the update function):

--create a new group to hold all of our blocks
local blocks = display.newGroup()
--setup some variables that we will use to position the ground
local groundMin = 420
local groundMax = 340
local groundLevel = groundMin
--this for loop will generate all of your ground pieces, we are going to
--make 8 in all.
for a = 1, 8, 1 do
isDone = false
--get a random number between 1 and 2, this is what we will use to decide which
--texture to use for our ground sprites. Doing this will give us random ground
--pieces so it seems like the ground goes on forever. You can have as many different
--textures as you want. The more you have the more random it will be, just remember to
--up the number in math.random(x) to however many textures you have.
numGen = math.random(2)
local newBlock
print (numGen)
if(numGen == 1 and isDone == false) then
newBlock = display.newImage("images/ground1.png")
isDone = true
end
if(numGen == 2 and isDone == false) then
newBlock = display.newImage("images/ground2.png")
isDone = true
end
--now that we have the right image for the block we are going
--to give it some member variables that will help us keep track
--of each block as well as position them where we want them.
newBlock.name = ("block" .. a)
newBlock.id = a
--because a is a variable that is being changed each run we can assign
--values to the block based on a. In this case we want the x position to
--be positioned the width of a block apart.
newBlock.x = (a * 79) - 79
newBlock.y = groundLevel
blocks:insert(newBlock)
end

The comments in the code should help you understand what everything does so far. Hopefully, what you are looking at now looks something like this:

Forth Background

Now, the last thing that we need to do is start to get the blocks moving. Let’s go ahead and add the code for that. Put this code in after the end of the update function:

function updateBlocks()
for a = 1, blocks.numChildren, 1 do
if(a > 1) then
newX = (blocks[a - 1]).x + 79
else
newX = (blocks[8]).x + 79
end
if((blocks[a]).x < -40) then
(blocks[a]).x, (blocks[a]).y = newX, groundLevel
else
(blocks[a]):translate(-5, 0)
end
end
end

Before anything will actually move, we need to be sure that we actually call the function from the update function. So, inside of the update function below the updateBackgrounds() line, call the function updateBlocks(). With that in there we should have everything moving now. Notice that instead of manually moving the blocks we instead used the translate function. This function is available to any object we create via the newImage call. Either method will work, so use one or the other, or use a mixture. Another thing that you should be noticing is that there is a gap in between some of the blocks. This happens because we are setting the location of the new blocks right next to the old location of the last block. The problem is that when we do it this way, we are trying to place it next to a moving object, so we might not always hit right next to it. This problem will become even bigger once we try to increase the traveling speed of the blocks, the faster they are moving the larger that gap will become. This problem can be overcome by simply adding a speed variable and doing our calculations based on that speed. Go back up to the lines of code where we initialized the variables groundMin and groundMax, and add this:

local speed = 5;

Next, replace the updateBlocks() and updateBackgrounds() functions with these:

function updateBlocks()
for a = 1, blocks.numChildren, 1 do
if(a > 1) then
newX = (blocks[a - 1]).x + 79
else
newX = (blocks[8]).x + 79 - speed
end
if((blocks[a]).x < -40) then
(blocks[a]).x, (blocks[a]).y = newX, (blocks[a]).y
else
(blocks[a]):translate(speed * -1, 0)
end
end
end
function updateBackgrounds()
--far background movement
backgroundfar.x = backgroundfar.x - (speed/55)
--near background movement
backgroundnear1.x = backgroundnear1.x - (speed/5)
if(backgroundnear1.x < -239) then
backgroundnear1.x = 760
end
backgroundnear2.x = backgroundnear2.x - (speed/5)
if(backgroundnear2.x < -239) then
backgroundnear2.x = 760
end
end

With those updated functions, your blocks should be moving nicely with no gaps at all!

One last thing to make this more game-like. Go back in the update function and put in this line of code after the update functions:

speed = speed + .05

Once that is in there you will be able to watch the level speed up before your eyes! The exact value of course is just an example, how fast you update the game will depend on your game and your audience. All that is left at this point is throwing in a hero and some obstacles and we have ourselves a game. That will come later though, as this wraps up the project for now. Getting all of that running was not so bad, and we will continue to add lots of functionality each iteration. Be sure to check back for the next tutorial, and if you have any questions or feedback let me know in the comments below!

Series Navigation«Corona SDK: Build an Endless Runner Game From Scratch!Build an Endless Runner Game From Scratch: Using Sprites»

Note: Want to add some source code? Type <pre><code> before it and </code></pre> after it. Find out more
  • Matt

    Another great tutorial! I can’t wait for the next one! :)

  • Ian

    When I complete the…

    local function update( event )
    updateBackgrounds()
    end

    .. section, I can’t get anything moving on my simulator. It’s driving me crazy. I went through it 3 times, even completely copied and pasted once and still can’t get the backgrounds moving. I can get them showing on the screen though. I only have Corona for Android, do you think it’s the screen resolution or something?

    • Tyler King
      Author

      Hey Ian sorry you are having troubles getting things moving. The problem shouldn’t be with android because it should all be platform independent at this point, also resolutions shouldn’t be a factor in things moving. A couple questions and suggestions:

      1) It sounds like the update function is not being called, did you by chance remove the timer that calls it while you were copying the code over?

      2) Are you getting any errors in the terminal? If there are any problems with the code an error will pop up there when you try to run it. The error will give you the exact line in your code that the problem exists.

      3) You say you tried copying and pasting everything and it didn’t work, did you try actually downloading the files and seeing if that works? If not give that a try first just to make sure there aren’t any small differences you might be missing.

      4) If 1, 2, and 3 still aren’t doing anything for you add print statements between significant lines of code to make sure that all of the lines of code are being called properly. For example the first print statements I would add would be in the update function. I would make my update function look something like this:

      local function update( event )
      print(“check 1″)
      updateBackgrounds()
      print(“check 2″)
      end

      Run it and look in your terminal. If update is running properly you should see check 1 and check 2 being printed over and over. If not then you know the problem is there. If that does work I would do the same thing inside of updateBackgrounds until you find a print statement that doesn’t show up correctly. Also be sure to add updateBlocks() to the update function. Let me know how it goes and thanks for reading!

  • N

    great tutorial! can’t wait for the next one =)))))))))))))))))))))

  • Matt

    Hi Tyler,

    The tutorial is great! I just have one question…

    I followed the tutorial and have my images moving on the screen. However, my images have a gap and as the speed of the game increases, so does the gap. I know you touched on this in the tutorial with the updateBlocks() function but I thought that only dealt with your ground images and getting those moving? I’m treating my ground images the same way as my background images so I didn’t think that was something I needed to use to make that gap disappear.

    Do I need to use the updateBlocks() function to make that gap disappear? Everything appears to be working just fine aside from the gap.

    Thanks for the great tutorials, I look forward to the next one!

    Matt

    • Tyler King
      Author

      Hey Matt glad you liked it and thanks for reading!

      The last section of code in the tutorial has new updateBlocks() and updateBackgrounds() functions that remove that gap.

      The “gap problem” is because you are trying to place an image next a moving image. So the faster that image is moving the larger the gap is going to be because the image has traveled further by them time we actually try to move the image next to it.

      So when you look at your code, you need to be sure that you are updating the position of the image you are moving by not only the location of the image you are moving it next to, but by the current speed as well. Update your code to do that(Should look something like this: (blocks[a]):translate(speed * -1, 0)) and you should be good to go. Let me know if you have any other questions about getting that going!

      • Matt

        Hi Tyler,

        Thanks for responding. I’m still not entirely sure what I’m doing wrong. I added the updateBlocks() function to my code and I still have a gap in my images. I’m still not sure that I have everything in the right places. I’m looking through my code and it all “seems” good, but I know there must be something wrong. My code essentially looks exactly like yours, aside from the fact that I don’t need any of the code you have for your ground images (as far as randomizing, etc.), my ground images are the same thing as my backgroundnear images (where I’m repeating two images over and over). Here’s my code…maybe you can see something that’s sticking out that I’m doing wrong. Thanks for the help!

        – Setup Application Parameters and Hide Status Bar
        width = display.contentWidth
        height = display.contentHeight
        display.setStatusBar(display.HiddenStatusBar)

        – Declare Variables
        local background, fog
        local backMountains1, backMountains2
        local frontMountains1, frontMountains2
        local dirt1, dirt2

        – Background Image
        local background = display.newImage(“Images/background.png”)
        background.x = width / 2
        background.y = height / 2

        – Back Mountain Images
        local backMountains1 = display.newImageRect(“Images/back-mountains.png”, 1920, 241)
        backMountains1:setReferencePoint(display.BottomLeftReferencePoint)
        backMountains1.x = 0
        backMountains1.y = 280

        local backMountains2 = display.newImageRect(“Images/back-mountains.png”, 1920, 241)
        backMountains2:setReferencePoint(display.BottomLeftReferencePoint)
        backMountains2.x = 1920
        backMountains2.y = 280

        – Fog Image
        local fog = display.newImage(“Images/fog.png”)
        fog.x = width / 2
        fog.y = height / 2

        – Front Mountain Images
        local frontMountains1 = display.newImageRect(“Images/front-mountains.png”, 1895, 166)
        frontMountains1:setReferencePoint(display.BottomLeftReferencePoint)
        frontMountains1.x = 0
        frontMountains1.y = 320

        local frontMountains2 = display.newImageRect(“Images/front-mountains.png”, 1895, 166)
        frontMountains2:setReferencePoint(display.BottomLeftReferencePoint)
        frontMountains2.x = 1895
        frontMountains2.y = 320

        – Dirt Images
        local dirt1 = display.newImageRect(“Images/dirt.png”, 1920, 60)
        dirt1:setReferencePoint(display.BottomLeftReferencePoint)
        dirt1.x = 0
        dirt1.y = 335

        local dirt2 = display.newImageRect(“Images/dirt.png”, 1920, 60)
        dirt2:setReferencePoint(display.BottomLeftReferencePoint)
        dirt2.x = 1920
        dirt2.y = 335

        – A Group to hold all of your blocks
        local blocks = display.newGroup()

        local speed = 5

        – This function will update the backgrounds at 30fps
        local function update (event)
        updateBackgrounds()
        updateBlocks()
        speed = speed + .05
        end

        function updateBlocks()
        for a = 1, blocks.numChildren, 1 do

        if(a > 1) then
        newX = (blocks[a - 1]).x + 79
        else
        newX = (blocks[8]).x + 79 – speed
        end

        if((blocks[a]).x < -40) then
        (blocks[a]).x, (blocks[a]).y = newX, (blocks[a]).y
        else
        (blocks[a]):translate(speed * -1, 0)
        end

        end
        end

        – Movement for the Back Mountains, Front Mountains & Dirt
        – By Doubling the images, they will repeat forever
        function updateBackgrounds()

        backMountains1.x = backMountains1.x – (speed/50)
        if (backMountains1.x < -1919) then
        backMountains1.x = 1920
        end

        backMountains2.x = backMountains2.x – (speed/50)
        if (backMountains2.x < -1919) then
        backMountains2.x = 1920
        end

        frontMountains1.x = frontMountains1.x – (speed/4)
        if (frontMountains1.x < -1894) then
        frontMountains1.x = 1895
        end

        frontMountains2.x = frontMountains2.x – (speed/4)
        if (frontMountains2.x < -1894) then
        frontMountains2.x = 1895
        end

        dirt1.x = dirt1.x – (speed/2)
        if (dirt1.x < -1919) then
        dirt1.x = 1920
        end

        dirt2.x = dirt2.x – (speed/2)
        if (dirt2.x < -1919) then
        dirt2.x = 1920
        end

        end

        timer.performWithDelay(1, update, -1)

  • Tyler King
    Author

    @Mark I can see what the problem is. I may need to clarify this in the actual tutorial. The reason why we are able to do the updateBackgrounds() method like that(manually set a new x position) is because of how they are designed. While they are right next to each other it isn’t like there is a need for there to be a smooth path. This works well in games like Canabalt(http://www.adamatomic.com/canabalt/), where there are platforms not needing to be exactly next to each other(This is why we can do our trees like that). So right now you are giving your dirt1.x and dirt2.x exact positions. Instead try changing it to how we handle the blocks in the sample code.

    Instead of having this:

    if (dirt1.x < -1919) then
    dirt1.x = 1920
    end

    Try changing it to something like:

    if (dirt1.x < -1919) then
    dirt1.x = dirt2.x + dirt2.width
    end

    where dirt2.width is the width of dirt2 in pixels. You may need to make small adjustments to those numbers, for example my blocks.width is 80. I found that by changing that 79 it would put the blocks exactly right next to each other. Because I have a set of 8 blocks I cycle through all of them doing this. However, I noticed that when it would reach the last block and restart with the first one there would still be a small gap between the last and the first blocks. That is why I update that block by the speed as well, it compensates for how fast the blocks are moving.

    Because you only have 2 blocks you might not have to worry about that. So to fix your blocks start by making the above change to your code(Do the same for dirt2), if you are still seeing a small gap after making those changes then try adjusting it by the speed as well(I imagine you will need to do this as well. If that is the case you code might look something like:

    if (dirt1.x < -1919) then
    dirt1.x = dirt2.x + dirt2.width + speed
    end

    Let me know how that goes!

  • Matt

    Hi Tyler,

    Thanks for the info on using the “.width”. That fixed the problem I was having! No more gaps!

    Thanks again!

    • Tyler King
      Author

      No problem I’m glad it is working now!

  • James

    Hi Tyler,

    In the Corona simulator – I’ve run your code. I haven’t changed anything but I’m not getting what you are getting in your screen shots.

    It seems the simulator when I run it has automatically scaled backgroundfar image (down to 480 to 320). How do I make it display at its native resolution?

    I can get the same image you get when running iPhone 4 simulator but not iPhone simulator.

    • James

      Hi Tyler,

      i added true and this seemed to fix this.

      local backgroundfar = display.newImage(“images/bgfar1.png”, true)

      can u explain what’s going on? I sort of get it but don’t fully get it.

      Thanks.

  • James

    So anything bigger than 480×320 needs true added on?

    • Tyler King
      Author

      Hey James thanks for the question and you pretty much nailed it head on. Corona SDK will auto scale large images automatically, unless you include the true at the end. The official format for display.newImage is as follows:

      display.newImage( [parentGroup,] filename [, baseDirectory] [, x, y] [,isFullResolution] )

      So that last true is telling the object to not auto-scale. The reason why it is working a little bit different on mine compared to yours could be a number of things. Which OS are developing on and which revision of Corona SDK are you using?

      Either way the best practice would be to use ‘true’ for the isFullResolution.

  • http://alejandro.im Alejandro

    If i want that my app function in iPhone 4 and iPad 2, how i do for set the multiples resolutions of the background and other elements ? Thanks and sorry for my bad english.

  • El Perro

    I copy-pasted everything here, but it doesn’t work, there seems to be a problem with the UpdateBlocks() it’s really weird, casue I’m COPY-PASTING all of this!

    Can you help me out, please!?

    —————————————————————————————–

    – main.lua

    —————————————————————————————–

    – Your code here

    display.setStatusBar(display.HiddenStatusBar)
    local backbackground=display.newImage(“background.png”)
    backbackground.x=240
    backbackground.y=160

    local backgroundfar=display.newImage(“bgfar1.png”)
    backgroundfar.x=480
    backgroundfar.y=160
    local backgroundnear1 = display.newImage(“bgnear2.png”)
    backgroundnear1.x = 240
    backgroundnear1.y = 160
    local backgroundnear2 = display.newImage(“bgnear2.png”)
    backgroundnear2.x = 760
    backgroundnear2.y = 160

    —Controla
    –the update function will control most everything that happens in our game
    –this will be called every frame(30 frames per second in our case, which is the Corona SDK default)
    local function update( event )
    –updateBackgrounds will call a function made specifically to handle the background movement

    –updateBlocks()

    updateBackgrounds()

    end

    function updateBackgrounds()
    –far background movement
    backgroundfar.x = backgroundfar.x – (.25)

    –near background movement
    backgroundnear1.x = backgroundnear1.x – (3)
    –if the sprite has moved off the screen move it back to the
    –other side so it will move back on
    if(backgroundnear1.x < -239) then
    backgroundnear1.x = 760
    end

    backgroundnear2.x = backgroundnear2.x – (3)
    if(backgroundnear2.x 1) then
    newX = (blocks[a - 1]).x + 79
    else
    newX = (blocks[8]).x + 79 – speed
    end

    if((blocks[a]).x < -40) then
    (blocks[a]).x, (blocks[a]).y = newX, (blocks[a]).y
    else
    (blocks[a]):translate(speed * -1, 0)
    end

    end
    end

  • Sam

    I am stuck on building setting’s. I am doing everything right but i am still having my device upright. I copied and pasted the code 5 time’s still nothing.

    • yosi

      that is the same problem i had… kinda wierd and funny cause i realized i saved the build.settings as a lua file. but the file should just be saved as build.setting.

  • Alex

    Hey – I have some more suggestions for your code…

    Instead of using

    timer.performWithDelay(1, update, -1)

    Look at the example ‘Fishies’ project provided with Corona SDK. Instead of executing your function 1000 times per second (very inefficient), you should execute it based on the frame-rate of the app. This will be much more efficient. Your app would probably look just fine at 30fps. That’s 33x more efficient. This will give you more CPU power to do more interesting things with your game.

    Instead of using “isDone”, you should just use an elseif construct.

    Instead of moving every block (inefficient), you could add them to a group and animate that. You could use two groups the width of the screen like your foreground images do. Just animate the position of the group and you won’t have any gaps between your blocks. Of course, you’ll need to get your math correct to not have gaps between your groups either but if you update based on frame-rate you shouldn’t have any issues and they’ll both move (very efficiently) together. Of course – your logic will get a little more tricks for positions of the blocks but I’d think it’s well worth it.

  • Pablo

    Amazing tutorial, thank you very much, you really changed my life, seriously. I’m engineer and also I make music for videogames. I’m starting programing this kind of games and this tutorial is perfect. If anytime you need music for your videogames or sound designers just contact me!

    • http://www.facebook.com/pargatd Pargat Dhillon

      Hey contact me at work@pargatdhillon.com , need sfx/music done for my apps