Text adventures & state machines (a newb approaches!)
- trubblegum
- Party member
- Posts: 192
- Joined: Wed Feb 22, 2012 10:40 pm
Re: Text adventures & state machines (a newb approaches!)
Very limited time today, but in short : Not worth it - try this : viewtopic.php?p=53634#p53634
Re: Text adventures & state machines (a newb approaches!)
in My opinion this is the simplest (I use it):
Code: Select all
local state = 1
local x = 300
local y = 200
local drawfunc = {}
function dtawanim()
love.graphics.print("state: "..state,x,y)
end
drawfunc[1] = function()
love.graphics.print(":)",30,30)
dtawanim()
end
drawfunc[2] = function()
love.graphics.print(":|",30,30)
dtawanim()
end
drawfunc[3] = function()
love.graphics.print(":(",30,30)
dtawanim()
end
function love.draw()
if drawfunc[state] then drawfunc[state]() end
end
local updatefunc = {}
updatefunc[1] = function(dt)
x = x + 20*dt
if x > 450 then x = 300 end
end
updatefunc[2] = function(dt)
y = y + 20*dt
if y > 350 then y = 200 end
end
updatefunc[3] = function(dt)
updatefunc[1](dt)
updatefunc[2](dt)
end
function love.update(dt)
if updatefunc[state] then updatefunc[state](dt) end
end
local keys = {
{["a"] = function()
state = 1
end,
["s"] = function()
state = 2
end,
["d"] = function()
state = 3
end},
{["a"] = function()
state = 3
end,
["s"] = function()
state = 2
end,
["d"] = function()
state = 1
end},
{["a"] = function()
state = 2
end,
["s"] = function()
state = 1
end,
["d"] = function()
state = 3
end}
}
function love.keypressed(key)
if keys[state] and keys[state][key] then keys[state][key]() end
end
Re:
I've commented it fairly heavily, hopefully it will help:a neobum wrote:That much I gathered and I was told that it's far from a smooth implementation. But I was hoping somebody would walk me through the process; function by function and explain what's doing what to what, in what order, why things are where they are and so on. Yes, folks, I'm really that thick.
Code: Select all
function love.load() --anything in here is called when the game first loads, and can be called manually later to reset the game
love.graphics.setFont(12) --sets the size of the current font object
StateManager = {} --creates a new table called StateManager
function StateManager:processKey(key)
--[[
^^ this creates a new function inside the table StateManager. The ":" is syntactical sugar for creating a method
you could also use:
StateManager.processKey = function(self, key)
function StateManager.processKey(self,key)
Here, "self" reffers to StateManager, ":" just hides its declaration.
"key" is the key that is detected and pass over from love.keyreleased
]]
local returnState = self.state.actionList[key] -- this looks for the key in the actionlist table
if (returnState ~= nil) then --this could be written "if returnStat then" - it just checks to see if the state had an option for the key that was pressed
self.state = returnState --sets the state of the current state to the state that is assigned to the key (e.g. presssing space would return state 2 the first time around)
end
end
function StateManager:show() --function called when we want to print the text that the state contains
return self.state.message -- return passes the message back to the calling function
end
function StateManager.init(state) --this creates a new state
local stateManager = { state = state, processKey = StateManager.processKey, show = StateManager.show }
--[[
this is kind of semi object oriented - it creates a new statemanager, and assigns the functions of the StateManager to the new state
and stores the state passed to this function inside the new state manager
]]
return stateManager --passes the newly created statemanager back to the calling function
end
State = {} -- creates a new table called State
function State.init(message, actionList) -- function that converts the two parameters passed to it into a table, and then returns that table
local state = { message = message, actionList = actionList }
return state
end
state1 = State.init("Hello Wörld! \n\n (Press SPACE to proceed.)", nil)
state2 = State.init("Are you impressed? \n\n\n1. YES \n\n2. NO", nil)
state3 = State.init("Good. You should be. After all, neobums rock! \n\n (Press ENTER to restart)", nil)
state4 = State.init("Saw through it did you? Yeah, Drav wrote this shit and I just copied it. \nI don't even know what half this code does! \n\n (Press ENTER to restart)", nil)
--these assign options to the above states:
state1.actionList = { [" "] = state2 }
state2.actionList = { ["1"] = state3, ["2"] = state4 }
state3.actionList = { ["return"] = state1 }
state4.actionList = { ["return"] = state1 }
StateManager = StateManager.init(state1) --sets up the first state
end
function love.keyreleased(key)--detects any key presses
StateManager:processKey(key)--passes them to the statemanager
end
function love.draw()
love.graphics.setColor(0, 255, 255, 255)
love.graphics.print(StateManager:show(), 100, 100)--calls the show function to find out what to print
end
Re:
For anyone that needs this necro-revival:
I've created a table called states{}, holding the two possible states, and a variable called state. In essence all that happens is some substitution in the love.update() and love.draw() functions.
The file menu.lua has an update() function and a draw() function and the file options.lua also has its own update() and draw() functions - which gets called depends simply upon the value of the 'state' variable.
Using this scheme you can create whatever states you need and keep the code for each state in its own file. How to change states? Well in the menu.lua file foer example, you'll have some code that detects when the user chooses to start a game and you change the state from 'menu' to 'playing'. Hope that helps - I don't suppose it's the best method but it seems not too hard to figure out IMHO.
Errors and omissions excepted!
This is a very simple state machine set-up and might help, especially as it consists of very few lines of code! This code goes in main.lua and needs two other files, 'menu.lua' and 'options.lua', representing the stuff that goes on in the main menu and the options screen of a game (in reality you'd have a bunch of other states such a 'playing' or 'game over' or whatever.a neobum wrote:That much I gathered and I was told that it's far from a smooth implementation. But I was hoping somebody would walk me through the process; function by function and explain what's doing what to what, in what order, why things are where they are and so on. Yes, folks, I'm really that thick.
I've created a table called states{}, holding the two possible states, and a variable called state. In essence all that happens is some substitution in the love.update() and love.draw() functions.
The file menu.lua has an update() function and a draw() function and the file options.lua also has its own update() and draw() functions - which gets called depends simply upon the value of the 'state' variable.
Code: Select all
local menuModule = require("menu")
local optionsModule = require("options")
-- some states
local states = {
["menu"] = menuModule,
["options"] = optionModule
}
-- set the initial game state to states["menu"] which has the value 'menuModule' in the above table
-- it's easier to type 'states.menu' than states["menu"] so that's what I've done here:
local state = states.menu
-- the state variable now holds the value 'menuModule'
-- in the standard love.update() callback function...
function love.update(dt)
-- call the update function for the current state
state.update(dt)
-- so in our case the above line acts as though it was written menuModule.update(dt)
-- and as a result, the function update(dt) in the file 'menu.lua' gets called
-- if the current state was set to state.options then the above line would be interpreted as optionModule.update(dt) and
-- update(dt) in 'options.lua' would be called instead
end
-- in the standard love.draw() callback function...
function love.draw()
-- this works in the same way as the update function above
-- so in our case it will call menuModule.draw()
state.draw()
-- if the current state was set to state.options then the above line would be interpreted as optionModule.draw() and
-- draw() in the file 'options.lua' would be called
end
function love.keypressed(k)
-- this would work in the same way as the two functions above so I'm not going to type it all out again :P
end
end
Errors and omissions excepted!
Re: Text adventures & state machines (a newb approaches!)
There's a good read imo Game Programming Patterns. It has a chapter on State Machines with drawings, explanations on where and why use them, and code examples.
Re: Text adventures & state machines (a newb approaches!)
That's a handy link - thanks!Rucikir wrote:There's a good read imo Game Programming Patterns. It has a chapter on State Machines with drawings, explanations on where and why use them, and code examples.
Who is online
Users browsing this forum: Amazon [Bot] and 5 guests