0

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()
Jo_Byr
  • 1
  • 2
  • Does this answer your question? [tkinter using two keys at the same time](https://stackoverflow.com/questions/39606019/tkinter-using-two-keys-at-the-same-time) – acw1668 Dec 18 '20 at 16:26

1 Answers1

0

If you want actions to be performed simultaneously you need to make them happen in the backround. Your code, as sits right now, is handling every action in serial fashion. For example if you hit the "left" button, your code will be moving your character left before anything else can happen. To deal with this you can use something like the threaded or multiprocess module. Both of them can help you thread your actions so they can be happening in the same time. Their docs are pretty specific on how you can use them.

threaded module : https://pypi.org/project/threaded/

multiprocess module : https://pypi.org/project/multiprocess/