Find a file
2019-12-02 21:30:30 -05:00
appimage Updated minimal love2d fennel setup for the spring lisp game jam. 2019-04-20 21:24:43 -04:00
lib Updated stdio.fnl to use built in fennel repl. 2019-12-02 21:30:30 -05:00
.gitignore Copy appimage scripts from goo-runner. 2018-11-30 17:39:46 -08:00
conf.lua Updated minimal love2d fennel setup for the spring lisp game jam. 2019-04-20 21:24:43 -04:00
fennel.lua Updated stdio.fnl to use built in fennel repl. 2019-12-02 21:30:30 -05:00
license.txt Initial commit. 2018-10-17 21:32:39 -04:00
love-release.sh Updated minimal love2d fennel setup for the spring lisp game jam. 2019-04-20 21:24:43 -04:00
main.lua Initial commit. 2018-10-17 21:32:39 -04:00
makefile Updated minimal love2d fennel setup for the spring lisp game jam. 2019-04-20 21:24:43 -04:00
mode-intro.fnl Updated minimal love2d fennel setup for the spring lisp game jam. 2019-04-20 21:24:43 -04:00
readme.org Updated stdio.fnl to use built in fennel repl. 2019-12-02 21:30:30 -05:00
wrap.fnl Fix syntax error and formatting. 2019-09-22 15:38:01 -07:00

Minimal Fennel Love2D Setup

In a lead up to the annual Autumn Lisp Game Jam I thought I'd look into Phil Hegelberg's approach to last Aprils Jam, using love2d in concert with fennel. Phil outlines his approach on his blog.

The first step is to see how fennel works as a standalone execution environment, then slowly integrate some of the love2d API.

This repo contains the minimal viable setup to get started with Phil Hegelberg's game design process, plus some additional libraries.

PROJECT=project-name
git clone https://gitlab.com/alexjgriffith/min-love2d-fennel.git $PROJECT
cd $PROJECT
rm -rf .git

Phil's Modal Callbacks (PMC)

Phil Hegelberg's exo-encounter-667 is structured using a modal callback system. Each game state has a mode and each mode has a series of specific callbacks.

If you design your game as a series of states in a very simple state machine, for example start-screen, play and end, with unidirectional progression, you can easily separate the logic for each state into state/mode specific callbacks. As an example, in order to have state dependant rendering that differs between start-screen,play and end you could provide a draw callback for each of those states. Similarly if we need state dependent logic and keyboard input we could provide update and keyboard callbacks. As you iterate you can add and remove callbacks and states/modes as needed with very little friction.

Emacs Setup

(autoload 'fennel-mode "/path/to/fennel-mode" nil t)
(require 'fennel-mode)

;; By default fennel-mode moves focus to the \*inferior-lisp\* buffer
;; setting `fennel-mode-switch-to-repl-after-reload' to nil prevents this
(customize-save-variable 'fennel-mode-switch-to-repl-after-reload nil)

(add-to-list 'auto-mode-alist '("\\.fnl\\'" . fennel-mode))

;; you can bind this to whatever you like
(defun run-love ()
  (interactive)
  (run-lisp "love ."))

;; for some reason when I load a fnl file it starts the slime minor mode
;; I have included the hook below to prevent this
(defun fennel-mode-hook-fun ()
  (interactive)
  (slime-mode nil))

(add-hook 'fennel-mode-hook 'fennel-mode-hook-fun)

Known Issues

Presently fennel.lua has to be in the main directory for fennel-reload from fennel-mode.el to work. The issue is

(let [old (require :module-name)
      _ (tset package.loaded :module-name nil)
     (ok new) (pcall require :module-name) ;; fails if fennel not in base directory
     new (if (not ok) (do (print new) old) new)]
  (when (= (type new) :table)
    (each [k v (pairs new)] (tset old k v))
    (each [k (pairs old)] (when (not (. new k)) (tset old k nil)))
    (tset package.loaded :module-name old)))

The error that gets thrown is.

./module-name.fnl:#Some Number#: module 'fennel' not found:
        no field package.preload['fennel']
        no 'fennel' in LOVE game directories.
        no file 'fennel' in LOVE paths.
        no file './fennel.lua'
        no file '/usr/local/share/luajit-2.0.5/fennel.lua'
        no file '/usr/local/share/lua/5.1/fennel.lua'
        no file '/usr/local/share/lua/5.1/fennel/init.lua'
        no file './fennel.so'
        no file '/usr/local/lib/lua/5.1/fennel.so'
        no file '/usr/local/lib/lua/5.1/loadall.so'