rendering.py 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. import numpy as np
  2. from PyQt5.QtCore import Qt
  3. from PyQt5.QtGui import QImage, QPixmap, QPainter, QColor, QPolygon
  4. from PyQt5.QtCore import QPoint, QSize, QRect
  5. from PyQt5.QtWidgets import QApplication, QMainWindow, QWidget
  6. from PyQt5.QtWidgets import QHBoxLayout, QVBoxLayout, QLabel, QFrame
  7. class Window(QMainWindow):
  8. """
  9. Simple application window to render the environment into
  10. """
  11. def __init__(self):
  12. super().__init__()
  13. self.setWindowTitle('MiniGrid Gym Environment')
  14. self.imgLabel = QLabel()
  15. self.imgLabel.setFrameStyle(QFrame.Panel | QFrame.Sunken)
  16. # Arrange widgets horizontally
  17. hbox = QHBoxLayout()
  18. hbox.addStretch(1)
  19. hbox.addWidget(self.imgLabel)
  20. hbox.addStretch(1)
  21. # Create a main widget for the window
  22. mainWidget = QWidget(self)
  23. self.setCentralWidget(mainWidget)
  24. mainWidget.setLayout(hbox)
  25. # Show the application window
  26. self.show()
  27. self.setFocus()
  28. self.closed = False
  29. # Callback for keyboard events
  30. self.keyDownCb = None
  31. def closeEvent(self, event):
  32. self.closed = True
  33. def setPixmap(self, pixmap):
  34. self.imgLabel.setPixmap(pixmap)
  35. def setKeyDownCb(self, callback):
  36. self.keyDownCb = callback
  37. def keyPressEvent(self, e):
  38. if self.keyDownCb == None:
  39. return
  40. keyName = None
  41. if e.key() == Qt.Key_Left:
  42. keyName = 'LEFT'
  43. elif e.key() == Qt.Key_Right:
  44. keyName = 'RIGHT'
  45. elif e.key() == Qt.Key_Up:
  46. keyName = 'UP'
  47. elif e.key() == Qt.Key_Down:
  48. keyName = 'DOWN'
  49. elif e.key() == Qt.Key_Space:
  50. keyName = 'SPACE'
  51. elif e.key() == Qt.Key_Return:
  52. keyName = 'RETURN'
  53. elif e.key() == Qt.Key_Escape:
  54. keyName = 'ESCAPE'
  55. if keyName == None:
  56. return
  57. self.keyDownCb(keyName)
  58. class Renderer:
  59. def __init__(self, width, height, ownWindow=False):
  60. self.width = width
  61. self.height = height
  62. self.img = QImage(width, height, QImage.Format_RGB888)
  63. self.painter = QPainter()
  64. self.window = None
  65. if ownWindow:
  66. self.app = QApplication([])
  67. self.window = Window()
  68. def close(self):
  69. """
  70. Deallocate resources used
  71. """
  72. pass
  73. def beginFrame(self):
  74. self.painter.begin(self.img)
  75. self.painter.setRenderHint(QPainter.Antialiasing, False)
  76. # Clear the background
  77. self.painter.setBrush(QColor(0, 0, 0))
  78. self.painter.drawRect(0, 0, self.width - 1, self.height - 1)
  79. def endFrame(self):
  80. self.painter.end()
  81. if self.window:
  82. if self.window.closed:
  83. self.window = None
  84. else:
  85. self.window.setPixmap(self.getPixmap())
  86. self.app.processEvents()
  87. def getPixmap(self):
  88. return QPixmap.fromImage(self.img)
  89. def getArray(self):
  90. """
  91. Get a numpy array of RGB pixel values.
  92. The size argument should be (3,w,h)
  93. """
  94. width = self.width
  95. height = self.height
  96. shape = (width, height, 3)
  97. numBytes = self.width * self.height * 3
  98. buf = self.img.bits().asstring(numBytes)
  99. output = np.frombuffer(buf, dtype='uint8')
  100. output = output.reshape(shape)
  101. return output
  102. def push(self):
  103. self.painter.save()
  104. def pop(self):
  105. self.painter.restore()
  106. def rotate(self, degrees):
  107. self.painter.rotate(degrees)
  108. def translate(self, x, y):
  109. self.painter.translate(x, y)
  110. def scale(self, x, y):
  111. self.painter.scale(x, y)
  112. def setLineColor(self, r, g, b, a=255):
  113. self.painter.setPen(QColor(r, g, b, a))
  114. def setColor(self, r, g, b, a=255):
  115. self.painter.setBrush(QColor(r, g, b, a))
  116. def setLineWidth(self, width):
  117. pen = self.painter.pen()
  118. pen.setWidthF(width)
  119. self.painter.setPen(pen)
  120. def drawLine(self, x0, y0, x1, y1):
  121. self.painter.drawLine(x0, y0, x1, y1)
  122. def drawCircle(self, x, y, r):
  123. center = QPoint(x, y)
  124. self.painter.drawEllipse(center, r, r)
  125. def drawPolygon(self, points):
  126. """Takes a list of points (tuples) as input"""
  127. points = map(lambda p: QPoint(p[0], p[1]), points)
  128. self.painter.drawPolygon(QPolygon(points))
  129. def fillRect(self, x, y, width, height, r, g, b, a=255):
  130. self.painter.fillRect(QRect(x, y, width, height), QColor(r, g, b, a))