Hey guys,
thought, it would be interesting for you: I've made HandmadeHero-like live code reloading. I've seen that there are alreay multiple topics on this, though this one can be done quite simply from scratch. It cannot be used in existing projects (probably) if you are using encapsulation. It requires you to structure the code in data-oriented manner.
The video:
http://youtu.be/WK84Nf1p8W0
The introduction to how it works:
http://martincohen.tumblr.com/post/1121 ... ith-love2d
The main.lua directly from the demo video:
https://gist.github.com/martincohen/27e ... b9c08d45a3
--M.
Live code reloading in Lua
- martincohen
- Prole
- Posts: 23
- Joined: Sat Feb 21, 2015 10:39 am
- Contact:
Re: Live code reloading in Lua
I've been working on something similar as well. I've made it slightly more robust. The biggest problem with what i have is that values doesn't get reset to nil if you removed them from the code and reload.
Say a = 5 is in the program when you start it.
love.graphics.print(a) -- will print 5.
Remove a = 5 . Save file.
love.graphics.print(a) -- will still print 5, "a" should now be "nil".
Close the love program and run again.
love.graphics.print(a) -- will crash because "a" is a "nil" value.
So hidden bugs might occur if you don't restart the program regularly.
A few pluses about the current implementation.
--It creates a "Push" file you can insert values into.
--It uses a protected function call, "pcall" so the program doesn't crash if you write an error. Instead it prints to console.
--Easy resetting of certain values if you don't set it in a function
Super Simple code reloading. Note that I use "love.filesystem.load" instead of "require". "love.filesystem.load" always loads the file.
Say a = 5 is in the program when you start it.
love.graphics.print(a) -- will print 5.
Remove a = 5 . Save file.
love.graphics.print(a) -- will still print 5, "a" should now be "nil".
Close the love program and run again.
love.graphics.print(a) -- will crash because "a" is a "nil" value.
So hidden bugs might occur if you don't restart the program regularly.
A few pluses about the current implementation.
--It creates a "Push" file you can insert values into.
--It uses a protected function call, "pcall" so the program doesn't crash if you write an error. Instead it prints to console.
--Easy resetting of certain values if you don't set it in a function
Code: Select all
--main.lua
-- free values like this gets reset when the file is saved
a = 40
function love.draw( )
--stuff on screen
a = a + 0.1
love.graphics.line(0,a,100,a)
love.graphics.print("apple pie , "..applePIE.." , "..tostring(a))
love.graphics.print(love.filesystem.getLastModified("main.lua"),0,14)
end
function love.timer.sleep() end -- is bugged
function love.update( )
-- loading files should be wraped into functions.
if LastHotModified ~= love.filesystem.getLastModified("main.lua") then
LastHotModified = love.filesystem.getLastModified("main.lua")
ok , hotData = pcall(love.filesystem.load,"main.lua") -- Load program
if ok then
print("Loaded")
ok,err = pcall(hotData) -- Execute program
if not ok then
print("Execute error: "..err)
end
else
print(hotData)
end
end
-- Bellow is a push file so you can insert variables into the program
if LastPushModified ~= love.filesystem.getLastModified("push.lua") then
LastPushModified = love.filesystem.getLastModified("push.lua")
pushData = love.filesystem.load("push.lua")
pushData()
love.filesystem.write("push.lua" , "\n--[["..love.filesystem.read("push.lua"))
print("Load Push")
end
end
function love.keypressed( key )
if key == "o" then
love.system.openURL("file://"..love.filesystem.getSaveDirectory())
end
if key == "l" then
load()
end
if key == "escape" then
love.event.quit()
end
if key == "f" then
forceData = love.filesystem.load("main.lua")
forceData()
end
end
-- A place to store values, Does NOT automaticlly get updated when file is reloaded.
--
function load( )
applePIE = 7
scancode = " "
end
-- What happens below here only execute when the love file is opened
if loadFirst == nil then
loadFirst = 0
load()
love.filesystem.write("push.lua" , "\n--[[ Anything bellow this line will NOT be commented out automatically ]]")
LastPushModified = love.filesystem.getLastModified("push.lua")
end
Code: Select all
--main.lua
function love.update(dt)
mainData = love.filesystem.load("main.lua")
mainData()
end
Artal, A .PSD loader: https://github.com/EvineDev/Artal
- Jasoco
- Inner party member
- Posts: 3727
- Joined: Mon Jun 22, 2009 9:35 am
- Location: Pennsylvania, USA
- Contact:
Re: Live code reloading in Lua
This is shorter:Evine wrote:Code: Select all
--main.lua function love.update(dt) mainData = love.filesystem.load("main.lua") mainData() end
Code: Select all
--main.lua
function love.update(dt)
mainData = love.filesystem.load("main.lua")()
end
- martincohen
- Prole
- Posts: 23
- Joined: Sat Feb 21, 2015 10:39 am
- Contact:
Re: Live code reloading in Lua
Not sure if I understand the problem correctly. So, please, ignore the following if I'm being dense here.
Of course, "my version" is a very basic one, the important part is the data orientation there.
With data-oriented version, you don't want to have any free variables, all the data are always kept in the memory and are kept the same between the reloads. If you want to change the data, then you'll either have to have a support for changing them while the game is running (some kind of a console, or a file, as you suggest) or to simply restart the whole game.
Usually you don't want the game to be running for entire game session (as the data might get really nasty). The idea of having it this way is to help you tune some code while the game is running. Say I'd like to tune a jump code, I want the data be always the same, though I want the functionality to be updated. In HandmadeHero, Casey also did a looping feature. So you can simply record your input to the game (each button pressed/joystick state stored for each frame) and let it be replayed automatically while you are tweaking the code. You can see it here https://www.youtube.com/watch?v=xrUSrVvB21c.
Of course, "my version" is a very basic one, the important part is the data orientation there.
With data-oriented version, you don't want to have any free variables, all the data are always kept in the memory and are kept the same between the reloads. If you want to change the data, then you'll either have to have a support for changing them while the game is running (some kind of a console, or a file, as you suggest) or to simply restart the whole game.
Usually you don't want the game to be running for entire game session (as the data might get really nasty). The idea of having it this way is to help you tune some code while the game is running. Say I'd like to tune a jump code, I want the data be always the same, though I want the functionality to be updated. In HandmadeHero, Casey also did a looping feature. So you can simply record your input to the game (each button pressed/joystick state stored for each frame) and let it be replayed automatically while you are tweaking the code. You can see it here https://www.youtube.com/watch?v=xrUSrVvB21c.
<3
Re: Live code reloading in Lua
I'm also watching Handhero. And I don't plan to implement a looping feature similar to what Casey implemented. I'm not convinced it's really that super useful for anything, a slight time saver if anything.
The purpose of the "free variables" is to reset certain variables each time the code is reloaded. Can also be trigger from within the game. Ex: Resetting player and boss health when you're testing the boss. Or resetting the player position when you have a poorly implemented collision detection in a platformer. Or testing AI code where you want to see how the AI handles certain situations.
The purpose of the "free variables" is to reset certain variables each time the code is reloaded. Can also be trigger from within the game. Ex: Resetting player and boss health when you're testing the boss. Or resetting the player position when you have a poorly implemented collision detection in a platformer. Or testing AI code where you want to see how the AI handles certain situations.
Well... Why not. I'd like to have the opportunity. It's possible with what I have now if I'm careful to set values to nil if I remove them from the code.martincohen wrote:Usually you don't want the game to be running for entire game session (as the data might get really nasty).
Fancy syntax tricks I didn't know of. You don't even have to assign it to a variable now. It's nigh unreadable to anyone reading a slight messy codebase. I'd much rather do it like this.Jasoco wrote: This is shorter:Code: Select all
--main.lua function love.update(dt) love.filesystem.load("main.lua") () -- EVEN SHORTER end
Code: Select all
--main.lua
function love.update(dt)
love.filesystem.loadRun("main.lua") -- Much more readable
end
function love.filesystem.loadRun(filename)
love.filesystem.load(filename) ()
end
Artal, A .PSD loader: https://github.com/EvineDev/Artal
Re: Live code reloading in Lua
My apologies, that was rude and unnecessary.
Who is online
Users browsing this forum: Ahrefs [Bot] and 5 guests