class Game(object): """ The main game class that holds the gameloop. """ def __init__(self, host, port, width, height): """ Create a screen and define some game specific things. """ self.host = host self.port = port self.width = width self.height = height self.players = {} pymlgame.init() self.screen = Screen(self.host, self.port, self.width, self.height) self.clock = Clock(5) self.running = True self.colors = [WHITE, BLUE, GREEN, CYAN, MAGENTA, YELLOW, RED] self.color_length = math.ceil(self.screen.height / len(self.colors)) # surfaces self.game_board = None self.init_game_board() self.dots = Surface(self.screen.width, self.screen.height) def init_game_board(self): self.game_board = [ 0 for _ in range(self.screen.height * self.screen.width) ] indices = random.sample( range(self.screen.height * self.screen.width), random.randint(self.screen.width // 2, (2 * (self.screen.height * self.screen.width) // 3))) for index in indices: self.game_board[index] = 1 def offset(self, width_idx, height_idx): return height_idx * self.screen.width + width_idx def board_value(self, width_idx, height_idx): if width_idx == -1 or height_idx == -1: return 0 return self.game_board[self.offset(width_idx, height_idx)] def update(self): """ Update the screens contents in every loop. """ # this is not really neccesary because the surface is black after initializing self.dots.fill(BLACK) intermediate_buffer = self.game_board.copy() for h_index in range(self.screen.height): for w_index in range(self.screen.width): id_above = h_index - 1 if h_index - 1 >= 0 else -1 id_left = w_index - 1 if w_index - 1 >= 0 else -1 id_right = w_index + 1 if w_index + 1 < self.screen.width else -1 id_bottom = h_index + 1 if h_index + 1 < self.screen.height else -1 cell_offset = self.offset(w_index, h_index) alive_check = [ self.board_value(id_left, id_above), self.board_value(w_index, id_above), self.board_value(id_right, id_above), self.board_value(id_left, h_index), self.board_value(w_index, h_index), self.board_value(id_right, h_index), self.board_value(id_left, id_bottom), self.board_value(w_index, id_bottom), self.board_value(id_right, id_bottom), ] # count neighbours that are alive counter = Counter(alive_check) num_alive = counter[1] if self.game_board[cell_offset] == 0: if num_alive == 3: intermediate_buffer[cell_offset] = 1 self.dots.draw_dot( (w_index, h_index), self.colors[h_index // self.color_length]) elif num_alive < 2: intermediate_buffer[cell_offset] = 0 elif 2 <= num_alive <= 3: self.dots.draw_dot( (w_index, h_index), self.colors[h_index // self.color_length]) else: intermediate_buffer[cell_offset] = 0 self.game_board = intermediate_buffer.copy() def render(self): """ Send the current screen content to Mate Light. """ self.screen.reset() self.screen.blit(self.dots) self.screen.update() self.clock.tick() def handle_events(self): """ Loop through all events. """ for event in pymlgame.get_events(): if event.type == E_NEWCTLR: #print(datetime.now(), '### new player connected with uid', event.uid) self.players[event.uid] = { 'name': 'alien_{}'.format(event.uid), 'score': 0 } elif event.type == E_DISCONNECT: #print(datetime.now(), '### player with uid {} disconnected'.format(event.uid)) self.players.pop(event.uid) elif event.type == E_KEYDOWN: #print(datetime.now(), '###', self.players[event.uid]['name'], 'pressed', event.button) if event.button == 9: self.init_game_board() else: self.colors.append(self.colors.pop(0)) elif event.type == E_PING: #print(datetime.now(), '### ping from', self.players[event.uid]['name']) pass def gameloop(self): """ A game loop that circles through the methods. """ try: while True: self.handle_events() self.update() self.render() except KeyboardInterrupt: pass
class Game(object): """ The main game class that holds the gameloop. """ def __init__(self, host, port, width, height): """ Create a screen and define some game specific things. """ self.host = host self.port = port self.width = width self.height = height self.players = {} pymlgame.init() self.screen = Screen(self.host, self.port, self.width, self.height) self.clock = Clock(5) self.running = True self.colors = [WHITE, BLUE, GREEN, CYAN, MAGENTA, YELLOW, RED] self.color_length = math.ceil(self.screen.height / len(self.colors)) # surfaces self.game_board = None self.init_game_board() self.dots = Surface(self.screen.width, self.screen.height) def init_game_board(self): self.game_board = [0 for _ in range(self.screen.height * self.screen.width)] indices = random.sample( range(self.screen.height * self.screen.width), random.randint(self.screen.width // 2, (2 * (self.screen.height * self.screen.width) // 3)) ) for index in indices: self.game_board[index] = 1 def offset(self, width_idx, height_idx): return height_idx * self.screen.width + width_idx def board_value(self, width_idx, height_idx): if width_idx == -1 or height_idx == -1: return 0 return self.game_board[self.offset(width_idx, height_idx)] def update(self): """ Update the screens contents in every loop. """ # this is not really neccesary because the surface is black after initializing self.dots.fill(BLACK) intermediate_buffer = self.game_board.copy() for h_index in range(self.screen.height): for w_index in range(self.screen.width): id_above = h_index - 1 if h_index - 1 >= 0 else -1 id_left = w_index - 1 if w_index - 1 >= 0 else -1 id_right = w_index + 1 if w_index + 1 < self.screen.width else -1 id_bottom = h_index + 1 if h_index + 1 < self.screen.height else -1 cell_offset = self.offset(w_index, h_index) alive_check = [ self.board_value(id_left, id_above), self.board_value(w_index, id_above), self.board_value(id_right, id_above), self.board_value(id_left, h_index), self.board_value(w_index, h_index), self.board_value(id_right, h_index), self.board_value(id_left, id_bottom), self.board_value(w_index, id_bottom), self.board_value(id_right, id_bottom), ] # count neighbours that are alive counter = Counter(alive_check) num_alive = counter[1] if self.game_board[cell_offset] == 0: if num_alive == 3: intermediate_buffer[cell_offset] = 1 self.dots.draw_dot((w_index, h_index), self.colors[h_index // self.color_length]) elif num_alive < 2: intermediate_buffer[cell_offset] = 0 elif 2 <= num_alive <= 3: self.dots.draw_dot((w_index, h_index), self.colors[h_index // self.color_length]) else: intermediate_buffer[cell_offset] = 0 self.game_board = intermediate_buffer.copy() def render(self): """ Send the current screen content to Mate Light. """ self.screen.reset() self.screen.blit(self.dots) self.screen.update() self.clock.tick() def handle_events(self): """ Loop through all events. """ for event in pymlgame.get_events(): if event.type == E_NEWCTLR: #print(datetime.now(), '### new player connected with uid', event.uid) self.players[event.uid] = {'name': 'alien_{}'.format(event.uid), 'score': 0} elif event.type == E_DISCONNECT: #print(datetime.now(), '### player with uid {} disconnected'.format(event.uid)) self.players.pop(event.uid) elif event.type == E_KEYDOWN: #print(datetime.now(), '###', self.players[event.uid]['name'], 'pressed', event.button) if event.button == 9: self.init_game_board() else: self.colors.append(self.colors.pop(0)) elif event.type == E_PING: #print(datetime.now(), '### ping from', self.players[event.uid]['name']) pass def gameloop(self): """ A game loop that circles through the methods. """ try: while True: self.handle_events() self.update() self.render() except KeyboardInterrupt: pass
class Game(object): """ The main game class that holds the gameloop. """ def __init__(self, host, port, width, height): """ Create a screen and define some game specific things. """ self.host = host self.port = port self.width = width self.height = height self.players = {} pymlgame.init() self.screen = Screen(self.host, self.port, self.width, self.height) self.clock = Clock(15) self.running = True self.colors = [WHITE, BLUE, GREEN, CYAN, MAGENTA, YELLOW, RED] # surfaces self.corners = Surface(self.screen.width, self.screen.height) self.lines = Surface(int(self.screen.width / 2) - 2, int(self.screen.height / 2) - 2) self.rects = Surface(int(self.screen.width / 2) - 2, int(self.screen.height / 2) - 2) self.circle = Surface(int(self.screen.width / 2) - 2, int(self.screen.height / 2) - 2) self.filled = Surface(int(self.screen.width / 2) - 2, int(self.screen.height / 2) - 2) def update(self): """ Update the screens contents in every loop. """ # this is not really neccesary because the surface is black after initializing self.corners.fill(BLACK) self.corners.draw_dot((0, 0), self.colors[0]) self.corners.draw_dot((self.screen.width - 1, 0), self.colors[0]) self.corners.draw_dot((self.screen.width - 1, self.screen.height - 1), self.colors[0]) self.corners.draw_dot((0, self.screen.height - 1), self.colors[0]) self.lines.fill(BLACK) self.lines.draw_line((1, 0), (self.lines.width - 1, 0), self.colors[1]) self.lines.draw_line((0, 1), (0, self.lines.height - 1), self.colors[3]) self.lines.draw_line((0, 0), (self.lines.width - 1, self.lines.height - 1), self.colors[2]) self.rects.fill(BLACK) self.rects.draw_rect((0, 0), (int(self.rects.width / 2) - 1, self.rects.height), self.colors[2], self.colors[3]) self.rects.draw_rect((int(self.rects.width / 2) + 1, 0), (int(self.rects.width / 2) - 1, self.rects.height), self.colors[3], self.colors[2]) self.circle.fill(BLACK) radius = int(min(self.circle.width, self.circle.height) / 2) - 1 self.circle.draw_circle((int(self.circle.width / 2) - 1, int(self.circle.height / 2) - 1), radius, self.colors[4], self.colors[5]) self.filled.fill(self.colors[6]) def render(self): """ Send the current screen content to Mate Light. """ self.screen.reset() self.screen.blit(self.corners) self.screen.blit(self.lines, (1, 1)) self.screen.blit(self.rects, (int(self.screen.width / 2) + 1, 1)) self.screen.blit(self.circle, (0, int(self.screen.height / 2) + 1)) self.screen.blit(self.filled, (int(self.screen.width / 2) + 1, int(self.screen.height / 2) + 1)) self.screen.update() self.clock.tick() def handle_events(self): """ Loop through all events. """ for event in pymlgame.get_events(): if event.type == E_NEWCTLR: #print(datetime.now(), '### new player connected with uid', event.uid) self.players[event.uid] = {'name': 'alien_{}'.format(event.uid), 'score': 0} elif event.type == E_DISCONNECT: #print(datetime.now(), '### player with uid {} disconnected'.format(event.uid)) self.players.pop(event.uid) elif event.type == E_KEYDOWN: #print(datetime.now(), '###', self.players[event.uid]['name'], 'pressed', event.button) self.colors.append(self.colors.pop(0)) elif event.type == E_KEYUP: #print(datetime.now(), '###', self.players[event.uid]['name'], 'released', event.button) self.colors.append(self.colors.pop(0)) elif event.type == E_PING: #print(datetime.now(), '### ping from', self.players[event.uid]['name']) pass def gameloop(self): """ A game loop that circles through the methods. """ try: while True: self.handle_events() self.update() self.render() except KeyboardInterrupt: pass
class Game(object): """ The main game class that holds the gameloop. """ def __init__(self, host, port, width, height): """ Create a screen and define some game specific things. """ self.host = host self.port = port self.width = width self.height = height self.players = {} pymlgame.init() self.screen = Screen(self.host, self.port, self.width, self.height) self.clock = Clock(15) self.running = True self.colors = [WHITE, BLUE, GREEN, CYAN, MAGENTA, YELLOW, RED] # surfaces self.corners = Surface(self.screen.width, self.screen.height) self.lines = Surface( int(self.screen.width / 2) - 2, int(self.screen.height / 2) - 2) self.rects = Surface( int(self.screen.width / 2) - 2, int(self.screen.height / 2) - 2) self.circle = Surface( int(self.screen.width / 2) - 2, int(self.screen.height / 2) - 2) self.filled = Surface( int(self.screen.width / 2) - 2, int(self.screen.height / 2) - 2) def update(self): """ Update the screens contents in every loop. """ # this is not really neccesary because the surface is black after initializing self.corners.fill(BLACK) self.corners.draw_dot((0, 0), self.colors[0]) self.corners.draw_dot((self.screen.width - 1, 0), self.colors[0]) self.corners.draw_dot((self.screen.width - 1, self.screen.height - 1), self.colors[0]) self.corners.draw_dot((0, self.screen.height - 1), self.colors[0]) self.lines.fill(BLACK) self.lines.draw_line((1, 0), (self.lines.width - 1, 0), self.colors[1]) self.lines.draw_line((0, 1), (0, self.lines.height - 1), self.colors[3]) self.lines.draw_line((0, 0), (self.lines.width - 1, self.lines.height - 1), self.colors[2]) self.rects.fill(BLACK) self.rects.draw_rect( (0, 0), (int(self.rects.width / 2) - 1, self.rects.height), self.colors[2], self.colors[3]) self.rects.draw_rect( (int(self.rects.width / 2) + 1, 0), (int(self.rects.width / 2) - 1, self.rects.height), self.colors[3], self.colors[2]) self.circle.fill(BLACK) radius = int(min(self.circle.width, self.circle.height) / 2) - 1 self.circle.draw_circle( (int(self.circle.width / 2) - 1, int(self.circle.height / 2) - 1), radius, self.colors[4], self.colors[5]) self.filled.fill(self.colors[6]) def render(self): """ Send the current screen content to Mate Light. """ self.screen.reset() self.screen.blit(self.corners) self.screen.blit(self.lines, (1, 1)) self.screen.blit(self.rects, (int(self.screen.width / 2) + 1, 1)) self.screen.blit(self.circle, (0, int(self.screen.height / 2) + 1)) self.screen.blit( self.filled, (int(self.screen.width / 2) + 1, int(self.screen.height / 2) + 1)) self.screen.update() self.clock.tick() def handle_events(self): """ Loop through all events. """ for event in pymlgame.get_events(): if event.type == E_NEWCTLR: #print(datetime.now(), '### new player connected with uid', event.uid) self.players[event.uid] = { 'name': 'alien_{}'.format(event.uid), 'score': 0 } elif event.type == E_DISCONNECT: #print(datetime.now(), '### player with uid {} disconnected'.format(event.uid)) self.players.pop(event.uid) elif event.type == E_KEYDOWN: #print(datetime.now(), '###', self.players[event.uid]['name'], 'pressed', event.button) self.colors.append(self.colors.pop(0)) elif event.type == E_KEYUP: #print(datetime.now(), '###', self.players[event.uid]['name'], 'released', event.button) self.colors.append(self.colors.pop(0)) elif event.type == E_PING: #print(datetime.now(), '### ping from', self.players[event.uid]['name']) pass def gameloop(self): """ A game loop that circles through the methods. """ try: while True: self.handle_events() self.update() self.render() except KeyboardInterrupt: pass
class Game: def __init__(self): pymlgame.init() self.screen = Screen() # self.screen = Screen(host='matelight') self.clock = Clock(5) self.map = Map('1-1') self.mario = Mario() self.world = self.map.render_pixmap() self.colmat = self.map.generate_collision_matrix() for y in range(self.map.height): print('%02d %02d ' % (y, self.convert_y(y)), end='') for x in range(self.map.width): print(self.colmat[x][y], end='') print() self.gameover = False self.camera = Camera(self.map.width, self.map.height) def collide(self, x, y): """ Check for a collision on the given position. :param x: x coord to check for collision :type x: int :param y: y coord to check for collision :type y: int :returns: bool - Collision detected? """ return self.colmat[int(x)][self.convert_y(int(y))] def convert_y(self, y): """ Converts coords from bottom 0 to top 0 for drawing. :param y: y coord with 0 at the bottom :type y: int :returns: int - y coord with 0 at the top """ return self.map.height - y - 1 def update(self): vel_x = 0 vel_y = 0 # apply jump force vel_y + self.mario.jumping if self.mario.jumping == 2: self.mario.jumping = 1 elif self.mario.jumping == 1: self.mario.jumping = 0 # apply movement force vel_x + self.mario.moving # apply gravity/falling vel_y -= 1 # Compute resulting velocity # Apply resulting velocity and update position new_x = self.mario.x + vel_x new_y = self.mario.y + vel_y print('X: %d -> %d' % (self.mario.x, new_x)) print('Y: %d -> %d' % (self.mario.y, new_y)) print('C: %d' % self.colmat[new_x][self.convert_y(new_y)]) print('R: %d' % self.collide(new_x, self.convert_y(new_y))) # Check collisions between objects # If collision, resolve it by moving back old_y = self.mario.y if not self.collide(self.mario.x, new_y) > 0: self.mario.y = new_y if not self.collide(new_x, old_y) > 0: self.mario.x = new_x # out of map? if self.mario.y < 0 or self.mario.x + self.mario.width <= 0 or self.mario.x >= self.map.width: self.gameover = True # camera self.camera.update((self.mario.x, self.mario.y)) # autowalk # self.mario.x += 1 def render(self): self.screen.reset() self.screen.blit(self.world, (int(0 - self.camera.x), int(0 - (self.convert_y(self.camera.y) - self.camera.height)))) self.screen.blit(self.mario.current, (int(self.mario.x - self.camera.x), int(self.convert_y(self.mario.y + self.mario.height) - (self.convert_y(self.camera.y) - self.camera.height)))) self.screen.update() self.clock.tick() def handle_events(self): for event in pymlgame.get_events(): if event.type == E_PING: print(datetime.now(), '# ping from', event.uid) else: print(datetime.now(), '# unknown event', event.uid, event.type) def start(self): try: while not self.gameover: self.handle_events() self.update() self.render() if self.gameover: break print('game over!') except KeyboardInterrupt: pass