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.

2


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


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.


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?


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.


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

@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.


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


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

Really nice for 162 tokens!!


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!


How many tokens are still left?

@merwok: Thanks!


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


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={}}

:)
)


Well done! Thanks for sharing :)


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?


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


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?


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

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.


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!



[Please log in to post a comment]