Implemented networking.

This commit is contained in:
Suwako Moriya 2020-02-03 00:31:31 +01:00
parent a2e76bde51
commit c64a19b257
Signed by: SuwakoMmh
GPG Key ID: A27482B806F13CD5
12 changed files with 262 additions and 57 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 167 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 490 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 490 B

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 112 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.1 KiB

View File

@ -9,7 +9,9 @@ Created on Sun Jan 26 17:50:16 2020
import sys, pygame, time, random, socket import sys, pygame, time, random, socket
from colorama import Fore, Style from colorama import Fore, Style
import numpy as np import numpy as np
import gzip
import json
import multiprocessing
def debug(*s): print("[D ] : " + def debug(*s): print("[D ] : " +
str(', '.join(map(str, s))) + str(', '.join(map(str, s))) +
@ -37,12 +39,74 @@ def error(*s): print(Fore.RED +
Style.RESET_ALL + Style.RESET_ALL +
str(', '.join(map(str, s))) + str(', '.join(map(str, s))) +
Style.RESET_ALL) Style.RESET_ALL)
level = 0
BUFFER_SIZE = 4096
CONTINUE = b'\x00'
END = b'\xFF'
for i in range(level):
exec("debug info warn error".split()[i] + "= lambda *x: None")
def lookahead(iterable):
it = iter(iterable)
last = next(it)
for val in it:
yield last, CONTINUE
last = val
yield last, END
def chunked(size, source):
for i in range(0, len(source), size):
yield source[i:i+size]
def handle(conn, queues):
try:
data = bytes()
while True:
in_data = conn.recv(BUFFER_SIZE)
if in_data == b"":
info("Socket closed remotely")
break
if in_data[0] == CONTINUE[0]:
data += in_data[1:]
elif in_data[0] == END[0]:
decompressed = gzip.decompress(data+in_data[1:]).decode('utf8')
queues['in'].put(json.loads(decompressed))
else :
warn("Invalid chunk received !!")
send(conn, {'error':True, 'content':"INV_CHUNK"})
break
finally:
info("Closing socket")
conn.close()
def send(conn, data_obj):
data = gzip.compress(bytes(json.dumps(data_obj), encoding='utf8'))
for chunk, info in lookahead(chunked(BUFFER_SIZE - 1, data)):
conn.sendall(info + chunk.ljust(BUFFER_SIZE - 1, b'\x00'))
class Client(object):
def __init__(self, hostname, port):
self.hostname = hostname
self.port = port
self.queues = {'in':multiprocessing.Queue(),
'out':multiprocessing.Queue()}
def start(self):
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
info(f"Connecting to {self.hostname}:{self.port}.")
self.socket.connect((self.hostname, self.port))
self.handler = multiprocessing.Process(target=handle,
args=(self.socket,
self.queues))
self.handler.start()
send(self.socket, {'type':'Hello', 'content':{'player_name':"Suwako"}})
self.handler.join()
finally:
info("Exiting.")
self.socket.close()
if __name__ == "__main__": if __name__ == "__main__":
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) client = Client("localhost", 9001)
sock.connect(("localhost", 9000)) client.start()
data = b"some data"
sock.sendall(data)
result = sock.recv(1024)
print(result)
sock.close()

View File

