I'm trying to create a TKinter based Space Invaders but I ahve trouble with the keyboard inputs.
Indeed, I've 3 "bind" :
- If the right arrow is pressed, the "character" moves to the right of 10px
- Same with left
- Finally, if the space bar is pressed a shoot is created (right now it's only a white rectangle above the "character"
But there comes the problem, if I press the spacebar while holding an arrow the ship stops, I can't make it shoot while moving.
I've found some posts here already (including one saying it may be due to how the system handles keypress, and he gave a solution but I wasn't able to use it) about this problem but I couldn't apply their solutions as my english and Python knowledge are short (first time I use OOP and classes).
So I've tried creating a new type of bind : beginning a non-stop move to the right on press of the arrow and stop of it on release, same for left and a condition on double hold but I wasn't able to code it. Would it even handle the problem or I need to find something else ?
Here's my code (french notes so ask if needed) :
from tkinter import Tk, Canvas, Button, Label
class SpaceInvaders():
def __init__(self):
self.window = Tk()
self.window.geometry("1200x900")
self.label_score = Label(self.window, text="Score : ")
self.label_score.place(x=10, y=10)
self.label_vies = Label(self.window, text="Vies :")
self.label_vies.place(x=1130, y=10)
self.button_new = Button(self.window, text="New Game", width=15)
self.button_new.place(x=400, y=860)
self.button_quit = Button(self.window, text="Quit", width=15, command = lambda:self.window.destroy())
self.button_quit.place(x=680, y=860)
self.canvas = Canvas(self.window, height = "800", width = "1200", bg='black')
self.canvas.pack(expand=True)
#Vaisseau et 1er alien
self.vaisseau = Vaisseau(self.canvas)
self.alien = Alien(self.canvas,self.window)
class Alien():
def __init__(self,canvas,window):
self.canvas = canvas
self.window = window
self.alien_x = 0
self.alien_y = 0
self.direction = 1
self.alien = self.canvas.create_rectangle(self.alien_x,self.alien_y,self.alien_x+100,self.alien_y+20, fill='white')
def run(self):
direction = self.direction
if direction==1:
if self.alien_x<1100:
self.alien_x += 5
else:
self.direction = -1
elif direction == -1:
if self.alien_x>0:
self.alien_x -= 5
else:
self.direction = 1
self.canvas.coords(self.alien,self.alien_x,self.alien_y,self.alien_x+100,self.alien_y+20)
self.window.after(20,self.run) #La méthode after semble retourner une erreur à 13 chiffres
class Vaisseau():
def __init__(self,canvas):
self.canvas = canvas
self.player_x = 0
self.player = self.canvas.create_rectangle(self.player_x,780,self.player_x+60,802,fill='white')
def event_handler(self,event):
if event.keysym == 'Right':
self.move(True)
elif event.keysym == 'Left':
self.move(False)
elif event.keysym == "space":
self.tir()
def move(self,right):
if right and self.player_x<1140:
self.player_x += 10
self.canvas.coords(self.player,self.player_x,780,self.player_x+60,802)
elif not right and self.player_x>0:
self.player_x -= 10
self.canvas.coords(self.player,self.player_x,780,self.player_x+60,802)
self.right_hold = False
def tir(self):
self.canvas.create_rectangle(self.player_x+27,760,self.player_x+33,775,fill="white")
game = SpaceInvaders()
game.alien.run()
game.window.bind("<KeyPress>",game.vaisseau.event_handler)
game.window.mainloop()