Skip to content

Commit

Permalink
sketch supports more handlers and changed pattern to use builder for …
Browse files Browse the repository at this point in the history
…init
  • Loading branch information
Acepie committed Apr 22, 2024
1 parent c1b4821 commit 460c1b1
Show file tree
Hide file tree
Showing 7 changed files with 155 additions and 44 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
*.ez
/build
erl_crash.dump
dist/*.js
/**/dist/*.js
60 changes: 47 additions & 13 deletions examples/ball_spawner/src/ball_spawner.gleam
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import gleam/float
import gleam/io
import gleam/list
import gleam/option
import p5js_gleam.{type P5, SketchConfig}
import gleam/string
import p5js_gleam.{type P5}
import p5js_gleam/bindings as p5

type Vector {
Expand Down Expand Up @@ -67,7 +67,6 @@ fn flip_ball_y(b: Ball) -> Ball {
}

fn tick(state: WorldState) -> WorldState {
io.debug(state)
let balls = {
use ball <- list.map(state.balls)
let Ball(Vector(x, y), _, _) = ball
Expand All @@ -80,12 +79,47 @@ fn tick(state: WorldState) -> WorldState {
WorldState(balls)
}

fn on_key(key: String, state: WorldState) -> WorldState {
io.println(key)
fn on_key_pressed(key: String, key_code: Int, state: WorldState) -> WorldState {
io.debug(
"On key pressed called with key: "
<> key
<> ", keyCode: "
<> string.inspect(key_code)
<> ", and current state: "
<> string.inspect(state),
)
state
}

fn on_mouse(
fn on_key_released(key: String, key_code: Int, state: WorldState) -> WorldState {
io.debug(
"On key released called with key: "
<> key
<> ", keyCode: "
<> string.inspect(key_code)
<> ", and current state: "
<> string.inspect(state),
)
state
}

fn on_mouse_moved(
x_position: Float,
y_position: Float,
state: WorldState,
) -> WorldState {
io.debug(
"On mouse moved called with x position: "
<> string.inspect(x_position)
<> ", y position: "
<> string.inspect(y_position)
<> ", and current state: "
<> string.inspect(state),
)
state
}

fn on_mouse_clicked(
x_position: Float,
y_position: Float,
state: WorldState,
Expand All @@ -108,11 +142,11 @@ fn on_mouse(
}

pub fn main() {
p5.start_sketch(SketchConfig(
init: setup,
draw: draw,
on_tick: option.Some(tick),
on_key: option.Some(on_key),
on_mouse: option.Some(on_mouse),
))
p5js_gleam.create_sketch(init: setup, draw: draw)
|> p5js_gleam.set_on_tick(tick)
|> p5js_gleam.set_on_key_pressed(on_key_pressed)
|> p5js_gleam.set_on_key_released(on_key_released)
|> p5js_gleam.set_on_mouse_moved(on_mouse_moved)
|> p5js_gleam.set_on_mouse_clicked(on_mouse_clicked)
|> p5.start_sketch
}
12 changes: 3 additions & 9 deletions examples/minimal/src/minimal.gleam
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import gleam/option
import p5js_gleam.{type P5, SketchConfig}
import p5js_gleam.{type P5}
import p5js_gleam/bindings as p5

fn setup(p: P5) -> String {
Expand All @@ -14,11 +13,6 @@ fn draw(p: P5, state: String) {
}

pub fn main() {
p5.start_sketch(SketchConfig(
init: setup,
draw: draw,
on_tick: option.None,
on_key: option.None,
on_mouse: option.None,
))
p5js_gleam.create_sketch(init: setup, draw: draw)
|> p5.start_sketch
}
2 changes: 1 addition & 1 deletion gleam.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name = "p5js_gleam"
version = "1.0.2"
version = "2.0.0"
target = "javascript"

description = "A simple game library providing p5.js bindings for Gleam in a functional style to make basic games and animations. Heavily inspired by the Racket library 2htdp/universe"
Expand Down
24 changes: 18 additions & 6 deletions scripts/generate_p5.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,16 +82,28 @@ export const startSketch = (config) => {
}
};
if (is_some(config.on_key)) {
if (is_some(config.on_key_pressed)) {
p.keyPressed = function () {
model = unwrap(config.on_key)(p.key, model);
}
model = unwrap(config.on_key_pressed)(p.key, p.keyCode, model);
};
}
if (is_some(config.on_key_released)) {
p.keyReleased = function () {
model = unwrap(config.on_key_released)(p.key, p.keyCode, model);
};
}
if (is_some(config.on_mouse)) {
if (is_some(config.on_mouse_clicked)) {
p.mouseClicked = function () {
model = unwrap(config.on_mouse)(p.pmouseX, p.pmouseY, model);
}
model = unwrap(config.on_mouse_clicked)(p.pmouseX, p.pmouseY, model);
};
}
if (is_some(config.on_mouse_moved)) {
p.mouseMoved = function () {
model = unwrap(config.on_mouse_moved)(p.pmouseX, p.pmouseY, model);
};
}
});
};
Expand Down
25 changes: 18 additions & 7 deletions src/p5js_ffi.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,28 @@ export const startSketch = (config) => {
}
};

if (is_some(config.on_key)) {
if (is_some(config.on_key_pressed)) {
p.keyPressed = function () {
model = unwrap(config.on_key)(p.key, model);
}
model = unwrap(config.on_key_pressed)(p.key, p.keyCode, model);
};
}

if (is_some(config.on_key_released)) {
p.keyReleased = function () {
model = unwrap(config.on_key_released)(p.key, p.keyCode, model);
};
}

if (is_some(config.on_mouse)) {
if (is_some(config.on_mouse_clicked)) {
p.mouseClicked = function () {
model = unwrap(config.on_mouse)(p.pmouseX, p.pmouseY, model);
}
model = unwrap(config.on_mouse_clicked)(p.pmouseX, p.pmouseY, model);
};
}

if (is_some(config.on_mouse_moved)) {
p.mouseMoved = function () {
model = unwrap(config.on_mouse_moved)(p.pmouseX, p.pmouseY, model);
};
}
});
};
Expand Down Expand Up @@ -92,4 +104,3 @@ export function strokeWeight(p, ...args) {
p.strokeWeight(...args);
return p;
}

74 changes: 67 additions & 7 deletions src/p5js_gleam.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,78 @@ import gleam/option.{type Option}
/// A reference to the P5js library. Primarily used to access the P5js APIs for drawing.
pub type P5

/// Configuration to start a sketch. Requires an init function to create the initial model, and a draw function to draw the model. Optionally, you can provide an on_tick function to update the model on each frame, an on_key function to handle key events, and an on_mouse function to handle mouse events.
pub type SketchConfig(model, ignored) {
/// Configuration to start a sketch. Requires an init function to create the initial model, and a draw function to draw the model. Other handlers can also be provided to update the model based on different user events. Use the `create_sketch` function and the `set_*` helpers to initialize your config.
pub opaque type SketchConfig(model, ignored) {
SketchConfig(
/// The init function takes a reference to the P5js library and returns the initial model. It should also create the canvas/do any P5 specific initialization.
init: fn(P5) -> model,
/// The draw function takes a reference to the P5js library and the current model then renders it to the screen.
draw: fn(P5, model) -> ignored,
/// on_tick functions take the current model, and return the updated model for the next frame.
/// Called on every frame. on_tick functions take the current model, and return the updated model for the next frame.
on_tick: Option(fn(model) -> model),
/// on_key functions take a string representing the key that was pressed, and the current model, and return the updated model.
on_key: Option(fn(String, model) -> model),
/// on_mouse functions take the x and y coordinates of the mouse, and the current model, and return the updated model.
on_mouse: Option(fn(Float, Float, model) -> model),
/// Called whenever a key is pressed down. on_key_pressed functions take a string representing the key that was pressed and a keycode representing the raw key code of the pressed key, and the current model, and return the updated model.
on_key_pressed: Option(fn(String, Int, model) -> model),
/// Called whenever a key is released. on_key_released functions take a string representing the key that was pressed and a keycode representing the raw key code of the pressed key, and the current model, and return the updated model.
on_key_released: Option(fn(String, Int, model) -> model),
/// Called whenever the user moves their mouse. on_mouse_move functions take the x and y coordinates of the mouse, and the current model, and return the updated model.
on_mouse_moved: Option(fn(Float, Float, model) -> model),
/// Called whenever the user clicks their mouse. on_mouse_click functions take the x and y coordinates of the mouse, and the current model, and return the updated model.
on_mouse_clicked: Option(fn(Float, Float, model) -> model),
)
}

/// Creates a minimal sketch configuration.
pub fn create_sketch(
init init: fn(P5) -> model,
draw draw: fn(P5, model) -> ignored,
) -> SketchConfig(model, ignored) {
SketchConfig(
init,
draw,
option.None,
option.None,
option.None,
option.None,
option.None,
)
}

/// Sets the `on_tick` function to be called.
pub fn set_on_tick(
s: SketchConfig(model, ignored),
on_tick: fn(model) -> model,
) -> SketchConfig(model, ignored) {
SketchConfig(..s, on_tick: option.Some(on_tick))
}

/// Sets the `on_key_pressed` function to be called.
pub fn set_on_key_pressed(
s: SketchConfig(model, ignored),
on_key_pressed: fn(String, Int, model) -> model,
) -> SketchConfig(model, ignored) {
SketchConfig(..s, on_key_pressed: option.Some(on_key_pressed))
}

/// Sets the `on_key_released` function to be called.
pub fn set_on_key_released(
s: SketchConfig(model, ignored),
on_key_released: fn(String, Int, model) -> model,
) -> SketchConfig(model, ignored) {
SketchConfig(..s, on_key_released: option.Some(on_key_released))
}

/// Sets the `on_mouse_moved` function to be called.
pub fn set_on_mouse_moved(
s: SketchConfig(model, ignored),
on_mouse_moved: fn(Float, Float, model) -> model,
) -> SketchConfig(model, ignored) {
SketchConfig(..s, on_mouse_moved: option.Some(on_mouse_moved))
}

/// Sets the `on_mouse_clicked` function to be called.
pub fn set_on_mouse_clicked(
s: SketchConfig(model, ignored),
on_mouse_clicked: fn(Float, Float, model) -> model,
) -> SketchConfig(model, ignored) {
SketchConfig(..s, on_mouse_clicked: option.Some(on_mouse_clicked))
}

0 comments on commit 460c1b1

Please sign in to comment.