creating an object at another objects position - Printable Version +- Python Forum (https://python-forum.io) +-- Forum: Python Coding (https://python-forum.io/forum-7.html) +--- Forum: GUI (https://python-forum.io/forum-10.html) +--- Thread: creating an object at another objects position (/thread-32582.html) |
creating an object at another objects position - gr3yali3n - Feb-19-2021 i want to create a small block to be a 'laser' and fire it from the canvas image im using as a ship. i've already created a list to append to and a ttl for the laser i even created the Laser class, but getting it to appear is not working like i thought it should. with laser.lasers.append() ive tried .append(self), .append(Laser) , .append(Laser(p[0],p[1],dx,dy)) i just dont know how to get it rolling. from tkinter import * from PIL import ImageTk,Image import time window_height = 400 window_width = 720 r =Tk() canvas=Canvas(r,width=window_width, height=window_height) bg=PhotoImage(file="./nightsky.png") bg1= canvas.create_image(0,0,anchor=NW,image=bg) canvas.pack() class Laser: lasers = [] def __init__(self,x,y,xv,yv): self.id = canvas.create_rectangle(10,10,24,24, fill = "red") self.lasers.append(self) self.ttl = 100 self.speed = 5 self.dx = 1 self.dy = 0 def update(self,dx,dy): if self.ttl == 0: canvas.delete(self.id) self.lasers.remove(self) return self.ttl =-1 canvas.move(self.id, x*self.speed, y*self.speed) class ship: def __init__(self,x,y,xv,yv): self.x = x self.y = y self.img = PhotoImage(file="./8bitship.png") self.id = canvas.create_image(0,0,anchor=NW,image=self.img) self.dx = 1 self.dy = 0 self.img_width = self.img.width() self.img_height = self.img.height() self.xv = 0 self.yv = 0 def move(self,x,y): p = canvas.coords(self.id) print(p) if p[0] <= 0 : x = 1 if p[0] + self.img_width > window_width : x = -1 if p[1] <=0 : y = 1 if p[1] + self.img_height > window_height : y = -1 canvas.move(self.id,x,y) def fire(self,x,y,xv,yv): p = canvas.coords(self.id) print("fire") Laser.lasers.append(Laser) mship = ship(0,0,0,0) r.bind("<Right>", lambda e: mship.move(x=8,y=0)) r.bind("<Left>",lambda e: mship.move(x=-8,y=0)) r.bind("<Up>",lambda e: mship.move(x=0,y=-8)) r.bind("<Down>", lambda e: mship.move(x=0,y=8)) r.bind("<space>", lambda e: mship.fire(0,0,0,0)) for laser in Laser.lasers: laser.update() r.update() r.mainloop() time.sleep(0.05) r.update() r.mainloop() RE: creating an object at another objects position - deanhystad - Feb-19-2021 What is the laser? RE: creating an object at another objects position - gr3yali3n - Feb-19-2021 lasers the list or Laser the class instance? the forloop laser was a mistake it was changed to, while True: r.mainloop() r.update() for Laser in Laser.lasers: Laser.update() time.sleep(0.05) RE: creating an object at another objects position - deanhystad - Feb-19-2021 You cannot do this: while True: r.mainloop() r.update() for Laser in Laser.lasers: Laser.update() time.sleep(0.05)mainloop is a blocking function call. It will never return. You will never call r.update() and you will never call any of your laser update code. If you want to make a game you are much better off starting with PyGame or some something similar. RE: creating an object at another objects position - gr3yali3n - Feb-19-2021 i am not trying to make a game. im trying to understand the mechanics behind why this works. a friend of mine is also trying to explain this to me and he got it to work lickety-split. the keybinding and objects is really what i am after here, but if you dont know how to get it done thats ok too. RE: creating an object at another objects position - deanhystad - Feb-19-2021 PyGame can be used for more than games. It is designed to make it easier to write applications where the user interacts with a highly dynamic application. Most GUI applications are completely event driven. The user clicks a button or does something and the software responds. Other than responding to user events the software is idle. Between the two are applications that are mostly event driven, but may also have a timer that periodically fires an event. This last may be what you are looking for. If I was writing the application in Qt I would use a QTimer. For tkinter I would see if I could do what I need with after(). You haven't answered my question. What is laser? When you see your program in your mind, what does laser do? RE: creating an object at another objects position - gr3yali3n - Feb-28-2021 I didn’t mean for my last statement to seem sarcastic, I should have worded it as, if I am not supposed to do this with Tkinter that is fine, I am also interested in pygame, I just don’t understand how a friend of mine got it done. (He doesn’t have the time to explain everything to me). but I finally got it. And laser is a instance of the Laser it stores the update method in each instance and that can be iterated Over with a for loop. At least that’s how I understood it. def fire(self): p = canvas.coords(self.id) Laser(p[0],p[3],self.dx,self.dy while True: r.mainloop() r.update() for laser in Laser.lasers: laser.update() time.sleep(.1) RE: creating an object at another objects position - deanhystad - Feb-28-2021 I was having a tough time understanding the lasers. Took the name too literally and expected a line that grows in length and didn't see how your rectangles would ever do something like that. But your lasers are projectiles which is fairly easy. The thing you are missing is the after() method. import math import tkinter as tk import random window_height = 400 window_width = 720 class Laser: instances = [] colors = ('red', 'yellow', 'blue', 'orange', 'green', 'purple', 'pink', 'brown', 'grey') @classmethod def update(cls): """Move all the lasers. Remove offscreen lasers""" cls.instances = [laser for laser in cls.instances if laser.move()] def __init__(self, x, y, dx, dy): self.id = canvas.create_line(x, y, x, y, width=3, fill=random.choice(self.colors)) self.x = x self.y = y self.dx = dx self.dy = dy self.length = 0 self.instances.append(self) def move(self): """Update laser position. Return True if visible""" self.length = min(30, self.length+1) self.x += self.dx self.y += self.dy x = self.x - self.length * self.dx y = self.y - self.length * self.dy if 0 <= x <= window_width and 0 <= y <= window_height: canvas.coords(self.id, int(x), int(y), int(self.x), int(self.y)) return True canvas.delete(self.id) return False def update_lasers(): """Periodically update the lasers""" Laser.update() root.after(10, update_lasers) def fire(*args): """Fire a rainbow starburst of lasers""" step = random.randint(1, 60) for angle in range(step//2, 360, step): angle = math.radians(angle) Laser(360, 200, math.sin(angle), math.cos(angle)) root = tk.Tk() canvas = tk.Canvas(root, width=window_width, height=window_height) canvas.pack() root.bind("<space>", fire) update_lasers() root.mainloop() |