WinstonHartnett / godot-haskell

Haskell bindings for GdNative

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

godot-haskell

Build Status

Haskell bindings for the Godot game engine.

  • Low-level (GDNative) in Godot.Gdnative
  • Nativescript (binding classes/methods/etc) in Godot.Nativescript
  • High-level (classes generated from the API ) in Godot.Api
  • Access methods through Godot.Core

Getting started with the examples

The easiest way to get started is to have a look at the demos included in the examples directory. First check out "Dodge the Creeps!", your first game from the Godot documentation. Following along with the documentation and the code should make everything understandable.

To build:

git clone --recursive https://github.com/SimulaVR/godot-haskell
stack install godot-haskell:exe:godot-haskell-project-generator
cd godot-haskell/examples/dodge-the-creeps
make

To make changes to the game, in two different terminals:

make stack-watch
make project-watch

The first command will constantly build Haskell code and copy the shared library into the Godot project, demo. The second command will constantly scan the Godot project and build Haskell code out of it.

Load up the game by importing game/project.godot into the editor, which you can do from the commandline with godot game/project.godot. To run the game in the editor press F5, stop it with F8.

Understanding the examples

There are two parts to every project. examples/dodge-the-creeps/game which is the Godot project and examples/dodge-the-creeps/src which are the Haskell sources. When you run cd examples/dodge-the-creeps && make stack to build the demo, it builds the project locally with stack build and then does a cp to copy the resulting shared library into the right place in examples/dodge-the-creeps/game. This way Godot will pick it up. If you just do a stack build without copying, your shared library will never update and Godot will run the old code.

You must regenerate examples/dodge-the-creeps/src/Project any time you modify the Godot project. This directory contains the Godot project mirrored into Haskell, just like @Servant@ provides you with API safety by declaring APIs in Haskell. When you change the name of a node in Godot, this will update a Haskell class instance, which will lead to a type error in your project. You can do this with stack exec godot-haskell-parse-game game src which will watch your project for changes.

Known issues & inconveniences

  • Script variables only appear in the editor when you reload it.
  • No type safety for call and call_deferred.
  • Every time you add a new node which needs a native script you need to manually select the library. It's tedious right now. This is the procedure for adding a new node backed by Haskell code: create the node, right click it, attach a script, select nativescript, the script will open in the editor, in the inspector find the Library subheading under NativeScript, click [empty], pick Load, the file picker will open, open lib, and select libmyproject.dnlib or whatever you've renamed the library to. That's it. Don't edit the empty file that's been opened. Now in Haskell, you can create a class with the same name as the Godot one and that inherits from the same type. See the demo. There is a ticket in Godot to automate this process :(

Setting up your own project.

It's best to start with one of the existing examples, make a copy, and rename the project. If you want to start another project use the stack template template/godot-haskell.hsroots Alternatively, fetch it directly from git:

stack new myproject https://raw.githubusercontent.com/SimulaVR/godot-haskell/master/template/godot-haskell.hsfiles

Changing Godot versions

You will need to regenerate the bindings if you switch Godot versions. At present, these are generated for the version that corresponds to the godot_headers submodule included here. This was 3.1 at the time of writing.

To regenerate bindings:

  • Replace godot_headers with a version that corresponds to your install. Instructions are included there, but that generally means either checking out the corresponding files or rebuilding Godot.
  • Check out a copy of the godot repo and make sure you're on the commit corresponding to your version of godot. You don't need to build this, but you probably will anyway. We need it because documentation files are not included in the api.json file found in godot_headers.
  • Summarize the documentation xml files into a json file:
# Prerequisite
sudo apt-get install jq libcurl4-gnutls-dev # Or equivalent on you OS/Distro
cabal install xml-to-json

# Generate the JSON
xml-to-json godot-install-directory/doc/classes/*.xml | jq -n '[inputs]' &> godot_doc_classes.json
  • Build the bindings themselves:
cd classgen
stack build
rm ../src/Godot/Core/* ../src/Godot/Tools/*
stack exec godot-haskell-classgen -- ../godot_headers/api.json ../godot_doc_classes.json ../

That's it! The rest of the bindings are fairly lightweight with few dependencies, so you shouldn't see much breakage in the rest of the package.

If you want to get an idea of what the Haskell libraries are doing, set the environment variable HS_GODOT_DEBUG.

Questions

The primary method of contact is the SimulaVR Discord server. Mirrors are available at Gitter and in the SimulaVR channel at Matrix.

Docs

Most of the API is documented but the lowest-level bindings, like GDNative functions don't have documentation. They are quite intuitive to use though.

About

Haskell bindings for GdNative

License:BSD 3-Clause "New" or "Revised" License


Languages

Language:Haskell 99.9%Language:Nix 0.1%Language:Shell 0.0%Language:Makefile 0.0%Language:C 0.0%