Skip to content

Nathan5563/quark

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Quark

A simple, cross-platform 2D game engine written in D with an Entity-Component System architecture. Quark provides a complete game development framework including physics simulation, sprite rendering, animation, audio, scripting, and a tilemap editor. See the project website for a video demo and API documentation.

Features

  • Entity-Component System: Modular game object architecture with components for transform, sprites, animation, physics, colliders, and scripting
  • Physics Engine: Rigidbody dynamics with gravity, velocity integration, and collision response
    • Spatial grid broadphase for efficient collision detection
    • Box and circle collider support with AABB and circle-circle/circle-rectangle narrowphase
    • Collision events (enter, stay, exit) and trigger support
  • Rendering System: SDL3-based sprite rendering with camera support and z-ordering
  • Animation System: Grid-based sprite sheet animation with configurable speed and looping
  • Audio System: Sound playback and looping using SDL3 audio streams
  • Scene Management: Hierarchical scene graph with entity trees and scene transitions
  • QScript Scripting Language: Custom scripting language for game logic with lexer, parser, and interpreter
  • Tilemap Editor: GTK-based visual editor for creating and editing tilemaps (JSON and binary export)
  • Multi-threaded Architecture: Separate threads for resource loading, audio, and physics

Build System

The project uses DUB, the D package manager and build system.

Prerequisites

  • DMD or LDC2 (D compiler)
  • DUB (D package manager)
  • Linux x86-64 or Windows x86-64/ARM64 (macOS not currently supported)

SDL3 and SDL3_image libraries are bundled in the lib/ directory for supported platforms.

Building from Source

Since Quark is a game engine library, you build projects that use it rather than the engine itself. Choose a project to build:

Project Path Description
Platformer game/platformer/ Full game demo showcasing engine features
Bouncy Balls game/bouncyballs/ Physics engine demo
Tilemap Editor editors/tilemap/ Visual tilemap creation tool
# Build and run the platformer demo
cd game/platformer
dub

# Build and run the physics demo
cd game/bouncyballs
dub

# Build and run the tilemap editor (requires GTK)
cd editors/tilemap
dub

# Run unit tests from the root directory
dub test

Executables are output to the bin/ directory.

Pre-built Binaries

Pre-built demo games for x86-64 users are available in EngineBuild.zip on the project website. Extract the archive and run the appropriate executable:

  • Windows: .exe files
  • Linux: .bin files

ARM users must compile from source.

Creating Your Own Game

To create a new game using Quark:

  1. Create a new directory under game/ (e.g., game/mygame/)
  2. Add a dub.json with a dependency on quark:
    {
        "dependencies": {
            "quark": {"path": "../.."}
        },
        "targetType": "executable",
        "targetPath": "../../bin"
    }
  3. Create your source files in game/mygame/source/
  4. Place art, sounds, and other assets in assets/mygame/
  5. Run dub from your game directory

Architecture

Project Structure

