Log In  

I recently wrote the following routine to scale text:

--scales some text, used for title
function scale_text(text,tlx,tly,sx,sy,col)

 print(text,0,0,col)
    for y=0,7 do
     for x=0,#text*8-1 do
      local col=pget(x,y)
      if col!=0 then
      local nx=x*sx+tlx
      local ny=y*sy+tly
      rectfill(nx,ny,nx+sx,ny+sy,col)
      end
     end
    end
    print(text,0,0,0)

end

However it depends on first printing the text to the screen.

I was trying to think of ways I could enable scaled text printing while other things are going on. Right now I just keep a black strip at the top of the screen of my current game so that I can scale text whenever I would like.

One idea I had was to create a table outside of Pico-8 that matches the Pico-8 font, and each row would be a single byte where every bit is a pixel, 8 bytes each for all characters in the font, then look up the correct bit when scaling each character, instead. Problem with that is the space it could use up, I guess.

I was kinda hoping the font would be in some kind of pseudo "system ROM" readable using PEEK, but I didn't see this listed in the memory map.

Another idea I had was to print every character, read the pixels and keep the data in a table. It'd be a sort of ugly "blip" of text right as the game starts up, though, but it might be so fast nobody would notice...

P#42303 2017-07-09 22:17 ( Edited 2017-07-15 05:58)

You can just do a cls() at the start of _draw, then print your text, pget it all, then cls() again and do what you normally want to do. It'll work fine. Try this in a blank cart. You'll see what I mean:

function _draw()
    cls(12)          --clear:blue
    print("a",0,0,7) --text
    c1=pget(0,0)     --should be 7
    c2=pget(1,1)     --should be 12
    cls()            --clear again
    print("c1="..c1,10,10,7)
    print("c2="..c2,10,16,7)
end

I had it clear to blue, instead of just cls(), so you could see it doesn't do anything like cause a flicker or something like that.

P#42304 2017-07-09 23:11 ( Edited 2017-07-10 03:13)

Oh yeah! Dur. I should have realized this was possible...it's all drawn to a backbuffer first right? Nothing you drew shows up til _draw exits, correct? Thanks!

P#42311 2017-07-10 08:53 ( Edited 2017-07-10 12:53)

Also, if you're writing code that doesn't re-draw the screen every frame, for whatever reason, then you could first do a memcpy of the first five or six rows of vram to an offscreen ram location, write out your text to the top of the screen, make use of it, and then memcpy the saved bit back before the end of frame.

It's too bad there isn't a function, DRAWBUF(addr) or somesuch, that says where the drawing primitives write to, rather than hardcoding it to 0x6000. That would allow the sort of thing above without having to save/reload visible screen memory.

P#42495 2017-07-15 01:58 ( Edited 2017-07-15 06:03)
1

Is this still a good way to accomplish scaling text? Since this several versions old now, thought maybe there's a better way now.

But if this is still valid, I'm having trouble connecting the dots between the scale_text() function offered and the explanation given by Dylan.

I mean, I understand why the double cls() and pget() works but that info doesn't make use of the scaling function. I thought the latter referenced the first but it does not.

P#114010 2022-07-07 00:38

Old thread, but thought I would pop in with my current solution. I take advantage of the new capability to set the screen as the sprite sheet. It does not do any cls(), and is somewhat plug-and-play, although it is prone to small graphical glitches.

This requires that you also implement "oprint", or outline print.

function oprint(str,x,y,c,co) --outline print
    for xx=-1,1,1 do
        for yy=-1,1,1 do
            print(str,x+xx,y+yy,co)
        end
    end
    print(str,x,y,c)
end

function bigprint(str,x,y,c,co,scale)
    poke(0x5f54,0x60) -- screen is spritesheet. spr and sspr use screen as source
    oprint(str,x,y,c,co) -- outline print to desired location
    local x0 = x-1
    local y0 = y-1
    local w = #str*4 + 2
    local h = 7 -- only works on single line strings for now
    palt(0b1111111111111111) -- set all colors transparent
    palt(c,false) -- only draw the text and outline colors
    palt(co,false)
    sspr(x0,y0,w,h,x0,y0,w*scale,h*scale) -- stretch the text with desired scale
    palt()
    poke(0x5f54,0x00) -- set spritesheet back to source for spr
end

