From 075bc569182ac15b44e9a203b8f642422d98c518 Mon Sep 17 00:00:00 2001 From: ske Date: Tue, 16 Jul 2024 10:17:22 -0300 Subject: [PATCH] `atlas.um` and `tilemap.um` updates (#202) --- src/bindings.c | 4 +- src/staembed.c | 179 +++++++++++++++++++++++++++++++++++++----------- umka/atlas.um | 76 ++++++++++++-------- umka/tilemap.um | 39 +++++++++-- 4 files changed, 221 insertions(+), 77 deletions(-) diff --git a/src/bindings.c b/src/bindings.c index d02d6be..027e704 100644 --- a/src/bindings.c +++ b/src/bindings.c @@ -187,7 +187,7 @@ umth_tilemap_draw(UmkaStackSlot *p, UmkaStackSlot *r) // ent - entity to collide with, t - tilemap, x and y - pointers to ints used to return, where the // collision occured -// fn umth_tilemap_getcoll(tc: ^th::Vf2, ic: ^th::Vf2, t: ^Tilemap, ent: ^Entity): int +// fn umth_tilemap_getcoll(tc: ^th::Vf2, ic: ^th::Vf2, t: ^Tilemap, ent: ^Entity): bool void umth_tilemap_getcoll(UmkaStackSlot *p, UmkaStackSlot *r) { @@ -199,7 +199,7 @@ umth_tilemap_getcoll(UmkaStackSlot *p, UmkaStackSlot *r) umkaGetResult(p, r)->intVal = th_coll_on_tilemap(ent, t, ic, tc); } -// fn umth_tilemap_getcoll_line(b: th::Vf2, e: th::Vf2, t: ^Tilemap, ic: ^th::Vf2): int +// fn umth_tilemap_getcoll_line(b: th::Vf2, e: th::Vf2, t: ^Tilemap, ic: ^th::Vf2): bool void umth_tilemap_getcoll_line(UmkaStackSlot *p, UmkaStackSlot *r) { diff --git a/src/staembed.c b/src/staembed.c index c127b2f..85c930a 100644 --- a/src/staembed.c +++ b/src/staembed.c @@ -1495,7 +1495,26 @@ const char *th_em_modulesrc[] = { "//~~\n" "\n" "//~~fn mk\n" -"fn mk*(cells: []th::uu, w: th::uu, at: atlas::Atlas, scale: th::fu = 1): Tilemap {\n" +"// Make a tilemap with all cells set to 0.\n" +"fn mk*(w, h: th::uu, at: atlas::Atlas, scale: th::fu = 1): Tilemap {\n" +"//~~\n" +"\tif !at.i.validate() {\n" +"\t\tth::__error(\"invalid atlas\")\n" +"\t}\n" +"\n" +"\tt := Tilemap{}\n" +"\tt.cells = make([]th::uu, w*h)\n" +"\tt.w = w\n" +"\tt.atlas = at\n" +"\tt.collMask = make([]bool, 10) // TODO\n" +"\tt.scale = scale\n" +"\n" +"\treturn t\n" +"}\n" +"\n" +"//~~fn mk2\n" +"// Make a tilemap from a list of cells.\n" +"fn mk2*(cells: []th::uu, w: th::uu, at: atlas::Atlas, scale: th::fu = 1): Tilemap {\n" "//~~\n" "\tif !at.i.validate() {\n" "\t\tth::__error(\"invalid atlas\")\n" @@ -1512,12 +1531,20 @@ const char *th_em_modulesrc[] = { "}\n" "\n" "//~~fn Tilemap.edit\n" -"// Sets tile at [x, y] to tile.\n" -"fn (t: ^Tilemap) edit*(x, y, tile: int) {\n" +"// Edit a tile in the tilemap.\n" +"fn (t: ^Tilemap) edit*(x, y, tile: int){\n" "//~~\n" "\tt.cells[y*t.w + x] = tile\n" "}\n" "\n" +"//~~fn Tilemap.get\n" +"// Get a tile from the tilemap.\n" +"fn (t: ^Tilemap) get*(x, y: int): int {\n" +"//~~\n" +"\treturn t.cells[y*t.w + x]\n" +"}\n" +"\n" +"\n" "fn umth_tilemap_draw(ct: ^Tilemap, tr: th::Transform)\n" "//~~fn Tilemap.draw\n" "// Draws the tilemap.\n" @@ -1528,7 +1555,7 @@ const char *th_em_modulesrc[] = { "\tumth_tilemap_draw(t, tr)\n" "}\n" "\n" -"fn umth_tilemap_getcoll(pos: ^th::Vf2, vert: ^th::Vf2, t: ^Tilemap, e: ^ent::Ent): int32\n" +"fn umth_tilemap_getcoll(pos: ^th::Vf2, vert: ^th::Vf2, t: ^Tilemap, e: ^ent::Ent): bool\n" "//~~fn Tilemap.getColl\n" "// Checks whether `e` collides with any of the tiles in `t`, which are in the\n" "// collmask.\n" @@ -1546,9 +1573,7 @@ const char *th_em_modulesrc[] = { "\tif ic == null { ic = &_ }\n" "\tif pos == null { pos = &_ }\n" "\n" -"\tc := umth_tilemap_getcoll(pos, ic, t, &e)\n" -"\n" -"\treturn bool(c)\n" +"\treturn umth_tilemap_getcoll(pos, ic, t, &e)\n" "}\n" "\n" "fn umth_tilemap_getcoll_line(b, e: th::Vf2, t: ^Tilemap, ic: ^th::Vf2): bool\n" @@ -2640,41 +2665,69 @@ const char *th_em_modulesrc[] = { "\treturn a\n" "}\n" "\n" +"//~~fn mk2\n" +"// i: source image\n" +"// cs: size of a cell in pixels\n" +"fn mk2*(i: image::Image, cs: th::Vf2): Atlas {\n" +"//~~\n" +"\tif !i.validate() {\n" +"\t\tth::__error(\"Image is not valid\")\n" +"\t}\n" +"\n" +"\ta := Atlas{}\n" +"\n" +"\ta.i = i\n" +"\ta.cs = cs\n" +"\ta.dm = i.getDims().div(cs)\n" +"\n" +"\treturn a\n" +"}\n" +"\n" "//~~fn Atlas.coords\n" "// returns the coordinates of the nth tile\n" -"fn (a: ^Atlas) coords*(n: int): (th::Vf2, std::Err) {\n" +"fn (a: ^Atlas) coords*(n: int): th::Vf2 {\n" "//~~\n" -"\to := th::Vf2{ n % trunc(a.dm.x), (n - n % trunc(a.dm.x)) / a.dm.x }\n" -"\tif o.x > a.dm.x || o.y > a.dm.y {\n" -"\t\treturn {}, th::__errFromCode(.out_of_bounds)\n" -"\t}\n" -"\treturn o, {}\n" +"\tn--\n" +"\treturn th::Vf2{ n % trunc(a.dm.x), (n - n % trunc(a.dm.x)) / a.dm.x }\n" "}\n" "\n" "//~~fn Atlas.rect\n" "// returns the rectangle of the nth tile\n" -"fn (a: ^Atlas) rect*(n: int): (rect::Rect, std::Err) {\n" +"fn (a: ^Atlas) rect*(n: int): rect::Rect {\n" "//~~\n" -"\to := th::Vf2{ n % trunc(a.dm.x), (n - n % trunc(a.dm.x)) / a.dm.x }\n" -"\tif o.x > a.dm.x || o.y > a.dm.y {\n" -"\t\treturn {}, th::__errFromCode(.out_of_bounds)\n" -"\t}\n" -"\treturn {o.x*a.cs.x, o.y*a.cs.y, a.cs.x, a.cs.y}, {}\n" +"\tn--\n" +"\treturn {(n % trunc(a.dm.x))*a.cs.x, ((n - n % trunc(a.dm.x)) / a.dm.x)*a.cs.y, a.cs.x, a.cs.y}\n" +"}\n" +"\n" +"//~~fn Atlas.index\n" +"// returns the index of the tile at the given coordinates\n" +"fn (a: ^Atlas) index*(at: th::Vf2): int {\n" +"//~~\n" +"\treturn int(trunc(at.x) + trunc(at.y) * trunc(a.dm.x)) - 1\n" +"}\n" +"\n" +"//~~fn Atlas.has\n" +"// returns true if the tile at the given coordinates exists\n" +"fn (a: ^Atlas) has*(at: th::Vf2): bool {\n" +"//~~\n" +"\treturn at.x >= 0 && at.y >= 0 && at.x < a.dm.x && at.y < a.dm.y\n" +"}\n" +"\n" +"//~~fn Atlas.hasIndex\n" +"// returns true if the tile at the given index exists\n" +"fn (a: ^Atlas) hasIndex*(n: int): bool {\n" +"//~~\n" +"\treturn n > 0 && n <= trunc(a.dm.x * a.dm.y)\n" "}\n" "\n" "//~~fn Atlas.cropSource\n" "// Crops the sourse image to only show a wanted tile\n" -"fn (a: ^Atlas) cropSource*(at: th::Vf2): std::Err {\n" +"fn (a: ^Atlas) cropSource*(at: th::Vf2) {\n" "//~~\n" -"\tif (at.x > a.dm.x || at.y > a.dm.y || at.x * at.y < 0) {\n" -"\t\treturn th::__errFromCode(.out_of_bounds)\n" -"\t}\n" -"\n" "\ta.i.crop(\n" "\t\t{at.x / a.dm.x, at.y / a.dm.y},\n" -"\t\t{(at.x+1) / a.dm.x, (at.y+1) / a.dm.y})\n" -"\n" -"\treturn {}\n" +"\t\t{(at.x+1) / a.dm.x, (at.y+1) / a.dm.y}\n" +"\t)\n" "}\n" "\n" "//~~enum PackStrategy\n" @@ -2698,17 +2751,11 @@ const char *th_em_modulesrc[] = { "\n" "//~~fn Atlas.draw\n" "// Draws the tile at `at`\n" -"fn (a: ^Atlas) draw*(at: th::Vf2, t: th::Transform): std::Err {\n" +"fn (a: ^Atlas) draw*(at: th::Vf2, t: th::Transform) {\n" "//~~\n" -"\tif (at.x > a.dm.x || at.y > a.dm.y || at.x * at.y < 0) {\n" -"\t\treturn th::__errFromCode(.out_of_bounds)\n" -"\t}\n" -"\n" "\ta.cropSource(at)\n" "\ta.i.draw(t, th::white)\n" "\ta.i.crop({}, {1, 1})\n" -"\n" -"\treturn {}\n" "}\n" "", "\n" @@ -5166,16 +5213,33 @@ const char *th_em_moduledocs[] = { "\n" "fn mk\n" "\n" -"fn mk*(cells: []th::uu, w: th::uu, at: atlas::Atlas, scale: th::fu = 1): Tilemap {\n" +"fn mk*(w, h: th::uu, at: atlas::Atlas, scale: th::fu = 1): Tilemap {\n" "\n" +"Make a tilemap with all cells set to 0.\n" +"\n" +"---------\n" +"\n" +"fn mk2\n" +"\n" +"fn mk2*(cells: []th::uu, w: th::uu, at: atlas::Atlas, scale: th::fu = 1): Tilemap {\n" +"\n" +"Make a tilemap from a list of cells.\n" "\n" "---------\n" "\n" "fn Tilemap.edit\n" "\n" -"fn (t: ^Tilemap) edit*(x, y, tile: int) {\n" +"fn (t: ^Tilemap) edit*(x, y, tile: int){\n" +"\n" +"Edit a tile in the tilemap.\n" +"\n" +"---------\n" +"\n" +"fn Tilemap.get\n" +"\n" +"fn (t: ^Tilemap) get*(x, y: int): int {\n" "\n" -"Sets tile at [x, y] to tile.\n" +"Get a tile from the tilemap.\n" "\n" "---------\n" "\n" @@ -6057,9 +6121,18 @@ const char *th_em_moduledocs[] = { "\n" "---------\n" "\n" +"fn mk2\n" +"\n" +"fn mk2*(i: image::Image, cs: th::Vf2): Atlas {\n" +"\n" +"i: source image\n" +"cs: size of a cell in pixels\n" +"\n" +"---------\n" +"\n" "fn Atlas.coords\n" "\n" -"fn (a: ^Atlas) coords*(n: int): (th::Vf2, std::Err) {\n" +"fn (a: ^Atlas) coords*(n: int): th::Vf2 {\n" "\n" "returns the coordinates of the nth tile\n" "\n" @@ -6067,15 +6140,39 @@ const char *th_em_moduledocs[] = { "\n" "fn Atlas.rect\n" "\n" -"fn (a: ^Atlas) rect*(n: int): (rect::Rect, std::Err) {\n" +"fn (a: ^Atlas) rect*(n: int): rect::Rect {\n" "\n" "returns the rectangle of the nth tile\n" "\n" "---------\n" "\n" +"fn Atlas.index\n" +"\n" +"fn (a: ^Atlas) index*(at: th::Vf2): int {\n" +"\n" +"returns the index of the tile at the given coordinates\n" +"\n" +"---------\n" +"\n" +"fn Atlas.has\n" +"\n" +"fn (a: ^Atlas) has*(at: th::Vf2): bool {\n" +"\n" +"returns true if the tile at the given coordinates exists\n" +"\n" +"---------\n" +"\n" +"fn Atlas.hasIndex\n" +"\n" +"fn (a: ^Atlas) hasIndex*(n: int): bool {\n" +"\n" +"returns true if the tile at the given index exists\n" +"\n" +"---------\n" +"\n" "fn Atlas.cropSource\n" "\n" -"fn (a: ^Atlas) cropSource*(at: th::Vf2): std::Err {\n" +"fn (a: ^Atlas) cropSource*(at: th::Vf2) {\n" "\n" "Crops the sourse image to only show a wanted tile\n" "\n" @@ -6102,7 +6199,7 @@ const char *th_em_moduledocs[] = { "\n" "fn Atlas.draw\n" "\n" -"fn (a: ^Atlas) draw*(at: th::Vf2, t: th::Transform): std::Err {\n" +"fn (a: ^Atlas) draw*(at: th::Vf2, t: th::Transform) {\n" "\n" "Draws the tile at `at`\n" "\n" diff --git a/umka/atlas.um b/umka/atlas.um index 2126c78..f46b903 100644 --- a/umka/atlas.um +++ b/umka/atlas.um @@ -33,41 +33,69 @@ fn mk*(i: image::Image, dm: th::Vf2): Atlas { return a } +//~~fn mk2 +// i: source image +// cs: size of a cell in pixels +fn mk2*(i: image::Image, cs: th::Vf2): Atlas { +//~~ + if !i.validate() { + th::__error("Image is not valid") + } + + a := Atlas{} + + a.i = i + a.cs = cs + a.dm = i.getDims().div(cs) + + return a +} + //~~fn Atlas.coords // returns the coordinates of the nth tile -fn (a: ^Atlas) coords*(n: int): (th::Vf2, std::Err) { +fn (a: ^Atlas) coords*(n: int): th::Vf2 { //~~ - o := th::Vf2{ n % trunc(a.dm.x), (n - n % trunc(a.dm.x)) / a.dm.x } - if o.x > a.dm.x || o.y > a.dm.y { - return {}, th::__errFromCode(.out_of_bounds) - } - return o, {} + n-- + return th::Vf2{ n % trunc(a.dm.x), (n - n % trunc(a.dm.x)) / a.dm.x } } //~~fn Atlas.rect // returns the rectangle of the nth tile -fn (a: ^Atlas) rect*(n: int): (rect::Rect, std::Err) { +fn (a: ^Atlas) rect*(n: int): rect::Rect { //~~ - o := th::Vf2{ n % trunc(a.dm.x), (n - n % trunc(a.dm.x)) / a.dm.x } - if o.x > a.dm.x || o.y > a.dm.y { - return {}, th::__errFromCode(.out_of_bounds) - } - return {o.x*a.cs.x, o.y*a.cs.y, a.cs.x, a.cs.y}, {} + n-- + return {(n % trunc(a.dm.x))*a.cs.x, ((n - n % trunc(a.dm.x)) / a.dm.x)*a.cs.y, a.cs.x, a.cs.y} +} + +//~~fn Atlas.index +// returns the index of the tile at the given coordinates +fn (a: ^Atlas) index*(at: th::Vf2): int { +//~~ + return int(trunc(at.x) + trunc(at.y) * trunc(a.dm.x)) - 1 +} + +//~~fn Atlas.has +// returns true if the tile at the given coordinates exists +fn (a: ^Atlas) has*(at: th::Vf2): bool { +//~~ + return at.x >= 0 && at.y >= 0 && at.x < a.dm.x && at.y < a.dm.y +} + +//~~fn Atlas.hasIndex +// returns true if the tile at the given index exists +fn (a: ^Atlas) hasIndex*(n: int): bool { +//~~ + return n > 0 && n <= trunc(a.dm.x * a.dm.y) } //~~fn Atlas.cropSource // Crops the sourse image to only show a wanted tile -fn (a: ^Atlas) cropSource*(at: th::Vf2): std::Err { +fn (a: ^Atlas) cropSource*(at: th::Vf2) { //~~ - if (at.x > a.dm.x || at.y > a.dm.y || at.x * at.y < 0) { - return th::__errFromCode(.out_of_bounds) - } - a.i.crop( {at.x / a.dm.x, at.y / a.dm.y}, - {(at.x+1) / a.dm.x, (at.y+1) / a.dm.y}) - - return {} + {(at.x+1) / a.dm.x, (at.y+1) / a.dm.y} + ) } //~~enum PackStrategy @@ -91,15 +119,9 @@ fn pack*(images: []image::Image, strategy: PackStrategy): (Atlas, std::Err) { //~~fn Atlas.draw // Draws the tile at `at` -fn (a: ^Atlas) draw*(at: th::Vf2, t: th::Transform): std::Err { +fn (a: ^Atlas) draw*(at: th::Vf2, t: th::Transform) { //~~ - if (at.x > a.dm.x || at.y > a.dm.y || at.x * at.y < 0) { - return th::__errFromCode(.out_of_bounds) - } - a.cropSource(at) a.i.draw(t, th::white) a.i.crop({}, {1, 1}) - - return {} } diff --git a/umka/tilemap.um b/umka/tilemap.um index fafdb95..3cf4ef4 100644 --- a/umka/tilemap.um +++ b/umka/tilemap.um @@ -31,7 +31,26 @@ type Tilemap* = struct { //~~ //~~fn mk -fn mk*(cells: []th::uu, w: th::uu, at: atlas::Atlas, scale: th::fu = 1): Tilemap { +// Make a tilemap with all cells set to 0. +fn mk*(w, h: th::uu, at: atlas::Atlas, scale: th::fu = 1): Tilemap { +//~~ + if !at.i.validate() { + th::__error("invalid atlas") + } + + t := Tilemap{} + t.cells = make([]th::uu, w*h) + t.w = w + t.atlas = at + t.collMask = make([]bool, 10) // TODO + t.scale = scale + + return t +} + +//~~fn mk2 +// Make a tilemap from a list of cells. +fn mk2*(cells: []th::uu, w: th::uu, at: atlas::Atlas, scale: th::fu = 1): Tilemap { //~~ if !at.i.validate() { th::__error("invalid atlas") @@ -48,12 +67,20 @@ fn mk*(cells: []th::uu, w: th::uu, at: atlas::Atlas, scale: th::fu = 1): Tilemap } //~~fn Tilemap.edit -// Sets tile at [x, y] to tile. -fn (t: ^Tilemap) edit*(x, y, tile: int) { +// Edit a tile in the tilemap. +fn (t: ^Tilemap) edit*(x, y, tile: int){ //~~ t.cells[y*t.w + x] = tile } +//~~fn Tilemap.get +// Get a tile from the tilemap. +fn (t: ^Tilemap) get*(x, y: int): int { +//~~ + return t.cells[y*t.w + x] +} + + fn umth_tilemap_draw(ct: ^Tilemap, tr: th::Transform) //~~fn Tilemap.draw // Draws the tilemap. @@ -64,7 +91,7 @@ fn (t: ^Tilemap) draw*(tr: th::Transform) { umth_tilemap_draw(t, tr) } -fn umth_tilemap_getcoll(pos: ^th::Vf2, vert: ^th::Vf2, t: ^Tilemap, e: ^ent::Ent): int32 +fn umth_tilemap_getcoll(pos: ^th::Vf2, vert: ^th::Vf2, t: ^Tilemap, e: ^ent::Ent): bool //~~fn Tilemap.getColl // Checks whether `e` collides with any of the tiles in `t`, which are in the // collmask. @@ -82,9 +109,7 @@ fn (t: ^Tilemap) getColl*(e: ent::Ent, ic: ^th::Vf2, pos: ^th::Vf2): bool { if ic == null { ic = &_ } if pos == null { pos = &_ } - c := umth_tilemap_getcoll(pos, ic, t, &e) - - return bool(c) + return umth_tilemap_getcoll(pos, ic, t, &e) } fn umth_tilemap_getcoll_line(b, e: th::Vf2, t: ^Tilemap, ic: ^th::Vf2): bool