class SplitScreen(State): def __init__(self) -> None: self.gameplay1 = Gameplay() self.gameplay2 = Gameplay() self.popups1: List[Popup] = [] self.popups2: List[Popup] = [] self.current_popup1: Optional[Popup] = None self.current_popup2: Optional[Popup] = None self.finished = False self.end_screen = False def is_finished(self) -> bool: return self.finished def initialize(self) -> None: self.gameplay1.set_device(ctx.device1) self.gameplay1.initialize() self.gameplay2.set_device(ctx.device2) self.gameplay2.initialize() def update(self, switch_state: Callable) -> None: if not self.end_screen: if self.gameplay1.game_over and not self.gameplay2.game_over: self.gameplay2.game_over = True self.end_screen = True self.popups1.append( Popup("You lost!", color="red", gcolor="orange")) self.popups2.append( Popup("You won!", color="green", gcolor="yellow")) elif self.gameplay2.game_over and not self.gameplay1.game_over: self.gameplay1.game_over = True self.end_screen = True self.popups1.append( Popup("You won!", color="green", gcolor="yellow")) self.popups2.append( Popup("You lost!", color="red", gcolor="orange")) elif self.gameplay1.game_over and self.gameplay2.game_over: self.end_screen = True self.popups1.append(Popup("Draw!", color="cyan")) self.popups2.append(Popup("Draw!", color="cyan")) if self.gameplay1.cancel or self.gameplay2.cancel: if self.end_screen or self.gameplay1.countdown > 0: self.finished = True return else: self.gameplay1.game_over = self.gameplay1.cancel self.gameplay2.game_over = self.gameplay2.cancel self.gameplay1.cancel = False self.gameplay2.cancel = False self.gameplay1.update() self.gameplay2.update() if self.gameplay1.score.duel_lines > 0: hole = randint(0, 9) self.gameplay2.add_garbage(hole, self.gameplay1.score.duel_lines) self.gameplay1.score.duel_lines = 0 if self.gameplay2.score.duel_lines > 0: hole = randint(0, 9) self.gameplay1.add_garbage(hole, self.gameplay2.score.duel_lines) self.gameplay2.score.duel_lines = 0 self.popups1.extend(self.gameplay1.get_popups()) self.gameplay1.clear_popups() self.popups2.extend(self.gameplay2.get_popups()) self.gameplay2.clear_popups() if not self.current_popup1 and self.popups1: self.current_popup1 = self.popups1.pop(0) elif self.current_popup1: if not self.current_popup1.update(): self.current_popup1 = None if not self.current_popup2 and self.popups2: self.current_popup2 = self.popups2.pop(0) elif self.current_popup2: if not self.current_popup2.update(): self.current_popup2 = None def draw(self) -> None: self.gameplay1.draw(130, 80) self.gameplay2.draw(880, 80) if self.current_popup1: self.current_popup1.draw(130 + 155, 80 + 220) if self.current_popup2: self.current_popup2.draw(880 + 155, 80 + 220)
class Online(State): def __init__(self) -> None: self.gameplay1 = Gameplay() self.gameplay2 = Gameplay() self.popups1: List[Popup] = [] self.popups2: List[Popup] = [] self.current_popup1: Optional[Popup] = None self.current_popup2: Optional[Popup] = None self.waiting = True self.waiting_cycle = 0 self.last_waiting_cycle = ctx.now self.buffer = b"" self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.socket.settimeout(10.0) self.finished = False self.end_screen = False def is_finished(self) -> bool: return self.finished def initialize(self) -> None: self.gameplay1.set_device(ctx.device1) self.gameplay1.initialize() self.gameplay2.set_device(Device("dummy")) self.gameplay2.initialize() try: self.socket.connect(config.server) except (ConnectionRefusedError, socket.timeout): print("unable to connect to server") self.finished = True def update(self, switch_state: Callable) -> None: read, write, error = select.select([self.socket], [self.socket], [self.socket], 0) if self.waiting: self.gameplay1.cancel_input.update() if self.socket in read: buffer = self.socket.recv(BUFFER_SIZE) if buffer == b"go": self.waiting = False self.current_popup2 = None elif buffer == b"ping": self.socket.sendall(b"pong") elif buffer == b"": print("server disconnected") self.finished = True elif self.gameplay1.cancel: self.socket.close() self.finished = True return if not self.end_screen: if self.gameplay1.game_over and not self.gameplay2.game_over: self.gameplay2.game_over = True self.end_screen = True self.popups1.append( Popup("You lost!", color="red", gcolor="orange")) self.popups2.append( Popup("You won!", color="green", gcolor="yellow")) elif self.gameplay2.game_over and not self.gameplay1.game_over: self.gameplay1.game_over = True self.end_screen = True self.popups1.append( Popup("You won!", color="green", gcolor="yellow")) self.popups2.append( Popup("You lost!", color="red", gcolor="orange")) elif self.gameplay1.game_over and self.gameplay2.game_over: self.end_screen = True self.popups1.append(Popup("Draw!", color="cyan")) self.popups2.append(Popup("Draw!", color="cyan")) if self.gameplay1.cancel: self.gameplay1.send = True self.gameplay1.cancel = False self.gameplay1.game_over = True if self.end_screen or self.gameplay1.countdown > 0: self.finished = True self.gameplay1.update() if self.socket in read: try: self.gameplay2 = jsonpickle.decode( protocol.recv(self.socket).decode()) except (RuntimeError, ConnectionResetError): error = [self.socket] if self.socket in write and self.gameplay1.send: self.gameplay1.send = False try: protocol.send(self.socket, jsonpickle.encode(self.gameplay1).encode()) except (ConnectionResetError, ConnectionAbortedError): error = [self.socket] if self.socket in error: if not self.end_screen: print("communication error") self.finished = True if self.gameplay2.score.duel_lines > 0: hole = randint(0, 9) self.gameplay1.add_garbage(hole, self.gameplay2.score.duel_lines) self.gameplay2.score.duel_lines = 0 self.gameplay1.score.duel_lines = 0 self.popups1.extend(self.gameplay1.get_popups()) self.gameplay1.clear_popups() self.popups2.extend(self.gameplay2.get_popups()) self.gameplay2.clear_popups() if not self.current_popup1 and self.popups1: self.current_popup1 = self.popups1.pop(0) elif self.current_popup1: if not self.current_popup1.update(): self.current_popup1 = None if not self.current_popup2 and self.popups2: self.current_popup2 = self.popups2.pop(0) elif self.current_popup2: if not self.current_popup2.update(): self.current_popup2 = None def draw(self) -> None: self.gameplay1.draw(130, 80) self.gameplay2.draw(880, 80, draw_piece=not self.waiting) if self.waiting: Text.draw("Awaiting", size=4, centerx=880 + 155, top=220) Text.draw("opponent", size=4, gcolor="red", centerx=880 + 155, top=280) string = "." * self.waiting_cycle Text.draw(string, size=8, gcolor="black", centerx=880 + 155, top=350) if ctx.now - self.last_waiting_cycle > 0.5: self.last_waiting_cycle = ctx.now self.waiting_cycle = (self.waiting_cycle + 1) % 4 if self.current_popup1: self.current_popup1.draw(130 + 155, 80 + 220) if self.current_popup2: self.current_popup2.draw(880 + 155, 80 + 220)
class Marathon(State): def __init__(self) -> None: self.gameplay = Gameplay() self.gravity = [ 1.00000, 0.79300, 0.61780, 0.47273, 0.35520, 0.26200, 0.18968, 0.13473, 0.09388, 0.06415, 0.04298, 0.02822, 0.01815, 0.01144, 0.00706, ] self.goal = 5 self.popups: List[Popup] = [] self.current_popup: Optional[Popup] = None self.end_screen = False self.finished = False self.pause = False def is_finished(self) -> bool: return self.finished def initialize(self) -> None: self.gameplay.set_device(ctx.device1) self.gameplay.initialize() def update(self, switch_state: Callable) -> None: if self.gameplay.game_over and not self.end_screen: self.end_screen = True self.popups.append(Popup("Game over!", color="red")) if self.gameplay.game_over and self.gameplay.cancel: self.finished = True return if self.gameplay.cancel: if self.gameplay.countdown > 0: self.finished = True return else: self.gameplay.game_over = True self.gameplay.cancel = False self.gameplay.update() if self.gameplay.score.lines > 0: self.goal -= self.gameplay.score.lines self.goal = max(0, self.goal) self.gameplay.score.lines = 0 if self.goal == 0: if self.gameplay.level == 15 and not self.end_screen: self.end_screen = True self.gameplay.game_over = True self.popups.append( Popup("You won!", color="green", gcolor="yellow") ) else: self.gameplay.level += 1 self.goal = 5 * self.gameplay.level self.gameplay.fall_interval = self.gravity[ self.gameplay.level - 1 ] self.popups.extend(self.gameplay.get_popups()) self.gameplay.clear_popups() if not self.current_popup and self.popups: self.current_popup = self.popups.pop(0) self.current_popup.duration *= 2 elif self.current_popup: if not self.current_popup.update(): self.current_popup = None def draw(self) -> None: self.gameplay.draw(200, 80) Text().draw("Level", centerx=125, top=300) Text().draw( str(self.gameplay.level), centerx=125, top=340, size=4, color="gold", ) Text().draw("Goal", centerx=125, top=450) Text().draw( str(self.goal), centerx=125, top=490, size=4, color="green" ) if self.current_popup: self.current_popup.draw(650, 250, center=False)