游戏开发中常用的设计模式

管理员
### 一、创建型模式 #### 1. 单例模式 (Singleton) 确保一个类只有一个实例,提供全局访问点。 代码示例: ```lua local GameManager = {} GameManager.__index = GameManager local instance = nil function GameManager.GetInstance() if not instance then instance = setmetatable({}, GameManager) instance.score = 0 instance.level = 1 end return instance end local gm = GameManager.GetInstance() ``` 应用场景:游戏状态管理、资源管理器、音频管理器、配置管理 #### 2. 对象池模式 (Object Pool) 重用对象,避免频繁创建和销毁。 代码示例: ```lua local BulletPool = {} BulletPool.__index = BulletPool function BulletPool.new(size) local self = setmetatable({}, BulletPool) self.pool = {} for i = 1, size do table.insert(self.pool, {active = false, x = 0, y = 0}) end return self end function BulletPool:acquire(x, y) for _, bullet in ipairs(self.pool) do if not bullet.active then bullet.active = true bullet.x = x bullet.y = y return bullet end end return nil end function BulletPool:release(bullet) bullet.active = false end ``` 应用场景:子弹、粒子效果、敌人对象、特效对象、连接池 #### 3. 原型模式 (Prototype) 通过克隆来创建对象。 代码示例: ```lua local Enemy = {} Enemy.__index = Enemy function Enemy:clone() local new_enemy = {} for k, v in pairs(self) do new_enemy[k] = v end setmetatable(new_enemy, Enemy) return new_enemy end local goblin_prototype = setmetatable({ health = 100, damage = 10, speed = 5 }, Enemy) local goblin1 = goblin_prototype:clone() local goblin2 = goblin_prototype:clone() ``` ### 二、结构型模式 #### 4. 组件模式 (Component) 将功能拆分成独立组件,动态组合。 代码示例: ```lua local Component = {} Component.__index = Component function Component.new(name) local self = setmetatable({}, Component) self.name = name return self end local HealthComponent = Component.new("Health") function HealthComponent:update(dt) if self.health <= 0 then self.parent:destroy() end end local MovementComponent = Component.new("Movement") function MovementComponent:update(dt) self.parent.x = self.parent.x + self.parent.vx * dt self.parent.y = self.parent.y + self.parent.vy * dt end local GameObject = {} GameObject.__index = GameObject function GameObject.new() local self = setmetatable({}, GameObject) self.components = {} return self end function GameObject:addComponent(component) component.parent = self self.components[component.name] = component end function GameObject:update(dt) for _, component in pairs(self.components) do if component.update then component:update(dt) end end end ``` #### 5. 外观模式 (Facade) 为复杂子系统提供简单接口。 代码示例: ```lua local GameAPI = {} function GameAPI.startGame() AudioManager:playBGM("main_theme") SceneManager:loadScene("level1") UIManager:showHUD() InputManager:enableInput() end function GameAPI.pauseGame() TimeManager:pause() AudioManager:pauseBGM() UIManager:showPauseMenu() end GameAPI.startGame() ``` ### 三、行为型模式 #### 6. 观察者模式 (Observer) 对象状态变化时通知所有依赖者。 代码示例: ```lua local EventSystem = {} EventSystem.listeners = {} function EventSystem.register(event, callback) if not EventSystem.listeners[event] then EventSystem.listeners[event] = {} end table.insert(EventSystem.listeners[event], callback) end function EventSystem.emit(event, data) if EventSystem.listeners[event] then for _, callback in ipairs(EventSystem.listeners[event]) do callback(data) end end end EventSystem.register("onEnemyKilled", function(data) print("击杀敌人: " .. data.enemy_type) AchievementSystem:checkAchievement("killer", data) end) EventSystem.register("onHealthChanged", function(data) UIManager:updateHealthBar(data.current, data.max) end) function onEnemyDeath(enemy) EventSystem.emit("onEnemyKilled", { enemy_type = enemy.type, position = {x = enemy.x, y = enemy.y} }) end ``` #### 7. 状态模式 (State) 对象行为随状态改变而改变。 代码示例: ```lua local PlayerState = {} PlayerState.__index = PlayerState function PlayerState:enter(player) end function PlayerState:exit(player) end function PlayerState:update(player, dt) end function PlayerState:handleInput(player, input) end local IdleState = setmetatable({}, PlayerState) function IdleState:enter(player) player.animation:play("idle") end function IdleState:handleInput(player, input) if input == "move" then player:changeState(RunState) elseif input == "jump" then player:changeState(JumpState) end end local RunState = setmetatable({}, PlayerState) function RunState:enter(player) player.animation:play("run") player.speed = 200 end function RunState:handleInput(player, input) if input == "stop" then player:changeState(IdleState) elseif input == "jump" then player:changeState(JumpState) end end local Player = {} Player.__index = Player function Player.new() local self = setmetatable({}, Player) self.state = nil self.states = {idle = IdleState, run = RunState, jump = JumpState} return self end function Player:changeState(newState) if self.state then self.state:exit(self) end self.state = newState self.state:enter(self) end ``` #### 8. 命令模式 (Command) 将请求封装为对象,支持撤销、重做。 代码示例: ```lua local Command = {} Command.__index = Command function Command:execute() end function Command:undo() end local MoveCommand = setmetatable({}, Command) function MoveCommand.new(entity, dx, dy) local self = setmetatable({}, MoveCommand) self.entity = entity self.dx = dx self.dy = dy self.old_x = entity.x self.old_y = entity.y return self end function MoveCommand:execute() self.entity.x = self.entity.x + self.dx self.entity.y = self.entity.y + self.dy end function MoveCommand:undo() self.entity.x = self.old_x self.entity.y = self.old_y end local InputSystem = {} InputSystem.commands = {} InputSystem.history = {} function InputSystem:bind(key, command) self.commands[key] = command end function InputSystem:handleInput(key) local command = self.commands[key] if command then command:execute() table.insert(self.history, command) end end function InputSystem:undo() local command = table.remove(self.history) if command then command:undo() end end ``` #### 9. 策略模式 (Strategy) 定义算法族,运行时选择算法。 代码示例: ```lua local AttackStrategy = {} AttackStrategy.__index = AttackStrategy local MeleeStrategy = setmetatable({}, AttackStrategy) function MeleeStrategy:attack(enemy) print("近战攻击造成50伤害") enemy:takeDamage(50) end local RangedStrategy = setmetatable({}, AttackStrategy) function RangedStrategy:attack(enemy) print("远程攻击造成30伤害") enemy:takeDamage(30) end local MagicStrategy = setmetatable({}, AttackStrategy) function MagicStrategy:attack(enemy) print("魔法攻击造成80伤害,消耗20法力") enemy:takeDamage(80) end local Player = {} Player.__index = Player function Player.new() local self = setmetatable({}, Player) self.attack_strategy = MeleeStrategy return self end function Player:setAttackStrategy(strategy) self.attack_strategy = strategy end function Player:attack(enemy) self.attack_strategy:attack(enemy) end local player = Player.new() player:attack(enemy) player:setAttackStrategy(RangedStrategy) player:attack(enemy) player:setAttackStrategy(MagicStrategy) player:attack(enemy) ``` ### 四、优化型模式 #### 10. 数据驱动模式 (Data-Driven) 将游戏数据与逻辑分离。 代码示例: ```lua local enemy_data = { goblin = {health = 100, damage = 10, speed = 5, model = "goblin.obj", texture = "goblin.png"}, orc = {health = 200, damage = 20, speed = 3, model = "orc.obj", texture = "orc.png"}, dragon = {health = 1000, damage = 100, speed = 8, model = "dragon.obj", texture = "dragon.png", abilities = {"fire_breath", "fly"}} } local EnemyFactory = {} function EnemyFactory.create(type) local data = enemy_data[type] if not data then return nil end local enemy = { health = data.health, damage = data.damage, speed = data.speed, model = data.model, texture = data.texture } return enemy end local goblin = EnemyFactory.create("goblin") local dragon = EnemyFactory.create("dragon") ``` #### 11. 空间分区模式 (Spatial Partition) 优化空间查询性能。 代码示例: ```lua local Grid = {} Grid.__index = Grid function Grid.new(width, height, cell_size) local self = setmetatable({}, Grid) self.cell_size = cell_size self.cells = {} self.width = width self.height = height return self end function Grid:getCellKey(x, y) local cx = math.floor(x / self.cell_size) local cy = math.floor(y / self.cell_size) return cx .. "," .. cy end function Grid:addEntity(entity) local key = self:getCellKey(entity.x, entity.y) if not self.cells[key] then self.cells[key] = {} end table.insert(self.cells[key], entity) entity.cell_key = key end function Grid:getNearbyEntities(x, y, radius) local nearby = {} local cell_radius = math.ceil(radius / self.cell_size) local cx = math.floor(x / self.cell_size) local cy = math.floor(y / self.cell_size) for dx = -cell_radius, cell_radius do for dy = -cell_radius, cell_radius do local key = (cx + dx) .. "," .. (cy + dy) if self.cells[key] then for _, entity in ipairs(self.cells[key]) do local dist = math.sqrt((entity.x - x)^2 + (entity.y - y)^2) if dist <= radius then table.insert(nearby, entity) end end end end end return nearby end ``` ### 五、游戏特定模式 #### 12. 更新循环模式 (Update Loop) 驱动游戏逻辑的持续执行。 代码示例: ```lua local GameLoop = {} GameLoop.__index = GameLoop function GameLoop.new() local self = setmetatable({}, GameLoop) self.last_time = 0 self.accumulator = 0 self.update_interval = 1 / 60 self.updatables = {} return self end function GameLoop:addUpdatable(obj) table.insert(self.updatables, obj) end function GameLoop:run() local current_time = love.timer.getTime() local delta_time = current_time - self.last_time self.last_time = current_time self.accumulator = self.accumulator + delta_time while self.accumulator >= self.update_interval do for _, obj in ipairs(self.updatables) do obj:update(self.update_interval) end self.accumulator = self.accumulator - self.update_interval end for _, obj in ipairs(self.updatables) do obj:draw() end end ``` #### 13. 双缓冲模式 (Double Buffer) 避免渲染撕裂,实现平滑动画。 代码示例: ```lua local DoubleBuffer = {} DoubleBuffer.__index = DoubleBuffer function DoubleBuffer.new(initial_data) local self = setmetatable({}, DoubleBuffer) initial_data = initial_data or {x = 0, y = 0} self.front = {x = initial_data.x, y = initial_data.y} self.back = {x = initial_data.x, y = initial_data.y} return self end function DoubleBuffer:write(data) self.back.x = data.x self.back.y = data.y end function DoubleBuffer:swap() self.front, self.back = self.back, self.front end function DoubleBuffer:read() return self.front end -- 游戏对象 local GameObject = {} GameObject.__index = GameObject function GameObject.new(x, y) local self = setmetatable({}, GameObject) self.position = DoubleBuffer.new({x = x or 0, y = y or 0}) self.velocity = {x = 1, y = 0} -- 向右移动 return self end function GameObject:update(dt) -- 读取当前位置 local current = self.position:read() -- 计算新位置 local new_x = current.x + self.velocity.x * dt local new_y = current.y + self.velocity.y * dt -- 写入后台缓冲 self.position:write({x = new_x, y = new_y}) -- 交换前后台 self.position:swap() end function GameObject:draw() local pos = self.position:read() print(string.format("绘制位置: (%.2f, %.2f)", pos.x, pos.y)) end -- 模拟游戏循环 local obj = GameObject.new(0, 0) local dt = 0.1 for i = 1, 5 do print("\n--- 帧", i, "---") obj:update(dt) obj:draw() end -- 输出示例: -- --- 帧 1 --- -- 绘制位置: (0.10, 0.00) -- --- 帧 2 --- -- 绘制位置: (0.20, 0.00) -- --- 帧 3 --- -- 绘制位置: (0.30, 0.00) ``` #### 14. 游戏状态管理 (Game State) 代码示例: ```lua -- 简化的状态管理器 local StateManager = { states = {}, current = nil } function StateManager:add(name, state) state.name = name self.states[name] = state end function StateManager:switch(name, ...) if self.current and self.current.onExit then self.current:onExit() end self.current = self.states[name] if not self.current then error("State not found: " .. name) end if self.current.onEnter then self.current:onEnter(...) end end function StateManager:update(dt) if self.current and self.current.onUpdate then self.current:onUpdate(dt) end end function StateManager:draw() if self.current and self.current.onDraw then self.current:onDraw() end end -- 创建状态 local menuState = { onEnter = function() print("进入菜单") end, onUpdate = function(dt) -- 检测输入 if love and love.keyboard.isDown("return") then StateManager:switch("game") end end, onDraw = function() print("绘制菜单") end } local gameState = { player = {health = 100}, onEnter = function(level) print("进入游戏,关卡: " .. level) self.player.health = 100 end, onUpdate = function(dt) if self.player.health <= 0 then StateManager:switch("gameover") end end, onDraw = function() print("绘制游戏,血量: " .. self.player.health) end } local gameOverState = { onEnter = function(score) print("游戏结束,得分: " .. score) end, onUpdate = function(dt) if love and love.keyboard.isDown("return") then StateManager:switch("menu") end end, onDraw = function() print("绘制游戏结束画面") end } -- 注册状态 StateManager:add("menu", menuState) StateManager:add("game", gameState) StateManager:add("gameover", gameOverState) -- 启动游戏 StateManager:switch("menu") ``` ### 六、设计模式选择指南 | 场景 | 推荐模式 | |------|----------| | 需要全局唯一实例 | 单例模式 | | 频繁创建销毁对象 | 对象池模式 | | 对象有多种状态 | 状态模式 | | 需要撤销/重做功能 | 命令模式 | | 系统间需要解耦 | 观察者模式 | | 算法可互换 | 策略模式 | | 优化空间查询 | 空间分区 | | 动态组合功能 | 组件模式 | | 游戏数据配置 | 数据驱动 | ### 七、最佳实践 1. 不要过度设计:简单场景用简单方案 2. 性能优先:游戏开发中性能是关键 3. 代码可读性:团队协作时尤为重要 4. 迭代优化:先实现功能,再优化性能 5. 选择合适模式:根据具体问题选择,不强行套用
评论 0

发表评论 取消回复

Shift+Enter 换行  ·  Enter 发送
还没有评论,来发表第一条吧