Mousetat

Snake minigame

Jan 10th, 2017
445
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 11.79 KB | None | 0 0
  1. --Write your name here
  2. admin = "Tat#0020"
  3.  
  4. add = ui.addTextArea
  5. rem = ui.removeTextArea
  6.  
  7. isPlaying = false
  8. foodMov = 0
  9.  
  10. gamemode = "Classic"
  11.  
  12. playersAlive = 0
  13.  
  14. --Arrow keys and WASD
  15. LEFT = 0; UP = 1; RIGHT = 2; DOWN = 3;
  16.  
  17. function main()
  18. admin = admin:lower():gsub("^%l", string.upper) --All letters must be lowercase except the first one
  19. local errorText, name = string.format("%q is not in the room, or doesn't exist.", admin)
  20. local map = "@7004831"
  21. --Whoever is in the pos [1] is the current player
  22. playerList = {admin} --Admin is the first player
  23. --Admin name control
  24. for k in pairs(tfm.get.room.playerList) do
  25. if k==admin then
  26. name = true
  27. break
  28. end
  29. end
  30. if not name then
  31. error(errorText)
  32. end
  33. tfm.exec.setGameTime(0, false)
  34. tfm.exec.disableAfkDeath()
  35. tfm.exec.disableAutoShaman()
  36. tfm.exec.disableAutoTimeLeft()
  37. tfm.exec.disableAutoNewGame()
  38. tfm.exec.disableMortCommand()
  39. tfm.exec.newGame(map)
  40. ui.setMapName("Snake!\n")
  41. add(-3, "<a href='event:play'>Classic</a>", nil, 755, 375)
  42. add(-4, "<a href='event:exit'>Exit</a>", admin, 605, 375)
  43. add(-5, "<a href='event:SS'>SnakeShaman</a>", admin, 650, 375)
  44. end
  45.  
  46. function checkPlayers(p)
  47. if p == 0 then tfm.exec.newGame(maps[math.random(#maps)]); end
  48. end
  49.  
  50. function eventNewPlayer(name)
  51. if gamemode=="Classic" then
  52. add(-3, "<a href='event:play'>Play</a>", name, 755, 375)
  53. add(0, "", name, 2, 38, 791, 254, 0x378990, 0x000000)
  54. if isPlaying then
  55. add(-1, "", name, pos.foodX, pos.foodY, 10, 10, math.random(0x00AA00, 0x00FF00), math.random(0x00AA00, 0x00FF00))
  56. ui.setMapName("Snake! <font color='#6A7495'>|</font> <font color='#C2C2DA'>Length: "..len.."</font>\n")
  57. end
  58. tfm.exec.respawnPlayer(name)
  59. end
  60. end
  61.  
  62. function eventPlayerWon(name)
  63. playersAlive = playersAlive - 1
  64. checkPlayers(playersAlive)
  65. end
  66.  
  67. function eventPlayerLeft(name)
  68. if gamemode=="Classic" then
  69. for i, k in pairs(playerList) do
  70. if name==k then
  71. for j=i, #playerList do
  72. playerList[j] = playerList[j+1]
  73. end
  74. break
  75. end
  76. end
  77. end
  78. end
  79.  
  80. function eventPlayerDied(name)
  81. playersAlive = playersAlive - 1
  82. checkPlayers(playersAlive)
  83. end
  84.  
  85. function eventNewGame()
  86. local xIni = 400
  87. playersAlive = 0
  88. if gamemode~="SS" then return; end
  89. headDef = {type=12, width=20, height=20, foreground=true, friction=0.3, restitution=0.2, angle=0, color=0x4AFF00}
  90. bodyDef = {type=12, width=20, height=20, foreground=true, friction=0.3, restitution=0.2, angle=0, color=0x33AE01}
  91. shamanName = ""
  92. for name in pairs(tfm.get.room.playerList) do
  93. playersAlive = playersAlive + 1
  94. if tfm.get.room.playerList[name].isShaman then shamanName = name; end
  95. end
  96. pos = {x = {}, y = {}, headX = 400, headY = 180}
  97. pressedKey = RIGHT
  98. len = 7
  99. tfm.exec.setUIShamanName("Snake ("..shamanName..")")
  100. tfm.exec.addPhysicObject(1, 400, 180, headDef)
  101. table.foreachi({LEFT, UP, RIGHT, DOWN}, function(_,l) system.bindKeyboard(shamanName, l, true, true) end) --Bind keys to the player
  102. for i=2, len do --Body
  103. xIni = xIni - 20
  104. pos.x[i], pos.y[i] = xIni, 180
  105. tfm.exec.addPhysicObject(i, xIni, 180, bodyDef)
  106. end
  107. timerTextArea(99, "<font size='12'>You are the shaman! Save the mice by moving the snake.</font>", shamanName, 225, 370, 4, nil, nil, 0x1b232a,0x000000)
  108. tfm.exec.killPlayer(shamanName)
  109. tfm.exec.setGameTime (120)
  110. end
  111.  
  112. function eventTextAreaCallback(id, name, event)
  113. local p = 0
  114. maps = {0,1,2,3,4,5,6,10,11,12,13,15,16,17,18,19,20,21,24,25,26,27,30,39,40,54,56,60,62,66,71,72,73,75,76,79,86,90,91,93,96,99,100,101,102,103,104,105,106,107,115,116,117,118,119,130,131,132,133,134,146}
  115. if event=="play" and gamemode~="SS" then
  116. gamemode = "Classic"
  117. if name~=playerList[1] and not gameover then --Is name the current player?
  118. for i, k in pairs(playerList) do
  119. if k==name then --Is name in the player list?
  120. timerTextArea(100, "Already in the player list, your current position is: "..i..".", name, 275, 300, 5, nil, nil, 0x1b232a,0x000000)
  121. return
  122. end
  123. end
  124. table.insert(playerList, name) --name isn't the current player nor is in the list so ill save his name
  125. timerTextArea(101, "You've been added to the player list, your current position is: "..#playerList..".", name, 275, 327, 5, nil, nil, 0x1b232a,0x000000)
  126. elseif gameover then --Is the game over textarea showing?
  127. timerTextArea(102, "Wait until 'GAME OVER' get erased.", name, 275, 354, 5, nil, nil, 0x1b232a,0x000000)
  128. else
  129. timerTextArea(103, "You're already playing!", name, 275, 378, 5, nil, nil, 0x1b232a,0x000000)
  130. end
  131. elseif event=="SS" and gamemode=="" then
  132. for _ in pairs(tfm.get.room.playerList) do
  133. p = p + 1
  134. end
  135. if p <= 2 then ui.addPopup (0, 0, "You need at least 3 mice in the room to play this.", admin, 275, 304); return; end
  136. tfm.exec.disableAfkDeath(false)
  137. tfm.exec.disableAutoNewGame(false)
  138. tfm.exec.disableAutoShaman(false)
  139. tfm.exec.disableAutoTimeLeft(false)
  140. tfm.exec.disableMortCommand(false)
  141. tfm.exec.disableAllShamanSkills()
  142. gamemode = event --SS
  143. for i=-1, len do
  144. rem(i)
  145. end
  146. tfm.exec.newGame(maps[math.random(#maps)])
  147. elseif gamemode=="SS" and event=="play" and name==admin then
  148. ui.addPopup (1, 1, "Are you sure you want to leave the SnakeShaman mode?", admin, 300, 200)
  149. elseif event=="exit" and name==admin then
  150. system.exit()
  151. end
  152. end
  153.  
  154. function eventPopupAnswer(id, name, answer)
  155. if answer=="yes" and name==admin then
  156. table.foreachi({LEFT, UP, RIGHT, DOWN}, function(_,l) system.bindKeyboard(shamanName, l, true, false) end)
  157. gamemode = "Classic"
  158. for i=1, len do
  159. tfm.exec.removePhysicObject(i)
  160. end
  161. main()
  162. end
  163. end
  164.  
  165. function gamemodeClassic(reset)
  166. local xIni = 400 --Body's initial position
  167. rem(-2) --Remove game over textarea if exists
  168. pos = {x = {}, y = {}, headX = 400, headY = 180, foodX = nil, foodY = nil} --Coords of everything here
  169. pressedKey = RIGHT
  170. ui.setMapName("Snake!\n")
  171. if reset then
  172. return
  173. end
  174. len = 3 --Snake's length, don't touch this!!
  175. add(0, "", nil, 2, 38, 791, 254, 0x378990, 0x000000) --Show the "map"
  176. table.foreachi({LEFT, UP, RIGHT, DOWN}, function(_,l) system.bindKeyboard(playerList[1], l, true, true) end) --Bind keys to the player
  177. add(1, "", nil, 400, 180, 10, 10, 0x4AFF00, 0x4AFF00) --Head
  178. for i=2, len do --Body
  179. xIni = xIni - 20
  180. pos.x[i], pos.y[i] = xIni, 180
  181. add(i, "", nil, xIni, 180, 10, 10, 0x33AE01, 0x33AE01)
  182. end
  183. ui.setMapName("Snake! <font color='#6A7495'>|</font> <font color='#C2C2DA'>Length: "..len.."</font>\n")
  184. drawFood() --The food textarea
  185. timerTextArea(99, "<font size='12'>Now is playing: "..playerList[1].."</font>", nil, 275, 273, 6, nil, nil, 0x1b232a,0x000000)
  186. tfm.exec.killPlayer(playerList[1])
  187. end
  188.  
  189. function drawFood()
  190. local _x, _y
  191. repeat --These are the map's limits
  192. _x = math.random(0, 780)
  193. _y = math.random(40, 280)
  194. until _x%20==0 and _y%20==0 --They must be divisible by 20 to match the movement of the snake
  195. pos.foodX, pos.foodY = _x, _y
  196. add(-1, "", nil, _x, _y, 10, 10, math.random(0x00AA00, 0x00FF00), math.random(0x00AA00, 0x00FF00))
  197. end
  198.  
  199. keyDelay = false --To avoid weird moves when pressing two keys at the same time
  200.  
  201. function eventKeyboard(name, key, down)
  202. local function forbiddenMovs(k, k2) --I was testing local functions here, it worked so i left it like this, it could be better though
  203. local e = (k==k2) or (k==RIGHT and k2==LEFT) or (k==LEFT and k2==RIGHT) or (k==DOWN and k2==UP) or (k==UP and k2==DOWN) --Forbidden movs
  204. return e
  205. end
  206. if name==playerList[1] or (name==shamanName and gamemode=="SS") and not keyDelay then
  207. if forbiddenMovs(pressedKey, key) or keyDelay then --If forbiddenMovs or keyDelay is true, the mov won't be executed
  208. return
  209. end
  210. keyDelay = true
  211. pressedKey = key
  212. end
  213. end
  214.  
  215. function movSnake(k, SS)
  216. local oldX, oldY = pos.headX, pos.headY --Save the head's current pos
  217. local _x, _y = 0, 0
  218. if k==LEFT then --Performs the movement according to the last key pressed
  219. pos.headX = pos.headX - 20
  220. elseif k==DOWN then
  221. pos.headY = pos.headY + 20
  222. elseif k==UP then
  223. pos.headY = pos.headY - 20
  224. elseif k==RIGHT then
  225. pos.headX = pos.headX + 20
  226. end
  227. pos.x[1], pos.y[1] = pos.headX, pos.headY --Save the head's new coords
  228. if SS then tfm.exec.addPhysicObject(1, pos.x[1], pos.y[1], headDef);
  229. else add(1, "", nil, pos.x[1], pos.y[1], 10, 10, 0x4AFF00, 0x4AFF00); end --Show head
  230. for i=2, len do --Show body in its new position
  231. _x, _y = pos.x[i], pos.y[i] --Save old coords
  232. pos.x[i], pos.y[i] = oldX, oldY --Save new coords
  233. if SS then tfm.exec.addPhysicObject(i, oldX, oldY, bodyDef);
  234. else add(i, "", nil, oldX, oldY, 10, 10, 0x33AE01, 0x33AE01); end --Show it in old coords of the following textarea
  235. oldX, oldY = _x, _y --Update coords to the next textarea
  236. end
  237. end
  238.  
  239. tick = 0
  240. gameover = false
  241.  
  242. function gameOver()
  243. table.foreachi({LEFT, UP, RIGHT, DOWN}, function(_,l) system.bindKeyboard(playerList[1], l, true, false) end)
  244. gameover = true
  245. tick = 6000 --6 sec until gameover textarea get erased
  246. tfm.exec.respawnPlayer(playerList[1])
  247. isPlaying = false
  248. for i=1, #playerList do
  249. playerList[i] = playerList[i+1]
  250. end
  251. end
  252.  
  253. function checkCoord()
  254. --Game over--
  255. if ((pos.headX <= -20 or pos.headX >= 800) or (pos.headY <= 20 or pos.headY >= 300)) then
  256. gameOver()
  257. end
  258. for i=2, #pos.x do
  259. if pos.x[i] == pos.headX and pos.y[i] == pos.headY then
  260. gameOver()
  261. end
  262. end
  263. --Grow 1 textarea--
  264. if pos.headX == pos.foodX and pos.headY == pos.foodY then
  265. rem(-1)
  266. drawFood()
  267. len = len + 1
  268. ui.setMapName("Snake! <font color='#6A7495'>|</font> <font color='#C2C2DA'>Length: "..len.."</font>\n")
  269. if len>10 and foodMov==0 then --The food textarea'll start moving when the snake gets 10
  270. foodMov = math.random(9000, 12000)
  271. foodMov = foodMov - (foodMov % 100)
  272. end
  273. end
  274. end
  275.  
  276. ta = {}
  277. can = 0
  278.  
  279. function timerTextArea(id, te, tr, x, y, t, wi, hei, bc, bo, alp, fpos) --Same parameters as a textarea, adding time
  280. add(id, te, tr, x, y, wi, hei, bc, bo, alp, fpos) --Show textarea
  281. ta[tostring(can)] = {t*1000, id}
  282. can = can + 1
  283. end
  284.  
  285. main()
  286.  
  287. function classicLoop()
  288. if #playerList>0 and not isPlaying and not gameover then --Start playing when playerList has at least one name
  289. isPlaying = true
  290. gamemode = "Classic"
  291. gamemodeClassic()
  292. end
  293. if isPlaying and not gameover then
  294. if len>10 and foodMov>0 then
  295. foodMov = foodMov - 500
  296. if foodMov<=0 then
  297. rem(-1)
  298. drawFood()
  299. foodMov = math.random(9000, 12000)
  300. foodMov = foodMov - (foodMov % 100)
  301. end
  302. end
  303. movSnake(pressedKey)
  304. checkCoord()
  305. end
  306. if tick>0 and gameover then --Esto se ejecuta siempre que tick sea mayor a cero, y gameover sea true
  307. add(-2, "<font size='25' color='#FFFFFF'><p align='center'>GAME OVER</p></font>", nil, 300, 180, nil, nil, math.random(0x000000, 0xBD1E1E))
  308. tick = tick - 500
  309. elseif tick==0 and gameover then
  310. gamemode = ""
  311. gamemodeClassic(true)
  312. for i=1, len do
  313. rem(i)
  314. end
  315. rem(-1)
  316. gameover = false
  317. foodMov = 0
  318. ui.setMapName("Snake! <font color='#6A7495'>|</font> <font color='#C2C2DA'>Waiting player... (click on Classic!)</font>\n")
  319. add(0, "", nil, 2, 38, 791, 254, 0x378990, 0x000000)
  320. end
  321. end
  322.  
  323. function SSLoop()
  324. movSnake(pressedKey, true)
  325. if pos.x[1] >= 920 or pos.x[1] <= -120 then pressedKey = UP; end
  326. if pos.y[1] >= 420 or pos.y[1] <= -100 then pressedKey = LEFT; end
  327. end
  328.  
  329. function eventLoop(t, tr)
  330. if gamemode=="Classic" or #playerList>0 then classicLoop();
  331. elseif gamemode=="SS" then SSLoop(); end
  332. if can > 0 then --This weird thing control temporary textareas
  333. for i,k in pairs (ta) do
  334. if ta[i][1] > 0 then
  335. ta[i][1] = ta[i][1] - 500
  336. else
  337. rem(ta[i][2])
  338. ta[i] = nil
  339. can = can - 1
  340. break
  341. end
  342. end
  343. end
  344. if keyDelay then keyDelay = false; end
  345. if tr <= 300 and gamemode == "SS" then checkPlayers(0); end
  346. end --To complete the map you need 520 foods.
Advertisement
Add Comment
Please, Sign In to add comment