Define the Game Class
Now that we have the Pad
and Puck
classes defined, we can move on to defining the Game
class. This class will be responsible for handling the game logic and drawing the game on the screen.
class Game:
def __init__(self, ax):
## create the initial line
self.ax = ax
ax.xaxis.set_visible(False)
ax.set_xlim([0, 7])
ax.yaxis.set_visible(False)
ax.set_ylim([-1, 1])
pad_a_x = 0
pad_b_x = .50
pad_a_y = pad_b_y = .30
pad_b_x += 6.3
## pads
pA, = self.ax.barh(pad_a_y, .2,
height=.3, color='k', alpha=.5, edgecolor='b',
lw=2, label="Player B",
animated=True)
pB, = self.ax.barh(pad_b_y, .2,
height=.3, left=pad_b_x, color='k', alpha=.5,
edgecolor='r', lw=2, label="Player A",
animated=True)
## distractors
self.x = np.arange(0, 2.22*np.pi, 0.01)
self.line, = self.ax.plot(self.x, np.sin(self.x), "r",
animated=True, lw=4)
self.line2, = self.ax.plot(self.x, np.cos(self.x), "g",
animated=True, lw=4)
self.line3, = self.ax.plot(self.x, np.cos(self.x), "g",
animated=True, lw=4)
self.line4, = self.ax.plot(self.x, np.cos(self.x), "r",
animated=True, lw=4)
## center line
self.centerline, = self.ax.plot([3.5, 3.5], [1, -1], 'k',
alpha=.5, animated=True, lw=8)
## puck (s)
self.puckdisp = self.ax.scatter([1], [1], label='_nolegend_',
s=200, c='g',
alpha=.9, animated=True)
self.canvas = self.ax.figure.canvas
self.background = None
self.cnt = 0
self.distract = True
self.res = 100.0
self.on = False
self.inst = True ## show instructions from the beginning
self.pads = [Pad(pA, pad_a_x, pad_a_y),
Pad(pB, pad_b_x, pad_b_y, 'r')]
self.pucks = []
self.i = self.ax.annotate(instructions, (.5, 0.5),
name='monospace',
verticalalignment='center',
horizontalalignment='center',
multialignment='left',
xycoords='axes fraction',
animated=False)
self.canvas.mpl_connect('key_press_event', self.on_key_press)
def draw(self):
draw_artist = self.ax.draw_artist
if self.background is None:
self.background = self.canvas.copy_from_bbox(self.ax.bbox)
## restore the clean slate background
self.canvas.restore_region(self.background)
## show the distractors
if self.distract:
self.line.set_ydata(np.sin(self.x + self.cnt/self.res))
self.line2.set_ydata(np.cos(self.x - self.cnt/self.res))
self.line3.set_ydata(np.tan(self.x + self.cnt/self.res))
self.line4.set_ydata(np.tan(self.x - self.cnt/self.res))
draw_artist(self.line)
draw_artist(self.line2)
draw_artist(self.line3)
draw_artist(self.line4)
## pucks and pads
if self.on:
self.ax.draw_artist(self.centerline)
for pad in self.pads:
pad.disp.set_y(pad.y)
pad.disp.set_x(pad.x)
self.ax.draw_artist(pad.disp)
for puck in self.pucks:
if puck.update(self.pads):
## we only get here if someone scored
self.pads[0].disp.set_label(f" {self.pads[0].score}")
self.pads[1].disp.set_label(f" {self.pads[1].score}")
self.ax.legend(loc='center', framealpha=.2,
facecolor='0.5',
prop=FontProperties(size='xx-large',
weight='bold'))
self.background = None
self.ax.figure.canvas.draw_idle()
return
puck.disp.set_offsets([[puck.x, puck.y]])
self.ax.draw_artist(puck.disp)
## just redraw the axes rectangle
self.canvas.blit(self.ax.bbox)
self.canvas.flush_events()
if self.cnt == 50000:
## just so we don't get carried away
print("...and you've been playing for too long!!!")
plt.close()
self.cnt += 1
def on_key_press(self, event):
if event.key == '3':
self.res *= 5.0
if event.key == '4':
self.res /= 5.0
if event.key == 'e':
self.pads[0].y += .1
if self.pads[0].y > 1 - .3:
self.pads[0].y = 1 - .3
if event.key == 'd':
self.pads[0].y -= .1
if self.pads[0].y < -1:
self.pads[0].y = -1
if event.key == 'i':
self.pads[1].y += .1
if self.pads[1].y > 1 - .3:
self.pads[1].y = 1 - .3
if event.key == 'k':
self.pads[1].y -= .1
if self.pads[1].y < -1:
self.pads[1].y = -1
if event.key == 'a':
self.pucks.append(Puck(self.puckdisp,
self.pads[randint(2)],
self.ax.bbox))
if event.key == 'A' and len(self.pucks):
self.pucks.pop()
if event.key == ' ' and len(self.pucks):
self.pucks[0]._reset(self.pads[randint(2)])
if event.key == '1':
for p in self.pucks:
p._slower()
if event.key == '2':
for p in self.pucks:
p._faster()
if event.key == 'n':
self.distract = not self.distract
if event.key == 'g':
self.on = not self.on
if event.key == 't':
self.inst = not self.inst
self.i.set_visible(not self.i.get_visible())
self.background = None
self.canvas.draw_idle()
if event.key == 'q':
plt.close()