Convert Figma logo to code with AI

hecrj logocoffee

An opinionated 2D game engine for Rust

1,073
55
1,073
45

Top Related Projects

2,383

A fast and flexible Markdown parser written in Swift.

2,341

Stencil is a simple and powerful template language for Swift.

2,278

A package manager that installs and runs executable Swift packages

Quick Overview

Coffee is a Rust library for building cross-platform graphical user interfaces (GUIs). It provides a high-level, declarative API for creating and managing GUI applications, with a focus on simplicity, performance, and flexibility.

Pros

  • Cross-platform: Coffee supports multiple platforms, including Windows, macOS, and Linux, allowing developers to create a single codebase that can be deployed across different operating systems.
  • Declarative API: The library's API is declarative, making it easier to reason about and compose UI elements, leading to more maintainable and scalable code.
  • Performance: Coffee is built on top of the Rust programming language, which provides low-level control and high-performance, making it suitable for building responsive and efficient GUI applications.
  • Flexibility: The library is designed to be modular and extensible, allowing developers to customize and extend its functionality as needed.

Cons

  • Relatively new: Coffee is a relatively new library, and as such, it may have a smaller community and fewer resources available compared to more established GUI frameworks.
  • Learning curve: The declarative nature of the API and the use of Rust may present a steeper learning curve for developers who are more familiar with imperative or object-oriented approaches to GUI development.
  • Limited ecosystem: While Coffee provides a solid foundation for building GUI applications, the ecosystem of third-party libraries and tools may be smaller compared to more mature GUI frameworks.
  • Rust-specific: As Coffee is built on Rust, it may not be the best choice for developers who are not familiar with or interested in learning the Rust programming language.

Code Examples

Here are a few code examples demonstrating the usage of the Coffee library:

  1. Creating a simple window:
use coffee::prelude::*;

fn main() {
    Application::new()
        .title("Hello, Coffee!")
        .size(800, 600)
        .run(HelloWorld {})
}

struct HelloWorld {}

impl Program for HelloWorld {
    type Msg = ();
    type Settings = ();

    fn update(&mut self, _msg: Self::Msg, _state: &mut ApplicationState) {}

    fn draw(&self, frame: &mut Frame) {
        frame.clear(Color::WHITE);
        frame.text("Hello, Coffee!", (400, 300), 32.0, Color::BLACK);
    }
}
  1. Creating a button:
use coffee::prelude::*;

fn main() {
    Application::new()
        .title("Button Example")
        .size(800, 600)
        .run(ButtonExample {})
}

struct ButtonExample {
    button_state: ButtonState,
}

impl Program for ButtonExample {
    type Msg = ButtonMessage;
    type Settings = ();

    fn new(_settings: Self::Settings) -> Self {
        ButtonExample {
            button_state: ButtonState::new(),
        }
    }

    fn update(&mut self, msg: Self::Msg, state: &mut ApplicationState) {
        self.button_state.update(msg, state);
    }

    fn draw(&self, frame: &mut Frame) {
        frame.clear(Color::WHITE);
        self.button_state.draw(frame, (400, 300), 100, 50, "Click me!");
    }
}
  1. Handling user input:
use coffee::prelude::*;

fn main() {
    Application::new()
        .title("Input Example")
        .size(800, 600)
        .run(InputExample {})
}

struct InputExample {
    input_state: InputState,
}

impl Program for InputExample {
    type Msg = InputMessage;
    type Settings = ();

    fn new(_settings: Self::Settings) -> Self {
        InputExample {
            input_state: InputState::new(),
        }
    }

    fn update(&mut self, msg: Self::Msg, state: &mut ApplicationState) {
        self.input_state.update(msg, state);
    }

