Saltar a contenido

Mover la paleta

El siguiente añadido es reaccionar a las pulsaciones Left Right para mover la paleta a izquierda y derecha:

08MoverPaleta.py
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
import tkinter
import random

class Juego:
    def __init__(self, ventana):
        self.ventana = ventana

        # Configurar ventana
        self.ventana.title('Bola')
        self.ventana.resizable(False, False)
        self.ventana.wm_attributes('-topmost', True)

        # Crear lienzo
        self.lienzo = tkinter.Canvas(self.ventana,
                                     width=500,
                                     height=400,
                                     bd=0)
        self.lienzo.pack()
        self.ventana.update()

        # Crear bola y paleta
        self.bola = Bola(self)
        self.paleta = Paleta(self)        

        # Indicadores
        self.terminar = False
        self.en_juego = False
        self.reiniciar= False

        # Asociar eventos de teclado
        self.ventana.bind_all('<KeyPress>', self.gestionar_tecla)
        self.ventana.bind_all('<KeyRelease>', self.detener_paleta)

    def gestionar_tecla(self,evento):
        if evento.keysym=='Escape':
            self.terminar = True
        elif evento.keysym=='space':            
            self.en_juego = True
        elif evento.keysym=='Left':
            self.paleta.desplaz_paleta(-1)
        elif evento.keysym=='Right':
            self.paleta.desplaz_paleta(1)

    def detener_paleta(self,evento):
            self.paleta.desplaz_paleta(0)

    def bucle(self):
        while True:
            if self.terminar:
                break

            if self.reiniciar and self.en_juego:
                self.lienzo.delete(self.id_bola)
                self.lienzo.delete(self.id_paleta)
                self.bola = Bola(self)
                self.paleta = Paleta(self)
                self.reiniciar = False

            if self.en_juego:
                self.ventana.update_idletasks()
                self.bola.mostrar()
                self.paleta.mostrar()

            self.ventana.update_idletasks()
            self.ventana.update()

class Bola:
    def __init__(self, juego):
        self.juego  = juego

        tamaño = 15
        self.lienzo_ancho = self.juego.lienzo.winfo_width()
        self.lienzo_alto = self.juego.lienzo.winfo_height()

        self.juego.id_bola = self.juego.lienzo.create_oval(0, 0, tamaño, tamaño,
                                                           fill='red')
        centro_x = self.lienzo_ancho/2 - tamaño/2
        centro_y = self.lienzo_alto/2 - tamaño/2
        self.juego.lienzo.move(self.juego.id_bola, centro_x, centro_y)

        self.desplaz_y = -(velocidad_bola)
        self.desplaz_x = random.choice([-2, -3, -4, 2, 3, 4])

    def mostrar(self):
        # obtener coordenadas bola (x1, y1, x2, y2)
        coord_bola = self.juego.lienzo.coords(self.juego.id_bola)
        borde_sup_bola = coord_bola[1]
        borde_inf_bola = coord_bola[3]
        borde_izd_bola = coord_bola[0]
        borde_dch_bola = coord_bola[2]

        # si ha tocado el borde superior, empezar a bajar
        if borde_sup_bola <= 1:
            self.desplaz_y = abs(self.desplaz_y)

        ## si toca el borde inferior, fin del juego
        if borde_inf_bola >= self.lienzo_alto:
            self.juego.en_juego = False
            self.juego.reiniciar = True

        # si ha tocado el borde lateral, cambiar de dirección
        if borde_izd_bola <= 1:
            self.desplaz_x = abs(self.desplaz_x)
        elif borde_dch_bola >= self.lienzo_ancho-1:
            self.desplaz_x = abs(self.desplaz_x)*(-1)

        # desplazar
        self.juego.lienzo.move(self.juego.id_bola, self.desplaz_x, self.desplaz_y)

class Paleta:
    def __init__(self, juego):
        self.juego  = juego

        ancho = 60
        self.lienzo_ancho = self.juego.lienzo.winfo_width()
        self.lienzo_alto = self.juego.lienzo.winfo_height()

        self.juego.id_paleta = self.juego.lienzo.create_rectangle(0, 0, ancho, 10, fill='blue')
        self.desplaz = velocidad_paleta
        self.desplaz_x = 0

        centro_x = self.lienzo_ancho/2 - ancho/2
        centro_y = self.lienzo_alto - 50

        self.juego.lienzo.move(self.juego.id_paleta, centro_x, centro_y)

    def desplaz_paleta(self, sentido):
        if not self.juego.en_juego:
            return

        if sentido==0:
            self.desplaz_x=0

        coord = self.juego.lienzo.coords(self.juego.id_paleta)
        borde_izd_paleta = coord[0]
        borde_dch_paleta = coord[2]

        self.desplaz_x = 0
        if borde_izd_paleta > 0 and sentido == -1:
            self.desplaz_x = -velocidad_paleta

        elif borde_dch_paleta < self.lienzo_ancho and sentido == 1:        
            self.desplaz_x = velocidad_paleta

    def mostrar(self):
        self.juego.lienzo.move(self.juego.id_paleta, self.desplaz_x, 0)          

velocidad_bola=4
velocidad_paleta=5
v = tkinter.Tk()
juego = Juego(v)
juego.bucle()
juego.ventana.update_idletasks()
juego.ventana.destroy()

En el bloque principal del programa establecemos la velocidad con la que se desplaza la paleta, medida en pixels:

velocidad_paleta=5

Inicializamos el objeto paleta con un desplazamiento horizontal de cero. Mientras no pulsemos las teclas, la paleta no se mueve:

self.desplaz = velocidad_paleta
self.desplaz_x = 0

En la gestión del evento KeyPress establecemos la dirección de desplazamiento:

elif evento.keysym=='Left':
    self.paleta.desplaz_paleta(-1)
elif evento.keysym=='Right':
    self.paleta.desplaz_paleta(1)

En el método desplaz_paleta() establecemos el desplazamiento:

if borde_izd_paleta > 0 and sentido == -1:
    self.desplaz_x = -velocidad_paleta

elif borde_dch_paleta < self.lienzo_ancho and sentido == 1:        
    self.desplaz_x = velocidad_paleta

Al soltar la tecla, detenemos el desplazamiento:

self.ventana.bind_all('<KeyRelease>', self.detener_paleta)

def detener_paleta(self,evento):
        self.paleta.desplaz_paleta(0)

Establecido el desplazamiento, refrescamos la paleta en cada iteración del bucle principal del juego:

if self.en_juego:
    self.ventana.update_idletasks()
    self.bola.mostrar()
    self.paleta.mostrar()

Nota: La paleta se desplaza a izquierda y derecha hasta tocar borde, pero es posible que el desplazamiento que se ejecuta en cada iteración sea superior a la distancia que falta para llegar al borde. Por este motivo, es posible que el extremo de la paleta se salga ligeramente del canvas. Podríamos refinar el programa para controlarlo pero no vamos a complicarlo. Apenas afecta a la jugabilidad.