EN VI

Python - Invader distance increases even though it shouldn not?

2024-03-15 22:30:08
How to Python - Invader distance increases even though it shouldn not

The distance between the Invader touching the left edge of the canvas increases even though it shouldn't. The Problem doesn't occur on the right side.

import tkinter
import timeit

tk = tkinter.Tk()
WIDTH = 1000
HEIGHT = 650
global canvas
canvas = tkinter.Canvas(tk, width=WIDTH, height=HEIGHT, bg="black")
canvas.pack()

class Invader():
    def __init__(self, canvas, play, x, y):
        self.canvas = canvas
        self.play = play
        self.x_coord = x
        self.y_coord = y
        self.shape = canvas.create_rectangle(self.x_coord, self.y_coord, self.x_coord + 50, self.y_coord + 50, fill='green')
        self.direction = 'left'

    def move(self):
        if self.direction == 'right':
            self.x_coord += 10
            if self.x_coord + 40 >= WIDTH:
                play.move_all_down()
        elif self.direction == 'left':
            self.x_coord -= 10
            if self.x_coord - 10 == 0:
                play.move_all_down()
        canvas.coords(self.shape, self.x_coord, self.y_coord, self.x_coord + 50, self.y_coord + 50)

class Play():
    def __init__(self, canvas):
        self.canvas = canvas
        self.invaderlist = []
        self.last_move_time = timeit.default_timer()
        self.move_delay = 0.3443434

    def move_invaders(self):
            current_time = timeit.default_timer()
            if current_time - self.last_move_time > self.move_delay:
                for invader in self.invaderlist:
                    invader.move()
                    self.last_move_time = current_time
    def move_all_down(self):
        for invader in self.invaderlist:
            invader.y_coord += 10
            canvas.coords(invader.shape, invader.x_coord, invader.y_coord, invader.x_coord + 50, invader.y_coord + 50)
            if invader.direction == 'left':
                invader.direction = 'right'
            elif invader.direction == 'right':
                invader.direction = 'left'


    def run_all(self):
        x_coords = [50, 120, 200, 270, 350, 420, 500, 570, 650, 720]
        y = 200
        for i in range(10):
            x = x_coords[i]
            invader = Invader(self.canvas, self, x, y)
            self.invaderlist.append(invader)
        while True:
            self.move_invaders()
            canvas.after(5)
            self.canvas.update()          

play = Play(canvas)
play.run_all()
tkinter.mainloop()

I tried outputting the coordinates when touching the left side plus added a line that printed the id of the invader and the coordinates, I also tried changing the distance that it checks for in line 26.

Solution:

Your loop in Play.move_invaders() can tell each invader to move, except that any invader that moves beyond the limit left or right will cause all invaders to move down, and that switches the direction, which changes the test for the other invaders (if self.direction == 'right': etc) so not all invaders move the same direction.

Your loop should first move all the invaders and then, if the limit was exceeded, should then call move_all_down():

import tkinter
import timeit

tk = tkinter.Tk()
WIDTH = 1000
HEIGHT = 650
global canvas
canvas = tkinter.Canvas(tk, width=WIDTH, height=HEIGHT, bg="black")
canvas.pack()

class Invader():
    def __init__(self, canvas, play, x, y):
        self.canvas = canvas
        self.play = play
        self.x_coord = x
        self.y_coord = y
        self.shape = canvas.create_rectangle(self.x_coord, self.y_coord, self.x_coord + 50, self.y_coord + 50, fill='green')
        self.direction = 'left'

    def move(self):
        limit = False
        if self.direction == 'right':
            self.x_coord += 10
            if self.x_coord + 40 >= WIDTH:
                limit = True
        elif self.direction == 'left':
            self.x_coord -= 10
            if self.x_coord - 10 <= 0:
                limit = True

        canvas.coords(self.shape, self.x_coord, self.y_coord, self.x_coord + 50, self.y_coord + 50)
        return limit

class Play():
    def __init__(self, canvas):
        self.canvas = canvas
        self.invaderlist = []
        self.last_move_time = timeit.default_timer()
        self.move_delay = 0.3443434

    def move_invaders(self):
            current_time = timeit.default_timer()
            if current_time - self.last_move_time > self.move_delay:
                move_down = False
                for invader in self.invaderlist:
                    limit = invader.move()
                    move_down = move_down or limit
                    self.last_move_time = current_time
                if move_down:
                    self.move_all_down()

    def move_all_down(self):
        for invader in self.invaderlist:
            invader.y_coord += 10
            #canvas.coords(invader.shape, invader.x_coord, invader.y_coord, invader.x_coord + 50, invader.y_coord + 50)
            if invader.direction == 'left':
                invader.direction = 'right'
            elif invader.direction == 'right':
                invader.direction = 'left'


    def run_all(self):
        x_coords = [50, 120, 200, 270, 350, 420, 500, 570, 650, 720]
        y = 200
        for i in range(10):
            x = x_coords[i]
            invader = Invader(self.canvas, self, x, y)
            self.invaderlist.append(invader)
        while True:
            self.move_invaders()
            canvas.after(5)
            self.canvas.update()          

play = Play(canvas)
play.run_all()
Answer

Login


Forgot Your Password?

Create Account


Lost your password? Please enter your email address. You will receive a link to create a new password.

Reset Password

Back to login