prog8/examples/cx16/interpolation.p8

193 lines
5.3 KiB
Lua

%import math
%import textio
%import sprites
%import floats
; shows the use of the LERP (Linear intERPolation) routines that prog8 provides.
; math.lerp / math.lerpw / floats.lerp / floats.lerp_fast
; LERP explained here: https://en.wikipedia.org/wiki/Linear_interpolation
; Here are a lot of easing functions you can use:
; https://blog.febucci.com/2018/08/easing-functions/ (links at the bottom)
main {
uword mx, my
sub start() {
void cx16.set_screen_mode(3)
cx16.mouse_config2(1)
sprites.set_mousepointer_hand()
repeat {
txt.cls()
txt.print("\n\n floats.lerp()")
sys.wait(60)
repeat 2 lerp_float()
txt.cls()
txt.print("\n\n floats.lerp() with easing")
sys.wait(60)
repeat 2 lerp_float_easing()
txt.cls()
txt.print("\n\n integer math.lerp()")
sys.wait(60)
repeat 2 lerp_normal()
txt.cls()
txt.print("\n\n integer math.lerp() with easing")
sys.wait(60)
repeat 2 lerp_easing()
txt.cls()
txt.print("\n\n floats.interpolate()")
sys.wait(60)
repeat 2 interpolate_float()
txt.cls()
txt.print("\n\n integer math.interpolate()")
sys.wait(60)
repeat 2 interpolate_int()
}
}
sub interpolate_float() {
ubyte tt
for tt in 0 to 255 step 3 {
sys.waitvsync()
mx = floats.interpolate(tt as float, 0, 255, 50, 250) as uword
my = floats.interpolate(tt as float, 0, 255, 30, 150) as uword
cx16.mouse_set_pos(mx, my)
}
for tt in 255 downto 0 step -3 {
sys.waitvsync()
mx = floats.interpolate(tt as float, 0, 255, 50, 250) as uword
my = floats.interpolate(tt as float, 0, 255, 30, 150) as uword
cx16.mouse_set_pos(mx, my)
}
}
sub interpolate_int() {
ubyte tt
for tt in 50 to 250 step 3 {
sys.waitvsync()
mx = math.interpolate(tt, 50, 250, 50, 250)
my = math.interpolate(tt, 50, 250, 30, 150)
cx16.mouse_set_pos(mx, my)
}
for tt in 250 downto 50 step -3 {
sys.waitvsync()
mx = math.interpolate(tt, 50, 250, 50, 250)
my = math.interpolate(tt, 50, 250, 30, 150)
cx16.mouse_set_pos(mx, my)
}
}
sub lerp_float() {
ubyte tt
for tt in 0 to 255 step 3 {
sys.waitvsync()
mx = floats.lerp(50, 250, tt as float/256) as uword
my = floats.lerp(30, 150, tt as float/256) as uword
cx16.mouse_set_pos(mx, my)
}
for tt in 255 downto 0 step -3 {
sys.waitvsync()
mx = floats.lerp(50, 250, tt as float/256) as uword
my = floats.lerp(30, 150, tt as float/256) as uword
cx16.mouse_set_pos(mx, my)
}
}
sub lerp_float_easing() {
float e
ubyte tt
for tt in 0 to 255 step 2 {
sys.waitvsync()
e = ease(tt)
mx = floats.lerp(50, 250, e) as uword
my = floats.lerp(30, 150, e) as uword
cx16.mouse_set_pos(mx, my)
}
for tt in 255 downto 0 step -2 {
sys.waitvsync()
e = 1 - ease(255-tt)
mx = floats.lerp(50, 250, e) as uword
my = floats.lerp(30, 150, e) as uword
cx16.mouse_set_pos(mx, my)
}
sub ease(ubyte t) -> float {
; bounce
const float n1 = 7.5625
const float d1 = 2.75
float x = t as float/256
if (x < 1 / d1) {
return n1 * x * x;
} else if (x < 2 / d1) {
x = x - 1.5 / d1;
return n1 * x * x + 0.75;
} else if (x < 2.5 / d1) {
x = x - 2.25 / d1;
return n1 * x * x + 0.9375;
} else {
x = x - 2.625 / d1;
return n1 * x * x + 0.984375;
}
}
sub ease2(ubyte t) -> float {
; 'smootherstep'
float x = t as float/256
return x * x * x * (x * (x * 6 - 15) + 10)
}
}
sub lerp_normal() {
ubyte tt
for tt in 0 to 255 step 3 {
sys.waitvsync()
mx = math.lerp(50, 250, tt)
my = math.lerp(30, 150, tt)
cx16.mouse_set_pos(mx, my)
}
for tt in 255 downto 0 step -3 {
sys.waitvsync()
mx = math.lerp(50, 250, tt)
my = math.lerp(30, 150, tt)
cx16.mouse_set_pos(mx, my)
}
}
sub lerp_easing() {
ubyte e
ubyte tt
for tt in 0 to 255 step 3 {
sys.waitvsync()
e = ease(tt)
mx = math.lerp(50, 250, e)
my = math.lerp(30, 150, e)
cx16.mouse_set_pos(mx, my)
}
for tt in 255 downto 0 step -3 {
sys.waitvsync()
e = ease(tt)
mx = math.lerp(50, 250, e)
my = math.lerp(30, 150, e)
cx16.mouse_set_pos(mx, my)
}
sub ease(ubyte t) -> ubyte {
return msb(t as uword*t) ; 'squaring'
}
}
}