love.scene (yet another scene graph library)

Showcase your libraries, tools and other projects that help your fellow love users.
User avatar
ivan
Party member
Posts: 1911
Joined: Fri Mar 07, 2008 1:39 pm
Contact:

love.scene (yet another scene graph library)

Post by ivan »

Love2D Scene Graph
This is a tiny (~10K) scene graph compatible with Love2D 11.3. This library is used to power all of the games behind 2dengine.com so the code is generalized and fairly well tested.

Features
- View or a "viewport" is a clipped rectangular area where the scene is rendered.
- Cameras allow you to pan, zoom and transform the view
- Sprites are nodes in the scene which can be translated, scaled or rotated. Each sprite is assigned a drawable graphic, usually an image, quad or text. Sprites can also be assigned a specific color, alpha value and blending mode
- Layers are basically groups of nodes, containing either sprites or other nested layers. Layers are helpful in ordering nodes along the Z-axis. Layers are used to build things like parallax, huds, minimaps and so on.

Repository and docs
https://github.com/2dengine/love.scene
https://2dengine.com/?p=scene

Example

Code: Select all

love.scene = require("scene")
local view = love.scene.newView()
local sprite = view:newSprite(0, 0)

local image = love.graphics.newImage("myimage.png")
sprite:setGraphic(image)

function love.draw()
  view:draw()
end
Attachments
example2.love
camera, tilemap
(12.64 KiB) Downloaded 112 times
example1.love
2000 sprites
(12.56 KiB) Downloaded 99 times
Last edited by ivan on Mon Dec 26, 2022 2:37 pm, edited 8 times in total.
User avatar
yetneverdone
Party member
Posts: 446
Joined: Sat Sep 24, 2016 11:20 am
Contact:

Re: love.scene (yet another scene graph library)

Post by yetneverdone »

Cool! I'm thinking if i could easily implement it for my game. Im in need of this for z-sorting feature.

Can you give an example or explanation on how to use the z ordering of layers based on sprite's y-position.
User avatar
ivan
Party member
Posts: 1911
Joined: Fri Mar 07, 2008 1:39 pm
Contact:

Re: love.scene (yet another scene graph library)

Post by ivan »

Thanks for taking a look yetneverdone!
It really depends on how you want to handle this.
Most of the time you want to use multiple layers:

Code: Select all

local background = view:newLayer(0, 0)
local middleground = view:newLayer(0, 0)
local foreground = view:newLayer(0, 0)

local bgsprite = background:newSprite(0, 0)
Note that sprites are sorted in the order they are created so:

Code: Select all

local under = view:newSprite(0, 0)
local above = view:newSprite(0, 0)
The easiest option is to create your sprites in the desired order.
In the rare event you want to change the depth dynamically you can use "setIndex":

Code: Select all

sprite:setIndex(1) --moves it to the bottom
or you can switch layers:

Code: Select all

sprite:setParent(foreground)
There is also a sorting function for layers.
This is useful for isometric games where the depth is affected by the Y position.

Code: Select all

layer:sort(function(a, b)
  -- return true if a is below b
end)
Thanks again for taking a look!
Last edited by ivan on Tue Aug 25, 2020 3:51 pm, edited 2 times in total.
User avatar
yetneverdone
Party member
Posts: 446
Joined: Sat Sep 24, 2016 11:20 am
Contact:

Re: love.scene (yet another scene graph library)

Post by yetneverdone »

Thank you!

How about integrating this with another camera lib?

Also i see that

Code: Select all

view:newSprite()
is a special case like

Code: Select all

love.graphics.newSprite()
?
User avatar
ivan
Party member
Posts: 1911
Joined: Fri Mar 07, 2008 1:39 pm
Contact:

Re: love.scene (yet another scene graph library)

Post by ivan »

I have never used any camera libs, so I'm not sure.
I should mention that the "view" object works very much like the viewport of a camera.
You can adjust the size and position of the viewport on the screen by setting its bounds:

Code: Select all

view:setBounds(vx, vy, vw, vh)
Typically you want to set this to the size of your game window.

You can change what is displayed inside the viewport using the "setScene" method:

Code: Select all

view:setScene(x, y, w, h) -- where w(idth) and h(eight) are optional
x and y is the scene origin which is the same as moving/panning the camera. The scene origin is typically the center of the viewport, and NOT the upper left corner!
w and h is the section of the scene (frustum) which is displayed inside the viewport.

Naturally, you can scale and rotate the view object too.
Last edited by ivan on Tue Aug 25, 2020 4:17 pm, edited 2 times in total.
User avatar
ivan
Party member
Posts: 1911
Joined: Fri Mar 07, 2008 1:39 pm
Contact:

Re: love.scene (yet another scene graph library)

Post by ivan »

The following two lines do the same thing:

Code: Select all

view:newSprite(0, 0)
love.scene.newSprite(view, 0, 0)
It's just a question of whatever syntax you prefer.
User avatar
yetneverdone
Party member
Posts: 446
Joined: Sat Sep 24, 2016 11:20 am
Contact:

Re: love.scene (yet another scene graph library)

Post by yetneverdone »

Hi, taking a look at this library again as I am experiencing issue with my rendering system.

So is `view` the same as what camera provides?

So as I understand it, one `scene.sprite` can only have one `sprite/image`?

My project is ECS-based so the `images` in my game are passed as reference to a `sprite` component and then my `RenderSprite` system handles drawing them. So Im thinking that if I am going to integrate this library instead of my own, I would need my `RenderSprite` system to handle the creation of `layers` and then when `entities` are passed into the system, i would register the `images` to the `sprite` right? On the top of my head something like:

Code: Select all

local spr_player = love.graphics.newImage("sprite.png")
local spr_enemy = love.graphics.newImage("enemy.png")
local e_player = Entity():give("sprite", spr_player) --also other components
local e_enemy = Entity():give("sprite", spr_enemy) --also other components

--in RenderSprite
--in init
self.view = love.scene.newView()
self.layers = {
  background = self.view:newLayer(),
  main = self.view:newLayer(),
  foreground = self.view:newLayer()
}

--when entities are registered
self.layers.main:newSprite(e_player.sprite.sprite) --e_player is registered first
self.layer.main:newSprite(e_enemy.sprite.sprite) 

--in update
self.layers.main:sort(function(a, b)
  -- sort by entity's z-component, higher z should be behind lower z as z corresponds to the y-position in the screen.
end)

--in draw
self.layers.background:draw()
self.layers.main:draw()
self.layers.foreground:draw()
User avatar
ivan
Party member
Posts: 1911
Joined: Fri Mar 07, 2008 1:39 pm
Contact:

Re: love.scene (yet another scene graph library)

Post by ivan »

yetneverdone wrote: Thu Dec 31, 2020 3:00 am So is `view` the same as what camera provides?
view is like the "viewport" of a camera. You can move it around and resize it using:

Code: Select all

view:setScene(x, y, w, h)
So as I understand it, one `scene.sprite` can only have one `sprite/image`?
You can assign ONE drawable object to each sprite. This could be an image, mesh, text, particlesystem, etc.
Assigning a drawable to a sprite is very similar to love.draw:

Code: Select all

love.graphics.draw(img, x, y, r, sx, sy, ox, oy)
sprite:setGraphic(img, x, y, r, sx, sy, ox, oy)
Your code looks fine, except for the last part.
We only "draw" the view object:

Code: Select all

view:draw()
User avatar
yetneverdone
Party member
Posts: 446
Joined: Sat Sep 24, 2016 11:20 am
Contact:

Re: love.scene (yet another scene graph library)

Post by yetneverdone »

Ive started testing this lib and it's kinda tricky integrating this with an existing camera system.

Also, no `setScale` for view? Also can you elaborate more on the `setScene`? Thank you
User avatar
ivan
Party member
Posts: 1911
Joined: Fri Mar 07, 2008 1:39 pm
Contact:

Re: love.scene (yet another scene graph library)

Post by ivan »

yetneverdone wrote: Sat Jan 02, 2021 7:07 am Ive started testing this lib and it's kinda tricky integrating this with an existing camera system.
You don't need a separate camera system - the "view" object works as a camera.
yetneverdone wrote: Sat Jan 02, 2021 7:07 am Also, no `setScale` for view? Also can you elaborate more on the `setScene`? Thank you
setScene determines the visible range of the viewport. So if you write:

Code: Select all

view:setScene(0, 0, 800, 600)
The viewport will cover an area of 800 by 600 centered around 0, 0. This will change the scale of the viewport automatically.
If you want to set the scale by hand, then don't use the last two parameters:

Code: Select all

view:setScene(0, 0)
view:setScale(2, 2)
If you want to change the actual size of the viewport within the game window you can use "setDimensions" or "setBounds":

Code: Select all

view:setDimensions(200, 200)

Code: Select all

view:setBounds(0, 0, 200, 200)
Either one of these functions will create a rectangular viewport 200 by 200 pixels in the top-left corner of the game window (0, 0).
Post Reply

Who is online

Users browsing this forum: No registered users and 35 guests