LÖVE游戏引擎 #

一、LÖVE 简介 #

1.1 什么是 LÖVE #

LÖVE(Love2D)是一个使用 Lua 编程语言开发 2D 游戏的开源框架。它提供了图形渲染、音频播放、输入处理、物理模拟等功能。

1.2 核心特点 #

  • 简单易用:API 设计直观
  • 跨平台:支持 Windows、macOS、Linux
  • 轻量级:框架小巧,启动快速
  • 开源免费:Zlib/libpng 许可证

1.3 游戏循环 #

lua
function love.load()
    -- 初始化代码
end

function love.update(dt)
    -- 更新逻辑
end

function love.draw()
    -- 绘制画面
end

二、安装与配置 #

2.1 安装 LÖVE #

bash
# macOS
brew install --cask love

# Windows
# 下载安装包:https://love2d.org/

# Linux
sudo apt install love

2.2 创建项目 #

text
mygame/
├── main.lua      -- 主入口
├── conf.lua      -- 配置文件
├── assets/       -- 资源文件
│   ├── images/
│   ├── sounds/
│   └── fonts/
└── lib/          -- 库文件

2.3 配置文件 #

lua
-- conf.lua
function love.conf(t)
    t.title = "My Game"
    t.version = "11.4"
    t.window.width = 800
    t.window.height = 600
    t.window.fullscreen = false
    t.window.vsync = true
end

2.4 运行游戏 #

bash
# 运行游戏
love mygame

# 打包游戏
love --game mygame

三、基本功能 #

3.1 图形绘制 #

lua
function love.load()
    x = 100
    y = 100
    radius = 50
end

function love.draw()
    -- 设置颜色(RGBA,0-1)
    love.graphics.setColor(1, 0, 0)
    
    -- 绘制圆形
    love.graphics.circle("fill", x, y, radius)
    
    -- 绘制矩形
    love.graphics.rectangle("fill", 200, 100, 100, 50)
    
    -- 绘制线条
    love.graphics.line(0, 0, 800, 600)
    
    -- 绘制文本
    love.graphics.print("Hello, LÖVE!", 10, 10)
end

3.2 加载图片 #

lua
function love.load()
    image = love.graphics.newImage("assets/player.png")
    x = 100
    y = 100
end

function love.draw()
    love.graphics.draw(image, x, y)
end

3.3 键盘输入 #

lua
function love.load()
    x = 400
    y = 300
    speed = 200
end

function love.update(dt)
    if love.keyboard.isDown("left") then
        x = x - speed * dt
    end
    if love.keyboard.isDown("right") then
        x = x + speed * dt
    end
    if love.keyboard.isDown("up") then
        y = y - speed * dt
    end
    if love.keyboard.isDown("down") then
        y = y + speed * dt
    end
end

function love.draw()
    love.graphics.circle("fill", x, y, 20)
end

function love.keypressed(key)
    if key == "escape" then
        love.event.quit()
    end
end

3.4 鼠标输入 #

lua
function love.load()
    x = 400
    y = 300
end

function love.update(dt)
    -- 获取鼠标位置
    local mx, my = love.mouse.getPosition()
    
    -- 跟随鼠标
    x = x + (mx - x) * 0.1
    y = y + (my - y) * 0.1
end

function love.mousepressed(x, y, button)
    if button == 1 then
        print("左键点击:", x, y)
    end
end

function love.draw()
    love.graphics.circle("fill", x, y, 20)
end

四、游戏对象 #

4.1 玩家类 #

lua
local Player = {}
Player.__index = Player

function Player:new(x, y)
    local instance = setmetatable({}, self)
    instance.x = x
    instance.y = y
    instance.width = 32
    instance.height = 32
    instance.speed = 200
    instance.vx = 0
    instance.vy = 0
    return instance
end

function Player:update(dt)
    -- 输入处理
    self.vx = 0
    self.vy = 0
    
    if love.keyboard.isDown("left") then self.vx = -self.speed end
    if love.keyboard.isDown("right") then self.vx = self.speed end
    if love.keyboard.isDown("up") then self.vy = -self.speed end
    if love.keyboard.isDown("down") then self.vy = self.speed end
    
    -- 更新位置
    self.x = self.x + self.vx * dt
    self.y = self.y + self.vy * dt
end

function Player:draw()
    love.graphics.setColor(0, 1, 0)
    love.graphics.rectangle("fill", self.x, self.y, self.width, self.height)
end

return Player

4.2 使用玩家类 #

lua
local Player = require("player")

function love.load()
    player = Player:new(400, 300)
end

function love.update(dt)
    player:update(dt)
end

function love.draw()
    player:draw()
end

五、动画 #

5.1 精灵动画 #

lua
function love.load()
    sprite = love.graphics.newImage("assets/spritesheet.png")
    
    -- 创建动画帧
    frames = {}
    local frame_width = 32
    local frame_height = 32
    
    for i = 0, 3 do
        frames[i + 1] = love.graphics.newQuad(
            i * frame_width, 0,
            frame_width, frame_height,
            sprite:getDimensions()
        )
    end
    
    current_frame = 1
    frame_time = 0
    frame_duration = 0.1
end

function love.update(dt)
    frame_time = frame_time + dt
    
    if frame_time >= frame_duration then
        frame_time = 0
        current_frame = current_frame + 1
        if current_frame > #frames then
            current_frame = 1
        end
    end
end

function love.draw()
    love.graphics.draw(sprite, frames[current_frame], 100, 100)
end

5.2 使用动画库 #

bash
# 安装 anim8 库
# 将 anim8.lua 放入 lib 目录
lua
local anim8 = require("lib.anim8")

