Howdy, Stranger!

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

Anagram viewer

edited April 2014 in Code Sharing Posts: 3

What do you think about the following program? Sorry for the bad English and the German comments, but i am German ;)
Touch on the screen to see the animation. You can change all parameters between this ---------- lines -----------


--# Main -- Anagram displayMode(FULLSCREEN) function setup() -------------------- wordList = {"A cool (not-only) anagram program","it moves and fades letters","to animate the change of two or more words","by David Knothe","and again:"} repeating = true In,Out,InOut,OutIn = 1,2,3,4 fade = {power = 2, effect = In, duration = 2, delay = 1} effectOnlyForFade = true fontSize(40) -------------------- actWord,actTime,startPosition,startLetter,endPosition,endLetter = prepareForNext(0,repeating,wordList) isAnimating = false hasAnimated = false end function draw() background(0) textMode(CORNER) -- Animation: if isAnimating then actTime = actTime + DeltaTime/fade.duration elseif hasAnimated then actTime = fade.duration + fade.delay end t = math.min(1,math.max(0,(actTime-fade.delay)/fade.duration)) -- 0 <= t <= 1 if fade.effect == In then a = t^fade.power elseif fade.effect == Out then a = t^(1/fade.power) elseif fade.effect == InOut then a = ( math.abs(2*t-1)^(1/fade.power)*sign(2*t-1) )/2+.5 elseif fade.effect == OutIn then a = ( math.abs(2*t-1)^(fade.power)*sign(2*t-1) )/2+.5 else a = t end translate(WIDTH/2,HEIGHT/2-fontSize()/2) for i in pairs(startPosition) do if effectOnlyForFade then -- Position linear position = startPosition[i]*(1-t)+endPosition[i]*t else position = startPosition[i]*(1-a)+endPosition[i]*a end if startLetter[i] == endLetter[i] then fill(255) text(startLetter[i],position,0) else fill(255,255*(1-a)) text(startLetter[i],position,0) fill(255,255*a) text(endLetter[i],position,0) end end if t == 1 then if actWord == #wordList-1 and not repeating then -- Zu Ende isAnimating = false hasAnimated = true else actWord,actTime,startPosition,startLetter,endPosition,endLetter = prepareForNext(actWord,repeating,wordList) end end end function prepareForNext(place,repeating,wordList) place = place + 1 -- Nächstes Wort if place%#wordList == 0 then startWord = wordList[#wordList] else startWord = wordList[place%#wordList] end endWord = wordList[place%#wordList+1] time = 0 startPlace,startLetter,endPlace,endLetter = createMoveLists(startWord,endWord) -- Listennamen müssten eigentlich im Plural sein, aber so liest es sich besser als bspw. "Position an der Stelle i" startWordPositions = getPositionsOnScreen(startWord) endWordPositions = getPositionsOnScreen(endWord) startPosition = getElementsInListWithIndicesFromList(startWordPositions,startPlace) endPosition = getElementsInListWithIndicesFromList(endWordPositions,endPlace) return place,time,startPosition,startLetter,endPosition,endLetter end function createMoveLists(startWord,endWord) -- Listen, die zurückgegeben werden: startPlace_ = {} startLetter_ = {} endPlace_ = {} endLetter_ = {} startLetterIsUsed = {} -- i.tes Element gibt an, ob der i.te Buchstabe im Startwort bereits verwendet wurde endLetterIsUsed = {} for i=1,string.len(startWord) do -- Jeden Buchstaben im Startwort analysieren startLetter = string.sub(startWord,i,i) possibleFirstChoiceEndLetters = {} -- Die für diesen Buchstaben möglichen Endplätze possibleSecondChoiceEndLetters = {} -- Zweite Wahl: Buchstabe ändert Großschreibung for j=1,string.len(endWord) do -- Schauen, welcher Buchstabe im Endwort ähnlich ist endLetter = string.sub(endWord,j,j) if startLetter == endLetter and not endLetterIsUsed[j] then table.insert(possibleFirstChoiceEndLetters,j) elseif string.lower(startLetter) == string.lower(endLetter) and not endLetterIsUsed[j] then table.insert(possibleSecondChoiceEndLetters,j) end end randomEndPlace = nil if #possibleFirstChoiceEndLetters > 0 then -- Zufälligen Endplatz für Buchstaben auswählen randomEndPlace = possibleFirstChoiceEndLetters[math.random(#possibleFirstChoiceEndLetters)] elseif #possibleSecondChoiceEndLetters > 0 then randomEndPlace = possibleSecondChoiceEndLetters[math.random(#possibleSecondChoiceEndLetters)] end if randomEndPlace then startLetterIsUsed[i] = true endLetterIsUsed[randomEndPlace] = true table.insert(startPlace_,i) table.insert(endPlace_,randomEndPlace) table.insert(startLetter_,startLetter) table.insert(endLetter_,string.sub(endWord,randomEndPlace,randomEndPlace)) end end notUsedStartLetters = {} -- Schauen, ob es nicht benutzte Buchstaben gibt notUsedEndLetters = {} for i=1,string.len(startWord) do if not startLetterIsUsed[i] then table.insert(notUsedStartLetters,i) end end for i=1,string.len(endWord) do if not endLetterIsUsed[i] then table.insert(notUsedEndLetters,i) end end if #notUsedStartLetters >= #notUsedEndLetters then -- Jedem Endbuchstaben einen Startbuchstaben zuordnen for _,endPlace in pairs(notUsedEndLetters) do randomStartPlaceIndex = math.random(#notUsedStartLetters) startPlace = notUsedStartLetters[randomStartPlaceIndex] table.insert(startPlace_,startPlace) table.insert(endPlace_,endPlace) table.insert(startLetter_,string.sub(startWord,startPlace,startPlace)) table.insert(endLetter_,string.sub(endWord,endPlace,endPlace)) table.remove(notUsedStartLetters,randomStartPlaceIndex) end for _,startPlace in pairs(notUsedStartLetters) do -- Immer noch übrig gebliebene Startbuchstaben table.insert(startPlace_,startPlace) table.insert(endPlace_,math.random(string.len(endWord))) table.insert(startLetter_,string.sub(startWord,startPlace,startPlace)) table.insert(endLetter_,"") end else -- Jedem Startbuchstaben einen Endbuchstaben zuordnen for _,startPlace in pairs(notUsedStartLetters) do randomEndPlaceIndex = math.random(#notUsedEndLetters) endPlace = notUsedEndLetters[randomEndPlaceIndex] table.insert(startPlace_,startPlace) table.insert(endPlace_,endPlace) table.insert(startLetter_,string.sub(startWord,startPlace,startPlace)) table.insert(endLetter_,string.sub(endWord,endPlace,endPlace)) table.remove(notUsedEndLetters,randomEndPlaceIndex) end for _,endPlace in pairs(notUsedEndLetters) do -- Immer noch übrig gebliebene Endbuchstaben table.insert(startPlace_,math.random(string.len(startWord))) table.insert(endPlace_,endPlace) table.insert(startLetter_,"") table.insert(endLetter_,string.sub(endWord,endPlace,endPlace)) end end return startPlace_,startLetter_,endPlace_,endLetter_ end function getPositionsOnScreen(word) posList = {0} for i=1,string.len(word) do char = string.sub(word,i,i) posList[i+1] = posList[i]+textSize(char) -- Position des nächsten Buchstabens anhand der Größe des aktuellen bestimmen end shift = posList[#posList]/2 for i in pairs(posList) do posList[i] = posList[i] - shift end return posList end function getElementsInListWithIndicesFromList(valueList,positionsList) endList = {} for i,p in pairs(positionsList) do endList[i] = valueList[p] end return endList end function sign(x) if x == x and x ~= 0 then return x/math.abs(x) end return 0 end function touched(touch) if not hasAnimated then isAnimating = true end end

