Skip to content

๐Ÿ• Perro โ€” A game engine written in Rust that utilizes a unique transpilation system that allows developers to write in high level languages for quick iteration and ease of use, while achieving native performance.

License

Notifications You must be signed in to change notification settings

PerroEngine/Perro

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

๐Ÿ• Perro Game Engine

Perro Logo

Perro is an experimental, open-source game engine written in Rust, designed as a modern alternative to engines like Unreal, Godot, and Unity.

It focuses on performance, flexibility, and ease of use with a unique scripting system that transpiles to Rust for native performance:

  • ๐Ÿถ Pup DSL โ€“ a beginner-friendly, lightweight scripting language that compiles to Rust for native performance. Write your gameplay logic in Pup and get the speed of Rust.
  • ๐ŸŽจ FUR (Flexible UI Rules) โ€“ a declarative UI system with layouts, panels, and boxing for easy UI design.
  • ๐Ÿ“ฆ Type-Safe Transpilation โ€“ full type checking and casting during code generation. All scripts transpile to Rust under the hood.
  • โšก Optimized Release Builds โ€“ scripts and assets statically link into your final binary.
  • ๐Ÿ”— Decoupled Signal System โ€“ global, name-based signals that completely decouple emitters from listeners. Use on SIGNALNAME() {} shorthand for automatic connections.

๐Ÿ‘ฉโ€๐Ÿ’ป For Game Developers

Quick Start

Clone the repository and build from source:

git clone https://github.com/PerroEngine/Perro.git
cd perro
cargo run -p perro_dev -- --path /path/to/project

โš ๏ธ Important: You must specify -- --path PATH when running perro_dev. The engine is primarily designed for compiling scripts and building projects, not for active development. For active game development, use the compiled release binary (see Performance section below).

Creating a New Project

Using the CLI:

# Create a new project (defaults to workspace/projects/ProjectName)
cargo run -p perro_core -- new MyGame

# Or specify a custom path
cargo run -p perro_core -- new MyGame /path/to/project

This creates a new project structure with:

  • project.toml - Project configuration
  • res/ - Resources folder (scenes, scripts, assets)
  • res/main.scn - Default scene with a "World" Node2D and Camera
  • .perro/ - Build artifacts (generated by compiler)
  • .gitignore - Ignores generated files

Development Workflow

Quick Dev Command (Build + Run):

# Build scripts and run project in one command
cargo run -p perro_core -- --path /path/to/project --dev

This automatically:

  1. Transpiles scripts (Pup โ†’ Rust)
  2. Compiles scripts into a DLL
  3. Runs the project

Manual Workflow (if you prefer more control):

1. Build Scripts Only:

# Compile scripts only (for testing changes)
cargo run -p perro_core -- --path /path/to/project --scripts

2. Run Project:

# Run project in dev mode (injects compiled scripts dynamically)
# โš ๏ธ You must specify -- --path PATH when running perro_dev
cargo run -p perro_dev -- --path /path/to/project
OR
cargo run -p perro_core -- --path /path/to/project --run

Note: The perro_dev runtime requires the --path argument. The engine (perro_core) is mainly for compiling scripts, not for active development. For better performance during development, see the Performance section below.

