Log In  


So I'm currently working on a semi randomly generated horizontal racing game. It's entirely horizontal, but the game will feature tracks that are a lot more elaborate with horizontal branching paths that are semi randomly generated in a spelunky style, made of 16x12 segments that are preset but with spikes and obstacles set in code. I'm having trouble figuring out how to fit all of the segments I want though, while still having the entirety of the map to work with, and possibly all of my sprite sheet. Does anyone have any advice on what I can do?



1

eermmm... you could try to store them in other ways like making a maptile represent a 2x2 or storing the maps in string(s) and then parsing it? IDK I'm not a pro or anything but use could use other storage like strings or memRAM.


1

@SmellyFishstiks Thanks, I was definitely thinking of storing it in strings but I've been unable to find enough information on how to compress and decompress the data.


1

I mean you can use Sub(),Tonum(),tostr(), and split()
(probably some more I don't know about.)
to munip strings if you need to.

Split() isn't on the pico-8 wiki (or at least the one I saw) but it looks for a "char(s?)" you put in the first slot (I think) and the 2nd slot is for the string and it returns a table of all of the stuff in the string but each index of the table is where the "char" you put it "splits" it.
Not sure if you even needed to know that but I thought it was important to show since there's little to no documentation on it.

(Although it's probably in the user instruction maneual.)

(and also now reading what you said maybe this wasn't your problem but eh, hope I could help somehow)


@SmellyFishstiks Yeah I've used some of those before and they probably could help, but what could I do to actually compress each segment into a string? That seems like the hardest part. It'd need to be an easy way that isn't time consuming to type out.


I mean you could write a tool and then printh() it I guess, it’s not the same thing but when I wrote the wave data for my game squid defense I wrote out the wave data in a comment block and then when I wanted to test it I would copy it and then erase the enters between the waves and then put it in the string, storing data in strings is tricky because if your a dumbo like me and use pico-8s editor to code it goes off the screen.. IDK.
For other stuff I’m working on I made external tools to help, like I made a map editor for my Löve game because I didn’t want to type it out :p
Not really exactly the same but making external tools can help out sometimes.

Although when it comes to data compression help I don’t really have experience with making things smaller... so idk


Here's something to consider: Pico-8 actively tries to compress everything you type into the code. This means that attempts to compress the data will have less effect than they might seem or even make the result larger. If that's not a problem or if your problem is the maximum length before compression, Run-Length Encoding (or RLE for short) is the first thing that comes to mind for a beginner (which I am in that topic as well). Basically, you alternate between a piece of data and the number of times that data is repeated. For example, in my game, "Basement", I used 2 character pairs in hexidecimal for character portraits, 1 for a color and 1 for the number pixels of that color. I didn't use it for map data though, cause when I tried making a tool to compress the maps it kept having bugs I could track down. I just dumped the maps as is instead.

For the actual storage of maps in a string, making a cartridge that dumps the map onto the clipboard would work. If you make a new cartridge and then copy the gfx and gff data over to it in a text editor, you can then use the map editor with the same sprites already there. From there, printh() can be used. Here's the actual code I used as an example:

function num_convert(n)
  if n>127 then
    r=chr(125)..chr(n)
  else
    r=chr(n+127)
  end
  return r
end

function _init()
  s=""
  for y=0,31 do
    for x=0,127 do
      c=mget(x,y)
      s=s..num_convert(c)
    end
  end
  printh(s,"@clip",true,false)
end

The ".." adds a string onto the end of another string. chr() translates a number into a character. This code also keeps the results above 127, because there's no unreadable characters (like new lines) in that range. It also uses the character at 125 (which points to a sprite I didn't use in maps) as an indication that the next character is above 128 already. If you're only using the first 127 sprites, though, this is overkill. In that case you can just add 127 to the result of mget(). The ranges for x and y were because I was dumping the entire map data.

After running the code, you would then be able to paste the result into either a text editor to verify that it worked or straight into your actual game cartridge.

The corresponding code to decode the string onto the map memory is this:

function load_map(m)
  local i=1
  local c=0
  local tc=0
  for y=0,31 do
    for x=0,127 do
      tc=ord(sub(m,i,i))
      if tc==125 then
        i+=1
        c=ord(sub(m,i,i))
        mset(x,y,c)
      else
        mset(x,y,tc-127)
      end
      i+=1
    end
  end

However, if you want it in a table or something like that to keep the map memory free for other things, mset would need to be replaced with your preferred way of story the data in a table. ord() translates characters into corresponding numbers, in case that isn't clear.


I've also made a little map compressor/decompressor like this, but it uses run length encoding as well for smaller string size. It allows you to use the first 160 sprites, and the decoding function takes just 38 tokens. For a few tokens more it could be made to work with the first 220 sprites, though, if you need that.

--encoder

 h=32 --# of rows of map to encode
 t={}
 i,p=1,8192
 len=1
 cls()
 while p<(8192+h*128) do
  local cbyte,nbyte=@p,@(p+1)
  if(nbyte==cbyte) len+=1
  if nbyte!=cbyte or len==159 then
   t[i]=cbyte
   t[i+1]=len
   len=1 i+=2
  end
  p+=1
 end
 new_s=""
 for i=1,#t do
  new_s=new_s..chr(t[i]+96)
 end
 printh(new_s,'@clip')
--decoder

function map_rle(str)
 local adr=8192
 for i=1,#str,2 do
  local l=ord(str,i+1)-96
  memset(adr,ord(str,i)-96,l) adr+=l
 end
end


[Please log in to post a comment]