0

Iam trying to build a simple road crossing game using python where the player can pick up buffs and got stuck in a trap. If player picks up a buff then car's movement is going to be slowed. if player got stuck on a trap then player will die.

However when trying to summon the buffs and the traps, python assumed that the buffmaker() and trap_maker() methods as a Turtle attribute Thus raising error. What can I do to fix these problems?

player.py

    STARTING_POSITION = (0, -280)
    MOVE_DISTANCE = 10
    FINISH_LINE_Y = 280


class Player(Turtle):
    def __init__(self):
        super().__init__()
        self.shape("classic")
        self.pu()
        self.go_to_start()
        self.setheading(90)
        self.fd(MOVE_DISTANCE)
def move_fd(self):
        self.setheading(90)
        self.fd(MOVE_DISTANCE)

    def move_bk(self):
        self.setheading(90)
        self.bk(MOVE_DISTANCE)

    def move_left(self):
        self.setheading(180)
        self.fd(MOVE_DISTANCE)

    def move_right(self):
        self.setheading(0)
        self.fd(MOVE_DISTANCE)

    def at_finish_line(self):
        if self.ycor() >= 300:
            return True
        else:
            False

    def go_to_start(self):
        self.goto(STARTING_POSITION)```


main.py

import time
from turtle import Screen
from player import Player
from car_manager import CarManager
from scoreboard import Scoreboard
from buff import Buff
from trap import Trap

carmanager = CarManager()
scoreboard = Scoreboard()
player = Player()
screen = Screen()
buff = Buff()
trap = Trap()
screen.setup(width=600, height=600)
screen.tracer(0)
screen.onkeypress(player.move_fd, "w")
screen.onkeypress(player.move_bk, "s")
screen.onkeypress(player.move_left, "a")
screen.onkeypress(player.move_right, "d")
screen.listen()
game_is_on = True

while game_is_on:
    time.sleep(0.1)
    screen.update()
    carmanager.carmaker()
    carmanager.car_move(scoreboard.score, 0)
    for cars in carmanager.cars:
        if player.distance(cars) <= 20:
            game_is_on = False
            scoreboard.gameover()
    if scoreboard.score > 0:
        buff.buffmaker()
    for buff in buff.buffs:
        if player.distance(buff)<20:
            carmanager.car_move(scoreboard.score, 1)
            time.sleep(3)
            carmanager.car_move(scoreboard.score, 0)
    for trap in trap.bombs:
        if player.distance(trap) <= 20:
            game_is_on = False
            scoreboard.gameover()
    if player.at_finish_line():
        player.go_to_start()
        scoreboard.update_points()



screen.exitonclick()


trap.py

import random

class Trap(Turtle):
    def __init__(self):
        super().__init__()
        self.hideturtle()
        self.screen.register_shape("Gifs/bomb.gif")
        self.bombs=[]


    def trap_maker(self):
        trap = Turtle()
        trap.shape("Gifs/bomb.gif")
        trap.pu()
        trap.goto(random.randint(-100, 100), random.randint(-200, 250))
        self.bombs.append(trap)```

buff.py

from turtle import Turtle
import random

class Trap(Turtle):
    def __init__(self):
        super().__init__()
        self.hideturtle()
        self.screen.register_shape("Gifs/stopwatch.gif")
        self.buffs=[]


    def buffmaker(self):
        buff = Turtle()
        buff.shape("Gifs/stopwatch.gif")
        buff.pu()
        buff.goto(random.randint(-100, 100), random.randint(-200, 250))
        self.bombs.append(buff)

carmanager.py

from turtle import Turtle
import random
COLORS = ["red", "orange", "yellow", "green", "blue", "purple"]
STARTING_MOVE_DISTANCE = 2
MOVE_INCREMENT = 2


class CarManager(Turtle):
    def __init__(self):
        super().__init__()
        self.hideturtle()
        self.cars=[]

    def carmaker(self):
        if random.randint(1, 24)==1:
            car = Turtle()
            car.shape("square")
            car.pu()
            car.color(random.choice(COLORS))
            car.setheading(180)
            car.shapesize(1, 2)
            car.goto(300, random.randint(-200, 250))
            self.cars.append(car)

    def car_move(self, multiplier, buff):
        for cars in self.cars:
            cars.fd(STARTING_MOVE_DISTANCE + ((0.5*multiplier)*MOVE_INCREMENT )- (0.25*buff))
  • It's not really a good idea to extend classes you don't own (unless they're expecting you to, which turtle isn't). Turtles have hundreds of methods and are wired into an internal turtle list that gets updated on every tick (if you have tracer on)--lots of opportunity for problems. I suggest using [composition rather than inhertance](https://stackoverflow.com/a/71003069/6243352) in turtle, to avoid a lot of confusion. Also, `while:` is not a good way to run an event loop. Prefer `ontimer`. – ggorlen May 25 '23 at 04:20
  • Where did you define the `buffmaker()` and `carmaker()` methods you're calling? Turtle tries to find them on your class and can't find them, so it tries the super class and can't find them there, either. They're not built into Python's Turtle class, so it's up to you to define them before you call them. – ggorlen May 25 '23 at 04:30
  • I've edited the question to include buff.py and carmanager.py (where buffmaker and carmaker is located). I copied carmaker to make buffmaker and trapmaker. car maker works but buffmaker and trapmaker dont. – Abdurrahman al hakim May 25 '23 at 07:07
  • What doesn't work, specifically--what's the error, if any? `self.bombs.append(buff)` -- I don't see `self.bombs` defined anywhere in `buff.py`. There are two `Trap` classes. Same feedback as before, no need to extend `Turtle`. A Car Manager is not a turtle, it's your own concept and has a list of Turtles as a property. – ggorlen May 25 '23 at 13:45

1 Answers1

1

The primary issue I see is that the class Buff isn't defined, by mistake it's also called Trap and appends to bombs instead of buffs:

buff.py

from turtle import Turtle
import random

class Trap(Turtle):
    def __init__(self):
        super().__init__()
        self.hideturtle()
        self.screen.register_shape("Gifs/stopwatch.gif")
        self.buffs=[]

    def buffmaker(self):
        buff = Turtle()
        buff.shape("Gifs/stopwatch.gif")
        buff.pu()
        buff.goto(random.randint(-100, 100), random.randint(-200, 250))
        self.bombs.append(buff)

Looks like a copy and paste error. Also this function is slightly broken:

def at_finish_line(self):
    if self.ycor() >= 300:
        return True
    else:
        False

The simple fix is:

def at_finish_line(self):
    if self.ycor() >= 300:
        return True
    else:
        return False

The better fix is:

def at_finish_line(self):
    return self.ycor() >= 300:
cdlane
  • 40,441
  • 5
  • 32
  • 81