From 760815c8652cc71eda06d3264ab1f05af2357f92 Mon Sep 17 00:00:00 2001 From: Jeremy Penner Date: Sun, 24 Apr 2022 22:45:30 -0400 Subject: [PATCH] Game is playable and editable --- edtris.txt | 56 ++++++++++++++++++++++++++++++++++++++++++++++++ game/rules.fnl | 33 +++++++++++++++++++++++----- game/tilemap.fnl | 2 +- 3 files changed, 85 insertions(+), 6 deletions(-) create mode 100644 edtris.txt diff --git a/edtris.txt b/edtris.txt new file mode 100644 index 0000000..6b55dcc --- /dev/null +++ b/edtris.txt @@ -0,0 +1,56 @@ +Welcome to Edtris, the Editable Tetris! + +This game has a text editor built into it! You are looking at an editor +called "lite", which is written in Lua and has been ported to run inside +the love2d game engine. + +Edtris is written in Fennel, which is a language in the Lisp family +that compiles to Lua. + +To your right is a file called "state.fnl" - this contains a snapshot of +all of the information that can change while the game is running. This +includes the next piece (represented by the letters O, I, J, L, S, Z, and T), +the current piece and its position in the well, the time left before the +current piece drops down one level, and the current speed of automatic +dropping. + +You can edit state.fnl and, with a simple keystroke, make your changes +live in the game! Try the following: + +1. Change the line reading + :next-piece "O" +(or instead of "O", whatever letter represents the next piece) +to say + :next-piece "I" +2. Hit Ctrl-S to save the file +3. Hit Alt-R to "reload" the file. If everything is alright, you will see + a message pop up at the bottom of the screen saying "Hotswapping game.state". + If an error message pops up instead, hit Ctrl-Z repeatedly to undo all of + your changes and try again! +4. Hit F1 to go back to the game. Now your next piece will be a long "I"-beam! + +At any time, you can press "E" to come back to this editor and try new things. +Feel free to experiment! + +* What happens if you make the well bigger? +* What happens if you remove the walls of the well? +* Can you draw a picture in the well? + +If you like, you can also run the game and the editor at the same time! +If you press Ctrl-Shift-P, type "game" and press enter, a new tab will +open with the game running inside. + +If you're feeling adventurous, you can edit the source code for this game while +it's running, too! That's how I made it! Most of the interesting rules are +defined in game/rules.fnl. You can find this file in the directory tree to the left, +or press Ctrl-P, type "rules.fnl", and press enter to jump right to it. + +* Can you add a new piece to the game? +* Can you make the up arrow make the piece levitate upwards, instead of rotating? + +This game was made for the Glorious Trainwrecks 15th Anniversary Klik Jam! +https://www.glorioustrainwrecks.com/node/12219 + +Happy 15th birthday, Glorious Trainwrecks! + +-- Jeremy Penner diff --git a/game/rules.fnl b/game/rules.fnl index 2bf1afc..0bd0632 100644 --- a/game/rules.fnl +++ b/game/rules.fnl @@ -74,17 +74,16 @@ " #"]]}) (fn Rules.choose-random-tetromino [] - (let [possible-values (icollect [k (pairs state.tetrominoes)] k) + (let [possible-values (icollect [k (pairs tetrominoes)] k) ivalue (love.math.random (length possible-values))] (. possible-values ivalue))) (fn Rules.tetromino [k irotation] - (let [rotations (or (. state.tetrominoes k) []) + (let [rotations (or (. tetrominoes k) []) irotation (+ (% (- irotation 1) (length rotations)) 1)] (. rotations irotation))) (fn Rules.reset-game [] - (set state.tetrominoes tetrominoes) (set state.well (map.new-tilemap 12 21)) (for [y 0 19] (map.set-itile-at 0 y state.well "X") @@ -95,6 +94,7 @@ (Rules.play-next-piece)) (fn Rules.play-next-piece [] + (Rules.clear-lines) (let [piece (or state.next-piece (Rules.choose-random-tetromino)) x (math.floor (/ (- (length (. state.well 1)) 2) 2))] (set state.current {: piece : x :y 0 :irotation 1}) @@ -151,10 +151,32 @@ (set state.current.x x) (set state.current.irotation irotation))))))) +(fn Rules.clear-lines [] + (let [rows (icollect [irow row (ipairs state.well)] (when (not (row:match "^X%#+X$")) row)) + first-row (. state.well 1) + empty-row (.. :X (string.rep " " (- (length first-row) 2)) :X) + cleared-rows (math.max 0 (- (length state.well) (length rows)))] + (when (> cleared-rows 0) + (for [i 1 cleared-rows] + (print i cleared-rows (length state.well)) + (table.insert rows 1 empty-row)) + (set state.well rows)))) + +(fn Rules.edit-game [] + (let [modes (require :editor.lovemode) + core (require :core) + filename "game/state.fnl" + f (io.open filename :w)] + (f:write (fv state)) + (f:close) + (modes:cycle) + (core.root_view:open_doc (core.open_doc filename)))) + (set Rules.commands {:move Rules.try-move-piece :rotate Rules.rotate - :reset Rules.reset-game}) + :reset Rules.reset-game + :edit Rules.edit-game}) (set Rules.keymap {:left [:move -1 0] @@ -163,7 +185,8 @@ :up [:rotate 1] :z [:rotate -1] :x [:rotate 1] - :r [:reset]}) + :r [:reset] + :e [:edit]}) (fn Rules.run-command [cmd] (when cmd diff --git a/game/tilemap.fnl b/game/tilemap.fnl index 1ebe98e..862b658 100644 --- a/game/tilemap.fnl +++ b/game/tilemap.fnl @@ -41,7 +41,7 @@ tile (tile-at tx ty tilemap tileset) xt (+ x (* tx dim.tilesize) (/ dim.tilesize 2)) yt (+ y (* ty dim.tilesize) (/ dim.tilesize 2))] - (drawtile tile xt yt))))) + (when tile (drawtile tile xt yt)))))) (fn world-to-tile [vec] (-> vec