May-28-2022, 07:09 PM
Another offering. This one is a little reflex game. Again, showing how expanding the challenge to 100 lines provides a lot more flexibility using GUI objects while keeping the code easy to follow.
#Stop it! Originally developed for Smallbasic in May 2016, converted to Python in May of 2022. (C)opyright codingCat AKA Matthew L. Parets -- Released under Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. #Hit the space bar to stop the ball. The closer you get to the middle ofthe basket, the higher your score. import tkinter, time #functions and events ---------------------------------------------------------------------------------------------------- def SpeedIncrease(): #At the end of every frame, decrease frame size and speed up global speed,framelength,framestart if time.time_ns() // 1000000 - framestart > framelength: #Have we reached the end of the frame? if framelength > 1: #Frames can only get so short, stop at 1 millisecond speed = speed * 2 #Double the speed if speed > 0.7: #Not too fast. speed = 0.7 #Set to half a pixel per frame framelength = framelength * 0.80 #Decrease the length of frame by 20% framestart = time.time_ns() // 1000000 #Start the next frame. def DisplayFinishfinishMsg(): #Display the win/lose message canvas.create_line(ballx,0,ballx,winhei, fill="#dddddd", width=2, dash=(2, 1,1,1)) #highlight the location of the of the ball canvas.create_line(ballx+ballsize,0,ballx+ballsize,winhei, fill="#dddddd", width=2, dash=(2, 1,1,1)) scoreMsg = 0 finishMsg = "" if ballx + ballsize < targetX: #Stopped before the basket finishMsg = "Too Soon!" scoreMsg = 0 elif ballx > targetX + targetWidth: #Stopped after the basic finishMsg = "Missed it!" scoreMsg = 0 elif ballx < targetX and ballx + ballsize > targetX: #Stoped just inside finishMsg = "Just Made it!" scoreMsg = round(1000 * (ballsize - (targetX - ballx))) elif ballx + ballsize > targetX + targetWidth and ballx < targetX + targetWidth: finishMsg= "Almost Missed it!" #Stopped almost outside scoreMsg = round(1000 * (ballsize - ((ballx + ballsize) - (targetX + targetWidth)))) else: #Nailed it - fully inside finishMsg = "Bulls Eye" scoreMsg = chr(8734) scoreMsg = "Score = " + str(scoreMsg) canvas.create_text(4,25, text = finishMsg, anchor="nw", font=("Tahoma",65,"bold","italic"),fill="#333333") canvas.create_text(0,25, text = finishMsg, anchor="nw", font=("Tahoma",65,"bold","italic"),fill="green") canvas.create_text(4,winhei - 25, text = scoreMsg, anchor="sw", font=("Tahoma",65,"bold","italic"),fill="#333333") canvas.create_text(0,winhei - 25, text = scoreMsg, anchor="sw", font=("Tahoma",65,"bold","italic"),fill="blue") #** Key press event - Update the last key variable def onKeyDown(event): global lastkey lastkey = event.keysym #** Shut down event. Called when window is closed. Having this event prevents the window itself from closing #** until the main processing loop stops, and the destroy function is called. def onShutdown(): global gameon gameon = False #Initial setup --------------------------------------------------------------------------------------------------------------- winwid, winhei = 800,500 #The size of the window win = tkinter.Tk() #build the window win.title("Stop it") #give the game a name win.geometry(f"{winwid}x{winhei}+0+0") #set the size and location of window -- looking for a super power? Google "python fstrings" lastkey="" #the last key pressed, set in the key down event ballsize = 50 #size of player ballx, bally = 0,winhei / 2 - ballsize/2 #location of player (centered to the left) targetSize = ballsize * 1.25 #the size and location of the target targetWidth = targetSize * 1.125 targetX = winwid - targetSize * 2.5 targetY = winhei/2 - targetSize/2 speed = 0.00075 #player speed at the start of the game (very slow) framelength = 500 #length of the frame at start of game (very long) gameon = True #game is on until the window is closed canvas = tkinter.Canvas(win,bg="#ffffcc",width=800, height=600) #add a work area to the window canvas.pack(expand=True) ball= canvas.create_oval(ballx,bally, ballx+ballsize,bally+ballsize, outline="#bb0000", fill="red", width=3) #add the player and target targetX + (targetWidth / 2) - (ballsize / 2) target = canvas.create_rectangle(targetX,targetY, targetX+targetWidth,targetY+targetSize, outline="#0000bb", fill="blue", width=3) win.bind("<KeyPress>", onKeyDown) win.protocol("WM_DELETE_WINDOW",onShutdown) # Main processing / Game loop. Repeats once per frame. --------------------------------------------------------------------- framestart = time.time_ns() // 1000000 #current millisecond count. Why note nanoseconds? Why divide by 1000000? Because no one wants to deal in billions of a second secstart = time.time_ns() // 1000000 while gameon and lastkey != "space" and ballx < winwid - ballsize: #continue until - the window is close, the space bar is pressed, or the ball reaches the far end of the screen ballx = ballx + speed #update the balls location canvas.coords(ball, ballx,bally, ballx+ballsize,bally+ballsize) #move ball to new location SpeedIncrease() #increase the speed, ball goes a little faster each round win.update() #update the graphics in the window (does not happen automatically) DisplayFinishfinishMsg() while gameon: #hold the window open until the player closes it win.update() time.sleep(0.25) #** Main processing loop is done, close the window win.destroy()