    fn draw(&self, frame: &mut Frame) {
        frame.clear(Color::WHITE);
        self.input_state.draw(frame

Competitor Comparisons

2,383

A fast and flexible Markdown parser written in Swift.

Pros of Ink

  • Written in Swift, offering native performance and integration with Apple platforms
  • Supports custom themes and syntax highlighting out of the box
  • Provides a more comprehensive set of features for static site generation

Cons of Ink

  • Limited to Swift ecosystem, reducing cross-platform compatibility
  • Steeper learning curve for developers not familiar with Swift
  • Less flexible for creating custom templating languages

Code Comparison

Ink (Swift):

struct MyTheme: HTMLFactory {
    func makeHeader(for site: Site) -> Node {
        .header(
            .h1(.text(site.name)),
            .p(.text(site.description))
        )
    }
}

Coffee (Rust):

fn header(site: &Site) -> Node {
    html! {
        <header>
            <h1>{ &site.name }</h1>
            <p>{ &site.description }</p>
        </header>
    }
}

Both examples demonstrate creating a header component, but Ink uses a more object-oriented approach with structs and methods, while Coffee utilizes a functional style with standalone functions and a custom HTML macro.

2,341

Stencil is a simple and powerful template language for Swift.

Pros of Stencil

  • More actively maintained with recent updates
  • Larger community and ecosystem
  • Supports a wider range of template features and syntax

Cons of Stencil

  • Steeper learning curve for beginners
  • Potentially more complex setup for simple projects
  • Heavier dependency footprint

Code Comparison

Stencil example:

struct Article: Codable {
    let title: String
    let body: String
}

let context = ["article": Article(title: "Hello", body: "World")]
let template = "{{ article.title }} - {{ article.body }}"

let rendered = try stencil.renderTemplate(string: template, context: context)

Coffee example:

use coffee::graphics::{Color, Frame, Window, WindowSettings};
use coffee::load::Task;
use coffee::{Game, Result, Timer};

struct MyGame;

impl Game for MyGame {
    fn load(_window: &Window) -> Task<MyGame> {
        Task::new(|| MyGame)
    }
}

While both projects serve different purposes (Stencil for templating and Coffee for game development), this comparison highlights their syntax and usage differences. Stencil focuses on template rendering, while Coffee provides a game development framework with a more declarative approach.

2,278

A package manager that installs and runs executable Swift packages

Pros of Mint

  • More active development with recent updates and releases
  • Broader scope, supporting full app development beyond just UI
  • Larger community and more extensive documentation

Cons of Mint

  • Steeper learning curve due to more complex features
  • Less focused on UI-specific tasks compared to Coffee
  • Potentially overkill for simple projects or prototypes

Code Comparison

Mint example:

component Main {
  fun render : Html {
    <div>
      <h1>"Hello, Mint!"</h1>
      <p>"Welcome to my app."</p>
    </div>
  }
}

Coffee example:

view : Model -> Html Msg
view model =
  div []
    [ h1 [] [ text "Hello, Coffee!" ]
    , p [] [ text "Welcome to my app." ]
    ]

Both frameworks use a declarative approach to UI development, but Mint's syntax is more concise and JavaScript-like, while Coffee follows Elm's functional style. Mint's component-based structure is evident in the example, whereas Coffee's view function is part of the Elm architecture.

Mint offers a more comprehensive solution for web app development, including state management and routing out of the box. Coffee, being based on Elm, provides a simpler and more focused approach to UI development with strong type safety. The choice between the two depends on project requirements and developer preferences.

Convert Figma logo designs to code with AI

Visual Copilot

Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.

Try Visual Copilot

README

Coffee

Integration status Documentation Crates.io License Gitter chat

An opinionated 2D game engine for Rust focused on simplicity, explicitness, and type-safety.

Coffee is in a very early stage of development. Many basic features are still missing, some dependencies are experimental, and there are probably many bugs. Feel free to contribute!

Features

And more! Check out the examples to see them in action.

Usage

Add coffee as a dependency in your Cargo.toml and enable a graphics backend feature (opengl, vulkan, metal, dx11, or dx12):

coffee = { version = "0.4", features = ["opengl"] }

Rust is quite slow in debug mode. If you experience performance issues when drawing hundreds of sprites, enable compiler optimizations in your Cargo.toml. I recommend level 2 optimizations in order to stay closer to --release performance:

[profile.dev]
opt-level = 2

Coffee moves fast and the master branch can contain breaking changes! If you want to learn about a specific release, check out the release list.

Overview

Here is a minimal example that will open a window:

use coffee::graphics::{Color, Frame, Window, WindowSettings};
use coffee::load::Task;
use coffee::{Game, Result, Timer};

fn main() -> Result<()> {
    MyGame::run(WindowSettings {
        title: String::from("A caffeinated game"),
        size: (1280, 1024),
        resizable: true,
        fullscreen: false,
        maximized: false,
    })
}

struct MyGame {
    // Your game state and assets go here...
}

impl Game for MyGame {
    type Input = (); // No input data
    type LoadingScreen = (); // No loading screen

    fn load(_window: &Window) -> Task<MyGame> {
        // Load your game assets here. Check out the `load` module!
        Task::succeed(|| MyGame { /* ... */ })
    }

    fn draw(&mut self, frame: &mut Frame, _timer: &Timer) {
        // Clear the current frame
        frame.clear(Color::BLACK);

        // Draw your game here. Check out the `graphics` module!
    }
}

Browse the documentation and the examples to learn more!

Implementation details

Coffee builds upon

  • winit for windowing and mouse/keyboard events.
  • gfx pre-ll for OpenGL support, based heavily on the ggez codebase.
  • wgpu for experimental Vulkan, Metal, D3D11 and D3D12 support.
  • stretch for responsive GUI layouting based on Flexbox.
  • glyph_brush for TrueType font rendering.
  • gilrs for gamepad support.
  • nalgebra for the Point, Vector, and Transformation types.
  • image for image loading and texture array building.

Contributing / Feedback

I am quite new to Rust, systems programming, and computer graphics. I am learning along the way as I build the engine for a game I am currently developing. I am always glad to to learn from anyone.

If you want to contribute, you are more than welcome to be a part of the project! Check out the current issues if you want to find something to work on. Try to share you thoughts first! Feel free to open a new issue if you want to discuss new ideas.

Any kind of feedback is welcome! You can open an issue or, if you want to talk, you can find me (and a bunch of awesome folks) over the #games-and-graphics channel in the Rust Community Discord. I go by @lone_scientist there.

Credits / Thank you

  • ggez, an awesome, easy-to-use, good game engine that introduced me to Rust. Its graphics implementation served me as a guide to implement OpenGL support for Coffee.
  • Kenney, creators of amazing free game assets with no strings attached. The built-in GUI renderer in Coffee uses a modified version of their UI sprites.