Log In  


Is there a nice way to draw a map flipped? In my case, I want to flip it horizontally but in general I guess flipping it vert/horz would be handy.

spr() has the flip flags, map() does not...is there some magic-ish way to do that?

I'm using 16x16 maps for backgrounds on my vertical shmup and want to mirror some when rendered so I don't have to use up more map space to get the same effect.

3


1
function map_mirror(tx,ty)
 cls(0)
 --draw left half
 map(tx,ty,0,0,8,16)
 -- set screen as sprite source
 poke(0x5f54,0x60)
 -- copy left half of screen flipped to the right half
 spr(0,64,0,8,16,true)
 -- set spritesheet back to normal
 poke(0x5f54,0x00)
end

This is about as fast as map.

function map_with_flip(tx,ty,sx,sy,tw,th,flip_x,flip_y)
 local y,mx,my,mdx,mdy
 y=sy
 mx=flip_x and (tx+tw-1/8) or tx
 my=flip_y and (ty+th-1/8) or ty
 mdx=flip_x and -1/8 or 1/8
 mdy=flip_y and -1/8 or 1/8
 while y<sy+th*8 do
  tline(sx,y,sx+tw*8-1,y,mx,my,mdx,0)
  my+=mdy
  y+=1
 end 
end

This is significantly slower than map but offers a lot of freedom.


Awesome, thanks for funcs, I'll give them a try and see how it goes.

I guess the downside to the mirror is that it's not really a flip per se. Since it has to use the regular map() call it doesn't seem like it can do a full 16x16 horz flip.

But it's really cool seeing how to capture the current screen into a sprite with the poke()...my mind doesn't go to memory functions when trying to solve problems.


You can't directly make a full flip of the screen :
if you try spr(0,0,0,16,16,true) while the sprite sheet and the screen are at the same address, the result is a mess because spr is reading part of its data while it has already been changed.
You could do it with intermediate steps :
-map the top half the screen
-spr the mirror into the bottom half
-memcopy the bottom half to high memory
map the bottom half

  • mirror the bottom half to top half with spr
  • memcopy the saved flipped bottom to bottom screen.
    With a big caveat that pokes are affected by the content of 0x5f54.
    Time should be around 3 times map() for a vertical flip.
    For a horizontal flip, because the left or right half screen is not a contiguous memory segment, you'd need a loop to save the screen, so probably in the same time range as the more versatile map_with_flip.
    Another approach could be to do it by progressively smaller slices of the screen

Makes sense...my whole motivation for even asking came as a sudden thing, I invented the problem, lol. I'm hopeful the flipper will work...I know it works...but that I can make it work with all the code I already have. I'll probably have to cut/refactor things so account for this addition but gonna see if it's worth the cost. As happens often, one of things I wish I had thought about before getting this far :)


Did a few more tests, and it turns out I misunderstood what happens when source and destination overlap : there's no mess at all, the source is fully copied somewhere first, then fully applied to the destination. The reason for the messes was just transparency, so the non flipped map was showing through the black parts of the flipped map.

function map_flip(tx,ty,flip_x,flip_y)
 --disable transparency
 palt(0)
 --draw map
 map(tx,ty,0,0,16,16)
 -- set screen as sprite source
 poke(0x5f54,0x60)
 -- flip map
 spr(0,0,0,16,16,flip_x,flip_y)
 -- set spritesheet back to normal
 poke(0x5f54,0x00)
end

CPU cost is around twice the cost of map (screen fully drawn twice)
You may want to avoid sprite 0 in the map, also, or add a cls(0) at start of the function (extra CPU cost).


function code

function pickmapcommand(cx,cy)
	local mx,my=cx\8,cy\8
	_mapcommand=_mapcommand or {}
	poke(0x5f54,0x60)
	for x=-1,17 do
		_mapcommand[x+mx]=_mapcommand[x+mx] or {}
		for y=-16,32 do
			if mget(x+mx,y+my)==255 then
				local mpy=mget(x+mx,y+my-1)
				local mph=mget(x+mx,y+my-2)
				_mapcommand[x+mx][y+my]={mpy,mph}
				mset(x+mx,y+my,0)
				mset(x+mx,y+my-1,0)
				mset(x+mx,y+my-2,0)
			end
			if _mapcommand[x+mx][y+my] then
				local mpy,mph=unpack(_mapcommand[x+mx][y+my])
				sspr((x+mx)*8-cx,(y+my+mpy)*8-cy,8,mph*8,(x+mx)*8,(y+my)*8,8,mph*8,false,true)
			end
		end
	end
	poke(0x5f54,0)
end


This is the side-scrolling version, where a special command is embedded in the MAP. The sprite for the command is set to 255.
When pickmapcommand() detects sprite 255 in the MAP visible to the camera, it retrieves the two sprites above it, receives the "downward Y coordinate" and "height" of the reference MAP for inversion, and stores these in a table. Once detected, it is set to 0 so that it will not be detected again.

The table stores commands for each coordinate, and inverted drawing is performed as necessary.

Example command:

[8x24]

3   -- Height\8
6   -- Y\8 cordinate
255 -- map flip command

Cart #mapflip_command_vertical-1 | 2025-04-25 | Code ▽ | Embed ▽ | No License



[Please log in to post a comment]