Ejemplo n.º 1
0
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)
Ejemplo n.º 2
0
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
Ejemplo n.º 3
0
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)
Ejemplo n.º 4
0
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)
Ejemplo n.º 5
0
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)
Ejemplo n.º 6
0
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)
Ejemplo n.º 7
0
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)
Ejemplo n.º 8
0
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)
Ejemplo n.º 9
0
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)
Ejemplo n.º 10
0
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)
Ejemplo n.º 11
0
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)
Ejemplo n.º 12
0
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()
Ejemplo n.º 13
0
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)
Ejemplo n.º 14
0
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)
Ejemplo n.º 15
0
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)
Ejemplo n.º 16
0
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()
Ejemplo n.º 17
0
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()
Ejemplo n.º 18
0
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)
Ejemplo n.º 19
0
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()
Ejemplo n.º 20
0
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()),
                )
Ejemplo n.º 22
0
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()
Ejemplo n.º 23
0
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

Ejemplo n.º 25
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)
Ejemplo n.º 26
0
    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()
Ejemplo n.º 27
0
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()
Ejemplo n.º 28
0
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()
Ejemplo n.º 29
0
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():
Ejemplo n.º 31
0
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()
Ejemplo n.º 32
0
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)
Ejemplo n.º 33
0
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)
Ejemplo n.º 34
0
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)
Ejemplo n.º 36
0
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)
Ejemplo n.º 38
0
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()
Ejemplo n.º 39
0
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()
Ejemplo n.º 40
0
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()
Ejemplo n.º 41
0
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
Ejemplo n.º 42
0
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)
Ejemplo n.º 43
0
Archivo: tkutil.py Proyecto: DT021/wau
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()