{"id":31,"date":"2026-04-17T19:25:15","date_gmt":"2026-04-17T19:25:15","guid":{"rendered":"https:\/\/theroyalscode.com\/students\/h_yusko\/?p=31"},"modified":"2026-04-17T19:25:15","modified_gmt":"2026-04-17T19:25:15","slug":"free-friday-4-17-26","status":"publish","type":"post","link":"https:\/\/theroyalscode.com\/students\/h_yusko\/2026\/04\/17\/free-friday-4-17-26\/","title":{"rendered":"Free Friday 4\/17\/26"},"content":{"rendered":"\n<p>This Free Friday, the first half of class was a fun break from the usual routine \u2014 we tried a variety of hot sauces with chicken nuggets, which made for a pretty entertaining time.<\/p>\n\n\n\n<p>For the other half of class, I watched YouTube and played Nitro Type, and then I finished a turtle game.<\/p>\n\n\n\n<p>This is The Code:<\/p>\n\n\n\n<p>import turtle<\/p>\n\n\n\n<p>import colorsys<\/p>\n\n\n\n<p>import random<\/p>\n\n\n\n<p>import math<\/p>\n\n\n\n<p>screen = turtle.Screen()<\/p>\n\n\n\n<p>screen.setup(1000,1000)<\/p>\n\n\n\n<p>screen.title(\u201cSynchronized Fireflies &#8211; PythonTurtle.Academy\u201d)<\/p>\n\n\n\n<p>turtle.hideturtle()<\/p>\n\n\n\n<p>turtle.speed(0)<\/p>\n\n\n\n<p>turtle.tracer(0,0)<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">Constants<\/h1>\n\n\n\n<p>H_YELLOWGREEN = 0.22 # constant: hue value of yellow green color.<\/p>\n\n\n\n<p>V_DARK = 0.1 # constant: brightness value of initial dark state<\/p>\n\n\n\n<p>V_BRIGHT = 1 # constant: brightness value of the brightest state<\/p>\n\n\n\n<p>FPS = 30 # constant: refresh about 30 times per second<\/p>\n\n\n\n<p>TIMER_VALUE = 1000\/\/FPS # the timer value in milliseconds for timer events<\/p>\n\n\n\n<p>CYCLE = 5 # costant: 5 second cycle for firefly to light up<\/p>\n\n\n\n<p>LIGHTUP_TIME = 1 # constant: 1 second light up and dim<\/p>\n\n\n\n<p>SPEED = 20 # 100 units per second<\/p>\n\n\n\n<p>CLOSE_ENOUGH = 16 # if distance squared to target is less than 16, then it is close enough.<\/p>\n\n\n\n<p># make sure that this number is greater than SPEED\/FPS squared<\/p>\n\n\n\n<p>N = 300 # Number of fireflies<\/p>\n\n\n\n<p>PHASE_DELTA = 0.01 # increment of phase when saw a neighbor fires up<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">Variables<\/h1>\n\n\n\n<p>fireflies = [] # list of firefly turtles<\/p>\n\n\n\n<p>v = [] # list of brightness values<\/p>\n\n\n\n<p>phase = [] # list of phases<\/p>\n\n\n\n<p>current_xpos = [] # list of current x coordinate<\/p>\n\n\n\n<p>current_ypos = [] # list of current y coordinate<\/p>\n\n\n\n<p>target_xpos = [] # list of target x coordinate<\/p>\n\n\n\n<p>target_ypos = [] # list of raget y coordinate<\/p>\n\n\n\n<p>def initialze_fireflies():<\/p>\n\n\n\n<p>for i in range(N):<\/p>\n\n\n\n<p>fireflies.append(turtle.Turtle()) # Add a turtle to the firefly turtle list<\/p>\n\n\n\n<p>v.append(V_DARK) # set them DARK first. The update function will update it to the correct value<\/p>\n\n\n\n<p>phase.append(random.uniform(0,CYCLE)) # phase is random from 0 to CYCLE<\/p>\n\n\n\n<p>current_xpos.append(random.uniform(-500,500)) # Let them go anywhere on screen<\/p>\n\n\n\n<p>current_ypos.append(random.uniform(-500,500))<\/p>\n\n\n\n<p>target_xpos.append(random.uniform(-500,500))<\/p>\n\n\n\n<p>target_ypos.append(random.uniform(-500,500))<\/p>\n\n\n\n<p>for firefly in fireflies: # initialize these turtles<\/p>\n\n\n\n<p>firefly.hideturtle()<\/p>\n\n\n\n<p>firefly.up()<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">this function computes brightness based on phase<\/h1>\n\n\n\n<p>def compute_brightness(phase):<\/p>\n\n\n\n<p>if phase &lt; CYCLE-LIGHTUP_TIME:<\/p>\n\n\n\n<p>temp = V_DARK # dormant period<\/p>\n\n\n\n<p>elif phase &lt; CYCLE-LIGHTUP_TIME\/2: # gradually (linearly) lighting up period<\/p>\n\n\n\n<p>temp = V_DARK + (V_BRIGHT-V_DARK)*(phase-(CYCLE-LIGHTUP_TIME))\/(LIGHTUP_TIME\/2)<\/p>\n\n\n\n<p>else: # gradually (linearly) dimming period<\/p>\n\n\n\n<p>temp = V_BRIGHT &#8211; (V_BRIGHT-V_DARK)*(phase-(CYCLE-LIGHTUP_TIME\/2))\/(LIGHTUP_TIME\/2)<\/p>\n\n\n\n<p>return temp<\/p>\n\n\n\n<p>def update_neibors(k):<\/p>\n\n\n\n<p>global phase<\/p>\n\n\n\n<p>for i in range(N):<\/p>\n\n\n\n<p>if i == k or phase[i] == CYCLE-LIGHTUP_TIME\/2: # don\u2019t update phase for itself or fireflies at peak<\/p>\n\n\n\n<p>continue<\/p>\n\n\n\n<p>if phase[i] &lt; CYCLE-LIGHTUP_TIME\/2: # before peak<\/p>\n\n\n\n<p>phase[i] = min(CYCLE-LIGHTUP_TIME\/2,phase[i]+PHASE_DELTA) # make sure don\u2019t pass the peak after incrementing phase<\/p>\n\n\n\n<p>else: # after peak<\/p>\n\n\n\n<p>phase[i] += PHASE_DELTA # increment phase by delta<\/p>\n\n\n\n<p>if phase[i] &gt; CYCLE: # phase passed CYCLE<\/p>\n\n\n\n<p>phase[i] -= CYCLE # make sure stays within CYCLE<\/p>\n\n\n\n<p>v[i] = compute_brightness(phase[i]) # with new phase, update the brightness<\/p>\n\n\n\n<p>def update_brightness():<\/p>\n\n\n\n<p>global phase,v<\/p>\n\n\n\n<p>for i in range(N):<\/p>\n\n\n\n<p>phase[i] += TIMER_VALUE\/1000 # increase the phase by time passed<\/p>\n\n\n\n<p>if phase[i] &gt; CYCLE: # phase passed CYCLE<\/p>\n\n\n\n<p>phase[i] -= CYCLE # make sure phase stays within CYCLE<\/p>\n\n\n\n<p>if phase[i] &gt; CYCLE-LIGHTUP_TIME\/2 and phase[i] &#8211; TIMER_VALUE\/1000 &lt; CYCLE-LIGHTUP_TIME\/2: # skipped peak<\/p>\n\n\n\n<p>phase[i] = CYCLE-LIGHTUP_TIME\/2 #cheat here: adjust phase to peak value<\/p>\n\n\n\n<p>v[i] = compute_brightness(phase[i]) # compute the brightness based on phase<\/p>\n\n\n\n<p>for i in range(N): # update other fireflies<\/p>\n\n\n\n<p>if phase[i] == CYCLE-LIGHTUP_TIME\/2: # only update when firefly is in peak<\/p>\n\n\n\n<p>update_neibors(i) # try to influence other fireflies<\/p>\n\n\n\n<p>def update_position():<\/p>\n\n\n\n<p>global current_xpos,current_ypos,target_xpos,target_ypos<\/p>\n\n\n\n<p>for i in range(N):<\/p>\n\n\n\n<p># move towards target SPEED\/FPS steps<\/p>\n\n\n\n<p># figure out angle to target first<\/p>\n\n\n\n<p>angle_to_target = math.atan2(target_ypos[i]-current_ypos[i],target_xpos[i]-current_xpos[i])<\/p>\n\n\n\n<p># compute changes to current position based on the angle and distance to move per 1\/FPS second.<\/p>\n\n\n\n<p>current_xpos[i] += SPEED\/FPS*math.cos(angle_to_target)<\/p>\n\n\n\n<p>current_ypos[i] += SPEED\/FPS*math.sin(angle_to_target)<\/p>\n\n\n\n<p># check to see if close enough to target.<\/p>\n\n\n\n<p>dist_to_target_squared = (current_xpos[i]-target_xpos[i])**2 + (current_ypos[i]-target_ypos[i])**2<\/p>\n\n\n\n<p>if dist_to_target_squared &lt; CLOSE_ENOUGH: # close enough, set new target<\/p>\n\n\n\n<p>target_xpos[i] = random.randint(-500,500) # target x coordinate, random location<\/p>\n\n\n\n<p>target_ypos[i] = random.randint(-500,500) # target y coordinate, random location<\/p>\n\n\n\n<p>def update_states():<\/p>\n\n\n\n<p>global should_draw<\/p>\n\n\n\n<p>update_brightness()<\/p>\n\n\n\n<p>update_position()<\/p>\n\n\n\n<p>should_draw = True<\/p>\n\n\n\n<p>screen.ontimer(update_states,TIMER_VALUE)<\/p>\n\n\n\n<p>def draw():<\/p>\n\n\n\n<p>global v,fireflies,should_draw,current_xpos,current_ypos<\/p>\n\n\n\n<p>if should_draw == False: # There is no change. Don\u2019t draw and return immediately<\/p>\n\n\n\n<p>return<\/p>\n\n\n\n<p>for i in range(N):<\/p>\n\n\n\n<p>fireflies[i].clear() # clear the current drawing<\/p>\n\n\n\n<p>color = colorsys.hsv_to_rgb(H_YELLOWGREEN,1,v[i]) # use colorsys to convert HSV to RGB color<\/p>\n\n\n\n<p>fireflies[i].color(color)<\/p>\n\n\n\n<p>fireflies[i].goto(current_xpos[i],current_ypos[i])<\/p>\n\n\n\n<p>fireflies[i].dot(10)<\/p>\n\n\n\n<p>should_draw = False # just finished drawing, set should_draw to False<\/p>\n\n\n\n<p>screen.bgcolor(\u2018black\u2019)<\/p>\n\n\n\n<p>initialze_fireflies()<\/p>\n\n\n\n<p>update_states()<\/p>\n\n\n\n<p>while True:<\/p>\n\n\n\n<p>draw() # draw forever<\/p>\n\n\n\n<p>screen.update()<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This Free Friday, the first half of class was a fun break from the usual routine \u2014 we tried a variety of hot sauces with chicken nuggets, which made for a pretty entertaining time. For the other half of class, I watched YouTube and played Nitro Type, and then I finished a turtle game. This [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-31","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/theroyalscode.com\/students\/h_yusko\/wp-json\/wp\/v2\/posts\/31","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/theroyalscode.com\/students\/h_yusko\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/theroyalscode.com\/students\/h_yusko\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/theroyalscode.com\/students\/h_yusko\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/theroyalscode.com\/students\/h_yusko\/wp-json\/wp\/v2\/comments?post=31"}],"version-history":[{"count":1,"href":"https:\/\/theroyalscode.com\/students\/h_yusko\/wp-json\/wp\/v2\/posts\/31\/revisions"}],"predecessor-version":[{"id":32,"href":"https:\/\/theroyalscode.com\/students\/h_yusko\/wp-json\/wp\/v2\/posts\/31\/revisions\/32"}],"wp:attachment":[{"href":"https:\/\/theroyalscode.com\/students\/h_yusko\/wp-json\/wp\/v2\/media?parent=31"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/theroyalscode.com\/students\/h_yusko\/wp-json\/wp\/v2\/categories?post=31"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/theroyalscode.com\/students\/h_yusko\/wp-json\/wp\/v2\/tags?post=31"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}