How to make an image constantly scroll?

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
Post Reply
ccde
Prole
Posts: 15
Joined: Sun Dec 29, 2013 10:47 pm

How to make an image constantly scroll?

Post by ccde »

Hey everyone, I am a bit of a newbie when it comes to Lua and Love2D, and I have decided to try to make a small game with it. I am trying to make an image scroll infinitely over the screen, but I can only get it to scroll once, and then it disappears.

What I want is a starfield that basically flies by constantly giving the illusion that you are flying in game.

Here is the code I have already (main.lua), its quite a bit.

Code: Select all

require "menu"

function love.load()
  --Load the Object

  version =" 0.1.1"
  screenWidth = 800 --Screen Width
  screenHeight = 600 -- Screen Heigth

  gamestate = "menu"

  titleMedium = love.graphics.newFont(45)
  menuBackground = love.graphics.newImage("assets/menu/menuBackground.jpg")
  menuMusic = love.audio.newSource("assets/menu/music.mp3", "static")

  platformImage = love.image.newImageData("assets/background.jpg")
  starImage = love.image.newImageData("assets/star_overlay.png")
  stars = love.graphics.newImage("assets/star_overlay.png")
  player = love.graphics.newImage("assets/player.png")

  startButton = love.graphics.newImage("assets/menu/start.png")
  quitButton = love.graphics.newImage("assets/menu/quit.png")

  love.window.setMode(screenWidth, screenHeight)
  print('setMode Done')
  screenCanvas = love.image.newImageData(screenWidth, screenHeight)
  screenCanvas1 = love.image.newImageData(screenWidth, screenHeight)
  print('Loaded Resources')

  bWidth = platformImage:getWidth()
  bHeight = platformImage:getHeight()

  sWidth = starImage:getWidth()
  sHeight = starImage:getHeight()

  playerSpeed = 15   
  starSpeed = 90

  nStars = 100

  xB = 0
  yB = 0
  xS = 0
  yS = 0
  print('Loaded Variables')

  --Main Menu Buttons
  button_spawn(startButton, 300, 250, "start")
  button_spawn(quitButton, 300,330, "quit")

  love.audio.play(menuMusic)

  if gamestate == "playing" then


  end

  print("Spice Invaders v" .. version .. " loaded.")

end

function love.update(dt)
--Update the Object
  if gamestate == "playing" then

    if love.keyboard.isDown("d") then
      xB = xB + (playerSpeed * dt)
    elseif love.keyboard.isDown("a") then
      xB = xB - (playerSpeed * dt)
    end
    if love.keyboard.isDown("s") then
      yB = yB + (playerSpeed * dt)
    elseif love.keyboard.isDown("w") then
      yB = yB - (playerSpeed * dt)
    end

    -- yS = yS - (starSpeed * dt)   

    screenCanvas:paste(platformImage,0,0,xB,yB)
    --   screenCanvas1:paste(starImage,0,0,xS,yS)
  end
end


function love.draw()
  --Draw the Object
  if gamestate == "playing" then
    love.graphics.setColor(255,255,255)

    finalImage = love.graphics.newImage(screenCanvas)
    --finalImage1 = love.graphics.newImage(screenCanvas1)

    love.graphics.draw(finalImage, -1, -1)
    -- love.graphics.draw(finalImage1, -1, -1)

    love.graphics.print("FPS: "..love.timer.getFPS() .. '\nMem(kB): ' .. math.floor(collectgarbage("count")), 650, 20)
    love.graphics.draw(player, 350, 250)


  end

  if gamestate == "menu" then
    love.graphics.draw(menuBackground, 0, 0)
    button_draw()
    love.graphics.setColor(255, 255, 255)
    love.graphics.print("Music Copyright by: SS Productions", 10, 580)
  end

end

function love.focus(bool)
end

function love.keypressed( key, unicode )

end

function love.keyreleased( key, unicode )
end

function love.mousepressed( x, y, button )

  if gamestate == "menu" then
    button_click(x,y)
  end

end

function love.mousereleased( x, y, button )
end

function love.quit()
end
Does anyone have any ideas on how to do this?

Thanks in advance :)
User avatar
micha
Inner party member
Posts: 1083
Joined: Wed Sep 26, 2012 5:13 pm

Re: How to make an image constantly scroll?

Post by micha »

There are two simple solutions:
First, when the image moves out of the screen, then lets it jump back. For example you have a screen of size 800x600 and the image has exactly the same size. Also you have scrolling only in horizontal direction. Then you need to draw the image twice, because otherwise no the whole screen is covered: If you scroll so that it is at position (-300,0) and at (500,0) you need to draw it once more, or the right part of the screen will be empty. Then for the jumping: Whenever the position of the first image is further to the right than (-800,0) then simply add 800 to the x-coordinate.

Second solution: Use a quad to draw the image and set the Wrap-mode of the image to "Repeat". Change the quad's coordinate each frame, based on the scrolling.
ccde
Prole
Posts: 15
Joined: Sun Dec 29, 2013 10:47 pm

Re: How to make an image constantly scroll?

Post by ccde »

micha wrote:There are two simple solutions:
First, when the image moves out of the screen, then lets it jump back. For example you have a screen of size 800x600 and the image has exactly the same size. Also you have scrolling only in horizontal direction. Then you need to draw the image twice, because otherwise no the whole screen is covered: If you scroll so that it is at position (-300,0) and at (500,0) you need to draw it once more, or the right part of the screen will be empty. Then for the jumping: Whenever the position of the first image is further to the right than (-800,0) then simply add 800 to the x-coordinate.

Second solution: Use a quad to draw the image and set the Wrap-mode of the image to "Repeat". Change the quad's coordinate each frame, based on the scrolling.
The image resolution is 1500 x 3000 though, and I only want it scrolling vertically. As I said before, I am a bit of a newb when it comes to lua/love, so I still don't know much about what I am doing.
AnW
Prole
Posts: 2
Joined: Sat Dec 20, 2014 4:47 pm

Re: How to make an image constantly scroll?

Post by AnW »

Well micha is perfectly right, but thought I'd just demonstrate it this as, incidentally, I did this for a little game I put together earlier this year.

Here is some example code that will do what you want. Well commented, so you can follow.

Code: Select all

--initialization code or whatever

background_image = --whatever image. Also, Image doesn't really matter as the method is the same.
background_y = 0
background_spd = 50 --speed of background scrolling in pixels-per-second

--more stuff...

function love.update(dt)

    --Each update loop we shift our background's y position down the screen (+y direction)
    --by our scroll speed scaled by the delta time to allow for variable framerates.
    background_y = background_y + background_spd * dt

    --We then check whether our y position has left the bottom of the screen.
    --If it has, just reset it.
    --The reason you don't simply reset it to 0 is that it might introduce a "jerk" in the scrolling.
    --Instead, we just subtract the screen height.
    if background_y > love.graphics.getHeight() then
        background_y = background_y - love.graphics.getHeight()
    end

end

function love.draw()

    --As micha said, we need to draw two images to cover the whole screen. 
    --The first is the "main" image, and assuming we are scrolling the background down the screen (+y direction by default), 
    --the second is drawn offset up by the image height to fill in the empty space 
    --that appears above the main image as it scrolls down.
    love.graphics.draw(background_image, 0, background_y) 
    love.graphics.draw(background_image, 0, background_y - background_image:getHeight())

end

If you have any more question's just ask.
ccde
Prole
Posts: 15
Joined: Sun Dec 29, 2013 10:47 pm

Re: How to make an image constantly scroll?

Post by ccde »

AnW wrote:Well micha is perfectly right, but thought I'd just demonstrate it this as, incidentally, I did this for a little game I put together earlier this year.

Here is some example code that will do what you want. Well commented, so you can follow.

Code: Select all

--initialization code or whatever

background_image = --whatever image. Also, Image doesn't really matter as the method is the same.
background_y = 0
background_spd = 50 --speed of background scrolling in pixels-per-second

--more stuff...

