Skip to content
This repository has been archived by the owner on Aug 24, 2024. It is now read-only.

Commit

Permalink
Split up main conjam.gleam file
Browse files Browse the repository at this point in the history
  • Loading branch information
nint8835 committed Apr 28, 2024
1 parent 645ea08 commit 946bae3
Show file tree
Hide file tree
Showing 6 changed files with 180 additions and 170 deletions.
51 changes: 51 additions & 0 deletions src/brush.gleam
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import canvas
import constants.{max_x, max_y}
import gleam/float
import gleam/int
import gleam/list
import gleam/result

pub fn apply_brush(
frame_data: canvas.ImageData,
mouse_x: Int,
mouse_y: Int,
brush_size: Int,
brush_colour: canvas.Pixel,
) -> canvas.ImageData {
list.range(-1 * brush_size, brush_size)
|> list.fold(frame_data, fn(row_data, y) {
list.range(-1 * brush_size, brush_size)
|> list.fold(row_data, fn(pixel_data, x) {
let distance =
float.square_root(
{
int.power(x, 2.0)
|> result.unwrap(0.0)
}
+. {
int.power(y, 2.0)
|> result.unwrap(0.0)
},
)
|> result.unwrap(0.0)
|> float.round()

let new_x = mouse_x + x
let new_y = mouse_y + y

case
distance > brush_size
|| new_x < 0
|| new_x > max_x
|| new_y < 0
|| new_y > max_y
{
True -> pixel_data
False -> {
pixel_data
|> canvas.set_pixel(new_x, new_y, brush_colour)
}
}
})
})
}
10 changes: 5 additions & 5 deletions src/canvas/canvas.gleam → src/canvas.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,15 @@ pub const canvas_width = 640

pub const canvas_height = 480

@external(javascript, "../ffi.mjs", "getIndex")
@external(javascript, "./ffi.mjs", "getIndex")
pub fn get_index(image_data: ImageData, index: Int) -> Pixel

pub fn get_pixel(image_data: ImageData, x: Int, y: Int) -> Pixel {
image_data
|> get_index(y * canvas_width + x)
}

@external(javascript, "../ffi.mjs", "setIndex")
@external(javascript, "./ffi.mjs", "setIndex")
pub fn set_index(image_data: ImageData, index: Int, pixel: Pixel) -> ImageData

