pythonturtle-graphicspython-turtle

Im having problems running 2 functions at the same time


Im a coding beginner who just got into python turtle. I have recently been working on a project where you control 2 characters. They are trying to shoot each other over a river. But i ran into an error where whenever one side fires a bullet and then the other one does aswell, the first bullet just freezes in place until the first one is finished. This ruins the entire game. Ive seen other posts with this "if name = main" thing but i dont understand it.

I have worked out that this is due to a function being called while another is still running. Ive tried multithreading it but it did not work and im way too much of a beginner to understand this. If someone could give me an explanation on how to fix this i would be very happy. (Yes the code is in german but the names of the variables dont really matter).

import turtle


sieg_1 = 0
sieg_2 = 0

kugel1speed = 4
kugel2speed = 4



screen = turtle.Screen()
screen.title("Paintball River")
screen.bgcolor("darkgreen")
screen.setup(width=800, height=600)

#wasd / links
character1 = turtle.Turtle()
character1.shape("square")
character1.color("mediumblue")
character1.speed(0)
character1.penup()
character1.goto(-200,0)

#pfeiltasten / rechts
character2 = turtle.Turtle()
character2.shape("square")
character2.color("red")
character2.speed(0)
character2.penup()
character2.goto(200, 0)

####################################################################
randkröte = turtle.Turtle()
randkröte.shape("square")
randkröte.color("grey")
randkröte.speed(100)
randkröte.pencolor("grey")
randkröte.pensize(30)
randkröte.penup()
randkröte.goto(386,0)
randkröte.pendown()
randkröte.left(90)
randkröte.forward(285)
randkröte.left(90)
randkröte.forward(772)
randkröte.left(90)
randkröte.forward(571)
randkröte.left(90)
randkröte.forward(790)
randkröte.penup()
randkröte.goto(386,-300)
randkröte.left(90)
randkröte.pendown()
randkröte.forward(400)
randkröte.penup()
randkröte.goto(-400,300)
randkröte.pendown()
randkröte.forward(1)


flusskröte = turtle.Turtle()
flusskröte.shape("square")
flusskröte.color("royalblue")
flusskröte.speed(100)
flusskröte.pencolor("royalblue")
flusskröte.pensize(179)
flusskröte.penup()
flusskröte.goto(0,-400)
flusskröte.pendown()
flusskröte.left(90)
flusskröte.forward(800)


###################################################################################



def schießen1():
    x1 = character1.xcor()
    y1 = character1.ycor()
    kugely1 = kugel1.ycor()
    if kugely1 == 330:
        kugel1.teleport(x1,y1)
        kugel1.goto(365,y1)

def schießen2(x,y):
    x2 = character2.xcor()
    y2 = character2.ycor()
    kugely2 = kugel2.ycor()
    if kugely2 == 350:
        kugel2.teleport(x2,y2)
        kugel2.goto(-365,y2)

kugel1 = turtle.Turtle()
kugel1.speed(kugel1speed)
kugel1.color("darkblue")
kugel1.shape("circle")
kugel1.shapesize(0.5)
kugel1.penup()
kugel1.hideturtle()
kugel1.goto(0,330)
kugel1.showturtle()



kugel2 = turtle.Turtle()
kugel2.speed(kugel2speed)
kugel2.color("darkred")
kugel2.shape("circle")
kugel2.shapesize(0.5)
kugel2.penup()
kugel2.hideturtle()
kugel2.goto(0,350)
kugel2.showturtle()


######################################################################################

speed = 20


def hoch1():
    y = character1.ycor()
    if y < 260:
        character1.sety(y + speed)

def runter1():
    y = character1.ycor()
    if y > -260:
        character1.sety(y - speed)

def links1():
    x = character1.xcor()
    if x > -350:
        character1.setx(x - speed)

def rechts1():
    x = character1.xcor()
    if x < -100:
        character1.setx(x + speed)


def hoch2():
    y = character2.ycor()
    if y < 260:
        character2.sety(y + speed)

def runter2():
    y = character2.ycor()
    if y > -260:
        character2.sety(y - speed)

def links2():
    x = character2.xcor()
    if x > 100:
        character2.setx(x - speed)

def rechts2():
    x = character2.xcor()
    if x < 350:
        character2.setx(x + speed)


screen.listen()

screen.onkeypress(screen.bye, "Escape")

screen.onkeyrelease(hoch2, "Up")
screen.onkeyrelease(runter2, "Down")
screen.onkeyrelease(links2, "Left")
screen.onkeyrelease(rechts2, "Right")


screen.onkeyrelease(hoch1, "w")
screen.onkeyrelease(runter1, "s")
screen.onkeyrelease(links1, "a")
screen.onkeyrelease(rechts1, "d")

screen.onkeyrelease(schießen1,"e")
screen.onscreenclick(schießen2)

######################################################################################

while True:
    screen.update()
    kugelx1 = kugel1.xcor()
    kugelx2 = kugel2.xcor()
    if kugelx1 == 365:
        kugel1.teleport(0,330)
    if kugelx2 == -365:
        kugel2.teleport(0,350)



