1

I am trying to make a tron game where its a local 2 player. My code is below but it is an unfinished product. I wanted to know how I can make it so if the shape enemy and the shape player touch each other or the line that they have created, it results to an outcome. Like printing Game Over and changing the background. I keep getting the errors written in my comments below.

def up():
    player.fd(15)
def right():
    player.fd(15)
def left():
    player.fd(15)
def down():
    player.fd(15)

playerPath = [[[100],[100]]]
enemyPath = [[[600],[600]]]
previousMove = "na"

#I keep getting this error: TclError: bad event type or keysym "up"

if previousMove != "up":
        #Check for other methods
    if previousMove == right():
        playerPath.append((playerPath[0][0][0] + 90, playerPath[0][0][1]))
    if previousMove == left():
        playerPath.append((playerPath[0][0][0] - 90, playerPath[0][0][1]))
    if previousMove == down():
        playerPath.append((playerPath[0][0][0] + 180, playerPath[0][0][1]))
        #repeat for other directions
if previousMove == "up":
    playerPath[0][0].append(playerPath[0][0][0] + 30)
    playerPath[0][1].append(playerPath[0][1][0] + 30)
previousMove = "up"


if previousMove != "right":
        #Check for other methods
    if previousMove == up():
        playerPath.append((playerPath[0][0][0] - 90, playerPath[0][0][1]))
    if previousMove == left():
        playerPath.append((playerPath[0][0][0] + 180, playerPath[0][0][1]))
    if  previousMove ==down():
        playerPath.append((playerPath[0][0][0] + 90, playerPath[0][0][1]))
       #repeat for other directions
if previousMove == "right":
    playerPath[0][0].append(playerPath[0][0][0] + 30)
    playerPath[0][1].append(playerPath[0][1][0] + 30)
previousMove = "right"


if previousMove != "left":
    #Check for other methods
    if previousMove == up():
        playerPath.append((playerPath[0][0][0] + 90, playerPath[0][0][1]))
    if previousMove == right():
        playerPath.append((playerPath[0][0][0] + 180, playerPath[0][0][1]))
    if previousMove == down():
        playerPath.append((playerPath[0][0][0] - 90, playerPath[0][0][1]))
        #repeat for other directions
if previousMove == "left":
    playerPath[0][0].append(playerPath[0][0][0] + 30)
    playerPath[0][1].append(playerPath[0][1][0] + 30)
previousMove = "left"


if previousMove != "down":
        #Check for other methods
    if previousMove == up():
        playerPath.append((playerPath[0][0][0] + 180, playerPath[0][0][1]))
    if previousMove == left():
        playerPath.append((playerPath[0][0][0] + 90, playerPath[0][0][1]))
    if previousMove == right():
        playerPath.append((playerPath[0][0][0] - 90, playerPath[0][0][1]))
        #repeat for other directions
if previousMove == "down":
    playerPath[0][0].append(playerPath[0][0][0] + 30)
    playerPath[0][1].append(playerPath[0][1][0] + 30)
previousMove = "down"

#This code gives me this error: IndexError: list index out of range    
#for subPath in enemyPath:
#    if player.position()[0] in range(subPath[0][0], subPath[0][1]) and player.position()[1] in range(subPath[1][0], subPath[1][1]):
#        print("Collision")


onkey(up, "up")
onkey(left, "left")
onkey(right, "right")
onkey(down, "down")

onkey(up1, "w")
onkey(left1, "a")
onkey(right1, "d")

listen()
mainloop()  
cdlane
  • 40,441
  • 5
  • 32
  • 81
User9123
  • 596
  • 2
  • 7
  • 14
  • Is there a reason there is no "Down" method? – SeeDerekEngineer Jul 14 '17 at 02:15
  • @SeeDerekEngineer the code I cant figure out how to make it move forever and turn up right down and left like the real game. So I just made it turn right or left regardless of the position. if u or anyone knows how to make it into the real control, I will gladly accept any suggestions. – User9123 Jul 14 '17 at 02:25

2 Answers2

2

Your code can't possibly work as given -- e.g. huge blocks of per keystroke code is at the top level were it'll only run once. Below is a complete rework of your code.

You need to test if you're crossing any line generated by your enemy, or yourself. This code keeps track of the segments and tests them on each move, completely obliterating the loser who accidentally steps on a line:

from turtle import Turtle, Screen

screen = Screen()
screen.bgcolor('black')

def up(who):
    global previousMove

    turtle, path = players[who]
    turtle.setheading(90)

    if previousMove != 'up':
        path.append(turtle.position())
    previousMove = 'up'

    turtle.fd(15)

    if checkCollision(turtle.position(), path, players[1 - who][PATH]):
        collision(turtle)

def right(who):
    global previousMove

    turtle, path = players[who]
    turtle.setheading(0)

    if previousMove != 'right':
        path.append(turtle.position())
    previousMove = 'right'

    turtle.fd(15)

    if checkCollision(turtle.position(), path, players[1 - who][PATH]):
        collision(turtle)

def left(who):
    global previousMove

    turtle, path = players[who]
    turtle.setheading(180)

    if previousMove != 'left':
        path.append(turtle.position())
    previousMove = 'left'

    turtle.fd(15)

    if checkCollision(turtle.position(), path, players[1 - who][PATH]):
        collision(turtle)

