import random from turtle import * # This creates the main screen where the game is shown screen = Screen() # The player’s car turtle player = Turtle() # A list that will store all AI cars aiCars = [] # A list that holds the white side markers on the track sideMarkers = [] # Turtles used only for drawing text on the screen scorePen = Turtle() commentPen = Turtle() hudPen = Turtle() countdownPen = Turtle() # Game state flags gameOver = False # Becomes True when the player crashes raceStarted = False # Becomes True after the countdown ends # Movement and boost flags (controlled by key presses) moveLeft = False moveRight = False boost = False # Speed values speed = 12 # Current speed of the game baseSpeed = 12 # Normal speed without boost # Total distance travelled by the player distance = 0 # Track size settings trackWidth = 300 trackHeight = 600 markerSpacing = 200 # Prevents commentary text from appearing too often commentCooldown = 0 # These are fun commentary messages shown during exciting moments HYPE_COMMENTS = [ "Woo hoo!", "Yeah!", "Nice move!", "Smooth driving!", "Brilliant!", "This is racing!", ] # Messages shown when the player narrowly avoids another car CLOSE_CALL_COMMENTS = [ "That was close!", "Brave move!", "Close call!", "Late on the brakes!", "Nearly clipped him!", ] # Messages shown when boost is active BOOST_COMMENTS = [ "Full throttle!", "He's flying!", "Foot to the floor!", "Maximum attack!", ] # Sets up the game window, background color, and loads car images def setupScreen(): screen.setup(600, 600) screen.title("F1 Dodge Race") screen.bgcolor("forest green") screen.tracer(0) screen.addshape("player.gif") screen.addshape("ai.gif") # Draws the racing track, the white borders, and the moving side markers def drawTrack(): track = Turtle() track.hideturtle() track.penup() track.goto(-trackWidth // 2, -trackHeight // 2) track.color("dim gray") track.begin_fill() for _ in range(2): track.forward(trackWidth) track.left(90) track.forward(trackHeight) track.left(90) track.end_fill() # Draws the left and right white borders of the track border = Turtle() border.hideturtle() border.penup() border.width(10) border.color("white") for x in (-trackWidth // 2, trackWidth // 2): border.goto(x, -trackHeight // 2) border.pendown() border.setheading(90) border.forward(trackHeight) border.penup() # Creates small white markers that move downward to fake road movement for i in range(-trackHeight // 2, trackHeight // 2 + markerSpacing, markerSpacing): for side in (-1, 1): marker = Turtle() marker.hideturtle() marker.penup() marker.color("white") marker.shape("square") marker.shapesize(stretch_wid=0.3, stretch_len=1.5) marker.goto(side * (trackWidth // 2 - 15), i) marker.showturtle() sideMarkers.append(marker) # Moves the side markers down the screen to make the track feel alive def scrollSideMarkers(): for marker in sideMarkers: y = marker.ycor() - speed if y < -trackHeight // 2: y += trackHeight + markerSpacing marker.sety(y) # Sets up the player car at the bottom of the track def setupPlayer(): player.shape("player.gif") player.penup() player.goto(0, -trackHeight // 2 + 50) player.setheading(90) # Creates AI cars and places them randomly on the track def setupAICars(): aiCars.clear() for _ in range(3): car = Turtle() car.shape("ai.gif") car.penup() car.setheading(270) car.goto( random.randint(-trackWidth // 2 + 30, trackWidth // 2 - 30), random.randint(100, trackHeight // 2) ) aiCars.append(car) # These functions turn movement flags on and off when keys are pressed def pressLeft(): global moveLeft moveLeft = True def releaseLeft(): global moveLeft moveLeft = False def pressRight(): global moveRight moveRight = True def releaseRight(): global moveRight moveRight = False def pressBoost(): global boost boost = True def releaseBoost(): global boost boost = False # Moves the player left or right while keeping them on the track def movePlayer(): if moveLeft and player.xcor() > -trackWidth // 2 + 30: player.setx(player.xcor() - 20) if moveRight and player.xcor() < trackWidth // 2 - 30: player.setx(player.xcor() + 20) # Moves AI cars downward and respawns them at the top when they leave the screen def moveWorld(): for car in aiCars: car.sety(car.ycor() - speed) if car.ycor() < -trackHeight // 2: car.goto( random.randint(-trackWidth // 2 + 30, trackWidth // 2 - 30), random.randint(trackHeight // 2, trackHeight) ) # Checks if the player has hit an AI car def checkCollision(): global gameOver for car in aiCars: if player.distance(car) < 40: gameOver = True showComment("CRASH!", "red") # Updates and shows how far the player has driven def updateScore(): global distance distance += speed * 0.03 scorePen.clear() scorePen.penup() scorePen.goto(-290, 260) scorePen.color("white") scorePen.write(f"Distance: {int(distance)} m", font=("Arial", 16, "bold")) # Shows the control instructions in the top-right corner def drawHUD(): hudPen.clear() hudPen.penup() hudPen.color("white") hudPen.goto(160, 260) hudPen.write( "⬅️ ➡️ Move\n⬆️ Boost", align="left", font=("Arial", 12, "normal") ) # Displays a short commentary message on screen for a moment def showComment(message, color="yellow"): global commentCooldown if commentCooldown > 0: return commentCooldown = 30 commentPen.clear() commentPen.penup() commentPen.goto(0, 200) commentPen.color(color) commentPen.write(message, align="center", font=("Arial", 20, "bold")) screen.ontimer(lambda: commentPen.clear(), 1000) # Shows a message when the player nearly crashes but survives def checkCloseCalls(): for car in aiCars: d = player.distance(car) if 40 < d < 65 and random.random() < 0.1: showComment(random.choice(CLOSE_CALL_COMMENTS), "orange") # Randomly shows hype commentary to make the game feel exciting def randomHype(): if random.random() < 0.005: showComment(random.choice(HYPE_COMMENTS), "yellow") # Shows a 3-2-1-GO countdown before the race starts def startCountdown(): countdownPen.hideturtle() countdownPen.penup() countdownPen.color("white") def show(text, color): countdownPen.clear() countdownPen.color(color) countdownPen.goto(0, 0) countdownPen.write(text, align="center", font=("Arial", 48, "bold")) show("3", "red") screen.ontimer(lambda: show("2", "orange"), 800) screen.ontimer(lambda: show("1", "yellow"), 1600) screen.ontimer(lambda: show("GO!", "green"), 2400) screen.ontimer(clearCountdown, 3000) # Clears the countdown and officially starts the race def clearCountdown(): global raceStarted countdownPen.clear() raceStarted = True gameLoop() # The main loop that keeps the game running and updating def gameLoop(): global speed, commentCooldown if not raceStarted: return if commentCooldown > 0: commentCooldown -= 1 if not gameOver: movePlayer() moveWorld() scrollSideMarkers() checkCollision() checkCloseCalls() randomHype() speed = baseSpeed + (10 if boost else 0) if boost and random.random() < 0.05: showComment(random.choice(BOOST_COMMENTS), "cyan") updateScore() drawHUD() screen.update() ontimer(gameLoop, 30) else: showGameOver() # Shows a large GAME OVER message when the player crashes def showGameOver(): pen = Turtle() pen.hideturtle() pen.penup() pen.goto(0, 0) pen.color("red") pen.write("GAME OVER", align="center", font=("Arial", 30, "bold")) # Draws the start screen and waits for the player to click def startScreen(): bg = Turtle() bg.hideturtle() bg.penup() bg.goto(-250, -150) bg.color("dim gray") bg.begin_fill() for _ in range(2): bg.forward(500) bg.left(90) bg.forward(300) bg.left(90) bg.end_fill() leftCar = Turtle() leftCar.hideturtle() leftCar.shape("player.gif") leftCar.penup() leftCar.goto(-180, -20) leftCar.setheading(90) leftCar.showturtle() rightCar = Turtle() rightCar.hideturtle() rightCar.shape("ai.gif") rightCar.penup() rightCar.goto(180, -20) rightCar.setheading(90) rightCar.showturtle() title = Turtle() title.hideturtle() title.penup() title.color("white") title.goto(0, 80) title.write("F1 Dodge Race", align="center", font=("Arial", 32, "bold")) controls = Turtle() controls.hideturtle() controls.penup() controls.color("white") controls.goto(0, -60) controls.write( "⬅️ ➡️ Steer\n⬆️ Boost", align="center", font=("Arial", 18, "normal") ) startText = Turtle() startText.hideturtle() startText.penup() startText.color("yellow") startText.goto(0, -120) startText.write("CLICK TO START", align="center", font=("Arial", 20, "bold")) screen.update() def start(x, y): bg.clear() leftCar.hideturtle() rightCar.hideturtle() title.clear() controls.clear() startText.clear() startGame() screen.onclick(start) # Sets up everything needed for the race and begins the countdown def startGame(): drawTrack() setupPlayer() setupAICars() scorePen.hideturtle() commentPen.hideturtle() hudPen.hideturtle() startCountdown() # This is the main starting point of the whole program def main(): setupScreen() screen.listen() screen.onkeypress(pressLeft, "Left") screen.onkeyrelease(releaseLeft, "Left") screen.onkeypress(pressRight, "Right") screen.onkeyrelease(releaseRight, "Right") screen.onkeypress(pressBoost, "Up") screen.onkeyrelease(releaseBoost, "Up") startScreen() screen.mainloop() main()