Best practices and things you'd like changed about Love2D

General discussion about LÖVE, Lua, game development, puns, and unicorns.
User avatar
Gunroar:Cannon()
Party member
Posts: 1142
Joined: Thu Dec 10, 2020 1:57 am

Re: Best practices and things you'd like changed about Love2D

Post by Gunroar:Cannon() »

pgimeno wrote: Sat Jun 05, 2021 12:54 am Edit: never mind
Y'know, these your "Edit: never mind"s really annoy me :brows: :rofl:
The risk I took was calculated,
but man, am I bad at math.

-How to be saved and born again :huh:
User avatar
Gunroar:Cannon()
Party member
Posts: 1142
Joined: Thu Dec 10, 2020 1:57 am

Re: Best practices and things you'd like changed about Love2D

Post by Gunroar:Cannon() »

Xii wrote: Sat Jun 05, 2021 12:02 am
That doesn't tell you the key was pressed right now. It just tells you the key was pressed sometime in the past and is still held down. It will be true for every frame until the key is released, not just the first frame after it has been pressed.
Okay, I see. Thnx for the info.
pgimeno wrote: Sat Jun 05, 2021 12:54 am Edit: never mind
Y'know, these your "Edit: never mind"s really annoy me :brows: :rofl:
The risk I took was calculated,
but man, am I bad at math.

-How to be saved and born again :huh:
User avatar
Gunroar:Cannon()
Party member
Posts: 1142
Joined: Thu Dec 10, 2020 1:57 am

Re: Best practices and things you'd like changed about Love2D

Post by Gunroar:Cannon() »

Xii wrote: Sat Jun 05, 2021 12:02 am
That doesn't tell you the key was pressed right now. It just tells you the key was pressed sometime in the past and is still held down. It will be true for every frame until the key is released, not just the first frame after it has been pressed.
Okay, I see. Thnx for the info.
pgimeno wrote: Sat Jun 05, 2021 12:54 am Edit: never mind
Y'know, these your "Edit: never mind"s really annoy me :brows: :rofl:
The risk I took was calculated,
but man, am I bad at math.

-How to be saved and born again :huh:
User avatar
pgimeno
Party member
Posts: 3656
Joined: Sun Oct 18, 2015 2:58 pm

Re: Best practices and things you'd like changed about Love2D

Post by pgimeno »

I posted an opinion but changed my mind. The forum doesn't allow deleting posts, so that's all I can do. It was about Xii's complaint about lack of edge detection for keys; I said it was no big deal, as I don't think it's a frequent use case, but then this whole thread is about opinions, so it felt out of place.

Here's a complete example of how to implement what he was requesting. It may feel hacky to use love.draw, but I believe that's more stable across versions than modifying love.run, which is prone to change. love.draw is the last user code executed before events are read, so adding it at the end of love.draw guarantees that the keys are stored before the next events come.

Code: Select all

local oldlevels = {}
local newlevels = {}

function love.keypressed(k, s)
  newlevels[s] = true
end

function love.keyreleased(k, s)
  newlevels[s] = false
end

local function justPressed(key)
  return newlevels[key] and not oldlevels[key]
end

local function justReleased(key)
  return oldlevels[key] and not newlevels[key]
end

function love.draw()
  if justPressed("space") then
    love.graphics.clear(255, 255, 255)
  end
  love.graphics.print("Press space to flash")

  for k, v in pairs(newlevels) do
    oldlevels[k] = v
  end
end
If you know that you're reading each key always and only once, i.e. calling justPressed exactly once per frame for each key, and don't care about missing a press and a release in the same frame, there's a shortcut that doesn't need you to hook the events:

Code: Select all

local edges = {}
local function justPressed(k)
  local old = edges[k]
  edges[k] = love.keyboard.isScancodeDown(k)
  return edges[k] and not old
end
User avatar
Gunroar:Cannon()
Party member
Posts: 1142
Joined: Thu Dec 10, 2020 1:57 am

Re: Best practices and things you'd like changed about Love2D

Post by Gunroar:Cannon() »

