Howdy, Stranger!

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

In this Discussion

Fixing my typewriter function (parses text, i guess) to draw words on the next line?

in Questions Posts: 117

Hi, im not sure how to explain. i have a typewriter function, and it only draws n characters, so sometimes words that are too long will start drawing on line a, then wrap to line b. and it looks weird. I don't mean to make you do it for me, but i'm not sure how to use the string functions to fix this

-- typewriterFixMe

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

    s = "Hello World! This is going to be a very long sentence, and I hope you understand. Please understand! Do not be alarmed. This is an example sentence. Supercalifragilisticexpealidocious"
    r = 25 --speed of typing

end

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

    -- This sets the line thickness
    strokeWidth(5)
    textWrapWidth(500)
    fontSize(20)
    textAlign(LEFT)
    textMode(CORNER)
    -- Do your drawing here
    typewriter(s, r, 100, 300, SOUND_HIT, 12)
end

function touched(t)
    typewriter_removelabel(s, r)
end
--[[
--Made for Codea, initially for Love2d
--THANKS azhukar for giving me the initial code that i based this on
--CODEA VERSION (love version coming soon) (soon became maybe never?)


Usage.
You can and should call typewriter from the draw function.
What it does is slowly types out text to the screen using text()
--The first parameter is the string to type
--the second parameter controls the speed of typing
--the third and fourth parameters set the drawing location
--the fifth parameter is a string to play a sound when typing a character
--]]


local function fixLineWrapping()
    -- i noticed that when dripping long words sometimes they wouldn't wrap. i.e. the first few characters draw on the first line, then when the word is too long it jumps to the second line. I'm not sure how to fix it


end

local __drip = {}   --cache the dripped text

local function dripText(text,charactersPerSecond,startTime,beep,label)
    --In Love2d we use love.timer.getTime() instead of ElapsedTime

    local c = charactersPerSecond   --the rate of speaking
    local d = ElapsedTime - startTime   --time since the first call to typewriter
    local n = math.floor (d * c)  --the number of characters typed
    local s = __drip[label][1]      --the string that is typed
    if n > #s then
        local x = s:sub(#s,#s)
        if not x:match('%s') then sound(beep) end   --play a sound
        return text:sub(1, n)

    end
    return nil
end



--the typewriter function can write text like a typewriter onto your screen
--it's meant to be placed into the draw function
--it takes the following parameters
--The first parameter is the string to type
--the second parameter controls the speed of typing, think of it as characters per second
--the third and fourth parameters set the drawing location
--the fifth parameter is a string for the sound when typing a character
--the sixth parameter specifies line height
--=========================
--set fill, wrapwidth, etc before you call typewriter
--you should use: textMode( CORNER )
--=========================
--if using LOVE2D here's a quick glossary of codea text() functions
--fill(r,g,b,a) sets the text color; 
--wrapWidth(int) causes text to wrap onto the next line; 
--textAlign(LEFT|CENTER|RIGHT) sets the alignment of text
--and is generally used with textWrapWidth;
------------------
--textMode( CORNER|CENTER ) sets the origin of text(string,x,y)
----corner: x,y specifies the lower left corner 
----center: x,y specifies the center
--sound(b) (where b is a string) plays a sound (i.e. sound('Documents:Beep') )
--=========================
function typewriter(s, r, x, y, b, lh)
    local StartTime
    if type(s) == 'table' then 
        typewriter_table(1,s,r,x,y,b,lh)
    elseif type(s) == 'string' then 
        typewriter_string(s,r,x,y,b,lh) 
    end
end

function typewriter_string(s, r, x, y, b, lh)
    local StartTime
    local label = table.concat({s,r}, ', ')
    if not __drip[label] then
        StartTime = ElapsedTime
        --in love2d use StartTime = love.timer.getTime()
        __drip[label] = {[1]='', [2]=StartTime} 
    elseif s == __drip[label][1] then
        local w,h = textSize(s)
        y = y - (h / lh - 1) * lh
        textAlign(LEFT)

        text(s,x,y)
        -- RETURNS NEXT LINE Y POSITION WHEN FINISHED
        -- SEE TYPEWRITER_TABLE
        return y - lh   
    else
        local start = __drip[label][2]
        __drip[label][1] = dripText(s, r, start, b, label) or __drip[label][1]
        local str = __drip[label][1]
        local w,h = textSize(str)
        y = y - (h / lh - 1) * lh
        textAlign(LEFT)

        text(str,x,y)
    end
end

-- iterate over table of strings
function typewriter_table(i, t, r, x, y, b, lh)
    local nextY = typewriter_string(t[i], r, x, y, b, lh)
    if nextY and t[i+1] then 
        typewriter_table(i+1, t, r, x, nextY, b, lh)
    end
end

function typewriter_removelabel(s,r)
    if type(s)=='table' then
        for i,v in ipairs(s) do
            __drip[table.concat({v,r}, ', ')] = nil
        end
    elseif type(s)=='string' then 
        local label = table.concat({s,r}, ', ')
        __drip[label] = nil
    end

end

Comments

  • dave1707dave1707 Mod
    Posts: 6,935

    @xThomas I don’t see anything wrong with seeing some characters starting to show at the end of the line and then jumping to the next line. The only way to fix that would be not to show the letters until you determine that the word would fit. I think that would look worse because you wouldn’t see the letters as they’re typed, but only the whole word all at once.

Sign In or Register to comment.