Solution

  • One common approach is to use multiprocess, but since said you dont want mutlithread since beginner level i assume you don't like that approach.

    Second approach coul be by making bullets to move bit by bit. Currently it looks like an instant translate for bullets.

    Trying smaller steps in each iteration of main game while loop allows bullet movement appear like they move in parallel instead of freezing

    So to achieve this we have two flags for flight of each bullet. if bullet is on flight it moves slightly.

    import turtle
    
    sieg_1 = 0
    sieg_2 = 0
    
    kugel1speed = 4
    kugel2speed = 4
    
    screen = turtle.Screen()
    screen.title("Paintball River")
    screen.bgcolor("darkgreen")
    screen.setup(width=800, height=600)
    
    # wasd / links
    character1 = turtle.Turtle()
    character1.shape("square")
    character1.color("mediumblue")
    character1.speed(0)
    character1.penup()
    character1.goto(-200, 0)
    
    # pfeiltasten / rechts
    character2 = turtle.Turtle()
    character2.shape("square")
    character2.color("red")
    character2.speed(0)
    character2.penup()
    character2.goto(200, 0)
    
    # Field boundaries
    randkröte = turtle.Turtle()
    randkröte.shape("square")
    randkröte.color("grey")
    randkröte.speed(100)
    randkröte.pencolor("grey")
    randkröte.pensize(30)
    randkröte.penup()
    randkröte.goto(386, 0)
    randkröte.pendown()
    randkröte.left(90)
    randkröte.forward(285)
    randkröte.left(90)
    randkröte.forward(772)
    randkröte.left(90)
    randkröte.forward(571)
    randkröte.left(90)
    randkröte.forward(790)
    randkröte.penup()
    randkröte.goto(386, -300)
    randkröte.left(90)
    randkröte.pendown()
    randkröte.forward(400)
    randkröte.penup()
    randkröte.goto(-400, 300)
    randkröte.pendown()
    randkröte.forward(1)
    
    flusskröte = turtle.Turtle()
    flusskröte.shape("square")
    flusskröte.color("royalblue")
    flusskröte.speed(100)
    flusskröte.pencolor("royalblue")
    flusskröte.pensize(179)
    flusskröte.penup()
    flusskröte.goto(0, -400)
    flusskröte.pendown()
    flusskröte.left(90)
    flusskröte.forward(800)
    
    # Bullet state flags
    kugel1_on_flight = False
    kugel2_on_flight = False
    
    # Functions
    def schießen1():
        global kugel1_on_flight
        if not kugel1_on_flight:
            x1 = character1.xcor()
            y1 = character1.ycor()
            kugel1.goto(x1, y1)
            kugel1_on_flight = True
    
    def schießen2(x, y):
        global kugel2_on_flight
        if not kugel2_on_flight:
            x2 = character2.xcor()
            y2 = character2.ycor()
            kugel2.goto(x2, y2)
            kugel2_on_flight = True
    
    kugel1 = turtle.Turtle()
    kugel1.speed(kugel1speed)
    kugel1.color("darkblue")
    kugel1.shape("circle")
    kugel1.shapesize(0.5)
    kugel1.penup()
    kugel1.hideturtle()
    kugel1.goto(0, 330)
    kugel1.showturtle()
    
    kugel2 = turtle.Turtle()
    kugel2.speed(kugel2speed)
    kugel2.color("darkred")
    kugel2.shape("circle")
    kugel2.shapesize(0.5)
    kugel2.penup()
    kugel2.hideturtle()
    kugel2.goto(0, 350)
    kugel2.showturtle()
    
    speed = 20
    
    def hoch1():
        y = character1.ycor()
        if y < 260:
            character1.sety(y + speed)
    
    def runter1():
        y = character1.ycor()
        if y > -260:
            character1.sety(y - speed)
    
    def links1():
        x = character1.xcor()
        if x > -350:
            character1.setx(x - speed)
    
    def rechts1():
        x = character1.xcor()
        if x < -100:
            character1.setx(x + speed)
    
    def hoch2():
        y = character2.ycor()
        if y < 260:
            character2.sety(y + speed)
    
    def runter2():
        y = character2.ycor()
        if y > -260:
            character2.sety(y - speed)
    
    def links2():
        x = character2.xcor()
        if x > 100:
            character2.setx(x - speed)
    
    def rechts2():
        x = character2.xcor()
        if x < 350:
            character2.setx(x + speed)
    
    screen.listen()
    screen.onkeypress(screen.bye, "Escape")
    screen.onkeyrelease(hoch2, "Up")
    screen.onkeyrelease(runter2, "Down")
    screen.onkeyrelease(links2, "Left")
    screen.onkeyrelease(rechts2, "Right")
    screen.onkeyrelease(hoch1, "w")
    screen.onkeyrelease(runter1, "s")
    screen.onkeyrelease(links1, "a")
    screen.onkeyrelease(rechts1, "d")
    screen.onkeyrelease(schießen1, "e")
    screen.onscreenclick(schießen2)
    
    # Main game loop
    while True:
        screen.update()
    
        # Update kugel1 position if on flight
        if kugel1_on_flight:
            kugel1.setx(kugel1.xcor() + 20)  # Move right
            if kugel1.xcor() >= 365:        # Reset if out of bounds
                kugel1.goto(0, 330)
                kugel1_on_flight = False
    
        # Update kugel2 position if on flight
        if kugel2_on_flight:
            kugel2.setx(kugel2.xcor() - 20)  # Move left
            if kugel2.xcor() <= -365:        # Reset if out of bounds
                kugel2.goto(0, 350)
                kugel2_on_flight = False