Change a PNG font on the fly

Previous topic - Next topic

Alex_R

Is it possible to change a PNG font on the fly? I pretend to create a fantasy language and change randomly some characters for western characters when the player achieve some goals in the game. So I need the possibility to change one character for another in the same PNG. I think I can create my own font PNG on the fly (off screen), and get it with GRABSPRITE or CREATESCREEN. But this procedure put the PNG into one ID sprite. How can I convert this sprite into a font?

Thank you!!

mentalthink

I never try, but if you put the char of the font coordinated whit the font... whit types

something like

Code (glbasic) Select
array letter[] as TCHAR

TYPE TCHAR
fnt
letter
id
endtype

DIMPUSH letter[],...
   
   FOR each item in letter[]
     setfont item.fnt
     print item.letter
   Next


I never try, but perhasp works... (I think the maximun number of different fonts it's 32... I'm not sure 100% about this)


mentalthink

HI Alex, here my Code... I hope can help you. You have attached all the project
Code (glbasic) Select
// --------------------------------- //
// Project: ajksdjk
// Start: Monday, April 15, 2013
// IDE Version: 11.322


// SETCURRENTDIR("Media") // go to media files
// --------------------------------- //
// Project: fly_Font
// Start: Monday, April 15, 2013
// IDE Version: 11.322


// SETCURRENTDIR("Media") // go to media files
LOADFONT "smalfont.png" ,0
LOADFONT "smalfont_02.png" ,1

TYPE TFONTaS
id
fnt;
letter;
ENDTYPE

GLOBAL fontas[] AS TFONTaS

DIM fontas[100]

FOR n=0 TO LEN(fontas[])-1
fontas[n].id=n
fontas[n].letter=CHR$(32+RND(100))
NEXT

FOR n=0 TO LEN(fontas[])-1 STEP 2
fontas[n].fnt = 0
fontas[n+1].fnt = 1


NEXT


WHILE TRUE

FOREACH item IN fontas[]
    SETFONT item.fnt
PRINT item.letter,0+(item.id*20),100

NEXT

SHOWSCREEN

WEND

Alex_R

Thanks mentalthink, this is one solution very usefull. However I still wonder if I can change on the fly a font PNG (the graphic) like I can change one sprite for an other.

Ian Price

#4
What you can do is have two fonts within the same anim - one with the elvish (or whatever) font and the other with latin font. So first 32 (64 or 96) chars would be foriegn then the next set would be the normal alphabet.

Using your bitmap font routine to print the characters is easy (use ASC of the text$ to get the sprite value). What you can do, over time is use an array to hold each letter's flag - eg
Code (glbasic) Select


GLOBAL evlvish%[]
DIM elvish[32]



Then what you can do, over time is set the array to 1 (eg. elvish[X]=1) so that when you are reading the ASC value of your text is use

[PSEUDO-CODE]
FUNCTION BMPtext(text$, X,Y)
  FOR n=0 to LEN (text$)
   character=ASC(text$)+(elvish[character]*number of characters in the font (32/64/96))
   DRAWANIM 1,character, X, Y
  NEXT
ENDFUNCTION
[/PSEUDO-CODE]

Does that make sense?

You can make set character appear over a period of time or by completing tasks by making another array which holds the preferred character pattern in order - eg 5,1,3 - would make E visible, then A, then C etc. based on their position in the alphabet.


[EDIT] I'm at work so can't create a working example right now.
I came. I saw. I played.

Alex_R

Thank you Ian. I've got the idea.  :)

CW

#6
Sounds like an interesting game idea, Alex. Will you allow your player to figure out missing letter equivalences, like solving a simple substitution cypher? That could be a sort of mini-game within your game. Those who don't want to bother solving the cypher can do more quests and fill it in the long way. Of course you would have to randomize the elvish at the start of each new adventure.

I hope you share your game with us when you are done.
Happy Coding!
-CW

Alex_R

Thank you CW. My next game is an isometric 2D, RPG. At the beginning you receive a weird book written in an ancient language that you don't understand. You have to travel distant lands searching old scrolls which teach you this ancient language revealing the content of the book. So the player, of course can find out the meaning of every scroll by simple substitution cypher to know the next tip in her mission or can finish the mission to reveal all letters and gaining experience and mana points.
Yes I'll put the game progress log and photos here to show you the work. Perhaps it is time to add to this forum a main theme named "Your game progress"?

Ian Price

Look forward to seeing your progress on this. :)
I came. I saw. I played.

kanonet

Quote from: Alex_R on 2013-Apr-17
Perhaps it is time to add to this forum a main theme named "Your game progress"?
This is what your personal blogs (in this forum) are for, you start posing about your game there. ;)
Lenovo Thinkpad T430u: Intel i5-3317U, 8GB DDR3, NVidia GeForce 620M, Micron RealSSD C400 @Win7 x64

Alex_R

Hi again!!

Now I have my own print function for my game as mentalthink and Ian Price suggested. I use one polyvector for each letter even if I think this method slows the speed game.  But on the other hand this is cool because I can also resize all characters checking the screeen resolution.

But now I have a problem. How can I solve the proportional printing issue? I mean, the wide of some characters is not the same that others. The GLBASIC print statement has the kernel. How can I programm a kernel like style? I don't know how to start.  :zzz:

Thank you!!

spacefractal

doing a dim push and proporty checks for purple in first Line?

polyvectors is faster than draw methods for font, but don't use alpha (by command, not in image itself) or colored font, which can slow down on iOS (or you are aware or it).
Genius.Greedy Mouse - Karma Miwa - Spot Race - CatchOut - PowerUp Elevation - The beagle Jam - Cave Heroes 2023 - https://spacefractal.itch.io/

Ian Price

If you are doing each letter independently then you could create an array containing the width of each letter. Then use that in your print routine
e.g.
Code (glbasic) Select

x=x+width[char[number]]


Or you could have a bodge job within your print routine -

Code (glbasic) Select

FUNCTION txt: x,y,ss$

LOCAL xpos%=0

LOCAL average_char_width%=16

  FOR i=0 TO LEN(ss$)-1
   cr=(ASC(MID$(ss$,i,1))-32)

    IF cr=0 THEN x=x-6  // Space
    IF cr=1 THEN x=x-6 // !
    IF cr=3 THEN x=x-6 // #
    IF cr=4 THEN x=x-6 // $
    IF cr=5 THEN x=x-4 // %
    IF cr=6 THEN x=x-2 // &
    IF cr=7 THEN x=x-12 // '
    IF cr=8 THEN x=x-10 // (
    IF cr=9 THEN x=x-8 // )

    // etc...

   DRAWANIM font,cr,x+(xpos*average_char_width),y

   xpos=xpos+1
  NEXT
ENDFUNCTION
I came. I saw. I played.

Alex_R

Thank you for your advice. The Ian Price solution is easy to do but too much code lines for 120 characters. However I don't see other method.  ;)

kanonet

No i would not suggest to use a hardcoded method, just check the width of each character when you load your font, store this in an array and use it when you display everything.
Lenovo Thinkpad T430u: Intel i5-3317U, 8GB DDR3, NVidia GeForce 620M, Micron RealSSD C400 @Win7 x64