import network, sys, pygame, random, xlog, time, colorsys pygame.init() address = ["0.0.0.0", int(sys.argv[1])] w, h = 640, 480 size = [w, h] black = [0, 0, 0] def random_color(): return [int(i*255) for i in colorsys.hsv_to_rgb(random.random(), 0.8, 1)] def normalize(n): if n > 0: return 1 if n < 0: return -1 return 0 def new_oid(): return random.randint(0,2147483648) class Obj: def __init__(self, oid): self.oid = oid def damage(self, dmg, author=None): pass def update(self): pass def draw(self, surface): pass def print_debug(self, lines): pass class Player(Obj): def __init__(self, oid, address, pos, color, life=100, score=0): Obj.__init__(self, oid) self.address = address self.pos = pos self.color = color self.score = score self.speed = [0, 0] self.life = life self.direction = [0, 1] def throw_energy_ball(self): oid = new_oid() pos = [self.pos[0], self.pos[1]] pos[0] += self.direction[0] * 16 pos[1] += self.direction[1] * 16 speed = [self.speed[0]+self.direction[0]*4, self.speed[1]+self.direction[1]*4] objects[oid] = EnergyBall(oid, pos, speed, self.oid) def stab(self): for oid in players: if oid == self.oid: continue player = players[oid] if abs(player.pos[0]-self.pos[0]) < 32 and abs(player.pos[1]-self.pos[1]) < 32: player.damage(10, self.oid) def damage(self, dmg, author=None): self.life -= dmg if self.life <= 0: self.speed = [0, 0] self.pos = [16, 16] self.life = 100 if author in players: players[author].score += 1 def update(self): if self.speed[0] != 0 or self.speed[1] != 0: self.direction = [normalize(self.speed[0]), normalize(self.speed[1])] self.pos[0] += self.speed[0] self.pos[1] += self.speed[1] def draw(self, surface): pygame.draw.rect(surface, self.color, (self.pos[0]-8, self.pos[1]-8, 16, 16)) lifebar = int(16*self.life/100) pygame.draw.rect(surface, (64,255,64), (self.pos[0]-8, self.pos[1]-16, lifebar, 4)) def print_debug(self, lines): lines.append("Player {}: {} / score {}".format(self.oid, obj.address, obj.score)) class EnergyBall(Obj): def __init__(self, oid, pos, speed, thrower): Obj.__init__(self, oid) self.pos = pos self.speed = speed self.thrower = thrower def update(self): self.pos[0] += self.speed[0] self.pos[1] += self.speed[1] for oid in objects: if oid == self.oid: continue obj = objects[oid] if abs(self.pos[0]-obj.pos[0])<8 and abs(self.pos[1]-obj.pos[1])<8: obj.damage(10, self.thrower) removable.append(self.oid) return def draw(self, surface): pygame.draw.rect(surface, (128,255,255), (self.pos[0]-2, self.pos[1]-2, 4, 4)) def damage(self, dmg, author=None): if dmg > 0: removable.append(self.oid) def print_debug(self, lines): pass screen = pygame.display.set_mode(size) clock = pygame.time.Clock() sock = network.Sock() sock.listen(address) me = Player(new_oid(), address, [random.randint(16, w-16), random.randint(16, h-16)], random_color()) objects = {me.oid: me} players = {me.oid: me} removable = [] def send_all(msg): for oid in players: if oid != me.oid: sock.send(msg, objects[oid].address) def make_recap(): pl = [] for oid in players: player = players[oid] pl.append({ "oid": oid, "pos": player.pos, "color": player.color, "address": player.address, "life": player.life, "score": player.score }) return {"type":"recap", "players":pl, "oid":me.oid} def remove_objects(): for oid in removable: if oid in objects: objects.pop(oid) if oid in players: players.pop(oid) removable.clear() sock.send({"type":"join","pos":me.pos,"color":me.color,"port":address[1],"oid":me.oid}, ["192.168.0.255", 33033]) sock.send({"type":"join","pos":me.pos,"color":me.color,"port":address[1],"oid":me.oid}, ["192.168.0.255", 33033]) sock.send({"type":"join","pos":me.pos,"color":me.color,"port":address[1],"oid":me.oid}, ["127.0.0.1", 33033]) last_recap = 0 while True: for event in pygame.event.get(): if event.type == pygame.QUIT: sys.exit() if event.type == pygame.KEYDOWN: if event.key == pygame.K_ESCAPE: send_all({"type":"quit", "oid":me.oid}) sys.exit() if event.key == pygame.K_RIGHT: me.speed[0] = 2 send_all({"type":"move", "oid":me.oid, "speed":me.speed}) elif event.key == pygame.K_LEFT: me.speed[0] = -2 send_all({"type":"move", "oid":me.oid, "speed":me.speed}) elif event.key == pygame.K_DOWN: me.speed[1] = 2 send_all({"type":"move", "oid":me.oid, "speed":me.speed}) elif event.key == pygame.K_UP: me.speed[1] = -2 send_all({"type":"move", "oid":me.oid, "speed":me.speed}) elif event.key == pygame.K_SPACE: me.stab() send_all({"type":"stab", "oid":me.oid}) elif event.key == pygame.K_c: me.throw_energy_ball() send_all({"type":"throw", "oid":me.oid}) elif event.type == pygame.KEYUP: if event.key == pygame.K_RIGHT: me.speed[0] = 0 send_all({"type":"move", "oid":me.oid, "speed":me.speed}) elif event.key == pygame.K_LEFT: me.speed[0] = 0 send_all({"type":"move", "oid":me.oid, "speed":me.speed}) elif event.key == pygame.K_DOWN: me.speed[1] = 0 send_all({"type":"move", "oid":me.oid, "speed":me.speed}) elif event.key == pygame.K_UP: me.speed[1] = 0 send_all({"type":"move", "oid":me.oid, "speed":me.speed}) for (r, c) in sock.get(): if r["oid"] == me.oid: continue if r["type"] == "join": sock.send(make_recap(), [c[0], r["port"]]) sock.send(make_recap(), [c[0], r["port"]]) new_player = Player(r["oid"], [c[0], r["port"]], r["pos"], r["color"]) players[r["oid"]] = new_player objects[r["oid"]] = new_player elif r["type"] == "move": players[r["oid"]].speed = r["speed"] elif r["type"] == "recap": for player in r["players"]: if not player["oid"] in players: address = player["address"] if address[0] == "0.0.0.0": address = [c[0], c[1]] new_player = Player(player["oid"], address, player["pos"], player["color"], life=player["life"], score=player["score"] ) objects[player["oid"]] = new_player players[player["oid"]] = new_player elif c[0] == player["address"][0]: players[player["oid"]].pos = player["pos"] players[player["oid"]].speed = player["speed"] elif r["type"] == "quit": removable.append(r["oid"]) elif r["type"] == "stab": objects[r["oid"]].stab() elif r["type"] == "throw": objects[r["oid"]].throw_energy_ball() remove_objects() screen.fill(black) lines = [] for oid in objects: obj = objects[oid] obj.update() obj.draw(screen) obj.print_debug(lines) remove_objects() xlog.display(screen, lines) if time.time() > last_recap + 5: send_all(make_recap()) last_recap = time.time() + 5 pygame.display.flip() clock.tick(30)