Yeeeessshhhhhh, I just saw how much I double posted. Sorry about that. When I pressed submit I didn't see it was on the second page so I thought it didn't go, then pasted what I typed(I always copy it so in case something bad happens I don't have to retype) and submitted again...twice.
pgimeno wrote: Sat Jun 05, 2021 11:06 am I posted an opinion but changed my mind. The forum doesn't allow deleting posts, so that's all I can do. It was about Xii's complaint about lack of edge detection for keys; I said it was no big deal, as I don't think it's a frequent use case, but then this whole thread is about opinions, so it felt out of place.
Okay, sorry, it's just that it pokes my curiosity and feels incomplete, plus you did it last time but didn't see when I asked you what you said. :ultrahappy:. I don't know, maybe you could put the edit at the bottom of the original post so people(read: me) knows what you're talking about. But your way is still okay, I guess.
The risk I took was calculated,
but man, am I bad at math.

-How to be saved and born again :huh:
grump
Party member
Posts: 947
Joined: Sat Jul 22, 2017 7:43 pm

Re: Best practices and things you'd like changed about Love2D

Post by grump »

pgimeno wrote: Sat Jun 05, 2021 11:06 am love.draw is the last user code executed before events are read, so adding it at the end of love.draw guarantees that the keys are stored before the next events come.
framestart and/or frameend events would be nice to have. Doing this stuff in love.update between input and output is often wrong, doing it at the end of love.draw feels dirty, and a custom love.run is not really an option for libraries.

A number of game state libraries people have posted here don't even care and switch between menu and game in love.update. One or two lines of code in the default love.run would make these things so much easier.
User avatar
pgimeno
Party member
Posts: 3656
Joined: Sun Oct 18, 2015 2:58 pm

Re: Best practices and things you'd like changed about Love2D

Post by pgimeno »

grump wrote: Sat Jun 05, 2021 12:29 pm framestart and/or frameend events would be nice to have. Doing this stuff in love.update between input and output is often wrong, doing it at the end of love.draw feels dirty, and a custom love.run is not really an option for libraries.

A number of game state libraries people have posted here don't even care and switch between menu and game in love.update. One or two lines of code in the default love.run would make these things so much easier.
+1. The best currently available workaround is to monkey-patch love.event.pollpump and love.graphics.present (or just the latter if you don't care about the first frame).

Also, it would be nice if love.handlers.update()/draw() was defined and called, instead of calling love.update and love.draw directly, for consistency with the rest of events and ease of hooking for libraries. I guess that asking for them to be enqueued like the rest of events is asking too much, due to the unpredictability in the ordering of the other events. You don't want a keypressed event to be processed between love.update and love.draw, for example.

Edit: I think I over-complicated my implementation of the edge detection code. This one also has the advantage of detecting a key press/release within one frame:

Code: Select all

local raisingEdges = {}
local fallingEdges = {}

function love.keypressed(k, s)
  raisingEdges[s] = true
end

function love.keyreleased(k, s)
  fallingEdges[s] = true
end

function justPressed(k)
  return raisingEdges[k] or false
end

function love.draw()
  ...

  for k in pairs(raisingEdges) do raisingEdges[k] = false end
  for k in pairs(fallingEdges) do fallingEdges[k] = false end
end
User avatar
Xii
Party member
Posts: 137
Joined: Thu Aug 13, 2020 9:09 pm
Contact:

Re: Best practices and things you'd like changed about Love2D

Post by Xii »

pgimeno wrote: Sat Jun 05, 2021 11:06 am [...] about Xii's complaint about lack of edge detection for keys; I said it was no big deal, as I don't think it's a frequent use case, [...]
Jumping in a platformer. Shooting in a shooter. Activating a special ability. Pressing undo. It's a very frequent use case to detect single key presses. And every dev has to write this boilerplate. It's not a big deal, it's simple and easy, but it's something we all have to write. Isn't the point of a library that we don't all need to implement the things we all universally need?
User avatar
slime
Solid Snayke
Posts: 3163
Joined: Mon Aug 23, 2010 6:45 am
Location: Nova Scotia, Canada
Contact:

Re: Best practices and things you'd like changed about Love2D

Post by slime »

Xii wrote: Sat Jun 05, 2021 7:33 pm Jumping in a platformer. Shooting in a shooter. Activating a special ability. Pressing undo. It's a very frequent use case to detect single key presses. And every dev has to write this boilerplate. It's not a big deal, it's simple and easy, but it's something we all have to write. Isn't the point of a library that we don't all need to implement the things we all universally need?
Those are all actions which are best handled via events (ie love.keypressed or keyreleased, in love's current API). Having code to check whether a key was pressed since the last time it was checked (i.e. the "wasPressed" approach) is subtly wrong because you will not detect things such as the user pressing and releasing a key twice in a frame. That may seem completely inconsequential at first but frame times are not predictable, and neither are user inputs. You're free to make that choice in your own game if you really want of course since love gives you the tools to do so, but I'd consider it bad design for a library or framework to promote that.

An easy way to think about the best place to handle something is - actions (undo, ability activation, etc) are best suited for key events, whereas things that happen over time (movement, charging an ability, etc) are best suited for per-frame code. Putting actions in per-frame code can be easy to do but leads to the above issues.

There's an argument to be made that events should be easier to use than having a centralized callback which executes everything that wants to handle that event. But that's still a fundamentally different approach than "wasPressed".

The main reason why love doesn't have that decentralized events feature yet is because people haven't come up with a design that works well with arbitrary game states, whereas the current approach lets users decide which events get routed through a game state.


As for wiki clarity, the wiki is freely editable by anyone. If you have an improvement to make, feel free to do it - but also keep in mind its primary purpose is simple documentation rather than tutorialization. Either having a note about sprite sheets in the image example you mentioned or having a second more in-depth example with sprite sheets seem like good approaches to me (rather than having a more complicated sprite sheet example up-front).


I agree that love.load is pretty redundant since love 11 (however it had initialization-related reasons to exist prior to love 11) - but outright removing it and breaking a bunch of code hasn't been a priority in the past either. Maybe it could be deprecated in love 12 or something.


The graphics, image, video, sound, audio, filesystem, font, math, physics, and timer modules don't use SDL at all. Input and windowing are mostly SDL wrappers, but I don't really consider that a bad thing (especially given love's core philosophy of not imposing restrictive high level choices you'd find in bigger engines) because SDL made some good design decisions in that area.
User avatar
Jeeper
Party member
Posts: 611
Joined: Tue Mar 12, 2013 7:11 pm
Contact:

Re: Best practices and things you'd like changed about Love2D

Post by Jeeper »

Xii wrote: Sat Jun 05, 2021 7:33 pm
pgimeno wrote: Sat Jun 05, 2021 11:06 am [...] about Xii's complaint about lack of edge detection for keys; I said it was no big deal, as I don't think it's a frequent use case, [...]
Jumping in a platformer. Shooting in a shooter. Activating a special ability. Pressing undo. It's a very frequent use case to detect single key presses. And every dev has to write this boilerplate. It's not a big deal, it's simple and easy, but it's something we all have to write. Isn't the point of a library that we don't all need to implement the things we all universally need?
I personally like Löves "do it yourself" approach, because something which may seem universally needed to you, might not be for others. I have never needed to write that boilerplate code which you talk about for example. I hope Löve focuses on staying a framework rather than trying to be an engine.
Post Reply

Who is online

Users browsing this forum: Majestic-12 [Bot] and 2 guests