npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@l8b/scene

v1.0.7

Published

Scene management and routing system for L8B

Downloads

1,466

Readme

@l8b/scene

LootiScript API Binding - Scene management and routing system for organizing game states.

Note: This package is used as an API binding for LootiScript in the l8b engine.

API Reference

scene()

Define a new scene with lifecycle methods.

scene("main_menu", {
  // Called when scene starts
  init = function(self)
    self.selected = 0
  end,

  // Called every frame
  update = function(self)
    if keyboard.press.ENTER == 1 then
      router.push("/game")
    end

    if keyboard.press.UP == 1 then
      self.selected = self.selected - 1
    end
  end,

  // Called every frame for rendering
  draw = function(self)
    screen.clear("#000000")
    screen.setColor("#FFFFFF")
    screen.drawText("Main Menu", 10, 10, 16)
  end,

  // Called when leaving scene
  cleanup = function(self)
    // Clean up resources
  end
})

Parameters:

  • name (string) - Scene name
  • definition (table) - Scene definition object
    • init (function, optional) - Called when scene starts
    • update (function, optional) - Called every frame
    • draw (function, optional) - Called every frame for rendering
    • cleanup (function, optional) - Called when leaving scene

route()

Map a URL path to a scene.

// Map root path to main menu
route("/", "main_menu")

// Map /game to game scene
route("/game", "game_scene")

// Map with parameters
route("/level/:id", "level_scene")
route("/player/:playerId/inventory", "inventory_scene")

Parameters:

  • path (string) - URL path pattern
  • sceneName (string) - Scene name to activate

Path Parameters:

  • Use :paramName for dynamic segments
  • Access via router.params.paramName

router

Global object for navigation and route state.

router.push()

Navigate to a path (adds to history).

// Navigate to game scene
router.push("/game")

// Navigate with parameters
router.push("/level/5")
router.push("/player/123/inventory")

Parameters:

  • path (string) - Path to navigate to

router.replace()

Navigate to a path (replaces current history entry).

// Replace current path
router.replace("/game_over")

Parameters:

  • path (string) - Path to navigate to

router.back()

Go back in browser history.

// Go back
router.back()

router.path

Get current path.

local currentPath = router.path
// Returns: "/level/5"

router.params

Get current route parameters.

// For route "/level/:id" at path "/level/5"
local levelId = router.params.id  // "5"

// For route "/player/:playerId/inventory" at "/player/123/inventory"
local playerId = router.params.playerId  // "123"

router.sceneName

Get current scene name.

local current = router.sceneName
// Returns: "level_scene"

Scene Lifecycle

Scenes have a defined lifecycle:

  1. init() - Called once when scene becomes active
  2. update() - Called every frame while scene is active
  3. draw() - Called every frame for rendering
  4. cleanup() - Called when leaving scene
scene("game", {
  init = function(self)
    // Initialize scene state
    self.score = 0
    self.player = {x = 100, y = 100}
  end,

  update = function(self)
    // Update game logic
    if keyboard.UP == 1 then
      self.player.y = self.player.y - 2
    end
  end,

  draw = function(self)
    // Render scene
    screen.clear("#000")
    screen.fillRect(self.player.x, self.player.y, 16, 16, "#FFF")
  end,

  cleanup = function(self)
    // Clean up when leaving scene
    self.score = 0
  end
})

Scene State

Access scene state via self:

scene("example", {
  init = function(self)
    // Set initial state
    self.counter = 0
    self.items = {}
  end,

  update = function(self)
    // Access and modify state
    self.counter = self.counter + 1

    if keyboard.press.SPACE == 1 then
      table.insert(self.items, {x = 10, y = 10})
    end
  end,

  draw = function(self)
    // Use state for rendering
    screen.drawText("Count: " .. self.counter, 10, 10, 12)
  end
})

Complete Example

// Define routes
route("/", "menu")
route("/game", "game")
route("/level/:id", "level")

// Main menu scene
scene("menu", {
  init = function(self)
    self.options = {"Start Game", "Options", "Quit"}
    self.selected = 0
  end,

  update = function(self)
    if keyboard.press.UP == 1 then
      self.selected = math.max(0, self.selected - 1)
    end

    if keyboard.press.DOWN == 1 then
      self.selected = math.min(#self.options - 1, self.selected + 1)
    end

    if keyboard.press.ENTER == 1 then
      if self.selected == 0 then
        router.push("/game")
      end
    end
  end,

  draw = function(self)
    screen.clear("#000")

    for i = 0, #self.options - 1 do
      local color = "#FFF"
      if i == self.selected then
        color = "#FF0"
      end
      screen.setColor(color)
      screen.drawText(self.options[i + 1], 100, 100 + i * 20, 14)
    end
  end
})

// Game scene
scene("game", {
  init = function(self)
    self.score = 0
  end,

  update = function(self)
    if keyboard.press.ESCAPE == 1 then
      router.push("/")
    end
  end,

  draw = function(self)
    screen.clear("#000")
    screen.setColor("#FFF")
    screen.drawText("Score: " .. self.score, 10, 10, 12)
  end
})

// Level scene with parameters
scene("level", {
  init = function(self)
    // Access route parameter
    self.levelId = router.params.id
    Console.log("Loading level " .. self.levelId)
  end,

  update = function(self)
    // Level logic
  end,

  draw = function(self)
    screen.clear("#000")
    screen.drawText("Level " .. self.levelId, 10, 10, 16)
  end
})