Comments

  • Jmv38Jmv38 Mod
    Posts: 3,297

    @someone very nice looking animation. Great job! Welcome on board.

  • Posts: 211

    @someone, I'm testing your code. I can´t put some letter like 'ç' or 'á' :(

  • Posts: 78

    @someone It is very suitable for animated display text. Thanks for sharing. :)

  • edited April 2014 Posts: 3

    @erickyamato Yes I know but I think thats not my fault - Codea doesn't support those letters.

    @matox @Jmv38 Thank you! :)

  • edited April 2014 Posts: 211

    @Someone, these letters are very important (to me, because I'm brazilian and portuguese has those letters) :/

    But, this is an amazing code! :)

  • Posts: 2,161

    @Someone Codea does support those letters. The issue is that string.sub works on the byte level, not the character level. Strings are encoded in utf-8 so you need to recognise a utf-8 encoded character and remove a whole one, which can be one or more bytes. My anagram program (which is one of the examples in Codea) contains code to handle utf8 strings.

  • Posts: 3

    @Andrew_Stacey Ok you're right. Sorry for that - If you want you could implement it, but I think I won't do it because it would destroy the shortness of the code ;) @erickyamato

  • Posts: 211

    @Andrew_Stacey I tryied to use some letters on your code, but it happens too :/

  • Posts: 2,161

    @erickyamato That's a very helpful bug report! What letters, what code, and what did you try?

  • Posts: 211

    @Andrew_Stacey I sent you a message!

    I used your code(anagrams) I'm brazilian and here in Brazil, we have some words like 'maçã' = 'apple'.

    I tryied to put those words on Words class

  • Posts: 2,161

    Ah, I remember now. There was a bug with my utf8 code that has since been fixed, but it didn't get backported into the Anagrams code. My latest version works just fine with your test word. It's bundled as part of "Library Base" on Codea Community.

  • edited May 2014 Posts: 211

    @Andrew_Stacey Could you please share the link?

Sign In or Register to comment.