Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
wking-io committed Dec 19, 2024
1 parent 0a9220f commit c8b33ea
Show file tree
Hide file tree
Showing 12 changed files with 1,015 additions and 317 deletions.
Binary file modified art/asset/test-tile.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified art/source/test-tile.aseprite
Binary file not shown.
996 changes: 691 additions & 305 deletions client/priv/static/client.mjs

Large diffs are not rendered by default.

56 changes: 45 additions & 11 deletions client/src/client.gleam
Original file line number Diff line number Diff line change
@@ -1,19 +1,26 @@
// IMPORTS ---------------------------------------------------------------------

import gleam/float
import gleam/int
import gleam/io
import gleam/list
import gleam/order.{type Order}
import gleam/result
import gleam_community/maths/elementary
import lib/canvas as canvas_impl
import lib/canvas/context as context_impl
import lib/coord
import lib/cursor
import lib/direction
import lib/engine
import lib/event
import lib/frames
import lib/input
import lib/map
import lib/map/demo_one
import lib/render
import lib/sprite
import lib/tile
import lib/vector
import lustre
import lustre/attribute
Expand Down Expand Up @@ -45,7 +52,7 @@ fn init(_) -> #(Model, Effect(Msg)) {
// UPDATE ----------------------------------------------------------------------

type Msg {
AppInitCanvas(Float)
AppInitEngine(Float)
AppSetNoCanvas
Tick(Float)
PlayerQueueEvent(event.Event)
Expand All @@ -57,8 +64,8 @@ type Event {

fn update(model: Model, msg: Msg) -> #(Model, Effect(Msg)) {
case msg {
AppInitCanvas(previous_time) -> #(
Ready(engine.new(previous_time)),
AppInitEngine(previous_time) -> #(
Ready(engine.new(previous_time, demo_one.new())),
effect.batch([setup_listeners(), schedule_next_frame()]),
)
AppSetNoCanvas -> #(NoCanvas, effect.none())
Expand Down Expand Up @@ -226,13 +233,7 @@ fn is_gt_or_eq(order: Order) -> Bool {
fn init_canvas() {
effect.from(fn(dispatch) {
engine.request_animation_frame(fn(timestamp) {
case render.with_context() {
Ok(render.RenderContext(_canvas, context)) -> {
context_impl.fill_rect(context, 0.0, 0.0, 1000.0, 1000.0)
dispatch(AppInitCanvas(timestamp))
}
_ -> dispatch(AppSetNoCanvas)
}
dispatch(AppInitEngine(timestamp))
})
})
}
Expand All @@ -249,11 +250,44 @@ fn view(_model: Model) -> Element(Msg) {
html.div([], [html.canvas([attribute.id(render.render_target_id)])])
}

fn scale_to_screen(from: Int) {
from * 32 |> int.to_float()
}

fn render(game_state: engine.GameState) -> Effect(Msg) {
effect.from(fn(_dispatch) {
engine.request_animation_frame(fn(_timestamp) {
case render.with_context() {
Ok(render.RenderContext(_canvas, context)) -> {
Ok(render.RenderContext(canvas, context)) -> {
canvas
|> canvas_impl.set_width(game_state.map.width)
|> canvas_impl.set_height(game_state.map.height)

game_state.map
|> map.each_tile(fn(coords, tile) {
let sprite_region =
game_state.map.sprite_sheet
|> tile.get_sprite(tile.terrain)

case sprite_region {
Ok(region) -> {
context_impl.draw_image_cropped(
context,
game_state.map.sprite_sheet.asset,
sprite.x(region) |> scale_to_screen(),
sprite.y(region) |> scale_to_screen(),
32.0,
32.0,
coord.x(coords) |> scale_to_screen(),
coord.y(coords) |> scale_to_screen(),
32.0,
32.0,
)
}
_ -> context
}
})

let new_cursor = case game_state.cursor_animation {
cursor.CursorIdle(elapsed, cycle, amplitude) -> {
let t = float.divide(elapsed, cycle) |> result.unwrap(0.0)
Expand Down
6 changes: 6 additions & 0 deletions client/src/client_lib_asset_ffi.mjs
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
const __asset_cache = {};

export function load_image(src) {
const cached_image = __asset_cache[src];
if (cached_image) return cached_image;

const image = new Image();
image.src = src;
__asset_cache[src] = image;
return image;
}
43 changes: 43 additions & 0 deletions client/src/lib/asset/demo.gleam
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import gleam/dict
import lib/asset
import lib/sprite

pub type DemoVariant {
Base
Variant1
Variant2
Variant3
Variant4
Variant5
Variant6
}

pub fn get_sprite_key(variant: DemoVariant) {
case variant {
Base -> "Base"
Variant1 -> "Variant1"
Variant2 -> "Variant2"
Variant3 -> "Variant3"
Variant4 -> "Variant4"
Variant5 -> "Variant5"
Variant6 -> "Variant6"
}
}

const sprites = [
#("Base", sprite.SpriteRegion(0, 0)), #("Variant1", sprite.SpriteRegion(0, 0)),
#("Variant2", sprite.SpriteRegion(0, 1)),
#("Variant3", sprite.SpriteRegion(0, 2)),
#("Variant4", sprite.SpriteRegion(0, 3)),
#("Variant5", sprite.SpriteRegion(0, 4)),
#("Variant6", sprite.SpriteRegion(0, 5)),
]

pub fn sprite_sheet() -> sprite.SpriteSheet {
sprite.SpriteSheet(
asset: asset.load_image(
"https://pub-e304780d47a742ad9bad4f35844cd6e6.r2.dev/test-tile.png",
),
sprites: dict.from_list(sprites),
)
}
58 changes: 58 additions & 0 deletions client/src/lib/coord.gleam
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import gleam/int

pub opaque type Coord {
Coord(x: Int, y: Int, width: Int, height: Int)
}

pub fn new(width: Int, height: Int) -> Coord {
Coord(0, 0, width, height)
}

pub fn move(from: Coord, x: Int, y: Int) -> Coord {
Coord(
int.clamp(from.x + x, 0, from.width),
int.clamp(from.y + y, 0, from.height),
from.width,
from.height,
)
}

pub fn next(coord: Coord) -> Coord {
case is_bounded_x(coord), is_bounded_y(coord) {
True, _ -> Coord(..coord, x: coord.x + 1)
_, True -> Coord(..coord, y: coord.y + 1)
_, _ -> coord
}
}

fn is_bounded_x(coord: Coord) -> Bool {
coord.x < coord.width - 1
}

fn is_bounded_y(coord: Coord) -> Bool {
coord.y < coord.height - 1
}

pub fn left(coord: Coord) -> Coord {
move(coord, -1, 0)
}

pub fn right(coord: Coord) -> Coord {
move(coord, 1, 0)
}

pub fn up(coord: Coord) -> Coord {
move(coord, 0, -1)
}

pub fn down(coord: Coord) -> Coord {
move(coord, 0, 1)
}

pub fn x(coord: Coord) {
coord.x
}

pub fn y(coord: Coord) {
coord.y
}
5 changes: 4 additions & 1 deletion client/src/lib/engine.gleam
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import lib/cursor
import lib/event
import lib/map
import lib/vector

pub type GameState {
Expand All @@ -10,17 +11,19 @@ pub type GameState {
cursor: vector.Vector,
cursor_animation: cursor.CursorAnimation,
fps: Float,
map: map.Map,
)
}

pub fn new(init: Float) -> GameState {
pub fn new(init: Float, map: map.Map) -> GameState {
GameState(
previous_time: init,
accumulator: 0.0,
event_queue: event.new_queue(),
cursor: vector.new(),
cursor_animation: cursor.new_idle_cursor(),
fps: 0.0,
map: map,
)
}

Expand Down
30 changes: 30 additions & 0 deletions client/src/lib/map.gleam
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import lib/coord
import lib/sprite
import lib/tile

pub type Map {
Map(
width: Int,
height: Int,
sprite_sheet: sprite.SpriteSheet,
tiles: List(tile.Tile),
)
}

pub fn each_tile(map: Map, f: fn(coord.Coord, tile.Tile) -> b) -> Nil {
each_tile_loop(map.tiles, coord.new(map.width, map.height), f)
}

fn each_tile_loop(
tiles: List(tile.Tile),
coords: coord.Coord,
f: fn(coord.Coord, tile.Tile) -> b,
) -> Nil {
case tiles {
[] -> Nil
[tile, ..rest] -> {
f(coords, tile)
each_tile_loop(rest, coord.next(coords), f)
}
}
}
88 changes: 88 additions & 0 deletions client/src/lib/map/demo_one.gleam
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import lib/asset/demo
import lib/map
import lib/tile

pub fn new() -> map.Map {
map.Map(width: 8, height: 8, sprite_sheet: demo.sprite_sheet(), tiles: [
// Row 1
new_tile(demo.Base),
new_tile(demo.Variant1),
new_tile(demo.Variant6),
new_tile(demo.Base),
new_tile(demo.Variant4),
new_tile(demo.Variant5),
new_tile(demo.Variant2),
new_tile(demo.Base),
// Row 2
new_tile(demo.Variant3),
new_tile(demo.Variant4),
new_tile(demo.Base),
new_tile(demo.Variant5),
new_tile(demo.Variant1),
new_tile(demo.Base),
new_tile(demo.Variant6),
new_tile(demo.Variant2),
// Row 3
new_tile(demo.Variant2),
new_tile(demo.Base),
new_tile(demo.Base),
new_tile(demo.Variant1),
new_tile(demo.Base),
new_tile(demo.Variant3),
new_tile(demo.Base),
// Row 4
new_tile(demo.Base),
new_tile(demo.Variant4),
new_tile(demo.Base),
new_tile(demo.Variant1),
new_tile(demo.Variant3),
new_tile(demo.Base),
new_tile(demo.Base),
new_tile(demo.Base),
new_tile(demo.Variant2),
// Row 5
new_tile(demo.Variant3),
new_tile(demo.Base),
new_tile(demo.Variant4),
new_tile(demo.Base),
new_tile(demo.Variant5),
new_tile(demo.Base),
new_tile(demo.Base),
new_tile(demo.Variant1),
// Row 6
new_tile(demo.Base),
new_tile(demo.Variant1),
new_tile(demo.Base),
new_tile(demo.Variant3),
new_tile(demo.Base),
new_tile(demo.Variant2),
new_tile(demo.Variant5),
new_tile(demo.Base),
// Row 7
new_tile(demo.Variant4),
new_tile(demo.Variant2),
new_tile(demo.Base),
new_tile(demo.Base),
new_tile(demo.Variant5),
new_tile(demo.Base),
new_tile(demo.Variant6),
new_tile(demo.Base),
// Row 8
new_tile(demo.Variant6),
new_tile(demo.Base),
new_tile(demo.Variant1),
new_tile(demo.Variant4),
new_tile(demo.Base),
new_tile(demo.Base),
new_tile(demo.Base),
new_tile(demo.Variant2),
])
}

fn new_tile(variant: demo.DemoVariant) -> tile.Tile {
tile.Tile(
elevation: 0,
terrain: tile.Demo(variant),
passability: tile.Passable,
)
}
18 changes: 18 additions & 0 deletions client/src/lib/sprite.gleam
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import gleam/dict
import lib/asset

pub type SpriteRegion {
SpriteRegion(x: Int, y: Int)
}

pub type SpriteSheet {
SpriteSheet(asset: asset.Asset, sprites: dict.Dict(String, SpriteRegion))
}

pub fn x(sr: SpriteRegion) {
sr.x
}

pub fn y(sr: SpriteRegion) {
sr.y
}
Loading

0 comments on commit c8b33ea

Please sign in to comment.