This is a quick and dirty solution. This works by:

  1. printing the text normally
  2. Using the screen as our sprite sheet
  3. using sspr to literally draw the stretched text ON TOP of the old text

An occasional issue is that the original text sometimes "peeks out" from behind the stretched text (see below). This is why I use outline-print - it does a slightly better job at covering the old text.

Interested in seeing if anyone has improvements!

P#114035 2022-07-07 17:23 ( Edited 2022-07-07 17:24)

Cool, thanks for sharing the code, gonna play with it. I'm wondering if you can combine it with the cls() trick to avoid having the "peek out" problem...? Because of course the words I'm using have very noticeable peeking :(

P#114039 2022-07-07 19:18

Cart #bprint-0 | 2022-07-08 | Code ▽ | Embed ▽ | License: CC4-BY-NC-SA

@morningtoast I have been thinking about this today, and I decided to finally do it the right way. Behold, bprint!!

Ultimately, if you want a "perfect" drawing of big text, you need a buffer to print the text normally first. My original implementation would print right on the screen, then print ON TOP of that, meaning some artifacts from print 1 would sometimes peek out from behind the new text.

This new implementation uses the first row in the sprite sheet as a buffer. I do the following:

  1. Copy the first row of sprites to user memory at 0x4300. This SHOULD be safe, as long as you aren't pulling any other shenanigans with user memory.
  2. We then black out the first row of sprites.
  3. The string to be printed is printed into the now-empty sprite row
  4. Use our new "sprites" which contain the text, we can just use SSPR to print the text
  5. Copy the sprites BACK to the sprite sheet from user memory, so you can continue drawing them.

I think this is a pretty plug-and-play solution to do what you want. It should be safe, again, as long as you aren't using user memory for anything else.

P#114046 2022-07-08 01:15 ( Edited 2022-07-08 01:15)

> Is this still a good way to accomplish scaling text?

We now have custom fonts and control codes for wide/tall/both text. The control codes may not cover everything that bprint provides (like outline), but they are easy and accessible.

P#114076 2022-07-08 16:16

I was not aware of control codes! - the docs have them.

Docs about control codes

Looks like we now have lots of special characters that can modify printing behavior, including doubling text size, pausing between printing characters (nice to have the built in!), and outlining text.

Will probably play with these on the next game. For titles, it may still be nice to have a custom function to bigprint, and I don't see any codes for centering text.

P#114078 2022-07-08 17:16 ( Edited 2022-07-08 17:40)
1

@paloblancogames - Thanks for the code update. I am using it in my upcoming game, so thanks for making it drop-in ready.

@merwok - Thanks for the tip...I'll have to look up how to use custom fonts and control codes. I'm still not very good and understanding how memory functions are applied. I usually try to avoid them, lol.


If anyone has a demo/example of control codes in action for altering font sizes, etc. and can link, that'd be awesome to see. I think it's always easier to see a working example and deconstructing it to learn.

P#114089 2022-07-09 00:33 ( Edited 2022-07-09 00:35)

@morningtoast NP!

The code is a little verbose, with a few one-line functions in there. You can probably inline these and save yourself a bunch of tokens, but for the sake of an educational cart, I wanted to be long-winded to make sure things are clear. You also probably only need obprint, but I wanted to show both options.

P#114114 2022-07-09 14:12

The code you provided above I did reduce down quite a bit, it's working great. But are those control codes? The manual talks about print() command with special characters and escape codes and such. I guess I thought control codes can make the magic happen without all the poke() stuff...maybe not.

It sounded like that with these control codes you could, say, double font size with a simple print() and some extra escape characters attached rather than poking and memory stuff.

I'm probably thinking/wishing for it to be simpler and that's usually not the case with PICO-8 but even using the function you've provided is wonderful. I'll just account for the tokens from the start next time I use it.

function scale_text(str,x,y,c,scale)
    memcpy(0x4300,0x0,0x0200)
    memset(0x0,0,0x0200)
    poke(0x5f55,0x00)
    print(str,0,0,7)
    poke(0x5f55,0x60)

    local w,h = #str*4,5
    pal(7,c)
    palt(0,true)
    sspr(0,0,w,h,x,y,w*scale,h*scale)
    pal()

    memcpy(0x0,0x4300,0x0200)
end
P#114184 2022-07-11 00:37

[Please log in to post a comment]

Follow Lexaloffle:          
Generated 2023-04-01 03:31:49 | 0.030s | Q:33