Log In  
Log In  

@ChristopherD

Follow
Follow

iOS developer/graphic artist living and working in Tokyo.
New to Pico-8, but loving the freedom that comes from its restrictions.
Haven't been this fired up about coding for quite a while O_O;

Purpose: calculating a line-line intersection point

I've been trying to learn physics coding, which also means re-learning math I have long forgotten. Recent studies in vectors, sin/cos, etc. were difficult but successful, so this task seemed like it would be pretty simple. And yet....

I cannot see what I'm doing wrong here.

I've implemented line-line intersection algorithms as transcribed in various places all over the internet, and the resulting {x,y} is always the same. So the answers are consistent, but do not match expectations whatsoever.

Note: I understand this algorithm does not catch all cases, but rather I'm trying to show the simplest form of the problem I'm struggling with. It should be working for the case illustrated, as far as I understand. The line endpoints are chosen specifically to intersect on-screen, but the intersection algorithm will generate negative values in most, but not all, cases (?!?!?)

function line_intersection(line1, line2)
    local p1, p2 = line1.p1, line1.p2
    local p3, p4 = line2.p1, line2.p2

    local a1 = p2.y - p1.y
    local b1 = p1.x - p2.x
    local c1 = a1 * p1.x + b1 * p1.y

    local a2 = p4.y - p3.y
    local b2 = p3.x - p4.x
    local c2 = a2 * p3.x + b2 * p3.y

    local denominator = a1 * b2 - a2 * b1
    local x = (b2*c1-b1*c2)/denominator 
    local y = (a1*c2-a2*c1)/denominator 
    print(x..","..y,0,120)
    return {x=x,y=y}
end

--l1 = {p1={x=10, y=25}, p2={x=25, y=10}} --THIS WORKS
l1 = {p1={x=10, y=26}, p2={x=26, y=10}} --THIS DOESN'T
l2 = {p1={x=0, y=0}, p2={x=60, y=60}}

function _draw()
    cls()
    line(l1.p1.x, l1.p1.y, l1.p2.x, l1.p2.y, 7)
    line(l2.p1.x, l2.p1.y, l2.p2.x, l2.p2.y, 7)
    local intersect = line_intersection(l1, l2)
    circ(intersect.x, intersect.y, 2, 8)
end

Is there a trick to doing this in Pico-8 that I'm not understanding? Other attempts to translate algorithms (say from Wikipedia or Stack Overflow) were successful, so I thought I had a handle on things. It's frustrating being stumped by something that seems so simple. If anyone can point me in the right direction, I'd appreciate the assist.

P#60617 2019-01-06 07:48

Here I present a method for stroking text and sprites.

In looking through solutions for stroked/filled text, I usually see print()on the string called 9 times; i.e. once at each cardinal location with a 1px offset. I realized if pixels were represented by "fat pixels" outlines of various thicknesses could be simulated.

For example, if a pixel is at (x,y),

rectfill(x-thickness, y-thickness, x+thickness, y+thickness,color)

with a normal pixel draw on top would look like an outlined pixel. I further realized that anything with transparent pixels could be outlined in this same manner, and so applied it to sprites.

This method works in the following:

  1. Video space is "borrowed" for less than a frame (?) to render the text and capture it's pixel data to user data space. (the specific address space used for this caching can be set to wherever you like; sprites are read as-is from sprite memory space)
  2. The bytes are walked and used to draw fat pixels (via rectfill()).
  3. The string is then rendered "as normal" at the location requested. (print()is only called twice: once to grab the pixel data cache, once to draw the string on top of the effects)
  4. Seems to be at 300 tokens currently.

This method has the following benefits:

  1. Visual effects are defined as a table (list) of inner tables, where each inner table defines:
{fill_color, stroke_color, line_thickness, effect_x_offset, effect_y_offset}
  1. Effects in a list are applied in the "painter method" from [1]..[#effect] where each subsequent effect is drawn on top of the previous. This allows for complex stackings of routines.
  2. Effects are just tables, and so can be pre-defined and re-used on other elements, including sprites.
  3. Effects are animatable, by simply swapping colors and offset values.
  4. Uses no sprites, only Pico-8 native text (though it could be pretty easily adapted to work with mini-font libraries that use custom sprites, I think)

Optimization possibilities
Unlike the "draw a string 9 times" methods, this methodology presents an opportunity for optimization. I'm still very new to Pico-8 and Lua, so this really only represents a starting point toward a better algorithm.

For example, I'm sure there are ways to make it more efficient.

  1. I believe the call to peek() could be switched to a peek4()?
  2. I believe the call to rectfill() could be swapped for direct writes to the bytes?
  3. I'm certain there are ways to reduce the token count from the current 300, but for the purpose of this post I tried to consolidate redundant code without sacrificing (too much) legibility.

(P.S. - I don't see how a name can be attached to a cart? @clip didn't use the file name? I see no tools here for setting title, license, etc.)

Cart [#56189#] | Code | 2018-09-04 | No License | Embed
3

P#56191 2018-09-04 20:03 ( Edited 2018-09-05 11:04)

I've been studying Pico-8 only for about a week now and really having a good time. I enjoy thinking within it's constraints. In particular I like fiddling around with the graphics memory directly to do fun video effects.

With the following code snippet I can move every other video line offscreen to the left or right, giving an interesting "tearing apart" video effect. This works great and is very fast, and gets me to a blank screen where "blank" just means the screen is filled with a chosen "clear color."

if (y%2==0) then
   memcpy(dst,src,63)
   memset(src,clear,1)
else
   memcpy(src,dst,63)
   memset(src+63,clear,1)
  end

So, now that the screen is clear, I want to do the opposite. Bring in a full screen image (perhaps a map or scaled sprite) onto screen in the reverse. i.e. Odd-lumbered video lines scroll in from the left and even-lumbered lines scroll in from the right.

This would assume that some pre-composed block of memory is waiting from which i do a similar memcpy() from off-screen to on-screen... or at least that is conceptually what i think needs to happen. But i do not understand the possibilities of Pico-8 deeply enough to understand how/where to keep such an offscreen buffer, or if that is even possible.

Any pointers on how to tackle this?

P#55535 2018-08-23 05:48 ( Edited 2018-08-24 08:30)

About | Contact | Updates | Terms of Use
Follow Lexaloffle:        
Generated 2019-04-19 18:26 | 0.092s | 4194k | Q:23