Log In  

Let's say I have an 8x8 sprite, like the one in my avatar. I want to manipulate that sprite as follows:

  1. Randomly position each non black sprite pixel outside the viewport.
  2. Move those pixels into the viewport to form the sprite.

I know how to do this with a whole sprite, but how might I achieve this effect with the individual sprite pixels? Obviously I'll need the following:

  1. Destination position of sprite within the viewport.
  2. The index position within the 8x8 grid of each pixel, offset from sprite destination position - e.g. x,y of sprite, then index of pixel within the sprite 8x8 grid.

Anyone have any ideas? I want this as a neat effect for spawning enemies at the start of each stage in a new game I an working on.

P#80560 2020-08-09 19:22

not clear about what you are trying to achieve.
did you look at sspr (eventually sset/sget)?

P#80564 2020-08-09 19:48

I want to set the positions of all non-black pixels (for 1 sprite) to random positions outside the viewport. I then want to move all the pixels into position (within the viewport) to form the sprite.

Think of it as the opposite of a particle explosion.

P#80565 2020-08-09 20:12 ( Edited 2020-08-09 20:20)
1

Use sget() to read the sprite data. Give each pixel a start and end position. Move the sprite pixels to their destination, by drawing them as individual pixels. Once all the pixels are at the destination, stop drawing the pixels and draw the whole sprite.

Does this make sense?

P#80567 2020-08-09 20:25

If using sget and all ends up being more tokens than you want to spend on an effect, you can always take it down a notch and just fling some similarly colored pixels into the approximate area of the sprite, maybe end with some flash or palette rotation before finally drawing the sprite proper.

P#80583 2020-08-10 06:22
1

Here's some code that will get the sprite data, and move it pixel-wise to a determined destination function.
Not really optimized, just to show how to do it. All you need to do to test it, is to draw something in spr1, and copy/paste the code.

-- reads sprite data, determines start pos and
-- delta values per pixel
--
-- sid - sprite number
-- _x - dest x of spr
-- _y - dest_y of spr
-- steps is the number of steps/frames to reach its destination
function compose_sprpixel(sid,_x,_y,steps)
 local t={}
 t.steps=steps
 t.data={}
 local x,y
 for y=0,7 do
    for x=0,7 do

        local quad=flr(rnd(4))
        local sx,sy,dx,dy
        if quad == 0 then
            sx=0-rnd(32)
            sy=flr(rnd(128))
        elseif quad == 1 then
            sx=flr(rnd(128))
            sy=0-rnd(32)
            elseif quad == 2 then
             sx=127+rnd(32)
             sy=flr(rnd(128))
            else
             sx=flr(rnd(128))
             sy=127+rnd(32)
            end
            local pd={}
            pd.col=sget( 
         (sid<<3)%128+x,
         (sid<<3)\8+y
         ) 
            pd.x=sx
            pd.y=sy
            pd.dx=((_x+x)-sx)/steps
            pd.dy=((_y+y)-sy)/steps
            add(t.data, pd)
        end
 end    
 return t
end

function _init()
    pixel=compose_sprpixel(1,63,63,30)
end

function _update()
    if pixel.steps > 0 then
        pixel.steps-=1
        local p
        for p in all(pixel.data) do
            p.x+=p.dx
            p.y+=p.dy
        end
    end
end

function _draw()
 cls()
 if pixel.steps > 0 then
        local p
        for p in all(pixel.data) do
            pset(p.x, p.y, p.col)
        end
    else
     spr(1,63,63)
    end
end
P#80587 2020-08-10 07:55

@tyroney That's a good idea, and one that I had already considered.

@spellcaster That's brilliant, and exactly what I was looking for. Unfortunately, I don't have enough free tokens left! There might be the possibility of further optimising to free-up some additional tokens, but it's my least favourite part of Pico-8 development and don't really think I want to spend significant time doing it! Besides that, I still have some other bugs to fix, and they might further reduce my available token count. That code is great though, and will definitely use it in a future game.

P#80589 2020-08-10 08:29

Like I said, it's not optimized. I could try to reduce the token count a bit, give me a minute or two

P#80590 2020-08-10 09:02
1

Ok, this is a bit more efficient:

function compose_sprpixel(sid,_x,_y,steps)

 local t,x,y={}
 t.steps,t.data=steps,{}

 for y=0,7 do
    for x=0,7 do
            local r,pd=rnd(),{}
            pd.col=sget((sid<<3)%128+x,sid\2+y) 
            pd.x,pd.y=sin(r)*200,cos(r)*200
            pd.dx,pd.dy=(_x+x-pd.x)/steps,(_y+y-pd.y)/steps
            add(t.data, pd)
  end
 end    
 return t
