TransWikia.com

Hilos en snake de 2 jugadores en python 3

Stack Overflow en español Asked by Godxy on February 5, 2021

Estoy haciendo el juego snake pero de 2 jugadores pero este se necesitan usar hilos para cada jugador. Al momento de intentar ejecutar, se abre la ventana pero esta se cierra. Y manda el error:

File "C:Program FilesWindowsAppsPythonSoftwareFoundation.Python.3.8_3.8.1776.0_x64__qbz5n2kfra8p0libthreading.py", line 932, in _bootstrap_inner
File "C:Program FilesWindowsAppsPythonSoftwareFoundation.Python.3.8_3.8.1776.0_x64__qbz5n2kfra8p0libthreading.py", line 932, in _bootstrap_inner
self.run()
File "C:Program FilesWindowsAppsPythonSoftwareFoundation.Python.3.8_3.8.1776.0_x64__qbz5n2kfra8p0libthreading.py", line 870, in run
self.run()
File "C:Program FilesWindowsAppsPythonSoftwareFoundation.Python.3.8_3.8.1776.0_x64__qbz5n2kfra8p0libthreading.py", line 870, in run
self._target(*self._args, **self._kwargs)
File "c:/Users/axelp/Downloads/snake_v5.py", line 39, in snake
self._target(*self._args, **self._kwargs)
cabeza = turtle.Turtle()
Se esta utilizando la librería turtle y anteriormente tenía la sintaxis así:

snake1 = Thread(target = snake("Up", "Down", "Left", "Right", 300, "blue", 0))
    snake2 = Thread(target = snake("w", "s", "a", "d", -300, "yellow", 1))  
    snake1.start()
    snake2.start()

Pero se ejecutaba desde el primer momento y no dejaba ejecutar al siguiente hilo por eso cambie la manera de crear el hilo.

import turtle
import time
import random
from threading import Thread

posponer = 0.1

#Marcador
puntuacion = [0, 0]
puntuacion_max = 0

# configuracion de la ventana
wn = turtle.Screen()
wn.title("Snake Battle Royale Super Ultra Mega Alfa Sniper V3")
wn.bgcolor("black")
wn.setup(width = 1250, height = 650)
wn.tracer(0)

#Comida
Comida = turtle.Turtle()
Comida.speed(0)
Comida.shape("circle")
Comida.color("red")
Comida.penup()
Comida.goto(0,100)

# texto
texto = turtle.Turtle()
texto.speed(0)
texto.color("white")
texto.penup()
texto.hideturtle()
texto.goto(0,260)
texto.write(f"Score Player One: {puntuacion[0]}, Score Player Two: {puntuacion[1]}    High Score: 0", align = "center", font = ("Sans", 12, "normal"))

def snake(subir, bajar, girar_izquierda, girar_derecha, inicio, color, jugador):
    global puntuacion_max, wn, Comida, texto
    #Cabeza serpiente
    cabeza = turtle.Turtle()
    cabeza.speed(0)
    # turtle, square, triangle, circle, triangle, classic
    cabeza.shape("circle")
    cabeza.color(color)
    cabeza.penup()
    #posicion inicial del jugador
    cabeza.goto(300,0)
    cabeza.direction = "stop"
    #segmentos / cuerpo de la serpiente
    segmentos = []
    #Funciones
def arriba():
    cabeza.direction = "up"

def abajo():
    cabeza.direction = "down"

def izquierda():
    cabeza.direction = "left"

def derecha():
    cabeza.direction = "right"

def pausa():
    cabeza.direction = "stop"

def mov():
    if cabeza.direction == "up":
        y = cabeza.ycor()
        cabeza.sety(y + 20)

    if cabeza.direction == "down":
        y = cabeza.ycor()
        cabeza.sety(y - 20)

    if cabeza.direction == "left":
        x = cabeza.xcor()
        cabeza.setx(x - 20)

    if cabeza.direction == "right":
        x = cabeza.xcor()
        cabeza.setx(x + 20)
        
#Teclado
wn.listen()
wn.onkeypress(arriba, subir)
wn.onkeypress(abajo, bajar)
wn.onkeypress(izquierda, girar_izquierda)
wn.onkeypress(derecha, girar_derecha)
wn.onkeypress(pausa, "p")

