- Common Lisp 100%
|
All checks were successful
CI / test (push) Successful in 7m52s
A canvas has a placement, a dmat3x2 from its draw function's coordinates to its renderer's, which scene-2d sets each frame to its item's global transform. Its draw function records from a start made of the placement's turn and stretch and of where the placement puts its origin within a pixel; the rest of the placement is applied as it is drawn. So moving, turning or stretching a node draws nothing again, but what it drew on the pixels, raster text and snapped shapes, when it moves off them, and what it drew for the scale when it turns or stretches. Each frame, each canvas's *canvas-transform*, the renderer's pixel transform after its placement, is worked out in doubles and packed as single-floats into slots of a uniform buffer the renderer keeps, one for each painter the canvas draws with, which its bundle binds; the slots that changed are written in one write. A node a million units out, under a view panned there, is drawn as precisely as one near the origin. draw-canvases and prepare-canvases take their transform as a dmat3x2, canvas-bounds gives a canvas's box in its own coordinates and takes a dmat3x2, and clips are kept in doubles. A control moved and resized at once draws again, which moving alone no longer does. |
||
|---|---|---|
| .forgejo/workflows | ||
| 2d | ||
| editor | ||
| export | ||
| font | ||
| play | ||
| player | ||
| program | ||
| project | ||
| resource | ||
| scene | ||
| scene-2d | ||
| src | ||
| tests | ||
| ui | ||
| .gitattributes | ||
| .gitignore | ||
| CLAUDE.md | ||
| LICENSE | ||
| pyssel.asd | ||
| README.org | ||
| stiftfile | ||
Pyssel
A game engine in the spirit of Godot, written in Common Lisp and scripted entirely in Common Lisp. Pyssel is Swedish for crafting or tinkering.
(asdf:load-system :pyssel)
(defpackage #:triangle
(:use #:cl #:clsl)
(:local-nicknames (#:gfx #:cl-gfx)))
(in-package #:triangle)
(define-shader triangle-vertex :vertex ((position :vec2) (color :vec3))
(values (vec4 position 0 1) color))
(define-shader triangle-fragment :fragment ((color :vec3))
(vec4 color 1))
(define-program triangle
"A triangle in its vertices' colours."
:vertex triangle-vertex :fragment triangle-fragment)
(defvar *pipeline*)
(defvar *vertices*)
(defun setup (engine)
(setf *pipeline* (pyssel:make-pipeline engine 'triangle)
*vertices* (gfx:create-buffer (pyssel:engine-device engine)
:size 60 :usage '(:vertex)))
(gfx:write-buffer *vertices*
(make-array 15 :element-type 'single-float
:initial-contents '( 0.0 -0.5 1.0 0.0 0.0
-0.5 0.5 0.0 1.0 0.0
0.5 0.5 0.0 0.0 1.0))))
(defun draw (engine pass)
(declare (ignore engine))
(pyssel:use-pipeline pass *pipeline*)
(gfx:set-vertex-buffer pass 0 *vertices*)
(gfx:draw pass 3))
(defvar *engine* (pyssel:start :title "Triangle" :setup 'setup :draw 'draw))
A window opens with a triangle in it, and the REPL stays free. Now redefine the fragment shader there:
(define-shader triangle-fragment :fragment ((color :vec3))
(vec4 (- 1 color) 1))
The next frame draws the triangle in the inverted colours. Redefine draw
and the next frame calls the new one. Close the window, or call
(pyssel:stop *engine*), to stop.
Pyssel assembles small libraries that stand on their own:
cl-wl and
cl-vk bind Wayland and Vulkan,
cl-windowing opens windows,
cl-gfx draws with the GPU,
clsl compiles shaders written in
Lisp, cl-gmath does the math,
cl-threads runs the threads, and
the text libraries lay out and render text. The engine's own parts are ASDF
systems named pyssel/... in this repository: pyssel is the core,
pyssel/2d the 2D renderer, pyssel/resource resources, their files and signals,
pyssel/font fonts as resources, pyssel/scene the scene tree, tweens and
saved scenes, pyssel/scene-2d its 2D nodes, pyssel/ui the user interface's
controls, containers and themes, pyssel/project projects and their settings,
pyssel/play games played in your Lisp, pyssel/editor the editor, with
its code editor, the Script screen, its REPL and its debugger, and
pyssel/export, with
pyssel/player, the player image exported games will start from.
Manual
The manual is the wiki. It starts with Getting Started, what Pyssel needs and its systems, then takes each in turn: the engines, 2D drawing, the scene tree, the user interface, projects, the editor, its Script screen, REPL and debugger.
Tests
stift test
The tests run engines offscreen on a Vulkan driver, such as Mesa's lavapipe
(mesa-vulkan-drivers), and, where Wayland is, in a window on headless
Weston (weston). They draw text in DejaVu Sans (fonts-dejavu-core); to
use it from another location, set PYSSEL_TEST_FONT to its path.
Credit
pyssel/2d draws Slug text with shaders ported from Eric Lengyel's
reference shaders (MIT License), through cl-slug. Software that uses it and
is distributed must credit them; cl-slug's NOTICE has the text.
pyssel/ui ships two fonts under the SIL Open Font License 1.1: Inter,
copyright The Inter Project Authors, and JetBrains Mono, copyright The
JetBrains Mono Project Authors. Their licences are beside them in
ui/fonts/, and go with them wherever they are distributed.
pyssel/scene's tweens ease with Robert Penner's easing equations,
copyright 2001 Robert Penner, as Godot 4.5 has them, under a permissive
licence whose notice is at the top of scene/easing.lisp and goes with
them wherever they are distributed.
License
MIT. See LICENSE.