jsb-netgame/game.py

247 lines
6.7 KiB
Python

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)