function love.load()
    sprite = love.graphics.newImage("assets/spritesheet.png")
    
    local grid = anim8.newGrid(32, 32, sprite:getWidth(), sprite:getHeight())
    
    animation = anim8.newAnimation(grid('1-4', 1), 0.1)
end

function love.update(dt)
    animation:update(dt)
end

function love.draw()
    animation:draw(sprite, 100, 100)
end

六、碰撞检测 #

6.1 简单碰撞 #

lua
local function check_collision(a, b)
    return a.x < b.x + b.width and
           a.x + a.width > b.x and
           a.y < b.y + b.height and
           a.y + a.height > b.y
end

6.2 使用物理引擎 #

lua
function love.load()
    -- 创建世界
    world = love.physics.newWorld(0, 9.81 * 64, true)
    
    -- 创建地面
    ground = {}
    ground.body = love.physics.newBody(world, 400, 550, "static")
    ground.shape = love.physics.newRectangleShape(800, 50)
    ground.fixture = love.physics.newFixture(ground.body, ground.shape)
    
    -- 创建球
    ball = {}
    ball.body = love.physics.newBody(world, 400, 200, "dynamic")
    ball.shape = love.physics.newCircleShape(20)
    ball.fixture = love.physics.newFixture(ball.body, ball.shape, 1)
    ball.fixture:setRestitution(0.7)  -- 弹性
end

function love.update(dt)
    world:update(dt)
end

function love.draw()
    love.graphics.setColor(0.5, 0.5, 0.5)
    love.graphics.polygon("fill", ground.body:getWorldPoints(ground.shape:getPoints()))
    
    love.graphics.setColor(1, 0, 0)
    love.graphics.circle("fill", ball.body:getX(), ball.body:getY(), ball.shape:getRadius())
end

七、音频 #

7.1 播放音效 #

lua
function love.load()
    jump_sound = love.audio.newSource("assets/jump.wav", "static")
    bg_music = love.audio.newSource("assets/music.mp3", "stream")
    
    bg_music:setLooping(true)
    bg_music:play()
end

function love.keypressed(key)
    if key == "space" then
        jump_sound:play()
    end
end

八、游戏状态 #

8.1 状态管理 #

lua
local Game = {}
Game.__index = Game

function Game:new()
    local instance = setmetatable({}, self)
    instance.state = "menu"
    instance.score = 0
    return instance
end

function Game:update(dt)
    if self.state == "menu" then
        -- 菜单逻辑
    elseif self.state == "playing" then
        -- 游戏逻辑
    elseif self.state == "gameover" then
        -- 结束逻辑
    end
end

function Game:draw()
    if self.state == "menu" then
        love.graphics.print("Press SPACE to start", 300, 300)
    elseif self.state == "playing" then
        love.graphics.print("Score: " .. self.score, 10, 10)
    elseif self.state == "gameover" then
        love.graphics.print("Game Over! Score: " .. self.score, 300, 300)
    end
end

function Game:keypressed(key)
    if self.state == "menu" and key == "space" then
        self.state = "playing"
    elseif self.state == "gameover" and key == "space" then
        self.state = "menu"
        self.score = 0
    end
end

return Game

九、完整示例 #

9.1 简单躲避游戏 #

lua
local player = {x = 400, y = 500, width = 40, height = 40, speed = 300}
local enemies = {}
local score = 0
local spawn_timer = 0
local game_over = false

function love.load()
    math.randomseed(os.time())
end

function love.update(dt)
    if game_over then return end
    
    -- 玩家移动
    if love.keyboard.isDown("left") then
        player.x = player.x - player.speed * dt
    end
    if love.keyboard.isDown("right") then
        player.x = player.x + player.speed * dt
    end
    
    -- 边界检测
    player.x = math.max(0, math.min(800 - player.width, player.x))
    
    -- 生成敌人
    spawn_timer = spawn_timer + dt
    if spawn_timer > 0.5 then
        spawn_timer = 0
        table.insert(enemies, {
            x = math.random(0, 800 - 30),
            y = -30,
            width = 30,
            height = 30,
            speed = 200 + math.random(100)
        })
    end
    
    -- 更新敌人
    for i = #enemies, 1, -1 do
        local e = enemies[i]
        e.y = e.y + e.speed * dt
        
        -- 碰撞检测
        if check_collision(player, e) then
            game_over = true
        end
        
        -- 移除出界敌人
        if e.y > 600 then
            table.remove(enemies, i)
            score = score + 1
        end
    end
end

function love.draw()
    -- 绘制玩家
    love.graphics.setColor(0, 1, 0)
    love.graphics.rectangle("fill", player.x, player.y, player.width, player.height)
    
    -- 绘制敌人
    love.graphics.setColor(1, 0, 0)
    for _, e in ipairs(enemies) do
        love.graphics.rectangle("fill", e.x, e.y, e.width, e.height)
    end
    
    -- 绘制分数
    love.graphics.setColor(1, 1, 1)
    love.graphics.print("Score: " .. score, 10, 10)
    
    if game_over then
        love.graphics.print("Game Over! Press R to restart", 300, 300)
    end
end

function love.keypressed(key)
    if key == "r" and game_over then
        enemies = {}
        score = 0
        game_over = false
    end
end

function check_collision(a, b)
    return a.x < b.x + b.width and
           a.x + a.width > b.x and
           a.y < b.y + b.height and
           a.y + a.height > b.y
end

十、总结 #

LÖVE 是开发 2D 游戏的优秀框架:

  1. 简单易用:直观的 API
  2. 功能丰富:图形、音频、输入、物理
  3. 跨平台:支持主流操作系统
  4. 社区活跃:丰富的库和教程

下一章,我们将学习 Lua 的应用场景。

最后更新:2026-03-27