diff --git a/chat.py b/chat.py
new file mode 100644
index 0000000..6b09431
--- /dev/null
+++ b/chat.py
@@ -0,0 +1,14 @@
+import network, sys, time
+
+sock = network.Sock()
+port = 33077
+
+if sys.argv[1] == "s":
+ sock.listen(["0.0.0.0", port])
+ while True:
+ for d, a in sock.get():
+ print(a, d)
+ time.sleep(0.1)
+elif sys.argv[1] == "c":
+ while True:
+ sock.send(input(), ["192.168.0.255", port])
diff --git a/demo.py b/demo.py
index 4c79817..ec3615d 100644
--- a/demo.py
+++ b/demo.py
@@ -12,5 +12,5 @@ if sys.argv[1] == "s":
time.sleep(0.1)
elif sys.argv[1] == "c":
while True:
- sock.send(str(time.time()), (sys.argv[3], port))
+ sock.send(time.time(), (sys.argv[3], port))
time.sleep(1)
diff --git a/demo1.py b/demo1.py
new file mode 100644
index 0000000..d2754de
--- /dev/null
+++ b/demo1.py
@@ -0,0 +1,8 @@
+import network, sys, time
+
+sock = network.Sock()
+destination = ["192.168.0.255", 33077]
+
+while True:
+ message = input("envoyer: ")
+ sock.send(message, destination)
diff --git a/demo2.py b/demo2.py
new file mode 100644
index 0000000..f226594
--- /dev/null
+++ b/demo2.py
@@ -0,0 +1,10 @@
+import network, sys, time
+
+sock = network.Sock()
+address = ("0.0.0.0", 33077)
+
+sock.listen(address)
+while True:
+ for d, a in sock.get():
+ print(a, d)
+ time.sleep(0.1)
diff --git a/game.py b/game.py
index ac244ba..202232b 100644
--- a/game.py
+++ b/game.py
@@ -1,4 +1,4 @@
-import network, sys, json, pygame, random, xlog
+import network, sys, pygame, random, xlog, time, colorsys
pygame.init()
@@ -7,26 +7,37 @@ 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): pass
+ 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):
+ 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 = 100
- self.direction = [1, 0]
+ self.life = life
+ self.direction = [0, 1]
def throw_energy_ball(self):
oid = new_oid()
@@ -34,7 +45,7 @@ class Player(Obj):
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)
+ objects[oid] = EnergyBall(oid, pos, speed, self.oid)
def stab(self):
for oid in players:
@@ -42,30 +53,37 @@ class Player(Obj):
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)
+ player.damage(10, self.oid)
- def damage(self, dmg):
+ def damage(self, dmg, author=None):
self.life -= dmg
if self.life <= 0:
- print("die!")
+ 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(32*self.life/100)
- pygame.draw.rect(surface, (64,255,64), (self.pos[0]-lifebar//2+8, self.pos[1]+6, lifebar, 4))
+ 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 {}: {}".format(self.oid, obj.address))
+ lines.append("Player {}: {} / score {}".format(self.oid, obj.address, obj.score))
class EnergyBall(Obj):
- def __init__(self, oid, pos, speed):
+ 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]
@@ -75,14 +93,14 @@ class EnergyBall(Obj):
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)
+ 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):
+ def damage(self, dmg, author=None):
if dmg > 0:
removable.append(self.oid)
@@ -95,15 +113,29 @@ clock = pygame.time.Clock()
sock = network.Sock()
sock.listen(address)
-me = Player(new_oid(), address, [10, 10], [255, 0, 0])
+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):
- msg = json.dumps(msg)
for oid in players:
- sock.send(msg, objects[oid].address)
+ 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:
@@ -113,8 +145,11 @@ def remove_objects():
players.pop(oid)
removable.clear()
-sock.send(json.dumps({"type":"join","pos":me.pos,"color":me.color,"port":address[1],"oid":me.oid}), ["192.168.0.255", 33033])
-sock.send(json.dumps({"type":"join","pos":me.pos,"color":me.color,"port":address[1],"oid":me.oid}), ["127.0.0.1", 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}, ["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():
@@ -125,19 +160,15 @@ while True:
send_all({"type":"quit", "oid":me.oid})
sys.exit()
if event.key == pygame.K_RIGHT:
- me.direction = [1, 0]
me.speed[0] = 2
send_all({"type":"move", "oid":me.oid, "speed":me.speed})
elif event.key == pygame.K_LEFT:
- me.direction = [-1, 0]
me.speed[0] = -2
send_all({"type":"move", "oid":me.oid, "speed":me.speed})
elif event.key == pygame.K_DOWN:
- me.direction = [0, 1]
me.speed[1] = 2
send_all({"type":"move", "oid":me.oid, "speed":me.speed})
elif event.key == pygame.K_UP:
- me.direction = [0, -1]
me.speed[1] = -2
send_all({"type":"move", "oid":me.oid, "speed":me.speed})
elif event.key == pygame.K_SPACE:
@@ -160,16 +191,14 @@ while True:
me.speed[1] = 0
send_all({"type":"move", "oid":me.oid, "speed":me.speed})
for (r, c) in sock.get():
- r = json.loads(r.decode())
if r["oid"] == me.oid:
continue
if r["type"] == "join":
- pl = []
- for oid in players:
- player = players[oid]
- pl.append({"oid":oid, "pos":player.pos, "color":player.color, "address":player.address})
- sock.send(json.dumps({"type":"recap", "players":pl, "oid":me.oid}), [c[0], r["port"]])
- players[r["oid"]] = Player(r["oid"], [c[0], r["port"]], r["pos"], r["color"])
+ 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":
@@ -178,12 +207,21 @@ while True:
address = player["address"]
if address[0] == "0.0.0.0":
address = [c[0], c[1]]
- objects[player["oid"]] = Player(player["oid"], address, player["pos"], player["color"])
- players[player["oid"]] = objects[player["oid"]]
+ 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()
@@ -200,5 +238,9 @@ while True:
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)
diff --git a/network.py b/network.py
index f62af0c..01aea39 100644
--- a/network.py
+++ b/network.py
@@ -1,4 +1,4 @@
-import socket, os, sys
+import socket, os, sys, json
from threading import Thread, Lock
NETTRACE = str(os.environ.get("NETTRACE", "0")) == "1"
@@ -12,25 +12,44 @@ class Sock:
self.queue_lock = Lock()
self.sock_thread = None
- def send(self, message, address):
+ def send_raw(self, message, address):
if type(message) == str:
message = message.encode()
if NETTRACE:
print("Send to", tuple(address), ":", message, file=sys.stderr)
self.sock.sendto(message, tuple(address))
+ def send(self, message, address):
+ message = json.dumps(message)
+ if NETTRACE:
+ print("Send to", tuple(address), ":", message, file=sys.stderr)
+ self.sock.sendto(message.encode(), tuple(address))
+
def listen(self, address, length=65535):
self.sock_thread = SockThread(self, tuple(address), length)
self.sock_thread.setDaemon(True)
self.sock_thread.start()
- def get(self):
+ def get_raw(self):
if len(self.queue) == 0:
return []
with self.queue_lock:
queue = self.queue
self.queue = []
return queue
+
+ def get(self):
+ if len(self.queue) == 0:
+ return []
+ queue = []
+ with self.queue_lock:
+ for r in self.queue:
+ try:
+ queue.append([json.loads(r[0].decode()), r[1]])
+ except:
+ pass
+ self.queue.clear()
+ return queue
class SockThread(Thread):
def __init__(self, sock, address, length):
diff --git a/template.py b/template.py
new file mode 100644
index 0000000..1c94ded
--- /dev/null
+++ b/template.py
@@ -0,0 +1,108 @@
+import network, sys, pygame, random, xlog, time, colorsys
+
+pygame.init()
+
+w, h = 640, 480 # Taille de la fenêtre
+size = [w, h]
+black = [0, 0, 0] # Couleur noire
+
+# Créer une couleur aléatoire
+def random_color():
+ return [int(i*255) for i in colorsys.hsv_to_rgb(random.random(), 0.8, 1)]
+
+# Créer un identifiant d'objet aléatoire
+def new_oid():
+ return random.randint(0,2147483648)
+
+# Définit les méthodes par défaut d'un objet
+class Obj:
+ def __init__(self, oid):
+ self.oid = oid
+ def update(self): pass
+ def draw(self, surface): pass
+ def print_debug(self, lines): pass
+
+# Définit un joueur
+class Player(Obj):
+ def __init__(self, oid, pos, color):
+ Obj.__init__(self, oid)
+ self.pos = pos
+ self.speed = [0, 0]
+ self.color = color
+
+ # Mise à jour de l'état du joueur
+ def update(self):
+ self.pos[0] += self.speed[0]
+ self.pos[1] += self.speed[1]
+
+ # Dessiner le joueur
+ def draw(self, surface):
+ pygame.draw.rect(surface, self.color, (self.pos[0]-8, self.pos[1]-8, 16, 16))
+
+ # Afficher le texte d'information
+ def print_debug(self, lines):
+ lines.append("Player {}".format(self.oid))
+
+screen = pygame.display.set_mode(size) # définir la taille de la fenêtre
+clock = pygame.time.Clock()
+
+# Créer notre propre joueur
+me = Player(new_oid(), [random.randint(16, w-16), random.randint(16, h-16)], random_color())
+objects = {me.oid: me} # dictionnaire de tous les objets
+players = {me.oid: me} # dictionnaire de tous les joueurs (qui sont aussi des objets)
+removable = [] # identifiants des objets à supprimer
+
+# Supprimer les objets à supprimer
+def remove_objects():
+ for oid in removable:
+ if oid in objects:
+ objects.pop(oid)
+ if oid in players:
+ players.pop(oid)
+ removable.clear()
+
+# Boucle principale
+while True:
+ # Lecture des événements
+ for event in pygame.event.get():
+ if event.type == pygame.QUIT:
+ sys.exit()
+ if event.type == pygame.KEYDOWN:
+ if event.key == pygame.K_ESCAPE:
+ sys.exit()
+ if event.key == pygame.K_RIGHT:
+ me.speed[0] = 2
+ elif event.key == pygame.K_LEFT:
+ me.speed[0] = -2
+ elif event.key == pygame.K_DOWN:
+ me.speed[1] = 2
+ elif event.key == pygame.K_UP:
+ me.speed[1] = -2
+ elif event.type == pygame.KEYUP:
+ if event.key == pygame.K_RIGHT:
+ me.speed[0] = 0
+ elif event.key == pygame.K_LEFT:
+ me.speed[0] = 0
+ elif event.key == pygame.K_DOWN:
+ me.speed[1] = 0
+ elif event.key == pygame.K_UP:
+ me.speed[1] = 0
+
+ remove_objects()
+
+ screen.fill(black) # colorier le fond en noir
+
+ # Mettre à jour tous les objets
+ lines = []
+ for oid in objects:
+ obj = objects[oid]
+ obj.update()
+ obj.draw(screen)
+ obj.print_debug(lines)
+
+ remove_objects()
+
+ xlog.display(screen, lines) # afficher le texte d'information
+
+ pygame.display.flip() # mettre à jour l'écran
+ clock.tick(30) # attendre un peu