26_ConsoleInput.lua 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. -- Console input example.
  2. -- This sample demonstrates:
  3. -- - Implementing a crude text adventure game, which accepts input both through the engine console,
  4. -- and standard input.
  5. -- - Disabling default execution of console commands as immediate mode Lua script.
  6. -- - Adding autocomplete options to the engine console.
  7. require "LuaScripts/Utilities/Sample"
  8. local gameOn = false
  9. local foodAvailable = false
  10. local eatenLastTurn = false
  11. local numTurns = 0
  12. local hunger = 0
  13. local urhoThreat = 0
  14. -- Hunger level descriptions
  15. local hungerLevels = {
  16. "bursting",
  17. "well-fed",
  18. "fed",
  19. "hungry",
  20. "very hungry",
  21. "starving"
  22. }
  23. -- Urho threat level descriptions
  24. local urhoThreatLevels = {
  25. "Suddenly Urho appears from a dark corner of the fish tank",
  26. "Urho seems to have his eyes set on you",
  27. "Urho is homing in on you mercilessly"
  28. }
  29. function Start()
  30. -- Execute the common startup for samples
  31. SampleStart()
  32. -- Disable default execution of Lua from the console
  33. SetExecuteConsoleCommands(false)
  34. -- Subscribe to console commands and the frame update
  35. SubscribeToEvent("ConsoleCommand", "HandleConsoleCommand")
  36. SubscribeToEvent("Update", "HandleUpdate")
  37. -- Subscribe key down event
  38. SubscribeToEvent("KeyDown", "HandleEscKeyDown")
  39. -- Hide logo to make room for the console
  40. SetLogoVisible(false)
  41. -- Show the console by default, make it large
  42. console.numRows = graphics.height / 16
  43. console.numBufferedRows = 2 * console.numRows
  44. console.commandInterpreter = "LuaScriptEventInvoker"
  45. console.visible = true
  46. console.closeButton.visible = false
  47. console:AddAutoComplete("help")
  48. console:AddAutoComplete("eat")
  49. console:AddAutoComplete("hide")
  50. console:AddAutoComplete("wait")
  51. console:AddAutoComplete("score")
  52. console:AddAutoComplete("quit")
  53. -- Show OS mouse cursor
  54. input.mouseVisible = true
  55. -- Set the mouse mode to use in the sample
  56. SampleInitMouseMode(MM_FREE)
  57. -- Open the operating system console window (for stdin / stdout) if not open yet
  58. -- Do not open in fullscreen, as this would cause constant device loss
  59. if not graphics.fullscreen then
  60. OpenConsoleWindow()
  61. end
  62. -- Initialize game and print the welcome message
  63. StartGame()
  64. -- Randomize from system clock
  65. SetRandomSeed(Time:GetSystemTime())
  66. end
  67. function HandleConsoleCommand(eventType, eventData)
  68. if eventData["Id"]:GetString() == "LuaScriptEventInvoker" then
  69. HandleInput(eventData["Command"]:GetString())
  70. end
  71. end
  72. function HandleUpdate(eventType, eventData)
  73. -- Check if there is input from stdin
  74. local input = GetConsoleInput()
  75. if input:len() > 0 then
  76. HandleInput(input)
  77. end
  78. end
  79. function HandleEscKeyDown(eventType, eventData)
  80. -- Unlike the other samples, exiting the engine when ESC is pressed instead of just closing the console
  81. if eventData["Key"]:GetInt() == KEY_ESCAPE then
  82. engine:Exit()
  83. end
  84. end
  85. function StartGame()
  86. print("Welcome to the Urho adventure game! You are the newest fish in the tank your\n" ..
  87. "objective is to survive as long as possible. Beware of hunger and the merciless\n" ..
  88. "predator cichlid Urho, who appears from time to time. Evading Urho is easier\n" ..
  89. "with an empty stomach. Type 'help' for available commands.")
  90. gameOn = true
  91. foodAvailable = false
  92. eatenLastTurn = false
  93. numTurns = 0
  94. hunger = 2
  95. urhoThreat = 0
  96. end
  97. function EndGame(message)
  98. print(message)
  99. print("Game over! You survived " .. numTurns .. " turns.\n" ..
  100. "Do you want to play again (Y/N)?")
  101. gameOn = false
  102. end
  103. function Advance()
  104. if urhoThreat > 0 then
  105. urhoThreat = urhoThreat + 1
  106. if urhoThreat > 3 then
  107. EndGame("Urho has eaten you!")
  108. return
  109. end
  110. elseif urhoThreat < 0 then
  111. urhoThreat = urhoThreat + 1
  112. elseif urhoThreat == 0 and Random() < 0.2 then
  113. urhoThreat = urhoThreat + 1
  114. end
  115. if urhoThreat > 0 then
  116. print(urhoThreatLevels[urhoThreat] .. ".")
  117. end
  118. if (numTurns % 4) == 0 and not eatenLastTurn then
  119. hunger = hunger + 1
  120. if hunger > 5 then
  121. EndGame("You have died from starvation!")
  122. return
  123. else
  124. print("You are " .. hungerLevels[hunger + 1] .. ".")
  125. end
  126. end
  127. eatenLastTurn = false
  128. if foodAvailable then
  129. print("The floating pieces of fish food are quickly eaten by other fish in the tank.")
  130. foodAvailable = false
  131. elseif Random() < 0.15 then
  132. print("The overhead dispenser drops pieces of delicious fish food to the water!")
  133. foodAvailable = true
  134. end
  135. numTurns = numTurns + 1
  136. end
  137. function TrimInput(input)
  138. return input:gsub("^%s*(.-)%s*$", "%1")
  139. end
  140. function HandleInput(input)
  141. local inputLower = TrimInput(input:lower())
  142. if inputLower:len() == 0 then
  143. print("Empty input given!")
  144. return
  145. end
  146. if inputLower == "quit" or inputLower == "exit" then
  147. engine:Exit()
  148. elseif gameOn then
  149. -- Game is on
  150. if inputLower == "help" then
  151. print("The following commands are available: 'eat', 'hide', 'wait', 'score', 'quit'.")
  152. elseif inputLower == "score" then
  153. print("You have survived " .. numTurns .. " turns.")
  154. elseif inputLower == "eat" then
  155. if foodAvailable then
  156. print("You eat several pieces of fish food.")
  157. foodAvailable = false
  158. eatenLastTurn = true
  159. if hunger > 3 then
  160. hunger = hunger - 2
  161. else
  162. hunger = hunger - 1
  163. end
  164. if hunger < 0 then
  165. EndGame("You have killed yourself by over-eating!")
  166. return
  167. else
  168. print("You are now " .. hungerLevels[hunger + 1] .. ".")
  169. end
  170. else
  171. print("There is no food available.")
  172. end
  173. Advance()
  174. elseif inputLower == "wait" then
  175. print("Time passes...")
  176. Advance()
  177. elseif inputLower == "hide" then
  178. if urhoThreat > 0 then
  179. local evadeSuccess = hunger > 2 or Random() < 0.5
  180. if evadeSuccess then
  181. print("You hide behind the thick bottom vegetation, until Urho grows bored.")
  182. urhoThreat = -2
  183. else
  184. print("Your movements are too slow you are unable to hide from Urho.")
  185. end
  186. else
  187. print("There is nothing to hide from.")
  188. end
  189. Advance()
  190. else
  191. print("Cannot understand the input '" .. input .. "'.")
  192. end
  193. else
  194. -- Game is over, wait for (y)es or (n)o reply
  195. local c = inputLower:sub(1, 1)
  196. if c == 'y' then
  197. StartGame()
  198. elseif c == 'n' then
  199. engine:Exit()
  200. else
  201. print("Please answer 'y' or 'n'.")
  202. end
  203. end
  204. end
  205. -- Create XML patch instructions for screen joystick layout specific to this sample app
  206. function GetScreenJoystickPatchString()
  207. return
  208. "<patch>" ..
  209. " <add sel=\"/element/element[./attribute[@name='Name' and @value='Button2']]\">" ..
  210. " <attribute name=\"Is Visible\" value=\"false\" />" ..
  211. " </add>" ..
  212. " <add sel=\"/element/element[./attribute[@name='Name' and @value='Hat0']]\">" ..
  213. " <attribute name=\"Is Visible\" value=\"false\" />" ..
  214. " </add>" ..
  215. "</patch>"
  216. end