Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

File-system based scene routing for LÖVE 2D games inspired by Next.js

License

NotificationsYou must be signed in to change notification settings

zhuravkovigor/love-scenes

Repository files navigation

File-system based scene routing for LÖVE 2D games inspired by Next.js

Features

  • 📁File-system based routing - Create scenes by simply adding files to your scenes directory
  • 🔀Dynamic routes - Support for parameterized routes like[id].lua
  • 📱Layout system - Wrap scenes with reusable layouts
  • 🎯Simple API - Easy to integrate into existing LÖVE 2D projects
  • 🔧Configurable - Customize scenes directory and behavior

Installation

LuaRocks (Recommended)

luarocks install love-scenes

Git/GitHub

Install directly from GitHub:

luarocks install --server=https://luarocks.org/manifests/zhuravkovigor love-scenes

Or clone and install manually:

git clone https://github.com/zhuravkovigor/love-scenes.gitcd love-scenesluarocks make love-scenes-1.0-1.rockspec

Manual Installation

  1. Download the latest release fromGitHub Releases
  2. Extract the files to your project directory
  3. Require the library in yourmain.lua

Development Installation

Clone the repository and install locally:

git clone https://github.com/zhuravkovigor/love-scenes.gitcd love-scenesmake install

Quick Start

1. Basic Setup

-- main.lualocalLoveScenes=require('love-scenes')functionlove.load()-- Initialize with default settingsLoveScenes.init()-- Navigate to the main sceneLoveScenes.navigate('/')endfunctionlove.update(dt)LoveScenes.update(dt)endfunctionlove.draw()LoveScenes.draw()end-- Forward input eventsfunctionlove.keypressed(key,scancode,isrepeat)LoveScenes.keypressed(key,scancode,isrepeat)end

2. Create Your First Scene

-- scenes/index.lua (Main menu at route "/")localscene= {}functionscene:load(params)self.title="My Awesome Game"endfunctionscene:update(dt)-- Scene update logicendfunctionscene:draw()love.graphics.printf(self.title,0,100,love.graphics.getWidth(),"center")endfunctionscene:keypressed(key)ifkey=="space"thenrequire('love-scenes').navigate('/game')endendreturnscene

3. Add More Scenes

-- scenes/game/index.lua (Game scene at route "/game")localscene= {}functionscene:load(params)self.player= {x=100,y=100}endfunctionscene:update(dt)iflove.keyboard.isDown("left")thenself.player.x=self.player.x-100*dtendiflove.keyboard.isDown("right")thenself.player.x=self.player.x+100*dtendendfunctionscene:draw()love.graphics.circle("fill",self.player.x,self.player.y,20)endreturnscene

File Structure

Love Scenes uses a file-system based routing approach similar to Next.js:

scenes/├── index.lua              # Route: /├── layout.lua             # Layout for all scenes├── game/│   ├── index.lua          # Route: /game│   └── layout.lua         # Layout for /game/* routes├── level/│   └── [level].lua        # Route: /level/1-1, /level/forest, etc.├── profile/│   └── [id].lua           # Route: /profile/123, /profile/abc, etc.├── shop/│   └── [category].lua     # Route: /shop/weapons, /shop/armor, etc.└── settings/    ├── index.lua          # Route: /settings    └── audio/        └── index.lua      # Route: /settings/audio

Routing Examples

Static Routes

  • scenes/index.lua/ (root)
  • scenes/about/index.lua/about
  • scenes/game/level/index.lua/game/level

Dynamic Routes

  • scenes/user/[id].lua/user/123,/user/abc
  • scenes/level/[level].lua/level/1-1,/level/forest
  • scenes/shop/[category].lua/shop/weapons,/shop/armor
  • scenes/post/[slug]/[id].lua/post/hello-world/123
-- scenes/level/[level].lualocalscene= {}functionscene:load(params)self.levelId=params.level-- Access the dynamic parameterprint("Loading level:",self.levelId)-- Different logic based on levelifself.levelId=="boss-1"thenself:loadBossLevel()elseself:loadNormalLevel()endendreturnscene

Layouts

Layouts wrap scenes and provide common UI elements:

-- scenes/layout.lua (Root layout for all scenes)locallayout= {}functionlayout:draw(drawScene)-- Draw headerlove.graphics.setColor(0.2,0.2,0.2)love.graphics.rectangle("fill",0,0,love.graphics.getWidth(),60)-- Draw scene contentlove.graphics.push()love.graphics.translate(0,60)drawScene()-- This renders the current scenelove.graphics.pop()-- Draw footerlove.graphics.setColor(0.2,0.2,0.2)love.graphics.rectangle("fill",0,love.graphics.getHeight()-40,love.graphics.getWidth(),40)endreturnlayout

Navigation

Navigate between scenes using thenavigate function:

localLoveScenes=require('love-scenes')-- Navigate to different routesLoveScenes.navigate('/')LoveScenes.navigate('/game')LoveScenes.navigate('/profile/123')LoveScenes.navigate('/settings/audio')-- Navigate with additional parametersLoveScenes.navigate('/user/123', {tab="settings"})

