Log In  

I wanted to achieve this effect with fill patterns for a recent project I started so I figured I'd share it here incase anyone else is interested in using it.

The local fill pattern function is shifting each row/column in the fill pattern by given x and y amount. It's using binary arithmetics and a cache of shift masks.

Here's the original code for version 1.0, takes 126 tokens:

--turns a screen-space fill pattern, into an object-space fill pattern by wrapping the patterns row and column by the given x and y amount.
function get_local_fill_pattern(x,y,fill_pattern)
    local add_bits=band(fill_pattern,0x0000.FFFF)
    fill_pattern=band(fill_pattern,0xFFFF)
    y=flr(y)%4
    if(y~=0)then
        local r_masks={0xFFF0,0xFF00,0xF000}
        local l_masks={0x000F,0x00FF,0x0FFF}
        fill_pattern=bxor(lshr(band(fill_pattern,r_masks[y]),y*4),shl(band(fill_pattern,l_masks[y]),(4-y)*4))
    end

    x=flr(x)%4
    if(x~=0)then
        local r_masks={0xEEEE,0xCCCC,0x8888}
        local l_masks={0x1111,0x3333,0x7777}
        fill_pattern=bxor(lshr(band(fill_pattern,r_masks[x]),x),shl(band(fill_pattern,l_masks[x]),4-x))
    end

    return bxor(fill_pattern,add_bits)
end

EDIT:
With great contributions and improvements by Felice here's a both faster, smaller and more API consistent version 2.0, takes 87 tokens:

_fillp_xmask_lo={[0]=0xffff,0x7777,0x3333,0x1111}
_fillp_xmask_hi={[0]=0x0000,0x8888,0xcccc,0xeeee}
_fillp_original=fillp

function fillp(p,x,y)
    if y then
        x=band(x,3)
        local p16=flr(p)
        local p32=rotr(p16+lshr(p16,16),band(y,3)*4+x)
        p+=flr(band(p32,_fillp_xmask_lo[x])+band(rotl(p32,4),_fillp_xmask_hi[x]))-p16
    end
    return _fillp_original(p)
end

Hope you find it useful!

Cart #48163 | 2018-01-14 | Code ▽ | Embed ▽ | License: CC4-BY-NC-SA
25

P#47695 2017-12-27 11:57 ( Edited 2018-01-14 11:23)

Excellent work. I've been wondering about how to implement this idea since fillp was released.

P#47697 2017-12-27 12:42 ( Edited 2017-12-27 17:42)
1

Good idea!

I refined your methods and took a fair chunk of the math and tokens off (now 80 tokens). Here's my version:

_fillp_xmask_lo={[0]=0xffff,0x7777,0x3333,0x1111}
_fillp_xmask_hi={[0]=0x0000,0x8888,0xcccc,0xeeee}

function fillp_local(x,y,p)
    x=band(x,3)
    local p16=flr(p)
    local p32=rotr(p16+lshr(p16,16),band(y,3)*4+x)
    return fillp(p-p16+flr(band(p32,_fillp_xmask_lo[x])+band(rotl(p32,4),_fillp_xmask_hi[x])))
end

And a demo thereof:

Cart #47737 | 2017-12-29 | Code ▽ | Embed ▽ | License: CC4-BY-NC-SA
1

P#47706 2017-12-27 17:18 ( Edited 2017-12-29 09:06)

Thanks Felice,
this is a very nice addition. Would you mind if I edit the original post with an update of your refined version?

Edit: I just noticed however, that your version doesn't respect the additional (floating point?) bits you can provide to a pattern to specify ignoring the second color from drawing. For instance, this pattern would not draw as intended:

local pattern=0b1110100110011010.1
fillp_local(x,y,pattern)

Once that is fixed I'll update the OP with your improvements, given you're alright with that.

Regards.

P#47728 2017-12-28 09:30 ( Edited 2017-12-28 17:27)

Do as you like with the code, I marked it creative commons for that reason. :)

It should be retaining the fractional transparency bit. I don't remember testing that so I may have failed to do it right. That's what the p-p16 is where I send the value on to fillp--the original pattern minus the integer bits, leaving the fractional bits, which are added to the resulting shifted pattern.

P#47734 2017-12-29 02:23 ( Edited 2020-03-11 03:57)

Oh, okay, I see what I did.

When I was rearranging code, I accidentally moved that p-p16 inside of the flr(), effectively deleting it.

Easy fix. See my original post for an updated version and a demo that <gasp> actually tests the transparency support. ;)

P#47738 2017-12-29 04:07 ( Edited 2020-03-11 03:57)
1

Actually...

One option would be to write a flat-out replacement for fillp() that takes optional x,y args after the pattern and shifts the pattern if so. That would add to the API pretty seamlessly, while not adding complexity and still keeping backwards compatibility.

Something like this:

_fillp_xmask_lo={[0]=0xffff,0x7777,0x3333,0x1111}
_fillp_xmask_hi={[0]=0x0000,0x8888,0xcccc,0xeeee}
_fillp_original=fillp

function fillp(p,x,y)
    if y then
        x=band(x,3)
        local p16=flr(p)
        local p32=rotr(p16+lshr(p16,16),band(y,3)*4+x)
        p+=flr(band(p32,_fillp_xmask_lo[x])+band(rotl(p32,4),_fillp_xmask_hi[x]))-p16
    end
    return _fillp_original(p)
end

It costs 7 more tokens, but it just feels more natural, and in keeping with the rest of the API, to extend an existing function. Other calls like map() and sspr() do similar things.

Obligatory demo:

Cart #47739 | 2017-12-29 | Code ▽ | Embed ▽ | License: CC4-BY-NC-SA
1

P#47740 2017-12-29 04:56 ( Edited 2020-03-11 03:57)
1

Felice, this is a way better approach so I'll update the original post with your improvements. Thanks and great work!

P#48162 2018-01-14 05:28 ( Edited 2018-01-14 11:04)

Ah, nice. I like my demo for having my name in it, but yours definitely demonstrates the functionality better. ;)

P#48167 2018-01-14 06:23 ( Edited 2018-01-14 11:23)

67 tokens with more arithmetic, no tables, and an otherwise pointless local x (not counting tokens for backward compatibility defaults)

local _fillp = fillp
local function fillp(p, x, y)
    p, x, y = p or 0, x or 0, y or 0 -- to maintain drop-in replacement compatibility with fillp(p)
    local p16, x = flr(p), band(x, 3)
    local f, p32 = flr(15 / 2 ^ x) * 0x1111, rotr(p16 + lshr(p16, 16), band(y, 3) * 4 + x)
    return _fillp(p - p16 + flr(band(p32, f) + band(rotl(p32, 4), 0xffff - f)))
end

and thanks to Felice's response on Discord, here it is with shl instead of ^, faster but two more tokens

local _fillp = fillp
local function fillp(p, x, y)
    p, x, y = p or 0, x or 0, y or 0 -- to maintain drop-in replacement compatibility with fillp(p)
    local p16, x = flr(p), band(x, 3)
    local f, p32 = flr(15 / shl(1,x)) * 0x1111, rotr(p16 + lshr(p16, 16), band(y, 3) * 4 + x)
    return _fillp(p - p16 + flr(band(p32, f) + band(rotl(p32, 4), 0xffff - f)))
end
P#72847 2020-02-06 23:37 ( Edited 2020-02-06 23:46)

Felice, I am curious why your natural extension above shifts neither x nor y when y is not present? If we want a seamless extension shouldn't it still shift x?

P#72848 2020-02-06 23:42

I was just economizing. I figured anyone wanting to shift the pattern would probably provide both parameters and that a single parameter would generally be an accident.

It's entirely reasonable to want to work with just x though. I just didn't do it. Arbitrary.

P#72849 2020-02-06 23:59

@sparr

I happened to come back and look at this. Isn't this:

flr(15 / shl(1,x)) * 0x1111

Just this?

flr(shr(15,x)) * 0x1111
P#73405 2020-02-24 09:13

I think you're right

P#73408 2020-02-24 09:53 ( Edited 2020-02-24 09:59)

I find it pretty neat you guys are still working this! :D

P#74423 2020-04-02 14:16
1

I have been banging my head all morning trying to do this and then I found this! thanks a lot

P#86599 2021-01-20 02:13

@Felice is a god when it comes to math/low-level. Let me know if you guys want me to update OP with any new/better version.

P#89125 2021-03-17 20:10

bumping a very old thread here, since I am using this function in a project I am working on. Thanks so much to the collaboration here!

@sparr and @Felice - I have a fundamentals question. Why are you using declaring "fillp" and "_fillp" as "local" above, if they are getting dropped into the global namespace?

P#136901 2023-11-04 12:02
1

I don't know why fillp is declared as local in the versions above, but to avoid adding _fillp to the global namespace, you can use a do/end block, like so:

do
 local _fillp = fillp
 function fillp(p, x, y)
  p, x, y = p or 0, x or 0, y or 0 -- to maintain drop-in replacement compatibility with fillp(p)
  local p16, x = flr(p), band(x, 3)
  local f, p32 = flr(15 / shl(1,x)) * 0x1111, rotr(p16 + lshr(p16, 16), band(y, 3) * 4 + x)
  return _fillp(p - p16 + flr(band(p32, f) + band(rotl(p32, 4), 0xffff - f)))
 end
end
P#136907 2023-11-04 14:40

Not a programmer but I'm glad you shared this, I'm sure I'll make use if it if I ever were to dip my toes into making pico8 programs.

P#136910 2023-11-04 16:14

[Please log in to post a comment]

Follow Lexaloffle:          
Generated 2024-03-28 16:57:28 | 0.051s | Q:46