
Floaty Turtle: A Flappy Bird clone in Logo
Floaty Turtle is a simple clone of Flappy Bird written in the Logo programming language that turtleSpaces uses.
Open in the integrated development environment (IDE)
NEWTURTLE "myrtle
TO floaty
;here is yet another example of a relatively complex
;game that can be rather simply implemented in Logo:
;a flappy bird clone!
;to make it work we use two turtles, one is the player
;and the other creates, moves and erases the pipes
;these are two seperate 'workers' or threads
;this procedure kicks off the game, displays a title
;screen, and then manages the player, processing
;input and moving the player appropriately
;the pipemaker turtle and its pipes procedure
;manages the pipes and checks for collisions
;the turtle does not move horizontally,
;instead the pipes do!
reset
cleartext
setbackgroundcolor pick [6 7 14 5 10 11 14 15]
;select a random background color from the given list
noaudiowait
;don't wait for audio to finish playing
setmodel [penup back 7 stamp "myrtle]
;we need to offset Myrtle's actual position more
;toward her center for the purposes of this game
setmodelscale 5
;make myrtle big!
playsound "doodoo
;startup sound
pipemaker:newworker [pipes]
;'kicks off' the pipemaker turtle, who
;creates and moves the pipes
;create the title screen:
penup
randomfillcolor
slideleft 180 forward 5
settypesize 60
pushturtle
;'push' the turtle's state (position etc) on
;to a stack, from which it can be 'popped'
;off later
typeset "Floaty
popturtle
;restore the previously pushed state
back 100
randfc
;short for randomfillcolor
pushturtle
typeset "Turtle
popturtle
bk 10 sr 70
;back and slideright
settypesize 10
randfc
typeset |Press any key to float!|
;title screen complete!
home
dn 90 rt 90
;down and right
make "raise 0
;the :raise container holds the current
;value remaining to float Myrtle upwards
forever [
if loopcount = 1 [say "Ready!]
if loopcount = 16 [say "Set!]
if loopcount = 31 [say "Go!]
;the loopcount is the number of times the forever
;loop has executed. Based on that count, say the
;appropriate ready set go component
if divisorp 100 loopcount [
;every 100 loops pick a random background
setbg pick [6 7 14 5 10 11 14 15]
;from the given list
]
;setbg short for setbackground
dosleep [50] [
;try to maintain an average of 50ms to do
;the following:
if loopcount > 30 [
;if the loopcount is greater than 30:
if :raise = 0 [
;if the value inside the :raise container
;is 0, then lower the turtle 2.5 turtle-units:
lower 2.5
]
[
;otherwise raise the turtle 2.5 turtle-units
;and decrease the value inside the :raise
;container by 2.5
raise 2.5
make "raise :raise - 2.5
]
if keyp [
;if a key is pressed, play a sound,
;remove the key from the keyboard buffer
;and increase the value of the :raise
;container by 20:
playsound "air
clearchar
make "raise :raise + 20
]
clean
;remove the turtle's 'track' -- it's not
;drawing or creating anything so we don't
;need to have it piling up
]
]
]
END
NEWTURTLE "pipemaker
TO pipes
;the pipemaker turtle's job is to
;create the pipes, shift them to the left
;and check if they've hit the turtle
clearscreen
noaudiowait
penup
home
slideright 250
back 120
up 90
;position the turtle appropriately for
;creating the pipes offscreen to the right
begintag "move
endtag
;this tag is used to shift the pipes,
;by replacing its contents with an ever-
;increasing slideleft directive
make "height 100
;this is the starting height of the pipes
make "heights [0 0 0 0 0]
;initialize an 'zeroes' list of pipe heights
make "score 0
make "count 0
;initialize the score and the pipe count
settypesize 20
;set the type size. Type is the text you
;create inside the 3D world
forever [
;do this forever:
sleep [50]
;try to do this stuff in an average of
;50ms -- less or more as needed to keep
;that average:
if divisorp 20 loopcount [
;every 20 loops:
inc "count
;increase the contents of the :count container
;by one
if loopcount > 60 [
;if the loopcount is greater than 60:
playsound "clang
inc "score
say :score
;make a sound, increment :score and say it
]
slideright 100
begintag loopcount
;create a new 'tag' for the pipe
;so we can remove it after it passes the
;left side of the screen
randomfillshade
;select a random fill shade
make "col 1 + random 5
;select a random number and put it in :col
setfillcolor item :col [12 9 7 6 11 14 10 13]
;set that color based on :col's index in the
;provided list
make "height :height + (-60 + random 120)
;increase or decrease :height based on a
;random number
if :height < 20 [make "height 30 + random 20] if :height > 120 [make "height 110 - random 20]
;if too high or low, pick a new value higher
;or lower as needed
queue :height "heights
;add the new height to the list of heights
;create the lower pipe:
cylinder 20 :height 50
lower :height
setfillcolor item :col [4 8 6 2 1 12 5 3]
;select the complementary color for the pipe
cylinder 25 20 50
lower 50
;type the pipe number:
down 90 right 90 back 10
if :count > 9 [bk 10]
inscribe :count
if :count > 9 [fd 10]
forward 10 left 90 up 90
;if gameplay is too slow, comment out
;the above five lines
;create the upper pipe:
lower 50
;remember, the turtle is upside down!
cylinder 25 20 50
lower 20
setfillcolor item :col [12 9 7 6 11 14 10 13]
cylinder 20 120 - ypos 50
raise :height + 120
endtag
;close the pipe 'tag'
if loopcount > 119 [erasetag loopcount - 100]
;erase the pipe that has left the screen
ignore pop "heights
;remove its height from the :heights container
;and just throw it away (ignore it)
]
if loopcount > 60 [
;check for crash:
if (or
myrtle:ypos > (-120 + (90 + item 3 :heights))
myrtle:ypos < (-120 + (20 + item 3 :heights))
;the third item in the :heights list is the
;height of the pipe around where the turtle
;is, so we can use that to see if we've hit
;anything
) [
(print |Crash! Final Score: | :score)
print |Press flag icon to play again!|
calm "myrtle
myrtle:run [setfillcolor 1 icosphere 30]
;red ball
audiowait
playsound "crack
playsound "aw
myrtle:clean
;gets rid of the red ball
noaudiowait
playsound "fall
say |too bad|
myrtle:repeat 90 [
forward 3 lower 3 wait 1
]
;fall to the ground
audiowait
playsound "crash
finish
;that's all folks
]
]
replacetag "move [slideleft loopcount * 5]
;increase the value of the slideleft
;command in the move tag, shifting the
;pipes to the left
]
;and that's it! Not really much code, is it?
END