Iteration Cycle:

  • Make changes to scripts in res/*
  • Re-run --dev or just --scripts + perro_dev
  • Fast iteration cycle (~1โ€“3s recompile time)

โš ๏ธ Source Mode Performance Considerations

When building games from source, the runtime (perro_dev) runs in debug mode by default, which means it's unoptimized. This is fine for development, but if you need better performance:

For better performance, run in release mode:

# Run perro_dev in release mode for better performance
cargo run --release -p perro_dev -- --path /path/to/project

If you're making engine changes:

  • Rebuild the runtime in release mode when you make engine changes:
    cargo build --release -p perro_dev
  • Then run the release binary:
    ./target/release/perro_dev.exe --path /path/to/project

If you're NOT making engine changes:

  • Precompile the runtime in release mode once:
    cargo build --release -p perro_dev
  • Then use the release binary for all your game development:
    ./target/release/PerroDevRuntime.exe --path /path/to/project
  • If no path is provided, the release binary must be in the same directory as a project folder with a valid project.toml in it.

Why? The source mode workflow (cargo run) is optimized for engine development, not heavy game operations. The engine (perro_core) is primarily designed for compiling scripts and building projects, not for active development. For better performance during game development, use --release flag or a pre-built release binary.

Release Build

Build Final Release:

# Build complete release (compiles everything statically and strips out console logs)
cargo run -p perro_core -- --path /path/to/project --project

Build Verbose Release (with console window):

# Build release with verbose output and visible console
cargo run -p perro_core -- --path /path/to/project --project --verbose

This:

  • Transpiles all scripts โ†’ Rust
  • Compiles scripts + project into a single binary
  • Embeds assets and scripts statically
  • Produces an optimized, distributable executable
  • Verbose mode: Removes Windows subsystem flag so console is visible and makes console logs visible (useful for debugging)

Result: A single executable with no external dependencies or DLLs.

Making Your First Game

  1. Create a new project using the CLI (see above)
  2. Write scripts in Pup in res/ folder
  3. Design scenes by editing res/*.scn JSON files
  4. Design UI with FUR files in res/
  5. Follow the development workflow above to test and iterate
  6. Build release when ready to distribute

๐Ÿถ Pup DSL

Pup is Perro's built-in scripting language โ€” simple, readable, and compiles to Rust.

Script Definition

Scripts are defined with the @script directive followed by a name and the node type they extend:

@script Player extends Sprite2D
    var speed = 7.5

    fn init() {
        Console.print("Player is ready!")
        set_speed(2.1)
    }

    fn set_speed(new_speed: float) {
        speed = new_speed
    }

    fn update() {
        var delta = Time.get_delta()
        self.transform.position.x += speed * delta
    }

Signals & Event Handling

Perro uses a global, decoupled signal system. Signals are identified by name strings, and any script can listen for any signal without needing a reference to the emitter. This completely decouples signalers from listeners.

Signal Shorthand: on SIGNALNAME() {}

The easiest way to handle signals is using the on keyword shorthand. This automatically creates a function and connects it to the signal at script initilization.

@script GameManager extends Node

on start_Pressed() {
    Console.print("Start button was pressed!")
    // Start the game...
}

on pause_Pressed() {
    Console.print("Game paused")
}

The on syntax automatically:

  • Connects the code inside to the signal matching the same name.

Manual Signal Connection

You can also manually connect signals using Signal.connect(), using the signal name, and function.

@script Player extends Sprite2D

var enemy: Node2D
var bob: Sprite2D

fn init() {
    // Connect to a signal on self (function name as string)
    Signal.connect("player_Died", on_player_died)
    
    // Connect to a signal on another node (using any node reference)
    Signal.connect("enemy_Defeated", enemy.on_enemy_defeated)
    Signal.connect("bob_Pressed", bob.on_bob_pressed)
    
}

fn on_player_died() {
    Console.print("Player died!")
}

Decoupled Signal System Example

Here's a complete example showing how signals work across different scripts:

FUR UI File (res/ui.fur):

[UI]
    [Button id=start]
        Start Game
    [/Button]
[/UI]

Game Manager Script (res/game_manager.pup):

@script GameManager extends Node

fn init() {
    Console.print("Game manager ready, listening for start button...")
}

// Listen for the start button signal (emitted automatically by the button)
on start_Pressed() {
    Console.print("Starting the game!")
    // Initialize game state, load level, etc.
}

Key Points:

  • The button in FUR automatically emits start_Pressed when clicked (based on its id)
  • The game manager doesn't need a reference to the button
  • The game manager doesn't even need to be in the same scene
  • Any script anywhere can listen for start_Pressed by name if connected
  • The signal system is completely global and decoupled

This decoupling means you can:

  • Have UI buttons that emit signals without any scripts attached
  • Have game logic scripts that listen for signals without knowing where they come from
  • Easily add new listeners or emitters without modifying existing code
  • Test signals independently of their sources

๐ŸŽจ FUR (Flexible UI Rules)

FUR is Perro's declarative UI system for building layouts and UI panels.

[UI]
    [Panel bg=sea-5 padding=4]
        [Text font-weight=bold text-color=white text-size=xl]
            Hello Perro!
        [/Text]
    [/Panel]
[/UI]

Current Features:

  • Layouts and child layouts
  • Panels and boxing
  • Styling and padding

See perro_editor/res/fur for real examples of FUR in use.


๐Ÿ”„ Dev vs Release

Dev Mode (DLL Loading)

  • Scripts are transpiled to Rust, compiled into a DLL
  • Engine loads the DLL at runtime
  • Load files from disk
  • Make changes โ†’ recompile (~1โ€“3s) โ†’ restart to see updates

Release Mode (Static Linking)

  • All scripts transpile โ†’ Rust
  • Statically linked into final binary
  • Result:
    • Single executable (no DLLs, no source included)
    • Optimized machine code from LLVM
    • Scenes, FUR files, images, etc. are all statically embedded
    • Your source scripts are protected

๐Ÿ› ๏ธ For Engine Contributors & Development

This repository contains the Perro engine source code. To build and work on the engine itself:

Prerequisites

  • Rust 1.92.0 or later (GNU toolchain required - this is what ships with the editor binary for compilation)
  • Cargo

โš ๏ธ Linux System Dependencies

On Linux, you may need to install system dependencies before building. If you encounter errors about missing libraries (such as libdbus-1-dev or libudev-dev), run:

# Install all dependencies (recommended)
./install-deps.sh

# Or install essential packages individually
sudo apt install -y libdbus-1-dev libudev-dev pkg-config

The install-deps.sh script will install all required dependencies for your distribution (Ubuntu/Debian, Fedora/RHEL, or Arch Linux). If you encounter GPG errors with apt update, the script will continue anyway and attempt to install the packages.

Common build errors:

  • libdbus-sys build failure โ†’ Install libdbus-1-dev and pkg-config
  • hidapi build failure (Unable to find libudev) โ†’ Install libudev-dev
  • Missing graphics libraries โ†’ The install script includes all necessary graphics dependencies

โš ๏ธ Important: GNU Toolchain Required on Windows

Perro requires the GNU toolchain. Here's how to install and set it up:

# Install the GNU toolchain (1.92.0 or later)
rustup toolchain install stable-x86_64-pc-windows-gnu

# Set GNU toolchain as default
rustup default stable-x86_64-pc-windows-gnu

# Verify you're using GNU toolchain
rustc --version
# Should show: rustc 1.92.0 (or later) ... (x86_64-pc-windows-gnu)

# Or verify with rustup
rustup show
# Should show: default toolchain: stable-x86_64-pc-windows-gnu

If you already have Rust installed with MSVC:

# Install GNU toolchain for 1.92.0
rustup toolchain install 1.92.0-x86_64-pc-windows-gnu

# Set it as default
rustup default 1.92.0-x86_64-pc-windows-gnu

# Verify
rustc --version

Updating an existing GNU toolchain:

# Update to latest stable GNU toolchain
rustup update stable-x86_64-pc-windows-gnu

# Or update your default (if already set to GNU)
rustup update stable

Repository Structure

perro/
โ”œโ”€โ”€ perro_core/          # Core engine (structs, scene, render graph)
โ”œโ”€โ”€ perro_dev/           # Dev wrapper binary (loads DLLs, runs projects with --path)
โ”œโ”€โ”€ perro_editor/        # Editor game project
โ”‚   โ”œโ”€โ”€ .perro/
โ”‚   โ”‚   โ”œโ”€โ”€ project/     # Editor project crate (final exported binary in --project mode)
โ”‚   โ”‚   โ””โ”€โ”€ scripts/     # Editor scripts crate (contains transpiled rust + builds DLL)
โ”‚   โ””โ”€โ”€ res/             # Resources (FUR files, scenes, assets, scripts)
โ””โ”€โ”€ projects/            # Example game projects

Building & Running

Open the Editor in Dev Mode:

# โš ๏ธ You must specify -- --path PATH when running perro_dev
cargo run -p perro_dev -- --path /path/to/project

# For better performance during development:
cargo run --release -p perro_dev -- --path /path/to/project

Build the Core Alone:

cargo build -p perro_core

All projects share a build cache (the main workspace target/ in source mode), so the core only compiles once.

Toolchain & Versioning

The editors are pinned to specific versions of the toolchain, (eg. 1.0 => 1.92.0), toolchains will NOT always be updated each engine update, as to not clog the end user's system with multiple toolchains they don't need. (1.0 and 1.1 could support the same toolchain, even if users update it only is installed once)

Current Requirements:

  • Rust 1.92.0 or later (required for wgpu 28.0.0)
  • Default toolchain version: 1.92.0

Project Compatibility:

  • Old projects use their original editor version by default
  • The Project Manager auto-updates to the latest version
  • You can manually upgrade a project to a newer editor version if desired
  • Older editor versions remain available for projects that haven't upgraded

Stabilized Features

  • โœ… Pup scripting system (Pup -> Rust pipeline)
  • โœ… Type checking and casting during Rust codegen
  • โœ… DLL loading & dynamic script loading
  • โœ… Static linking of scripts and assets during release
  • โœ… FUR layouts, panels, child layouts, and boxing
  • โœ… Global decoupled signal system with 500ns dispatch

In Progress / Planned

  • ๐Ÿ”„ Pup DSL expansion (control flow, standard library)
  • ๐Ÿ”„ FUR runtime editing & editor viewer
  • ๐Ÿ“‹ Scene editor
  • ๐Ÿ“‹ Asset pipeline

Experimental Features

  • ๐Ÿงช C# & TypeScript Support โ€“ Experimental transpiler support for C# and TypeScript via Tree Sitter. These languages would be great additions once the transpiler stabilizes, but are currently experimental and not all AST bindings and behavior are implemented yet.

๐Ÿค Contributing

Contributions are welcome! You can work on:

  • Engine โ€“ perro_core (rendering, scene, runtime)
  • Editor โ€“ Edit the source code and UI of the editor at perro_editor/res
  • Scripting โ€“ Pup DSL expansion, transpiler improvements, other language support as needed
  • Tooling โ€“ build system, asset pipeline

See CONTRIBUTING.md for guidelines.


๐Ÿ’œ Support Perro

Your support helps us continue developing Perro and making it accessible to everyone. With enough funding, donations can enable full-time development on Perro, dramatically accelerating progress and bringing features to production faster.

Donations help fund:

  • ๐Ÿ’ผ Full-Time Development โ€“ Your contributions can enable dedicated, full-time work on Perro, allowing for faster feature development, more consistent updates, and quicker bug fixes
  • ๐Ÿš€ Accelerated Development โ€“ More time for core features like the scene editor, asset pipeline, and expanded Pup DSL capabilities
  • ๐Ÿ› ๏ธ Better Tooling & Infrastructure โ€“ Improved development tools, CI/CD pipelines, documentation, and testing infrastructure
  • ๐Ÿ“š Enhanced Documentation โ€“ Comprehensive tutorials, example projects, and detailed guides
  • ๐Ÿ› Bug Fixes & Stability โ€“ More time fixing bugs, improving performance, and ensuring Perro runs smoothly across platforms
  • ๐ŸŒ Community Growth โ€“ Supporting forums, community events, and developer outreach
  • โšก Performance & Optimization โ€“ Investing in profiling tools and optimization work

Ways to Support:

Every contribution, no matter the size, makes a difference! Thank you for supporting open-source game development! ๐ŸŽฎ


๐Ÿ“œ License

Perro is licensed under the Apache 2.0 License. See LICENSE for details.


๐Ÿพ Why "Perro"?

Every developer needs a loyal partner, just like a dog โ€” and that's what Perro means in Spanish.

About

๐Ÿ• Perro โ€” A game engine written in Rust that utilizes a unique transpilation system that allows developers to write in high level languages for quick iteration and ease of use, while achieving native performance.

Topics

Resources

License

Code of conduct

Contributing

Stars

Watchers

Forks

Sponsor this project

Languages