function love.update(dt)

    --Each update loop we shift our background's y position down the screen (+y direction)
    --by our scroll speed scaled by the delta time to allow for variable framerates.
    background_y = background_y + background_spd * dt

    --We then check whether our y position has left the bottom of the screen.
    --If it has, just reset it.
    --The reason you don't simply reset it to 0 is that it might introduce a "jerk" in the scrolling.
    --Instead, we just subtract the screen height.
    if background_y > love.graphics.getHeight() then
        background_y = background_y - love.graphics.getHeight()
    end

end

function love.draw()

    --As micha said, we need to draw two images to cover the whole screen. 
    --The first is the "main" image, and assuming we are scrolling the background down the screen (+y direction by default), 
    --the second is drawn offset up by the image height to fill in the empty space 
    --that appears above the main image as it scrolls down.
    love.graphics.draw(background_image, 0, background_y) 
    love.graphics.draw(background_image, 0, background_y - background_image:getHeight())

end

If you have any more question's just ask.
Ahh..thanks so much, it works exactly like I wanted it too. There are a few problems though that might be related to image scrolling. After about 20 to 30 seconds of running the game, the background disappears leaving only the players ship and the stars moving. There is also alot of lag after this. I can't find out what is causing this. I am also getting an issue with tables in my menu.lua class, where it is telling me it is expecting a table and recieving userdata. This is after I modified it a bit, but when I reverted it (the code is now the same as it used to be when it worked) im still getting the errors. I know its not really relevant however I thought I would ask if this was just a bug or not.

Thanks again :)
AnW
Prole
Posts: 2
Joined: Sat Dec 20, 2014 4:47 pm

Re: How to make an image constantly scroll?

Post by AnW »

Well, I'm not really sure what might be going wrong honestly. However, I took a look at the code you posted in your opening post and have a comment.

I noticed that you are using ImageDatas vs Images for the most part and am curious as to why? If I remember right, ImageDatas in Love2d are images on disk that have been decoded and loaded into main memory (RAM), whereas Images are images that have been sent to video ram (VRAM) and made into opengl textures for fast rendering. Essentially, this means that if you are not going to be changing the image, you might as well just use newImage() to load straight into VRAM.

What I'm getting at is that I notice you are pasting the contents of your background ImageData into your 'buffer' ImageData, and then creating a new Image every frame. This involves sending the ImageData contents to VRAM to create a texture every frame as is going to be rather slow. (You'll notice that it mentions this in the wiki: https://www.love2d.org/wiki/love.graphics.newImage) It would be far better to just create an Image and be done with it.

I can't really address the problems you mentioned directly, but I get the feeling it might have to do with you unnecessarily using ImageDatas and creating Images from them to often.
ccde
Prole
Posts: 15
Joined: Sun Dec 29, 2013 10:47 pm

Re: How to make an image constantly scroll?

Post by ccde »

AnW wrote:Well, I'm not really sure what might be going wrong honestly. However, I took a look at the code you posted in your opening post and have a comment.

I noticed that you are using ImageDatas vs Images for the most part and am curious as to why? If I remember right, ImageDatas in Love2d are images on disk that have been decoded and loaded into main memory (RAM), whereas Images are images that have been sent to video ram (VRAM) and made into opengl textures for fast rendering. Essentially, this means that if you are not going to be changing the image, you might as well just use newImage() to load straight into VRAM.

What I'm getting at is that I notice you are pasting the contents of your background ImageData into your 'buffer' ImageData, and then creating a new Image every frame. This involves sending the ImageData contents to VRAM to create a texture every frame as is going to be rather slow. (You'll notice that it mentions this in the wiki: https://www.love2d.org/wiki/love.graphics.newImage) It would be far better to just create an Image and be done with it.

I can't really address the problems you mentioned directly, but I get the feeling it might have to do with you unnecessarily using ImageDatas and creating Images from them to often.
I didn't really notice the difference, and I didn't really know what I was doing so I looked up how to tile something and it was said that I needed to use ImageData although I wasn't too sure why. I will replace then with images.
Post Reply

Who is online

Users browsing this forum: No registered users and 61 guests