Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/noteed/loading

A silly experiment with low-res graphics in Haskell
https://github.com/noteed/loading

haskell sdl2

Last synced: about 2 months ago
JSON representation

A silly experiment with low-res graphics in Haskell

Awesome Lists containing this project

README

        

# Loading

Just trying out the SDL2 library with Haskell.

- This uses a `shell.nix` file to bring in the necessary dependencies to build
the code.
- This uses `direnv` (and thus a `.envrc`) with the `use_nix` feature to
automatically use the above `shell.nix` upon entering this directory.

The code doesn't do much: it displays a window, and a littel dot. It can be
moved with the arrow keys, a dot can be drawn by pressing `space`, and `q`
exits the program.

Simply setting an environment variable is enough to get controller events even
when the window is not visible:

```
$ SDL_JOYSTICK_ALLOW_BACKGROUND_EVENTS=1 bin/loading run
```

## Building

To build the binary at `bin/loading`, simply run

```
$ nix-build -A binaries
```

To validate the code during developement, use `ghcid` by running:

```
$ scripts/ghcid.sh
```

## Current status

- The rendering is done with a low resolution, similar to old games.
- Some basic shapes (point, line, triangle) are rendered.
- Some commands can be done with a gamepad.
- Left mouse button clicks change the cursor location, and sets the magnified
zone location.
- Pressing `q` quits the application.
- Pressing `e` enables/disables logging polled events.
- Pressing `m` or right shoulder button show/hide a magnified zone of the
screen.
- Pressing the arrow keys or d-pad move the cursor.
- Pressing `space` or "A" button draw a point where the cursor is.
- `loading headless` generates directly a screenshot, without actually opening
an interactive window.
- A crude fixed frame rate is implemented. This limits CPU usage to 2% (window
on a hidden workspace) or 5% (window visible) on my T480, instead of 99%
(hidden) or 50% (visible).

When quitting, a screenshot is captured as `screenshot.png`.

A nice way to view the screenshot that mimics the behavior of the SDL window
under my xmonad configuration is using the following call:

```
$ feh --borderless --force-aliasing -g 1920x1200+320+120 --zoom fill screenshot.png
```

This creates a floating, centered window with the 384x240 image scaled,
conserving sharp "big" pixels.

## Notes

The `defaultWindow` has its `windowResizable` to False. With XMonad, this makes
the window appear at the requested size and centered (above tiled windows).
Setting `windowResizable` to True instead makes it behave like a regular
window: when it appears, it is tiled among the other windows.

To obtain "big" pixels, i.e. an appearance of a low resolution image similar to
old games, there is a `rendererLogicalSize` function. At first it seems to
work, but actually some drawing routines are not properly scaled (e.g.
`drawLine`, or `triangle` from the sdl-gfx library). Instead I have used a low
resolution texture as rendering target, which is then copied to the default
render target.

I was unsure if my X Box controller would work. I plugged it in (wired), and
checked `dmesg`:

```
[16352.189193] input: Microsoft X-Box One S pad as /devices/pci0000:00/0000:00:14.0/usb1/1-1/1-1:1.0/input/input21
[16352.189271] usbcore: registered new interface driver xpad
```

This looked good and I confirmed it was working with `jstest /dev/input/js0`.

Note: the build scripts hard-code paths into the Nix store to build against the
sdl2 image library. This should be fixed.