Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Pixel font [how do I tint a mesh?]

edited July 2016 in Questions Posts: 38

How would I go about making a pixel font? What I mean by that is how would I create a class that would have a function to convert the characters of a string into sprites that look like (pixelated) letters? The first letter/sprite would have the original x, y coordinates in the setup function, but the other letters/sprites would use the same y coordinate but the x value would change after each letter/sprite.

For example if I set the coordinates to 20 (x), and 500 (y) the first letter/sprite coordinates would of course be 20 , and 500 (x, y), but the second letter/sprite would be 40, and 500 (x + 20, y), but the third letter/sprite would be 60, and 500 (x + 20 * 2, x), but the fourth would be 80, and 500 (x + 20 * 3, y), and so on. Depending on the width of the letter/sprite I may add more or less to x. I would also add more to x if there was a space.

I hope I made myself clear enough. I tried my best to make that understandable

Tagged:
«1

Comments

  • dave1707dave1707 Mod
    Posts: 7,520
    displayMode(FULLSCREEN)
    supportedOrientations(LANDSCAPE_ANY)
    
    function draw()
        background(40, 40, 50)
        fill(255)
        for z=33,127 do
            text(string.char(z),10.5*(z-31),500)
        end
    end
    
  • dave1707dave1707 Mod
    edited June 2016 Posts: 7,520

    Or if you want to do it from a string. Just have to figure out the pixelated part.

    displayMode(FULLSCREEN)
    supportedOrientations(LANDSCAPE_ANY)
    
    function setup()
        str="abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ"    
    end
    
    function draw()
        background(40, 40, 50)
        fill(255)
        for z=1,#str do
            text(string.sub(str,z,z),18*z,500)
        end
    end
    
  • Posts: 2,020

    (pixelated) letters

    Do you mean, like a retro, 8-bit, pixel-art look? Big chunky pixels?

  • dave1707dave1707 Mod
    Posts: 7,520

    Here's an example of setting up your own characters. You can create any shape character you want.

    supportedOrientations(LANDSCAPE_ANY)
    
    function setup()
        tab={
        -- 0 to 9
        ["0"]={64,496,280,776,520,520,520,520,776,776,280,240,0,0,0,0},
        ["1"]={0,192,224,240,192,192,192,192,192,192,192,192,0,0,0,0},
        ["2"]={64,496,792,776,768,256,384,192,48,24,24,1020,0,0,0,0},
        ["3"]={0,496,280,776,256,448,384,768,512,776,792,496,0,0,0,0},
        ["4"]={0,384,448,480,416,400,408,396,1020,384,384,384,0,0,0,0},
        ["5"]={0,1008,16,24,88,504,776,512,512,776,280,240,0,0,0,0},
        ["6"]={64,496,792,8,8,504,796,520,520,776,280,496,0,0,0,0},
        ["7"]={0,1016,256,384,128,192,64,96,32,32,48,48,0,0,0,0},
        ["8"]={64,496,280,792,280,496,440,776,520,520,792,496,0,0,0,0},
        ["9"]={0,496,280,776,520,776,920,752,512,776,408,240,0,0,0,0},
    
        -- A to Z
        ["A"]={0,192,448,352,800,816,528,2032,2040,3080,3084,2060,0,0,0,0},
        ["B"]={240,1016,1560,1048,1560,1016,2040,1048,3096,3096,1560,1016,0,0,0,0},
        ["C"]={384,2016,3120,2072,8,8,8,8,6168,2072,3120,2016,0,0,0,0},
        ["D"]={112,2040,3096,2072,2072,6168,6168,6168,2072,3096,1560,1016,0,0,0,0},
        ["E"]={2032,2040,24,24,24,2040,2040,24,24,24,24,4088,0,0,0,0},
        ["F"]={2032,2040,24,24,24,1016,1016,24,24,24,24,24,0,0,0,0},
        ["G"]={896,4064,6192,4120,24,8,7688,7688,4120,4112,7280,4032,0,0,0,0},
        ["H"]={2048,2072,2072,2072,2072,4088,4088,2072,2072,2072,2072,2072,0,0,0,0},
        ["I"]={0,24,24,24,24,24,24,24,24,24,24,24,0,0,0,0},
        ["J"]={0,384,384,384,384,384,384,384,384,396,216,248,0,0,0,0},
        ["K"]={0,1560,792,408,216,248,504,408,792,1560,1048,3096,0,0,0,0},
        ["L"]={0,24,24,24,24,24,24,24,24,24,24,1016,0,0,0,0},
        ["M"]={12304,12344,14392,14392,10360,11352,9304,9432,8856,8856,9112,8472,0,0,0,0},
        ["N"]={2048,2072,2104,2168,2136,2264,2456,2328,2840,3608,3096,3096,0,0,0,0},
        ["O"]={896,4064,6192,6168,4104,12296,12296,12296,4120,6168,3120,2016,0,0,0,0},
        ["P"]={240,2040,3096,3096,3096,3096,2040,24,24,24,24,24,0,0,0,0},
        ["Q"]={896,4064,2096,6168,4104,12296,12296,4104,4120,6936,3632,8160,4096,0,0,0},
        ["R"]={496,4088,3096,2072,2072,3608,1016,792,1560,3096,3096,6168,0,0,0,0},
        ["S"]={448,1008,1560,1048,24,240,1984,1536,3080,3096,1592,1008,0,0,0,0},
        ["T"]={2040,2044,192,192,192,192,192,192,192,192,192,192,0,0,0,0},
        ["U"]={2048,2072,2072,2072,2072,2072,2072,2072,2072,3096,1584,992,0,0,0,0},
        ["V"]={2048,2060,3080,1048,1552,1552,560,800,288,352,448,192,0,0,0,0},
        ["W"]={512,34572,34568,34056,52632,19864,18576,18576,30960,12400,12384,12384,0,0,0,0},
        ["X"]={8,1048,1584,800,480,192,448,480,800,1584,1048,3084,0,0,0,0},
        ["Y"]={2048,3080,1560,560,800,480,192,192,192,192,192,192,0,0,0,0},
        ["Z"]={2040,2040,1536,768,384,192,64,96,48,24,28,2044,0,0,0,0},
        [" "]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
        }
    
        str="THIS IS A TEST 123 456 789"
    end
    
    function draw()
        background(0)
        fill(255)
        pos=20
        for b=1,#str do
            c=string.sub(str,b,b)
            pos=pos+25
            for z=1,16 do
                for x=0,16 do
                    if 2^x&tab[c][z] >0 then
                        rect(pos+x*2,600-z*2,2,2)
                    end
                end 
            end       
        end
    end
    
  • IgnatzIgnatz Mod
    Posts: 5,396

    Here is another method, drawing a character into a small image, then creating a large image (eg 4x larger) and copying each pixel of the small image into the large image as a block of pixels to give a chunky effect.

    The advantage is you can create a whole set of pixelated characters, in any font you like, with no need to hand draw any of them. The best would be to use this program to create a single sprite sheet with all the characters in a table format, then you just have to look up the one you need each time.

    Note, you will need to play with the font choice, and the size of the larger image, to get the effect you want.

    function setup()
        chars={}
        for i=0,9 do
            chars[i]=MakePixelChar(i)
        end
    end
    
    function draw()
        background(200)
        for i=0,9 do
            sprite(chars[i],100+i*60,HEIGHT/2)
        end
    end
    
    --draws a char in a small image, then copies it to a larger image
    function MakePixelChar(a)
        --s is size of initial image
        --x is the size of the enlarged image, as a multiple of x, eg 3 or 5
        --fs is the font size of the text in the initial image
        local s,x,fs=20,8,16
        local img=image(s,s)
        setContext(img)
        fontSize(fs)
        text(a,s/2,s/2)
        setContext()
        local img2=image(s*x,s*x)
        for i=1,s do
            local ik=(i-1)*x+1
            for j=1,s do
                local jk=(j-1)*x+1
                local r,g,b,a=img:get(i,j)
                if a>0 then
                    for i2=ik,ik+x do
                        for j2=jk,jk+x do
                            img2:set(i2,j2,color(r,g,b))
                        end
                    end
                end
            end
        end
        return img2
    end
    
  • Posts: 809

    ^ These are pretty cool. How to install a font to let it be in Codea? Not working for me.

  • Posts: 2,020

    @TokOut search the forum for "install font". You'll need to use a third party app to install a font system-wide on your iPad.

  • IgnatzIgnatz Mod
    Posts: 5,396

    Don't forget lots of fonts are built into Codea - see the font command

  • Posts: 38

    Can't wait to try them all and see what works best for me.

  • edited June 2016 Posts: 38

    Do you mean, like a retro, 8-bit, pixel-art look? Big chunky pixels?

    Yes @yojimbo2000 , but not too big. Small enough to be the size of regular text (maybe a bit bigger). So I could have a dialogue box on the bottom of the screen that wouldn't be to big to interfere with the game (that I'm making). For some reason I like the look of retro pixel, plus it is the easiest to make and import into Codea for me. I think it's because I like games like Mincraft and Terraria.

  • Posts: 2,020

    @Ignatz there is no need to make a copy of the image, just Sprite or mesh it big with noSmooth

    @GameCoder the key to making pixel art in Codea is the noSmooth() command. This stops the graphics system from trying to smooth out your blow-up texture, giving you the blocky hard-edged look you need. Here is a pixel vision class, it can be used for anything, not just text


    --# Main -- PixelVision displayMode(FULLSCREEN) function setup() pixelVision = PixelVision() message = [[ It is a dark time for the Rebellion. Although the Death Star has been destroyed, Imperial troops have driven the Rebel forces from their hidden base and pursued them across the galaxy. Evading the dreaded Imperial Starfleet, a group of freedom fighters led by Luke Skywalker has established a new secret base on the remote ice world of Hoth. The evil lord Darth Vader, obsessed with finding young Skywalker, has dispatched thousands of remote probes into the far reaches of space.... ]] font("Inconsolata") fill(255, 247, 0, 255) textAlign(CENTER) end function draw() pixelVision:startDrawing() --do your drawing here, using full screen coordinates (it all gets scaled) background(40, 40, 50) fontSize(32) text(message, WIDTH/2, HEIGHT/2) pixelVision:stopDrawing() end --# PixelVision PixelVision = class() function PixelVision:init(size) local size = size or 4 --size of each block self.scale = 1/size self.image = image(WIDTH//size, HEIGHT//size) self.mesh = mesh() self.mesh:addRect(WIDTH/2, HEIGHT/2,WIDTH,HEIGHT) self.mesh.texture = self.image end function PixelVision:startDrawing() setContext(self.image) pushMatrix() scale(self.scale) end function PixelVision:stopDrawing() popMatrix() setContext() noSmooth() self.mesh:draw() end
  • dave1707dave1707 Mod
    edited June 2016 Posts: 7,520

    Here's another way. Change the fontSize(5) and Sprite size (2000) to get different effects.

    function setup()
        img=image(WIDTH,300)
        message = [[
        It is a dark time for the Rebellion.
        Although the Death Star has been destroyed,
        Imperial troops have driven the Rebel forces
        from their hidden base and pursued them
        across the galaxy.
        Evading the dreaded Imperial Starfleet, 
        a group of freedom fighters led by 
        Luke Skywalker has established a new secret
        base on the remote ice world of Hoth.
        The evil lord Darth Vader, obsessed with
        finding young Skywalker, has dispatched
        thousands of remote probes into the far
        reaches of space....
        ]]
        pix()
    end
    
    function draw()
        background(0)
        sprite(img,WIDTH/2,300,2000)
    end
    
    function pix()
        noSmooth()
        fontSize(5)
        setContext(img)
        fill(117, 226, 7, 255)
        text(message,WIDTH/2,150)
        setContext()
    end
    
  • Posts: 2,020

    I got bored and added a retro star field, to demonstrate animated pixel vision:


    --# Main -- PixelVision displayMode(FULLSCREEN) supportedOrientations(LANDSCAPE_ANY) function setup() size = 4 pixelVision = PixelVision(size) starField = StarField() message = [[ It is a dark time for the Rebellion. Although the Death Star has been destroyed, Imperial troops have driven the Rebel forces from their hidden base and pursued them across the galaxy. Evading the dreaded Imperial Starfleet, a group of freedom fighters led by Luke Skywalker has established a new secret base on the remote ice world of Hoth. The evil lord Darth Vader, obsessed with finding young Skywalker, has dispatched thousands of remote probes into the far reaches of space.... ]] font("Futura-Medium") fontSize(32) fill(255, 247, 0, 255) textWrapWidth(490) -- textAlign(CENTER) messageW, messageH = textSize(message) end function draw() pixelVision:startDrawing() --do your drawing here, using full screen coordinates (it all gets scaled) background(0) starField:draw() perspective() camera(0,0,1000 / size, 0,0,0) rotate(-70, 1,0,0) text(message,0,(-messageH * 1.2) + ElapsedTime * 20) -- text(message, WIDTH/2, -250 + ElapsedTime * 40) pixelVision:stopDrawing() end --# PixelVision PixelVision = class() function PixelVision:init(size) local size = size or 4 --size of each block self.scale = 1/size self.image = image(WIDTH//size, HEIGHT//size) self.mesh = mesh() self.mesh:addRect(WIDTH/2, HEIGHT/2,WIDTH,HEIGHT) self.mesh.texture = self.image end function PixelVision:startDrawing() setContext(self.image) pushMatrix() scale(self.scale) end function PixelVision:stopDrawing() popMatrix() setContext() ortho() viewMatrix(matrix()) noSmooth() self.mesh:draw() end --# StarField StarField = class() function StarField:init(max) self.mesh = mesh() self.mesh.texture = readImage("Space Art:Star") self.stars = {} self.max = max or 300 for i = 1,self.max do self.mesh:addRect(0,0,0,0) end end function StarField:add(i) local x = WIDTH * (math.random()-0.5) * 0.5 local y = HEIGHT * (math.random()-0.5) * 0.5 local dx, dy = (vec2(x,y):normalize() * 0.2):unpack() -- print(x,y,dx,dy) self.stars[i] = {x = x, y = y, dx = dx, dy = dy} end function StarField:draw() local len = #self.stars if len < self.max then len = len + 1 self:add(len) end for i = 1,len do local star = self.stars[i] star.x = star.x + star.dx star.y = star.y + star.dy star.dx = star.dx * 1.01 star.dy = star.dy * 1.01 if math.abs(star.x) > WIDTH * 0.5 or math.abs(star.y) > HEIGHT * 0.5 then self:add(i) end local bright = math.abs(star.dx) self.mesh:setRect(i, star.x, star.y, bright * 10, bright * 10, -star.dx) self.mesh:setRectColor(i, color(255 * bright)) end pushMatrix() translate(WIDTH/2, HEIGHT/2) self.mesh:draw() popMatrix() end
  • Posts: 809

    @yojimbo2000, I think it's time for you to make your own movies with Codea :)

  • Posts: 154

    @yojimbo2000, very cool!
    Just missing the music ... But otherwise it's perfect.

  • edited July 2016 Posts: 38

    Thank you for the Pixel Vision code, although I will still use Pixel Vision for other things I've decided to go with my original idea. I have taken it apon myself to create the class for it, but there's only one problem.

    I can't rap my head around a way I would create a table within a class. Then add sprites to it in a loop.

    please keep in mind that I know the code doesn't do anything yet

    Here's the 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
    
    end
    
    function PixelFont:draw()
        -- Codea does not automatically call this method
    
            -- these are all the Characters in the alphabet err... I mean the first three letters in the alphabet
        letters = ""
    
        for n = 1, 3 do
    
                if string.find(letters, "a", n) then
                sprite("Project:a", x, y, 40, 40)
             -- code that will add this sprite above into a table
                x = x + n * 28
            elseif string.find(letters, "b", n) then
                sprite("Project:b", x, y, 40, 40)
             -- code that will add this sprite above into a table
                x = x + n * 30
            elseif string.find(letters, "c", n) then
                sprite("Project:c", x, y, 40, 40)
             -- code that will add this sprite above into a table
                x = x + n * 28 -- I don't know how much I should add to x if c is before any letter so for now it's 28
                end                
            n = n + 1
    
        end
    -- code that will draw all the sprites in the table that was created up there in the loop
    
    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
    

    Here's what it's supposed to do:

    there's supposed to be a picture of the correct results here but I can't seem to get the image to paste in

    Here's the code that created the image that was supposed to be above:

    -- Test
    
    -- Use this function to perform your initial setup
    function setup()
        print("Please Help me Fourm!")
    end
    
    -- This function gets called once every frame
    function draw()
        -- This sets a dark background color 
        background(40, 40, 50)
    
        -- Do your drawing here
    
     x = 500
     y = 450
    
        sprite("Project:a", x, y, 40, 50)
        sprite("Project:b", x + 28, y, 40, 50)
        sprite("Project:c", x + 58, y, 44, 50)    
    end
    

    I was also going to paste in the sprites I used but I can't paste them in :(

  • edited July 2016 Posts: 38

    I just noticed a problem already. On the line with (and ever other line that uses "n" excluding the one in the for loop)

    n = n + 1
    

    the variable "n" should be changed to something else. I want the variable that will be replacing "n" in that line to be = 1 in the first run of that loop and then have 1 more be add each time so by the second time it would be 2 then 3.

    Edit: I think I should just change the "n" in

    for n = 1, 3 do
    

    to "i" and leave the every other "n" alone.

  • Posts: 38

    I also can't figure out how to detect how many individual characters are in a string. I want to do this so I can replace the "3" in

    for n = 1, 3 do
    

    with a variable that represents how many characters were in the string.

  • Posts: 2,020

    #myString returns the length of a string (same syntax as an array). This seems like a lot of work just to draw text on the screen. I think you're reinventing the wheel. You know that you can install custom fonts to the iPad, which Codea can then use? There's quite a few retro pixel fonts. You'll need a third party app to install it on the iPad (I use one called FondFont). You won't be able to see it in the Codea font picker, but you can still use it by just manually putting its name into the font command.

  • edited July 2016 Posts: 38

    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.

  • Posts: 2,020

    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.

  • edited July 2016 Posts: 38

    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.

  • IgnatzIgnatz Mod
    edited July 2016 Posts: 5,396

    @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

  • edited July 2016 Posts: 38

    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?

  • dave1707dave1707 Mod
    Posts: 7,520

    Search the forum for asset packs.

  • Posts: 2,020

    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.

  • edited July 2016 Posts: 38

    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?

  • dave1707dave1707 Mod
    Posts: 7,520

    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
    
  • Posts: 38

    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
    
  • dave1707dave1707 Mod
    Posts: 7,520

    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.

  • dave1707dave1707 Mod
    Posts: 7,520

    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
    
  • Posts: 38

    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.

  • Posts: 38

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

  • dave1707dave1707 Mod
    edited July 2016 Posts: 7,520

    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
    
  • edited July 2016 Posts: 38

    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
    
  • dave1707dave1707 Mod
    edited July 2016 Posts: 7,520

    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
    
  • edited July 2016 Posts: 38

    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?

  • Posts: 38

    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!?

  • dave1707dave1707 Mod
    edited July 2016 Posts: 7,520

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

  • edited July 2016 Posts: 38

    In main I did:

    function setup()
        letters=PixelFont(100,300, "caa")
        print(string.format(letters1))
    end
    
    function draw()
        background(40, 40, 50)
        letters:draw()
    end
    

    And it only printed "Dropbox:ascii27" once

  • dave1707dave1707 Mod
    edited July 2016 Posts: 7,520

    Run this and see what prints. It should print Dropbox:ascii97 Dropbox:ascii98 Dropbox:ascii99 .

    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)
            print(letters1)   -- print what letters1 is
            img=readImage(letters1)
            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
    
  • Posts: 38

    Ok now it printed what you said but I still don't understand why it draws 3 "c"s instead of an "a" a "b" and a "c".

  • dave1707dave1707 Mod
    edited July 2016 Posts: 7,520

    OK, something isn't working the way I think it should. I'm getting the same thing. The texture image isn't changing to the different images.

  • dave1707dave1707 Mod
    edited July 2016 Posts: 7,520

    @Ignatz @yojimbo2000 Is there a way to change the texture image. It looks like only one image is being used for the texture instead of 3. I'm overlooking something right now.

    EDIT: Apparently different rects can't have different images in the same mesh. All of the rects get the last image assigned.

  • dave1707dave1707 Mod
    Posts: 7,520

    @GameCoder I'm thinking that what needs to be done is each letter image needs to be put into a single larger image. Then that larger image is used for the mesh texture.

  • Posts: 38

    Can we try it the way we were doing it before first. I might not be able to create a image big enough (with the app I'm using to create the textures).

  • dave1707dave1707 Mod
    Posts: 7,520

    Try it which way. What code above are you referring to.

  • edited July 2016 Posts: 38

    Yes @dave1707
    This code:

    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)
            print(letters1)   -- print what letters1 is
            img=readImage(letters1)
            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
    
    function setup()
        letters=PixelFont(100,300, "abc")
    end
    
    function draw()
        background(40, 40, 50)
        letters:draw()
    end
    
  • dave1707dave1707 Mod
    Posts: 7,520

    Try this and tell me what happens.

    function setup()
        letters=PixelFont(30,400, "abc")
    end
    
    function draw()
        background(40, 40, 50)
        letters:draw()
    end
    
    PixelFont = class()
    
    function PixelFont:init(x,y,letters)
        self.pos=vec2(x,y)
        self.letters=letters
        self.mTab={}
        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)
            self.mTab[z]=mesh()
            self.mTab[z].texture=img
            self.mTab[z]:addRect(self.pos.x+z*img.width,self.pos.y,img.width,img.height)
        end
    end
    
    function PixelFont:draw()
        for a,b in pairs(self.mTab) do
            b:draw()
        end
    end
    
  • edited July 2016 Posts: 38

    It... WORKED! Thank you! :)

Sign In or Register to comment.