Thomas Grops via Python-list wrote: > Hi I have created some code, which moves a rectangle around and when it > hits the edge it picks a random new direction. It does this by the count > function within my class. I am wanting to create a button to randomly > change count but I my class seems to be getting errors. > > I also wanted to create a second class object tank2 but it doesn't seem to > move when I create it with tank2.Tank(x,y,vx,vy) and call tank1.move() > > Can anyone help me many thanks.
It may take some time to get it, but don't use time.sleep() in a tkinter script! > def right(self): > canvas.move(self.id,+5,0)#move right > > #reposition x,vx,y,vy values > self.x+=5 > self.vx+=5 > > #Update canvas > canvas.update() > time.sleep(0.1) When you have to repeat the same code with small variations (the canvas.move() arguments) make these variations arguments of the function. > def move(self): > > # Loop for steps in movement > for t in range(1, 10000): > #Move direction depending on count value > if self.count==0: > self.left() So 0 means "left" and 6 means "down and right". If a value's meaning is not obvious use a name instead LEFT = 42 # also have a look at the enum module in the stdlib if self.count == LEFT: self.left() > if self.count==1: > self.right() > if self.count==2: > self.up() > if self.count==3: > self.down() > if self.count==4: > self.upLeft() > if self.count==5: > self.upRight() > if self.count==6: > self.downRight() > if self.count==7: > self.downLeft() That's quite a lot of if-s. It might be better to use a table. > #Left border > if self.x <= 0: > #banned directions > excludedNumbers = [0,4,7] > #define random integer to be selected > randomNumber = random.randint(0,8) > #nested while loop so that the banned directions are not > #selected > while randomNumber in excludedNumbers: > randomNumber = random.randint(0,8) > #feed allowed random direction back to the count > self.count=randomNumber > > #Right border > elif self.vx >= 1000: > #banned directions > excludedNumbers = [1,5,6] > #define random integer to be selected > randomNumber = random.randint(0,8) > #nested while loop so that the banned directions are not > #selected > while randomNumber in excludedNumbers: > randomNumber = random.randint(0,8) > #feed allowed random direction back to the count Instead of repeating your code with copy-and-past make a helper function like the randx() posted by Larry Hudson. By the way, randint(min, max) may return max so there are 9 possible outcomes while you handle only 8. To be consistent with Python's half-open ranges use random.randrange(8) # may return 0, 1, 2, 3, 4, 5, 6, 7, but not 8 Below is what became of your code when I messed with it. Don't copy it, try to pick up ideas, and have fun! import tkinter as tk import random #Canvas size WIDTH = 1000 HEIGHT = 700 BUTTONS_PER_ROW = 6 MRIGHT = 0 MLEFT = 1 MUP = 2 MDOWN = 3 MLEFTUP = 4 MRIGHTUP = 5 MRIGHTDOWN = 6 MLEFTDOWN = 7 class Tank(): def __init__(self, root, canvas, name, x, y, width, height, color): self.root = root self.canvas = canvas self.color = color self.name = name self.__life = 10 self.speed = 1 self.x = x self.y = y self.width = width self.height = height self.direction = MRIGHT self.id = canvas.create_rectangle( x, y, self.right, self.bottom, fill=color ) self.moves = [ (5, 0), # right (-5, 0), # left (0, -2), # up (0, 2), # down (-1, -1), # left-up (1, -1), # right-up (1, 1), # right-down (-1, 1) # left-down ] @property def right(self): return self.x + self.width @property def bottom(self): return self.y + self.height def attack(self): print('ouch!') self.__life -= 1 def checkLife(self): if self.__life <= 0: print('dead') else: print(str(self.__life) + " life left") def medic(self): self.__life += 5 def move_tank(self, dx, dy): self.x += dx self.y += dy self.canvas.move(self.id, dx, dy) def move(self): self.move_tank(*self.moves[self.direction]) # If a boundary has been crossed, pick a direction randomly directions = set(range(8)) if self.x <= 0: directions -= {MLEFT, MLEFTUP, MLEFTDOWN} elif self.right >= WIDTH: directions -= {MRIGHT, MRIGHTUP, MRIGHTDOWN} if self.y <= 0: directions -= {MUP, MLEFTUP, MRIGHTUP} elif self.bottom >= HEIGHT: directions -= {MDOWN, MLEFTDOWN, MRIGHTDOWN} assert directions, "nowhere to go!" if len(directions) < 8: print(self, "hit wall, changing direction") self.direction = random.choice(list(directions)) self.root.after(10, self.move) def changeDirection(self): print(self, "changing direction on user request") self.direction = random.randrange(8) def __str__(self): return self.name def random_color(): colors = [ random.randrange(128), random.randrange(128, 256), random.randrange(128) ] random.shuffle(colors) return "#{:02x}{:02x}{:02x}".format(*colors) def main(): root = tk.Tk() canvas = tk.Canvas(root, width=WIDTH, height=HEIGHT, bg='khaki') canvas.grid(row=0, column=0, columnspan=BUTTONS_PER_ROW) tanks = [ Tank( root, canvas, "Tank #{}".format(i), x, 650, 40, 40, random_color()) for i, x in enumerate(range(0, WIDTH, 80), 1) ] for i, tank in enumerate(tanks): tank.move() button = tk.Button( root, text=tank.name, command=tank.changeDirection, bg=tank.color ) button.grid(row=1+i // BUTTONS_PER_ROW, column=i % BUTTONS_PER_ROW) root.mainloop() if __name__ == "__main__": main() PS: > #life, speed, starting position, vectors, size of tank > def __init__(self, x, y, vx, vy): Python has docstrings. Use them! -- https://mail.python.org/mailman/listinfo/python-list