quark/
├── dub.json                             # Engine library configuration
├── assets/                              # Game assets (images, sounds, tilemaps)
│   ├── bouncyballs/                     # Bouncy balls demo assets
│   └── platformer/                      # Platformer demo assets
│       ├── images/                      # Sprite sheets and backgrounds
│       └── sounds/                      # Audio files
├── bin/                                 # Built executables
├── docs/                                # Documentation
├── editors/
│   └── tilemap/                         # GTK-based tilemap editor
│       └── source/
│           ├── editor.d                 # Main editor window
│           └── components/              # Canvas and palette widgets
├── game/
│   ├── bouncyballs/                     # Physics demo
│   └── platformer/                      # Full game demo
│       └── source/
│           ├── platformer.d             # Game host implementation
│           ├── scenes/                  # Level definitions
│           └── scripts/                 # QScript game logic (.qscr)
├── lib/                                 # Pre-built SDL3 libraries
│   ├── linux/x64/                       # libSDL3.so, libSDL3_image.so
│   └── windows/
│       ├── x64/                         # SDL3.dll, SDL3_image.dll
│       └── arm/                         # SDL3.dll, SDL3_image.dll
└── source/quark/                        # Engine source code
    ├── common/                          # Math utilities
    │   ├── vector.d                     # Vec2 types (Vec2f, Vec2i, Vec2d)
    │   ├── matrix.d                     # Matrix operations
    │   ├── grid.d                       # Spatial grid data structure
    │   └── tree.d                       # Tree/scene graph structure
    ├── core/                            # ECS foundation
    │   ├── component.d                  # Base Component class
    │   ├── entity.d                     # Entity container
    │   ├── scene.d                      # Scene/entity tree management
    │   ├── host.d                       # Game loop and threading
    │   └── manager.d                    # Base Manager class
    ├── components/                      # Built-in components
    │   ├── transform.d                  # Position, rotation, scale
    │   ├── spriterenderer.d             # Sprite drawing
    │   ├── animator.d                   # Sprite animation
    │   ├── camera.d                     # Viewport camera
    │   ├── rigidbody.d                  # Physics body
    │   ├── script.d                     # QScript attachment
    │   └── colliders/                   # Collision shapes
    │       ├── boxcollider.d            # AABB collider
    │       └── circlecollider.d         # Circle collider
    ├── managers/                        # Singleton managers
    │   ├── resourcemanager.d            # Texture and sound loading
    │   ├── audiomanager.d               # Sound playback
    │   ├── scenemanager.d               # Scene transitions
    │   ├── physicsmanager.d             # Physics world interface
    │   └── debugmanager.d               # Debug visualization
    ├── physics/                         # Physics subsystem
    │   ├── world.d                      # Physics world coordination
    │   ├── broadphase.d                 # Spatial grid collision culling
    │   ├── collision.d                  # Narrowphase detection
    │   └── solver.d                     # Collision response
    ├── scripting/                       # QScript language
    │   ├── lexer.d                      # Tokenizer
    │   ├── parser.d                     # AST generation
    │   ├── interpreter.d                # Runtime execution
    │   └── grammar.txt                  # Language specification
    └── events/                          # Event system
        ├── types.d                      # Event definitions
        ├── inbox.d                      # Thread-safe message queue
        └── wiring.d                     # Event routing

Engine Design

Entity-Component System

Entities are containers for components. Components provide specific functionality and are updated each frame:

// Create an entity with components
auto player = new Entity("Player");

auto transform = new TransformComponent();
transform.position = Vec2f(100, 200);
player.addComponent(transform);

auto sprite = new SpriteRendererComponent("assets/player.png");
player.addComponent(sprite);

auto rigidbody = new RigidbodyComponent();
rigidbody.useGravity = true;
player.addComponent(rigidbody);

auto collider = new BoxColliderComponent(Vec2f(32, 64));
player.addComponent(collider);

scene.addEntity(player);

Component Lifecycle

Components have lifecycle methods called at appropriate times:

Method Description
onInit() Called when component is added to an entity
onStart() Called on first frame the component is active
preUpdate(dt) Called every frame before physics
postUpdate(dt) Called every frame after physics
preRender() Called before rendering
postRender() Called after rendering
onExit() Called when component is removed

QScript Scripting

QScript is a custom scripting language for game logic. Scripts can access engine APIs through built-in functions:

// player.qscr
var speed = 200;
var jumpForce = 400;

func onCollisionEnter(other) {
    if (getName(other) == "Coin") {
        playSound("assets/coin.wav");
        destroy(other);
    }
}

func update(dt) {
    var vx = 0;
    if (isKeyDown("left")) { vx = -speed; }
    if (isKeyDown("right")) { vx = speed; }
    setVelocityX(self, vx);
    
    if (isKeyDown("space") && isGrounded(self)) {
        setVelocityY(self, -jumpForce);
    }
}

Physics System

The physics engine uses a broadphase-narrowphase approach:

  1. Broadphase: Spatial grid partitioning culls distant objects
  2. Narrowphase: Precise collision detection (AABB, circle-circle, circle-AABB)
  3. Solver: Collision response with impulse-based resolution
// Configure rigidbody physics
rigidbody.mass = 2.0f;
rigidbody.bounciness = 0.8f;
rigidbody.linearDrag = 0.1f;
rigidbody.useGravity = true;
rigidbody.isKinematic = false;  // Set true for static/animated objects

// Apply forces
rigidbody.addForce(Vec2f(100, 0));
rigidbody.velocity = Vec2f(50, -200);

Troubleshooting

SDL Renderer Issues on Linux/WSL

If the window appears but nothing is visible, try using the software renderer:

export SDL_RENDER_DRIVER=software && ./bin/platformer

Audio is currently very buggy on WSL and will likely not be fixed.

Debug Mode

The platformer demo includes a hidden debug mode. Type the sequence [0w0] during gameplay to toggle collider visualization and editing.

License

MIT License — Copyright © 2026 Nathan Abebe

About

A feature-complete, data-driven 2D game engine written in the D programming language. Uses multithreading for subsystems with different timesteps, including physics, audio, and a custom scripting language.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages