See repro cart - unless I am totally wrong on my software tline, pico8 tline ("hw tline") is not correctly rendering lines with arbitrary slopes.

Software version eventually converge toward correct pattern, tline does not.

Hi @freds72

This might be a bug in documentation rather than runtime. The problem is that tline increments both map_x, map_y every pixel regardless of the primary axis. Perhaps the easiest way to explain is with another reference implementation:

function tline3(x0,y0,x1,y1,mx,my,mdx,mdy) local dx,dy=0,0 x0=x0\1+.5 y0=y0\1+.5 x1=x1\1+.5 y1=y1\1+.5 -- 3 pixel line has 2 steps local steps=max(abs(x1-x0),abs(y1-y0)) if (steps > 0) then dx=(x1-x0)/steps dy=(y1-y0)/steps end while steps>=0 do pset(x0,y0,msget(mx,my)) x0+=dx y0+=dy mx+=mdx my+=mdy steps-=1 end end |

The difference in behaviour in tline2 is caused by incrementing u or v (whichever is not the primary axis) only when error is exceeded. Moving "u+=du" outside of the "if error>=0 then" block would give the same behaviour as tline3.

So, to match a tline 1:1 with the pixels on the spritesheet along an arbitrary line, the number of steps are needed. By "steps", I mean "number_of_pixels_to_draw - 1" (disregarding clipping):

local steps = max(dx,dy) tline( p0.x,p0.y,p1.x,p1.y, p0.u,p0.v, (p1.u-p0.u)/steps, (p1.v-p0.v)/steps) |

I hope that makes sense! I'll try to make this clearer in the next update of the manual.

@zep

Just to be clear:

You're saying that it's intended that these all result in the same *final* (accumulated) UV at the end of the line?

tline( 0,0,100, 0, u0,v0, du,dv ) tline( 0,0,100,100, u0,v0, du,dv ) -- even though this line is technically longer tline( 0,0, 0,100, u0,v0, du,dv ) |

Total side note:

You should stop encouraging people (by example from The Creator) to use **\1** as a **flr()** substitute. Using **&-1** is way, way more efficient on both the virtual cpu and the host cpu.

Most of the borderline embedded systems you'd like PICO-8 to run on for handheld mode are going to have *very* slow divide operations, because making a fast(er) divide is a silicon nightmare from what I understand.

If **\1** is commonly used in tight loops, it's going to drag perf wayyyyy down on handhelds. A divide can easily be 30-70x slower than simple stuff like an **&-1** bitwise op.

If nothing else, you should bodge the parser so it recognizes a floored-divide operator with a RHS of a literal '1' and just replace it behind the scenes with an **&-1**, because even if *you* stop doing it, others will probably propagate the bad version anyway. :P

[Please log in to post a comment]