blockbattle.lua 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432
  1. -- title: blockbattle
  2. -- author: pixelbath
  3. -- desc: a falling blocks game totally not inspired by anything previous
  4. -- script: lua
  5. local spriteIndexStart = 256
  6. local blockSize = 5
  7. local t = 0
  8. local t_move = 0
  9. local is_move_pressed = false
  10. local is_das_triggered = false
  11. -- i, o, j, l, t, s, z
  12. local pieces = {
  13. {
  14. {
  15. {0, 0, 0, 0},
  16. {1, 1, 1, 1},
  17. {0, 0, 0, 0},
  18. {0, 0, 0, 0},
  19. },
  20. {
  21. {0, 1, 0, 0},
  22. {0, 1, 0, 0},
  23. {0, 1, 0, 0},
  24. {0, 1, 0, 0},
  25. },
  26. },
  27. {
  28. {
  29. {0, 0, 0, 0},
  30. {0, 4, 4, 0},
  31. {0, 4, 4, 0},
  32. {0, 0, 0, 0},
  33. },
  34. },
  35. {
  36. {
  37. {0, 0, 0, 0},
  38. {2, 2, 2, 0},
  39. {0, 0, 2, 0},
  40. {0, 0, 0, 0},
  41. },
  42. {
  43. {0, 2, 0, 0},
  44. {0, 2, 0, 0},
  45. {2, 2, 0, 0},
  46. {0, 0, 0, 0},
  47. },
  48. {
  49. {2, 0, 0, 0},
  50. {2, 2, 2, 0},
  51. {0, 0, 0, 0},
  52. {0, 0, 0, 0},
  53. },
  54. {
  55. {0, 2, 2, 0},
  56. {0, 2, 0, 0},
  57. {0, 2, 0, 0},
  58. {0, 0, 0, 0},
  59. },
  60. },
  61. {
  62. {
  63. {0, 0, 0, 0},
  64. {3, 3, 3, 0},
  65. {3, 0, 0, 0},
  66. {0, 0, 0, 0},
  67. },
  68. {
  69. {0, 3, 0, 0},
  70. {0, 3, 0, 0},
  71. {0, 3, 3, 0},
  72. {0, 0, 0, 0},
  73. },
  74. {
  75. {0, 0, 3, 0},
  76. {3, 3, 3, 0},
  77. {0, 0, 0, 0},
  78. {0, 0, 0, 0},
  79. },
  80. {
  81. {3, 3, 0, 0},
  82. {0, 3, 0, 0},
  83. {0, 3, 0, 0},
  84. {0, 0, 0, 0},
  85. },
  86. },
  87. {
  88. {
  89. {0, 0, 0, 0},
  90. {5, 5, 5, 0},
  91. {0, 5, 0, 0},
  92. {0, 0, 0, 0},
  93. },
  94. {
  95. {0, 5, 0, 0},
  96. {0, 5, 5, 0},
  97. {0, 5, 0, 0},
  98. {0, 0, 0, 0},
  99. },
  100. {
  101. {0, 5, 0, 0},
  102. {5, 5, 5, 0},
  103. {0, 0, 0, 0},
  104. {0, 0, 0, 0},
  105. },
  106. {
  107. {0, 5, 0, 0},
  108. {5, 5, 0, 0},
  109. {0, 5, 0, 0},
  110. {0, 0, 0, 0},
  111. },
  112. },
  113. {
  114. {
  115. {0, 0, 0, 0},
  116. {0, 6, 6, 0},
  117. {6, 6, 0, 0},
  118. {0, 0, 0, 0},
  119. },
  120. {
  121. {6, 0, 0, 0},
  122. {6, 6, 0, 0},
  123. {0, 6, 0, 0},
  124. {0, 0, 0, 0},
  125. },
  126. },
  127. {
  128. {
  129. {0, 0, 0, 0},
  130. {7, 7, 0, 0},
  131. {0, 7, 7, 0},
  132. {0, 0, 0, 0},
  133. },
  134. {
  135. {0, 7, 0, 0},
  136. {7, 7, 0, 0},
  137. {7, 0, 0, 0},
  138. {0, 0, 0, 0},
  139. },
  140. },
  141. }
  142. local piece = {}
  143. local board = {}
  144. local game_state = {
  145. board = {},
  146. level = 1,
  147. piece_queue = {},
  148. piece_bag = {},
  149. update = nil,
  150. }
  151. local active_piece = {
  152. type = nil,
  153. rotation = 1,
  154. x = 3, y = 0,
  155. }
  156. local rules = {
  157. keyrepeat = 5,
  158. das = 20,
  159. are = 4,
  160. }
  161. -- gaiden, vs, single
  162. local options = {
  163. gametype = "gaiden",
  164. shared_queue = true,
  165. }
  166. function shuffle(x)
  167. for i = #x, 2, -1 do
  168. local j = math.random(i)
  169. x[i], x[j] = x[j], x[i]
  170. end
  171. end
  172. function fill_bag()
  173. -- just throw a bag of randomized pieces in it
  174. local new_bag = { 1, 2, 3, 4, 5, 6, 7 }
  175. shuffle(new_bag)
  176. for i = 1,7 do
  177. table.insert(game_state.piece_bag, new_bag[i])
  178. end
  179. end
  180. function init_board()
  181. for y = 1, 20 do
  182. board[y] = {}
  183. for x = 1, 10 do
  184. board[y][x] = 0
  185. end
  186. end
  187. end
  188. function spawn_piece()
  189. trace("spawn")
  190. if #game_state.piece_bag <= 4 then
  191. fill_bag()
  192. end
  193. active_piece = {
  194. type = game_state.piece_bag[1],
  195. rotation = 1,
  196. x = 3, y = 0,
  197. }
  198. table.remove(game_state.piece_bag, 1)
  199. end
  200. function hard_drop()
  201. for i=20,0,-1 do
  202. local tempy = active_piece.y + i
  203. if test_can_fit(active_piece.type, active_piece.x, tempy, active_piece.rotation) then
  204. return i
  205. end
  206. end
  207. return 0
  208. -- active_piece.rotation = 1
  209. -- active_piece.type = active_piece.type + 1
  210. -- if active_piece.type > 7 then active_piece.type = 1 end
  211. -- trace("hard_drop: new type: "..tostring(active_piece.type)..", rot="..tostring(active_piece.rotation))
  212. end
  213. function soft_drop()
  214. active_piece.y = active_piece.y + 1
  215. end
  216. function try_move_right()
  217. active_piece.x = active_piece.x + 1
  218. end
  219. function try_move_left()
  220. active_piece.x = active_piece.x - 1
  221. end
  222. function handle_input()
  223. is_move_pressed = false
  224. if btnp(0) then
  225. -- spawn_piece()
  226. hard_drop()
  227. end
  228. if btn(1) then
  229. is_move_pressed = true
  230. if t_move <= 0 then
  231. t_move = rules.das
  232. soft_drop()
  233. end
  234. end
  235. if btn(2) then
  236. is_move_pressed = true
  237. if t_move <= 0 then
  238. if not is_das_triggered then
  239. t_move = rules.das
  240. else
  241. t_move = rules.keyrepeat
  242. end
  243. is_das_triggered = true
  244. try_move_left()
  245. end
  246. end
  247. if btn(3) then
  248. is_move_pressed = true
  249. if t_move <= 0 then
  250. if not is_das_triggered then
  251. t_move = rules.das
  252. else
  253. t_move = rules.keyrepeat
  254. end
  255. is_das_triggered = true
  256. try_move_right()
  257. end
  258. end
  259. if btnp(4) then
  260. active_piece.rotation = active_piece.rotation - 1
  261. if active_piece.rotation < 1 then
  262. active_piece.rotation = #pieces[active_piece.type]
  263. end
  264. end
  265. if btnp(5) then
  266. active_piece.rotation = active_piece.rotation + 1
  267. if active_piece.rotation > #pieces[active_piece.type] then
  268. active_piece.rotation = 1
  269. end
  270. end
  271. if is_move_pressed then
  272. t_move = t_move - 1
  273. else
  274. t_move = -1
  275. is_das_triggered = false
  276. end
  277. end
  278. function draw_board(xpos, ypos)
  279. -- draw next pieces
  280. for i=1,3 do
  281. local ptype = game_state.piece_bag[i]
  282. draw_piece(200, 20 + (i * 20), ptype, 1)
  283. end
  284. end
  285. function draw_piece(xpos, ypos, ptype, rotation)
  286. for y = 1, 4 do
  287. for x = 1, 4 do
  288. local block = pieces[ptype][rotation][y][x]
  289. if block ~= 0 then
  290. spr(
  291. spriteIndexStart + block,
  292. (x - 1) * blockSize + xpos,
  293. (y - 1) * blockSize + ypos
  294. )
  295. end
  296. end
  297. end
  298. end
  299. -- BEGIN state updates
  300. function update_intro()
  301. if t == 30 then
  302. game_state.update = update_menu
  303. else
  304. print("intro " .. tostring(30-t))
  305. end
  306. end
  307. function update_menu()
  308. print("Press X to start")
  309. if btnp(5) then
  310. game_state.update = update_game
  311. init_board()
  312. fill_bag()
  313. spawn_piece()
  314. end
  315. end
  316. function update_game()
  317. handle_input()
  318. draw_board()
  319. draw_piece(active_piece.x * blockSize, active_piece.y * blockSize, active_piece.type, active_piece.rotation)
  320. end
  321. -- END state updates
  322. function test_can_fit(ptype, xpos, ypos, rotation)
  323. for y = 1, 4 do
  324. for x = 1, 4 do
  325. local block = pieces[ptype][rotation][y][x]
  326. if block ~= 0 then
  327. if ypos + y > 21 or ypos + y < 0 then return false end
  328. trace("yooo "..tostring(ypos))
  329. -- TODO: some nil reference here idk
  330. local cell = game_state.board[ypos + y - 1][xpos + x - 1]
  331. if cell ~= 0 then
  332. return false
  333. end
  334. end
  335. end
  336. end
  337. return true
  338. end
  339. function piece.move_left()
  340. local tempx = active_piece.x - 1
  341. if piece.test_can_fit(active_piece.type, tempx, active_piece.y, active_piece.rotation) then
  342. active_piece.x = tempx
  343. return true
  344. end
  345. return false
  346. end
  347. function piece.move_right()
  348. local tempx = active_piece.x + 1
  349. if piece.test_can_fit(active_piece.type, tempx, active_piece.y, active_piece.rotation) then
  350. active_piece.x = tempx
  351. return true
  352. end
  353. return false
  354. end
  355. function piece.soft_drop()
  356. local tempy = active_piece.y + 1
  357. if piece.test_can_fit(active_piece.type, active_piece.x, tempy, active_piece.rotation) then
  358. active_piece.y = tempy
  359. return true
  360. end
  361. return false
  362. end
  363. -- if return value is 0, piece should lock immediately
  364. function piece.test_hard_drop()
  365. for i=20,0,-1 do
  366. local tempy = active_piece.y + i
  367. if piece.test_can_fit(active_piece.type, active_piece.x, tempy, active_piece.rotation) then
  368. return i
  369. end
  370. end
  371. return 0
  372. end
  373. game_state.update = update_intro
  374. function TIC()
  375. cls(0)
  376. -- call our current state's update
  377. game_state.update()
  378. t = t + 1
  379. end
  380. -- <SPRITES>
  381. -- 001:bbbbc0009aaab0009aaab0009aaab00089999000000000000000000000000000
  382. -- 002:8aaab0008999a0008999a0008999a00088888000000000000000000000000000
  383. -- 003:4444c00023334000233340002333400012222000000000000000000000000000
  384. -- 004:3cccc0002444c0002444c0002444c00012222000000000000000000000000000
  385. -- 005:55554000766650007666500076665000f7777000000000000000000000000000
  386. -- 006:ddddc000feeed000feeed000feeed000fffff000000000000000000000000000
  387. -- 007:3333400012223000122230001222300081111000000000000000000000000000
  388. -- 016:8bbbb0008abba0008a99a0008999900088888000000000000000000000000000
  389. -- 017:f5555000f6556000f6776000f7777000fffff000000000000000000000000000
  390. -- 018:0aaa0000a000a000a000a000a000a0000aaa0000000000000000000000000000
  391. -- 019:0666000060006000600060006000600006660000000000000000000000000000
  392. -- 020:000000000bc000000abbc0000aaabbc00aaaaff00aaff0000ff0000000000000
  393. -- 021:0000000005400000065540000666554006666ff0066ff0000ff0000000000000
  394. -- 022:0000000000044000004cc4000444cc4004444440004444000004400000000000
  395. -- </SPRITES>
  396. -- <PALETTE>
  397. -- 000:1a1c2c5d275db13e53ef7d57ffcd75a7f07038b76425717929366f3b5dc941a6f673eff7f4f4f494b0c2566c86333c57
  398. -- </PALETTE>