def down(who):
    global previousMove

    turtle, path = players[who]
    turtle.setheading(270)

    if previousMove != 'down':
        path.append(turtle.position())
    previousMove = 'down'

    turtle.fd(15)

    if checkCollision(turtle.position(), path, players[1 - who][PATH]):
        collision(turtle)

def collision(turtle):
    for key in ('Up', 'Left', 'Right', 'Down', 'w', 'a', 'd', 'x'):
        screen.onkey(None, key)  # disable game
    turtle.clear()  # remove the loser from the board!

def checkCollision(position, path1, path2):
    if len(path1) > 1:

        A, B = position, path1[-1]  # only check most recent line segment

        if len(path1) > 3:  # check for self intersection
            for i in range(len(path1) - 3):
                C, D = path1[i:i + 2]

                if intersect(A, B, C, D):
                    return True

        if len(path2) > 1:  # check for intersection with other turtle's path
            for i in range(len(path2) - 1):
                C, D = path2[i:i + 2]

                if intersect(A, B, C, D):
                    return True
    return False

X, Y = 0, 1

def ccw(A, B, C):
    """ https://stackoverflow.com/a/9997374/5771269 """
    return (C[Y] - A[Y]) * (B[X] - A[X]) > (B[Y] - A[Y]) * (C[X] - A[X])

def intersect(A, B, C, D):
    """ Return true if line segments AB and CD intersect """
    return ccw(A, C, D) != ccw(B, C, D) and ccw(A, B, C) != ccw(A, B, D)

player = Turtle('circle')
player.shapesize(6 / 20)
player.color('red')
player.pensize(6)
player.speed('fastest')
player.penup()
player.setposition(100, 100)
player.pendown()

enemy = Turtle('circle')
enemy.shapesize(6 / 20)
enemy.color('blue')
enemy.pensize(6)
enemy.speed('fastest')
enemy.penup()
enemy.setposition(-300, -300)
enemy.pendown()

players = [[player, [player.position()]], [enemy, [enemy.position()]]]
PLAYER, ENEMY = 0, 1
TURTLE, PATH = 0, 1

previousMove = None  # consolidate moves in same direction into single line segment

screen.onkey(lambda: up(PLAYER), 'Up')
screen.onkey(lambda: left(PLAYER), 'Left')
screen.onkey(lambda: right(PLAYER), 'Right')
screen.onkey(lambda: down(PLAYER), 'Down')

screen.onkey(lambda: up(ENEMY), 'w')
screen.onkey(lambda: left(ENEMY), 'a')
screen.onkey(lambda: right(ENEMY), 'd')
screen.onkey(lambda: down(ENEMY), 'x')

screen.listen()

screen.mainloop()

The line segment crossing code is taken from How can I check if two segments intersect?

The above code is incomplete and buggy -- it needs additional work to become a finished game. But it basically plays allowing you to try out ideas:

enter image description here

cdlane
  • 40,441
  • 5
  • 32
  • 81
1

The turtle "position" method will prove very helpful in this instance: http://interactivepython.org/runestone/static/IntroPythonTurtles/Summary/summary.html

Specifically, you could do

if player.position() == enemy.position():
      print  "Game Over"
      return

As for the scenario where a collision occurs with a line, you will need to store the path traveled by the two player's in a list or array, then determine in a similar if statement above if the player's move runs into one of those spaces.

You could store the path by creating a 2D array or list. If the player is moving in the same direction, you append to the appropriate axis a list of the range of distance the player has traveled. If the player moves in a new direction, append a new list with the range of distance traveled along the axis.

playerPath = [[[100],[100]]]   #[[[X], [Y]]]
enemyPath = [[[600],[600]]]
previousMove = "na"
if up():
    if previousMove != "up":
        #Check for other methods
        if right():
            playerPath[0][0].append(playerPath[0][0][0] + 90)
            playerPath.insert(0, (playerPath[0][0][0], playerPath[0][0]
            [1])
        #repeat for other directions
    if previousMove == "up":
        playerPath[0][0].append(playerPath[0][0][0])
        playerPath[0][1].append(playerPath[0][1][0] + 30)
    previousMove = "up"
...

When checking if a collision has occured, loop through the subpaths, checking if the player.position X and Y values are in the X and Y path that has been traversed already.

for subPath in enemyPath:
    if player.position()[0] in range(subPath[0][0], subPath[0][1]) and
    player.position()[1] in range(subPath[1][0], subPath[1][1]):
    print "Collision"
    return
SeeDerekEngineer
  • 770
  • 2
  • 6
  • 22
  • thanks, how would I store the path traveled? That's the biggest problem I have. – User9123 Jul 14 '17 at 02:15
  • this has helped me a lot thank you.I changed the code above I had two more questions. would I just repeat what I have been doing with all directions. And I always get an syntaxerror no matter what I type after this line playerPath.append((playerPath[0][0][0] + 90, playerPath[0][0][1]). – User9123 Jul 14 '17 at 03:18
  • 1.Yes 2.You are missing the other ")" in that call to append. – SeeDerekEngineer Jul 14 '17 at 03:23
  • I got the if right(): but just for an example so I can fully understand, can you do the other direction for left() Thanks in advance – User9123 Jul 14 '17 at 05:12