Pixel font [how do I tint a mesh?]

Ok @yojimbo2000 , I see your point. But some people perfer to make there own version wheel and that’s ok if you feel like doing more work. I would have looked for a retro style font before (if I had even had the idea, which I didn’t) I started working on this class, but right now I don’t feel like giving up on my code just yet (especially because it’s almost finished). All I need to do is figure out what I explained I wanted and add the rest of the alphabet. I will look into your suggestion when all is lost…

Edit: I felt like it came off rude when I said “if I had even had the idea, which I didn’t” I just want to let you know I meant no bad intentions by typing that.

OK, if this is the root you want to take.

First, string.find isn’t going to work, because it will reorder the string you’re trying to write. Use a gmatch iterator matching on . (means any character) to step through each letter in the string you’re writing:

for letter in myParagraph:gmatch(".") do

then, because doing an if test on absolutely every character you want to print (26 lower case, 26 uppercase, punctuation, numbers etc) would be incredibly tedious to type, I would store the references to the glyphs in a key: value array. If your keys are just letters you can write them like this

glyphs = {a = "Dropbox:Aglyph", b = "Dropbox:Bglyph}

etc. But if your glyphs start with non-numbers, then you need to use an explicit syntax to indicate that they’re a string,[" "]:

{["1"] = "Dropbox:1glyph"}

Then, in your loop through the letters, you can just write

for letter in myParagraph:gmatch(".") do
    sprite(glyphs[letter])

One last thing. For performance reasons, rather than having 70-odd different textures and spriting each of them in turn, it would be much, much more efficient to put all of your glyphs into a single texture (mono-spaced glyphs would be best here), and have your text drawn as a single mesh. Using sprite is fine for throwing together quick mock-ups, but it’s not very perfomant, especially when lots of separate textures are used. This is the sort of thing the texture would look like. You might find a ready made one by googling:

glyphs

You’d addRect for each letter, and setRectTex to point to the correct texture. Eg, say the glyphs are arranged in a square texture, in a 10 x 10 pattern. Lets say “A” is in the top left corner, and they read from left-to-right. The texcoords and width/ height for A would be setRectTex(rect, 0,0.9,0.1,0.1). Your glyphs array could store these as vec2s.

glyphs = {a = vec2(0, 0.9), b = vec2(0.1, 0.9), c = vec2(0.2, 0.9)}

Then loop:

for letter in myParagraph:gmatch(".") do
    local rect = paragraphMesh:addRect(x,y,w,h)
    local g = glyphs[letter]
    paragraphMesh:setRectTex(rect, g.x, g.y, 0.1, 0.1)

Or better yet, layout your glyphs in the same order as ASCII 32-122, then use the bytecode for the letter to work out the co-ords, no need for a glyphs array.

for letter in myParagraph:gmatch(".") do
    local rect = paragraphMesh:addRect(x,y,w,h)
    local ascii = letter:byte() - 32 --ASCII printable characters start at 32
    local x = ascii % 10
    local y = ascii // 10
    local tx = 10/ x
    local ty = 0.9 - (10/ y) --invert, texY so that you start from the top of the image
    paragraphMesh:setRectTex(rect, tx, ty, 0.1, 0.1)

Right, you got a lot of work to do, so jump to it.

Thank you @yojimbo2000, I just have 2 more questions about this discussion. I’ve never used meshes before and I don’t really know how they work or even what they really are. So could you explain how they work and what makes them more efficient then sprites (for making a font). I will also research meshs to get an answer, but I mainly want to know how I would use them for the font. And lastly would it be possible to convert Pixel Vision code into a Shader, because I only plan on using it on sprites anyway. The only problem is I don’t really understand how Shaders work so I would be the last person I would ask to convert it.

@GameCoder - I’ve written some ebooks, here, the Codea one discusses meshes

https://www.dropbox.com/sh/mr2yzp07vffskxt/AACqVnmzpAKOkNDWENPmN4psa

I wouldn’t take on too much right now, I suggest you leave shaders for later

I want to make a asset pack with all the my textures so I can call all those textures within the class and make it easier to use my font in whatever project I want to export my font class to. How would I do that?

Search the forum for asset packs.

You could quite easily write a pixelvision shader, but it would be a waste of resources. Given that the pixelvision effect is based on lowres assets being upscaled with nosmooth(), its far more efficient to do just that, have lowres assets, and sprite/ rect them too large. Then your textures will be a quarter of the size, and that makes a big difference to speed and memory. If you put a regular-sized/res texture onto a mesh, and then used a shader to create the pixellated look, you’d lose out on that performance gain. You’d be putting 4x as many pixels into the pipeline as you actually end up using.

I am naming all my textures after there ascci numbers. How would I make it so that when I call a texture it will have a variable in the file location text (I don’t know whatever you call it). In:

letters.texture=readImage("Dropbox:(the variable for the textures name)")

in the quotes I want there to be a variable that represents the letters texture name (which is the same as it’s ascci number). So how would I do that?

Is this what you’re after. This will read each character of a string (str) and create str1 which is a name equivalent to the ascii value of the letter. You can change the name ascii to your choice. The letters.texture would be the image for str1.

function setup()
    str="ABCabc"
    for z=1,#str do
        c=string.sub(str,z,z)
        v=string.byte(c)
        str1=string.format("Dropbox:ascii%d",v)
        print(c.." =   "..str1)
        -- letters.texture=readImage(str1)
    end
end

Where do I put your code? Do I put in in “PixelFont:initi” or “PixelFont:draw”

code:

-- Pixel Font

PixelFont = class()

function PixelFont:init(x, y, letters)
    -- you can accept and set parameters here
 self.pos = vec2(x,y)
 self.letters = letters
    letters=letters
    for z=1,#letters do
        c=string.sub(letters,z,z)
        v=string.byte(c)
        letters1=string.format("Dropbox:ascii%d",v)
        print(c.." =   "..letters1)
    end
end

function PixelFont:draw()
    -- Codea does not automatically call this method

    letters = ""    

for letter in letters:gmatch(".") do
    local rect = lettersMesh:addRect(x,y,40,50)
    local ascii = letter:byte() - 32 --ASCII printable characters start at 32
    local x = ascii % 10
    local y = ascii // 10
    local tx = 10/ x
    local ty = 0.9 - (10/ y) --invert, texYd so that you start from the top of the image
    lettersMesh:setRectTex(rect, tx, ty, 0.1, 0.1)
    letters.texture=readImage(letters1)

    end
end

-- Main

-- Use this function to perform your initial setup
function setup()

letters = PixelFont(500, 450, "abc")
-- the letters should be able to be called in any order for example it could have been "bca" or "cab"
end

-- This function gets called once every frame
function draw()
     -- This sets a dark background color
    background(40, 40, 50)

    -- Do your drawing here
PixelFont:draw()

end

I’m not following what your code is supposed to do, but my code should go in draw. My code should read each letter in self.letters, create the image name Documents:ascii## for each letter, letters.texture will read that image and you would sprite that image to the screen.

Here’s what I think your code should look like. Since I don’t have your images, I substituted text for sprite. When you use sprite, comment out text and you might have to change the *10 to some other value based on the width of the images.

function setup()
    letters=PixelFont(100,300, "abc")
end

function draw()
    background(40, 40, 50)
    fill(255)
    letters:draw()
end

PixelFont = class()

function PixelFont:init(x, y, letters)
    self.pos = vec2(x,y)
    self.letters = letters
end

function PixelFont:draw()
    for z=1,#self.letters do
        c=string.sub(self.letters,z,z)
        v=string.byte(c)
        letters1=string.format("Dropbox:ascii%d",v)
        img=readImage(letters1)
        --sprite(img,self.pos.x+z*10,self.pos.y)
        text(c,self.pos.x+z*10,self.pos.y)
    end
end

The code converts the text I input in main and uses textures that look like the characters used in the input to create a mesh that would look like a line of text.

I wanted to do that so I could set the mesh textures to whatever the text looked like

OK. Instead of my code above spriteing each letter to the screen, create the mesh texture instead. If that’s the case, then you can create the mesh texture in PixelFont:init and then show the texture in PixelFont:draw.

function setup()
    letters=PixelFont(100,300, "abc")
end

function draw()
    background(40, 40, 50)
    fill(255)
    letters:draw()
end

PixelFont = class()

function PixelFont:init(x, y, letters)
    self.pos = vec2(x,y)
    self.letters = letters
    for z=1,#self.letters do
        c=string.sub(self.letters,z,z)
        v=string.byte(c)
        letters1=string.format("Dropbox:ascii%d",v)
        img=readImage(letters1)
        -- code to add each letter to the texture
    end
end

function PixelFont:draw()
    -- code to draw the texture
end

It works (sort of). But I’m getting a error message in the output, it says “PixelFont:16:attempt to index a nil value (global ‘letters1Mesh’)
stack traceback:PixelFont:16: in method 'draw’Main:8: in function ‘draw’”.
here’s the code:

-- PixelFont

PixelFont = class()

function PixelFont:init(x, y, letters)
    self.pos = vec2(x,y)
    self.letters = letters
    for z=1,#self.letters do
        c=string.sub(self.letters,z,z)
        v=string.byte(c)
        letters1=string.format("Dropbox:ascii%d",v)
    end
end

function PixelFont:draw()
    -- code to draw the texture
           for letter in letters1:gmatch(".") do
            local rect = letters1Mesh:addRect(x,y,40,50)
            local ascii = v - 32 --ASCII printable characters start at 32
            local x = ascii % 10
            local y = ascii // 10
            local tx = 10/ x
            local ty = 0.9 - (10/ y) --invert, texYd so that you start from the top of the image
            lettersMesh1:setRectTex(rect, tx, ty, 0.1, 0.1)
            letters1.texture=readImage(letters1)

    end
end

-- Main

function setup()
    letters=PixelFont(100,300, "abc")
end

function draw()
    background(40, 40, 50)
    fill(255)
    letters:draw()
end

I don’t see anyplace where you’re defining lettersMesh1.

lettersMesh1=mesh()

Here’s an example where I create a mesh texture. Since I don’t have your images, I used Cargo Bot:Crate Green 1 instead of letters1.

function setup()
    letters=PixelFont(100,300, "abc")
end

function draw()
    background(40, 40, 50)
    letters:draw()
end

PixelFont = class()

function PixelFont:init(x,y,letters)
    self.m=mesh()
    self.pos=vec2(x,y)
    self.letters=letters
    for z=1,#self.letters do
        c=string.sub(self.letters,z,z)
        v=string.byte(c)
        letters1=string.format("Dropbox:ascii%d",v)
        img=readImage("Cargo Bot:Crate Green 1")
        self.m.texture=img
        self.m:addRect(self.pos.x,self.pos.y,img.width,img.height)
        self.pos.x=self.pos.x+img.width
    end
end

function PixelFont:draw()
    self.m:draw()
end

I replaced the cargobot texture with “letters1” (without quotes in the code). Then it worked, but all the letters looked like my “c” texture. What’s going on?
Edit: And how can I fix that?

I just realized that the textures for the letters only looked like the last letter in the text. So if “letters” equaled “bca” they would all be “a” and if it were “cab” they would all be “b”. What!?

See what letters1 is, print(letters1). It should show 3 different values.