@ -7,7 +7,7 @@ Created on Mon Jan 27 16:32:02 2020
""" """
import numpy as np import numpy as np
import visual
class Mass(): class Mass():
def __init__(self, pos=(0, 0), speed=(0, 0), mass=1): def __init__(self, pos=(0, 0), speed=(0, 0), mass=1):
@ -15,9 +15,11 @@ class Mass():
self.speed = np.array(speed, dtype='float64') self.speed = np.array(speed, dtype='float64')
self.mass = mass self.mass = mass
self.G = 0.00000000001 self.G = 0.00000000001
self.ticks=0
def tick(self): def tick(self):
self.pos += self.speed self.pos += self.speed
self.ticks+=1
def ref(self, def ref(self,
origin=np.array((0, 0), dtype='float64'), origin=np.array((0, 0), dtype='float64'),
@ -36,6 +38,18 @@ class Mass():
u = d/norm_d u = d/norm_d
norm = self.G * element.mass * (d[0]**2 + d[1]**2) norm = self.G * element.mass * (d[0]**2 + d[1]**2)
self.speed += norm*u self.speed += norm*u
def fire(*a):
pass
class Projectile(Mass):
def __init__(self,
orientation=0,
pos=(0, 0),
speed=(0, 0),
mass=0.000000001):
Mass.__init__(self, pos=pos, speed=speed, mass=mass)
self.orientation = orientation
class Player(Mass): class Player(Mass):
@ -44,11 +58,13 @@ class Player(Mass):
pos=(0, 0), pos=(0, 0),
speed=(0, 0), speed=(0, 0),
mass=1, mass=1,
thrust=0.01): thrust=0.01,
fire_force=1):
Mass.__init__(self, pos=pos, speed=speed, mass=mass) Mass.__init__(self, pos=pos, speed=speed, mass=mass)
self.orientation = orientation self.orientation = orientation
self.actions = {"thrust": False, "fire": False} self.actions = {"thrust": False, "fire": False}
self.thrust=thrust self.thrust=thrust
self.fire_force=fire_force
def action(self, **kwargs): def action(self, **kwargs):
print(kwargs) print(kwargs)
@ -64,6 +80,20 @@ class Player(Mass):
def apply_forces(self, elements): def apply_forces(self, elements):
Mass.apply_forces(self, elements) Mass.apply_forces(self, elements)
self.apply_thrust() self.apply_thrust()
def fire(self, elements):
if self.actions['fire']:
projectile = visual.Projectile(orientation=self.orientation,
pos=self.pos,
speed=self.speed)
orientation = np.deg2rad(self.orientation + 90)
or_tuple=(np.cos(orientation), -np.sin(orientation))
pnorm = self.fire_force/projectile.mecha.mass
snorm = self.fire_force/self.mass
projectile.mecha.speed += snorm * np.array(or_tuple, dtype='float64')
self.speed -= snorm * np.array(or_tuple, dtype='float64')
elements.append(projectile)
self.actions['fire'] = False
if __name__ == "__main__": if __name__ == "__main__":
pass pass

3
requirements.txt Normal file
View File

@ -0,0 +1,3 @@
numpy
colorama
pygame

173
server.py
View File

