| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181 | import numpy as npfrom PyQt5.QtCore import Qtfrom PyQt5.QtGui import QImage, QPixmap, QPainter, QColor, QPolygonfrom PyQt5.QtCore import QPoint, QSize, QRectfrom PyQt5.QtWidgets import QApplication, QMainWindow, QWidgetfrom PyQt5.QtWidgets import QHBoxLayout, QVBoxLayout, QLabel, QFrameclass Window(QMainWindow):    """    Simple application window to render the environment into    """    def __init__(self):        super().__init__()        self.setWindowTitle('MiniGrid Gym Environment')        self.imgLabel = QLabel()        self.imgLabel.setFrameStyle(QFrame.Panel | QFrame.Sunken)        # Arrange widgets horizontally        hbox = QHBoxLayout()        hbox.addStretch(1)        hbox.addWidget(self.imgLabel)        hbox.addStretch(1)        # Create a main widget for the window        mainWidget = QWidget(self)        self.setCentralWidget(mainWidget)        mainWidget.setLayout(hbox)        # Show the application window        self.show()        self.setFocus()        self.closed = False        # Callback for keyboard events        self.keyDownCb = None    def closeEvent(self, event):        self.closed = True    def setPixmap(self, pixmap):        self.imgLabel.setPixmap(pixmap)    def setKeyDownCb(self, callback):        self.keyDownCb = callback    def keyPressEvent(self, e):        if self.keyDownCb == None:            return        keyName = None        if e.key() == Qt.Key_Left:            keyName = 'LEFT'        elif e.key() == Qt.Key_Right:            keyName = 'RIGHT'        elif e.key() == Qt.Key_Up:            keyName = 'UP'        elif e.key() == Qt.Key_Down:            keyName = 'DOWN'        elif e.key() == Qt.Key_Space:            keyName = 'SPACE'        elif e.key() == Qt.Key_Return:            keyName = 'RETURN'        elif e.key() == Qt.Key_Alt:            keyName = 'ALT'        elif e.key() == Qt.Key_Control:            keyName = 'CTRL'        elif e.key() == Qt.Key_PageUp:            keyName = 'PAGE_UP'        elif e.key() == Qt.Key_PageDown:            keyName = 'PAGE_DOWN'        elif e.key() == Qt.Key_Backspace:            keyName = 'BACKSPACE'        elif e.key() == Qt.Key_Escape:            keyName = 'ESCAPE'        if keyName == None:            return        self.keyDownCb(keyName)class Renderer:    def __init__(self, width, height, ownWindow=False):        self.width = width        self.height = height        self.img = QImage(width, height, QImage.Format_RGB888)        self.painter = QPainter()        self.window = None        if ownWindow:            self.app = QApplication([])            self.window = Window()    def close(self):        """        Deallocate resources used        """        pass    def beginFrame(self):        self.painter.begin(self.img)        self.painter.setRenderHint(QPainter.Antialiasing, False)        # Clear the background        self.painter.setBrush(QColor(0, 0, 0))        self.painter.drawRect(0, 0, self.width - 1, self.height - 1)    def endFrame(self):        self.painter.end()        if self.window:            if self.window.closed:                self.window = None            else:                self.window.setPixmap(self.getPixmap())                self.app.processEvents()    def getPixmap(self):        return QPixmap.fromImage(self.img)    def getArray(self):        """        Get a numpy array of RGB pixel values.        The size argument should be (3,w,h)        """        width = self.width        height = self.height        shape = (width, height, 3)        numBytes = self.width * self.height * 3        buf = self.img.bits().asstring(numBytes)        output = np.frombuffer(buf, dtype='uint8')        output = output.reshape(shape)        return output    def push(self):        self.painter.save()    def pop(self):        self.painter.restore()    def rotate(self, degrees):        self.painter.rotate(degrees)    def translate(self, x, y):        self.painter.translate(x, y)    def scale(self, x, y):        self.painter.scale(x, y)    def setLineColor(self, r, g, b, a=255):        self.painter.setPen(QColor(r, g, b, a))    def setColor(self, r, g, b, a=255):        self.painter.setBrush(QColor(r, g, b, a))    def setLineWidth(self, width):        pen = self.painter.pen()        pen.setWidthF(width)        self.painter.setPen(pen)    def drawLine(self, x0, y0, x1, y1):        self.painter.drawLine(x0, y0, x1, y1)    def drawCircle(self, x, y, r):        center = QPoint(x, y)        self.painter.drawEllipse(center, r, r)    def drawPolygon(self, points):        """Takes a list of points (tuples) as input"""        points = map(lambda p: QPoint(p[0], p[1]), points)        self.painter.drawPolygon(QPolygon(points))    def fillRect(self, x, y, width, height, r, g, b, a=255):        self.painter.fillRect(QRect(x, y, width, height), QColor(r, g, b, a))
 |