Configuration

All configuration parameters are optional. Love Scenes works out of the box with sensible defaults:

-- Minimal setup - all parameters are optionalLoveScenes.init()-- With custom configurationLoveScenes.init({scenesPath="scenes",-- Directory containing scenes (default: "scenes")autoLoad=true,-- Automatically load scenes on init (default: true)enableLayouts=true,-- Enable layout system (default: true)debugMode=false-- Enable debug logging (default: false)})

Configuration Options

ParameterTypeDefaultDescription
scenesPathstring"scenes"Directory containing your scene files
autoLoadbooleantrueAutomatically scan and load scenes on initialization
enableLayoutsbooleantrueEnable the layout system for wrapping scenes
debugModebooleanfalseEnable debug logging to console

Scene Lifecycle

Scenes have several lifecycle methods:

localscene= {}functionscene:load(params)-- Called when scene is created and loaded-- Access route parameters via params-- Initialize scene data, load assets, set up stateendfunctionscene:onEnter(next)-- Called when navigating to this scene-- next is an optional callback for controlling transition timingifnextthen-- Perform any animations or async setup-- Call next() when ready for the scene to become activenext()endendfunctionscene:onLeave(next)-- Called when leaving this scene-- next is an optional callback for controlling transition timingifnextthen-- Perform cleanup animations-- Call next() when ready to complete the transitionnext()endendfunctionscene:update(dt)-- Called every frameendfunctionscene:draw()-- Called every frame for renderingend-- LÖVE 2D callbacks are automatically forwardedfunctionscene:keypressed(key,scancode,isrepeat)-- Handle inputendfunctionscene:mousepressed(x,y,button,isTouch,presses)-- Handle mouse inputendreturnscene

Example with Transition Animation

localscene= {}localfade_alpha=1functionscene:onEnter(next)ifnextthen-- Start fade-in animationfade_alpha=0-- Don't block transition, let it proceed immediatelynext()elsefade_alpha=1endendfunctionscene:update(dt)-- Simple fade-in animationiffade_alpha<1thenfade_alpha=math.min(1,fade_alpha+dt*2)endendfunctionscene:draw()love.graphics.push()love.graphics.setColor(1,1,1,fade_alpha)-- Draw scene content with fade effectlove.graphics.printf("Scene Content",0,100,love.graphics.getWidth(),"center")love.graphics.pop()endreturnscene

Layout Lifecycle

Layouts also have lifecycle methods:

locallayout= {}functionlayout:load()-- Called when layout is createdendfunctionlayout:onEnter(scene,next)-- Called when a scene using this layout is entered-- scene: the scene that will be rendered-- next: optional callback for controlling transition timingifnextthennext()endendfunctionlayout:onLeave(next)-- Called when leaving this layout-- next: optional callback for controlling transition timingifnextthennext()endend-- Called when leaving this layoutendfunctionlayout:update(dt)-- Called every frame before scene updateendfunctionlayout:draw(drawScene)-- Called every frame for rendering-- drawScene() renders the current sceneendreturnlayout

API Reference

LoveScenes.init(config)

Initialize the library with optional configuration.All parameters are optional - the library works with sensible defaults.

Parameters:

  • config (table, optional): Configuration options. If omitted, uses default values.
    • scenesPath (string, optional): Directory containing scenes (default: "scenes")
    • autoLoad (boolean, optional): Automatically load scenes on init (default: true)
    • enableLayouts (boolean, optional): Enable layout system (default: true)
    • debugMode (boolean, optional): Enable debug logging (default: false)

Examples:

-- Minimal setupLoveScenes.init()-- With custom scenes directoryLoveScenes.init({scenesPath="game-scenes"})-- With debug modeLoveScenes.init({debugMode=true })

LoveScenes.navigate(path, params)

Navigate to a scene.

Parameters:

  • path (string): Route path (e.g., "/", "/game", "/user/123")
  • params (table, optional): Additional parameters to pass to the scene

LoveScenes.getCurrentScene()

Get the current active scene instance.

LoveScenes.getCurrentLayout()

Get the current active layout instance.

Complete Examples

Basic Game Setup

Here's a complete example of a simple game with multiple scenes:

-- main.lualocalLoveScenes=require('love-scenes')functionlove.load()LoveScenes.init({debugMode=true-- Enable debug logging    })-- Start at main menuLoveScenes.navigate('/')endfunctionlove.update(dt)LoveScenes.update(dt)endfunctionlove.draw()LoveScenes.draw()end-- Forward all LÖVE callbacksfunctionlove.keypressed(key,scancode,isrepeat)LoveScenes.keypressed(key,scancode,isrepeat)endfunctionlove.mousepressed(x,y,button,isTouch,presses)LoveScenes.mousepressed(x,y,button,isTouch,presses)end
-- scenes/index.lua (Main Menu)localLoveScenes=require('love-scenes')localscene= {}functionscene:load()self.title="My Awesome Game"self.menuItems= {"Start Game","Settings","Quit"}self.selectedIndex=1endfunctionscene:update(dt)-- Menu logic hereendfunctionscene:draw()-- Draw titlelove.graphics.setFont(love.graphics.newFont(32))love.graphics.printf(self.title,0,100,love.graphics.getWidth(),"center")-- Draw menu itemslove.graphics.setFont(love.graphics.newFont(16))fori,iteminipairs(self.menuItems)dolocaly=200+ (i-1)*40localcolor=i==self.selectedIndexand {1,1,0}or {1,1,1}love.graphics.setColor(color)love.graphics.printf(item,0,y,love.graphics.getWidth(),"center")endlove.graphics.setColor(1,1,1)-- Reset colorendfunctionscene:keypressed(key)ifkey=="up"thenself.selectedIndex=math.max(1,self.selectedIndex-1)elseifkey=="down"thenself.selectedIndex=math.min(#self.menuItems,self.selectedIndex+1)elseifkey=="return"thenifself.selectedIndex==1thenLoveScenes.navigate('/game')elseifself.selectedIndex==2thenLoveScenes.navigate('/settings')elseifself.selectedIndex==3thenlove.event.quit()endendendreturnscene
-- scenes/game/index.lua (Game Scene)localLoveScenes=require('love-scenes')localscene= {}functionscene:load()self.player= {x=400,y=300,speed=200    }self.enemies= {}self.score=0endfunctionscene:update(dt)-- Player movementiflove.keyboard.isDown("left","a")thenself.player.x=self.player.x-self.player.speed*dtendiflove.keyboard.isDown("right","d")thenself.player.x=self.player.x+self.player.speed*dtendiflove.keyboard.isDown("up","w")thenself.player.y=self.player.y-self.player.speed*dtendiflove.keyboard.isDown("down","s")thenself.player.y=self.player.y+self.player.speed*dtend-- Keep player on screenself.player.x=math.max(20,math.min(love.graphics.getWidth()-20,self.player.x))self.player.y=math.max(20,math.min(love.graphics.getHeight()-20,self.player.y))endfunctionscene:draw()-- Draw playerlove.graphics.setColor(0,1,0)-- Greenlove.graphics.circle("fill",self.player.x,self.player.y,20)-- Draw UIlove.graphics.setColor(1,1,1)-- Whitelove.graphics.print("Score:"..self.score,10,10)love.graphics.print("Press ESC to return to menu",10,30)endfunctionscene:keypressed(key)ifkey=="escape"thenLoveScenes.navigate('/')endendreturnscene

Dynamic Routes Example

-- scenes/profile/[id].lua (Dynamic User Profile)localscene= {}functionscene:load(params)self.userId=params.idself.userInfo=self:loadUserInfo(self.userId)endfunctionscene:loadUserInfo(id)-- Simulate loading user datareturn {name="User"..id,level=math.random(1,100),score=math.random(1000,99999)    }endfunctionscene:draw()love.graphics.printf("User Profile",0,50,love.graphics.getWidth(),"center")love.graphics.printf("ID:"..self.userId,0,100,love.graphics.getWidth(),"center")love.graphics.printf("Name:"..self.userInfo.name,0,130,love.graphics.getWidth(),"center")love.graphics.printf("Level:"..self.userInfo.level,0,160,love.graphics.getWidth(),"center")love.graphics.printf("Score:"..self.userInfo.score,0,190,love.graphics.getWidth(),"center")love.graphics.printf("Press ESC to go back",0,250,love.graphics.getWidth(),"center")endfunctionscene:keypressed(key)ifkey=="escape"thenrequire('love-scenes').navigate('/')endendreturnscene

Now you can navigate to different user profiles:

  • LoveScenes.navigate('/profile/123')
  • LoveScenes.navigate('/profile/player1')
  • LoveScenes.navigate('/profile/admin')

Tips and Best Practices

1. Scene Organization

  • Keep related scenes in subdirectories (e.g.,scenes/game/,scenes/menu/)
  • Use descriptive names for dynamic routes:[playerId].lua,[levelName].lua

2. State Management

  • Initialize all scene data in theload() method
  • UseonEnter() andonLeave() for cleanup and transitions
  • Store global state outside of individual scenes if needed

3. Performance

  • Preload assets inload() method
  • UseonLeave() to clean up resources
  • Consider using layouts for shared UI elements

4. Navigation

  • Use absolute paths for navigation:/game,/settings/audio
  • Pass additional data via the params parameter
  • Handle navigation errors gracefully

Examples

Check out thescenes/ directory in this repository for complete examples including:

  • Main menu with navigation
  • Game scene with player movement
  • Settings scene with configurable options
  • Dynamic profile scenes with URL parameters
  • Layout system with header and footer

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

MIT License - see LICENSE file for details.

About

File-system based scene routing for LÖVE 2D games inspired by Next.js

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

[8]ページ先頭

©2009-2025 Movatter.jp