@ -11,6 +11,8 @@ if sys.platform == 'win32':
import multiprocessing.reduction import multiprocessing.reduction
from colorama import Fore, Style from colorama import Fore, Style
import numpy as np import numpy as np
import json
import gzip
def debug(*s): print("[D ] : " + def debug(*s): print("[D ] : " +
@ -40,65 +42,150 @@ def error(*s): print(Fore.RED +
str(', '.join(map(str, s))) + str(', '.join(map(str, s))) +
Style.RESET_ALL) Style.RESET_ALL)
level = 1 level = 0
BUFFER_SIZE = 4096
CONTINUE = b'\x00'
END = b'\xFF'
for i in range(level): for i in range(level):
exec("debug info warn error".split()[i] + "= lambda *x: None") exec("debug info warn error".split()[i] + "= lambda *x: None")
def lookahead(iterable):
it = iter(iterable)
last = next(it)
for val in it:
yield last, CONTINUE
last = val
yield last, END
def handle(connection, address): def chunked(size, source):
for i in range(0, len(source), size):
yield source[i:i+size]
def handle(conn, address, queues):
try: try:
info("Connected at "+ ':'.join(map(str,address))) info("Inbound Connection at " + ':'.join(map(str,address)))
data = bytes()
while True: while True:
data = connection.recv(1024) in_data = conn.recv(BUFFER_SIZE)
if data == b"": if in_data == b"":
info("Socket closed remotely at " + ':'.join(map(str,address))) info("Socket closed remotely at " + ':'.join(map(str,address)))
break break
debug("Received data %r" % data) if in_data[0] == CONTINUE[0]:
connection.sendall(data) data += in_data[1:]
debug("Sent data") elif in_data[0] == END[0]:
except: decompressed = gzip.decompress(data+in_data[1:]).decode('utf8')
warn("Problem handling request") queues['in'].put(json.loads(decompressed))
connection.close() else :
raise warn("Invalid chunk received !!")
send(conn, {'error':True, 'content':"INV_CHUNK"})
break
finally: finally:
debug("Closing socket with " + ':'.join(map(str,address))) info("Closing socket at " + ':'.join(map(str,address)))
connection.close() conn.close()
def send(conn, data_obj):
data = gzip.compress(bytes(json.dumps(data_obj), encoding='utf8'))
for chunk, info in lookahead(chunked(BUFFER_SIZE - 1, data)):
conn.sendall(info + chunk.ljust(BUFFER_SIZE - 1, b'\x00'))
class Server(object): class Server(object):
def __init__(self, hostname, port): def __init__(self, hostname, port):
self.hostname = hostname self.hostname = hostname
self.port = port self.port = port
self.run = False
self.connections = []
def start(self): def start(self):
debug("listening") self.run = True
info(f"Listening on {self.hostname}:{self.port}.")
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.socket.bind((self.hostname, self.port)) try:
self.socket.listen(1) self.socket.bind((self.hostname, self.port))
self.socket.listen(1)
while True:
conn, address = self.socket.accept() while self.run:
process = multiprocessing.Process(target=handle, conn, address = self.socket.accept()
args=(conn, address)) queues = {'in':multiprocessing.Queue(),
process.daemon = True 'out':multiprocessing.Queue()}
process.start() p = multiprocessing.Process(target=handle, args=(conn,
address,
queues))
p.start()
self.connections.append({'conn':conn, 'address':address,
'queues':queues, 'process':p})
finally:
for process in multiprocessing.active_children():
info("Shutting down process {process}")
process.terminate()
process.join()
self.socket.close()
def stop(self):
info(f"Shutting down the listenner.")
self.run = False
if __name__ == "__main__": if __name__ == "__main__":
server = Server("0.0.0.0", 9000) server = Server("0.0.0.0", 9001)
try: server.start()
info("Listening")
server.start() if False :
except: def handle(connection, address):
error("Unexpected exception") try:
for process in multiprocessing.active_children(): info("Connected at "+ ':'.join(map(str,address)))
info("Shutting down process %r", process) while True:
process.terminate() data = connection.recv(1024)
process.join() if data == b"":
raise info("Socket closed remotely at " + ':'.join(map(str,address)))
finally: break
info("Shutting down") debug("Received data %r" % data)
for process in multiprocessing.active_children(): connection.sendall(data)
info("Shutting down process %r", process) debug("Sent data")
process.terminate() except:
process.join() warn("Problem handling request")
info("All done") connection.close()
raise
finally:
debug("Closing socket with " + ':'.join(map(str,address)))
connection.close()
class Server(object):
def __init__(self, hostname, port):
self.hostname = hostname
self.port = port
self.connections = []
def start(self):
debug("listening")
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.socket.bind((self.hostname, self.port))
self.socket.listen(1)
while True:
conn, address = self.socket.accept()
process = multiprocessing.Process(target=handle,
args=(conn, address))
process.daemon = True
process.start()
if __name__ == "__main__":
server = Server("0.0.0.0", 9000)
try:
info("Listening")
server.start()
except:
error("Unexpected exception")
for process in multiprocessing.active_children():
info("Shutting down process %r", process)
process.terminate()
process.join()
raise
finally:
info("Shutting down")
for process in multiprocessing.active_children():
info("Shutting down process %r", process)
process.terminate()
process.join()
info("All done")

View File

@ -22,7 +22,7 @@ class Obj():
return np.array((self.position.width, self.position.height), return np.array((self.position.width, self.position.height),
dtype='float64') dtype='float64')
def draw(self, def draw(self, screen,
scale=1, scale=1,
reference=np.array((0, 0), dtype='float64'), reference=np.array((0, 0), dtype='float64'),
size=(0, 0)): size=(0, 0)):
@ -30,6 +30,8 @@ class Obj():
scaled_pos = scale * (self.mecha.pos - reference + npsize/(2*scale)) scaled_pos = scale * (self.mecha.pos - reference + npsize/(2*scale))
if np.linalg.norm(scaled_pos - npsize/2) > max(size): if np.linalg.norm(scaled_pos - npsize/2) > max(size):
return return
if min(self.position.size)*scale < 1 :
return
scaled_dimension = (scale*self.dimension()).astype(int) scaled_dimension = (scale*self.dimension()).astype(int)
scaled_image = pygame.transform.scale(self.image, scaled_dimension) scaled_image = pygame.transform.scale(self.image, scaled_dimension)
scaled_image = pygame.transform.rotate(scaled_image, scaled_image = pygame.transform.rotate(scaled_image,
@ -41,7 +43,7 @@ class Obj():
class Star(Obj): class Star(Obj):
def __init__(self, **keyargs): def __init__(self, **keyargs):
self.mecha = mecha.Player(**keyargs) self.mecha = mecha.Mass(**keyargs)
self.image = pygame.image.load("assets/ship/loop/00001.png") self.image = pygame.image.load("assets/ship/loop/00001.png")
self.position = self.image.get_rect() self.position = self.image.get_rect()
@ -59,6 +61,11 @@ class Player(Obj):
self.image = pygame.image.load("assets/ship/loop/00001.png").convert_alpha() self.image = pygame.image.load("assets/ship/loop/00001.png").convert_alpha()
self.position = self.image.get_rect() self.position = self.image.get_rect()
class Projectile(Obj):
def __init__(self, **keyargs):
self.mecha = mecha.Projectile(**keyargs)
self.image = pygame.image.load("assets/projectile/loop/00001.png")
self.position = self.image.get_rect()
if __name__ == "__main__": if __name__ == "__main__":
import time import time
@ -70,7 +77,7 @@ if __name__ == "__main__":
tick = (time.time(), time.time(), 0) tick = (time.time(), time.time(), 0)
screen = pygame.display.set_mode(size, screen = pygame.display.set_mode(size,
flags=pygame.RESIZABLE) flags=pygame.RESIZABLE)
elements = [Player(speed=(5, 0), pos=(10, -200)), Player(speed=(-5, 0), pos=(10, 200), mass = 1), Planet(mass=200), Planet(mass=200, pos=(0,20), speed=(-1,0)), Planet(mass=150, pos = (0, 1000), speed = (15, 0)), Player(mass=5, pos = (0, 1010), speed = (15, 1))] elements = [Player(speed=(5, 0), pos=(10, -200)), Player(speed=(-5, 0), pos=(10, 200), mass = 1), Planet(mass=7000), Planet(mass=200, pos=(0,20), speed=(-1,0)), Planet(mass=150, pos = (0, 1000), speed = (15, 0)), Player(mass=5, pos = (0, 1010), speed = (15, 1))]
reference = 2 reference = 2
joy=[1, 1] joy=[1, 1]
while 1: while 1:
@ -95,11 +102,15 @@ if __name__ == "__main__":
reference = (reference + 1)%len(elements) reference = (reference + 1)%len(elements)
if event.key == (32): if event.key == (32):
elements[1].mecha.action(thrust=True) elements[1].mecha.action(thrust=True)
if event.key == 119:
elements[1].mecha.action(fire = True)
if event.type == pygame.KEYUP: if event.type == pygame.KEYUP:
if event.key in keys: if event.key in keys:
keys.remove(event.key) keys.remove(event.key)
if event.key == (32): if event.key == (32):
elements[1].mecha.action(thrust=False) elements[1].mecha.action(thrust=False)
if event.key == 119:
elements[1].mecha.action(fire = False)
screen.fill(black) screen.fill(black)
for key in keys: for key in keys:
if key in [275,276,273,274]: if key in [275,276,273,274]:
@ -107,6 +118,16 @@ if __name__ == "__main__":
elements[1].mecha.orientation=joy[0]*(-3) elements[1].mecha.orientation=joy[0]*(-3)
for element in elements: for element in elements:
element.mecha.apply_forces([element.mecha for element in elements]) element.mecha.apply_forces([element.mecha for element in elements])
j = 0
while j < len(elements):
if type(elements[j]) is mecha.visual.Projectile and elements[j].mecha.ticks > 25*30:
del elements[j]
j-=1
j+=1
j = 0
while j < len(elements):
elements[j].mecha.fire(elements)
j+=1
for element in elements: for element in elements:
element.mecha.tick() element.mecha.tick()
ori,speed=origin=np.array(elements[0].mecha.pos), np.array(elements[0].mecha.speed) ori,speed=origin=np.array(elements[0].mecha.pos), np.array(elements[0].mecha.speed)
@ -118,7 +139,7 @@ if __name__ == "__main__":
while 10**(joy[1]*0.05) < 0.08 : while 10**(joy[1]*0.05) < 0.08 :
joy[1] += 1 joy[1] += 1
for element in elements: for element in elements:
element.draw(scale=10**(joy[1]*0.05), reference=elements[reference].mecha.pos, size=screen.get_size()) element.draw(screen, scale=10**(joy[1]*0.05), reference=elements[reference].mecha.pos, size=screen.get_size())
pygame.display.flip() pygame.display.flip()
# for element in elements: # for element in elements:
# element.apply(camera=camera, origin=origin) # element.apply(camera=camera, origin=origin)