1
0
Fork 0
forked from AbleOS/ableos

various render changes, implement sine & cosine for stn.math

This commit is contained in:
koniifer 2024-10-19 15:54:19 +01:00
parent 7caa47b9fb
commit a94332370a
10 changed files with 182 additions and 67 deletions

38
Cargo.lock generated
View file

@ -61,9 +61,9 @@ dependencies = [
[[package]] [[package]]
name = "anyhow" name = "anyhow"
version = "1.0.89" version = "1.0.90"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "86fdf8605db99b54d3cd748a44c6d04df638eb5dafb219b135d0149bd0db01f6" checksum = "37bf3594c4c988a53154954629820791dde498571819ae4ca50ca811e060cc95"
[[package]] [[package]]
name = "autocfg" name = "autocfg"
@ -145,9 +145,9 @@ checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3"
[[package]] [[package]]
name = "cc" name = "cc"
version = "1.1.30" version = "1.1.31"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b16803a61b81d9eabb7eae2588776c4c1e584b738ede45fdbb4c972cec1e9945" checksum = "c2e7962b54006dcfcc61cb72735f4d89bb97061dd6a7ed882ec6b8ee53714c6f"
dependencies = [ dependencies = [
"shlex", "shlex",
] ]
@ -350,12 +350,12 @@ checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb"
[[package]] [[package]]
name = "hbbytecode" name = "hbbytecode"
version = "0.1.0" version = "0.1.0"
source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#ea736d88244ce1d85999d7ce6387a63c655b7000" source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#6ad0b41759dacd5767b5c9cfbc1b3b11c025396a"
[[package]] [[package]]
name = "hblang" name = "hblang"
version = "0.1.0" version = "0.1.0"
source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#ea736d88244ce1d85999d7ce6387a63c655b7000" source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#6ad0b41759dacd5767b5c9cfbc1b3b11c025396a"
dependencies = [ dependencies = [
"hashbrown 0.15.0", "hashbrown 0.15.0",
"hbbytecode", "hbbytecode",
@ -367,7 +367,7 @@ dependencies = [
[[package]] [[package]]
name = "hbvm" name = "hbvm"
version = "0.1.0" version = "0.1.0"
source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#ea736d88244ce1d85999d7ce6387a63c655b7000" source = "git+https://git.ablecorp.us/AbleOS/holey-bytes.git#6ad0b41759dacd5767b5c9cfbc1b3b11c025396a"
dependencies = [ dependencies = [
"hbbytecode", "hbbytecode",
] ]
@ -420,9 +420,9 @@ checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946"
[[package]] [[package]]
name = "hyper" name = "hyper"
version = "1.4.1" version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" checksum = "bbbff0a806a4728c99295b254c8838933b5b082d75e3cb70c8dab21fdfbcfa9a"
dependencies = [ dependencies = [
"bytes", "bytes",
"futures-channel", "futures-channel",
@ -567,9 +567,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.159" version = "0.2.161"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5" checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1"
[[package]] [[package]]
name = "limine" name = "limine"
@ -718,9 +718,9 @@ dependencies = [
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "1.0.87" version = "1.0.88"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b3e4daa0dcf6feba26f985457cdf104d4b4256fc5a09547140f3631bb076b19a" checksum = "7c3a7fc5db1e57d5a779a352c8cdb57b29aa4c40cc69c3a68a7fedc815fbf2f9"
dependencies = [ dependencies = [
"unicode-ident", "unicode-ident",
] ]
@ -945,9 +945,9 @@ dependencies = [
[[package]] [[package]]
name = "rustls" name = "rustls"
version = "0.23.14" version = "0.23.15"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "415d9944693cb90382053259f89fbb077ea730ad7273047ec63b19bc9b160ba8" checksum = "5fbb44d7acc4e873d613422379f69f237a1b141928c02f6bc6ccfddddc2d7993"
dependencies = [ dependencies = [
"once_cell", "once_cell",
"ring", "ring",
@ -968,9 +968,9 @@ dependencies = [
[[package]] [[package]]
name = "rustls-pki-types" name = "rustls-pki-types"
version = "1.9.0" version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0e696e35370c65c9c541198af4543ccd580cf17fc25d8e05c5a242b202488c55" checksum = "16f1201b3c9a7ee8039bcadc17b7e605e2945b27eee7631788c1bd2b0643674b"
[[package]] [[package]]
name = "rustls-webpki" name = "rustls-webpki"
@ -1035,9 +1035,9 @@ dependencies = [
[[package]] [[package]]
name = "serde_json" name = "serde_json"
version = "1.0.128" version = "1.0.131"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" checksum = "67d42a0bd4ac281beff598909bb56a86acaf979b84483e1c79c10dcaf98f8cf3"
dependencies = [ dependencies = [
"itoa", "itoa",
"memchr", "memchr",

View file

@ -31,15 +31,6 @@ unsafe fn memcpy(mut dest: *mut u8, mut src: *const u8, mut count: usize) {
return; return;
} }
// let dest_misalignment = dest as usize & 7;
// if dest_misalignment != 0 {
// let align_bytes = 8 - dest_misalignment;
// src.copy_to_nonoverlapping(dest, align_bytes);
// dest = dest.add(align_bytes);
// src = src.add(align_bytes);
// count -= align_bytes;
// }
while count >= 8 { while count >= 8 {
if (src as usize) & 7 == 0 && (dest as usize) & 7 == 0 { if (src as usize) & 7 == 0 && (dest as usize) & 7 == 0 {
*(dest as *mut u64) = *(src as *const u64); *(dest as *mut u64) = *(src as *const u64);

View file

@ -0,0 +1,33 @@
# Images
- General over image format
- Support formats:
- PNG
- Animation
# API
- Font Loader
- VGA fonts
- Colour operations:
- Alpha Composite
- Invert
- Surface Operations:
- FlipV
- FlipH
- Resize
- Wrap the colour operations
- Tile
- Gradient overlay
- Draw operations:
- Curve raster algorithm
- VGA font fast blit
- VGA font render
- Polygon
# Backend
- SVGA Driver
- Support whatever vulkan stuff able is cooking
# Bits and bobs on the table
- Funny 3D Renderer
- stn.memory.swap & kernel message
- Make memory.{copy, set} smart

View file

@ -1,5 +1,5 @@
.{Color, Surface} := @use("./lib.hb"); .{Color, Surface, new_surface} := @use("./lib.hb");
.{log} := @use("../../stn/src/lib.hb") .{log, memory} := @use("../../stn/src/lib.hb")
BitmapFileHeader := packed struct { BitmapFileHeader := packed struct {
img_type: u16, img_type: u16,
@ -63,4 +63,41 @@ surface_from_bmp := fn(bmp: ^u8): Surface {
} }
return .(@bitcast(bmp), @intcast(info_header.width), @intcast(info_header.height)) return .(@bitcast(bmp), @intcast(info_header.width), @intcast(info_header.height))
}
new_surface_from_bmp := fn(bmp: ^u8): Surface {
file_header := @as(^BitmapFileHeader, @bitcast(bmp))
if file_header.img_type != 0x4D42 {
log.error("failed to load bmp image: not a bmp image, idiot\0")
return @as(Surface, idk)
}
info_header := @as(^BitmapInfoHeader, @bitcast(bmp + @sizeof(BitmapFileHeader)))
bmp += file_header.offset
width := @as(int, @intcast(info_header.width))
height := @as(int, @intcast(info_header.height))
surface := new_surface(width, height)
top_start_idx := surface.buf
bottom_start_idx := surface.buf + width * (height - 1)
rows_to_copy := height
top_cursor := @as(^Color, @bitcast(bmp))
bottom_cursor := top_cursor + width * (height - 1)
loop if rows_to_copy <= 1 break else {
@inline(memory.copy, Color, top_cursor, bottom_start_idx, @bitcast(width))
@inline(memory.copy, Color, bottom_cursor, top_start_idx, @bitcast(width))
top_start_idx += surface.width
bottom_start_idx -= surface.width
top_cursor += width
bottom_cursor -= width
rows_to_copy -= 2
}
if rows_to_copy == 1 {
@inline(memory.copy, Color, top_cursor, top_start_idx, @bitcast(width))
}
return surface
} }

View file

@ -11,6 +11,8 @@ new_surface := mode.new_surface
surface_from_ptr := mode.surface_from_ptr surface_from_ptr := mode.surface_from_ptr
clone_surface := mode.clone_surface clone_surface := mode.clone_surface
free_surface := mode.free_surface free_surface := mode.free_surface
index := mode.index
indexptr := mode.indexptr
// Colours // Colours
Color := packed struct {b: u8, g: u8, r: u8, a: u8} Color := packed struct {b: u8, g: u8, r: u8, a: u8}

View file

@ -31,7 +31,7 @@ clone_surface := fn(surface: ^Surface): Surface {
} }
free_surface := fn(surface: ^Surface): void { free_surface := fn(surface: ^Surface): void {
// todo // todo: depends on stn.memory.free
return return
} }
@ -56,18 +56,22 @@ sync := fn(surface: Surface): void {
return @inline(memory.copy, Color, surface.buf, framebuffer, @bitcast(surface.width * surface.height)) return @inline(memory.copy, Color, surface.buf, framebuffer, @bitcast(surface.width * surface.height))
} }
screenidx := fn(surface: Surface, x: int, y: int): int { index := fn(surface: Surface, x: int, y: int): int {
return x + surface.width * y return x + surface.width * y
} }
indexptr := fn(surface: Surface, x: int, y: int): ^Color {
return surface.buf + @inline(index, surface, x, y)
}
put_pixel := fn(surface: Surface, pos: Vec2(int), color: Color): void { put_pixel := fn(surface: Surface, pos: Vec2(int), color: Color): void {
*(surface.buf + @inline(screenidx, surface, pos.x, pos.y)) = color *@inline(indexptr, surface, pos.x, pos.y) = color
return return
} }
put_filled_rect := fn(surface: Surface, pos: Vec2(int), tr: Vec2(int), color: Color): void { put_filled_rect := fn(surface: Surface, pos: Vec2(int), tr: Vec2(int), color: Color): void {
top_start_idx := surface.buf + @inline(screenidx, surface, pos.x, pos.y) top_start_idx := @inline(indexptr, surface, pos.x, pos.y)
bottom_start_idx := surface.buf + @inline(screenidx, surface, pos.x, pos.y + tr.y - 1) bottom_start_idx := @inline(indexptr, surface, pos.x, pos.y + tr.y - 1)
rows_to_fill := tr.y rows_to_fill := tr.y
loop if rows_to_fill <= 1 break else { loop if rows_to_fill <= 1 break else {
@ -87,19 +91,19 @@ put_filled_rect := fn(surface: Surface, pos: Vec2(int), tr: Vec2(int), color: Co
} }
put_rect := fn(surface: Surface, pos: Vec2(int), tr: Vec2(int), color: Color): void { put_rect := fn(surface: Surface, pos: Vec2(int), tr: Vec2(int), color: Color): void {
start_idx := @inline(screenidx, surface, pos.x, pos.y) start_idx := @inline(indexptr, surface, pos.x, pos.y)
end_idx := @inline(screenidx, surface, pos.x, pos.y + tr.y) end_idx := @inline(indexptr, surface, pos.x, pos.y + tr.y)
right_start_idx := @inline(screenidx, surface, pos.x + tr.x, pos.y) right_start_idx := @inline(indexptr, surface, pos.x + tr.x, pos.y)
loop if start_idx > end_idx break else { loop if start_idx > end_idx break else {
*(surface.buf + start_idx) = color; *start_idx = color;
*(surface.buf + right_start_idx) = color *right_start_idx = color
start_idx += surface.width start_idx += surface.width
right_start_idx += surface.width right_start_idx += surface.width
} }
@inline(memory.set, Color, &color, surface.buf + @inline(screenidx, surface, pos.x, pos.y), @bitcast(tr.x + 1)) @inline(memory.set, Color, &color, @inline(indexptr, surface, pos.x, pos.y), @bitcast(tr.x + 1))
@inline(memory.set, Color, &color, surface.buf + @inline(screenidx, surface, pos.x, pos.y + tr.y), @bitcast(tr.x + 1)) @inline(memory.set, Color, &color, @inline(indexptr, surface, pos.x, pos.y + tr.y), @bitcast(tr.x + 1))
return return
} }
@ -116,7 +120,7 @@ put_line_low := fn(surface: Surface, p0: Vec2(int), p1: Vec2(int), color: Color)
y := p0.y y := p0.y
x := p0.x x := p0.x
loop if x == p1.x break else { loop if x == p1.x break else {
*(surface.buf + @inline(screenidx, surface, x, y)) = color *@inline(indexptr, surface, x, y) = color
if D > 0 { if D > 0 {
y += yi y += yi
D += 2 * (dy - dx) D += 2 * (dy - dx)
@ -140,7 +144,7 @@ put_line_high := fn(surface: Surface, p0: Vec2(int), p1: Vec2(int), color: Color
x := p0.x x := p0.x
y := p0.y y := p0.y
loop if y == p1.y break else { loop if y == p1.y break else {
*(surface.buf + @inline(screenidx, surface, x, y)) = color *@inline(indexptr, surface, x, y) = color
if D > 0 { if D > 0 {
x += xi x += xi
D += 2 * (dx - dy) D += 2 * (dx - dy)
@ -169,16 +173,21 @@ put_line := fn(surface: Surface, p0: Vec2(int), p1: Vec2(int), color: Color): vo
return return
} }
put_surface := fn(surface: Surface, top: Surface, pos: Vec2(int)): void { put_surface := fn(surface: Surface, top: Surface, pos: Vec2(int), flip_v: bool): void {
top_start_idx := surface.buf + @inline(screenidx, surface, pos.x, pos.y) top_start_idx := @inline(indexptr, surface, pos.x, pos.y)
bottom_start_idx := surface.buf + @inline(screenidx, surface, pos.x, pos.y + top.height - 1) bottom_start_idx := @inline(indexptr, surface, pos.x, pos.y + top.height - 1)
rows_to_copy := top.height rows_to_copy := top.height
top_cursor := top.buf top_cursor := top.buf
bottom_cursor := top.buf + top.width * (top.height - 1) bottom_cursor := top.buf + top.width * (top.height - 1)
loop if rows_to_copy <= 1 break else { loop if rows_to_copy <= 1 break else {
@inline(memory.copy, Color, top_cursor, top_start_idx, @bitcast(top.width)) if flip_v {
@inline(memory.copy, Color, bottom_cursor, bottom_start_idx, @bitcast(top.width)) @inline(memory.copy, Color, top_cursor, bottom_start_idx, @bitcast(top.width))
@inline(memory.copy, Color, bottom_cursor, top_start_idx, @bitcast(top.width))
} else {
@inline(memory.copy, Color, top_cursor, top_start_idx, @bitcast(top.width))
@inline(memory.copy, Color, bottom_cursor, bottom_start_idx, @bitcast(top.width))
}
top_start_idx += surface.width top_start_idx += surface.width
bottom_start_idx -= surface.width bottom_start_idx -= surface.width
@ -208,7 +217,7 @@ put_trirect := fn(surface: Surface, pos: Vec2(int), size: Vec2(int), color0: Col
target := pos + size target := pos + size
loop if pos.x == target.x break else { loop if pos.x == target.x break else {
put_vline(surface, pos.x, pos.y, target.y, color0) @inline(put_vline, surface, pos.x, pos.y, target.y, color0)
@inline(put_vline, surface, pos.x, pos.y, start_y, color1) @inline(put_vline, surface, pos.x, pos.y, start_y, color1)
pos += step pos += step
} }
@ -226,7 +235,7 @@ put_vline := fn(surface: Surface, x: int, y0: int, y1: int, color: Color): void
y := y0 y := y0
loop if y == y1 break else { loop if y == y1 break else {
*(surface.buf + @inline(screenidx, surface, x, y)) = color *@inline(indexptr, surface, x, y) = color
y += 1 y += 1
} }
@ -240,12 +249,7 @@ put_hline := fn(surface: Surface, y: int, x0: int, x1: int, color: Color): void
x0 = x1 x0 = x1
x1 = tmp x1 = tmp
} }
x := x0 @inline(memory.set, Color, &color, @inline(indexptr, surface, x0, y), @bitcast(x1 - x0 - 1))
loop if x == x1 break else {
*(surface.buf + @inline(screenidx, surface, x, y)) = color
x += 1
}
return return
} }

View file

@ -10,7 +10,46 @@ max := fn($Expr: type, a: Expr, b: Expr): Expr {
c := a - b c := a - b
return a - (c & c >> @intcast(@sizeof(Expr) - 1)) return a - (c & c >> @intcast(@sizeof(Expr) - 1))
} }
signum := fn($Expr: type, x: Expr): int {
if x > @as(Expr, @intcast(0)) {
return 1
} else if x < @as(Expr, @intcast(0)) {
return -1
} else {
return 0
}
}
signincl := fn($Expr: type, x: Expr): int {
if x > @as(Expr, @intcast(0)) {
return 1
}
return -1
}
Vec2 := fn($Expr: type): type { Vec2 := fn($Expr: type): type {
return struct {x: Expr, y: Expr} return struct {x: Expr, y: Expr}
}
SIN_TABLE := [int].(0, 174, 348, 523, 697, 871, 1045, 1218, 1391, 1564, 1736, 1908, 2079, 2249, 2419, 2588, 2756, 2923, 3090, 3255, 3420, 3583, 3746, 3907, 4067, 4226, 4384, 4540, 4695, 4848, 5000, 5150, 5299, 5446, 5591, 5735, 5877, 6018, 6156, 6293, 6427, 6560, 6691, 6819, 6946, 7071, 7193, 7313, 7431, 7547, 7660, 7771, 7880, 7986, 8090, 8191, 8290, 8386, 8480, 8571, 8660, 8746, 8829, 8910, 8987, 9063, 9135, 9205, 9271, 9335, 9396, 9455, 9510, 9563, 9612, 9659, 9702, 9743, 9781, 9816, 9848, 9877, 9902, 9925, 9945, 9961, 9975, 9986, 9993, 9998, 10000)
sin_i := fn(theta_deg: int, amplitude: int): int {
theta := theta_deg % 360
if theta < 0 {
theta += 360
}
quadrant := theta / 90
theta = theta % 90
sign := 1 - ((quadrant & 2) >> 1) * 2
complement := quadrant & 1
index := theta * (1 - complement) + (90 - theta) * complement
sin_value := SIN_TABLE[index] * sign
return (sin_value * amplitude + 5000) / 10000
}
cos_i := fn(theta_deg: int, amplitude: int): int {
return @inline(sin_i, theta_deg + 90, amplitude)
} }

View file

@ -71,7 +71,7 @@ main := fn(): int {
// Apply the image to the screen // Apply the image to the screen
pos := Vec2(int).(x, 100) pos := Vec2(int).(x, 100)
render.put_surface(screen, window, pos) render.put_surface(screen, window, pos, false)
if window_count >= 1 { if window_count >= 1 {
x = 10 x = 10
break break

View file

@ -8,27 +8,27 @@ bmp_1 := @embed("./assets/able.bmp")
bmp_2 := @embed("./assets/mini.bmp") bmp_2 := @embed("./assets/mini.bmp")
example := fn(): void { example := fn(): void {
screen := render.init(true)
images := [render.Surface; 2].( images := [render.Surface; 2].(
render.image.surface_from_bmp(@bitcast(&bmp_1)), render.image.surface_from_bmp(@bitcast(&bmp_1)),
render.image.surface_from_bmp(@bitcast(&bmp_2)), render.image.surface_from_bmp(@bitcast(&bmp_2)),
) )
screen := render.init(true)
vel := Vec2(int).(1, 1) vel := Vec2(int).(1, 1)
pos := Vec2(int).(100, 100) pos := Vec2(int).(100, 100)
n := -1 n := 0
loop { loop {
image := images[n] image := images[n]
render.put_surface(screen, image, pos) render.put_surface(screen, image, pos, false)
render.sync(screen) render.sync(screen)
render.clear(screen, render.black) render.clear(screen, render.black)
if pos.x == 0 | pos.x == screen.width - image.width { if pos.x == 0 | pos.x == screen.width - image.width {
vel.x = -vel.x vel.x = -vel.x
n = -1 - n n = 1 - n
} }
if pos.y == 0 | pos.y == screen.height - image.height { if pos.y == 0 | pos.y == screen.height - image.height {
vel.y = -vel.y vel.y = -vel.y
n = -1 - n n = 1 - n
} }
pos += vel pos += vel

View file

@ -14,7 +14,10 @@ example := fn(): void {
side := image.width / 8 side := image.width / 8
vel_inner := Vec2(int).(1, 1) vel_inner := Vec2(int).(1, 1)
pos_inner := Vec2(int).((image.width - side) / 2, (image.height - side) / 2) pos_inner := Vec2(int).((image.width - side) / 2, (image.height - side) / 2)
color := random.range(render.Color, render.black, render.white) // workaround for compiler bug
color := render.Color.(0, 0, 0, 0)
color = random.range(render.Color, render.black, render.white)
target_color := color
loop { loop {
render.clear(screen, render.black) render.clear(screen, render.black)
// color += .(1, 1, 1, 1) // color += .(1, 1, 1, 1)
@ -22,17 +25,17 @@ example := fn(): void {
render.put_rect(image, pos_inner, .(side, side), render.black) render.put_rect(image, pos_inner, .(side, side), render.black)
render.put_rect(image, .(0, 0), .(image.width - 1, image.height - 1), color) render.put_rect(image, .(0, 0), .(image.width - 1, image.height - 1), color)
render.put_surface(screen, image, pos) render.put_surface(screen, image, pos, false)
render.put_rect(image, pos_inner, .(side, side), color) render.put_rect(image, pos_inner, .(side, side), color)
render.sync(screen) render.sync(screen)
if pos_inner.x == 0 | pos_inner.x == image.width - side { if pos_inner.x == 0 | pos_inner.x == image.width - side {
vel_inner.x = -vel_inner.x vel_inner.x = -vel_inner.x
color = random.range(render.Color, render.black, render.white) target_color = random.range(render.Color, render.black, render.white)
} }
if pos_inner.y == 0 | pos_inner.y == image.height - side { if pos_inner.y == 0 | pos_inner.y == image.height - side {
vel_inner.y = -vel_inner.y vel_inner.y = -vel_inner.y
color = random.range(render.Color, render.black, render.white) target_color = random.range(render.Color, render.black, render.white)
} }
if pos.x == 0 | pos.x == screen.width - image.width { if pos.x == 0 | pos.x == screen.width - image.width {
@ -42,6 +45,12 @@ example := fn(): void {
vel.y = -vel.y vel.y = -vel.y
} }
color += .(
@intcast(color.b < target_color.b) - @intcast(color.b > target_color.b),
@intcast(color.g < target_color.g) - @intcast(color.g > target_color.g),
@intcast(color.r < target_color.r) - @intcast(color.r > target_color.r),
0,
)
pos += vel pos += vel
pos_inner += vel_inner pos_inner += vel_inner
} }