class Move(Frame): def __init__(self, parent): Frame.__init__(self, parent) self.parent = parent self.initUI() self.animate() def initUI(self): self.parent.title("Move") self.pack(fill=BOTH, expand=1) self.canvas = Canvas(self) self.oval = self.canvas.create_oval(40, 10, 110, 80, outline="black", width=2) self.canvas.pack(fill=BOTH, expand=1) def animate(self): location = self.canvas.coords(self.oval) self.canvas.coords(self.oval, location[0] + 2.5, location[1], location[2] + 2.5, location[3]) self.after(1000, self.animate)
class MarcaFoto(Frame): def __init__(self, root): Frame.__init__(self, root) self.grid(column=0, row=0) self.canvas = Canvas(self, width=604, height=480) self.canvas.grid(column=0, row=0, columnspan=2) self.coords = Label(self) self.coords.grid(column=0, row=1) nome_arq_foto = 'turma1-640x480.gif' self.foto = PhotoImage(file=nome_arq_foto) self.canvas.create_image(0, 0, image=self.foto, anchor=NW) self.canvas.bind('<Motion>', self.moveu) self.canvas.bind('<ButtonPress>', self.marcar) self.marca_ativa = None def moveu(self, evento): if self.marca_ativa is not None: bbox = self.canvas.coords(self.marca_ativa) bbox[2:4] = [evento.x, evento.y] self.canvas.coords(self.marca_ativa, *bbox) def marcar(self, evento): if self.marca_ativa is None: self.marca_ativa = self.canvas.create_oval(evento.x, evento.y, evento.x, evento.y, outline='green', width=5) else: coords = [int(i) for i in self.canvas.coords(self.marca_ativa)] self.coords['text'] = coords print coords self.marca_ativa = None
class Track: """ operates with list of satellites it can read data about satellites from file, from url, display satellites """ def __init__(self): # loading images: img = Image.open('map.jpg') self.map_img = ImageTk.PhotoImage(img) img = Image.open('sat.png').convert("RGBA") self.sat_img = ImageTk.PhotoImage(img) self.anim = Canvas(width = 1024, height = 513) self.anim.create_image((0,0), anchor = NW, image = self.map_img) self.satellites = [] # list of satelites loaded from TLE self.draw_sats = [] # indices of desired satellites, and their # canvas ID, for animation def load_local(self, file_name): fp = open(file_name, 'r') line = fp.readline() print "load" while line > '': title = line l1 = fp.readline() l2 = fp.readline() tle_data = TLE(title, l1, l2) sat = Satellite(tle_data, datetime.today()) self.satellites.append(sat) line = fp.readline() def load_url(self, url, file_name): # will be improved later,,, now just downloading txt # and writes it to file buff = urllib2.urlopen(url) fp = open(file_name, 'rw') fp.write(buff.read()) def update_satellites(self, dt): """ recalculate data about satellites """ for (index, _id) in self.draw_sats: self.satellites[index].update(dt) # for sat in self.satellites: # sat.update(15) def add_satellite(self, index): # index will be taken from GUI,,,aditional images can be added _id = self.anim.create_image(self.satellites[index].map_coords, image = self.sat_img) self.draw_sats.append((index, _id)) # better use dictionaries # testing: self.satellites[index].get_coords() self.anim.create_line(self.satellites[index].trajectory) def draw(self): """updates position of the satellites on the canvas""" for (index, _id) in self.draw_sats: self.anim.coords(_id, self.satellites[index].map_coords)
class ResultsTable(Frame): """A custom table widget which displays words alongside the users guesses""" def __init__(self, parent, width=400, height=200): Frame.__init__(self, parent) self.canvas = Canvas(self, width=width, height=height, bg="#FFFFFF") self.canvas.configure(bd=2, relief=SUNKEN) self.canvas.pack(side=LEFT) self.centre_line = self.canvas.create_line(0, 0, 0, 0) scrollbar = Scrollbar(self) scrollbar.pack(side=RIGHT, fill=Y) scrollbar.configure(command=self.canvas.yview) self.canvas.configure(yscrollcommand=scrollbar.set, scrollregion=(0, 0, width, height)) self.width=width self.height_in_lines = height/18 self.item_count = 0 self.font = ("Helvetica", 12) def add_word(self, word): """Add a word to the table""" top = 20*self.item_count if top > 200: #If necessary extend scroll region downwards self.canvas.configure(scrollregion=(0, 0, self.width, top+20)) colour = "#139E1C" if word.isCorrect else "#F30000" #Draw the word in the left column self.canvas.create_text(2, top, anchor=NW, text=word, font=self.font) #Draw the guess in the right column self.canvas.create_text(self.width/2+2, top, anchor=NW, text=word.answer, font=self.font, fill=colour) #Draw a line to separate this row from those below self.canvas.create_line(0, top+19, self.width, top+19) #Extend centre line of tablr self.canvas.coords(self.centre_line, self.width/2, 0, self.width/2, top+19) self.item_count += 1 def add_list(self, word_list): """Add a list to the table""" for word in word_list: self.add_word(word) def clear(self): """Clear the table of all words""" self.item_count = 0 self.canvas.delete(ALL)
class App(Frame): """Tkinter App.""" def __init__(self, parent, queue): """Init Tkinter app.""" Frame.__init__(self, parent) self.parent = parent self.parent.wm_attributes('-type', 'dialog') self.queue = queue self.initUI() self.worker() def initUI(self): """Init UI.""" self.parent.title('PySnake') self.canvas = Canvas(self.parent, width=500, height=300, bg='black') self.canvas.pack() self.score = self.canvas.create_text(30, 270, anchor=W, fill='blue', text='Score: 0') self.food = self.canvas.create_rectangle(0, 0, 0, 0, fill='white') self.snake = self.canvas.create_line((0, 0), (0, 0), fill='green', width=10) def worker(self): try: while True: job = self.queue.get_nowait() if job.has_key('snake'): #self.snake = self.canvas.create_line(*job['snake'], fill='green', width=10) points = [x for point in job['snake'] for x in point] self.canvas.coords(self.snake, *points) elif job.has_key('food'): x, y = job['food'] self.canvas.coords(self.food, (x - 5), (y - 5), (x + 5), (y + 5)) elif job.has_key('score'): self.canvas.itemconfigure(self.score, text='Score: {}'.format(job['score'])) elif job.has_key('quit'): self.parent.quit() self.queue.task_done() except Queue.Empty: pass self.after(50, self.worker)
class App(Frame): """Tkinter App.""" def __init__(self, parent, queue): """Init Tkinter app.""" Frame.__init__(self, parent) self.parent = parent self.parent.wm_attributes("-type", "dialog") self.queue = queue self.initUI() self.worker() def initUI(self): """Init UI.""" self.parent.title("PySnake") self.canvas = Canvas(self.parent, width=500, height=300, bg="black") self.canvas.pack() self.score = self.canvas.create_text(30, 270, anchor=W, fill="blue", text="Score: 0") self.food = self.canvas.create_rectangle(0, 0, 0, 0, fill="white") self.snake = self.canvas.create_line((0, 0), (0, 0), fill="green", width=10) def worker(self): try: while True: job = self.queue.get_nowait() if job.has_key("snake"): # self.snake = self.canvas.create_line(*job['snake'], fill='green', width=10) points = [x for point in job["snake"] for x in point] self.canvas.coords(self.snake, *points) elif job.has_key("food"): x, y = job["food"] self.canvas.coords(self.food, (x - 5), (y - 5), (x + 5), (y + 5)) elif job.has_key("score"): self.canvas.itemconfigure(self.score, text="Score: {}".format(job["score"])) elif job.has_key("quit"): self.parent.quit() self.queue.task_done() except Queue.Empty: pass self.after(50, self.worker)
class SpectrumGraph(object): def __init__(self, root): # create bar graph self._canvas = Canvas(root, width=CANVAS_WIDTH, height=CANVAS_HEIGHT, bg='black') self._canvas.pack() self._bars = [] for pos in range(0, CANVAS_WIDTH, BAR_WIDTH): r = self._canvas.create_rectangle(pos, CANVAS_HEIGHT, pos + BAR_WIDTH, 100, fill='white') self._bars.append(r) """ Function set_bar_data(self, data) Takes a 1d signal of 2^N length, and averages it over the bars, then sets the data to the graph eg: an array a[1023:0:] -> a[63:0] """ def set_bar_data(self, data): assert (len(data) % NUM_BARS == 0) stride = len(data) / NUM_BARS bars = np.mean(data.reshape(-1, stride), axis=1) # computes average for bars self._set_bars(bars) """ Given a numpy array of length equal to the number of bars, we set each bar to that particular height """ def _set_bars(self, bars): for i, pos in enumerate(range(0, CANVAS_WIDTH, BAR_WIDTH)): bar_height = min(CANVAS_HEIGHT, CANVAS_HEIGHT * bars[i]) self._canvas.coords(self._bars[i], pos, CANVAS_HEIGHT, pos + BAR_WIDTH, CANVAS_HEIGHT - bar_height)
class Move(Frame): def __init__(self, parent): Frame.__init__(self, parent) self.parent = parent self.initUI() self.animate() def initUI(self): self.parent.title("Move") self.pack(fill=BOTH, expand=1) self.canvas = Canvas(self) self.oval = self.canvas.create_oval(40, 10, 110, 80, outline="black", width=2) self.canvas.pack(fill=BOTH, expand=1) def animate(self): location = self.canvas.coords(self.oval) self.canvas.coords(self.oval, location[0]+2.5, location[1], location[2]+2.5, location[3]) self.after(1000, self.animate)
class ResultsTable(Frame): def __init__(self, parent, width=400, height=200): Frame.__init__(self, parent) self.canvas = Canvas(self, width=width, height=height, bg="#FFFFFF") self.canvas.configure(bd=2, relief=SUNKEN) self.canvas.pack(side=LEFT) self.centre_line = self.canvas.create_line(0, 0, 0, 0) scrollbar = Scrollbar(self) scrollbar.pack(side=RIGHT, fill=Y) scrollbar.configure(command=self.canvas.yview) self.canvas.configure(yscrollcommand=scrollbar.set, scrollregion=(0, 0, width, height)) self.width=width self.height_in_lines = height/18 self.item_count = 0 self.font = ("Helvetica", 12) def add_word(self, word): top = 20*self.item_count if top > 200: self.canvas.configure(scrollregion=(0, 0, self.width, top+20)) colour = "#139E1C" if word.isCorrect else "#F30000" self.canvas.create_text(2, top, anchor=NW, text=word, font=self.font) self.canvas.create_text(self.width/2+2, top, anchor=NW, text=word.answer, font=self.font, fill=colour) self.canvas.create_line(0, top+19, self.width, top+19) self.canvas.coords(self.centre_line, self.width/2, 0, self.width/2, top+19) self.item_count += 1 def add_list(self, word_list): for word in word_list: self.add_word(word) def clear(self): self.item_count = 0 self.canvas.delete(ALL)
class Ex(Frame): def __init__(self,parent): Frame.__init__(self,parent) self.parent = parent self.x_before = 20 self.x_current = 20 self.y_before = 200 self.y_current = 200 self.FirstRun = True self.initUI() self.runRandWalk(STEPS) self.FirstRun = False def initUI(self): self.parent.title("Random Walk Lines 1") self.pack(fill=BOTH,expand=1) self.style = Style() self.style.theme_use("default") frame = Frame(self,relief=RAISED,borderwidth=2) frame.pack(fill=BOTH,expand=True) self.canvas = Canvas(frame) self.canvas.create_line(10,200,390,200,dash=(4,2), width=2) self.canvas.pack(fill=BOTH,expand=1) self.newWalkButton = Button(self,text="New Walk", command=self.newWalk) self.closeButton = Button(self,text="Close", command=self.closeAll) # pack the buttons here self.closeButton.pack(side=RIGHT,padx=5,pady=5) self.newWalkButton.pack(side=RIGHT) def newWalk(self): for x in range(0,STEPS): getTag = "step"+str(x) self.canvas.coords(getTag,(0,0,0,0)) self.x_current = 20 self.x_before = 20 self.y_current = 200 self.y_before = 200 self.runRandWalk(STEPS) def closeAll(self): Frame.quit(self) def RandWalk(self,whichStep): r = random.randint(0,1) addval = 0; toTag = "step"+str(whichStep) if r == 0: addval = ADDVAL else: addval = -ADDVAL self.y_current = self.y_before + addval self.x_current = self.x_before + XSTEP if self.y_current < 200: if self.y_before == 200: if self.FirstRun == True: self.canvas.create_line(self.x_before,self.y_before, self.x_current,self.y_current, fill = "green", width = 5, tags=toTag) else: self.canvas.coords(toTag,(self.x_before,self.y_before, self.x_current,self.y_current),) self.canvas.itemconfig(toTag,fill="green") else: if self.FirstRun == True: self.canvas.create_line(self.x_before,self.y_before, self.x_current,self.y_current, fill = "green", width = 5, tags=toTag) else: self.canvas.coords(toTag,(self.x_before,self.y_before, self.x_current,self.y_current)) self.canvas.itemconfig(toTag,fill="green") else: if self.y_before<200: if self.FirstRun==True: self.canvas.create_line(self.x_before,self.y_before, self.x_current,self.y_current, fill = "green", width = 5, tags=toTag) else: self.canvas.coords(toTag,(self.x_before,self.y_before, self.x_current,self.y_current)) self.canvas.itemconfig(toTag,fill="green") else: if self.FirstRun==True: self.canvas.create_line(self.x_before,self.y_before, self.x_current,self.y_current, fill = "red", width = 5, tags=toTag) else: self.canvas.coords(toTag,(self.x_before,self.y_before, self.x_current,self.y_current)) self.canvas.itemconfig(toTag,fill="red") self.canvas.pack(fill=BOTH,expand=1) self.x_before = self.x_current self.y_before = self.y_current def runRandWalk(self,steps): for x in range(0,steps): self.RandWalk(x)
class Ex(Frame): def __init__(self,parent): Frame.__init__(self,parent) self.parent = parent self.x_before = 400 self.x_current = 400 self.y_before = 400 self.y_current = 400 self.FirstRun = True self.AddVal = ADDVAL self.AddVal_X = ADDVAL_X self.initUI() self.runRandWalk(STEPS) self.FirstRun = False self.Steps = STEPS self.newSteps = STEPS self.XStep = XSTEP def initUI(self): self.parent.title("Random Walk Lines 1") self.pack(fill=BOTH,expand=1) self.style = Style() self.style.theme_use("default") frame = Frame(self,relief=RAISED,borderwidth=2) frame.pack(fill=BOTH,expand=True) self.canvas = Canvas(frame) self.canvas.create_line(10,400,790,400,dash=(4,2), width=2) self.canvas.create_line(400,10,400,790,dash=(4,2), width=2) self.canvas.pack(fill=BOTH,expand=1) self.newWalkButton = Button(self,text="New Walk", command=self.newWalk) self.closeButton = Button(self,text="Close", command=self.closeAll) self.stepsButton = Button(self,text="Send Steps", command=self.sendSteps) self.xSizeButton = Button(self,text="Set X Step", command=self.xSize) self.ySizeButton = Button(self,text="Set Y Step", command=self.ySize) self.xSizeBox = Entry(self,width=10) self.ySizeBox = Entry(self,width=10) self.stepsBox = Entry(self,width=10) # pack the buttons here self.closeButton.pack(side=RIGHT,padx=5,pady=5) self.newWalkButton.pack(side=RIGHT) self.stepsButton.pack(side=RIGHT) self.stepsBox.pack(side=RIGHT) self.xSizeButton.pack(side=RIGHT) self.xSizeBox.pack(side=RIGHT) self.ySizeButton.pack(side=RIGHT) self.ySizeBox.pack(side=RIGHT) def ySize(self): self.AddVal = int(self.ySizeBox.get()) def xSize(self): self.AddVal_X = int(self.xSizeBox.get()) def sendSteps(self): self.newSteps = int(self.stepsBox.get()) def newWalk(self): for x in range(0,self.Steps): getTag = "step"+str(x) self.canvas.coords(getTag,(0,0,0,0)) self.Steps = self.newSteps self.x_current = 400 self.x_before = 400 self.y_current = 400 self.y_before = 400 self.runRandWalk(self.Steps) def closeAll(self): Frame.quit(self) def RandWalk(self,whichStep): r = random.randint(0,1) rx = random.randint(0,1) addval = 0; addval_x = 0; toTag = "step"+str(whichStep) if r == 0: addval = (self.AddVal) else: addval = -(self.AddVal) if rx==0: addval_x = (self.AddVal_X) else: addval_x = -(self.AddVal_X) self.y_current = self.y_before + addval self.x_current = self.x_before + addval_x if self.y_current < 200: if self.y_before == 200: if self.FirstRun == True: self.canvas.create_line(self.x_before,self.y_before, self.x_current,self.y_current, fill = "green", width = 5, tags=toTag) else: self.canvas.coords(toTag,(self.x_before,self.y_before, self.x_current,self.y_current),) self.canvas.itemconfig(toTag,fill="green") else: if self.FirstRun == True: self.canvas.create_line(self.x_before,self.y_before, self.x_current,self.y_current, fill = "green", width = 5, tags=toTag) else: self.canvas.coords(toTag,(self.x_before,self.y_before, self.x_current,self.y_current)) self.canvas.itemconfig(toTag,fill="green") else: if self.y_before<200: if self.FirstRun==True: self.canvas.create_line(self.x_before,self.y_before, self.x_current,self.y_current, fill = "green", width = 5, tags=toTag) else: self.canvas.coords(toTag,(self.x_before,self.y_before, self.x_current,self.y_current)) self.canvas.itemconfig(toTag,fill="green") else: if self.FirstRun==True: self.canvas.create_line(self.x_before,self.y_before, self.x_current,self.y_current, fill = "red", width = 5, tags=toTag) else: self.canvas.coords(toTag,(self.x_before,self.y_before, self.x_current,self.y_current)) self.canvas.itemconfig(toTag,fill="red") self.canvas.pack(fill=BOTH,expand=1) self.x_before = self.x_current self.y_before = self.y_current def runRandWalk(self,steps): for x in range(0,steps): self.RandWalk(x)
class ProgressBar: def __init__(self, master=None, orientation="horizontal", min=0, max=100, width=100, height=18, doLabel=1, appearance="sunken", fillColor="blue", background="gray", labelColor="yellow", labelFont="Verdana", labelText="", labelFormat="%d%%", value=0, bd=2): # preserve various values self.master=master self.orientation=orientation self.min=min self.max=max self.width=width self.height=height self.doLabel=doLabel self.fillColor=fillColor self.labelFont= labelFont self.labelColor=labelColor self.background=background self.labelText=labelText self.labelFormat=labelFormat self.value=value self.frame=Frame(master, relief=appearance, bd=bd) self.canvas=Canvas(self.frame, height=height, width=width, bd=0, highlightthickness=0, background=background) self.scale=self.canvas.create_rectangle(0, 0, width, height, fill=fillColor) self.label=self.canvas.create_text(self.canvas.winfo_reqwidth() / 2, height / 2, text=labelText, anchor="c", fill=labelColor, font=self.labelFont) self.update() self.canvas.pack(side='top', fill='x', expand='no') def updateProgress(self, newValue, newMax=None): if newMax: self.max = newMax self.value = newValue self.update() def update(self): # Trim the values to be between min and max value=self.value if value > self.max: value = self.max if value < self.min: value = self.min # Adjust the rectangle if self.orientation == "horizontal": self.canvas.coords(self.scale, 0, 0, float(value) / self.max * self.width, self.height) else: self.canvas.coords(self.scale, 0, self.height - (float(value) / self.max*self.height), self.width, self.height) # Now update the colors self.canvas.itemconfig(self.scale, fill=self.fillColor) self.canvas.itemconfig(self.label, fill=self.labelColor) # And update the label if self.doLabel: if value: if value >= 0: pvalue = int((float(value) / float(self.max)) * 100.0) else: pvalue = 0 self.canvas.itemconfig(self.label, text=self.labelFormat % pvalue) else: self.canvas.itemconfig(self.label, text='') else: self.canvas.itemconfig(self.label, text=self.labelFormat % self.labelText) self.canvas.update_idletasks()
class RoomDisplay(Frame): def __init__(self, parent, actionList, room): Frame.__init__(self, parent) self.actionList = actionList self.room = room self.parent = parent self.initUI() self.displayMotion() def initUI(self): self.parent.title("Room") self.pack(fill=BOTH, expand=1) self.canvas = Canvas(self) for level in xrange(0, len(self.room)): for grid in xrange(0, len(self.room[level])): if self.room[level][grid] == 0.0: self.canvas.create_line((grid+1)*50, 50+100*(len(self.room)-level), (grid+2)*50, 50+100*(len(self.room)-level), width=2) else: self.canvas.create_rectangle((grid+1)*50, 50+100*(len(self.room)-level), (grid+2)*50, 50+100*(len(self.room)-level-self.room[level][grid]), outline="black", fill="black", width=2) self.canvas.create_line(50, 50, 50, 50+100*len(self.room), width=2) self.canvas.create_line(400, 50, 400, 50+100*len(self.room), width=2) character_one = self.characterXYCoordinates(self.actionList[0][0], LEFT) character_two = self.characterXYCoordinates(self.actionList[0][1], RIGHT) self.character_one_side = LEFT self.character_two_side = RIGHT self.character_one = self.canvas.create_oval(character_one[0], character_one[1], character_one[2], character_one[3], outline="red", fill="red", width=2) self.character_two = self.canvas.create_oval(character_two[0], character_two[1], character_two[2], character_two[3], outline="blue", fill="blue", width=2) self.currentAction = 0 self.canvas.pack(fill=BOTH, expand=1) def characterXYCoordinates(self, state, side): left_boundary = 52.5 + 50*state[0] if side == LEFT: left_boundary = left_boundary + 25 bottom_boundary = 50 + 100*(len(self.room)-state[1]-self.room[state[1]][state[0]]) - 20 return (left_boundary, bottom_boundary, left_boundary+20, bottom_boundary-20) def displayMotion(self): if self.currentAction < len(self.actionList)-1: print self.actionList[self.currentAction+1] if self.actionList[self.currentAction][2] == self.actionList[self.currentAction+1][2] and \ self.actionList[self.currentAction][3] == 0 and \ self.actionList[self.currentAction+1][3] == 0: # Switch sides old_character_one = self.characterXYCoordinates(self.actionList[self.currentAction][0], self.character_one_side) old_character_two = self.characterXYCoordinates(self.actionList[self.currentAction][1], self.character_two_side) self.character_one_side = switchSides(self.character_one_side) self.character_two_side = switchSides(self.character_two_side) new_character_one = self.characterXYCoordinates(self.actionList[self.currentAction+1][0], self.character_one_side) new_character_two = self.characterXYCoordinates(self.actionList[self.currentAction+1][1], self.character_two_side) else: old_character_one = self.characterXYCoordinates(self.actionList[self.currentAction][0], self.character_one_side) old_character_two = self.characterXYCoordinates(self.actionList[self.currentAction][1], self.character_two_side) new_character_one = self.characterXYCoordinates(self.actionList[self.currentAction+1][0], self.character_one_side) new_character_two = self.characterXYCoordinates(self.actionList[self.currentAction+1][1], self.character_two_side) self.animate(self.character_one, old_character_one, new_character_one, 0, 0) self.animate(self.character_two, old_character_two, new_character_two, 0, 1) self.currentAction = self.currentAction+1 def animate(self, character, start, end, iteration, thread_index): interpolate0 = start[0] + (end[0]-start[0])*iteration/NUM_ITERATIONS interpolate1 = start[1] + (end[1]-start[1])*iteration/NUM_ITERATIONS interpolate2 = start[2] + (end[2]-start[2])*iteration/NUM_ITERATIONS interpolate3 = start[3] + (end[3]-start[3])*iteration/NUM_ITERATIONS self.canvas.coords(character, interpolate0, interpolate1, interpolate2, interpolate3) if iteration < NUM_ITERATIONS: self.after(10, self.animate, character, start, end, iteration+1, thread_index) elif thread_index == 0: self.after(10, self.displayMotion)
class Display(ttkFrame): ''' Displays the drone state on a graphical interface ''' REFRESH_PERIOD = 0.2 #5Hz by default ARM_LENGTH = 23 #pixels PIXELS_METER = 100.0 #pixels/meter _instance = None @staticmethod def getInstance(): if Display._instance == None: root = Tk() root.geometry() Display._instance = Display(root) return Display._instance def __init__(self, parent): ''' Constructor ''' ttkFrame.__init__(self, parent) self._refreshTime = Display.REFRESH_PERIOD self._stateProvider = None self._launcherMethod = None self._isRunning = False self._droneThread = None self._parent = parent self._initUI() def setStateProvider(self, stateProvider): ''' Set the flight state provider ''' self._stateProvider = stateProvider return self def setLauncherMethod(self, launcherMethod): ''' Set the method which controlls the process. It is required since the main thread (main loop) is used by the GUI. Therefore, the process for the business logic must be executed within another thread. ''' self._launcherMethod = launcherMethod return self def setRefreshTime(self, refreshTime): self._refreshTime = refreshTime return self def start(self): if self._launcherMethod and not self._droneThread: self._droneThread = Thread(target=self._launcherMethod) self._droneThread.start() self._isRunning = True if self._stateProvider: self._refresh() self._parent.mainloop() def stop(self): self._isRunning = False if self._droneThread and self._droneThread.isAlive(): self._droneThread.join(5.0) def quit(self): self.stop() ttkFrame.quit(self) def _initUI(self): self._parent.title("Drone Flight Emulator") self.style = Style() self.style.theme_use("default") self.pack(fill=BOTH, expand=1) #Draw frame drawFrame = tkFrame(self) drawFrame.grid(column=0, row=0, sticky="W") self._canvasYZ = Canvas(drawFrame, bg="white", height=200, width=200) self._canvasYZ.grid(column=0, row=0, sticky="W", padx=(2,0), pady=(2,0)) self._canvasXZ = Canvas(drawFrame, bg="white", height=200, width=200) self._canvasXZ.grid(column=1, row=0, sticky="E", padx=(2,2), pady=(2,0)) self._canvasXY = Canvas(drawFrame, bg="white", height=200, width=400) self._canvasXY.grid(column=0, row=1, columnspan=2, sticky="S", padx=(2,2), pady=(0,2)) self._linesXY = [self._canvasXY.create_line(200,100, 200, 90, fill="#ff0000"), \ self._canvasXY.create_line(200,100, 210, 100, fill="#0000ff"), \ self._canvasXY.create_line(200,100, 200, 110, fill="#0000ff"), \ self._canvasXY.create_line(200,100, 190, 100, fill="#0000ff")] self._linesYZ = [self._canvasYZ.create_line(100,200, 90, 200, fill="#0000ff"), \ self._canvasYZ.create_line(100,200, 110, 200, fill="#0000ff")] self._linesXZ = [self._canvasXZ.create_line(100,200, 90, 200, fill="#0000ff"), \ self._canvasXZ.create_line(100,200, 110, 200, fill="#0000ff")] #Info frame infoFrame = tkFrame(self) infoFrame.grid(column=1, row=0, sticky="NE", padx=4) #Angles Label(infoFrame, text="Coords").grid(column=0, row=0, sticky="WE") self._coordTexts = [StringVar(),StringVar(),StringVar()] for index in range(3): Entry(infoFrame, textvariable=self._coordTexts[index], state=DISABLED, width=5).grid(column=index, row=1) #Angles Label(infoFrame, text="Angles").grid(column=0, row=2, sticky="WE") self._angleTexts = [StringVar(),StringVar(),StringVar()] for index in range(3): Entry(infoFrame, textvariable=self._angleTexts[index], state=DISABLED, width=5).grid(column=index, row=3) #Accels Label(infoFrame, text="Accels").grid(column=0, row=4, sticky="WE") self._accelTexts = [StringVar(),StringVar(),StringVar()] for index in range(3): Entry(infoFrame, textvariable=self._accelTexts[index], state=DISABLED, width=5).grid(column=index, row=5) #Speeds Label(infoFrame, text="Speeds").grid(column=0, row=6, sticky="WE") self._speedTexts = [StringVar(),StringVar(),StringVar()] for index in range(3): Entry(infoFrame, textvariable=self._speedTexts[index], state=DISABLED, width=5).grid(column=index, row=7) def _plotXY(self, coord, angles): x = int((coord[0]*Display.PIXELS_METER + 200.0) % 400.0) y = int((100.0 - coord[1]*Display.PIXELS_METER) % 200.0) sinz = sin(angles[2]) cosz = cos(angles[2]) lines = [Vector.rotateVector(line, sinz, cosz) \ for line in [ [0, Display.ARM_LENGTH], \ [Display.ARM_LENGTH, 0], \ [0, -Display.ARM_LENGTH], \ [-Display.ARM_LENGTH, 0]] ] for index in range(4): self._canvasXY.coords(self._linesXY[index], x, y, x+lines[index][0], y-lines[index][1]) def _plotHeight(self, x, y, angle, canvas, lines): cosine = cos(angle) sine = sin(angle) vectors = [Vector.rotateVector(vector, sine, cosine) \ for vector in [[-Display.ARM_LENGTH, 0], \ [Display.ARM_LENGTH, 0]] ] for index in range(2): canvas.coords(lines[index], x, y, x+vectors[index][0], y+vectors[index][1]) def _plotXZ(self, coord, angles): x = 100 y = int(200.0 - (coord[2]*Display.PIXELS_METER%200.0)) self._plotHeight(x, y, angles[1], self._canvasXZ, self._linesXZ) def _plotYZ(self, coord, angles): x = 100 y = int(200.0 - (coord[2]*Display.PIXELS_METER%200.0)) self._plotHeight(x, y, -angles[0], self._canvasYZ, self._linesYZ) def _refresh(self): if self._isRunning: state = self._stateProvider.getState() if not state._crashed: angles = [radians(angle) for angle in state._angles] self._plotXY(state._coords, angles) self._plotXZ(state._coords, angles) self._plotYZ(state._coords, angles) for index in range(3): self._coordTexts[index].set("{0:.3f}".format(state._coords[index])) self._angleTexts[index].set("{0:.3f}".format(state._angles[index])) self._accelTexts[index].set("{0:.3f}".format(state._accels[index])) self._speedTexts[index].set("{0:.3f}".format(state._speeds[index])) else: self._canvasXY.create_text((200,100), text="CRASHED!", fill="#ff0000") self._canvasXZ.create_text((100,100), text="CRASHED!", fill="#ff0000") self._canvasYZ.create_text((100,100), text="CRASHED!", fill="#ff0000") self.update_idletasks() self.after(int(self._refreshTime * 1000.0), self._refresh)
class Game(): WIDTH = 300 HEIGHT = 500 def start(self): '''Starts the game. Creates a window, a canvas, and a first shape. Binds the event handler. Then starts a GUI timer of ms interval self.speed and starts the GUI main loop. ''' #TODO start() needs to be refactored so that the creation of the # window, label, and canvas are independent from setting them to # defaults and starting the game. # # There should also be a way for the user to restart and pause # the game if he or she wishes. # # It's a little weird that level is based only on time and that # as a result it increases faster and faster. Wouldn't it make # more sense for level to be a result of completed lines? self.level = 1 self.score = 0 self.speed = 500 self.counter = 0 self.create_new_game = True self.root = Tk() self.root.title("Tetris") self.status_var = StringVar() self.status_var.set("Level: 1, Score: 0") self.status = Label(self.root, textvariable=self.status_var, font=("Helvetica", 10, "bold")) self.status.pack() self.canvas = Canvas( self.root, width=Game.WIDTH, height=Game.HEIGHT) self.canvas.pack() self.root.bind("<Key>", self.handle_events) self.timer() self.root.mainloop() def timer(self): '''Every self.speed ms, attempt to cause the current_shape to fall(). If fall() returns False, create a new shape and check if it can fall. If it can't, then the game is over. ''' if self.create_new_game == True: self.current_shape = Shape(self.canvas) self.create_new_game = False if not self.current_shape.fall(): lines = self.remove_complete_lines() if lines: self.score += 10 * self.level**2 * lines**2 self.status_var.set("Level: %d, Score: %d" % (self.level, self.score)) self.current_shape = Shape(self.canvas) if self.is_game_over(): #TODO This is a problem. You rely on the timer method to # create a new game rather than creating it here. As a # result, there is an intermittent error where the user # event keypress Down eventually causes can_move_box # to throw an IndexError, since the current shape has # no boxes. Instead, you need to cleanly start a new # game. I think refactoring start() might help a lot # here. # # Furthermore, starting a new game currently doesn't reset # the levels. You should place all your starting constants # in the same place so it's clear what needs to be reset # when. self.create_new_game = True self.game_over() self.counter += 1 if self.counter == 5: self.level += 1 self.speed -= 20 self.counter = 0 self.status_var.set("Level: %d, Score: %d" % (self.level, self.score)) self.root.after(self.speed, self.timer) def handle_events(self, event): '''Handle all user events.''' if event.keysym == "Left": self.current_shape.move(-1, 0) if event.keysym == "Right": self.current_shape.move(1, 0) if event.keysym == "Down": self.current_shape.move(0, 1) if event.keysym == "Up": self.current_shape.rotate() def is_game_over(self): '''Check if a newly created shape is able to fall. If it can't fall, then the game is over. ''' for box in self.current_shape.boxes: if not self.current_shape.can_move_box(box, 0, 1): return True return False def remove_complete_lines(self): shape_boxes_coords = [self.canvas.coords(box)[3] for box in self.current_shape.boxes] all_boxes = self.canvas.find_all() all_boxes_coords = {k : v for k, v in zip(all_boxes, [self.canvas.coords(box)[3] for box in all_boxes])} lines_to_check = set(shape_boxes_coords) boxes_to_check = dict((k, v) for k, v in all_boxes_coords.iteritems() if any(v == line for line in lines_to_check)) counter = Counter() for box in boxes_to_check.values(): counter[box] += 1 complete_lines = [k for k, v in counter.iteritems() if v == (Game.WIDTH/Shape.BOX_SIZE)] if not complete_lines: return False for k, v in boxes_to_check.iteritems(): if v in complete_lines: self.canvas.delete(k) del all_boxes_coords[k] #TODO Would be cooler if the line flashed or something for (box, coords) in all_boxes_coords.iteritems(): for line in complete_lines: if coords < line: self.canvas.move(box, 0, Shape.BOX_SIZE) return len(complete_lines) def game_over(self): self.canvas.delete(Tkinter.ALL) tkMessageBox.showinfo( "Game Over", "You scored %d points." % self.score)
class Breakout(Tk): def __init__(self): Tk.__init__(self) self.geometry('400x400') self.resizable(0,0) # game screen self.canvas = Canvas(self, bg='black', width=400, height=400) self.canvas.pack(expand=1, fill=BOTH) # ball self._initiate_new_ball() # paddle self.canvas.create_rectangle(175,375,225,385, fill='black', outline='white', tags='paddle') self.bind('<Key>', self._move_paddle) # bricks self.bricks = {} brick_coords = [5,5,35,15] for i in range(39): self.canvas.create_rectangle(*brick_coords, outline='white', fill=('#{}'.format(randint(100000,999999))), tags='brick' + str(i)) self.bricks['brick' + str(i)] = None brick_coords[0] += 30; brick_coords[2] += 30 if brick_coords[2] > 395: brick_coords[0] = 5; brick_coords[2] = 35 brick_coords[1] += 10; brick_coords[3] += 10 def _initiate_new_ball(self): if self.canvas.find_withtag('ball'): self.canvas.delete('ball') self.x = 60; self.y = 100 self.angle = 140; self.speed = 5 self.canvas.create_oval(self.x,self.y,self.x+10,self.y+10, fill='lawn green', outline='white', tags='ball') self.after(1000, self._move_ball) def _move_paddle(self, event): if event.keysym == 'Left': if self.canvas.coords('paddle')[0] > 0: self.canvas.move('paddle', -10, 0) elif event.keysym == 'Right': if self.canvas.coords('paddle')[2] < 400: self.canvas.move('paddle', +10, 0) def _move_ball(self): # variables to determine where ball is in relation to other objects ball = self.canvas.find_withtag('ball')[0] bounds = self.canvas.find_overlapping(0,0,400,400) paddle = self.canvas.find_overlapping(*self.canvas.coords('paddle')) for brick in self.bricks.iterkeys(): self.bricks[brick] = self.canvas.find_overlapping(*self.canvas.bbox(brick)) # calculate change in x,y values of ball angle = self.angle - 90 # correct for quadrant IV increment_x = cos(radians(angle)) * self.speed increment_y = sin(radians(angle)) * self.speed # finite state machine to set ball state if ball in bounds: self.ball_state = 'moving' for brick, hit in self.bricks.iteritems(): if ball in hit: self.ball_state = 'hit_brick' delete_brick = brick elif ball in paddle: self.ball_state = 'hit_wall' elif ball not in bounds: if self.canvas.coords('ball')[1] < 400: self.ball_state = 'hit_wall' else: self.ball_state = 'out_of_bounds' self._initiate_new_ball() # handler for ball state if self.ball_state is 'moving': self.canvas.move('ball', increment_x, increment_y) self.after(15, self._move_ball) elif self.ball_state is 'hit_brick' or self.ball_state is 'hit_wall': if self.ball_state == 'hit_brick': self.canvas.delete(delete_brick) del self.bricks[delete_brick] self.canvas.move('ball', -increment_x, -increment_y) self.angle += choice([119, 120, 121]) self._move_ball()
class TKEA_win(object): def __init__(self, ea, p, rec, varlist): self.vl = varlist # list of EA attributes which you wanna make accessible via window self.ea = ea # the EA instance self.ea.generation_callbacks.append(self.update_solu_canvas) self.ea.generation_callbacks.append(self.update_mstep_bar) self.ea.generation_callbacks.append(self.rec_save_status) self.ea.generation_callbacks.append(self.acp_update) self.acp_type = 'linear' # also allowed up to date: 'semilogy' self.acp_ylim = False self.acp_freq = 1 self.update_freq = 1 self.p = p # main population self.rec = rec tmppop = population_like(p, size=1) self.frontman = tmppop[0] # an extra individual, the one bein plotted def appear(self): self.mwin = Tk() # root or main window self.mwin.title('EA progress visualisation') self.setupFig() self.setupWindow() def setupFig(self): self.fig = plt.figure(figsize=(8, 7), dpi=80) self.sp1 = self.fig.add_subplot( 211 ) # additional colorbar might be created under the name self.sp1_cb self.sp2 = self.fig.add_subplot( 212 ) # additional colorbar might be created under the name self.sp2_cb self.sp1t = self.sp1.set_title('ini') self.sp2t = self.sp2.set_title('ini') def setupWindow(self): self.f_inp = Frame(self.mwin) self.f_inp.pack(side='left') self.f_plot = Frame(self.mwin) self.f_plot.pack(side='right') self.c = FigureCanvasTkAgg(self.fig, master=self.f_plot) self.c.show() self.c.get_tk_widget().pack(side=TOP, fill=BOTH, expand=1) # setup the input area self.f_actn = LabelFrame(self.f_inp, text='action') self.f_actn.grid(row=0, column=0) self.f_gg = Frame(self.f_actn) self.f_gg.pack() l_gg = Label(self.f_gg, text='generations') l_gg.pack() self.e_gg = Entry(self.f_gg) self.e_gg.pack() self.e_gg.insert(0, '40') # number of generations self.b_rini = Button(self.f_actn, text='randini', command=self.randini) self.b_rini.pack() self.b_run1 = Button(self.f_actn, text='update & run', command=self.run_with_readout) self.b_run1.pack() self.b_run2 = Button(self.f_actn, text='run (continue)', command=self.run_no_readout) self.b_run2.pack() if len(self.vl): self.add_entries(self.vl) # draw initial plot self.draw_ini_solu( ) # sort of setting up instructive initial geometry plot of non-optimised geometry self.acp_ini() self.f_tb = Frame(self.f_plot) self.f_tb.pack() self.tb = NavigationToolbar2TkAgg(self.c, self.f_tb) self.c2 = Canvas(self.f_inp, width=80, height=140) self.c2.grid(row=4, column=0) self.ini_mstep_bar() def add_entries(self, vl): for el in vl: if not hasattr(self.ea, el['name']): raise TypeError( 'you try to set up an entry for a name which is no attribute of the chosen EA' ) fr = Frame(self.f_actn) fr.pack() lab = Label(fr, text=el['name']) lab.pack() e = Entry(fr) e.pack() e.insert(0, str(el['inival'])) # number of generations el['Entry'] = e def draw_ini_solu(self): self.frontman.plot_into_axes(self.sp1) txt = 'initial DNA'.format(self.frontman.DNA) self.sp1t.set_text(txt) def draw_solu(self, dude): self.frontman.copy_DNA_of(dude, copyscore=True, copyparents=True, copyancestcode=True) self.frontman.evaluate() self.frontman.update_plot(self.sp1) txt = 'generation {}: score is {:.3f} after {} function calls'.format( self.p.gg, self.ea.bestdude.score, self.ea.tell_neval()) #self.sp1t.set_text(txt) self.sp1.set_title(txt) self.c.draw() def mainloop(self): self.mwin.mainloop() def randini(self): self.p.reset() self.rec.clear() self.ea.bestdude = None self.ea.zeroth_generation(random_ini=True) self.draw_solu(self.ea.bestdude) self.c.draw() def run_with_readout(self): for el in self.vl: if el['type'] is float: val = float(el['Entry'].get()) exec('self.ea.' + el['name'] + '=' + str(val)) elif el['type'] is int: val = int(float(el['Entry'].get())) exec('self.ea.' + el['name'] + '=' + str(val)) elif el['type'] is str: val = el['Entry'].get() exec('self.ea.' + el['name'] + "='" + val + "'") elif el['type'] is list: val = el['Entry'].get() exec('self.ea.' + el['name'] + "=" + val) print 'string {} and what resulted {}'.format( val, eval('self.ea.' + el['name'])) else: raise NotImplementedError( 'only float and int parameters cared for at this point') self.ea.run(int(float(self.e_gg.get()))) def run_no_readout(self): self.ea.run(int(float(self.e_gg.get()))) def update_solu_canvas(self, eaobj): if np.mod(self.p.gg, self.update_freq) == 0: self.draw_solu(self.ea.bestdude) def ini_mstep_bar(self): fg_color = bluered4hex(0.36) #textcolor='white' self.c2.create_rectangle(43, 0, 57, 140, fill='white', outline='white') mstep_barheight = int(-0.25 * log10(self.ea.mstep) * 140) mstep_barheight = clip(mstep_barheight, 0, 140) self.mstep_bar = self.c2.create_rectangle(43, mstep_barheight, 57, 140, fill='green', outline='green') for h in [2, 35, 70, 105, 140]: self.c2.create_line(40, h, 60, h, width=2, fill=fg_color) for h, poww in zip([6, 30, 65, 100, 130], ['0', '-1', '-2', '-3', '-4']): self.c2.create_text(20, h, text='10**' + poww, font=('Courier', '6')) def update_mstep_bar(self, eaobj): mstep_barheight = int(-0.25 * log10(self.ea.mstep) * 140) mstep_barheight = clip(mstep_barheight, 0, 140) self.c2.coords(self.mstep_bar, 43, mstep_barheight, 57, 140) self.mwin.update_idletasks() def rec_save_status(self, eaobj): self.rec.save_status() def acp_ini(self, whiggle=0): x = [] y = [] farbe = [] for i, g in enumerate(self.rec.gg): for j in range(self.p.psize): x.append(g) y.append(self.rec.adat['scores'][i][j]) farbe.append(self.rec.adat['ancestcodes'][i][j]) x.append(0) y.append(0) farbe.append(0.) # for normalisation of color map x.append(0) y.append(0) farbe.append(1.) # for normalisation of color map x = flipud(array(x)) y = flipud(array(y)) farbe = flipud(array(farbe)) if whiggle: x = x + whiggle * npr.rand(len(x)) - 0.5 * whiggle self.acdots = self.sp2.scatter(x, y, marker='o', c=farbe, cmap=ancestcolors, zorder=True) if self.acp_type == 'semilogy': self.sp2.semilogy() if self.acp_ylim: self.sp2.axis((0, self.p.gg, self.acp_ylim[0], self.acp_ylim[1])) else: self.sp2.axis((0, self.p.gg, 0, np.max(y))) def acp_update(self, eaobj, whiggle=0): if np.mod(self.p.gg, self.acp_freq) == 0: self.sp2.cla() self.acp_ini(whiggle=whiggle) self.c.draw()
class Game(): WIDTH = 300 HEIGHT = 500 def start(self): '''Starts the game. Creates a window, a canvas, and a first shape. Binds the event handler. Then starts a GUI timer of ms interval self.speed and starts the GUI main loop. ''' #TODO start() needs to be refactored so that the creation of the # window, label, and canvas are independent from setting them to # defaults and starting the game. # # There should also be a way for the user to restart and pause # the game if he or she wishes. # # It's a little weird that level is based only on time and that # as a result it increases faster and faster. Wouldn't it make # more sense for level to be a result of completed lines? self.level = 1 self.score = 0 self.speed = 500 self.counter = 0 self.create_new_game = True self.root = Tk() self.root.title("Tetris") self.status_var = StringVar() self.status_var.set("Level: 1, Score: 0") self.status = Label(self.root, textvariable=self.status_var, font=("Helvetica", 10, "bold")) self.status.pack() self.canvas = Canvas(self.root, width=Game.WIDTH, height=Game.HEIGHT) self.canvas.pack() self.root.bind("<Key>", self.handle_events) self.timer() self.root.mainloop() def timer(self): '''Every self.speed ms, attempt to cause the current_shape to fall(). If fall() returns False, create a new shape and check if it can fall. If it can't, then the game is over. ''' if self.create_new_game == True: self.current_shape = Shape(self.canvas) self.create_new_game = False if not self.current_shape.fall(): lines = self.remove_complete_lines() if lines: self.score += 10 * self.level**2 * lines**2 self.status_var.set("Level: %d, Score: %d" % (self.level, self.score)) self.current_shape = Shape(self.canvas) if self.is_game_over(): #TODO This is a problem. You rely on the timer method to # create a new game rather than creating it here. As a # result, there is an intermittent error where the user # event keypress Down eventually causes can_move_box # to throw an IndexError, since the current shape has # no boxes. Instead, you need to cleanly start a new # game. I think refactoring start() might help a lot # here. # # Furthermore, starting a new game currently doesn't reset # the levels. You should place all your starting constants # in the same place so it's clear what needs to be reset # when. self.create_new_game = True self.game_over() self.counter += 1 if self.counter == 5: self.level += 1 self.speed -= 20 self.counter = 0 self.status_var.set("Level: %d, Score: %d" % (self.level, self.score)) self.root.after(self.speed, self.timer) def handle_events(self, event): '''Handle all user events.''' if event.keysym == "Left": self.current_shape.move(-1, 0) if event.keysym == "Right": self.current_shape.move(1, 0) if event.keysym == "Down": self.current_shape.move(0, 1) if event.keysym == "Up": self.current_shape.rotate() def is_game_over(self): '''Check if a newly created shape is able to fall. If it can't fall, then the game is over. ''' for box in self.current_shape.boxes: if not self.current_shape.can_move_box(box, 0, 1): return True return False def remove_complete_lines(self): shape_boxes_coords = [ self.canvas.coords(box)[3] for box in self.current_shape.boxes ] all_boxes = self.canvas.find_all() all_boxes_coords = { k: v for k, v in zip(all_boxes, [self.canvas.coords(box)[3] for box in all_boxes]) } lines_to_check = set(shape_boxes_coords) boxes_to_check = dict((k, v) for k, v in all_boxes_coords.iteritems() if any(v == line for line in lines_to_check)) counter = Counter() for box in boxes_to_check.values(): counter[box] += 1 complete_lines = [ k for k, v in counter.iteritems() if v == (Game.WIDTH / Shape.BOX_SIZE) ] if not complete_lines: return False for k, v in boxes_to_check.iteritems(): if v in complete_lines: self.canvas.delete(k) del all_boxes_coords[k] #TODO Would be cooler if the line flashed or something for (box, coords) in all_boxes_coords.iteritems(): for line in complete_lines: if coords < line: self.canvas.move(box, 0, Shape.BOX_SIZE) return len(complete_lines) def game_over(self): self.canvas.delete(Tkinter.ALL) tkMessageBox.showinfo("Game Over", "You scored %d points." % self.score)
class Cockpit(ttkFrame): ''' Remote controller GUI ''' KEY_ANG_SPEED = "ang-speed" KEY_ANGLES = "angles" KEY_ACCEL = "accel" PID_KEYS = ["P", "I", "D"] DEFAULT_DRONE_IP = "192.168.1.130" DEFAULT_DRONE_PORT = 2121 DIR_NONE = 0 DIR_VERTICAL = 1 DIR_HORIZONTAL = 2 MAX_ACCEL = 10.0 #TODO angles. Replace by m/s² MAX_ACCEL_Z = 0.1 #m/s² MAX_ANGLE_SPEED = 50.0 #º/s def __init__(self, parent, isDummy = False, droneIp = DEFAULT_DRONE_IP, dronePort = DEFAULT_DRONE_PORT): ''' Constructor ''' ttkFrame.__init__(self, parent) self._started = IntVar() self._integralsEnabled = IntVar() self._target = [0.0] * 4 self._selectedPidConstats = "--" self._pidConstants = { Cockpit.KEY_ANG_SPEED:{ "X":{ "P": 0.0, "I": 0.0, "D": 0.0 }, "Y":{ "P": 0.0, "I": 0.0, "D": 0.0 }, "Z":{ "P": 0.0, "I": 0.0, "D": 0.0 } }, Cockpit.KEY_ANGLES: { "X":{ "P": 0.0, "I": 0.0, "D": 0.0 }, "Y":{ "P": 0.0, "I": 0.0, "D": 0.0 } }, Cockpit.KEY_ACCEL:{ "X":{ "P": 0.0, "I": 0.0, "D": 0.0 }, "Y":{ "P": 0.0, "I": 0.0, "D": 0.0 }, "Z":{ "P": 0.0, "I": 0.0, "D": 0.0 } } } self.parent = parent self.initUI() self._controlKeysLocked = False if not isDummy: self._link = INetLink(droneIp, dronePort) else: self._link = ConsoleLink() self._link.open() self._updateInfoThread = Thread(target=self._updateInfo) self._updateInfoThreadRunning = False self._readingState = False self._start() def initUI(self): self.parent.title("Drone control") self.style = Style() self.style.theme_use("default") self.pack(fill=BOTH, expand=1) self.parent.bind_all("<Key>", self._keyDown) self.parent.bind_all("<KeyRelease>", self._keyUp) if system() == "Linux": self.parent.bind_all("<Button-4>", self._onMouseWheelUp) self.parent.bind_all("<Button-5>", self._onMouseWheelDown) else: #case of Windows self.parent.bind_all("<MouseWheel>", self._onMouseWheel) #Commands commandsFrame = tkFrame(self) commandsFrame.grid(column=0, row=0, sticky="WE") self._startedCB = Checkbutton(commandsFrame, text="On", variable=self._started, command=self._startedCBChanged) self._startedCB.pack(side=LEFT, padx=4) self._integralsCB = Checkbutton(commandsFrame, text="Int.", variable=self._integralsEnabled, \ command=self._integralsCBChanged, state=DISABLED) self._integralsCB.pack(side=LEFT, padx=4) self._quitButton = Button(commandsFrame, text="Quit", command=self.exit) self._quitButton.pack(side=LEFT, padx=2, pady=2) # self._angleLbl = Label(commandsFrame, text="Angle") # self._angleLbl.pack(side=LEFT, padx=4) # # self._angleEntry = Entry(commandsFrame, state=DISABLED) # self._angleEntry.pack(side=LEFT) #Info infoFrame = tkFrame(self) infoFrame.grid(column=1, row=1, sticky="E", padx=4) #Throttle Label(infoFrame, text="Throttle").grid(column=0, row=0, sticky="WE") self._throttleTexts = [StringVar(),StringVar(),StringVar(),StringVar()] Entry(infoFrame, textvariable=self._throttleTexts[3], state=DISABLED, width=5).grid(column=0, row=1) Entry(infoFrame, textvariable=self._throttleTexts[0], state=DISABLED, width=5).grid(column=1, row=1) Entry(infoFrame, textvariable=self._throttleTexts[2], state=DISABLED, width=5).grid(column=0, row=2) Entry(infoFrame, textvariable=self._throttleTexts[1], state=DISABLED, width=5).grid(column=1, row=2) #Angles Label(infoFrame, text="Angles").grid(column=0, row=3, sticky="WE") self._angleTexts = [StringVar(),StringVar(),StringVar()] for index in range(3): Entry(infoFrame, textvariable=self._angleTexts[index], state=DISABLED, width=5).grid(column=index, row=4) #Accels Label(infoFrame, text="Accels").grid(column=0, row=5, sticky="WE") self._accelTexts = [StringVar(),StringVar(),StringVar()] for index in range(3): Entry(infoFrame, textvariable=self._accelTexts[index], state=DISABLED, width=5).grid(column=index, row=6) #Speeds Label(infoFrame, text="Speeds").grid(column=0, row=7, sticky="WE") self._speedTexts = [StringVar(),StringVar(),StringVar()] for index in range(3): Entry(infoFrame, textvariable=self._speedTexts[index], state=DISABLED, width=5).grid(column=index, row=8) #Height Label(infoFrame, text="Height").grid(column=0, row=9, sticky="W") self._heightText = StringVar() Entry(infoFrame, state=DISABLED, width=5).grid(column=1, row=9) #control controlFrame = tkFrame(self) controlFrame.grid(column=0, row=1, sticky="W") self._throttle = DoubleVar() self._thrustScale = Scale(controlFrame, orient=VERTICAL, from_=100.0, to=-100.0, \ tickinterval=0, variable=self._throttle, \ length=200, showvalue=1, \ state=DISABLED, command=self._onThrustScaleChanged) self._thrustScale.bind("<Double-Button-1>", self._onThrustScaleDoubleButton1, "+") self._thrustScale.grid(column=0) self._shiftCanvas = Canvas(controlFrame, bg="white", height=400, width=400, \ relief=SUNKEN) self._shiftCanvas.bind("<Button-1>", self._onMouseButton1) #self._shiftCanvas.bind("<ButtonRelease-1>", self._onMouseButtonRelease1) self._shiftCanvas.bind("<B1-Motion>", self._onMouseButton1Motion) self._shiftCanvas.bind("<Double-Button-1>", self._onMouseDoubleButton1) self._shiftCanvas.bind("<Button-3>", self._onMouseButton3) #self._shiftCanvas.bind("<ButtonRelease-3>", self._onMouseButtonRelease3) self._shiftCanvas.bind("<B3-Motion>", self._onMouseButton3Motion) self._shiftCanvas.grid(row=0,column=1, padx=2, pady=2) self._shiftCanvas.create_oval(2, 2, 400, 400, outline="#ff0000") self._shiftCanvas.create_line(201, 2, 201, 400, fill="#ff0000") self._shiftCanvas.create_line(2, 201, 400, 201, fill="#ff0000") self._shiftMarker = self._shiftCanvas.create_oval(197, 197, 205, 205, outline="#0000ff", fill="#0000ff") self._yaw = DoubleVar() self._yawScale = Scale(controlFrame, orient=HORIZONTAL, from_=-100.0, to=100.0, \ tickinterval=0, variable=self._yaw, \ length=200, showvalue=1, \ command=self._onYawScaleChanged) self._yawScale.bind("<Double-Button-1>", self._onYawScaleDoubleButton1, "+") self._yawScale.grid(row=1, column=1) self._controlKeyActive = False #PID calibration pidCalibrationFrame = tkFrame(self) pidCalibrationFrame.grid(column=0, row=2, sticky="WE"); self._pidSelected = StringVar() self._pidSelected.set("--") self._pidListBox = OptionMenu(pidCalibrationFrame, self._pidSelected, "--", \ Cockpit.KEY_ANG_SPEED, Cockpit.KEY_ANGLES, Cockpit.KEY_ACCEL, \ command=self._onPidListBoxChanged) self._pidListBox.pack(side=LEFT, padx=2) self._pidListBox.config(width=10) self._axisSelected = StringVar() self._axisSelected.set("--") self._axisListBox = OptionMenu(pidCalibrationFrame, self._axisSelected, "--", "X", "Y", "Z", \ command=self._onAxisListBoxChanged) self._axisListBox.pack(side=LEFT, padx=2) self._axisListBox.config(state=DISABLED) Label(pidCalibrationFrame, text="P").pack(side=LEFT, padx=(14, 2)) self._pidPString = StringVar() self._pidPString.set("0.00") self._pidPSpinbox = Spinbox(pidCalibrationFrame, width=5, from_=0.0, to=100.0, increment=0.01, state=DISABLED, \ textvariable=self._pidPString, command=self._onPidSpinboxChanged) self._pidPSpinbox.pack(side=LEFT, padx=2) Label(pidCalibrationFrame, text="I").pack(side=LEFT, padx=(14, 2)) self._pidIString = StringVar() self._pidIString.set("0.00") self._pidISpinbox = Spinbox(pidCalibrationFrame, width=5, from_=0.0, to=100.0, increment=0.01, state=DISABLED, \ textvariable=self._pidIString, command=self._onPidSpinboxChanged) self._pidISpinbox.pack(side=LEFT, padx=2) Label(pidCalibrationFrame, text="D").pack(side=LEFT, padx=(14, 2)) self._pidDString = StringVar() self._pidDString.set("0.00") self._pidDSpinbox = Spinbox(pidCalibrationFrame, width=5, from_=0.0, to=100.0, increment=0.01, state=DISABLED, \ textvariable=self._pidDString, command=self._onPidSpinboxChanged) self._pidDSpinbox.pack(side=LEFT, padx=2) #debug debugFrame = tkFrame(self) debugFrame.grid(column=0, row=3, sticky="WE") self._debugMsg = Message(debugFrame, anchor="nw", justify=LEFT, relief=SUNKEN, width=300) self._debugMsg.pack(fill=BOTH, expand=1) def _start(self): self._readDroneConfig() def exit(self): self._link.send({"key": "close", "data": None}) self._stopUpdateInfoThread() self._link.close() self.quit() def _updateTarget(self): markerCoords = self._shiftCanvas.coords(self._shiftMarker) coords = ((markerCoords[0] + markerCoords[2]) / 2, (markerCoords[1] + markerCoords[3]) / 2) self._target[1] = float(coords[0] - 201) * Cockpit.MAX_ACCEL / 200.0 self._target[0] = float(coords[1] - 201) * Cockpit.MAX_ACCEL / 200.0 #Remote control uses clockwise angle, but the drone's referece system uses counter-clockwise angle self._target[2] = -self._yaw.get() * Cockpit.MAX_ANGLE_SPEED / 100.0 self._target[3] = self._throttle.get() * Cockpit.MAX_ACCEL_Z / 100.0 self._sendTarget() def _keyDown(self, event): if event.keysym == "Escape": self._throttle.set(0) self._started.set(0) self._thrustScale.config(state=DISABLED) self._stopUpdateInfoThread() self._sendIsStarted() elif event.keysym.startswith("Control"): self._controlKeyActive = True elif not self._controlKeysLocked and self._controlKeyActive: if event.keysym == "Up": self._thrustScaleUp() elif event.keysym == "Down": self._thrustScaleDown() elif event.keysym == "Left": self._yawLeft() elif event.keysym == "Right": self._yawRight() elif event.keysym == "space": self._yawReset() self._thrustReset() elif not self._controlKeysLocked and not self._controlKeyActive: if event.keysym == "Up": self._moveShiftCanvasMarker((0,-5)) elif event.keysym == "Down": self._moveShiftCanvasMarker((0,5)) elif event.keysym == "Left": self._moveShiftCanvasMarker((-5,0)) elif event.keysym == "Right": self._moveShiftCanvasMarker((5,0)) elif event.keysym == "space": self._resetShiftCanvasMarker() def _keyUp(self, eventArgs): if eventArgs.keysym.startswith("Control"): self._controlKeyActive = False def _onMouseButton1(self, eventArgs): self._lastMouseCoords = (eventArgs.x, eventArgs.y) def _onMouseButtonRelease1(self, eventArgs): self._shiftCanvas.coords(self._shiftMarker, 197, 197, 205, 205) def _limitCoordsToSize(self, coords, size): if coords[0] > size: x = size elif coords[0] < 0: x = 0 else: x = coords[0] if coords[1] > size: y = size elif coords[1] < 0: y = 0 else: y = coords[1] return (x,y) def _moveShiftCanvasMarker(self, shift): lastCoords = self._shiftCanvas.coords(self._shiftMarker) newCoords = (lastCoords[0] + shift[0], lastCoords[1] + shift[1]) newCoords = self._limitCoordsToSize(newCoords, 400) self._shiftCanvas.coords(self._shiftMarker, newCoords[0], newCoords[1], newCoords[0] + 8, newCoords[1] + 8) self._updateTarget() def _resetShiftCanvasMarker(self): self._shiftCanvas.coords(self._shiftMarker, 197, 197, 205, 205) self._updateTarget() def _onMouseButton1Motion(self, eventArgs): deltaCoords = (eventArgs.x - self._lastMouseCoords[0], eventArgs.y - self._lastMouseCoords[1]) self._moveShiftCanvasMarker(deltaCoords) self._lastMouseCoords = (eventArgs.x, eventArgs.y) def _onMouseDoubleButton1(self, eventArgs): self._resetShiftCanvasMarker() def _onMouseButton3(self, eventArgs): self._lastMouseCoords = (eventArgs.x, eventArgs.y) self._mouseDirection = Cockpit.DIR_NONE def _onMouseButtonRelease3(self, eventArgs): self._shiftCanvas.coords(self._shiftMarker, 197, 197, 205, 205) def _onMouseButton3Motion(self, eventArgs): deltaCoords = (eventArgs.x - self._lastMouseCoords[0], eventArgs.y - self._lastMouseCoords[1]) if self._mouseDirection == Cockpit.DIR_NONE: if abs(deltaCoords[0]) > abs(deltaCoords[1]): self._mouseDirection = Cockpit.DIR_HORIZONTAL else: self._mouseDirection = Cockpit.DIR_VERTICAL if self._mouseDirection == Cockpit.DIR_HORIZONTAL: deltaCoords = (deltaCoords[0], 0) else: deltaCoords = (0, deltaCoords[1]) self._moveShiftCanvasMarker(deltaCoords) self._lastMouseCoords = (eventArgs.x, eventArgs.y) def _thrustScaleUp(self): if self._started.get(): newValue = self._thrustScale.get() + 1 self._thrustScale.set(newValue) self._updateTarget() def _thrustScaleDown(self): if self._started.get(): newValue = self._thrustScale.get() - 1 self._thrustScale.set(newValue) self._updateTarget() def _thrustReset(self): if self._started.get(): self._thrustScale.set(0.0) self._updateTarget() def _onThrustScaleDoubleButton1(self, eventArgs): self._thrustReset() return "break" def _yawRight(self): newValue = self._yaw.get() + 1 self._yaw.set(newValue) self._updateTarget() def _yawLeft(self): newValue = self._yaw.get() - 1 self._yaw.set(newValue) self._updateTarget() def _yawReset(self): self._yaw.set(0) self._updateTarget() def _onMouseWheelUp(self, eventArgs): if not self._controlKeyActive: self._thrustScaleUp() else: self._yawRight() def _onMouseWheelDown(self, eventArgs): if not self._controlKeyActive: self._thrustScaleDown() else: self._yawLeft() def _onMouseWheel(self, eventArgs): factor = int(eventArgs.delta/120) if not self._controlKeyActive: if self._started.get(): newValue = self._thrustScale.get() + factor self._thrustScale.set(newValue) self._updateTarget() else: newValue = self._yaw.get() + factor self._yaw.set(newValue) self._updateTarget() def _onYawScaleChanged(self, eventArgs): self._updateTarget() def _onYawScaleDoubleButton1(self, eventArgs): self._yawReset() return "break" def _startedCBChanged(self): if not self._started.get(): self._throttle.set(0) self._thrustScale.config(state=DISABLED) self._integralsCB.config(state=DISABLED) self._stopUpdateInfoThread() else: self._thrustScale.config(state="normal") self._integralsCB.config(state="normal") self._startUpdateInfoThread() self._sendIsStarted() def _integralsCBChanged(self): self._link.send({"key": "integrals", "data":self._integralsEnabled.get() != 0}) def _onThrustScaleChanged(self, eventArgs): self._updateTarget() def _sendTarget(self): self._link.send({"key": "target", "data": self._target}) def _sendIsStarted(self): isStarted = self._started.get() != 0 self._link.send({"key": "is-started", "data": isStarted}) def _sendPidCalibrationData(self): if self._pidSelected.get() != "--" and self._axisSelected.get() != "--": pidData = { "pid": self._pidSelected.get(), "axis": self._axisSelected.get(), "p": float(self._pidPSpinbox.get()), "i": float(self._pidISpinbox.get()), "d": float(self._pidDSpinbox.get())} self._link.send({"key": "pid-calibration", "data": pidData}) def _updatePidCalibrationData(self): pid = self._pidSelected.get() axis = self._axisSelected.get() if pid != "--" and axis != "--": self._pidConstants[pid][axis]["P"] = float(self._pidPSpinbox.get()) self._pidConstants[pid][axis]["I"] = float(self._pidISpinbox.get()) self._pidConstants[pid][axis]["D"] = float(self._pidDSpinbox.get()) def _readDroneConfig(self): self._link.send({"key": "read-drone-config", "data": None}, self._onDroneConfigRead) def _readDroneState(self): if not self._readingState: self._readingState = True self._link.send({"key": "read-drone-state", "data": None}, self._onDroneStateRead) def _readPidConfigItem(self, message, cockpitKey, axises, configKeys): for i in range(len(axises)): for j in range(len(Cockpit.PID_KEYS)): self._pidConstants[cockpitKey][axises[i]][Cockpit.PID_KEYS[j]] = message[configKeys[j]][i] def _onDroneConfigRead(self, message): #TODO Show current configuration within the GUI (at least relevant settings) if message: #Angle-speeds self._readPidConfigItem(message, Cockpit.KEY_ANG_SPEED, ["X", "Y", "Z"], \ [Configuration.PID_ANGLES_SPEED_KP, \ Configuration.PID_ANGLES_SPEED_KI, \ Configuration.PID_ANGLES_SPEED_KD]) #Angles self._readPidConfigItem(message, Cockpit.KEY_ANGLES, ["X", "Y"], \ [Configuration.PID_ANGLES_KP, \ Configuration.PID_ANGLES_KI, \ Configuration.PID_ANGLES_KD]) #Accels self._readPidConfigItem(message, Cockpit.KEY_ACCEL, ["X", "Y", "Z"], \ [Configuration.PID_ACCEL_KP, \ Configuration.PID_ACCEL_KI, \ Configuration.PID_ACCEL_KD]) def _onDroneStateRead(self, state): if state: for index in range(4): self._throttleTexts[index].set("{0:.3f}".format(state["_throttles"][index])) for index in range(3): self._accelTexts[index].set("{0:.3f}".format(state["_accels"][index])) self._angleTexts[index].set("{0:.3f}".format(state["_angles"][index])) else: self._stopUpdateInfoThread() self._readingState = False def _onPidSpinboxChanged(self): self._updatePidCalibrationData() self._sendPidCalibrationData() def _onPidListBoxChanged(self, pid): self._axisSelected.set("--") self._pidPString.set("--") self._pidIString.set("--") self._pidDString.set("--") self._pidPSpinbox.config(state=DISABLED) self._pidISpinbox.config(state=DISABLED) self._pidDSpinbox.config(state=DISABLED) self._selectedPidConstats = pid if pid == "--": self._axisListBox.config(state=DISABLED) self._controlKeysLocked = False else: self._axisListBox.config(state="normal") self._controlKeysLocked = True def _onAxisListBoxChanged(self, axis): if axis == "--" or (self._selectedPidConstats == Cockpit.KEY_ANGLES and axis == "Z"): self._pidPString.set("--") self._pidIString.set("--") self._pidDString.set("--") self._pidPSpinbox.config(state=DISABLED) self._pidISpinbox.config(state=DISABLED) self._pidDSpinbox.config(state=DISABLED) self._controlKeysLocked = axis != "--" else: self._pidPString.set("{:.2f}".format(self._pidConstants[self._selectedPidConstats][axis]["P"])) self._pidIString.set("{:.2f}".format(self._pidConstants[self._selectedPidConstats][axis]["I"])) self._pidDString.set("{:.2f}".format(self._pidConstants[self._selectedPidConstats][axis]["D"])) self._pidPSpinbox.config(state="normal") self._pidISpinbox.config(state="normal") self._pidDSpinbox.config(state="normal") self._controlKeysLocked = True def _updateInfo(self): while self._updateInfoThreadRunning: self._readDroneState() time.sleep(1.0) def _startUpdateInfoThread(self): self._updateInfoThreadRunning = True if not self._updateInfoThread.isAlive(): self._updateInfoThread.start() def _stopUpdateInfoThread(self): self._updateInfoThreadRunning = False if self._updateInfoThread.isAlive(): self._updateInfoThread.join()
class Cockpit(ttkFrame): ''' Remote device GUI ''' #TODO: 20160415 DPM - Set these values from configuration file #--- config THROTTLE_BY_USER = True THROTTLE_RESOLUTION = 0.1 # Joystick enabled or not, if any JOYSTICK_ENABLED = True DEFAULT_DRONE_IP = "192.168.1.130" DEFAULT_DRONE_PORT = 2121 #--- end config KEY_ANG_SPEED = "ang-speed" KEY_ANGLES = "angles" KEY_ACCEL = "accel" PID_KEYS = ["P", "I", "D"] DIR_NONE = 0 DIR_VERTICAL = 1 DIR_HORIZONTAL = 2 def __init__(self, parent, isDummy=False, droneIp=DEFAULT_DRONE_IP, dronePort=DEFAULT_DRONE_PORT): ''' Constructor ''' ttkFrame.__init__(self, parent) self._target = [0.0] * 4 self._selectedPidConstats = "--" self._pidConstants = { Cockpit.KEY_ANG_SPEED: { "X": { "P": 0.0, "I": 0.0, "D": 0.0 }, "Y": { "P": 0.0, "I": 0.0, "D": 0.0 }, "Z": { "P": 0.0, "I": 0.0, "D": 0.0 } }, Cockpit.KEY_ANGLES: { "X": { "P": 0.0, "I": 0.0, "D": 0.0 }, "Y": { "P": 0.0, "I": 0.0, "D": 0.0 } }, Cockpit.KEY_ACCEL: { "X": { "P": 0.0, "I": 0.0, "D": 0.0 }, "Y": { "P": 0.0, "I": 0.0, "D": 0.0 }, "Z": { "P": 0.0, "I": 0.0, "D": 0.0 } } } self.parent = parent self.initUI() self._controlKeysLocked = False if not isDummy: self._link = INetLink(droneIp, dronePort) else: self._link = ConsoleLink() self._link.open() self._updateInfoThread = Thread(target=self._updateInfo) self._updateInfoThreadRunning = False self._readingState = False self._start() def initUI(self): self.parent.title("Drone control") self.style = Style() self.style.theme_use("default") self.pack(fill=BOTH, expand=1) self.parent.bind_all("<Key>", self._keyDown) self.parent.bind_all("<KeyRelease>", self._keyUp) if system() == "Linux": self.parent.bind_all("<Button-4>", self._onMouseWheelUp) self.parent.bind_all("<Button-5>", self._onMouseWheelDown) else: #case of Windows self.parent.bind_all("<MouseWheel>", self._onMouseWheel) #Commands commandsFrame = tkFrame(self) commandsFrame.grid(column=0, row=0, sticky="WE") self._started = IntVar() self._startedCB = Checkbutton(commandsFrame, text="On", variable=self._started, command=self._startedCBChanged) self._startedCB.pack(side=LEFT, padx=4) # self._integralsCB = Checkbutton(commandsFrame, text="Int.", variable=self._integralsEnabled, \ # command=self._integralsCBChanged, state=DISABLED) # self._integralsCB.pack(side=LEFT, padx=4) self._quitButton = Button(commandsFrame, text="Quit", command=self.exit) self._quitButton.pack(side=LEFT, padx=2, pady=2) # self._angleLbl = Label(commandsFrame, text="Angle") # self._angleLbl.pack(side=LEFT, padx=4) # # self._angleEntry = Entry(commandsFrame, state=DISABLED) # self._angleEntry.pack(side=LEFT) #Info infoFrame = tkFrame(self) infoFrame.grid(column=1, row=1, sticky="NE", padx=4) #Throttle Label(infoFrame, text="Throttle").grid(column=0, row=0, sticky="WE") self._throttleTexts = [ StringVar(), StringVar(), StringVar(), StringVar() ] Entry(infoFrame, textvariable=self._throttleTexts[3], state=DISABLED, width=5).grid(column=0, row=1) Entry(infoFrame, textvariable=self._throttleTexts[0], state=DISABLED, width=5).grid(column=1, row=1) Entry(infoFrame, textvariable=self._throttleTexts[2], state=DISABLED, width=5).grid(column=0, row=2) Entry(infoFrame, textvariable=self._throttleTexts[1], state=DISABLED, width=5).grid(column=1, row=2) #Angles Label(infoFrame, text="Angles").grid(column=0, row=3, sticky="WE") self._angleTexts = [StringVar(), StringVar(), StringVar()] for index in range(3): Entry(infoFrame, textvariable=self._angleTexts[index], state=DISABLED, width=5).grid(column=index, row=4) #Accels Label(infoFrame, text="Accels").grid(column=0, row=5, sticky="WE") self._accelTexts = [StringVar(), StringVar(), StringVar()] for index in range(3): Entry(infoFrame, textvariable=self._accelTexts[index], state=DISABLED, width=5).grid(column=index, row=6) #Speeds Label(infoFrame, text="Speeds").grid(column=0, row=7, sticky="WE") self._speedTexts = [StringVar(), StringVar(), StringVar()] for index in range(3): Entry(infoFrame, textvariable=self._speedTexts[index], state=DISABLED, width=5).grid(column=index, row=8) #Height Label(infoFrame, text="Height").grid(column=0, row=9, sticky="E") self._heightText = StringVar() Entry(infoFrame, textvariable=self._heightText, state=DISABLED, width=5).grid(column=1, row=9) #Loop rate Label(infoFrame, text="Loop @").grid(column=0, row=10, sticky="E") self._loopRateText = StringVar() Entry(infoFrame, textvariable=self._loopRateText, state=DISABLED, width=5).grid(column=1, row=10) Label(infoFrame, text="Hz").grid(column=2, row=10, sticky="W") #control controlFrame = tkFrame(self) controlFrame.grid(column=0, row=1, sticky="W") self._throttle = DoubleVar() if Cockpit.THROTTLE_BY_USER: self._thrustScale = Scale(controlFrame, orient=VERTICAL, from_=100.0, to=0.0, \ tickinterval=0, variable=self._throttle, resolution=Cockpit.THROTTLE_RESOLUTION, \ length=200, showvalue=1, \ state=DISABLED, command=self._onThrustScaleChanged) else: self._thrustScale = Scale(controlFrame, orient=VERTICAL, from_=100.0, to=-100.0, \ tickinterval=0, variable=self._throttle, \ length=200, showvalue=1, \ state=DISABLED, command=self._onThrustScaleChanged) self._thrustScale.bind("<Double-Button-1>", self._onThrustScaleDoubleButton1, "+") self._thrustScale.grid(column=0) self._shiftCanvas = Canvas(controlFrame, bg="white", height=400, width=400, \ relief=SUNKEN) self._shiftCanvas.bind("<Button-1>", self._onMouseButton1) #self._shiftCanvas.bind("<ButtonRelease-1>", self._onMouseButtonRelease1) self._shiftCanvas.bind("<B1-Motion>", self._onMouseButton1Motion) self._shiftCanvas.bind("<Double-Button-1>", self._onMouseDoubleButton1) self._shiftCanvas.bind("<Button-3>", self._onMouseButton3) #self._shiftCanvas.bind("<ButtonRelease-3>", self._onMouseButtonRelease3) self._shiftCanvas.bind("<B3-Motion>", self._onMouseButton3Motion) self._shiftCanvas.grid(row=0, column=1, padx=2, pady=2) self._shiftCanvas.create_oval(1, 1, 400, 400, outline="#ff0000") self._shiftCanvas.create_line(200, 2, 200, 400, fill="#ff0000") self._shiftCanvas.create_line(2, 200, 400, 200, fill="#ff0000") self._shiftMarker = self._shiftCanvas.create_oval(196, 196, 204, 204, outline="#0000ff", fill="#0000ff") self._yaw = DoubleVar() self._yawScale = Scale(controlFrame, orient=HORIZONTAL, from_=-100.0, to=100.0, \ tickinterval=0, variable=self._yaw, \ length=200, showvalue=1, \ command=self._onYawScaleChanged) self._yawScale.bind("<Double-Button-1>", self._onYawScaleDoubleButton1, "+") self._yawScale.grid(row=1, column=1) self._controlKeyActive = False #PID calibration pidCalibrationFrame = tkFrame(self) pidCalibrationFrame.grid(column=0, row=2, sticky="WE") self._pidSelected = StringVar() self._pidSelected.set("--") self._pidListBox = OptionMenu(pidCalibrationFrame, self._pidSelected, "--", \ Cockpit.KEY_ANG_SPEED, Cockpit.KEY_ANGLES, Cockpit.KEY_ACCEL, \ command=self._onPidListBoxChanged) self._pidListBox.pack(side=LEFT, padx=2) self._pidListBox.config(width=10) self._axisSelected = StringVar() self._axisSelected.set("--") self._axisListBox = OptionMenu(pidCalibrationFrame, self._axisSelected, "--", "X", "Y", "Z", \ command=self._onAxisListBoxChanged) self._axisListBox.pack(side=LEFT, padx=2) self._axisListBox.config(state=DISABLED) Label(pidCalibrationFrame, text="P").pack(side=LEFT, padx=(14, 2)) self._pidPString = StringVar() self._pidPString.set("0.00") self._pidPSpinbox = Spinbox(pidCalibrationFrame, width=5, from_=0.0, to=10000.0, increment=0.01, state=DISABLED, \ textvariable=self._pidPString, command=self._onPidSpinboxChanged) self._pidPSpinbox.pack(side=LEFT, padx=2) Label(pidCalibrationFrame, text="I").pack(side=LEFT, padx=(14, 2)) self._pidIString = StringVar() self._pidIString.set("0.00") self._pidISpinbox = Spinbox(pidCalibrationFrame, width=5, from_=0.0, to=10000.0, increment=0.01, state=DISABLED, \ textvariable=self._pidIString, command=self._onPidSpinboxChanged) self._pidISpinbox.pack(side=LEFT, padx=2) Label(pidCalibrationFrame, text="D").pack(side=LEFT, padx=(14, 2)) self._pidDString = StringVar() self._pidDString.set("0.00") self._pidDSpinbox = Spinbox(pidCalibrationFrame, width=5, from_=0.0, to=10000.0, increment=0.01, state=DISABLED, \ textvariable=self._pidDString, command=self._onPidSpinboxChanged) self._pidDSpinbox.pack(side=LEFT, padx=2) #debug debugFrame = tkFrame(self) debugFrame.grid(column=0, row=3, sticky="WE") self._debugMsg = Message(debugFrame, anchor="nw", justify=LEFT, relief=SUNKEN, width=300) self._debugMsg.pack(fill=BOTH, expand=1) def _start(self): self._readDroneConfig() if Cockpit.JOYSTICK_ENABLED: self._joystickManager = JoystickManager.getInstance() self._joystickManager.start() joysticks = self._joystickManager.getJoysticks() if len(joysticks) != 0: self._joystick = joysticks[0] self._joystick.onAxisChanged += self._onJoystickAxisChanged self._joystick.onButtonPressed += self._onJoystickButtonPressed else: self._joystick = None def _onJoystickAxisChanged(self, sender, index): if self._started.get() and sender == self._joystick: axisValue = self._joystick.getAxisValue(index) if index == 0: self._yaw.set(axisValue) self._updateTarget() elif index == 1 and not Cockpit.THROTTLE_BY_USER: thrust = -axisValue self._throttle.set(thrust) self._updateTarget() elif index == 2 and Cockpit.THROTTLE_BY_USER: rowThrottle = (axisValue + 100.0) / 2.0 if rowThrottle < 10.0: throttle = rowThrottle * 6.0 elif rowThrottle < 90.0: throttle = 60.0 + ((rowThrottle - 10.0) / 8.0) else: throttle = 70.0 + (rowThrottle - 90.0) * 3.0 self._throttle.set(throttle) self._sendThrottle() elif index == 3: x = 196 + axisValue * 2 lastCoords = self._shiftCanvas.coords(self._shiftMarker) coords = (x, lastCoords[1]) self._plotShiftCanvasMarker(coords) elif index == 4: y = 196 + axisValue * 2 lastCoords = self._shiftCanvas.coords(self._shiftMarker) coords = (lastCoords[0], y) self._plotShiftCanvasMarker(coords) def _onJoystickButtonPressed(self, sender, index): if sender == self._joystick and index == 7: if self._started.get() == 0: self._startedCB.select() else: self._startedCB.deselect() # Tkinter's widgets seem not to be calling the event-handler # when they are changed programmatically. Therefore, the # even-handler is called explicitly here. self._startedCBChanged() def exit(self): self._link.send({"key": "close", "data": None}) self._stopUpdateInfoThread() self._link.close() if Cockpit.JOYSTICK_ENABLED: self._joystickManager.stop() self.quit() def _updateTarget(self): markerCoords = self._shiftCanvas.coords(self._shiftMarker) coords = ((markerCoords[0] + markerCoords[2]) / 2, (markerCoords[1] + markerCoords[3]) / 2) self._target[0] = float( coords[1] - 200) / 2.0 # X-axis angle / X-axis acceleration self._target[1] = float( coords[0] - 200) / 2.0 # Y-axis angle / Y-axis acceleration #Remote control uses clockwise angle, but the drone's referece system uses counter-clockwise angle self._target[2] = -self._yaw.get() # Z-axis angular speed # Z-axis acceleration (thrust). Only when the motor throttle is not controlled by user directly if Cockpit.THROTTLE_BY_USER: self._target[3] = 0.0 else: self._target[3] = self._throttle.get() self._sendTarget() def _keyDown(self, event): if event.keysym == "Escape": self._throttle.set(0) self._started.set(0) self._thrustScale.config(state=DISABLED) self._stopUpdateInfoThread() self._sendIsStarted() elif event.keysym.startswith("Control"): self._controlKeyActive = True elif not self._controlKeysLocked and self._controlKeyActive: if event.keysym == "Up": self._thrustScaleUp() elif event.keysym == "Down": self._thrustScaleDown() elif event.keysym == "Left": self._yawLeft() elif event.keysym == "Right": self._yawRight() elif event.keysym == "space": self._yawReset() if not Cockpit.THROTTLE_BY_USER: self._thrustReset() elif not self._controlKeysLocked and not self._controlKeyActive: if event.keysym == "Up": self._moveShiftCanvasMarker((0, -5)) elif event.keysym == "Down": self._moveShiftCanvasMarker((0, 5)) elif event.keysym == "Left": self._moveShiftCanvasMarker((-5, 0)) elif event.keysym == "Right": self._moveShiftCanvasMarker((5, 0)) elif event.keysym == "space": self._resetShiftCanvasMarker() def _keyUp(self, eventArgs): if eventArgs.keysym.startswith("Control"): self._controlKeyActive = False def _onMouseButton1(self, eventArgs): self._lastMouseCoords = (eventArgs.x, eventArgs.y) def _onMouseButtonRelease1(self, eventArgs): self._shiftCanvas.coords(self._shiftMarker, 196, 196, 204, 204) def _limitCoordsToSize(self, coords, size, width): maxSize = size - (width / 2.0) minSize = -(width / 2.0) if coords[0] > maxSize: x = maxSize elif coords[0] < minSize: x = minSize else: x = coords[0] if coords[1] > maxSize: y = maxSize elif coords[1] < minSize: y = minSize else: y = coords[1] return (x, y) def _plotShiftCanvasMarker(self, coords): coords = self._limitCoordsToSize(coords, 400, 8) self._shiftCanvas.coords(self._shiftMarker, coords[0], coords[1], coords[0] + 8, coords[1] + 8) self._updateTarget() def _moveShiftCanvasMarker(self, shift): lastCoords = self._shiftCanvas.coords(self._shiftMarker) newCoords = (lastCoords[0] + shift[0], lastCoords[1] + shift[1]) self._plotShiftCanvasMarker(newCoords) def _resetShiftCanvasMarker(self): self._shiftCanvas.coords(self._shiftMarker, 196, 196, 204, 204) self._updateTarget() def _onMouseButton1Motion(self, eventArgs): deltaCoords = (eventArgs.x - self._lastMouseCoords[0], eventArgs.y - self._lastMouseCoords[1]) self._moveShiftCanvasMarker(deltaCoords) self._lastMouseCoords = (eventArgs.x, eventArgs.y) def _onMouseDoubleButton1(self, eventArgs): self._resetShiftCanvasMarker() def _onMouseButton3(self, eventArgs): self._lastMouseCoords = (eventArgs.x, eventArgs.y) self._mouseDirection = Cockpit.DIR_NONE def _onMouseButtonRelease3(self, eventArgs): self._shiftCanvas.coords(self._shiftMarker, 196, 196, 204, 204) def _onMouseButton3Motion(self, eventArgs): deltaCoords = (eventArgs.x - self._lastMouseCoords[0], eventArgs.y - self._lastMouseCoords[1]) if self._mouseDirection == Cockpit.DIR_NONE: if abs(deltaCoords[0]) > abs(deltaCoords[1]): self._mouseDirection = Cockpit.DIR_HORIZONTAL else: self._mouseDirection = Cockpit.DIR_VERTICAL if self._mouseDirection == Cockpit.DIR_HORIZONTAL: deltaCoords = (deltaCoords[0], 0) else: deltaCoords = (0, deltaCoords[1]) self._moveShiftCanvasMarker(deltaCoords) self._lastMouseCoords = (eventArgs.x, eventArgs.y) def _thrustScaleUp(self): #TODO: 20160526 DPM: El valor de incremento de aceleración (1.0) puede ser muy alto if self._started.get(): newValue = self._thrustScale.get() \ + (Cockpit.THROTTLE_RESOLUTION if Cockpit.THROTTLE_BY_USER else 1.0) self._thrustScale.set(newValue) self._updateTarget() def _thrustScaleDown(self): #TODO: 20160526 DPM: El valor de decremento de aceleración (1.0) puede ser muy alto if self._started.get(): newValue = self._thrustScale.get() \ - (Cockpit.THROTTLE_RESOLUTION if Cockpit.THROTTLE_BY_USER else 1.0) self._thrustScale.set(newValue) self._updateTarget() def _thrustReset(self): if self._started.get(): self._thrustScale.set(0.0) self._updateTarget() def _onThrustScaleDoubleButton1(self, eventArgs): self._thrustReset() return "break" def _yawRight(self): newValue = self._yaw.get() + 1 self._yaw.set(newValue) self._updateTarget() def _yawLeft(self): newValue = self._yaw.get() - 1 self._yaw.set(newValue) self._updateTarget() def _yawReset(self): self._yaw.set(0) self._updateTarget() def _onMouseWheelUp(self, eventArgs): if not self._controlKeyActive: self._thrustScaleUp() else: self._yawRight() def _onMouseWheelDown(self, eventArgs): if not self._controlKeyActive: self._thrustScaleDown() else: self._yawLeft() def _onMouseWheel(self, eventArgs): factor = eventArgs.delta / (1200.0 if Cockpit.THROTTLE_BY_USER and not self._controlKeyActive else 120.0) if not self._controlKeyActive: if self._started.get(): newValue = self._thrustScale.get() + factor self._thrustScale.set(newValue) self._updateTarget() else: newValue = self._yaw.get() + factor self._yaw.set(newValue) self._updateTarget() def _onYawScaleChanged(self, eventArgs): self._updateTarget() def _onYawScaleDoubleButton1(self, eventArgs): self._yawReset() return "break" def _startedCBChanged(self): if not self._started.get(): self._throttle.set(0) self._thrustScale.config(state=DISABLED) #self._integralsCB.config(state=DISABLED) self._stopUpdateInfoThread() else: self._thrustScale.config(state="normal") #self._integralsCB.config(state="normal") self._startUpdateInfoThread() self._sendIsStarted() # def _integralsCBChanged(self): # # self._link.send({"key": "integrals", "data":self._integralsEnabled.get() != 0}) # def _onThrustScaleChanged(self, eventArgs): if Cockpit.THROTTLE_BY_USER: self._sendThrottle() else: self._updateTarget() def _sendThrottle(self): self._link.send({"key": "throttle", "data": self._throttle.get()}) def _sendTarget(self): self._link.send({"key": "target", "data": self._target}) def _sendIsStarted(self): isStarted = self._started.get() != 0 self._link.send({"key": "is-started", "data": isStarted}) def _sendPidCalibrationData(self): if self._pidSelected.get() != "--" and self._axisSelected.get( ) != "--": pidData = { "pid": self._pidSelected.get(), "axis": self._axisSelected.get(), "p": float(self._pidPSpinbox.get()), "i": float(self._pidISpinbox.get()), "d": float(self._pidDSpinbox.get()) } self._link.send({"key": "pid-calibration", "data": pidData}) def _updatePidCalibrationData(self): pid = self._pidSelected.get() axis = self._axisSelected.get() if pid != "--" and axis != "--": self._pidConstants[pid][axis]["P"] = float(self._pidPSpinbox.get()) self._pidConstants[pid][axis]["I"] = float(self._pidISpinbox.get()) self._pidConstants[pid][axis]["D"] = float(self._pidDSpinbox.get()) def _readDroneConfig(self): self._link.send({ "key": "read-drone-config", "data": None }, self._onDroneConfigRead) def _readDroneState(self): if not self._readingState: self._readingState = True self._link.send({ "key": "read-drone-state", "data": None }, self._onDroneStateRead) def _readPidConfigItem(self, message, cockpitKey, axises, configKeys): for i in range(len(axises)): for j in range(len(Cockpit.PID_KEYS)): self._pidConstants[cockpitKey][axises[i]][ Cockpit.PID_KEYS[j]] = message[configKeys[j]][i] def _onDroneConfigRead(self, message): #TODO Show current configuration within the GUI (at least relevant settings) if message: #Angle-speeds self._readPidConfigItem(message, Cockpit.KEY_ANG_SPEED, ["X", "Y", "Z"], \ [Configuration.PID_ANGLES_SPEED_KP, \ Configuration.PID_ANGLES_SPEED_KI, \ Configuration.PID_ANGLES_SPEED_KD]) #Angles self._readPidConfigItem(message, Cockpit.KEY_ANGLES, ["X", "Y"], \ [Configuration.PID_ANGLES_KP, \ Configuration.PID_ANGLES_KI, \ Configuration.PID_ANGLES_KD]) #Accels self._readPidConfigItem(message, Cockpit.KEY_ACCEL, ["X", "Y", "Z"], \ [Configuration.PID_ACCEL_KP, \ Configuration.PID_ACCEL_KI, \ Configuration.PID_ACCEL_KD]) def _onDroneStateRead(self, state): if state: for index in range(4): self._throttleTexts[index].set("{0:.3f}".format( state["_throttles"][index])) for index in range(3): self._accelTexts[index].set("{0:.3f}".format( state["_accels"][index])) self._angleTexts[index].set("{0:.3f}".format( state["_angles"][index])) currentPeriod = state["_currentPeriod"] if currentPeriod > 0.0: freq = 1.0 / currentPeriod self._loopRateText.set("{0:.3f}".format(freq)) else: self._loopRateText.set("--") else: self._stopUpdateInfoThread() self._readingState = False def _onPidSpinboxChanged(self): self._updatePidCalibrationData() self._sendPidCalibrationData() def _onPidListBoxChanged(self, pid): self._axisSelected.set("--") self._pidPString.set("--") self._pidIString.set("--") self._pidDString.set("--") self._pidPSpinbox.config(state=DISABLED) self._pidISpinbox.config(state=DISABLED) self._pidDSpinbox.config(state=DISABLED) self._selectedPidConstats = pid if pid == "--": self._axisListBox.config(state=DISABLED) self._controlKeysLocked = False else: self._axisListBox.config(state="normal") self._controlKeysLocked = True def _onAxisListBoxChanged(self, axis): if axis == "--" or (self._selectedPidConstats == Cockpit.KEY_ANGLES and axis == "Z"): self._pidPString.set("--") self._pidIString.set("--") self._pidDString.set("--") self._pidPSpinbox.config(state=DISABLED) self._pidISpinbox.config(state=DISABLED) self._pidDSpinbox.config(state=DISABLED) self._controlKeysLocked = axis != "--" else: self._pidPString.set("{:.2f}".format( self._pidConstants[self._selectedPidConstats][axis]["P"])) self._pidIString.set("{:.2f}".format( self._pidConstants[self._selectedPidConstats][axis]["I"])) self._pidDString.set("{:.2f}".format( self._pidConstants[self._selectedPidConstats][axis]["D"])) self._pidPSpinbox.config(state="normal") self._pidISpinbox.config(state="normal") self._pidDSpinbox.config(state="normal") self._controlKeysLocked = True def _updateInfo(self): while self._updateInfoThreadRunning: self._readDroneState() time.sleep(1.0) def _startUpdateInfoThread(self): self._updateInfoThreadRunning = True if not self._updateInfoThread.isAlive(): self._updateInfoThread.start() def _stopUpdateInfoThread(self): self._updateInfoThreadRunning = False if self._updateInfoThread.isAlive(): self._updateInfoThread.join()
class App: def __init__(self, master, height, width): from Tkinter import Label, Entry, Canvas, Button Label(master, text="Initial conditions:").grid(row=0, column=0, columnspan=2) Label(master, text="q").grid(row=1, column=0) Label(master, text="p").grid(row=2, column=0) Label(master, text="t").grid(row=3, column=0) Label(master, text="v").grid(row=4, column=0) Label(master, text="b").grid(row=5, column=0) Label(master, text="l").grid(row=6, column=0) Label(master, text="g").grid(row=7, column=0) Button(master, text="Reset", command=self.resetInitialConditions).grid(row=8, column=0, columnspan=2) self.q = Entry(master) self.p = Entry(master) self.t = Entry(master) self.v = Entry(master) self.b = Entry(master) self.l = Entry(master) self.g = Entry(master) self.q.grid(row=1, column=1) self.p.grid(row=2, column=1) self.t.grid(row=3, column=1) self.v.grid(row=4, column=1) self.b.grid(row=5, column=1) self.l.grid(row=6, column=1) self.g.grid(row=7, column=1) self.canv = Canvas(master, height=height, width=width) self.canv.grid(row=0, column=2, rowspan=8) self.pendulum = DrivenPendulum() self.q.insert(0, 2.) self.p.insert(0, 0.) self.t.insert(0, 0.) self.v.insert(0, 2.) self.b.insert(0, 1.) self.l.insert(0, 1.5) self.g.insert(0, -10.) self.rad = 8 self.scaleFactor = 50 self.shiftPosition = array([width//2, height//2]) self.axes = self.canv.create_line(tuple(self.shiftPosition) + tuple(self.shiftPosition) + tuple(self.shiftPosition)) self.bob1 = self.canv.create_oval(self.getOvalCoords(self.shiftPosition), fill="blue") self.bob2 = self.canv.create_oval(self.getOvalCoords(self.shiftPosition), fill="red") self.resetInitialConditions() self.updatePendulum() def getOvalCoords(self, position): return (position[0]-self.rad, position[1]-self.rad, position[0]+self.rad, position[1]+self.rad) def updatePendulum(self): pos1 = (self.scaleFactor*self.pendulum.getInnerPosition()*array([1, -1])).astype(int) + self.shiftPosition pos2 = (self.scaleFactor*self.pendulum.getOuterPosition()*array([1, -1])).astype(int) + self.shiftPosition self.canv.coords(self.axes, tuple(self.shiftPosition) + tuple(pos1) + tuple(pos2)) self.canv.coords(self.bob1, self.getOvalCoords(pos1)) self.canv.coords(self.bob2, self.getOvalCoords(pos2)) print self.pendulum.getPhaseSpacePoint() self.pendulum.evolve(0.05) self.canv.after(20, self.updatePendulum) def resetInitialConditions(self): self.pendulum.setInitialConditions( float(self.q.get()), float(self.t.get()), float(self.v.get()), float(self.p.get()), float(self.b.get()), float(self.l.get()), float(self.g.get()), )
class TkProgessBar(Frame): """ TkListboxMulticolumn component which can display multi-sortable listbox """ def __init__(self, master, cnf={}, **kw): """ Construct a listbox widget with one or many column and label field for header Valid resource names: background, bd, bg, borderwidth, class, colormap, fg, font, foreground, height, highlightbackground, """ Frame.__init__(self, master) self._value = kw.get('value', 0.0) # Create canvas for drawing in self._canvas = Canvas( self, bg=kw.get('bg', 'white'), width=kw.get('width', 300), height=kw.get('height', 20), relief=kw.get('relief', 'sunken'), border=kw.get('border', 1) ) self._canvas.pack(fill='both', expand='yes') # Drawing a rectangle self._rect = self._canvas.create_rectangle( 0, 0, 0, self._canvas.winfo_reqheight(), fill=kw.get('fillcolor', 'blue'), width=0 ) # Drawing a text area self._text = self._canvas.create_text( self._canvas.winfo_reqwidth()/2, self._canvas.winfo_reqheight()/2, text='', fill=kw.get('textcolor', 'gray') ) self.bind('<Configure>', self._update_coords) def _update_coords(self, event): '''Updates the position of the text and rectangle inside the canvas when the size of the widget gets changed.''' # looks like we have to call update_idletasks() twice to make sure # to get the results we expect self._canvas.update_idletasks() self._canvas.coords(self._text, self._canvas.winfo_width()/2, self._canvas.winfo_height()/2) self._canvas.coords(self._rect, 0, 0, self._canvas.winfo_width()*self._value, self._canvas.winfo_height()) self._canvas.update_idletasks() def get(self, first, last=None): """ return percent and text value """ return self._value, self._canvas.itemcget(self._text, 'text') def set(self, value=0.0, text=None): ''' Set different values. ''' #make the value failsafe: if value < 0.0: value = 0.0 elif value > 1.0: value = 1.0 self._value = value if text == None: #if no text is specified use the default percentage string: text = str(int(round(100 * value))) + ' %' self._canvas.coords(self._rect, 0, 0, self._canvas.winfo_width()*value, self._canvas.winfo_height()) self._canvas.itemconfigure(self._text, text=text) self._canvas.update_idletasks()
class Walking(Frame): def __init__(self, parent): Frame.__init__(self, parent) self.parent = parent self.init() self.animate() def init(self): self.parent.title("Walking") self.pack(fill=BOTH, expand=1) self.canvas = Canvas(self) self.current_iteration = 0 self.num_iterations = 100 self.segment_length = 50.0 # Start Coordinates self.start_hip = [50.0, 120.0] self.start_left_foot = [80.0, 200.0] self.start_right_foot = [20.0, 200.0] # End Coordinates self.end_hip = [80.0, 105.0] self.end_left_foot = [80.0, 200.0] self.end_right_foot = [80.0, 180.0] # Calculate starting left leg leg_angle = math.atan2(self.start_left_foot[1] - self.start_hip[1], self.start_left_foot[0] - self.start_hip[0]) leg_length = distance(self.start_hip[0], self.start_hip[1], self.start_left_foot[0], self.start_left_foot[1]) segment_angle = math.acos((leg_length / 2) / self.segment_length) self.current_left_ankle = leg_angle + segment_angle self.current_left_knee = 2 * (PI / 2 - segment_angle) self.current_left_hip = (PI / 2 - leg_angle) + segment_angle # Calculate starting right leg leg_angle = math.atan2(self.start_right_foot[1] - self.start_hip[1], self.start_right_foot[0] - self.start_hip[0]) leg_length = distance(self.start_hip[0], self.start_hip[1], self.start_right_foot[0], self.start_right_foot[1]) segment_angle = math.acos((leg_length / 2) / self.segment_length) self.current_right_ankle = leg_angle + segment_angle self.current_right_knee = 2 * (PI / 2 - segment_angle) self.current_right_hip = (PI / 2 - leg_angle) + segment_angle # Calculate ending left leg leg_length = distance(self.end_hip[0], self.end_hip[1], self.end_left_foot[0], self.end_left_foot[1]) segment_angle = math.acos((leg_length / 2) / self.segment_length) self.end_left_ankle = PI / 2 + segment_angle self.end_left_knee = 2 * (PI / 2 - segment_angle) self.end_left_hip = segment_angle # Calculate ending right leg leg_length = distance(self.end_hip[0], self.end_hip[1], self.end_right_foot[0], self.end_right_foot[1]) segment_angle = math.acos((leg_length / 2) / self.segment_length) self.end_right_ankle = PI / 2 + segment_angle self.end_right_knee = 2 * (PI / 2 - segment_angle) self.end_right_hip = segment_angle self.dif_left_ankle = (self.end_left_ankle - self.current_left_ankle) / self.num_iterations self.dif_left_knee = (self.end_left_knee - self.current_left_knee) / self.num_iterations self.dif_left_hip = (self.end_left_hip - self.current_left_hip) / self.num_iterations self.dif_right_ankle = (self.end_right_ankle - self.current_right_ankle) / self.num_iterations self.dif_right_knee = (self.end_right_knee - self.current_right_knee) / self.num_iterations self.dif_right_hip = (self.end_right_hip - self.current_right_hip) / self.num_iterations # Calculate starting position knee_y_dif = self.segment_length * math.sin(self.current_left_ankle) knee_x_dif = self.segment_length * math.cos(self.current_left_ankle) knee_x = self.start_left_foot[0] - knee_x_dif knee_y = self.start_left_foot[1] - knee_y_dif self.left_lower_leg = self.canvas.create_line(self.start_left_foot[0], self.start_left_foot[1], knee_x, knee_y, width=2) self.left_upper_leg = self.canvas.create_line(knee_x, knee_y, self.start_hip[0], self.start_hip[1], width=2) knee_y_dif = self.segment_length * math.sin(self.current_right_ankle) knee_x_dif = self.segment_length * math.cos(self.current_right_ankle) knee_x = self.start_right_foot[0] - knee_x_dif knee_y = self.start_right_foot[1] - knee_y_dif self.right_lower_leg = self.canvas.create_line( self.start_right_foot[0], self.start_right_foot[1], knee_x, knee_y, width=2) self.right_upper_leg = self.canvas.create_line(knee_x, knee_y, self.start_hip[0], self.start_hip[1], width=2) self.torso = self.canvas.create_line(self.start_hip[0], self.start_hip[1], self.start_hip[0], self.start_hip[1] - 80.0, width=2) self.canvas.pack(fill=BOTH, expand=1) def animate(self): # Left lower leg self.current_left_ankle = self.current_left_ankle + self.dif_left_ankle knee_y_dif = self.segment_length * math.sin(self.current_left_ankle) knee_x_dif = self.segment_length * math.cos(self.current_left_ankle) knee_x = self.start_left_foot[0] - knee_x_dif knee_y = self.start_left_foot[1] - knee_y_dif self.canvas.coords(self.left_lower_leg, self.start_left_foot[0], self.start_left_foot[1], knee_x, knee_y) # Left upper leg self.current_left_knee = self.current_left_knee + self.dif_left_knee aligned_angle = self.current_left_knee - (PI - self.current_left_ankle) hip_y_dif = self.segment_length * math.sin(aligned_angle) hip_x_dif = self.segment_length * math.cos(aligned_angle) hip_x = knee_x - hip_x_dif hip_y = knee_y - hip_y_dif self.canvas.coords(self.left_upper_leg, knee_x, knee_y, hip_x, hip_y) # Right upper leg self.current_right_hip = self.current_right_hip + self.dif_right_hip aligned_angle = PI / 2 - self.current_right_hip hip_y_dif = self.segment_length * math.sin(aligned_angle) hip_x_dif = self.segment_length * math.cos(aligned_angle) knee_x = hip_x + hip_x_dif knee_y = hip_y + hip_y_dif self.canvas.coords(self.right_upper_leg, knee_x, knee_y, hip_x, hip_y) # Right lower leg self.current_right_knee = self.current_right_knee + self.dif_right_knee aligned_angle = self.current_right_knee - (PI / 2 - self.current_right_hip) knee_y_dif = self.segment_length * math.sin(aligned_angle) knee_x_dif = self.segment_length * math.cos(aligned_angle) foot_x = knee_x - knee_x_dif foot_y = knee_y + knee_y_dif self.canvas.coords(self.right_lower_leg, foot_x, foot_y, knee_x, knee_y) # Torso self.canvas.coords(self.torso, hip_x, hip_y, hip_x, hip_y - 80.0) self.current_iteration = self.current_iteration + 1 if self.current_iteration < self.num_iterations: self.after(10, self.animate)
if event.char == '>': scaling_factor = scaling_factor + 0.1 resize() elif event.char == '<': scaling_factor = scaling_factor - 0.1 resize() elif event.char == "<Right>": x = x + 5 print x #elif event.char (x, y) = canvas.coords(chrid) canvas.bind("<Right>", lambda event: canvas.move(chrid, 5, 0)) canvas.bind("<Left>", lambda event: canvas.move(chrid, -5, 0)) canvas.bind("<Up>", lambda event: canvas.move(chrid, 0, -5)) canvas.bind("<Down>", lambda event: canvas.move(chrid, 0, 5)) canvas.focus_set() canvas.bind("<Key>", key) scaling_factor = 1.0
class Display(ttkFrame): ''' Displays the drone state on a graphical interface ''' REFRESH_PERIOD = 0.2 ARM_LENGTH = 23 #pixels PIXELS_METER = 100.0 #pixels/meter _instance = None @staticmethod def getInstance(): if Display._instance == None: root = Tk() root.geometry() Display._instance = Display(root) return Display._instance def __init__(self, parent): ''' Constructor ''' ttkFrame.__init__(self, parent) self._stateProvider = None self._launcherMethod = None self._isRunning = False self._droneThread = None self._parent = parent self._initUI() def setStateProvider(self, stateProvider): self._stateProvider = stateProvider return self def setLauncherMethod(self, launcherMethod): self._launcherMethod = launcherMethod return self def start(self): if self._launcherMethod and not self._droneThread: self._droneThread = Thread(target=self._launcherMethod) self._droneThread.start() self._isRunning = True if self._stateProvider: self._refresh() self._parent.mainloop() def stop(self): self._isRunning = False if self._droneThread and self._droneThread.isAlive(): self._droneThread.join(5.0) def quit(self): self.stop() ttkFrame.quit(self) def _initUI(self): self._parent.title("Drone Flight Emulator") self.style = Style() self.style.theme_use("default") self.pack(fill=BOTH, expand=1) drawFrame = tkFrame(self) drawFrame.grid(column=0, row=0, sticky="W") self._canvasYZ = Canvas(drawFrame, bg="white", height=200, width=200) self._canvasYZ.grid(column=0, row=0, sticky="W", padx=(2,0), pady=(2,0)) self._canvasXZ = Canvas(drawFrame, bg="white", height=200, width=200) self._canvasXZ.grid(column=1, row=0, sticky="E", padx=(2,2), pady=(2,0)) self._canvasXY = Canvas(drawFrame, bg="white", height=200, width=400) self._canvasXY.grid(column=0, row=1, columnspan=2, sticky="S", padx=(2,2), pady=(0,2)) self._linesXY = [self._canvasXY.create_line(200,100, 200, 90, fill="#ff0000"), \ self._canvasXY.create_line(200,100, 210, 100, fill="#0000ff"), \ self._canvasXY.create_line(200,100, 200, 110, fill="#0000ff"), \ self._canvasXY.create_line(200,100, 190, 100, fill="#0000ff")] self._linesYZ = [self._canvasYZ.create_line(100,200, 90, 200, fill="#0000ff"), \ self._canvasYZ.create_line(100,200, 110, 200, fill="#0000ff")] self._linesXZ = [self._canvasXZ.create_line(100,200, 90, 200, fill="#0000ff"), \ self._canvasXZ.create_line(100,200, 110, 200, fill="#0000ff")] def _plotXY(self, coord, angles): x = int((coord[0]*Display.PIXELS_METER + 200.0) % 400.0) y = int((100.0 - coord[1]*Display.PIXELS_METER) % 200.0) sinz = sin(angles[2]) cosz = cos(angles[2]) lines = [Vector.rotateVector(line, sinz, cosz) \ for line in [ [0, Display.ARM_LENGTH], \ [Display.ARM_LENGTH, 0], \ [0, -Display.ARM_LENGTH], \ [-Display.ARM_LENGTH, 0]] ] for index in range(4): self._canvasXY.coords(self._linesXY[index], x, y, x+lines[index][0], y-lines[index][1]) def _plotHeight(self, x, y, angle, canvas, lines): cosine = cos(angle) sine = sin(angle) vectors = [Vector.rotateVector(vector, sine, cosine) \ for vector in [[-Display.ARM_LENGTH, 0], \ [Display.ARM_LENGTH, 0]] ] for index in range(2): canvas.coords(lines[index], x, y, x+vectors[index][0], y+vectors[index][1]) def _plotXZ(self, coord, angles): x = 100 y = int(200.0 - (coord[2]*Display.PIXELS_METER%200.0)) self._plotHeight(x, y, angles[1], self._canvasXZ, self._linesXZ) def _plotYZ(self, coord, angles): x = 100 y = int(200.0 - (coord[2]*Display.PIXELS_METER%200.0)) self._plotHeight(x, y, -angles[0], self._canvasYZ, self._linesYZ) def _refresh(self): if self._isRunning: state = self._stateProvider.getState() angles = [radians(angle) for angle in state._angles] self._plotXY(state._coords, angles) self._plotXZ(state._coords, angles) self._plotYZ(state._coords, angles) self.update_idletasks() self.after(int(Display.REFRESH_PERIOD * 1000.0), self._refresh)
class Breakout(Tk): def __init__(self): Tk.__init__(self) #self.canvas.delete('all') self.geometry('790x600') self.resizable( 0, 0 ) #set both parameters to false and to check whether window is resizable in x and y directions self.func() # game screen def func(self): self.canvas = Canvas(self, bg='skyblue', width=990, height=600, highlightcolor='green') self.canvas.pack( expand=1, fill=BOTH ) #when it is true and widget expands to fill any space # ball self._initiate_new_ball() #self.level=choice([1]) # paddle self.canvas.create_rectangle(375, 975, 525, 585, fill='red', tags='paddle') self.bind('<Key>', self._move_paddle) # bricks self.bricks = {} brick_coords = [15, 12, 60, 45] for i in range(56): self.canvas.create_rectangle(brick_coords, outline='green', fill=('yellow'), tags='brick' + str(i)) self.bricks['brick' + str(i)] = None brick_coords[0] += 55 brick_coords[2] += 55 if brick_coords[2] > 790: brick_coords[0] = 15 brick_coords[2] = 60 brick_coords[1] += 55 brick_coords[3] += 55 def _initiate_new_ball(self): if self.canvas.find_withtag('ball'): self.canvas.delete('ball') self.x = 300 self.y = 350 self.angle = 240 self.speed = 10 self.level = 0 self.score = 0 self.canvas.create_oval(self.x, self.y, self.x + 10, self.y + 10, fill='orange', outline='red', tags='ball') self.after(2000, self._move_ball) def _move_paddle(self, event): if event.keysym == 'Left': if self.canvas.coords('paddle')[0] > 0: self.canvas.move('paddle', -20, 0) elif event.keysym == 'Right': if self.canvas.coords('paddle')[2] < 990: self.canvas.move('paddle', +20, 0) #def _move_ball1(self): # call1() #self._initiate_new_ball1() def _move_ball(self): # variables to determine where ball is in relation to other objects ball = self.canvas.find_withtag('ball')[0] bounds = self.canvas.find_overlapping(0, 0, 790, 600) paddle = self.canvas.find_overlapping( *self.canvas.coords('paddle')) for brick in self.bricks.iterkeys(): self.bricks[brick] = self.canvas.find_overlapping( *self.canvas.bbox(brick)) # calculate change in x,y values of ball angle = self.angle - 120 # correct for quadrant IV increment_x = cos(radians(angle)) * self.speed increment_y = sin(radians(angle)) * self.speed #self.level += choice([1]) #score=self.score #score=0 # finite state machine to set ball state if ball in bounds: self.ball_state = 'moving' for brick, hit in self.bricks.iteritems(): if ball in hit: self.ball_state = 'hit_brick' delete_brick = brick elif ball in paddle: self.ball_state = 'hit_wall' elif (self.score) // 3 == 56: self.canvas.create_text( WIDTH / 4, HEIGHT / 2.3, text="CONGRATS!! GAME COMPLETED!", font=("Helvetica", 20), fill="orange") self.canvas.create_text(WIDTH / 4, HEIGHT / 2, text=(self.score // 3), font=("Helvetica", 20), fill="red") self.canvas.create_text(WIDTH / 4, HEIGHT / 1.7, text="YOUR SCORE ", font=("Helvetica", 20), fill="darkorange") #image() quit_to_exit() call() elif ball not in bounds: if self.canvas.coords('ball')[1] < 600: self.ball_state = 'hit_wall' else: self.ball_state = 'out_of_bounds' #self.level += choice([1]) self.canvas.create_text( WIDTH / 2.5, HEIGHT / 2.3, text="GAME OVER !!PLEASE CLOSE THE WINDOW TO RESTART!", tag="cr2", font=("Helvetica", 20), fill="orange") self.canvas.create_text(WIDTH / 4, HEIGHT / 2, text="YOUR SCORE IS", tag="cr1", font=("Helvetica", 20), fill="orange") self.canvas.create_text(WIDTH / 4, HEIGHT / 1.7, text=(self.score // 3) + 1, tag="cr", font=("Helvetica", 20), fill="red") quit_to_exit() call() self._initiate_new_ball() #self.bind('<key>',self.game_over) #game = Breakout() #game.mainloop() # handler for ball state if self.ball_state is 'moving': self.canvas.move('ball', increment_x, increment_y) self.after(35, self._move_ball) # self.level +=choice([1]) elif self.ball_state is 'hit_brick' or self.ball_state is 'hit_wall': if self.ball_state == 'hit_brick': self.canvas.delete(delete_brick) del self.bricks[delete_brick] self.canvas.move('ball', -increment_x, -increment_y) # self.level += choice([1]) self.score += choice([1]) self.angle += choice([135]) self.canvas.delete("cr") self.canvas.delete("cr1") self.canvas.delete("cr2") #canvas.create_text(WIDTH/4,HEIGHT/5,text="GAME OVER!") self._move_ball()
class Breakout(Tk): def __init__(self): Tk.__init__(self) self.geometry('400x400') self.resizable(0, 0) # game screen self.canvas = Canvas(self, bg='black', width=400, height=400) self.canvas.pack(expand=1, fill=BOTH) # ball self._initiate_new_ball() # paddle self.canvas.create_rectangle(175, 375, 225, 385, fill='black', outline='white', tags='paddle') self.bind('<Key>', self._move_paddle) # bricks self.bricks = {} brick_coords = [5, 5, 35, 15] for i in range(39): self.canvas.create_rectangle(*brick_coords, outline='white', fill=('#{}'.format( randint(100000, 999999))), tags='brick' + str(i)) self.bricks['brick' + str(i)] = None brick_coords[0] += 30 brick_coords[2] += 30 if brick_coords[2] > 395: brick_coords[0] = 5 brick_coords[2] = 35 brick_coords[1] += 10 brick_coords[3] += 10 def _initiate_new_ball(self): if self.canvas.find_withtag('ball'): self.canvas.delete('ball') self.x = 60 self.y = 100 self.angle = 140 self.speed = 5 self.canvas.create_oval(self.x, self.y, self.x + 10, self.y + 10, fill='lawn green', outline='white', tags='ball') self.after(1000, self._move_ball) def _move_paddle(self, event): if event.keysym == 'Left': if self.canvas.coords('paddle')[0] > 0: self.canvas.move('paddle', -10, 0) elif event.keysym == 'Right': if self.canvas.coords('paddle')[2] < 400: self.canvas.move('paddle', +10, 0) def _move_ball(self): # variables to determine where ball is in relation to other objects ball = self.canvas.find_withtag('ball')[0] bounds = self.canvas.find_overlapping(0, 0, 400, 400) paddle = self.canvas.find_overlapping(*self.canvas.coords('paddle')) for brick in self.bricks.iterkeys(): self.bricks[brick] = self.canvas.find_overlapping( *self.canvas.bbox(brick)) # calculate change in x,y values of ball angle = self.angle - 90 # correct for quadrant IV increment_x = cos(radians(angle)) * self.speed increment_y = sin(radians(angle)) * self.speed # finite state machine to set ball state if ball in bounds: self.ball_state = 'moving' for brick, hit in self.bricks.iteritems(): if ball in hit: self.ball_state = 'hit_brick' delete_brick = brick elif ball in paddle: self.ball_state = 'hit_wall' elif ball not in bounds: if self.canvas.coords('ball')[1] < 400: self.ball_state = 'hit_wall' else: self.ball_state = 'out_of_bounds' self._initiate_new_ball() # handler for ball state if self.ball_state is 'moving': self.canvas.move('ball', increment_x, increment_y) self.after(15, self._move_ball) elif self.ball_state is 'hit_brick' or self.ball_state is 'hit_wall': if self.ball_state == 'hit_brick': self.canvas.delete(delete_brick) del self.bricks[delete_brick] self.canvas.move('ball', -increment_x, -increment_y) self.angle += choice([119, 120, 121]) self._move_ball()
class Game: def __init__(self): self.root = Tk() self.frame1 = None self.frame2 = None self.w = None self.scoreC = None self.score = 0 self.hor = True self.upid = self.downid = self.rightid = self.leftid = 0 self.head = -1 self.time = 700 def home(self): self.frame1 = Frame(self.root, width=750, height=350, padx=250, bg="black") self.frame2 = Frame(self.root, height=250, width=750, bg="black", padx=25) self.root.wm_minsize(width=750, height=666) self.root.configure(bg="black") self.frame1.pack_propagate(0) self.frame1.update() self.frame1.configure(pady=self.frame1.cget("height") / 2.5) logo = PhotoImage(file="logo.gif") starth = Button(self.frame1, text="Hard", bg="orange", padx=25, pady=5, font=Font(family="comic sans MS", size=10), command=lambda: self.callgame(40)) startm = Button(self.frame1, text="Medium", bg="teal", padx=25, pady=5, font=Font(family="comic sans MS", size=10), command=lambda: self.callgame(60)) starte = Button(self.frame1, text="Easy", bg="orange", padx=25, pady=5, font=Font(family="comic sans MS", size=10), command=lambda: self.callgame(75)) self.frame2.pack_propagate(0) exp = """ This is a game in which the arrow keys are used to move the snake around and to get points""" exf = Font(family="comic sans MS", size=20) Label(self.frame2, image=logo, bg="black", text=exp, padx=10).pack(side="right") Label(self.frame2, fg="white", bg="black", text=exp, justify="left", font=exf).pack(side="left") starte.grid(row=0, columnspan=2) startm.grid(row=0, columnspan=2, column=4, padx=18) starth.grid(row=0, columnspan=2, column=8) head = Font(family="comic sans MS", size=30) self.H = Label(self.root, text="SNAKES", font=head, fg="orange", bg="black", pady=10) self.H.pack() self.frame2.pack(expand=True) self.frame1.pack(expand=True) self.root.mainloop() def callgame(self, time): self.time = time self.game() def do_after_cancel(self, a, b): if a != 0: self.w.after_cancel(a) if b != 0: self.w.after_cancel(b) def calldown(self, key): if self.hor: self.do_after_cancel(self.leftid, self.rightid) self.down(0) def callup(self, key): if self.hor: self.do_after_cancel(self.leftid, self.rightid) self.up(0) def callright(self, key): if not self.hor: self.do_after_cancel(self.upid, self.downid) self.right(0) def callleft(self, key): if not self.hor: self.do_after_cancel(self.upid, self.downid) self.left(0) def game(self): self.score = 0 self.w = Canvas(self.root, width=750, height=500, relief="flat", highlightbackground="grey", highlightthickness=10) self.frame1.destroy() self.frame2.destroy() self.root.configure(width=1000, padx=10) self.root.pack_propagate(0) self.w.configure(background="black") self.w.pack(side="left") self.w.create_line(300, 250, 450, 250, width=10, fill="teal") self.scoreC = Label(self.root, text="Score\n" + str(self.score), bg="black", fg="teal", padx=25, pady=35, font=Font(family="comic sans MS", size=25)) self.head = self.w.create_line(450, 250, 455, 250, width=10, fill="white") self.scoreC.pack(side="top") self.root.bind("<Up>", self.callup) self.root.bind("<Down>", self.calldown) self.root.bind("<Right>", self.callright) self.root.bind("<Left>", self.callleft) self.createFood() self.right(0) def down(self, i): crd = self.w.coords(1) if len(crd) > 0: if crd[0] == crd[2]: if crd[1] > crd[3]: # print("inside if1") crd[1] -= 10 if crd[1] < crd[3]: # print("inside if2") crd[1] += 10 else: if crd[0] > crd[2]: crd[0] -= 10 if crd[0] < crd[2]: crd[0] += 10 crd[-1] += 10 if i == 0: crd.append(crd[-2]) crd.append(crd[-2]) crd[-3] -= 10 if crd[0] == crd[2] and crd[1] == crd[3]: crd = crd[2:] self.w.coords(1, *crd) self.w.delete(self.head) self.head = self.w.create_line(crd[-2], crd[-1], crd[-2], crd[-1] + 5, width=10, fill="orange") end = self.end() self.checkEaten() i += 1 self.hor = False if not end: self.downid = self.w.after(self.time, self.down, i) else: self.w.delete(1) self.w.delete(self.head) self.w.delete(self.food) self.start = Button(self.root, text="Start", bg="orange", padx=25, pady=25, font=Font(family="comic sans MS", size=15), command=lambda: self.callhome()) self.start.pack(side="bottom") def up(self, i): crd = self.w.coords(1) if len(crd) > 0: if crd[0] == crd[2]: if crd[1] > crd[3]: # print("inside if1") crd[1] -= 10 if crd[1] < crd[3]: # print("inside if2") crd[1] += 10 else: if crd[0] > crd[2]: crd[0] -= 10 if crd[0] < crd[2]: crd[0] += 10 crd[-1] -= 10 if i == 0: crd.append(crd[-2]) crd.append(crd[-2]) crd[-3] += 10 if crd[0] == crd[2] and crd[1] == crd[3]: crd = crd[2:] self.w.coords(1, *crd) self.w.delete(self.head) self.head = self.w.create_line(crd[-2], crd[-1], crd[-2], crd[-1] - 5, width=10, fill="orange") end = self.end() self.checkEaten() i += 1 self.hor = False if not end: self.upid = self.w.after(self.time, self.up, i) else: self.w.delete(1) self.w.delete(self.head) self.w.delete(self.food) self.start = Button(self.root, text="Start", bg="orange", padx=25, pady=25, font=Font(family="comic sans MS", size=15), command=lambda: self.callhome()) self.start.pack(side="bottom") def right(self, i): crd = self.w.coords(1) if len(crd) > 0: if crd[0] == crd[2]: if crd[1] > crd[3]: # print("inside if1") crd[1] -= 10 if crd[1] < crd[3]: # print("inside if2") crd[1] += 10 else: if crd[0] > crd[2]: crd[0] -= 10 if crd[0] < crd[2]: crd[0] += 10 crd[-2] += 10 if i == 0: crd.append(crd[-2]) crd.append(crd[-2]) crd[-4] -= 10 if crd[0] == crd[2] and crd[1] == crd[3]: crd = crd[2:] self.w.coords(1, *crd) self.w.delete(self.head) self.head = self.w.create_line(crd[-2], crd[-1], crd[-2] + 5, crd[-1], width=10, fill="orange") end = self.end() self.checkEaten() i += 1 self.hor = True if not end: self.rightid = self.w.after(self.time, self.right, i) else: self.w.delete(1) self.w.delete(self.head) self.w.delete(self.food) self.start = Button(self.root, text="Start", bg="orange", padx=25, pady=25, font=Font(family="comic sans MS", size=15), command=lambda: self.callhome()) self.start.pack(side="bottom") def left(self, i): crd = self.w.coords(1) if len(crd) > 0: if crd[0] == crd[2]: if crd[1] > crd[3]: # print("inside if1") crd[1] -= 10 if crd[1] < crd[3]: # print("inside if2") crd[1] += 10 else: if crd[0] > crd[2]: crd[0] -= 10 if crd[0] < crd[2]: crd[0] += 10 crd[-2] -= 10 if i == 0: crd.append(crd[-2]) crd.append(crd[-2]) crd[-4] += 10 if crd[0] == crd[2] and crd[1] == crd[3]: crd = crd[2:] self.w.coords(1, *crd) self.w.delete(self.head) self.head = self.w.create_line(crd[-2], crd[-1], crd[-2] - 5, crd[-1], width=10, fill="orange") end = self.end() self.checkEaten() i += 1 self.hor = True if not end: self.leftid = self.w.after(self.time, self.left, i) else: self.w.delete(1) self.w.delete(self.head) self.w.delete(self.food) self.start = Button(self.root, text="Start", bg="orange", padx=25, pady=25, font=Font(family="comic sans MS", size=15), command=lambda: self.callhome()) self.start.pack(side="bottom") def createFood(self): # self.w.delete(self.food) #deleting old food. crd = self.w.coords(1) ext = [] for i in crd: ext.append(i) for j in range(-50, 50): ext.append(i + j) randx = random.randrange(20, 730) randy = random.randrange(20, 480) while randx not in ext and randy not in ext: randx = random.randrange(20, 730) randy = random.randrange(20, 480) self.food = self.w.create_line(randx, randy, randx + 12, randy, width=10, fill="yellow") def checkEaten(self): headcoords = self.w.coords(self.head) foodcoords = self.w.coords(self.food) # self.w.delete(self.food) flag = False # print(headcoords[-4]) # print(foodcoords[-4]) # print(foodcoords[-2]) if int(headcoords[-4]) in range( int(foodcoords[-4]) - 7, int(foodcoords[-2]) + 7) and int(headcoords[-3]) in range( int(foodcoords[-1]) - 10, int(foodcoords[-1] + 10)): flag = True if flag: self.grow() self.score += 10 self.scoreC.configure(text="Score\n" + str(self.score), bg="black", fg="teal", padx=25, pady=35, font=Font(family="comic sans MS", size=25)) self.w.delete(self.food) self.createFood() def grow(self): crd = self.w.coords(1) if crd[0] != crd[2]: # horizontal condition if crd[0] < crd[2]: crd[0] -= 20 else: crd[0] += 20 self.w.coords(1, *crd) else: if crd[3] < crd[1]: crd[1] += 20 else: crd[1] -= 20 self.w.coords(1, *crd) def end(self): crd = self.w.coords(1) h = self.w.coords(self.head) a = 0 while a < len(crd) - 2: if crd[a] == crd[a + 2]: if (h[0] == crd[a] and crd[a + 1] < h[1] < crd[a + 3]) or ( h[0] == crd[a] and crd[a + 1] > h[1] > crd[a + 3]): return True else: if (h[1] == crd[a + 1] and crd[a] < h[0] < crd[a + 2]) or ( h[1] == crd[a + 1] and crd[a] > h[0] > crd[a + 2]): return True a += 2 if (h[0] == 0 and 0 < h[1] < 500) or (h[1] == 0 and 0 < h[0] < 750) or ( h[1] == 510 and 0 < h[0] < 750) or (h[0] == 760 and 0 < h[1] < 500): return True return False def callhome(self): self.w.destroy() self.start.destroy() self.H.destroy() self.scoreC.destroy() self.home()
class PhyUI(): def callback_switcher(self): """ Callback function for switching status between 'freezed' and 'on going'. """ play_ref = self.button_play if not self.locked : play_ref.config(text = "Play") self.locked = True else: play_ref.config(text = "Freeze") self.locked = False def keyevent_up_press(self, event): """ Callback for pressing up key. """ self.mouse_lock = True self.selected_user_accel_factor[0] = 1 def keyevent_up_release(self, event): """ Callback for releasing up key. """ self.mouse_lock = False self.selected_user_accel_factor[0] = 0 def keyevent_down_press(self, event): """ Callback for pressing down key. """ self.mouse_lock = True self.selected_user_accel_factor[1] = 1 def keyevent_down_release(self, event): """ Callback for releasing down key. """ self.mouse_lock = False self.selected_user_accel_factor[1] = 0 def keyevent_left_press(self, event): """ Callback for pressing left key. """ self.mouse_lock = True self.selected_user_accel_factor[2] = 1 def keyevent_left_release(self, event): """ Callback for releasing left key. """ self.mouse_lock = False self.selected_user_accel_factor[2] = 0 def keyevent_right_press(self, event): """ Callback for pressing right key """ self.mouse_lock = True self.selected_user_accel_factor[3] = 1 def keyevent_right_release(self, event): """ Callback for releasing right key """ self.mouse_lock = False self.selected_user_accel_factor[3] = 0 def __init__(self, root_handle, canvas_width, canvas_height): """ Setup the whole application.""" self.locked = True # True for freeze. self.mouse_lock = False # True for locking the mouse behavior. self.selected = None # What ball is selected now? self.selected_user_accel_factor = [0, 0, 0, 0] # Acceleration from user's keypress event self.selected_user_accel_val = [Vect2D(0, 15), Vect2D(0, -5), Vect2D(-5, 0), Vect2D(5, 0)] self.circles = [] # Reference to all the balls. # Initialize the main variables for the application self.frm_main = Frame(root_handle) self.frm_side_top = LabelFrame(root_handle, text = "Realtime Parameters:") self.frm_side_bot = Frame(root_handle) # Setup the frames self.canv_width = canvas_width self.canv_height = canvas_height self.canvas_base = Vect2D(0, self.canv_height) self.canvas = Canvas( self.frm_main, width = self.canv_width, height = self.canv_height, bg = "#cccccc") # Setup the canvas self.canvas.bind_all("<KeyPress-w>", self.keyevent_up_press) self.canvas.bind_all("<KeyRelease-w>", self.keyevent_up_release) self.canvas.bind_all("<KeyPress-a>", self.keyevent_left_press) self.canvas.bind_all("<KeyRelease-a>", self.keyevent_left_release) self.canvas.bind_all("<KeyPress-d>", self.keyevent_right_press) self.canvas.bind_all("<KeyRelease-d>", self.keyevent_right_release) self.canvas.bind_all("<KeyPress-s>", self.keyevent_down_press) self.canvas.bind_all("<KeyRelease-s>", self.keyevent_down_release) # Setup all keys self.button_play = Button(self.frm_side_bot, text = "Play", command = self.callback_switcher) self.button_add = Button(self.frm_side_bot, text = "Exit", command = root_handle.quit) # Setup all the buttons side_names = ["Mass", "Positioin", "Velocity", "Acceleration"] self.side_label = [] self.side_entry = [] for name in side_names: self.side_label.append(Label(self.frm_side_top, text = name + ":")) self.side_entry.append(Label(self.frm_side_top, width = 20)) # Setup information area located on the sidebar self.frm_main.grid(row = 0, column = 0, rowspan = 2) self.frm_side_top.grid(row = 0, column = 1, sticky = "S") self.frm_side_bot.grid(row = 1, column = 1, sticky = "S") self.canvas.grid(row = 0, column = 0, columnspan = 2) self.button_play.grid(row = 1, column = 0, sticky = "E") self.button_add.grid(row = 1, column = 1, sticky = "W") for i in xrange(len(self.side_label)): self.side_label[i].grid(row = i, column = 0) self.side_entry[i].grid(row = i, column = 1) # Build up the layout def set_viewport(self, math_bl, math_tr): """ Set the translation rate. You should call this before calling trans or rev_trans. """ self.scale_factor = Vect2D( self.canv_width / float(math_tr.x - math_bl.x), -self.canv_height / float(math_tr.y - math_bl.y)) self.math_base = math_bl def trans(self, pos): """ Translation (from math coord to canvas coord).""" return (pos - self.math_base).scale(self.scale_factor) + \ self.canvas_base def rev_trans(self, pos): """ Reverse translation (from canvas coord to math coord).""" return (pos - self.canvas_base).rev_scale(self.scale_factor) + \ self.math_base def canvas_refresh(self, id, vertexes): """ Refresh the canvas """ self.canvas.coords(id, vertexes) def update_side_bot(self): """ Update the information posted on the side bar.""" if self.selected: self.side_entry[0].config(text = str(self.selected.mass)) self.side_entry[1].config(text = self.selected.shift.get_str()) self.side_entry[2].config(text = self.selected.velo.get_str()) self.side_entry[3].config(text = self.selected.accel.get_str()) else: for i in xrange(4): self.side_entry[i].config(text = "") def create_circle(self, vertexes): """ Create a circle graphically and return the id of the object. """ return self.canvas.create_oval( vertexes, fill="white" ) def create_line(self, vertexes): """ Create a line graphically and return the id of the object.""" return self.canvas.create_line(vertexes) def register_trigger(self, obj, real_interval, math_interval): """ Call this for hooking any simulated objects.""" self.canvas.after( real_interval, obj.refresh, real_interval, math_interval)
global scaling_factor if event.char == '>': scaling_factor = scaling_factor + 0.1 resize() elif event.char == '<': scaling_factor = scaling_factor - 0.1 resize() elif event.char == "<Right>": x = x + 5 print x (x, y) = canvas.coords(zoeid) canvas.bind("<Right>", lambda event: canvas.move(zoeid, 5, 0)) canvas.bind("<Left>", lambda event: canvas.move(zoeid, -5, 0)) canvas.bind("<Up>", lambda event: canvas.move(zoeid, 0, -5)) canvas.bind("<Down>", lambda event: canvas.move(zoeid, 0, 5)) canvas.focus_set() canvas.bind("<Key>", key) scaling_factor = 1.0 def resize():
class Application(Frame, object): """The application main class.""" WIDTH, HEIGHT = 1280, 720 BG = 'white' FONT = 'Verdana' FILE_OPEN_OPTIONS = { 'mode': 'rb', 'title': 'Choose *.json file', 'defaultextension': '.json', 'filetypes': [('JSON file', '*.json')] } DEFAULTS = 'default_settings.yaml' def __init__(self, master=None): """Creates application main window with sizes self.WIDTH and self.HEIGHT. :param master: instance - Tkinter.Tk instance """ super(Application, self).__init__(master) self.master.title('Engine Game') self.master.geometry('{}x{}'.format(self.WIDTH, self.HEIGHT)) self.master.protocol('WM_DELETE_WINDOW', self.exit) self.source = None self._map = None self.points = None self.lines = None self.captured_point = None self.x0 = None self.y0 = None self.scale_x = None self.scale_y = None self.font_size = None self.coordinates = {} self.captured_lines = {} self.canvas_obj = AttrDict() self.icons = { 0: PhotoImage(file=join('icons', 'player_city.png')), 1: PhotoImage(file=join('icons', 'city.png')), 2: PhotoImage(file=join('icons', 'market.png')), 3: PhotoImage(file=join('icons', 'store.png')), 4: PhotoImage(file=join('icons', 'point.png')), 5: PhotoImage(file=join('icons', 'player_train.png')), 6: PhotoImage(file=join('icons', 'train.png')), 7: PhotoImage(file=join('icons', 'crashed_train.png')), 8: PhotoImage(file=join('icons', 'collision.png')), 9: PhotoImage(file=join('icons', 'play.png')), 10: PhotoImage(file=join('icons', 'play_pressed.png')), 11: PhotoImage(file=join('icons', 'stop.png')), 12: PhotoImage(file=join('icons', 'stop_pressed.png')) } self.queue_requests = { 0: self.set_status_bar, 1: self.set_player_idx, 2: self.build_map, 3: self.refresh_map, 4: self.set_available_games, 99: self.bot_control } self.settings_window = None if exists(expanduser(self.DEFAULTS)): with open(expanduser(self.DEFAULTS), 'r') as cfg: defaults = DefaultsDict.from_yaml(cfg) self.host = None if not defaults.host else str(defaults.host) self.port = None if not defaults.port else int(defaults.port) self.timeout = None if not defaults.timeout else int(defaults.timeout) self.username = None if not defaults.username else str(defaults.username) self.password = None if not defaults.password else str(defaults.password) else: self.host, self.port, self.timeout, self.username, self.password = None, None, None, None, None self.player_idx = None self.posts = {} self.trains = {} self.select_game_window = False self.available_games = None self.game = None self.num_players = None self.num_turns = None self.bot = Bot() self.bot_thread = None self.menu = Menu(self) filemenu = Menu(self.menu) filemenu.add_command(label='Open file', command=self.file_open) filemenu.add_command(label='Server settings', command=self.open_server_settings) filemenu.add_command(label='Select game', command=self.select_game) filemenu.add_command(label='Exit', command=self.exit) self.menu.add_cascade(label='Menu', menu=filemenu) master.config(menu=self.menu) self._status_bar = StringVar() self.label = Label(master, textvariable=self._status_bar) self.label.pack() self.frame = Frame(self) self.frame.bind('<Configure>', self._resize_frame) self.canvas = Canvas(self.frame, bg=self.BG, scrollregion=(0, 0, self.winfo_width(), self.winfo_height())) self.canvas.bind('<Button-1>', self._capture_point) self.canvas.bind('<Motion>', self._move_point) self.canvas.bind('<B1-ButtonRelease>', self._release_point) self.canvas.bind('<Configure>', self._resize_canvas) hbar = Scrollbar(self.frame, orient=HORIZONTAL) hbar.pack(side=BOTTOM, fill=X) hbar.config(command=self.canvas.xview) vbar = Scrollbar(self.frame, orient=VERTICAL) vbar.pack(side=RIGHT, fill=Y) vbar.config(command=self.canvas.yview) self.canvas.config(xscrollcommand=hbar.set, yscrollcommand=vbar.set) self.canvas.pack(fill=BOTH, expand=True) self.play = Label(self.canvas, bg='white') self.play.configure(image=self.icons[9]) self.play.bind('<Button-1>', self._play_press) self.play.bind('<B1-ButtonRelease>', self._play_release) self.stop = Label(self.canvas, bg='white') self.stop.configure(image=self.icons[11]) self.stop.bind('<Button-1>', self._stop_press) self.stop.bind('<B1-ButtonRelease>', self._stop_release) self.frame.pack(fill=BOTH, expand=True) self.weighted = IntVar(value=1) self.weighted_check = Checkbutton(self, text='Proportionally to length', variable=self.weighted, command=self._proportionally) self.weighted_check.pack(side=LEFT) self.show_weight = IntVar() self.show_weight_check = Checkbutton(self, text='Show length', variable=self.show_weight, command=self.show_weights) self.show_weight_check.pack(side=LEFT) self.pack(fill=BOTH, expand=True) self.requests_executor() self.get_available_games() self.set_status_bar('Click Play to start the game') self.play.place(rely=0.5, relx=0.5, anchor=CENTER) @property def map(self): """Returns the actual map.""" return self._map @map.setter def map(self, value): """Clears previously drawn map and assigns a new map to self._map.""" self.clear_map() self.canvas.configure(scrollregion=(0, 0, self.canvas.winfo_width(), self.canvas.winfo_height())) self.x0, self.y0 = self.canvas.winfo_width() / 2, self.canvas.winfo_height() / 2 self._map = value @staticmethod def midpoint(x_start, y_start, x_end, y_end): """Calculates a midpoint coordinates between two points. :param x_start: int - x coordinate of the start point :param y_start: int - y coordinate of the start point :param x_end: int - x coordinate of the end point :param y_end: int - y coordinate of the end point :return: 2-tuple of a midpoint coordinates """ return (x_start + x_end) / 2, (y_start + y_end) / 2 def _resize_frame(self, event): """Calculates new font size each time frame size changes. :param event: Tkinter.Event - Tkinter.Event instance for Configure event :return: None """ self.font_size = int(0.0125 * min(event.width, event.height)) def _resize_canvas(self, event): """Redraws map each time Canvas size changes. Scales map each time visible part of Canvas is enlarged. :param event: Tkinter.Event - Tkinter.Event instance for Configure event :return: None """ if self.map: k = min(float(event.width) / float(self.x0 * 2), float(event.height) / float(self.y0 * 2)) self.scale_x, self.scale_y = self.scale_x * k, self.scale_y * k self.x0, self.y0 = self.x0 * k, self.y0 * k self.redraw_map() self.redraw_trains() x_start, y_start, x_end, y_end = self.canvas.bbox('all') x_start = 0 if x_start > 0 else x_start y_start = 0 if y_start > 0 else y_start self.canvas.configure(scrollregion=(x_start, y_start, x_end, y_end)) def _proportionally(self): """Rebuilds map and redraws trains.""" self.build_map() self.redraw_trains() def _capture_point(self, event): """Stores captured point and it's lines. :param event: Tkinter.Event - Tkinter.Event instance for ButtonPress event :return: None """ x, y = self.canvas.canvasx(event.x), self.canvas.canvasy(event.y) obj_ids = self.canvas.find_overlapping(x - 5, y - 5, x + 5, y + 5) if not obj_ids: return for obj_id in obj_ids: if obj_id in self.canvas_obj.point.keys(): self.captured_point = obj_id point_idx = self.canvas_obj.point[obj_id]['idx'] self.captured_lines = {} for line_id, attr in self.canvas_obj.line.items(): if attr['start_point'] == point_idx: self.captured_lines[line_id] = 'start_point' if attr['end_point'] == point_idx: self.captured_lines[line_id] = 'end_point' if self.weighted.get(): self.weighted.set(0) def _release_point(self, event): """Writes new coordinates for a moved point and resets self.captured_point and self.captured_lines. :param event: Tkinter.Event - Tkinter.Event instance for ButtonRelease event :return: None """ if self.captured_point: idx = self.canvas_obj.point[self.captured_point]['idx'] x, y = self.canvas.canvasx(event.x), self.canvas.canvasy(event.y) self.coordinates[idx] = (x, y) self.points[idx]['x'], self.points[idx]['y'] = (x - self.x0) / self.scale_x, (y - self.y0) / self.scale_y self.captured_point = None self.captured_lines = {} def _move_point(self, event): """Moves point and its lines. Moves weights if self.show_weight is set to 1. In case some point is moved beyond Canvas border Canvas scrollregion is resized correspondingly. :param event: Tkinter.Event - Tkinter.Event instance for Motion event :return: None """ if self.captured_point: new_x, new_y = self.canvas.canvasx(event.x), self.canvas.canvasy(event.y) self.canvas.coords(self.captured_point, new_x, new_y) indent_y = self.icons[self.canvas_obj.point[self.captured_point]['icon']].height() / 2 + self.font_size if self.canvas_obj.point[self.captured_point]['text_obj']: self.canvas.coords(self.canvas_obj.point[self.captured_point]['text_obj'], new_x, new_y - indent_y) self.coordinates[self.canvas_obj.point[self.captured_point]['idx']] = (new_x, new_y) self.canvas.configure(scrollregion=self.canvas.bbox('all')) for line_id, attr in self.captured_lines.items(): line_attrs = self.canvas_obj.line[line_id] if attr == 'start_point': x, y = self.coordinates[line_attrs['end_point']] self.canvas.coords(line_id, new_x, new_y, x, y) else: x, y = self.coordinates[line_attrs['start_point']] self.canvas.coords(line_id, x, y, new_x, new_y) if self.show_weight.get(): mid_x, mid_y = self.midpoint(new_x, new_y, x, y) self.canvas.coords(line_attrs['weight_obj'][1], mid_x, mid_y) r = self.font_size * len(str(line_attrs['weight'])) self.canvas.coords(line_attrs['weight_obj'][0], mid_x - r, mid_y - r, mid_x + r, mid_y + r) self.redraw_trains() def _play_press(self, _): """Draws play button pressed icon.""" self.play.configure(image=self.icons[10]) def _play_release(self, _): """Draws play button icon and calls bot_control method.""" self.play.configure(image=self.icons[9]) self.bot_control() def _stop_press(self, _): """Draws stop button pressed icon.""" self.stop.configure(image=self.icons[12]) def _stop_release(self, _): """Draws stop buton icon and calls bot_control method.""" self.stop.configure(image=self.icons[11]) self.bot_control() def set_player_idx(self, value): """Sets a player idx value.""" self.player_idx = value def file_open(self): """Opens file dialog and builds and draws a map once a file is chosen. Stops bot if its started.""" path = tkFileDialog.askopenfile(parent=self.master, **self.FILE_OPEN_OPTIONS) if path: if self.bot_thread: self.bot_control() self.posts, self.trains = {}, {} self.source = path.name self.weighted_check.configure(state=NORMAL) self.build_map() def open_server_settings(self): """Opens server settings window.""" ServerSettings(self, title='Server settings') def select_game(self): """Opens select game window.""" self.select_game_window = True SelectGame(self, title='Select game') self.select_game_window = False self.set_status_bar('Click Play to start the game') def exit(self): """Closes application and stops bot if its started.""" if self.bot_thread: self.bot_control() self.master.destroy() def bot_control(self): """Starts bot for playing the game or stops it if it is started.""" if not self.bot_thread: self.bot_thread = Thread(target=self.bot.start, kwargs={ 'host': self.host, 'port': self.port, 'time_out': self.timeout, 'username': self.username, 'password': self.password, 'game': self.game, 'num_players': self.num_players, 'num_turns': self.num_turns}) self.bot_thread.start() else: self.bot.stop() self.bot_thread.join() self.bot_thread = None def get_available_games(self): """Requests a list of available games.""" if self.select_game_window: self.bot.get_available_games(host=self.host, port=self.port, time_out=self.timeout) self.after(1000, self.get_available_games) def set_available_games(self, games): """Sets new value for available games list.""" self.available_games = games def set_status_bar(self, value): """Assigns new status bar value and updates it. :param value: string - status bar string value :return: None """ self._status_bar.set(value) self.label.update() def build_map(self, source=None): """Builds and draws new map. :param source: string - source string; could be JSON string or path to *.json file. :return: None """ if source: self.source = source if self.source: self.map = Graph(self.source, weighted=self.weighted.get()) self.set_status_bar('Map title: {}'.format(self.map.name)) self.points, self.lines = self.map.get_coordinates() self.draw_map() def draw_map(self): """Draws map by prepared coordinates.""" self.draw_lines() self.draw_points() def clear_map(self): """Clears previously drawn map and resets coordinates and scales.""" self.canvas.delete('all') self.scale_x, self.scale_y = None, None self.coordinates = {} def redraw_map(self): """Redraws existing map by existing coordinates.""" if self.map: self.coordinates = {} for obj_id in self.canvas_obj.line: self.canvas.delete(obj_id) self.draw_lines() self.redraw_points() def redraw_points(self): """Redraws map points by existing coordinates.""" if self.map: for obj_id, attrs in self.canvas_obj.point.items(): if attrs['text_obj']: self.canvas.delete(attrs['text_obj']) self.canvas.delete(obj_id) self.draw_points() def redraw_trains(self): """Redraws existing trains.""" if self.trains and hasattr(self.canvas_obj, 'train'): for obj_id, attrs in self.canvas_obj.train.items(): self.canvas.delete(attrs['text_obj']) self.canvas.delete(obj_id) self.draw_trains() @prepare_coordinates def draw_points(self): """Draws map points by prepared coordinates.""" point_objs = {} captured_point_idx = self.canvas_obj.point[self.captured_point]['idx'] if self.captured_point else None for idx in self.points.keys(): x, y = self.coordinates[idx] if self.posts and idx in self.posts.keys(): post_type = self.posts[idx]['type'] if post_type == 1: status = '{}/{} {}/{} {}/{}'.format(self.posts[idx]['population'], self.posts[idx]['population_capacity'], self.posts[idx]['product'], self.posts[idx]['product_capacity'], self.posts[idx]['armor'], self.posts[idx]['armor_capacity']) elif post_type == 2: status = '{}/{}'.format(self.posts[idx]['product'], self.posts[idx]['product_capacity']) else: status = '{}/{}'.format(self.posts[idx]['armor'], self.posts[idx]['armor_capacity']) image_id = 0 if post_type == 1 and self.posts[idx]['player_idx'] == self.player_idx else post_type point_id = self.canvas.create_image(x, y, image=self.icons[image_id]) y -= (self.icons[post_type].height() / 2) + self.font_size text_id = self.canvas.create_text(x, y, text=status, font="{} {}".format(self.FONT, self.font_size)) else: post_type = 4 point_id = self.canvas.create_image(x, y, image=self.icons[post_type]) text_id = None point_objs[point_id] = {'idx': idx, 'text_obj': text_id, 'icon': post_type} self.captured_point = point_id if idx == captured_point_idx else self.captured_point self.canvas_obj['point'] = point_objs @prepare_coordinates def draw_lines(self): """Draws map lines by prepared coordinates and shows their weights if self.show_weight is set to 1.""" line_objs, captured_lines_idx = {}, {} if self.captured_lines: for line_id in self.captured_lines.keys(): captured_lines_idx[self.canvas_obj.line[line_id]['idx']] = line_id for idx, attrs in self.lines.items(): x_start, y_start = self.coordinates[attrs['start_point']] x_stop, y_stop = self.coordinates[attrs['end_point']] line_id = self.canvas.create_line(x_start, y_start, x_stop, y_stop) line_objs[line_id] = {'idx': idx, 'weight': attrs['weight'], 'start_point': attrs['start_point'], 'end_point': attrs['end_point'], 'weight_obj': ()} if idx in captured_lines_idx.keys(): self.captured_lines[line_id] = self.captured_lines.pop(captured_lines_idx[idx]) self.canvas_obj['line'] = line_objs self.show_weights() @prepare_coordinates def draw_trains(self): """Draws trains by prepared coordinates.""" trains = {} for train in self.trains.values(): start_point = self.lines[train['line_idx']]['start_point'] end_point = self.lines[train['line_idx']]['end_point'] weight = self.lines[train['line_idx']]['weight'] position = train['position'] x_start, y_start = self.coordinates[start_point] x_end, y_end = self.coordinates[end_point] delta_x, delta_y = int((x_start - x_end) / weight) * position, int((y_start - y_end) / weight) * position x, y = x_start - delta_x, y_start - delta_y if train['cooldown'] > 0: icon = 7 status = None else: icon = 5 if train['player_idx'] == self.player_idx else 6 status = '{}/{}'.format(train['goods'], train['goods_capacity']) indent_y = self.icons[icon].height() / 2 train_id = self.canvas.create_image(x, y - indent_y, image=self.icons[icon]) text_id = self.canvas.create_text(x, y - (2 * indent_y + self.font_size), text=status, font="{} {}".format(self.FONT, self.font_size)) if status else None trains[train_id] = {'icon': icon, 'text_obj': text_id} self.canvas_obj['train'] = trains def show_weights(self): """Shows line weights when self.show_weight is set to 1 and hides them when it is set to 0.""" if not self.canvas_obj: return if self.show_weight.get(): for line in self.canvas_obj.line.values(): if line['weight_obj']: for obj in line['weight_obj']: self.canvas.itemconfigure(obj, state='normal') else: x_start, y_start = self.coordinates[line['start_point']] x_end, y_end = self.coordinates[line['end_point']] x, y = self.midpoint(x_start, y_start, x_end, y_end) value = line['weight'] size = self.font_size r = int(size) * len(str(value)) oval_id = self.canvas.create_oval(x - r, y - r, x + r, y + r, fill=self.BG, width=0) text_id = self.canvas.create_text(x, y, text=value, font="{} {}".format(self.FONT, str(size))) line['weight_obj'] = (oval_id, text_id) else: for line in self.canvas_obj.line.values(): if line['weight_obj']: for obj in line['weight_obj']: self.canvas.itemconfigure(obj, state='hidden') def requests_executor(self): """Dequeues and executes requests. Assigns corresponding label to bot control button.""" if not self.bot.queue.empty(): request_type, request_body = self.bot.queue.get_nowait() if request_type == 99 and request_body: self.open_server_settings() request_body = None if request_body is not None: self.queue_requests[request_type](request_body) else: self.queue_requests[request_type]() if self.bot_thread and self.bot_thread.is_alive(): if self.play.place_info(): self.play.place_forget() self.stop.place(rely=0.99, relx=0.995, anchor=SE) else: if self.stop.place_info(): self.stop.place_forget() self.play.place(rely=0.5, relx=0.5, anchor=CENTER) self.after(50, self.requests_executor) def refresh_map(self, dynamic_objects): """Refreshes map with passed dynamic objects. :param dynamic_objects: dict - dict of dynamic objects :return: None """ for post in dynamic_objects['posts']: self.posts[post['point_idx']] = post for train in dynamic_objects['trains']: self.trains[train['idx']] = train self.redraw_points() self.redraw_trains()
class ConstraintSolver(Frame): def __init__(self, parent): Frame.__init__(self, parent) self.parent = parent self.init() self.animate() def init(self): self.parent.title("ConstraintSolver") self.pack(fill=BOTH, expand=1) self.canvas = Canvas(self) self.current_iteration = 0 self.num_iterations = 100 # Start Coordinates self.start_hip = [50.0, 120.0] self.start_left_foot = [80.0, 200.0] self.start_right_foot = [20.0, 200.0] # End Coordinates self.end_hip = [80.0, 105.0] self.end_left_foot = [80.0, 200.0] self.end_right_foot = [80.0, 185.0] self.segment_length = 50.0 # Variables self.left_leg_length = distance(self.start_hip[0], self.start_hip[1], self.start_left_foot[0], self.start_left_foot[1]) self.left_leg_angle = math.atan2( self.start_left_foot[1] - self.start_hip[1], self.start_left_foot[0] - self.start_hip[0]) self.right_leg_length = distance(self.start_hip[0], self.start_hip[1], self.start_right_foot[0], self.start_right_foot[1]) self.right_leg_angle = math.atan2( self.start_right_foot[1] - self.start_hip[1], self.start_right_foot[0] - self.start_hip[0]) # Calculate Starting Positions left_segment_angle = math.acos( (self.left_leg_length / 2) / self.segment_length) left_knee_x_dif = self.segment_length * math.cos(self.left_leg_angle + left_segment_angle) left_knee_y_dif = self.segment_length * math.sin(self.left_leg_angle + left_segment_angle) left_knee_x = self.start_left_foot[0] - left_knee_x_dif left_knee_y = self.start_left_foot[1] - left_knee_y_dif right_segment_angle = math.acos( (self.right_leg_length / 2) / self.segment_length) right_knee_x_dif = self.segment_length * math.cos( self.right_leg_angle + right_segment_angle) right_knee_y_dif = self.segment_length * math.sin( self.right_leg_angle + right_segment_angle) right_knee_x = self.start_right_foot[0] - right_knee_x_dif right_knee_y = self.start_right_foot[1] - right_knee_y_dif # Add Lines to Canvas self.left_lower_leg = self.canvas.create_line(self.start_left_foot[0], self.start_left_foot[1], left_knee_x, left_knee_y, width=2) self.left_upper_leg = self.canvas.create_line(left_knee_x, left_knee_y, self.start_hip[0], self.start_hip[1], width=2) self.right_lower_leg = self.canvas.create_line( self.start_right_foot[0], self.start_right_foot[1], right_knee_x, right_knee_y, width=2) self.right_upper_leg = self.canvas.create_line(right_knee_x, right_knee_y, self.start_hip[0], self.start_hip[1], width=2) self.torso = self.canvas.create_line(self.start_hip[0], self.start_hip[1], self.start_hip[0], self.start_hip[1] - 80.0, width=2) self.canvas.pack(fill=BOTH, expand=1) def left_leg_length_change(self): end_hip_dif_x = self.start_left_foot[0] - self.end_hip[0] end_hip_dif_y = self.start_left_foot[1] - self.end_hip[1] end_hip_angle = math.atan2(end_hip_dif_y, end_hip_dif_x) angle_dif = end_hip_angle - self.left_leg_angle projection = math.cos(angle_dif) * math.sqrt(end_hip_dif_x**2 + end_hip_dif_y**2) distance_dif = projection - self.left_leg_length iteration_ratio = 1.0 / (self.num_iterations - self.current_iteration) return self.left_leg_length + distance_dif * iteration_ratio def left_leg_angle_change(self): end_hip_dif_x = self.start_left_foot[0] - self.end_hip[0] end_hip_dif_y = self.start_left_foot[1] - self.end_hip[1] end_hip_angle = math.atan2(end_hip_dif_y, end_hip_dif_x) angle_dif = end_hip_angle - self.left_leg_angle iteration_ratio = 1.0 / (self.num_iterations - self.current_iteration) return self.left_leg_angle + angle_dif * iteration_ratio def right_leg_length_change(self): current_hip_x = self.start_left_foot[0] - \ math.cos(self.left_leg_angle)*self.left_leg_length current_hip_y = self.start_left_foot[1] - \ math.sin(self.left_leg_angle)*self.left_leg_length end_right_foot_dif_x = self.end_right_foot[0] - current_hip_x end_right_foot_dif_y = self.end_right_foot[1] - current_hip_y end_right_foot_angle = math.atan2(end_right_foot_dif_y, end_right_foot_dif_x) angle_dif = end_right_foot_angle - self.right_leg_angle projection = math.cos(angle_dif) * math.sqrt(end_right_foot_dif_x**2 + end_right_foot_dif_y**2) distance_dif = projection - self.right_leg_length iteration_ratio = 1.0 / (self.num_iterations - self.current_iteration) return self.right_leg_length + distance_dif * iteration_ratio def right_leg_angle_change(self): current_hip_x = self.start_left_foot[0] - \ math.cos(self.left_leg_angle)*self.left_leg_length current_hip_y = self.start_left_foot[1] - \ math.sin(self.left_leg_angle)*self.left_leg_length end_right_foot_dif_x = self.end_right_foot[0] - current_hip_x end_right_foot_dif_y = self.end_right_foot[1] - current_hip_y end_right_foot_angle = math.atan2(end_right_foot_dif_y, end_right_foot_dif_x) angle_dif = end_right_foot_angle - self.right_leg_angle iteration_ratio = 1.0 / (self.num_iterations - self.current_iteration) return self.right_leg_angle + angle_dif * iteration_ratio def update_variables(self): new_left_leg_length = self.left_leg_length_change() # print "Old: ", self.left_leg_length, " New: ", new_left_leg_length new_left_leg_angle = self.left_leg_angle_change() # print "Old: ", self.left_leg_angle, " New: ", new_left_leg_angle new_right_leg_length = self.right_leg_length_change() # print "Old: ", self.right_leg_length, " New: ", new_right_leg_length new_right_leg_angle = self.right_leg_angle_change() # print "Old: ", self.right_leg_angle, " New: ", new_right_leg_angle self.left_leg_length = new_left_leg_length self.left_leg_angle = new_left_leg_angle self.right_leg_length = new_right_leg_length self.right_leg_angle = new_right_leg_angle def animate(self): # Calculate Current Position left_segment_angle = math.acos( (self.left_leg_length / 2) / self.segment_length) left_knee_x_dif = self.segment_length * math.cos(self.left_leg_angle + left_segment_angle) left_knee_y_dif = self.segment_length * math.sin(self.left_leg_angle + left_segment_angle) left_knee_x = self.start_left_foot[0] - left_knee_x_dif left_knee_y = self.start_left_foot[1] - left_knee_y_dif hip_x_dif = self.left_leg_length * math.cos(self.left_leg_angle) hip_y_dif = self.left_leg_length * math.sin(self.left_leg_angle) hip_x = self.start_left_foot[0] - hip_x_dif hip_y = self.start_left_foot[1] - hip_y_dif right_segment_angle = math.acos( (self.right_leg_length / 2) / self.segment_length) aligned_angle = self.right_leg_angle - right_segment_angle right_knee_x_dif = self.segment_length * math.cos(aligned_angle) right_knee_y_dif = self.segment_length * math.sin(aligned_angle) right_knee_x = hip_x + right_knee_x_dif right_knee_y = hip_y + right_knee_y_dif right_foot_x_dif = self.right_leg_length * math.cos( self.right_leg_angle) right_foot_y_dif = self.right_leg_length * math.sin( self.right_leg_angle) right_foot_x = hip_x + right_foot_x_dif right_foot_y = hip_y + right_foot_y_dif # Update Lines on Canvas self.canvas.coords(self.left_lower_leg, self.start_left_foot[0], self.start_left_foot[1], left_knee_x, left_knee_y) self.canvas.coords(self.left_upper_leg, left_knee_x, left_knee_y, hip_x, hip_y) self.canvas.coords(self.right_upper_leg, right_knee_x, right_knee_y, hip_x, hip_y) self.canvas.coords(self.right_lower_leg, right_foot_x, right_foot_y, right_knee_x, right_knee_y) self.canvas.coords(self.torso, hip_x, hip_y, hip_x, hip_y - 80.0) self.current_iteration = self.current_iteration + 1 if self.current_iteration < self.num_iterations: self.update_variables() self.after(10, self.animate)
class Screen(Observer): def __init__(self, parent, model): self.parent = parent self.model = model self.canvas = Canvas(parent) self.curve_id = -1 self.control_points_id = [] self.control_point_index = -1 def set_canvas(self, canvas): self.canvas = canvas def get_canvas(self): return self.canvas # View : update() the Bezier curve def update(self, subject): curve = subject.get_curve() self.canvas.delete(self.curve_id) self.curve_id = self.canvas.create_line(curve, width=3, fill='gray40') # View : control points visualisation def update_control_points(self, model): control_points = model.get_control_points() # self.canvas.delete('ctrl_pts') del self.control_points_id[:] i = 0 while i < len(control_points): x, y = control_points[i] self.control_points_id.append( self.canvas.create_oval(x, y, x + 10, y + 10, outline='black', fill='green')) i = i + 1 # Controler : control point interaction to update the Bezier curve def select_point(self, event, model): control_points = model.get_control_points() # selection of a control point i = 0 while i < len(control_points): x, y = control_points[i] if x - 10 < event.x < x + 10 and y - 10 < event.y < y + 10: self.control_point_index = i self.canvas.itemconfigure( self.control_points_id[self.control_point_index], fill='red') break i = i + 1 # insertion of a control point if self.control_point_index == -1: i = 0 while i < len(control_points) - 1: x1, y1 = control_points[i] x2, y2 = control_points[i + 1] print(event.x, event.y) if (x1 < event.x < x2 or x2 < event.x < x1) and (y1 < event.y < y2 or y2 < event.y < y1): control_points.insert(i, (event.x, event.y)) model.set_control_points(control_points) self.update_control_points(model) break i = i + 1 self.update_control_points(model) def move_point(self, event, model): if 0 <= self.control_point_index < len(self.control_points_id): coords = self.canvas.coords( self.control_points_id[self.control_point_index]) x1, y1 = coords[0], coords[1] x1, y1 = event.x - x1, event.y - y1 control_points = model.get_control_points() control_points[self.control_point_index] = event.x, event.y model.set_control_points(control_points) self.canvas.move(self.control_points_id[self.control_point_index], x1, y1) model.compute_curve() def release_point(self, event): self.canvas.itemconfigure( self.control_points_id[self.control_point_index], fill='green') self.control_point_index = -1 def packing(self): self.canvas.pack(fill='both', expand=True)
class Example(Frame): def __init__(self, parent): Frame.__init__(self, parent) self.parent = parent self.buttons = {} self.nodes = {} self.edges = {} self.active_node = None self.active_edge = None self.start = None self.x = None self.y = None self.cycles = None self.show_cycles_only_mode = False self.steps = None self.step_index = None self.parent.title("Demonstrační aplikace - nalezení elementárních cyklů v orientovaném grafu") self.style = Style() self.style.theme_use("default") self.pack(fill=BOTH, expand=1) self.columnconfigure(1, weight=1) self.columnconfigure(3, pad=7) self.rowconfigure(5, weight=1) self.rowconfigure(6, pad=7) self.label = Label(self, text="graf1.graphml") self.label.grid(sticky=W, pady=4, padx=5) self.canvas = Canvas(self) self.canvas.bind('<Double-Button-1>', self.event_add_node) self.canvas.bind('<Button-1>', self.event_add_edge_start) self.canvas.bind('<B1-Motion>', self.event_add_edge_move) self.canvas.bind('<ButtonRelease-1>', self.event_add_edge_end) self.canvas.bind('<Button-3>', self.event_move_node_start) self.canvas.bind('<B3-Motion>', self.event_move_node) self.canvas.pack() self.canvas.grid(row=1, column=0, columnspan=2, rowspan=6, padx=5, sticky=E + W + S + N) self.buttons['start'] = b = Button(self, text="Start", width=15) b.bind('<Button-1>', self.event_start) b.grid(row=1, column=3) self.buttons['next'] = b = Button(self, text=">>", width=15, state=DISABLED) b.bind('<Button-1>', self.event_next_step) b.grid(row=2, column=3, pady=4) self.buttons['prev'] = b = Button(self, text="<<", width=15, state=DISABLED) b.bind('<Button-1>', self.event_prev_step) b.grid(row=3, column=3, pady=4) b = Checkbutton(self, text="Pouze cykly", command=self.event_change_mode) b.grid(row=4, column=3, pady=4) self.buttons['reset'] = b = Button(self, text="Reset", width=15) b.bind('<Button-1>', self.event_reset) b.grid(row=6, column=3) menubar = Menu(self.parent) self.parent.config(menu=menubar) fileMenu = Menu(menubar) fileMenu.add_command(label="Načíst", command=self.onLoad) fileMenu.add_command(label="Uložit", command=self.onSave) fileMenu.add_separator() fileMenu.add_command(label="Konec", command=self.onExit) menubar.add_cascade(label="Soubor", menu=fileMenu) fileMenu = Menu(menubar) fileMenu.add_command(label="O aplikaci", command=self.onAbout) menubar.add_cascade(label="Nápověda", menu=fileMenu) def onExit(self): self.quit() def onLoad(self): fileTypes = [('Soubory typu GraphML', '*.graphml')] dialog = tkFileDialog.Open(self, filetypes=fileTypes) filename = dialog.show() if filename != '': self.readFile(filename) def onSave(self): fileTypes = [('GraphML files', '*.graphml')] dialog = tkFileDialog.SaveAs(self, filetypes=fileTypes) filename = dialog.show() if filename != '': if not filename.endswith(".graphml"): filename += ".graphml" self.writeFile(filename) def onAbout(self): box.showinfo("O aplikaci", "Demonstrace algoritmu nalezení elementárních cyklů v orientovaném grafu podle D. B. Johnsona. \n\n" "Autoři:\n" "Paulík Miroslav\n" "Pavlů Igor\n" "FIT VUT v Brně 2013") def readFile(self, filename): self.reset() try: parser = GraphMLParser() g = parser.parse(filename) except Exception: box.showerror("Chyba při zpracování vstupního souboru", "Chybný formát souboru.") return nodeMap = {} try: for gnode in g.nodes(): nodeMap[gnode.id] = self.__add_node(int(gnode['x']), int(gnode['y'])) except KeyError: box.showerror("Chyba při zpracování vstupního souboru", "Uzlum chybi udaje o pozici (atributy x a y).") self.reset() return try: for gedge in g.edges(): start = nodeMap[gedge.node1.id] end = nodeMap[gedge.node2.id] isCurve = gedge.node1.id == gedge.node2.id self.__add_edge(start, end, isCurve) self.label.configure(text=os.path.basename(filename)) except KeyError: box.showerror("Chyba při zpracování vstupního souboru", "Soubor obsahuje hrany spojujici neexistujici hrany") self.reset() return self.repaint() def writeFile(self, filename): g = Graph() for i in self.nodes: node = self.nodes[i] node.name = str(i) gnode = g.add_node(i) gnode['label'] = i gnode['x'] = node.x gnode['y'] = node.y for i in self.edges: edge = self.edges[i] edge.name = i parser = GraphMLParser() parser.write(g, filename) def repaint(self): for e in self.edges: edge = self.edges[e] self.canvas.itemconfigure(e, fill=edge.color) for v in self.nodes: node = self.nodes[v] self.canvas.itemconfigure(v, fill=node.color) def reset_colors(self): for n in self.nodes: self.nodes[n].color = "white" for e in self.edges: self.edges[e].color = "grey" def reset(self): self.nodes = {} self.edges = {} self.canvas.delete("all") self.buttons['prev'].config(state=DISABLED) self.buttons['next'].config(state=DISABLED) def run(self): x = ElementaryCircuitsDetector(self.nodes, self.edges) x.detect_cycles() self.cycles = x.cycles self.step_index = 0 self.steps = x.get_all_steps() self.algorithm_step_move(0) if len(self.steps) > 0: self.buttons['prev'].config(state=1) self.buttons['next'].config(state=1) def event_reset(self, event): self.reset() def event_prev_step(self, event): if str(self.buttons['prev'].cget("state")) != str(DISABLED): self.algorithm_step_move(-1) def event_next_step(self, event): if str(self.buttons['next'].cget("state")) != str(DISABLED): self.algorithm_step_move(1) def event_start(self, event): self.run() def event_change_mode(self): self.show_cycles_only_mode = not self.show_cycles_only_mode self.run() def event_add_edge_start(self, event): self.x = event.x self.y = event.y def event_add_edge_move(self, event): if self.active_edge is None: self.active_edge = self.canvas.create_line(self.x, self.y, event.x, event.y, arrow="last", width=2) else: x1, y1, x2, y2 = self.canvas.coords(self.active_edge) self.canvas.coords(self.active_edge, x1, y1, event.x, event.y) def event_add_edge_end(self, event): if self.active_edge is None: return x1, y1, x2, y2 = self.canvas.coords(self.active_edge) start = self.__get_node_from_position(x1, y1) end = self.__get_node_from_position(x2, y2) if start is None or end is None: self.canvas.delete(self.active_edge) elif start == end: self.canvas.delete(self.active_edge) edge = Edge(start, start, True) points = edge.get_coords() self.active_edge = self.canvas.create_line(points, width=2, smooth=True, arrow="last") self.canvas.tag_lower(self.active_edge, min(self.nodes.keys())) self.edges[self.active_edge] = edge else: x, y = self.__calculate_edge_end_from_nodes(start, end) self.canvas.coords(self.active_edge, start.x, start.y, x, y) self.canvas.tag_lower(self.active_edge, min(self.nodes.keys())) edge = Edge(start, end) self.edges[self.active_edge] = edge self.active_edge = None self.x = None self.y = None def event_move_node_start(self, event): id = self.__get_id_from_position(event.x, event.y) if id is None: return self.__activate_node(id) self.x = event.x self.y = event.y def event_move_node(self, event): id = self.active_node if id is None: return deltax = event.x - self.x deltay = event.y - self.y self.canvas.move(id, deltax, deltay) self.x = event.x self.y = event.y coord = self.canvas.coords(id) self.nodes[self.active_node].x = (coord[2] - coord[0]) / 2 + coord[0] self.nodes[self.active_node].y = (coord[3] - coord[1]) / 2 + coord[1] self.__repair_edge_starting_in_node(self.nodes[self.active_node]) self.__repair_edge_ending_in_node(self.nodes[self.active_node]) def event_add_node(self, event): id = self.__get_id_from_position(event.x, event.y, reverse=True) if id is None or id not in self.nodes: self.__add_node(event.x, event.y) def __repair_edge_ending_in_node(self, node): list_of_edge_ids = [] for edge_id in self.edges: edge = self.edges[edge_id] if edge.end == node: list_of_edge_ids.append(edge_id) for edge_id in list_of_edge_ids: edge = self.edges[edge_id] x, y = self.__calculate_edge_end_from_nodes(edge.start, edge.end) if edge.is_curve: coords = edge.get_coords() self.canvas.coords(edge_id, coords[0][0], coords[0][1], coords[1][0], coords[1][1], coords[2][0], coords[2][1], coords[3][0], coords[3][1]) else: self.canvas.coords(edge_id, edge.start.x, edge.start.y, x, y) def __repair_edge_starting_in_node(self, node): list_of_edge_ids = [] for edge_id in self.edges: edge = self.edges[edge_id] if edge.start == node: list_of_edge_ids.append(edge_id) for edge_id in list_of_edge_ids: edge = self.edges[edge_id] x, y = self.__calculate_edge_end_from_nodes(edge.start, edge.end) if edge.is_curve: coords = edge.get_coords() self.canvas.coords(edge_id, coords[0][0], coords[0][1], coords[1][0], coords[1][1], coords[2][0], coords[2][1], coords[3][0], coords[3][1]) else: self.canvas.coords(edge_id, edge.start.x, edge.start.y, x, y) def __calculate_edge_end_from_nodes(self, start_node, end_node): diffx = end_node.x - start_node.x diffy = end_node.y - start_node.y distance = math.sqrt(diffx ** 2 + diffy ** 2) if distance > 0: ratio = NODE_SIZE / 2 / distance x = end_node.x - diffx * ratio y = end_node.y - diffy * ratio return x, y return end_node.x, end_node.y def __activate_node(self, id): self.__deactivate_node() if id in self.nodes: self.active_node = id def __deactivate_node(self): self.active_node = None def __get_id_from_position(self, x, y, reverse=False): overlaping = self.canvas.find_overlapping(x, y, x, y) if len(overlaping) > 0: if reverse: return overlaping[-1] else: return overlaping[0] else: return None def __get_node_from_position(self, x, y): id = self.__get_id_from_position(x, y) if id is not None and id in self.nodes: return self.nodes[id] else: return None def __add_node(self, x, y): node = Node(x, y) id = self.canvas.create_oval(node.get_coord(), fill="blue") self.nodes[id] = node return node def __add_edge(self, start, end, is_curve=False): edge = Edge(start, end, is_curve) if is_curve: id = self.canvas.create_line(edge.get_coords(), width=2, smooth=True, arrow="last") else: id = self.canvas.create_line(start.x, start.y, end.x, end.y, arrow="last", width=2) self.edges[id] = edge self.canvas.tag_lower(id, min(self.nodes.keys())) self.__repair_edge_starting_in_node(start) return edge def algorithm_step_move(self, move): if self.show_cycles_only_mode: # cycles only if (self.step_index + move) < len(self.cycles) and self.step_index + move >= 0: self.step_index += move self.reset_colors() colors = ['green', 'blue', 'red', 'yellow', 'purple', 'brown'] color_index = self.step_index % len(colors) for edge in self.cycles[self.step_index]: edge.color = edge.start.color = edge.end.color = colors[color_index] self.repaint() else: if (self.step_index + move) < len(self.steps) and self.step_index + move >= 0: self.step_index += move self.reset_colors() for i in range(self.step_index + 1): colors = self.steps[i] for id in colors: if id in self.nodes.keys(): self.nodes[id].color = colors[id] elif id in self.edges.keys(): self.edges[id].color = colors[id] self.repaint()
class ConstraintSolver(Frame): def __init__(self, parent): Frame.__init__(self, parent) self.parent = parent self.init() self.animate() def init(self): self.parent.title("ConstraintSolver") self.pack(fill=BOTH, expand=1) self.canvas = Canvas(self) self.current_iteration = 0 self.num_iterations = 100 # Start Coordinates self.start_hip = [50.0, 120.0] self.start_left_foot = [80.0, 200.0] self.start_right_foot = [20.0, 200.0] # End Coordinates self.end_hip = [80.0, 105.0] self.end_left_foot = [80.0, 200.0] self.end_right_foot = [80.0, 185.0] self.segment_length = 50.0 # Variables self.left_leg_length = distance(self.start_hip[0], self.start_hip[1], self.start_left_foot[0], self.start_left_foot[1]) self.left_leg_angle = math.atan2(self.start_left_foot[1]-self.start_hip[1], self.start_left_foot[0]-self.start_hip[0]) self.right_leg_length = distance(self.start_hip[0], self.start_hip[1], self.start_right_foot[0], self.start_right_foot[1]) self.right_leg_angle = math.atan2(self.start_right_foot[1]-self.start_hip[1], self.start_right_foot[0]-self.start_hip[0]) # Calculate Starting Positions left_segment_angle = math.acos((self.left_leg_length/2)/self.segment_length) left_knee_x_dif = self.segment_length*math.cos(self.left_leg_angle+left_segment_angle) left_knee_y_dif = self.segment_length*math.sin(self.left_leg_angle+left_segment_angle) left_knee_x = self.start_left_foot[0]-left_knee_x_dif left_knee_y = self.start_left_foot[1]-left_knee_y_dif right_segment_angle = math.acos((self.right_leg_length/2)/self.segment_length) right_knee_x_dif = self.segment_length*math.cos(self.right_leg_angle+right_segment_angle) right_knee_y_dif = self.segment_length*math.sin(self.right_leg_angle+right_segment_angle) right_knee_x = self.start_right_foot[0]-right_knee_x_dif right_knee_y = self.start_right_foot[1]-right_knee_y_dif # Add Lines to Canvas self.left_lower_leg = self.canvas.create_line(self.start_left_foot[0], self.start_left_foot[1], left_knee_x, left_knee_y, width=2) self.left_upper_leg = self.canvas.create_line(left_knee_x, left_knee_y, self.start_hip[0], self.start_hip[1], width=2) self.right_lower_leg = self.canvas.create_line(self.start_right_foot[0], self.start_right_foot[1], right_knee_x, right_knee_y, width=2) self.right_upper_leg = self.canvas.create_line(right_knee_x, right_knee_y, self.start_hip[0], self.start_hip[1], width=2) self.torso = self.canvas.create_line(self.start_hip[0], self.start_hip[1], self.start_hip[0], self.start_hip[1]-80.0, width=2) self.canvas.pack(fill=BOTH, expand=1) def left_leg_length_change(self): end_hip_dif_x = self.start_left_foot[0] - self.end_hip[0] end_hip_dif_y = self.start_left_foot[1] - self.end_hip[1] end_hip_angle = math.atan2(end_hip_dif_y, end_hip_dif_x) angle_dif = end_hip_angle - self.left_leg_angle projection = math.cos(angle_dif)*math.sqrt(end_hip_dif_x**2+end_hip_dif_y**2) distance_dif = projection - self.left_leg_length iteration_ratio = 1.0/(self.num_iterations - self.current_iteration) return self.left_leg_length + distance_dif*iteration_ratio def left_leg_angle_change(self): end_hip_dif_x = self.start_left_foot[0] - self.end_hip[0] end_hip_dif_y = self.start_left_foot[1] - self.end_hip[1] end_hip_angle = math.atan2(end_hip_dif_y, end_hip_dif_x) angle_dif = end_hip_angle - self.left_leg_angle iteration_ratio = 1.0/(self.num_iterations - self.current_iteration) return self.left_leg_angle + angle_dif*iteration_ratio def right_leg_length_change(self): current_hip_x = self.start_left_foot[0] - \ math.cos(self.left_leg_angle)*self.left_leg_length current_hip_y = self.start_left_foot[1] - \ math.sin(self.left_leg_angle)*self.left_leg_length end_right_foot_dif_x = self.end_right_foot[0] - current_hip_x end_right_foot_dif_y = self.end_right_foot[1] - current_hip_y end_right_foot_angle = math.atan2(end_right_foot_dif_y, end_right_foot_dif_x) angle_dif = end_right_foot_angle - self.right_leg_angle projection = math.cos(angle_dif)*math.sqrt(end_right_foot_dif_x**2+end_right_foot_dif_y**2) distance_dif = projection - self.right_leg_length iteration_ratio = 1.0/(self.num_iterations - self.current_iteration) return self.right_leg_length + distance_dif*iteration_ratio def right_leg_angle_change(self): current_hip_x = self.start_left_foot[0] - \ math.cos(self.left_leg_angle)*self.left_leg_length current_hip_y = self.start_left_foot[1] - \ math.sin(self.left_leg_angle)*self.left_leg_length end_right_foot_dif_x = self.end_right_foot[0] - current_hip_x end_right_foot_dif_y = self.end_right_foot[1] - current_hip_y end_right_foot_angle = math.atan2(end_right_foot_dif_y, end_right_foot_dif_x) angle_dif = end_right_foot_angle - self.right_leg_angle iteration_ratio = 1.0/(self.num_iterations - self.current_iteration) return self.right_leg_angle + angle_dif*iteration_ratio def update_variables(self): new_left_leg_length = self.left_leg_length_change() # print "Old: ", self.left_leg_length, " New: ", new_left_leg_length new_left_leg_angle = self.left_leg_angle_change() # print "Old: ", self.left_leg_angle, " New: ", new_left_leg_angle new_right_leg_length = self.right_leg_length_change() # print "Old: ", self.right_leg_length, " New: ", new_right_leg_length new_right_leg_angle = self.right_leg_angle_change() # print "Old: ", self.right_leg_angle, " New: ", new_right_leg_angle self.left_leg_length = new_left_leg_length self.left_leg_angle = new_left_leg_angle self.right_leg_length = new_right_leg_length self.right_leg_angle = new_right_leg_angle def animate(self): # Calculate Current Position left_segment_angle = math.acos((self.left_leg_length/2)/self.segment_length) left_knee_x_dif = self.segment_length*math.cos(self.left_leg_angle+left_segment_angle) left_knee_y_dif = self.segment_length*math.sin(self.left_leg_angle+left_segment_angle) left_knee_x = self.start_left_foot[0]-left_knee_x_dif left_knee_y = self.start_left_foot[1]-left_knee_y_dif hip_x_dif = self.left_leg_length*math.cos(self.left_leg_angle) hip_y_dif = self.left_leg_length*math.sin(self.left_leg_angle) hip_x = self.start_left_foot[0]-hip_x_dif hip_y = self.start_left_foot[1]-hip_y_dif right_segment_angle = math.acos((self.right_leg_length/2)/self.segment_length) aligned_angle = self.right_leg_angle - right_segment_angle right_knee_x_dif = self.segment_length*math.cos(aligned_angle) right_knee_y_dif = self.segment_length*math.sin(aligned_angle) right_knee_x = hip_x + right_knee_x_dif right_knee_y = hip_y + right_knee_y_dif right_foot_x_dif = self.right_leg_length*math.cos(self.right_leg_angle) right_foot_y_dif = self.right_leg_length*math.sin(self.right_leg_angle) right_foot_x = hip_x + right_foot_x_dif right_foot_y = hip_y + right_foot_y_dif # Update Lines on Canvas self.canvas.coords(self.left_lower_leg, self.start_left_foot[0], self.start_left_foot[1], left_knee_x, left_knee_y) self.canvas.coords(self.left_upper_leg, left_knee_x, left_knee_y, hip_x, hip_y) self.canvas.coords(self.right_upper_leg, right_knee_x, right_knee_y, hip_x, hip_y) self.canvas.coords(self.right_lower_leg, right_foot_x, right_foot_y, right_knee_x, right_knee_y) self.canvas.coords(self.torso, hip_x, hip_y, hip_x, hip_y-80.0) self.current_iteration = self.current_iteration + 1 if self.current_iteration < self.num_iterations: self.update_variables() self.after(10, self.animate)
class histogramWidget: BACKGROUND = "#222222" EDGE_HISTOGRAM_COLOR = "#999999" NODE_HISTOGRAM_COLOR = "#555555" TOOLTIP_COLOR="#FFFF55" PADDING = 8 CENTER_WIDTH = 1 CENTER_COLOR = "#444444" ZERO_GAP = 1 UPDATE_WIDTH = 9 UPDATE_COLOR = "#FFFFFF" HANDLE_WIDTH = 5 HANDLE_COLOR = "#FFFFFF" HANDLE_LENGTH = (HEIGHT-2*PADDING) TICK_COLOR = "#FFFFFF" TICK_WIDTH = 10 TICK_FACTOR = 2 LOG_BASE = 10.0 def __init__(self, parent, x, y, width, height, data, logScale=False, callback=None): self.canvas = Canvas(parent,background=histogramWidget.BACKGROUND, highlightbackground=histogramWidget.BACKGROUND,width=width,height=height) self.canvas.place(x=x,y=y,width=width,height=height,bordermode="inside") self.logScale = logScale self.callback = callback self.edgeBars = [] self.nodeBars = [] self.binValues = [] self.numBins = len(data) - 1 self.currentBin = self.numBins # start the slider at the highest bin edgeRange = 0.0 nodeRange = 0.0 for values in data.itervalues(): if values[0] > edgeRange: edgeRange = values[0] if values[1] > nodeRange: nodeRange = values[1] edgeRange = float(edgeRange) # ensure that it will yield floats when used in calculations... nodeRange = float(nodeRange) if logScale: edgeRange = math.log(edgeRange,histogramWidget.LOG_BASE) nodeRange = math.log(nodeRange,histogramWidget.LOG_BASE) # calculate the center line - but don't draw it yet self.center_x = histogramWidget.PADDING if self.logScale: self.center_x += histogramWidget.TICK_WIDTH+histogramWidget.PADDING self.center_y = height/2 self.center_x2 = width-histogramWidget.PADDING self.center_y2 = self.center_y + histogramWidget.CENTER_WIDTH # draw the histograms with background-colored baseline rectangles (these allow tooltips to work on very short bars with little area) self.bar_interval = float(self.center_x2 - self.center_x) / (self.numBins+1) bar_x = self.center_x edge_y2 = self.center_y-histogramWidget.PADDING edge_space = edge_y2-histogramWidget.PADDING node_y = self.center_y2+histogramWidget.PADDING node_space = (height-node_y)-histogramWidget.PADDING thresholds = sorted(data.iterkeys()) for threshold in thresholds: self.binValues.append(threshold) edgeWeight = data[threshold][0] nodeWeight = data[threshold][1] if logScale: if edgeWeight > 0: edgeWeight = math.log(edgeWeight,histogramWidget.LOG_BASE) else: edgeWeight = 0 if nodeWeight > 0: nodeWeight = math.log(nodeWeight,histogramWidget.LOG_BASE) else: nodeWeight = 0 bar_x2 = bar_x + self.bar_interval edge_y = histogramWidget.PADDING + int(edge_space*(1.0-edgeWeight/edgeRange)) edge = self.canvas.create_rectangle(bar_x,edge_y,bar_x2,edge_y2,fill=histogramWidget.EDGE_HISTOGRAM_COLOR,width=0) baseline = self.canvas.create_rectangle(bar_x,edge_y2+histogramWidget.ZERO_GAP,bar_x2,edge_y2+histogramWidget.PADDING,fill=histogramWidget.BACKGROUND,width=0) self.canvas.addtag_withtag("Threshold: %f" % threshold,edge) self.canvas.addtag_withtag("No. Edges: %i" % data[threshold][0],edge) self.canvas.tag_bind(edge,"<Enter>",self.updateToolTip) self.canvas.tag_bind(edge,"<Leave>",self.updateToolTip) self.edgeBars.append(edge) self.canvas.addtag_withtag("Threshold: %f" % threshold,baseline) self.canvas.addtag_withtag("No. Edges: %i" % data[threshold][0],baseline) self.canvas.tag_bind(baseline,"<Enter>",self.updateToolTip) self.canvas.tag_bind(baseline,"<Leave>",self.updateToolTip) node_y2 = node_y + int(node_space*(nodeWeight/nodeRange)) node = self.canvas.create_rectangle(bar_x,node_y,bar_x2,node_y2,fill=histogramWidget.NODE_HISTOGRAM_COLOR,width=0) baseline = self.canvas.create_rectangle(bar_x,node_y-histogramWidget.PADDING,bar_x2,node_y-histogramWidget.ZERO_GAP,fill=histogramWidget.BACKGROUND,width=0) self.canvas.addtag_withtag("Threshold: %f" % threshold,node) self.canvas.addtag_withtag("No. Nodes: %i" % data[threshold][1],node) self.canvas.tag_bind(node,"<Enter>",self.updateToolTip) self.canvas.tag_bind(node,"<Leave>",self.updateToolTip) self.nodeBars.append(node) self.canvas.addtag_withtag("Threshold: %f" % threshold,baseline) self.canvas.addtag_withtag("No. Nodes: %i" % data[threshold][1],baseline) self.canvas.tag_bind(baseline,"<Enter>",self.updateToolTip) self.canvas.tag_bind(baseline,"<Leave>",self.updateToolTip) bar_x = bar_x2 # now draw the center line self.centerLine = self.canvas.create_rectangle(self.center_x,self.center_y,self.center_x2,self.center_y2,fill=histogramWidget.CENTER_COLOR,width=0) # draw the tick marks if logarithmic if self.logScale: tick_x = histogramWidget.PADDING tick_x2 = histogramWidget.PADDING+histogramWidget.TICK_WIDTH start_y = edge_y2 end_y = histogramWidget.PADDING dist = start_y-end_y while dist > 1: dist /= histogramWidget.TICK_FACTOR self.canvas.create_rectangle(tick_x,end_y+dist-1,tick_x2,end_y+dist,fill=histogramWidget.TICK_COLOR,width=0) start_y = node_y end_y = height-histogramWidget.PADDING dist = end_y-start_y while dist > 1: dist /= histogramWidget.TICK_FACTOR self.canvas.create_rectangle(tick_x,end_y-dist,tick_x2,end_y-dist+1,fill=histogramWidget.TICK_COLOR,width=0) # draw the update bar bar_x = self.currentBin*self.bar_interval + self.center_x bar_x2 = self.center_x2 bar_y = self.center_y-histogramWidget.UPDATE_WIDTH/2 bar_y2 = bar_y+histogramWidget.UPDATE_WIDTH self.updateBar = self.canvas.create_rectangle(bar_x,bar_y,bar_x2,bar_y2,fill=histogramWidget.UPDATE_COLOR,width=0) # draw the handle handle_x = self.currentBin*self.bar_interval-histogramWidget.HANDLE_WIDTH/2+self.center_x handle_x2 = handle_x+histogramWidget.HANDLE_WIDTH handle_y = self.center_y-histogramWidget.HANDLE_LENGTH/2 handle_y2 = handle_y+histogramWidget.HANDLE_LENGTH self.handleBar = self.canvas.create_rectangle(handle_x,handle_y,handle_x2,handle_y2,fill=histogramWidget.HANDLE_COLOR,width=0) self.canvas.tag_bind(self.handleBar, "<Button-1>",self.adjustHandle) self.canvas.tag_bind(self.handleBar, "<B1-Motion>",self.adjustHandle) self.canvas.tag_bind(self.handleBar, "<ButtonRelease-1>",self.adjustHandle) parent.bind("<Left>",lambda e: self.nudgeHandle(e,-1)) parent.bind("<Right>",lambda e: self.nudgeHandle(e,1)) # init the tooltip as nothing self.toolTipBox = self.canvas.create_rectangle(0,0,0,0,state="hidden",fill=histogramWidget.TOOLTIP_COLOR,width=0) self.toolTip = self.canvas.create_text(0,0,state="hidden",anchor="nw") self.canvas.bind("<Enter>",self.updateToolTip) self.canvas.bind("<Leave>",self.updateToolTip) def adjustHandle(self, event): newBin = int(self.numBins*(event.x-self.center_x)/float(self.center_x2-self.center_x)+0.5) if newBin == self.currentBin or newBin < 0 or newBin > self.numBins: return self.canvas.move(self.handleBar,(newBin-self.currentBin)*self.bar_interval,0) self.currentBin = newBin if self.callback != None: self.callback(self.binValues[newBin]) def nudgeHandle(self, event, distance): temp = self.currentBin+distance if temp < 0 or temp > self.numBins: return self.canvas.move(self.handleBar,distance*self.bar_interval,0) self.currentBin += distance if self.callback != None: self.callback(self.binValues[self.currentBin]) def update(self, currentBins): currentBar = self.canvas.coords(self.updateBar) self.canvas.coords(self.updateBar,currentBins*self.bar_interval+self.center_x,currentBar[1],currentBar[2],currentBar[3]) def updateToolTip(self, event): allTags = self.canvas.gettags(self.canvas.find_overlapping(event.x,event.y,event.x+1,event.y+1)) if len(allTags) == 0: self.canvas.itemconfig(self.toolTipBox,state="hidden") self.canvas.itemconfig(self.toolTip,state="hidden") return outText = "" for t in allTags: if t == "current": continue outText += t + "\n" outText = outText[:-1] # strip the last return self.canvas.coords(self.toolTip,event.x+20,event.y) self.canvas.itemconfig(self.toolTip,state="normal",text=outText,anchor="nw") # correct if our tooltip is off screen textBounds = self.canvas.bbox(self.toolTip) if textBounds[2] >= WIDTH-2*histogramWidget.PADDING: self.canvas.itemconfig(self.toolTip, anchor="ne") self.canvas.coords(self.toolTip,event.x-20,event.y) if textBounds[3] >= HEIGHT-2*histogramWidget.PADDING: self.canvas.itemconfig(self.toolTip, anchor="se") elif textBounds[3] >= HEIGHT-2*histogramWidget.PADDING: self.canvas.itemconfig(self.toolTip, anchor="sw") # draw the box behind it self.canvas.coords(self.toolTipBox,self.canvas.bbox(self.toolTip)) self.canvas.itemconfig(self.toolTipBox, state="normal")
class Walking(Frame): def __init__(self, parent): Frame.__init__(self, parent) self.parent = parent self.init() self.animate() def init(self): self.parent.title("Walking") self.pack(fill=BOTH, expand=1) self.canvas = Canvas(self) self.current_iteration = 0 self.num_iterations = 100 self.segment_length = 50.0 # Start Coordinates self.start_hip = [50.0,120.0] self.start_left_foot = [80.0,200.0] self.start_right_foot = [20.0,200.0] # End Coordinates self.end_hip = [80.0,105.0] self.end_left_foot = [80.0,200.0] self.end_right_foot = [80.0,180.0] # Calculate starting left leg leg_angle = math.atan2(self.start_left_foot[1]-self.start_hip[1], self.start_left_foot[0]-self.start_hip[0]) leg_length = distance(self.start_hip[0], self.start_hip[1], self.start_left_foot[0], self.start_left_foot[1]) segment_angle = math.acos((leg_length/2)/self.segment_length) self.current_left_ankle = leg_angle + segment_angle self.current_left_knee = 2*(PI/2 - segment_angle) self.current_left_hip = (PI/2 - leg_angle) + segment_angle # Calculate starting right leg leg_angle = math.atan2(self.start_right_foot[1]-self.start_hip[1], self.start_right_foot[0]-self.start_hip[0]) leg_length = distance(self.start_hip[0], self.start_hip[1], self.start_right_foot[0], self.start_right_foot[1]) segment_angle = math.acos((leg_length/2)/self.segment_length) self.current_right_ankle = leg_angle + segment_angle self.current_right_knee = 2*(PI/2 - segment_angle) self.current_right_hip = (PI/2 - leg_angle) + segment_angle # Calculate ending left leg leg_length = distance(self.end_hip[0], self.end_hip[1], self.end_left_foot[0], self.end_left_foot[1]) segment_angle = math.acos((leg_length/2)/self.segment_length) self.end_left_ankle = PI/2 + segment_angle self.end_left_knee = 2*(PI/2 - segment_angle) self.end_left_hip = segment_angle # Calculate ending right leg leg_length = distance(self.end_hip[0], self.end_hip[1], self.end_right_foot[0], self.end_right_foot[1]) segment_angle = math.acos((leg_length/2)/self.segment_length) self.end_right_ankle = PI/2 + segment_angle self.end_right_knee = 2*(PI/2 - segment_angle) self.end_right_hip = segment_angle self.dif_left_ankle = (self.end_left_ankle - self.current_left_ankle)/self.num_iterations self.dif_left_knee = (self.end_left_knee - self.current_left_knee)/self.num_iterations self.dif_left_hip = (self.end_left_hip - self.current_left_hip)/self.num_iterations self.dif_right_ankle = (self.end_right_ankle - self.current_right_ankle)/self.num_iterations self.dif_right_knee =(self.end_right_knee - self.current_right_knee)/self.num_iterations self.dif_right_hip = (self.end_right_hip - self.current_right_hip)/self.num_iterations # Calculate starting position knee_y_dif = self.segment_length*math.sin(self.current_left_ankle) knee_x_dif = self.segment_length*math.cos(self.current_left_ankle) knee_x = self.start_left_foot[0]-knee_x_dif knee_y = self.start_left_foot[1]-knee_y_dif self.left_lower_leg = self.canvas.create_line(self.start_left_foot[0], self.start_left_foot[1], knee_x, knee_y, width=2) self.left_upper_leg = self.canvas.create_line(knee_x, knee_y, self.start_hip[0], self.start_hip[1], width=2) knee_y_dif = self.segment_length*math.sin(self.current_right_ankle) knee_x_dif = self.segment_length*math.cos(self.current_right_ankle) knee_x = self.start_right_foot[0]-knee_x_dif knee_y = self.start_right_foot[1]-knee_y_dif self.right_lower_leg = self.canvas.create_line(self.start_right_foot[0], self.start_right_foot[1], knee_x, knee_y, width=2) self.right_upper_leg = self.canvas.create_line(knee_x, knee_y, self.start_hip[0], self.start_hip[1], width=2) self.torso = self.canvas.create_line(self.start_hip[0], self.start_hip[1], self.start_hip[0], self.start_hip[1]-80.0, width=2) self.canvas.pack(fill=BOTH, expand=1) def animate(self): # Left lower leg self.current_left_ankle = self.current_left_ankle + self.dif_left_ankle knee_y_dif = self.segment_length*math.sin(self.current_left_ankle) knee_x_dif = self.segment_length*math.cos(self.current_left_ankle) knee_x = self.start_left_foot[0]-knee_x_dif knee_y = self.start_left_foot[1]-knee_y_dif self.canvas.coords(self.left_lower_leg, self.start_left_foot[0], self.start_left_foot[1], knee_x, knee_y) # Left upper leg self.current_left_knee = self.current_left_knee + self.dif_left_knee aligned_angle = self.current_left_knee - (PI - self.current_left_ankle) hip_y_dif = self.segment_length*math.sin(aligned_angle) hip_x_dif = self.segment_length*math.cos(aligned_angle) hip_x = knee_x - hip_x_dif hip_y = knee_y - hip_y_dif self.canvas.coords(self.left_upper_leg, knee_x, knee_y, hip_x, hip_y) # Right upper leg self.current_right_hip = self.current_right_hip + self.dif_right_hip aligned_angle = PI/2 - self.current_right_hip hip_y_dif = self.segment_length*math.sin(aligned_angle) hip_x_dif = self.segment_length*math.cos(aligned_angle) knee_x = hip_x + hip_x_dif knee_y = hip_y + hip_y_dif self.canvas.coords(self.right_upper_leg, knee_x, knee_y, hip_x, hip_y) # Right lower leg self.current_right_knee = self.current_right_knee + self.dif_right_knee aligned_angle = self.current_right_knee - (PI/2 - self.current_right_hip) knee_y_dif = self.segment_length*math.sin(aligned_angle) knee_x_dif = self.segment_length*math.cos(aligned_angle) foot_x = knee_x - knee_x_dif foot_y = knee_y + knee_y_dif self.canvas.coords(self.right_lower_leg, foot_x, foot_y, knee_x, knee_y) # Torso self.canvas.coords(self.torso, hip_x, hip_y, hip_x, hip_y-80.0) self.current_iteration = self.current_iteration + 1 if self.current_iteration < self.num_iterations: self.after(10, self.animate)
class TKEA_win(object): def __init__(self,ea,p,rec,varlist): self.vl=varlist # list of EA attributes which you wanna make accessible via window self.ea=ea # the EA instance self.ea.generation_callbacks.append(self.update_solu_canvas) self.ea.generation_callbacks.append(self.update_mstep_bar) self.ea.generation_callbacks.append(self.rec_save_status) self.ea.generation_callbacks.append(self.acp_update) self.acp_type='linear' # also allowed up to date: 'semilogy' self.acp_ylim=False self.acp_freq=1 self.update_freq=1 self.p=p # main population self.rec=rec tmppop=population_like(p,size=1) self.frontman=tmppop[0] # an extra individual, the one bein plotted def appear(self): self.mwin=Tk() # root or main window self.mwin.title('EA progress visualisation') self.setupFig() self.setupWindow() def setupFig(self): self.fig=plt.figure(figsize=(8,7), dpi=80) self.sp1=self.fig.add_subplot(211) # additional colorbar might be created under the name self.sp1_cb self.sp2=self.fig.add_subplot(212) # additional colorbar might be created under the name self.sp2_cb self.sp1t=self.sp1.set_title('ini') self.sp2t=self.sp2.set_title('ini') def setupWindow(self): self.f_inp=Frame(self.mwin); self.f_inp.pack(side='left') self.f_plot=Frame(self.mwin); self.f_plot.pack(side='right') self.c=FigureCanvasTkAgg(self.fig, master=self.f_plot); self.c.show() self.c.get_tk_widget().pack(side=TOP, fill=BOTH, expand=1) # setup the input area self.f_actn=LabelFrame(self.f_inp,text='action'); self.f_actn.grid(row=0,column=0) self.f_gg=Frame(self.f_actn); self.f_gg.pack() l_gg=Label(self.f_gg,text='generations'); l_gg.pack() self.e_gg = Entry(self.f_gg); self.e_gg.pack(); self.e_gg.insert(0,'40') # number of generations self.b_rini=Button(self.f_actn,text='randini',command=self.randini); self.b_rini.pack() self.b_run1=Button(self.f_actn,text='update & run',command=self.run_with_readout); self.b_run1.pack() self.b_run2=Button(self.f_actn,text='run (continue)',command=self.run_no_readout); self.b_run2.pack() if len(self.vl): self.add_entries(self.vl) # draw initial plot self.draw_ini_solu() # sort of setting up instructive initial geometry plot of non-optimised geometry self.acp_ini() self.f_tb=Frame(self.f_plot); self.f_tb.pack() self.tb=NavigationToolbar2TkAgg(self.c,self.f_tb) self.c2=Canvas(self.f_inp,width=80,height=140); self.c2.grid(row=4,column=0) self.ini_mstep_bar() def add_entries(self,vl): for el in vl: if not hasattr(self.ea,el['name']): raise TypeError('you try to set up an entry for a name which is no attribute of the chosen EA') fr=Frame(self.f_actn); fr.pack() lab=Label(fr,text=el['name']); lab.pack() e = Entry(fr); e.pack(); e.insert(0,str(el['inival'])) # number of generations el['Entry']=e def draw_ini_solu(self): self.frontman.plot_into_axes(self.sp1) txt='initial DNA'.format(self.frontman.DNA) self.sp1t.set_text(txt) def draw_solu(self,dude): self.frontman.copy_DNA_of(dude,copyscore=True,copyparents=True,copyancestcode=True) self.frontman.evaluate() self.frontman.update_plot(self.sp1) txt='generation {}: score is {:.3f} after {} function calls'.format(self.p.gg,self.ea.bestdude.score,self.ea.tell_neval()) #self.sp1t.set_text(txt) self.sp1.set_title(txt) self.c.draw() def mainloop(self): self.mwin.mainloop() def randini(self): self.p.reset() self.rec.clear() self.ea.bestdude=None self.ea.zeroth_generation(random_ini=True) self.draw_solu(self.ea.bestdude) self.c.draw() def run_with_readout(self): for el in self.vl: if el['type'] is float: val=float(el['Entry'].get()) exec('self.ea.'+el['name']+'='+str(val)) elif el['type'] is int: val=int(float(el['Entry'].get())) exec('self.ea.'+el['name']+'='+str(val)) elif el['type'] is str: val=el['Entry'].get() exec('self.ea.'+el['name']+"='"+val+"'") elif el['type'] is list: val=el['Entry'].get() exec('self.ea.'+el['name']+"="+val) print 'string {} and what resulted {}'.format(val,eval('self.ea.'+el['name'])) else: raise NotImplementedError('only float and int parameters cared for at this point') self.ea.run(int(float(self.e_gg.get()))) def run_no_readout(self): self.ea.run(int(float(self.e_gg.get()))) def update_solu_canvas(self,eaobj): if np.mod(self.p.gg,self.update_freq)==0: self.draw_solu(self.ea.bestdude) def ini_mstep_bar(self): fg_color=bluered4hex(0.36); #textcolor='white' self.c2.create_rectangle(43,0,57,140,fill='white',outline='white') mstep_barheight=int(-0.25*log10(self.ea.mstep)*140); mstep_barheight=clip(mstep_barheight,0,140) self.mstep_bar=self.c2.create_rectangle(43,mstep_barheight,57,140,fill='green',outline='green') for h in [2,35,70,105,140]: self.c2.create_line(40,h,60,h,width=2,fill=fg_color) for h,poww in zip([6,30,65,100,130],['0','-1','-2','-3','-4']): self.c2.create_text(20,h,text='10**'+poww,font=('Courier','6')) def update_mstep_bar(self,eaobj): mstep_barheight=int(-0.25*log10(self.ea.mstep)*140); mstep_barheight=clip(mstep_barheight,0,140) self.c2.coords(self.mstep_bar,43,mstep_barheight,57,140) self.mwin.update_idletasks() def rec_save_status(self,eaobj): self.rec.save_status() def acp_ini(self,whiggle=0): x=[]; y=[]; farbe=[] for i,g in enumerate(self.rec.gg): for j in range(self.p.psize): x.append(g) y.append(self.rec.adat['scores'][i][j]) farbe.append(self.rec.adat['ancestcodes'][i][j]) x.append(0); y.append(0); farbe.append(0.) # for normalisation of color map x.append(0); y.append(0); farbe.append(1.) # for normalisation of color map x=flipud(array(x)); y=flipud(array(y)); farbe=flipud(array(farbe)) if whiggle: x=x+whiggle*npr.rand(len(x))-0.5*whiggle self.acdots=self.sp2.scatter(x,y,marker='o',c=farbe,cmap=ancestcolors,zorder=True) if self.acp_type=='semilogy': self.sp2.semilogy() if self.acp_ylim: self.sp2.axis((0,self.p.gg,self.acp_ylim[0],self.acp_ylim[1])) else: self.sp2.axis((0,self.p.gg,0,np.max(y))) def acp_update(self,eaobj,whiggle=0): if np.mod(self.p.gg,self.acp_freq)==0: self.sp2.cla() self.acp_ini(whiggle=whiggle) self.c.draw()
class Cockpit(ttkFrame): ''' Remote device GUI ''' #TODO: 20160415 DPM - Set these values from configuration file #--- config THROTTLE_BY_USER = True THROTTLE_RESOLUTION = 0.1 # Joystick enabled or not, if any JOYSTICK_ENABLED = True DEFAULT_DRONE_IP = "192.168.1.130" DEFAULT_DRONE_PORT = 2121 #--- end config KEY_ANG_SPEED = "ang-speed" KEY_ANGLES = "angles" KEY_ACCEL = "accel" PID_KEYS = ["P", "I", "D"] DIR_NONE = 0 DIR_VERTICAL = 1 DIR_HORIZONTAL = 2 def __init__(self, parent, isDummy = False, droneIp = DEFAULT_DRONE_IP, dronePort = DEFAULT_DRONE_PORT): ''' Constructor ''' ttkFrame.__init__(self, parent) self._target = [0.0] * 4 self._selectedPidConstats = "--" self._pidConstants = { Cockpit.KEY_ANG_SPEED:{ "X":{ "P": 0.0, "I": 0.0, "D": 0.0 }, "Y":{ "P": 0.0, "I": 0.0, "D": 0.0 }, "Z":{ "P": 0.0, "I": 0.0, "D": 0.0 } }, Cockpit.KEY_ANGLES: { "X":{ "P": 0.0, "I": 0.0, "D": 0.0 }, "Y":{ "P": 0.0, "I": 0.0, "D": 0.0 } }, Cockpit.KEY_ACCEL:{ "X":{ "P": 0.0, "I": 0.0, "D": 0.0 }, "Y":{ "P": 0.0, "I": 0.0, "D": 0.0 }, "Z":{ "P": 0.0, "I": 0.0, "D": 0.0 } } } self.parent = parent self.initUI() self._controlKeysLocked = False if not isDummy: self._link = INetLink(droneIp, dronePort) else: self._link = ConsoleLink() self._link.open() self._updateInfoThread = Thread(target=self._updateInfo) self._updateInfoThreadRunning = False self._readingState = False self._start() def initUI(self): self.parent.title("Drone control") self.style = Style() self.style.theme_use("default") self.pack(fill=BOTH, expand=1) self.parent.bind_all("<Key>", self._keyDown) self.parent.bind_all("<KeyRelease>", self._keyUp) if system() == "Linux": self.parent.bind_all("<Button-4>", self._onMouseWheelUp) self.parent.bind_all("<Button-5>", self._onMouseWheelDown) else: #case of Windows self.parent.bind_all("<MouseWheel>", self._onMouseWheel) #Commands commandsFrame = tkFrame(self) commandsFrame.grid(column=0, row=0, sticky="WE") self._started = IntVar() self._startedCB = Checkbutton(commandsFrame, text="On", variable=self._started, command=self._startedCBChanged) self._startedCB.pack(side=LEFT, padx=4) # self._integralsCB = Checkbutton(commandsFrame, text="Int.", variable=self._integralsEnabled, \ # command=self._integralsCBChanged, state=DISABLED) # self._integralsCB.pack(side=LEFT, padx=4) self._quitButton = Button(commandsFrame, text="Quit", command=self.exit) self._quitButton.pack(side=LEFT, padx=2, pady=2) # self._angleLbl = Label(commandsFrame, text="Angle") # self._angleLbl.pack(side=LEFT, padx=4) # # self._angleEntry = Entry(commandsFrame, state=DISABLED) # self._angleEntry.pack(side=LEFT) #Info infoFrame = tkFrame(self) infoFrame.grid(column=1, row=1, sticky="NE", padx=4) #Throttle Label(infoFrame, text="Throttle").grid(column=0, row=0, sticky="WE") self._throttleTexts = [StringVar(),StringVar(),StringVar(),StringVar()] Entry(infoFrame, textvariable=self._throttleTexts[3], state=DISABLED, width=5).grid(column=0, row=1) Entry(infoFrame, textvariable=self._throttleTexts[0], state=DISABLED, width=5).grid(column=1, row=1) Entry(infoFrame, textvariable=self._throttleTexts[2], state=DISABLED, width=5).grid(column=0, row=2) Entry(infoFrame, textvariable=self._throttleTexts[1], state=DISABLED, width=5).grid(column=1, row=2) #Angles Label(infoFrame, text="Angles").grid(column=0, row=3, sticky="WE") self._angleTexts = [StringVar(),StringVar(),StringVar()] for index in range(3): Entry(infoFrame, textvariable=self._angleTexts[index], state=DISABLED, width=5).grid(column=index, row=4) #Accels Label(infoFrame, text="Accels").grid(column=0, row=5, sticky="WE") self._accelTexts = [StringVar(),StringVar(),StringVar()] for index in range(3): Entry(infoFrame, textvariable=self._accelTexts[index], state=DISABLED, width=5).grid(column=index, row=6) #Speeds Label(infoFrame, text="Speeds").grid(column=0, row=7, sticky="WE") self._speedTexts = [StringVar(),StringVar(),StringVar()] for index in range(3): Entry(infoFrame, textvariable=self._speedTexts[index], state=DISABLED, width=5).grid(column=index, row=8) #Height Label(infoFrame, text="Height").grid(column=0, row=9, sticky="E") self._heightText = StringVar() Entry(infoFrame, textvariable=self._heightText, state=DISABLED, width=5).grid(column=1, row=9) #Loop rate Label(infoFrame, text="Loop @").grid(column=0, row=10, sticky="E") self._loopRateText = StringVar() Entry(infoFrame, textvariable=self._loopRateText, state=DISABLED, width=5).grid(column=1, row=10) Label(infoFrame, text="Hz").grid(column=2, row=10, sticky="W") #control controlFrame = tkFrame(self) controlFrame.grid(column=0, row=1, sticky="W") self._throttle = DoubleVar() if Cockpit.THROTTLE_BY_USER: self._thrustScale = Scale(controlFrame, orient=VERTICAL, from_=100.0, to=0.0, \ tickinterval=0, variable=self._throttle, resolution=Cockpit.THROTTLE_RESOLUTION, \ length=200, showvalue=1, \ state=DISABLED, command=self._onThrustScaleChanged) else: self._thrustScale = Scale(controlFrame, orient=VERTICAL, from_=100.0, to=-100.0, \ tickinterval=0, variable=self._throttle, \ length=200, showvalue=1, \ state=DISABLED, command=self._onThrustScaleChanged) self._thrustScale.bind("<Double-Button-1>", self._onThrustScaleDoubleButton1, "+") self._thrustScale.grid(column=0) self._shiftCanvas = Canvas(controlFrame, bg="white", height=400, width=400, \ relief=SUNKEN) self._shiftCanvas.bind("<Button-1>", self._onMouseButton1) #self._shiftCanvas.bind("<ButtonRelease-1>", self._onMouseButtonRelease1) self._shiftCanvas.bind("<B1-Motion>", self._onMouseButton1Motion) self._shiftCanvas.bind("<Double-Button-1>", self._onMouseDoubleButton1) self._shiftCanvas.bind("<Button-3>", self._onMouseButton3) #self._shiftCanvas.bind("<ButtonRelease-3>", self._onMouseButtonRelease3) self._shiftCanvas.bind("<B3-Motion>", self._onMouseButton3Motion) self._shiftCanvas.grid(row=0,column=1, padx=2, pady=2) self._shiftCanvas.create_oval(1, 1, 400, 400, outline="#ff0000") self._shiftCanvas.create_line(200, 2, 200, 400, fill="#ff0000") self._shiftCanvas.create_line(2, 200, 400, 200, fill="#ff0000") self._shiftMarker = self._shiftCanvas.create_oval(196, 196, 204, 204, outline="#0000ff", fill="#0000ff") self._yaw = DoubleVar() self._yawScale = Scale(controlFrame, orient=HORIZONTAL, from_=-100.0, to=100.0, \ tickinterval=0, variable=self._yaw, \ length=200, showvalue=1, \ command=self._onYawScaleChanged) self._yawScale.bind("<Double-Button-1>", self._onYawScaleDoubleButton1, "+") self._yawScale.grid(row=1, column=1) self._controlKeyActive = False #PID calibration pidCalibrationFrame = tkFrame(self) pidCalibrationFrame.grid(column=0, row=2, sticky="WE"); self._pidSelected = StringVar() self._pidSelected.set("--") self._pidListBox = OptionMenu(pidCalibrationFrame, self._pidSelected, "--", \ Cockpit.KEY_ANG_SPEED, Cockpit.KEY_ANGLES, Cockpit.KEY_ACCEL, \ command=self._onPidListBoxChanged) self._pidListBox.pack(side=LEFT, padx=2) self._pidListBox.config(width=10) self._axisSelected = StringVar() self._axisSelected.set("--") self._axisListBox = OptionMenu(pidCalibrationFrame, self._axisSelected, "--", "X", "Y", "Z", \ command=self._onAxisListBoxChanged) self._axisListBox.pack(side=LEFT, padx=2) self._axisListBox.config(state=DISABLED) Label(pidCalibrationFrame, text="P").pack(side=LEFT, padx=(14, 2)) self._pidPString = StringVar() self._pidPString.set("0.00") self._pidPSpinbox = Spinbox(pidCalibrationFrame, width=5, from_=0.0, to=10000.0, increment=0.01, state=DISABLED, \ textvariable=self._pidPString, command=self._onPidSpinboxChanged) self._pidPSpinbox.pack(side=LEFT, padx=2) Label(pidCalibrationFrame, text="I").pack(side=LEFT, padx=(14, 2)) self._pidIString = StringVar() self._pidIString.set("0.00") self._pidISpinbox = Spinbox(pidCalibrationFrame, width=5, from_=0.0, to=10000.0, increment=0.01, state=DISABLED, \ textvariable=self._pidIString, command=self._onPidSpinboxChanged) self._pidISpinbox.pack(side=LEFT, padx=2) Label(pidCalibrationFrame, text="D").pack(side=LEFT, padx=(14, 2)) self._pidDString = StringVar() self._pidDString.set("0.00") self._pidDSpinbox = Spinbox(pidCalibrationFrame, width=5, from_=0.0, to=10000.0, increment=0.01, state=DISABLED, \ textvariable=self._pidDString, command=self._onPidSpinboxChanged) self._pidDSpinbox.pack(side=LEFT, padx=2) #debug debugFrame = tkFrame(self) debugFrame.grid(column=0, row=3, sticky="WE") self._debugMsg = Message(debugFrame, anchor="nw", justify=LEFT, relief=SUNKEN, width=300) self._debugMsg.pack(fill=BOTH, expand=1) def _start(self): self._readDroneConfig() if Cockpit.JOYSTICK_ENABLED: self._joystickManager = JoystickManager.getInstance() self._joystickManager.start() joysticks = self._joystickManager.getJoysticks() if len(joysticks) != 0: self._joystick = joysticks[0] self._joystick.onAxisChanged += self._onJoystickAxisChanged self._joystick.onButtonPressed += self._onJoystickButtonPressed else: self._joystick = None def _onJoystickAxisChanged(self, sender, index): if self._started.get() and sender == self._joystick: axisValue = self._joystick.getAxisValue(index) if index == 0: self._yaw.set(axisValue) self._updateTarget() elif index == 1 and not Cockpit.THROTTLE_BY_USER: thrust = -axisValue self._throttle.set(thrust) self._updateTarget() elif index == 2 and Cockpit.THROTTLE_BY_USER: rowThrottle = (axisValue + 100.0)/2.0 if rowThrottle < 10.0: throttle = rowThrottle * 6.0 elif rowThrottle < 90.0: throttle = 60.0 + ((rowThrottle - 10.0) / 8.0) else: throttle = 70.0 + (rowThrottle - 90.0) * 3.0 self._throttle.set(throttle) self._sendThrottle() elif index == 3: x = 196 + axisValue * 2 lastCoords = self._shiftCanvas.coords(self._shiftMarker) coords = (x, lastCoords[1]) self._plotShiftCanvasMarker(coords) elif index == 4: y = 196 + axisValue * 2 lastCoords = self._shiftCanvas.coords(self._shiftMarker) coords = (lastCoords[0], y) self._plotShiftCanvasMarker(coords) def _onJoystickButtonPressed(self, sender, index): if sender == self._joystick and index == 7: if self._started.get() == 0: self._startedCB.select() else: self._startedCB.deselect() # Tkinter's widgets seem not to be calling the event-handler # when they are changed programmatically. Therefore, the # even-handler is called explicitly here. self._startedCBChanged() def exit(self): self._link.send({"key": "close", "data": None}) self._stopUpdateInfoThread() self._link.close() if Cockpit.JOYSTICK_ENABLED: self._joystickManager.stop() self.quit() def _updateTarget(self): markerCoords = self._shiftCanvas.coords(self._shiftMarker) coords = ((markerCoords[0] + markerCoords[2]) / 2, (markerCoords[1] + markerCoords[3]) / 2) self._target[0] = float(coords[1] - 200) / 2.0 # X-axis angle / X-axis acceleration self._target[1] = float(coords[0] - 200) / 2.0 # Y-axis angle / Y-axis acceleration #Remote control uses clockwise angle, but the drone's referece system uses counter-clockwise angle self._target[2] = -self._yaw.get() # Z-axis angular speed # Z-axis acceleration (thrust). Only when the motor throttle is not controlled by user directly if Cockpit.THROTTLE_BY_USER: self._target[3] = 0.0 else: self._target[3] = self._throttle.get() self._sendTarget() def _keyDown(self, event): if event.keysym == "Escape": self._throttle.set(0) self._started.set(0) self._thrustScale.config(state=DISABLED) self._stopUpdateInfoThread() self._sendIsStarted() elif event.keysym.startswith("Control"): self._controlKeyActive = True elif not self._controlKeysLocked and self._controlKeyActive: if event.keysym == "Up": self._thrustScaleUp() elif event.keysym == "Down": self._thrustScaleDown() elif event.keysym == "Left": self._yawLeft() elif event.keysym == "Right": self._yawRight() elif event.keysym == "space": self._yawReset() if not Cockpit.THROTTLE_BY_USER: self._thrustReset() elif not self._controlKeysLocked and not self._controlKeyActive: if event.keysym == "Up": self._moveShiftCanvasMarker((0,-5)) elif event.keysym == "Down": self._moveShiftCanvasMarker((0,5)) elif event.keysym == "Left": self._moveShiftCanvasMarker((-5,0)) elif event.keysym == "Right": self._moveShiftCanvasMarker((5,0)) elif event.keysym == "space": self._resetShiftCanvasMarker() def _keyUp(self, eventArgs): if eventArgs.keysym.startswith("Control"): self._controlKeyActive = False def _onMouseButton1(self, eventArgs): self._lastMouseCoords = (eventArgs.x, eventArgs.y) def _onMouseButtonRelease1(self, eventArgs): self._shiftCanvas.coords(self._shiftMarker, 196, 196, 204, 204) def _limitCoordsToSize(self, coords, size, width): maxSize = size-(width/2.0) minSize = -(width/2.0) if coords[0] > maxSize: x = maxSize elif coords[0] < minSize: x = minSize else: x = coords[0] if coords[1] > maxSize: y = maxSize elif coords[1] < minSize: y = minSize else: y = coords[1] return (x,y) def _plotShiftCanvasMarker(self, coords): coords = self._limitCoordsToSize(coords, 400, 8) self._shiftCanvas.coords(self._shiftMarker, coords[0], coords[1], coords[0] + 8, coords[1] + 8) self._updateTarget() def _moveShiftCanvasMarker(self, shift): lastCoords = self._shiftCanvas.coords(self._shiftMarker) newCoords = (lastCoords[0] + shift[0], lastCoords[1] + shift[1]) self._plotShiftCanvasMarker(newCoords) def _resetShiftCanvasMarker(self): self._shiftCanvas.coords(self._shiftMarker, 196, 196, 204, 204) self._updateTarget() def _onMouseButton1Motion(self, eventArgs): deltaCoords = (eventArgs.x - self._lastMouseCoords[0], eventArgs.y - self._lastMouseCoords[1]) self._moveShiftCanvasMarker(deltaCoords) self._lastMouseCoords = (eventArgs.x, eventArgs.y) def _onMouseDoubleButton1(self, eventArgs): self._resetShiftCanvasMarker() def _onMouseButton3(self, eventArgs): self._lastMouseCoords = (eventArgs.x, eventArgs.y) self._mouseDirection = Cockpit.DIR_NONE def _onMouseButtonRelease3(self, eventArgs): self._shiftCanvas.coords(self._shiftMarker, 196, 196, 204, 204) def _onMouseButton3Motion(self, eventArgs): deltaCoords = (eventArgs.x - self._lastMouseCoords[0], eventArgs.y - self._lastMouseCoords[1]) if self._mouseDirection == Cockpit.DIR_NONE: if abs(deltaCoords[0]) > abs(deltaCoords[1]): self._mouseDirection = Cockpit.DIR_HORIZONTAL else: self._mouseDirection = Cockpit.DIR_VERTICAL if self._mouseDirection == Cockpit.DIR_HORIZONTAL: deltaCoords = (deltaCoords[0], 0) else: deltaCoords = (0, deltaCoords[1]) self._moveShiftCanvasMarker(deltaCoords) self._lastMouseCoords = (eventArgs.x, eventArgs.y) def _thrustScaleUp(self): #TODO: 20160526 DPM: El valor de incremento de aceleración (1.0) puede ser muy alto if self._started.get(): newValue = self._thrustScale.get() \ + (Cockpit.THROTTLE_RESOLUTION if Cockpit.THROTTLE_BY_USER else 1.0) self._thrustScale.set(newValue) self._updateTarget() def _thrustScaleDown(self): #TODO: 20160526 DPM: El valor de decremento de aceleración (1.0) puede ser muy alto if self._started.get(): newValue = self._thrustScale.get() \ - (Cockpit.THROTTLE_RESOLUTION if Cockpit.THROTTLE_BY_USER else 1.0) self._thrustScale.set(newValue) self._updateTarget() def _thrustReset(self): if self._started.get(): self._thrustScale.set(0.0) self._updateTarget() def _onThrustScaleDoubleButton1(self, eventArgs): self._thrustReset() return "break" def _yawRight(self): newValue = self._yaw.get() + 1 self._yaw.set(newValue) self._updateTarget() def _yawLeft(self): newValue = self._yaw.get() - 1 self._yaw.set(newValue) self._updateTarget() def _yawReset(self): self._yaw.set(0) self._updateTarget() def _onMouseWheelUp(self, eventArgs): if not self._controlKeyActive: self._thrustScaleUp() else: self._yawRight() def _onMouseWheelDown(self, eventArgs): if not self._controlKeyActive: self._thrustScaleDown() else: self._yawLeft() def _onMouseWheel(self, eventArgs): factor = eventArgs.delta/(1200.0 if Cockpit.THROTTLE_BY_USER and not self._controlKeyActive else 120.0) if not self._controlKeyActive: if self._started.get(): newValue = self._thrustScale.get() + factor self._thrustScale.set(newValue) self._updateTarget() else: newValue = self._yaw.get() + factor self._yaw.set(newValue) self._updateTarget() def _onYawScaleChanged(self, eventArgs): self._updateTarget() def _onYawScaleDoubleButton1(self, eventArgs): self._yawReset() return "break" def _startedCBChanged(self): if not self._started.get(): self._throttle.set(0) self._thrustScale.config(state=DISABLED) #self._integralsCB.config(state=DISABLED) self._stopUpdateInfoThread() else: self._thrustScale.config(state="normal") #self._integralsCB.config(state="normal") self._startUpdateInfoThread() self._sendIsStarted() # def _integralsCBChanged(self): # # self._link.send({"key": "integrals", "data":self._integralsEnabled.get() != 0}) # def _onThrustScaleChanged(self, eventArgs): if Cockpit.THROTTLE_BY_USER: self._sendThrottle() else: self._updateTarget() def _sendThrottle(self): self._link.send({"key": "throttle", "data": self._throttle.get()}) def _sendTarget(self): self._link.send({"key": "target", "data": self._target}) def _sendIsStarted(self): isStarted = self._started.get() != 0 self._link.send({"key": "is-started", "data": isStarted}) def _sendPidCalibrationData(self): if self._pidSelected.get() != "--" and self._axisSelected.get() != "--": pidData = { "pid": self._pidSelected.get(), "axis": self._axisSelected.get(), "p": float(self._pidPSpinbox.get()), "i": float(self._pidISpinbox.get()), "d": float(self._pidDSpinbox.get())} self._link.send({"key": "pid-calibration", "data": pidData}) def _updatePidCalibrationData(self): pid = self._pidSelected.get() axis = self._axisSelected.get() if pid != "--" and axis != "--": self._pidConstants[pid][axis]["P"] = float(self._pidPSpinbox.get()) self._pidConstants[pid][axis]["I"] = float(self._pidISpinbox.get()) self._pidConstants[pid][axis]["D"] = float(self._pidDSpinbox.get()) def _readDroneConfig(self): self._link.send({"key": "read-drone-config", "data": None}, self._onDroneConfigRead) def _readDroneState(self): if not self._readingState: self._readingState = True self._link.send({"key": "read-drone-state", "data": None}, self._onDroneStateRead) def _readPidConfigItem(self, message, cockpitKey, axises, configKeys): for i in range(len(axises)): for j in range(len(Cockpit.PID_KEYS)): self._pidConstants[cockpitKey][axises[i]][Cockpit.PID_KEYS[j]] = message[configKeys[j]][i] def _onDroneConfigRead(self, message): #TODO Show current configuration within the GUI (at least relevant settings) if message: #Angle-speeds self._readPidConfigItem(message, Cockpit.KEY_ANG_SPEED, ["X", "Y", "Z"], \ [Configuration.PID_ANGLES_SPEED_KP, \ Configuration.PID_ANGLES_SPEED_KI, \ Configuration.PID_ANGLES_SPEED_KD]) #Angles self._readPidConfigItem(message, Cockpit.KEY_ANGLES, ["X", "Y"], \ [Configuration.PID_ANGLES_KP, \ Configuration.PID_ANGLES_KI, \ Configuration.PID_ANGLES_KD]) #Accels self._readPidConfigItem(message, Cockpit.KEY_ACCEL, ["X", "Y", "Z"], \ [Configuration.PID_ACCEL_KP, \ Configuration.PID_ACCEL_KI, \ Configuration.PID_ACCEL_KD]) def _onDroneStateRead(self, state): if state: for index in range(4): self._throttleTexts[index].set("{0:.3f}".format(state["_throttles"][index])) for index in range(3): self._accelTexts[index].set("{0:.3f}".format(state["_accels"][index])) self._angleTexts[index].set("{0:.3f}".format(state["_angles"][index])) currentPeriod = state["_currentPeriod"] if currentPeriod > 0.0: freq = 1.0/currentPeriod self._loopRateText.set("{0:.3f}".format(freq)) else: self._loopRateText.set("--") else: self._stopUpdateInfoThread() self._readingState = False def _onPidSpinboxChanged(self): self._updatePidCalibrationData() self._sendPidCalibrationData() def _onPidListBoxChanged(self, pid): self._axisSelected.set("--") self._pidPString.set("--") self._pidIString.set("--") self._pidDString.set("--") self._pidPSpinbox.config(state=DISABLED) self._pidISpinbox.config(state=DISABLED) self._pidDSpinbox.config(state=DISABLED) self._selectedPidConstats = pid if pid == "--": self._axisListBox.config(state=DISABLED) self._controlKeysLocked = False else: self._axisListBox.config(state="normal") self._controlKeysLocked = True def _onAxisListBoxChanged(self, axis): if axis == "--" or (self._selectedPidConstats == Cockpit.KEY_ANGLES and axis == "Z"): self._pidPString.set("--") self._pidIString.set("--") self._pidDString.set("--") self._pidPSpinbox.config(state=DISABLED) self._pidISpinbox.config(state=DISABLED) self._pidDSpinbox.config(state=DISABLED) self._controlKeysLocked = axis != "--" else: self._pidPString.set("{:.2f}".format(self._pidConstants[self._selectedPidConstats][axis]["P"])) self._pidIString.set("{:.2f}".format(self._pidConstants[self._selectedPidConstats][axis]["I"])) self._pidDString.set("{:.2f}".format(self._pidConstants[self._selectedPidConstats][axis]["D"])) self._pidPSpinbox.config(state="normal") self._pidISpinbox.config(state="normal") self._pidDSpinbox.config(state="normal") self._controlKeysLocked = True def _updateInfo(self): while self._updateInfoThreadRunning: self._readDroneState() time.sleep(1.0) def _startUpdateInfoThread(self): self._updateInfoThreadRunning = True if not self._updateInfoThread.isAlive(): self._updateInfoThread.start() def _stopUpdateInfoThread(self): self._updateInfoThreadRunning = False if self._updateInfoThread.isAlive(): self._updateInfoThread.join()
class Game: def __init__(self): self.root = Tk() self.frame1 = None self.frame2 = None self.w = None self.scoreC = None self.score = 0 self.hor = True self.upid = self.downid = self.rightid = self.leftid = 0 self.head = -1 self.time = 700 def home(self): self.frame1 = Frame(self.root, width=750, height=350, padx=250, bg="black") self.frame2 = Frame(self.root, height=250, width=750, bg="black", padx=25) self.root.wm_minsize(width=750, height=666) self.root.configure(bg="black") self.frame1.pack_propagate(0) self.frame1.update() self.frame1.configure(pady=self.frame1.cget("height") / 2.5) logo = PhotoImage(file="Game_Logo.gif") starth = Button(self.frame1, text="Hard", bg="orange", padx=25, pady=5, font=Font(family="comic sans MS", size=10), command=lambda: self.callgame(40)) startm = Button(self.frame1, text="Medium", bg="teal", padx=25, pady=5, font=Font(family="comic sans MS", size=10), command=lambda: self.callgame(60)) starte = Button(self.frame1, text="Easy", bg="orange", padx=25, pady=5, font=Font(family="comic sans MS", size=10), command=lambda: self.callgame(75)) self.frame2.pack_propagate(0) exp = """ This is a game in which the arrow keys are used to move the snake around and to get points""" exf = Font(family="comic sans MS", size=20) Label(self.frame2, image=logo, bg="black", text=exp, padx=10).pack(side="right") Label(self.frame2, fg="white", bg="black", text=exp, justify="left", font=exf).pack(side="left") starte.grid(row=0, columnspan=2) startm.grid(row=0, columnspan=2, column=4, padx=18) starth.grid(row=0, columnspan=2, column=8) head = Font(family="comic sans MS", size=30) self.H=Label(self.root, text="SNAKES", font=head, fg="orange", bg="black", pady=10) self.H.pack() self.frame2.pack(expand=True) self.frame1.pack(expand=True) self.root.mainloop() def callgame(self, time): self.time = time self.game() def calldown(self, key): if self.hor: self.w.after_cancel(self.leftid) self.w.after_cancel(self.rightid) self.down(0) def callup(self, key): if self.hor: self.w.after_cancel(self.leftid) self.w.after_cancel(self.rightid) self.up(0) def callright(self, key): if not self.hor: self.w.after_cancel(self.upid) self.w.after_cancel(self.downid) self.right(0) def callleft(self, key): if not self.hor: self.w.after_cancel(self.upid) self.w.after_cancel(self.downid) self.left(0) def game(self): self.score = 0 self.w = Canvas(self.root, width=750, height=500, relief="flat", highlightbackground="grey", highlightthickness=10) self.frame1.destroy() self.frame2.destroy() self.root.configure(width=1000, padx=10) self.root.pack_propagate(0) self.w.configure(background="black") self.w.pack(side="left") self.w.create_line(300, 250, 450, 250, width=10, fill="teal") self.scoreC = Label(self.root, text="Score\n" + str(self.score), bg="black", fg="teal", padx=25, pady=35, font=Font(family="comic sans MS", size=25)) self.head = self.w.create_line(450, 250, 455, 250, width=10, fill="white") self.scoreC.pack(side="top") self.root.bind("<Up>", self.callup) self.root.bind("<Down>", self.calldown) self.root.bind("<Right>", self.callright) self.root.bind("<Left>", self.callleft) self.createFood() self.right(0) def down(self, i): crd = self.w.coords(1) if len(crd) > 0: if crd[0] == crd[2]: if crd[1] > crd[3]: # print("inside if1") crd[1] -= 10 if crd[1] < crd[3]: # print("inside if2") crd[1] += 10 else: if crd[0] > crd[2]: crd[0] -= 10 if crd[0] < crd[2]: crd[0] += 10 crd[-1] += 10 if i == 0: crd.append(crd[-2]) crd.append(crd[-2]) crd[-3] -= 10 if crd[0] == crd[2] and crd[1] == crd[3]: crd = crd[2:] self.w.coords(1, *crd) self.w.delete(self.head) self.head = self.w.create_line(crd[-2], crd[-1], crd[-2], crd[-1] + 5, width=10, fill="orange") end = self.end() self.checkEaten() i += 1 self.hor = False if not end: self.downid = self.w.after(self.time, self.down, i) else: self.w.delete(1) self.w.delete(self.head) self.w.delete(self.food) self.start = Button(self.root, text="Start", bg="orange", padx=25, pady=25, font=Font(family="comic sans MS", size=15), command=lambda: self.callhome()) self.start.pack(side="bottom") def up(self, i): crd = self.w.coords(1) if len(crd)>0: if crd[0] == crd[2]: if crd[1] > crd[3]: # print("inside if1") crd[1] -= 10 if crd[1] < crd[3]: # print("inside if2") crd[1] += 10 else: if crd[0] > crd[2]: crd[0] -= 10 if crd[0] < crd[2]: crd[0] += 10 crd[-1] -= 10 if i == 0: crd.append(crd[-2]) crd.append(crd[-2]) crd[-3] += 10 if crd[0] == crd[2] and crd[1] == crd[3]: crd = crd[2:] self.w.coords(1, *crd) self.w.delete(self.head) self.head = self.w.create_line(crd[-2], crd[-1], crd[-2], crd[-1] - 5, width=10, fill="orange") end = self.end() self.checkEaten() i += 1 self.hor = False if not end: self.upid = self.w.after(self.time, self.up, i) else: self.w.delete(1) self.w.delete(self.head) self.w.delete(self.food) self.start = Button(self.root, text="Start", bg="orange", padx=25, pady=25, font=Font(family="comic sans MS", size=15), command=lambda: self.callhome()) self.start.pack(side="bottom") def right(self, i): crd = self.w.coords(1) if len(crd) > 0: if crd[0] == crd[2]: if crd[1] > crd[3]: # print("inside if1") crd[1] -= 10 if crd[1] < crd[3]: # print("inside if2") crd[1] += 10 else: if crd[0] > crd[2]: crd[0] -= 10 if crd[0] < crd[2]: crd[0] += 10 crd[-2] += 10 if i == 0: crd.append(crd[-2]) crd.append(crd[-2]) crd[-4] -= 10 if crd[0] == crd[2] and crd[1] == crd[3]: crd = crd[2:] self.w.coords(1, *crd) self.w.delete(self.head) self.head = self.w.create_line(crd[-2], crd[-1], crd[-2] + 5, crd[-1], width=10, fill="orange") end = self.end() self.checkEaten() i += 1 self.hor = True if not end: self.rightid = self.w.after(self.time, self.right, i) else: self.w.delete(1) self.w.delete(self.head) self.w.delete(self.food) self.start = Button(self.root, text="Start", bg="orange", padx=25, pady=25, font=Font(family="comic sans MS", size=15), command=lambda: self.callhome()) self.start.pack(side="bottom") def left(self, i): crd = self.w.coords(1) if len(crd) > 0: if crd[0] == crd[2]: if crd[1] > crd[3]: # print("inside if1") crd[1] -= 10 if crd[1] < crd[3]: # print("inside if2") crd[1] += 10 else: if crd[0] > crd[2]: crd[0] -= 10 if crd[0] < crd[2]: crd[0] += 10 crd[-2] -= 10 if i == 0: crd.append(crd[-2]) crd.append(crd[-2]) crd[-4] += 10 if crd[0] == crd[2] and crd[1] == crd[3]: crd = crd[2:] self.w.coords(1, *crd) self.w.delete(self.head) self.head = self.w.create_line(crd[-2], crd[-1], crd[-2] - 5, crd[-1], width=10, fill="orange") end = self.end() self.checkEaten() i += 1 self.hor = True if not end: self.leftid = self.w.after(self.time, self.left, i) else: self.w.delete(1) self.w.delete(self.head) self.w.delete(self.food) self.start = Button(self.root, text="Start", bg="orange", padx=25, pady=25, font=Font(family="comic sans MS", size=15), command=lambda: self.callhome()) self.start.pack(side="bottom") def createFood(self): # self.w.delete(self.food) #deleting old food. crd = self.w.coords(1) ext = [] for i in crd: ext.append(i) for j in range(-50, 50): ext.append(i + j) randx = random.randrange(20, 730) randy = random.randrange(20, 480) while randx not in ext and randy not in ext: randx = random.randrange(20, 730) randy = random.randrange(20, 480) self.food = self.w.create_line(randx, randy, randx + 12, randy, width=10, fill="yellow") def checkEaten(self): headcoords = self.w.coords(self.head) foodcoords = self.w.coords(self.food) # self.w.delete(self.food) flag = False # print(headcoords[-4]) # print(foodcoords[-4]) # print(foodcoords[-2]) if int(headcoords[-4]) in range(int(foodcoords[-4]) - 7, int(foodcoords[-2]) + 7) and int( headcoords[-3]) in range(int(foodcoords[-1]) - 10, int(foodcoords[-1] + 10)): flag = True if flag: self.grow() self.score += 10 self.scoreC.configure(text="Score\n" + str(self.score), bg="black", fg="teal", padx=25, pady=35, font=Font(family="comic sans MS", size=25)) self.w.delete(self.food) self.createFood() def grow(self): crd = self.w.coords(1) if crd[0] != crd[2]: # horizontal condition if crd[0] < crd[2]: crd[0] -= 20 else: crd[0] += 20 self.w.coords(1, *crd) else: if crd[3] < crd[1]: crd[1] += 20 else: crd[1] -= 20 self.w.coords(1, *crd) def end(self): crd = self.w.coords(1) h = self.w.coords(self.head) a = 0 while a < len(crd) - 2: if crd[a] == crd[a + 2]: if (h[0] == crd[a] and crd[a + 1] < h[1] < crd[a + 3]) or ( h[0] == crd[a] and crd[a + 1] > h[1] > crd[a + 3]): return True else: if (h[1] == crd[a + 1] and crd[a] < h[0] < crd[a + 2]) or (h[1] == crd[a + 1] and crd[a] > h[0] > crd[a + 2]): return True a += 2 if (h[0] == 0 and 0 < h[1] < 500) or (h[1] == 0 and 0 < h[0] < 750) or (h[1] == 510 and 0 < h[0] < 750) or (h[0] == 760 and 0<h[1]<500): return True return False def callhome(self): self.w.destroy() self.start.destroy() self.H.destroy() self.scoreC.destroy() self.home()
class Env(): def __init__(self, master, random_start_pos=False, nr_cols=5, nr_rows=5, walls=[(1, 1), (1, 2), (2, 1), (2, 2)], red_block_pos_l=[(4, 1)], green_block_pos_l=[(4, 0)], cell_width=100): self.master = master ############################ # Game setting self.nr_cols, self.nr_rows = (nr_cols, nr_rows) self.actions = ["up", "down", "left", "right"] self.walk_reward = -0.04 # Walls self.walls = walls # Red Grid self.red_block_pos_l = red_block_pos_l # Green Grid self.green_block_pos_l = green_block_pos_l self.special_grids = [(red[0], red[1], "red", -1) for red in self.red_block_pos_l] + \ [(green[0], green[1], "green", 1) for green in self.green_block_pos_l] ######################## # player setting self.player_pos = (0, self.nr_rows - 1) # random start position or not self.random_start_pos = random_start_pos # Score self.score = 1 # Terminal flag self.terminal = False ############################################# # Game UI configuration self.triangle_size = 0.1 self.cell_width = cell_width self.board = Canvas(self.master, width=self.nr_cols * self.cell_width, height=self.nr_rows * self.cell_width) self.board.grid(row=0, column=0) # cell_score_min = -0.2 # cell_score_max = 0.2 # Special grid setting self.cell_scores = {} # key bind setting self.master.bind("<Up>", self.call_up) self.master.bind("<Down>", self.call_down) self.master.bind("<Right>", self.call_right) self.master.bind("<Left>", self.call_left) self.master.bind('<Escape>', lambda e: self.master.destroy()) self.master.bind('<space>', self.restart_game) return def call_up(self, event): return self.try_move(0, -1) def call_down(self, event): return self.try_move(0, 1) def call_left(self, event): return self.try_move(-1, 0) def call_right(self, event): return self.try_move(1, 0) def response_action(self, action): # self.actions = ["up", "down", "left", "right"] # print "Action: {}".format(self.actions[action]) if action == 0: return self.call_up(None) if action == 1: return self.call_down(None) if action == 2: return self.call_left(None) if action == 3: return self.call_right(None) def restart_game(self, _): self.init_player_pos() self.score = 1 self.terminal = False self.board.coords( self.me, self.player_pos[0] * self.cell_width + self.cell_width * 2 / 10, self.player_pos[1] * self.cell_width + self.cell_width * 2 / 10, self.player_pos[0] * self.cell_width + self.cell_width * 8 / 10, self.player_pos[1] * self.cell_width + self.cell_width * 8 / 10) def init_player_pos(self): if self.random_start_pos: while True: new_x = random.randint(0, self.nr_cols - 1) new_y = random.randint(0, self.nr_rows - 1) if not ((new_x, new_y) in self.walls or (new_x, new_y) == self.red_block_pos_l or (new_x, new_y) == self.green_block_pos_l): self.player_pos = (new_x, new_y) break print self.player_pos else: self.player_pos = (0, self.nr_rows - 1) def get_player_position(self): return self.player_pos def render_grid(self): for i in range(self.nr_cols): for j in range(self.nr_rows): self.board.create_rectangle(i * self.cell_width, j * self.cell_width, (i + 1) * self.cell_width, (j + 1) * self.cell_width, fill="white", width=1) # temp = {} # for action in self.actions: # temp[action] = create_triangle(i, j, action) # self.cell_scores[(i,j)] = temp for (i, j, c, w) in self.special_grids: self.board.create_rectangle(i * self.cell_width, j * self.cell_width, (i + 1) * self.cell_width, (j + 1) * self.cell_width, fill=c, width=1) for (i, j) in self.walls: self.board.create_rectangle(i * self.cell_width, j * self.cell_width, (i + 1) * self.cell_width, (j + 1) * self.cell_width, fill="black", width=1) self.me = self.board.create_rectangle( self.player_pos[0] * self.cell_width + self.cell_width * 2 / 10, self.player_pos[1] * self.cell_width + self.cell_width * 2 / 10, self.player_pos[0] * self.cell_width + self.cell_width * 8 / 10, self.player_pos[1] * self.cell_width + self.cell_width * 8 / 10, fill="orange", width=1, tag="me") def try_move(self, dx, dy): reward = self.walk_reward # always update reward self.score += self.walk_reward new_x = self.player_pos[0] + dx new_y = self.player_pos[1] + dy # see if a valid move if new_x >= 0 and new_x < self.nr_cols and \ new_y >= 0 and new_y < self.nr_rows and \ not ((new_x, new_y) in self.walls): self.board.coords( self.me, new_x * self.cell_width + self.cell_width * 2 / 10, new_y * self.cell_width + self.cell_width * 2 / 10, new_x * self.cell_width + self.cell_width * 8 / 10, new_y * self.cell_width + self.cell_width * 8 / 10) self.player_pos = (new_x, new_y) for (i, j, c, w) in self.special_grids: if self.player_pos[0] == i and self.player_pos[1] == j: self.score -= self.walk_reward self.score += w reward = w if self.score > 0: print "Success! self.score: ", self.score else: print "Fail! self.score: ", self.score self.terminal = True break print "Reward: {}\tPosition: {}\tTerminal: {}\tScore: {}".format( reward, self.player_pos, self.terminal, self.score) return reward, self.player_pos, self.terminal, self.score
class Game(): WIDTH = 300 HEIGHT = 500 def start(self): self.level = 1 self.score = 0 self.speed = 500 self.counter = 0 self.create_new_game = True self.root = Tk() self.root.title("Tetris") self.status_var = StringVar() self.status_var.set("Level: 1, Score: 0") self.status = Label(self.root, textvariable=self.status_var, font=("Helvetica", 10, "bold")) self.status.pack() self.canvas = Canvas( self.root, width=Game.WIDTH, height=Game.HEIGHT) self.canvas.pack() self.root.bind("<Key>", self.handle_events) self.timer() self.root.mainloop() def timer(self): if self.create_new_game == True: self.current_shape = Shape(self.canvas) self.create_new_game = False if not self.current_shape.fall(): lines = self.remove_complete_lines() if lines: self.score += 10 * self.level**2 * lines**2 self.status_var.set("Level: %d, Score: %d" % (self.level, self.score)) self.current_shape = Shape(self.canvas) if self.is_game_over(): self.create_new_game = True self.game_over() self.counter += 1 if self.counter == 5: self.level += 1 self.speed -= 20 self.counter = 0 self.status_var.set("Level: %d, Score: %d" % (self.level, self.score)) self.root.after(self.speed, self.timer) def handle_events(self, event): if event.keysym == "Left": self.current_shape.move(-1, 0) if event.keysym == "Right": self.current_shape.move(1, 0) if event.keysym == "Down": self.current_shape.move(0, 1) if event.keysym == "Up": self.current_shape.rotate() def is_game_over(self): for box in self.current_shape.boxes: if not self.current_shape.can_move_box(box, 0, 1): return True return False def remove_complete_lines(self): shape_boxes_coords = [self.canvas.coords(box)[3] for box in self.current_shape.boxes] all_boxes = self.canvas.find_all() all_boxes_coords = {k : v for k, v in zip(all_boxes, [self.canvas.coords(box)[3] for box in all_boxes])} lines_to_check = set(shape_boxes_coords) boxes_to_check = dict((k, v) for k, v in all_boxes_coords.iteritems() if any(v == line for line in lines_to_check)) counter = Counter() for box in boxes_to_check.values(): counter[box] += 1 complete_lines = [k for k, v in counter.iteritems() if v == (Game.WIDTH/Shape.BOX_SIZE)] if not complete_lines: return False for k, v in boxes_to_check.iteritems(): if v in complete_lines: self.canvas.delete(k) del all_boxes_coords[k] for (box, coords) in all_boxes_coords.iteritems(): for line in complete_lines: if coords < line: self.canvas.move(box, 0, Shape.BOX_SIZE) return len(complete_lines) def game_over(self): self.canvas.delete(Tkinter.ALL) tkMessageBox.showinfo( "Game Over", "You scored %d points." % self.score)
class ProgressBar: def __init__(self, master=None, orientation="horizontal", min=0, max=100, width=100, height=18, doLabel=1, appearance="sunken", fillColor="blue", background="gray", labelColor="yellow", labelFont="Verdana", labelText="", labelFormat="%d%%", value=0, bd=2): # preserve various values self.master = master self.orientation = orientation self.min = min self.max = max self.width = width self.height = height self.doLabel = doLabel self.fillColor = fillColor self.labelFont = labelFont self.labelColor = labelColor self.background = background self.labelText = labelText self.labelFormat = labelFormat self.value = value self.frame = Frame(master, relief=appearance, bd=bd) self.canvas = Canvas(self.frame, height=height, width=width, bd=0, highlightthickness=0, background=background) self.scale = self.canvas.create_rectangle(0, 0, width, height, fill=fillColor) self.label = self.canvas.create_text(self.canvas.winfo_reqwidth() / 2, height / 2, text=labelText, anchor="c", fill=labelColor, font=self.labelFont) self.update() self.canvas.pack(side='top', fill='x', expand='no') def updateProgress(self, newValue, newMax=None): if newMax: self.max = newMax self.value = newValue self.update() def update(self): # Trim the values to be between min and max value = self.value if value > self.max: value = self.max if value < self.min: value = self.min # Adjust the rectangle if self.orientation == "horizontal": self.canvas.coords(self.scale, 0, 0, float(value) / self.max * self.width, self.height) else: self.canvas.coords( self.scale, 0, self.height - (float(value) / self.max * self.height), self.width, self.height) # Now update the colors self.canvas.itemconfig(self.scale, fill=self.fillColor) self.canvas.itemconfig(self.label, fill=self.labelColor) # And update the label if self.doLabel: if value: if value >= 0: pvalue = int((float(value) / float(self.max)) * 100.0) else: pvalue = 0 self.canvas.itemconfig(self.label, text=self.labelFormat % pvalue) else: self.canvas.itemconfig(self.label, text='') else: self.canvas.itemconfig(self.label, text=self.labelFormat % self.labelText) self.canvas.update_idletasks()