while True:
    wn.update()

    #Coliciones con los bordes
    if cabeza.xcor() > 600 or cabeza.xcor() < -600 or cabeza.ycor() > 300 or cabeza.ycor() < -300:
        time.sleep(1)
        cabeza.goto(inicio,0)
        Comida.goto(0, 100)
        cabeza.direction = "stop"

        # Borrar los segmentos.
        for segmento in segmentos:
            segmento.hideturtle()
        if len(segmentos) != 0:
            segmentos.remove(nuevo_segmento)

        #Limpiar lista de segmentos
        segmentos.clear()

        #Resetear marcador
        puntuacion[jugador] = 0
        texto.clear()
        texto.write("Score Player One: {}, Score Player Two: {}    High Score: {}".format(puntuacion[0], puntuacion[1], puntuacion_max),
                align = "center", font = ("Sans", 12, "normal"))

    # colision de comida
    if cabeza.distance(Comida) < 20:
        x = random.randint(-580, 580)
        y = random.randint(-280, 280)
        Comida.goto(x,y) 

        nuevo_segmento = turtle.Turtle()
        nuevo_segmento.speed(0)
        nuevo_segmento.shape("circle")
        nuevo_segmento.color(color)
        nuevo_segmento.penup()
        segmentos.append(nuevo_segmento)

        #Aumentar marcador
        puntuacion[jugador] += 10

        if puntuacion[jugador] > puntuacion_max:
            puntuacion_max = puntuacion[jugador]

        texto.clear()       
        texto.write("Score Player One: {}, Score Player Two: {}    High Score: {}".format(puntuacion[0], puntuacion[1], puntuacion_max),
                align = "center", font = ("Sans", 12, "normal"))

    #Mover el cuerpo de la serpiente
    totalseg = len (segmentos)
    for index in range(totalseg -1, 0, -1):
        x = segmentos[index -1].xcor()
        y = segmentos[index -1].ycor()
        segmentos[index].goto(x, y)

    if totalseg > 0:
        x = cabeza.xcor()
        y = cabeza.ycor()
        segmentos[0].goto(x,y)

    mov()

    #Colisiones con el cuerpo 
    for segmento in segmentos:
        if segmento.distance(cabeza)< 20:
            time.sleep(1)
            cabeza.goto(inicio,0)
            Comida.goto(0, 100)
            cabeza.direction = "stop"

            #Esconder los segmentos
            for segmento in segmentos:
                segmento.goto(1300,1300)

            segmentos.clear()

    time.sleep(posponer)

def Main(): 
    '''
    snake1 = Thread(target = snake("Up", "Down", "Left", "Right", 300, "blue", 0))
    snake2 = Thread(target = snake("w", "s", "a", "d", -300, "yellow", 1))  
    snake1.start()
    snake2.start()
    
    '''  
    snake1 = Thread(name = 'snake', target=snake, args=("Up", "Down", "Left", "Right", 300, "blue", 0))
    snake2 = Thread(name = 'snake2', target=snake, args=("w", "s", "a", "d", -300, "yellow", 1))
    snake1.start()
    snake2.start()

if __name__ == '__main__':
    Main()

One Answer

Al ejecutar tu código aparece el siguiente error: RuntimeError: main thread is not in main loop

Para que dos jugadores utilicen la misma interfaz tendrías que cambiar completamente tu código, pero si lo que quieres es mostrar dos ventanas iguales podrías utilizar subprocess. Por ejemplo:

# import sys, subprocess
# ...

def Main(): 
    if len(sys.argv) == 2 and sys.argv[1].isdigit():
        for i in range(int(sys.argv[1])):
            subprocess.Popen(f'{sys.executable} {sys.argv[0]}')
    else:
        snake("Up", "Down", "Left", "Right", 300, "blue", 0) # Puedes pasar argumentos por línea de comandos o hacer que sean aleatorios con random

En este ejemplo, si ejecutas python snake_v5.py se abrirá una instancia del juego, si ejecutas python snake_v5.py 2 se abrirán dos instancias. Pero dos usuarios no podrán jugar a la vez porque solamente una de las instancias tendrá el foco en un momento dado.

Realmente tienes que adaptar el código para que el juego permita dos jugadores (en la misma interfaz), y que cada uno utilice distintas teclas para jugar. Puedes hacerlo sin threads y sin subprocesos.

Un saludo!

Answered by tecnobillo on February 5, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP