-
Notifications
You must be signed in to change notification settings - Fork 13
/
Copy pathexample.py
161 lines (134 loc) · 5.41 KB
/
example.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
"""
Example of using hexutil.
A simple roguelike kernel written in PyQt5.
"""
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
import hexutil
class Level(object):
"""Represents a level in the game.
Currently there is only one.
"""
def __init__(self, size):
"""Create level with a random walk"""
tiles = {}
for tile in hexutil.origin.random_walk(100):
tiles[tile] = '~' # add water
for tile in hexutil.origin.random_walk(size):
tiles[tile] = '.' # add floor tiles
self.tiles = tiles
self.seen_tiles = {}
def get_tile(self, hexagon):
return self.tiles.get(hexagon, '#')
def get_seen_tile(self, hexagon):
return self.seen_tiles.get(hexagon, ' ')
def is_passable(self, hexagon):
return self.get_tile(hexagon) not in '#~'
def is_transparent(self, hexagon):
return self.get_tile(hexagon) != '#'
def update_fov(self, fov):
for hexagon in fov:
self.seen_tiles[hexagon] = self.get_tile(hexagon)
class GameWidget(QtWidgets.QWidget):
"""The Qt Widget which shows the game."""
_tile_brushes = {
'.' : QtGui.QBrush(QtGui.QColor("yellow")),
'~' : QtGui.QBrush(QtGui.QColor("blue")),
'#' : QtGui.QBrush(QtGui.QColor("brown")),
}
selected_hexagon = None
selected_path = frozenset()
def __init__(self, *args, **kws):
super().__init__(*args, **kws)
self.setMouseTracking(True) # we want to receive mouseMoveEvents
self.level = Level(500)
self.player = hexutil.origin
self.hexgrid = hexutil.HexGrid(24)
# initialize GUI objects needed for painting
self.font = QtGui.QFont("Helvetica", 20)
self.font.setStyleHint(QtGui.QFont.SansSerif)
self.pen = QtGui.QPen()
self.pen.setWidth(2)
self.select_brush = QtGui.QBrush(QtGui.QColor(127, 127, 255, 127))
self.unseen_brush = QtGui.QBrush(QtGui.QColor(0, 0, 0, 127))
self.update_fov()
def update_fov(self):
self.fov = self.player.field_of_view(transparent=self.level.is_transparent, max_distance=10)
self.level.update_fov(self.fov)
def hexagon_of_pos(self, pos):
"""Compute the hexagon at the screen position."""
size = self.size()
xc = size.width()//2
yc = size.height()//2
return self.player + self.hexgrid.hex_at_coordinate(pos.x() - xc, pos.y() - yc)
def mousePressEvent(self, event):
hexagon = self.hexagon_of_pos(event.pos())
path = self.player.find_path(hexagon, self.level.is_passable)
if path and len(path) >= 2:
self.player = path[1]
self.update_fov()
self.select_hexagon(event.pos())
self.repaint()
def mouseMoveEvent(self, event):
self.select_hexagon(event.pos())
def select_hexagon(self, pos):
"""Select hexagon and path to hexagon at position."""
hexagon = self.hexagon_of_pos(pos)
if hexagon != self.selected_hexagon:
self.selected_hexagon = hexagon
path = self.player.find_path(hexagon, self.level.is_passable)
if path is None:
self.selected_path = frozenset()
else:
self.selected_path = frozenset(path[1:])
self.repaint()
def paintEvent(self, event):
# compute center of window
size = self.size()
xc = size.width()//2
yc = size.height()//2
# bounding box when we translate the origin to be at the center
bbox = hexutil.Rectangle(-xc, -yc, size.width(), size.height())
hexgrid = self.hexgrid
painter = QtGui.QPainter()
painter.begin(self)
try:
# paint background black
painter.save()
painter.setPen(QtCore.Qt.NoPen)
painter.setBrush(QtGui.QColor())
painter.drawRect(0, 0, size.width(), size.height())
painter.restore()
# set up drawing state
painter.setPen(self.pen)
painter.setRenderHint(QtGui.QPainter.Antialiasing)
painter.setRenderHint(QtGui.QPainter.TextAntialiasing)
painter.setFont(self.font)
painter.translate(xc, yc)
# draw each hexagon which is in the window
for hexagon in hexgrid.hexes_in_rectangle(bbox):
polygon = QtGui.QPolygon([QtCore.QPoint(*corner) for corner in hexgrid.corners(hexagon)])
hexagon2 = hexagon + self.player
tile = self.level.get_seen_tile(hexagon2)
if tile == ' ':
continue
painter.setBrush(self._tile_brushes[tile])
painter.drawPolygon(polygon)
if hexagon2 not in self.fov:
painter.setBrush(self.unseen_brush)
painter.drawPolygon(polygon)
if hexagon2 in self.selected_path:
painter.setBrush(self.select_brush)
painter.drawPolygon(polygon)
if hexagon2 == self.player:
rect = hexgrid.bounding_box(hexagon)
rect = QtCore.QRectF(*rect) # convert to Qt RectF
painter.drawText(rect, QtCore.Qt.AlignCenter, '@')
finally:
painter.end()
def main():
app = QtWidgets.QApplication(sys.argv)
window = GameWidget()
window.show()
app.exec_()
main()