Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 15 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ Sincere thanks from Claudius team to all those who have contributed or made sugg

Claudius uses [Tamzen font](https://github.com/sunaku/tamzen-font) as the default text font.

# Docs

There are [odoc](https://github.com/ocaml/odoc) documentation for most of Claudius. You can find an online version [on the Claudius website](https://claudiusfx.org/claudius/index.html).

There is also a large range of [example programs using Claudius](https://github.com/claudiusFX/claudius-examples/) that you are encouraged to experiment with: try running them and then changing the code to see what else you can get them to do!

# Using Claudius

Claudius is a library for OCaml to do retro-style graphics, and so you need to create a new project that uses Cladius. But because Claudius isn't currently in Opam, you'll need to add it into your project using one of the two methods:
Expand All @@ -31,6 +37,14 @@ And then once that is installed, you can add it as a dependancy to your project

To see examples of how Claudius is used and learn how it works, we recommend you checkout the [examples library](https://github.com/claudiusFX/claudius-examples), run those, and then try editing the examples to make them do different things!

## Standard keys

Mostly Claudius doesn't have any interaction points beyond those you provide, but there are a few:

* F1 - Show debug overlay
* F2 - Save a screenshot to a GIF
* F3 - Save an animation to a GIF

## Developing Claudius

If you want to make open-source contributions to Claudius, you are welcome to do so. For that you will need to use the below approach
Expand All @@ -48,17 +62,7 @@ $ cd ..
$ git submodule update --init --recursive
```

## Standard keys

Mostly Claudius doesn't have any interaction points beyond those you provide, but there are a few:

* F1 - Show debug overlay
* F2 - Save a screenshot to a GIF
* F3 - Save an animation to a GIF

# Docs

There are [odoc](https://github.com/ocaml/odoc) documentation for most of Claudius. You can build that documentation with:
You can build that documentation with:

```shell
$ dune build @doc
Expand Down
7 changes: 5 additions & 2 deletions doc/index.mld
Original file line number Diff line number Diff line change
Expand Up @@ -125,11 +125,10 @@ let = p Palette.generate_plasma_palette 14
|> Palette.of_list
]}

Aside: because you can't change the palette once Claudius has started, this may feel very restrictive compared to TIC-80 and other fantasy console systems, and you'd be correct. However, because a palette in Claudius allows for more than just 16 colours, you can take a functional approach and compose a palette that is the super set of the various palettes you will need and then use offsets when rendering to access the approapriate "bank" of colours.

{2 Screens}

Once you have a colour palette defined, you can now create the screen mode you want to use for this program's lifetime:
Once you have a colour palette defined, you can now create the screen mode you want to use with {!Claudius.Screen.create}:

{[
let s = Screen.create 640 480 1 (Palette.generate_mono_palette 16)
Expand All @@ -143,6 +142,10 @@ let s = Screen.create 320 200 3 (Palette.generate_plasma_palette 256)

Claudius will use this information to generate the initial framebuffer state if you don't provide a boot function, and it is used to generate and render the window Claudius will display on the screen.

In retro-graphics there are many effects that are powered by updating the palette, and to allow this Claudius supports updating the palette as your program is running. For example, it is a common to rotate the palette colours to get an on screen effect rather than rewriting all the pixels with new palette values. To update the palette you provide a new palette to the screen by calling {!Claudius.Screen.update_palette}.

Screens also let you load a set of images ready to use in your program. By loading them at the start of your program, Claudius can correctly allocate palette entries for the colours in the images, so the palette becomes the colours you specifed when you create the palette, plus the colours from any images you loaded.

{1 Details}

{1 Pulling this together}
Expand Down
3 changes: 1 addition & 2 deletions src/framebuffer.ml
Original file line number Diff line number Diff line change
Expand Up @@ -463,8 +463,7 @@ let filled_polygon (points : (int * int) list) (col : int) (buffer : t) =

let draw_picture (pic : Picture.t) ?(scale = 1.0) (offset_x : int)
(offset_y : int) (fb : t) : unit =
let src_w = Picture.original_width pic in
let src_h = Picture.original_height pic in
let src_w, src_h = Picture.dimensions pic in
let dst_w = int_of_float (float src_w *. scale) in
let dst_h = int_of_float (float src_h *. scale) in
let pixels = Picture.pixels pic in
Expand Down
3 changes: 1 addition & 2 deletions src/picture.ml
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,7 @@ let load (filepath : string) : t =
let palette, pixels, w, h = load_png_as_indexed filepath in
{ palette; pixels; width = w; height = h }

let original_width (pic : t) = pic.width
let original_height (pic : t) = pic.height
let dimensions (pic : t) = (pic.width, pic.height)
let pixels (pic : t) = pic.pixels
let palette (pic : t) = pic.palette

Expand Down
10 changes: 4 additions & 6 deletions src/picture.mli
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,12 @@ type t
val load : string -> t
(** [load filename] loads a PNG file and returns a picture. *)

val original_width : t -> int
(** [original_width pic] returns the original width in pixels. *)

val original_height : t -> int
(** [original_height pic] returns the original height in pixels. *)
val dimensions : t -> int * int
(** [dimensions pic] returns the width and height of the image in pixels. *)

val pixels : t -> int array
(** [pixels pic] returns the indexed pixel array. *)
(** [pixels pic] returns the indexed pixel array. The pixels are arranged in
consecutive rows, with the top left pixel of the image first. *)

val palette : t -> Palette.t
(** [palette pic] returns the color palette of the picture. *)
Expand Down
8 changes: 4 additions & 4 deletions src/screen.mli
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,6 @@ val create :
images will be loaded and their palettes merged into the screen's global
palette.*)

val update_palette : t -> Palette.t -> unit
(**[update screen new_palette] creates a new screen with updated palette and
marks the screen as dirty.*)

val create_with_font : int -> int -> int -> Font.t -> Palette.t -> t
(** [create width height scale font palette] Deprecated: now use create with the
optional font. *)
Expand All @@ -39,6 +35,10 @@ val dimensions : t -> int * int
val palette : t -> Palette.t
(** [palette screen] Returns the palette associated with the [screen]. *)

val update_palette : t -> Palette.t -> unit
(**[update screen new_palette] updates the screen with provided palette and
marks the screen as dirty.*)

val scale : t -> int
(** [scale screen] Returns the scaling factor used when drawing [screen] to a
window. *)
Expand Down
14 changes: 6 additions & 8 deletions test/test_picture.ml
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@ open Picture
let test_valid_png _ =
(* Credits for tetris.png: https://publicdomainvectors.org/en/free-clipart/3D-Tetris-blocks-vector-illustration/6089.html *)
let pic = load "../test_assets/tetris.png" in
assert_bool "width > 0" (original_width pic > 0);
assert_bool "height > 0" (original_height pic > 0);
let width, height = dimensions pic in
assert_bool "width > 0" (width > 0);
assert_bool "height > 0" (height > 0);
assert_bool "has pixels" (Array.length (pixels pic) > 0)

let test_scaled_dimensions _ =
let pic = load "../test_assets/tetris.png" in
let w = original_width pic in
let h = original_height pic in
let w, h = dimensions pic in
assert_equal w (Array.length (pixels pic) / h)

let test_draw_picture_normal _ =
Expand All @@ -32,16 +32,14 @@ let test_draw_picture_negative_offset _ =

let test_draw_picture_scaled _ =
let pic = load "../test_assets/tetris.png" in
let w = original_width pic in
let h = original_height pic in
let w, h = dimensions pic in
assert_equal (w * h) (Array.length (pixels pic))

let test_load_png_as_indexed_transparent _ =
let pic = Picture.load "../test_assets/tetris.png" in
let pal = Picture.palette pic in
let pixels = Picture.pixels pic in
let w = Picture.original_width pic in
let h = Picture.original_height pic in
let w, h = Picture.dimensions pic in
assert_bool "image has width > 0" (w > 0);
assert_bool "image has height > 0" (h > 0);
(* palette[0] reserved for transparency *)
Expand Down