Skip to content

Jack-Ji/jok

Repository files navigation

jok

A minimal 2d/3d game framework for zig.

What you need?

  • Latest zig compiler
  • SDL library
  • Any code editor you like (consider using zls for your own favor)

Features

  • Friendly build system, very easy to setup new project
  • Able to cross-compile between Windows and Linux (thanks to ziglang)
  • Excellent rendering performance (thanks to SDL2's geometry rendering)
  • Fully integrated Dear-ImGui
  • 2D vector graphics (line/rectangle/quad/triangle/circle/bezier-curve/convex-polygon/polyline/custom-path)
  • 2D sprite rendering (scale/rotate/blending/flipping/depth)
  • 2D sprite sheet generation/save/load
  • 2D animation system
  • 2D particle system
  • 2D scene management
  • 2D physics system (via chipmunk)
  • 3D skybox rendering
  • 3D mesh rendering (gouraud/flat shading)
  • 3D glTF 2.0 support
  • 3D rigid/skeleton animation rendering/blending
  • 3D lighting effect (Blinn-Phong model by default, customizable)
  • 3D sprite/billboard rendering
  • 3D particle system
  • 3D scene management
  • Friendly easing system
  • Font loading/rendering (TrueType)
  • SVG loading/rendering
  • Sound/Music playing/mixing

Supported platforms

  • Windows
  • Linux
  • MacOS (?)

TIPS: To eliminate console terminal on Windows platform, override exe.subsystem with .Windows in your build script.

How to start?

  1. Add jok as your project's dependency

    Add jok dependency to your build.zig.zon, with following command:

    zig fetch --save https://github.com/jack-ji/jok/archive/[commit-sha].tar.gz

    For the [commit-sha] just pick the latest from here: https://github.com/jack-ji/jok/commits/main

    For those using proxies to access network, zig fetch might not work properly, here's what you can do instead:

    wget https://github.com/jack-ji/jok/archive/[commit-sha].tar.gz
    zig fetch --save [commit-sha].tar.gz
    rm -f [commit-sha].tar.gz
  2. Use jok's build script to add build step

    In your build.zig, add:

    const std = @import("std");
    const jok = @import("jok");
    
    pub fn build(b: *std.Build) void {
        const target = b.standardTargetOptions(.{});
        const optimize = b.standardOptimizeOption(.{});
        const exe = jok.createGame(
            b,
            "mygame",
            "src/main.zig",
            target,
            optimize,
            .{},
        );
        const install_cmd = b.addInstallArtifact(exe, .{});
    
        const run_cmd = b.addRunArtifact(exe);
        run_cmd.step.dependOn(&install_cmd.step);
    
        const run_step = b.step("run", "Run game");
        run_step.dependOn(&run_cmd.step);
    }
  3. Install SDL2 library:

    • Windows Platform

      Download SDL library from here, extract into your hard drive, and create file .build_config/sdl.json in your project directory:

      {
        "x86_64-windows-gnu": {
          "include": "D:/SDL2-2.28.5/x86_64-w64-mingw32/include",
          "libs": "D:/SDL2-2.28.5/x86_64-w64-mingw32/lib",
          "bin": "D:/SDL2-2.28.5/x86_64-w64-mingw32/bin"
        }
      }
    • Linux Platform

      Debian/Ubuntu:

      sudo apt install libsdl2-dev

      Fedora/CentOS:

      sudo yum install SDL2-devel
    • MacOS

      brew install sdl2
  4. Write some code!

    You may import and use jok now, here's skeleton of your src/main.zig:

    const std = @import("std");
    const jok = @import("jok");
    const sdl = jok.sdl;
    const j2d = jok.j2d;
    const j3d = jok.j3d;
    
    pub fn init(ctx: jok.Context) !void {
        // your init code
    }
    
    pub fn event(ctx: jok.Context, e: sdl.Event) !void {
        // your event processing code
    }
    
    pub fn update(ctx: jok.Context) !void {
        // your game state updating code
    }
    
    pub fn draw(ctx: jok.Context) !void {
      // your 2d drawing
      {
          j2d.begin(.{});
          defer j2d.end();
          // ......
      }
    
      // your 3d drawing
      {
          j3d.begin(.{});
          defer j3d.end();
          // ......
      }
    }
    
    pub fn quit(ctx: jok.Context) void {
        // your deinit code
    }

    Noticed yet? That's right, you don't need to write main function, jok got your back. The game is deemed as a separate package to jok's runtime as a matter of fact. Your only responsibility is to provide 5 public functions:

    • init - initialize your game, run only once
    • event - process events happened between frames (keyboard/mouse/controller etc)
    • update - logic update between frames
    • draw - render your screen here (60 fps by default)
    • quit - do something before game is closed

    You can customize some setup settings (window width/height, fps, debug level etc), by defining some public constants using predefined names (they're all prefixed withjok_). Checkout src/config.zig.

    Now, compile and run your game using command zig build run, have fun! Please let me know if you have any issue or developed something interesting with this little framework.

NOTE

Jok is short for joke, which is about how overly-complicated modern graphics programming has become. People are gradually forgetting lots of computing techniques used to deliver amazing games on simple machines. With so many tools, engines and computing resources at hand, however, gamedev is not as fun as it used to be. Jok is an offort trying to bring the joy of gamedev back, it's being developed in the spirit of retro-machines of 1990s (especially PS1), which implies following limitations:

The limitations demand developers to be both creative and careful about game's design.

Third-Party Libraries

Built-in Fonts

Games made in jok