Is there a way to not clear the screen on update?

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
ItsAaronGeorge
Prole
Posts: 2
Joined: Thu Nov 05, 2015 4:26 am

Is there a way to not clear the screen on update?

Post by ItsAaronGeorge »

I have started reading The Nature of Code and am trying to port the examples from processing.js to love2D.

I've started trying to implement the Random Walker, however the draw function seems to clear the screen every frame, when what I want it to do is to keep the last frame and then draw on top of it.

I was looking at just pushing the new coordinates each frame to an array and then drawing all the coordinates on each frame, but that makes a very large array, very quick.

Does anyone know how to do this?

main.lua

Code: Select all

-- Example I.1: Traditional random walk

-- Set the window title
love.window.setTitle('Example I.1: Traditional random walk')

-- This function is called exactly once at the beginning of the game.
function love.load ()
    theWalker = require('Walker')
    theWalker:init(love.window.getWidth() / 2, love.window.getHeight() / 2, 0, 0, love.window.getWidth(), love.window.getHeight())

end

-- Callback function used to update the state of the game every frame.
function love.update (delta)

    -- Make `theWalker` take a step
    theWalker:step()
end

-- Callback function used to draw on the screen every frame.
function love.draw ()

    -- Draw `theWalker` to the screen
    love.graphics.setColor(255, 255, 255)
    love.graphics.rectangle('fill', theWalker.x, theWalker.y, 1, 1)
end

-- Callback function triggered when a key is pressed.
function love.keypressed (key)

    -- On `escape` quit
    if key == 'escape' then
        love.event.quit()
    end
end
walker.lua

Code: Select all

local Walker = {}

-- Takes in constraints for the walker
function Walker:init (x, y, x1, y1, x2, y2)
    self.x = x
    self.y = y
    self.constraints = {}
    self.constraints.x1 = x1
    self.constraints.y1 = y1
    self.constraints.x2 = x2
    self.constraints.y2 = y2
end

function Walker:step ()

    -- Generate a number between 0 and 3 inclusive
    choice = math.floor(math.random() * 4)

    -- Calulate the movement
    if choice == 0 then
        self.x = self.x + 1
    elseif choice == 1 then
        self.x = self.x - 1
    elseif choice == 2 then
        self.y = self.y + 1
    else
        self.y = self.y - 1
    end

    -- Constrain movement to the window's bounds
    if self.x < self.constraints.x1 then
        self.x = self.constraints.x1
    end

    if self.x > self.constraints.x2 then
        self.x = self.constraints.x2
    end

    if self.y < self.constraints.y1 then
        self.y = self.constraints.y1
    end

    if self.y > self.constraints.y2 then
        self.y = self.constraints.y2
    end
end

return Walker
Thanks for your help.
User avatar
Jasoco
Inner party member
Posts: 3726
Joined: Mon Jun 22, 2009 9:35 am
Location: Pennsylvania, USA
Contact:

Re: Is there a way to not clear the screen on update?

Post by Jasoco »

Without actually using your own modified love.run function, your best bet is to use a canvas. Since you have to clear those manually you can use them like a, well, a canvas that you paint on. With the option of clearing it whenever you want.

That's what I'd suggest. You could even use multiple canvases and draw canvases to canvases. Play around.
ItsAaronGeorge
Prole
Posts: 2
Joined: Thu Nov 05, 2015 4:26 am

Re: Is there a way to not clear the screen on update?

Post by ItsAaronGeorge »

Thanks Jasoco.

I actually just had that idea myself and got it done. I'll post the updated code below incase anyone wants to use it for reference.

main.lua

Code: Select all

-- Example I.1: Traditional random walk

-- Debug
debug = true

-- Set the window title
love.window.setTitle('Example I.1: Traditional random walk')

-- This function is called exactly once at the beginning of the game.
function love.load ()
    theWalker = require('Walker')
    theWalker:init()
end

-- Callback function used to update the state of the game every frame.
function love.update (delta)

    -- Make `theWalker` take a step
    theWalker:step()
end

-- Callback function used to draw on the screen every frame.
function love.draw ()

    -- Draw the walker
    theWalker:draw()
end

-- Callback function triggered when a key is pressed.
function love.keypressed (key)

    -- On `escape` quit
    if key == 'escape' then
        love.event.quit()
    end
end
walker.lua

Code: Select all

local Utils = require('utils')
local Walker = {}

-- Takes in constraints for the walker
function Walker:init (x, y, x1, y1, x2, y2)
    self.x = x or love.window.getWidth() / 2
    self.y = y or love.window.getHeight() / 2
    self.constraints = {}
    self.constraints.x1 = x1 or 0
    self.constraints.y1 = y1 or 0
    self.constraints.x2 = x2 or love.window.getWidth()
    self.constraints.y2 = y2 or love.window.getHeight()
    self.travelled = {}
    self.travelled.x1 = x or love.window.getWidth() / 2
    self.travelled.y1 = y or love.window.getHeight() / 2
    self.travelled.x2 = x or love.window.getWidth() / 2
    self.travelled.y2 = y or love.window.getHeight() / 2
    self.canvas = love.graphics.newCanvas(love.window.getWidth(), love.window.getHeight())