end

function _init()
    pixel=compose_sprpixel(1,63,63,30)
end

function _draw()
 cls()
 if pixel.steps > 0 then
        local p
        for p in all(pixel.data) do
            pset(p.x, p.y, p.col)
            p.x+=p.dx
            p.y+=p.dy           
        end
        pixel.steps-=1
    else
     spr(1,63,63)
    end
end
P#80591 2020-08-10 09:23 ( Edited 2020-08-10 18:33)

Really nice for 162 tokens!!

P#80600 2020-08-10 16:43

Yeah, that's awesome. Calls to sfx and music are already taking me over my token limit, but I will definitely be using this routine in my next game!

P#80602 2020-08-10 16:49

How many tokens are still left?

@merwok: Thanks!

P#80606 2020-08-10 18:28 ( Edited 2020-08-10 18:30)

About -10! I'm currently going through my code to optimise.

P#80608 2020-08-10 19:10
1

Fun mini project - my take on it, slightly more packaged:

-- teleport a 8x8 sprite
-- sx sy spritesheet source position
-- dx dy screen destination 
-----------
-- credits
-- idea:  @spellcaster
-- from: https://www.lexaloffle.com/bbs/?tid=39162
function make_teleport(sx,sy,dx,dy,steps)
    steps=steps or 20
    local data,t={},0
    for j=0,7 do
     for i=0,7 do
      local a=rnd()
      local x,y=128*cos(a),128*sin(a)
      add(data,{
        sget(sx+i,sy+j),
        x,
        y,
        (dx+i-x)/steps,
        (dy+j-y)/steps
      })
     end
    end

 return function()
  if(t>steps) sspr(sx,sy,8,8,dx,dy) return
    for _,p in pairs(data) do
        local c,x,y,dx,dy=unpack(p)         
        pset(x+t*dx,y+t*dy,c)
    end
    -- with a bit of acceleration
    t+=1.2 
 end
end

Demo cart (btn 4 to restart):

Cart #podeforumu-0 | 2020-08-10 | Code ▽ | Embed ▽ | No License
1

(and guys, you can create a table in one go like that:

t={steps=steps,data={}}

:)
)

P#80610 2020-08-10 19:57 ( Edited 2020-08-10 19:59)

Well done! Thanks for sharing :)

P#80616 2020-08-10 23:51

I've been playing around with this to get some neat little spawning/scaling effects:

One thing I wish it had though - the ability to specify a sprite number instead of its x,y co-ords in the sprite sheet. Or is there an easy way to get a sprite number via its x,y co-ords?

P#81503 2020-09-04 19:31

you reinvented sspr - a native pico8 function to scale pixels.
tbh I would prefer the pixel ‘teleport’ function (see above posts) for that effect.

P#81515 2020-09-05 05:36

That's the routine I'm using to get that effect. Is there an easy way to get it working using sprite number instead of spritesheet coords?

P#81518 2020-09-05 12:43 ( Edited 2020-09-05 12:44)

sspr is using sprite coords - you can get sprite coords from sprite index:

local sx,sy=band(s*8,127),8*flr(s/16)
-- post 0.2
local sx,sy=(s<<3)&127,(s\16)<<3
P#81526 2020-09-05 20:40 ( Edited 2020-09-06 07:25)

That's great, thanks. BTW, it's your routine I used for the scaling in the GIF. I wasn't expecting that effect when I was playing around with it. Being able to manipulate individual pixels opens up a lot of possibilities.

P#81544 2020-09-06 16:55 ( Edited 2020-09-06 16:56)

I would like to use the function but with a sprite that’s 1) bigger than 8x8 pixels 2) displayed at 2x size 3) stored as one half drawn using flip_x.

Solving 1 seems as easy as replacing 'for i=0,7' by 'i=0,width-1' (same for j)

For 2, I would need to adapt the destination coordinate calculation and change pset to rect. A nice effect would be to keep 1px at the start and wait a little before drawing 2px then 4px.

3 seems too complicated to solve, no? the solution would be to create the full sprite in the draw state, then copy to spritesheet and work from that, wouldn’t it?

Thanks for any advice!

P#82271 2020-09-25 17:43

[Please log in to post a comment]

Follow Lexaloffle:          
Generated 2024-03-28 17:36:31 | 0.042s | Q:41