pub fn set_pixel(
Expand All @@ -28,18 +28,18 @@ pub fn set_pixel(
|> set_index(y * canvas_width + x, pixel)
}

@external(javascript, "../ffi.mjs", "mutateFrame")
@external(javascript, "./ffi.mjs", "mutateFrame")
pub fn mutate_frame(mutator: fn(ImageData) -> ImageData) -> Nil

@external(javascript, "../ffi.mjs", "getNeighboursMatching")
@external(javascript, "./ffi.mjs", "getNeighboursMatching")
pub fn get_neighbours_matching(
image_data: ImageData,
x: Int,
y: Int,
predicate: fn(Pixel) -> Bool,
) -> Int

@external(javascript, "../ffi.mjs", "ensurePixelExists")
@external(javascript, "./ffi.mjs", "ensurePixelExists")
pub fn ensure_pixel_exists(
image_data: ImageData,
x: Int,
Expand Down
26 changes: 26 additions & 0 deletions src/collapse.gleam
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import canvas
import constants.{max_y}
import gleam/bool

pub fn collapse_like(
frame_data: canvas.ImageData,
x: Int,
y: Int,
) -> canvas.ImageData {
use <- canvas.ensure_pixel_exists(frame_data, x, y)
use <- bool.guard(when: y == max_y, return: frame_data)

let pixel_val =
frame_data
|> canvas.get_pixel(x, y)
let below_pixel_val =
frame_data
|> canvas.get_pixel(x, y + 1)

case pixel_val == below_pixel_val && pixel_val != 0x00000000 {
True ->
frame_data
|> canvas.set_pixel(x, y + 1, 0x00000000)
False -> frame_data
}
}
191 changes: 26 additions & 165 deletions src/conjam.gleam
Original file line number Diff line number Diff line change
@@ -1,168 +1,8 @@
import canvas/canvas
import gleam/bool
import gleam/float
import gleam/int
import gleam/list
import gleam/result

const max_x = 639

const max_y = 479

fn apply_gravity(
frame_data: canvas.ImageData,
x: Int,
y: Int,
next_pixel_offset: Int,
) -> canvas.ImageData {
use <- canvas.ensure_pixel_exists(frame_data, x, y)
use <- bool.guard(when: y == max_y, return: frame_data)

let pixel_val =
frame_data
|> canvas.get_pixel(x, y)

use <- bool.guard(when: pixel_val == 0x00000000, return: frame_data)

let below_pixel_val =
frame_data
|> canvas.get_pixel(x, y + 1)

case below_pixel_val {
0x00000000 ->
frame_data
|> canvas.set_pixel(x, y + 1, pixel_val)
|> canvas.set_pixel(x, y, 0x00000000)
_ -> {
let next_x = x + next_pixel_offset

let below_next_pixel_val = {
case next_x > max_x || next_x < 0 {
True -> 0xffffffff
False ->
frame_data
|> canvas.get_pixel(next_x, y + 1)
}
}

case below_next_pixel_val {
0x00000000 ->
frame_data
|> canvas.set_pixel(next_x, y + 1, pixel_val)
|> canvas.set_pixel(x, y, 0x00000000)
_ -> {
let prev_x = x - next_pixel_offset

let below_prev_pixel_val = {
case prev_x > max_x || prev_x < 0 {
True -> 0xffffffff
False ->
frame_data
|> canvas.get_pixel(prev_x, y + 1)
}
}

case below_prev_pixel_val {
0x00000000 ->
frame_data
|> canvas.set_pixel(prev_x, y + 1, pixel_val)
|> canvas.set_pixel(x, y, 0x00000000)
_ -> frame_data
}
}
}
}
}
}

fn collapse_like(
frame_data: canvas.ImageData,
x: Int,
y: Int,
) -> canvas.ImageData {
use <- canvas.ensure_pixel_exists(frame_data, x, y)
use <- bool.guard(when: y == max_y, return: frame_data)

let pixel_val =
frame_data
|> canvas.get_pixel(x, y)
let below_pixel_val =
frame_data
|> canvas.get_pixel(x, y + 1)

case pixel_val == below_pixel_val && pixel_val != 0x00000000 {
True ->
frame_data
|> canvas.set_pixel(x, y + 1, 0x00000000)
False -> frame_data
}
}

fn iter_pixels(
frame_data: canvas.ImageData,
x: Int,
y: Int,
next_pixel_offset: Int,
) -> canvas.ImageData {
case x, y {
_, -1 -> frame_data
-1, _ -> iter_pixels(frame_data, max_x, y - 1, next_pixel_offset)
x, _ if x > max_x -> iter_pixels(frame_data, 0, y - 1, next_pixel_offset)
_, _ -> {
let new_frame_data =
frame_data
|> apply_gravity(x, y, next_pixel_offset)
|> collapse_like(x, y)

iter_pixels(new_frame_data, x + next_pixel_offset, y, next_pixel_offset)
}
}
}

fn apply_brush(
frame_data: canvas.ImageData,
mouse_x: Int,
mouse_y: Int,
brush_size: Int,
brush_colour: canvas.Pixel,
) -> canvas.ImageData {
list.range(-1 * brush_size, brush_size)
|> list.fold(frame_data, fn(row_data, y) {
list.range(-1 * brush_size, brush_size)
|> list.fold(row_data, fn(pixel_data, x) {
let distance =
float.square_root(
{
int.power(x, 2.0)
|> result.unwrap(0.0)
}
+. {
int.power(y, 2.0)
|> result.unwrap(0.0)
},
)
|> result.unwrap(0.0)
|> float.round()

let new_x = mouse_x + x
let new_y = mouse_y + y

case
distance > brush_size
|| new_x < 0
|| new_x > max_x
|| new_y < 0
|| new_y > max_y
{
True -> pixel_data
False -> {
pixel_data
|> canvas.set_pixel(new_x, new_y, brush_colour)
}
}
})
})
}
import brush.{apply_brush}
import canvas
import collapse.{collapse_like}
import constants.{max_x, max_y}
import gravity.{apply_gravity}

pub fn draw_frame(
frame_number: Int,
Expand Down Expand Up @@ -193,3 +33,24 @@ pub fn draw_frame(
initial_data
|> iter_pixels(initial_x, max_y, initial_move_direction)
}

fn iter_pixels(
frame_data: canvas.ImageData,
x: Int,
y: Int,
next_pixel_offset: Int,
) -> canvas.ImageData {
case x, y {
_, -1 -> frame_data
-1, _ -> iter_pixels(frame_data, max_x, y - 1, next_pixel_offset)
x, _ if x > max_x -> iter_pixels(frame_data, 0, y - 1, next_pixel_offset)
_, _ -> {
let new_frame_data =
frame_data
|> apply_gravity(x, y, next_pixel_offset)
|> collapse_like(x, y)

iter_pixels(new_frame_data, x + next_pixel_offset, y, next_pixel_offset)
}
}
}
3 changes: 3 additions & 0 deletions src/constants.gleam
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
pub const max_x = 639

pub const max_y = 479
69 changes: 69 additions & 0 deletions src/gravity.gleam
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import canvas
import constants.{max_x, max_y}
import gleam/bool

pub fn apply_gravity(
frame_data: canvas.ImageData,
x: Int,
y: Int,
next_pixel_offset: Int,
) -> canvas.ImageData {
use <- canvas.ensure_pixel_exists(frame_data, x, y)
use <- bool.guard(when: y == max_y, return: frame_data)

let pixel_val =
frame_data
|> canvas.get_pixel(x, y)

use <- bool.guard(when: pixel_val == 0x00000000, return: frame_data)

let below_pixel_val =
frame_data
|> canvas.get_pixel(x, y + 1)

case below_pixel_val {
0x00000000 ->
frame_data
|> canvas.set_pixel(x, y + 1, pixel_val)
|> canvas.set_pixel(x, y, 0x00000000)
_ -> {
let next_x = x + next_pixel_offset

let below_next_pixel_val = {
case next_x > max_x || next_x < 0 {
True -> 0xffffffff
False ->
frame_data
|> canvas.get_pixel(next_x, y + 1)
}
}

case below_next_pixel_val {
0x00000000 ->
frame_data
|> canvas.set_pixel(next_x, y + 1, pixel_val)
|> canvas.set_pixel(x, y, 0x00000000)
_ -> {
let prev_x = x - next_pixel_offset

let below_prev_pixel_val = {
case prev_x > max_x || prev_x < 0 {
True -> 0xffffffff
False ->
frame_data
|> canvas.get_pixel(prev_x, y + 1)
}
}

case below_prev_pixel_val {
0x00000000 ->
frame_data
|> canvas.set_pixel(prev_x, y + 1, pixel_val)
|> canvas.set_pixel(x, y, 0x00000000)
_ -> frame_data
}
}
}
}
}
}

0 comments on commit 946bae3

Please sign in to comment.