end

-- Make walker take a step
function Walker:step ()

    -- Generate a number between 0 and 3 inclusive
    choice = math.floor(math.random() * 4)

    -- Calulate the movement
    if choice == 0 then
        self.x = self.x + 1
    elseif choice == 1 then
        self.x = self.x - 1
    elseif choice == 2 then
        self.y = self.y + 1
    else
        self.y = self.y - 1
    end

    -- Constrain movement to the window's bounds
    self.x = Utils.constrain(self.x, self.constraints.x1, self.constraints.x2)
    self.y = Utils.constrain(self.y, self.constraints.y1, self.constraints.y2)

    -- Update travelled
    self:updateTravelled(self.x, self.y)
end

-- Update `Walker` constraints
function Walker:updateConstraints (x1, y1, x2, y2)
    self.constraints.x1 = x1
    self.constraints.y1 = y1
    self.constraints.x2 = x2
    self.constraints.y2 = y2
end

-- Update `Walker.travelled` properties
function Walker:updateTravelled (x, y)
    if x < self.travelled.x1 then
        self.travelled.x1 = x
    end

    if x > self.travelled.x2 then
        self.travelled.x2 = x
    end

    if y < self.travelled.y1 then
        self.travelled.y1 = y
    end

    if y > self.travelled.y2 then
        self.travelled.y2 = y
    end
end

-- Draw `Walker`
function Walker:draw ()

    -- If debug
    if debug then

        -- Draw travelled box
        love.graphics.setColor(255, 0, 255)
        love.graphics.rectangle('line', theWalker.travelled.x1, theWalker.travelled.y1, theWalker.travelled.x2 - theWalker.travelled.x1, theWalker.travelled.y2 - theWalker.travelled.y1)
    end

    -- Set the canvas to `self.canvas`
    love.graphics.setCanvas(self.canvas)

    -- Draw `theWalker`'s position to `self.canvas`
    love.graphics.setColor(140, 140, 140)
    love.graphics.rectangle('fill', theWalker.x, theWalker.y, 1, 1)

    -- Set the drawing context back to screen
    love.graphics.setCanvas()

    -- Draw the `self.canvas` to screen
    love.graphics.draw(self.canvas, 0, 0)

    -- If debug
    if debug then

        -- Draw axis lines
        love.graphics.setColor(255, 0, 0)
        love.graphics.rectangle('fill', 0, self.y, love.window.getWidth(), 1)
        love.graphics.rectangle('fill', self.x, 0, 1, love.window.getHeight())
    end

    -- Draw the current location as white colour
    love.graphics.setColor(255, 255, 255)
    love.graphics.rectangle('fill', theWalker.x, theWalker.y, 2, 2)
end

return Walker
utils.lua

Code: Select all

-- Utils
local Utils = {}

-- Constrain
function Utils.constrain (number, min, max)
    if number > max then
        return max
    elseif number < min then
        return min
    else
        return number
    end
end

return Utils
User avatar
vrld
Party member
Posts: 917
Joined: Sun Apr 04, 2010 9:14 pm
Location: Germany
Contact:

Re: Is there a way to not clear the screen on update?

Post by vrld »

There is a quick hack: overwrite love.graphics.clear with an empty function. Put this somwhere in main.lua:

Code: Select all

love.graphics.clear = function() end
I have come here to chew bubblegum and kick ass... and I'm all out of bubblegum.

hump | HC | SUIT | moonshine
User avatar
slime
Solid Snayke
Posts: 3162
Joined: Mon Aug 23, 2010 6:45 am
Location: Nova Scotia, Canada
Contact:

Re: Is there a way to not clear the screen on update?

Post by slime »

vrld wrote:There is a quick hack: overwrite love.graphics.clear with an empty function.
This is hacky in more ways than just preventing love.graphics.clear from functioning – the OS will fill the screen with garbage when certain things happen (e.g. if the window is minimized and then maximized, or if another window is placed in front of the LÖVE window), depending on the operating system. Clearing the screen and redrawing everything is the only way to avoid displaying garbage when that happens.

Using a Canvas completely avoids that issue, of course. ;)
User avatar
vrld
Party member
Posts: 917
Joined: Sun Apr 04, 2010 9:14 pm
Location: Germany
Contact:

Re: Is there a way to not clear the screen on update?

Post by vrld »

Yeah, you should be using canvases if you plan to give the software to other people. Removing the call to love.graphics.clear() from love.run() has, by the way, the same problems that slime pointed out.

But there is a place for hacks like these: explorative programming that you do just for yourself.
I have come here to chew bubblegum and kick ass... and I'm all out of bubblegum.

hump | HC | SUIT | moonshine
Post Reply

Who is online

Users browsing this forum: Google [Bot] and 3 guests