-
-
Save PlainSight/5f324f9a215e72fb2539454c88ded5bc to your computer and use it in GitHub Desktop.
import pygame, sys | |
from pygame.locals import * | |
import pickle | |
import select | |
import socket | |
WIDTH = 400 | |
HEIGHT = 400 | |
BUFFERSIZE = 2048 | |
screen = pygame.display.set_mode((WIDTH, HEIGHT)) | |
pygame.display.set_caption('Game') | |
clock = pygame.time.Clock() | |
sprite1 = pygame.image.load('images/BlueThing/BlueThing_front.png') | |
sprite2 = pygame.image.load('images/Ladette/Ladette_front.png') | |
sprite3 = pygame.image.load('images/TrashPanda/TrashPanda_front.png') | |
sprite4 = pygame.image.load('images/Tubby/Tubby_front.png') | |
serverAddr = '127.0.0.1' | |
if len(sys.argv) == 2: | |
serverAddr = sys.argv[1] | |
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) | |
s.connect((serverAddr, 4321)) | |
playerid = 0 | |
sprites = { 0: sprite1, 1: sprite2, 2: sprite3, 3: sprite4 } | |
class Minion: | |
def __init__(self, x, y, id): | |
self.x = x | |
self.y = y | |
self.vx = 0 | |
self.vy = 0 | |
self.id = id | |
def update(self): | |
self.x += self.vx | |
self.y += self.vy | |
if self.x > WIDTH - 50: | |
self.x = WIDTH - 50 | |
if self.x < 0: | |
self.x = 0 | |
if self.y > HEIGHT - 50: | |
self.y = HEIGHT - 50 | |
if self.y < 0: | |
self.y = 0 | |
if self.id == 0: | |
self.id = playerid | |
def render(self): | |
screen.blit(sprites[self.id % 4], (self.x, self.y)) | |
#game events | |
#['event type', param1, param2] | |
# | |
#event types: | |
# id update | |
# ['id update', id] | |
# | |
# player locations | |
# ['player locations', [id, x, y], [id, x, y] ...] | |
#user commands | |
# position update | |
# ['position update', id, x, y] | |
class GameEvent: | |
def __init__(self, vx, vy): | |
self.vx = vx | |
self.vy = vy | |
cc = Minion(50, 50, 0) | |
minions = [] | |
while True: | |
ins, outs, ex = select.select([s], [], [], 0) | |
for inm in ins: | |
gameEvent = pickle.loads(inm.recv(BUFFERSIZE)) | |
if gameEvent[0] == 'id update': | |
playerid = gameEvent[1] | |
print(playerid) | |
if gameEvent[0] == 'player locations': | |
gameEvent.pop(0) | |
minions = [] | |
for minion in gameEvent: | |
if minion[0] != playerid: | |
minions.append(Minion(minion[1], minion[2], minion[0])) | |
for event in pygame.event.get(): | |
if event.type == QUIT: | |
pygame.quit() | |
sys.exit() | |
if event.type == KEYDOWN: | |
if event.key == K_LEFT: cc.vx = -10 | |
if event.key == K_RIGHT: cc.vx = 10 | |
if event.key == K_UP: cc.vy = -10 | |
if event.key == K_DOWN: cc.vy = 10 | |
if event.type == KEYUP: | |
if event.key == K_LEFT and cc.vx == -10: cc.vx = 0 | |
if event.key == K_RIGHT and cc.vx == 10: cc.vx = 0 | |
if event.key == K_UP and cc.vy == -10: cc.vy = 0 | |
if event.key == K_DOWN and cc.vy == 10: cc.vy = 0 | |
clock.tick(60) | |
screen.fill((255,255,255)) | |
cc.update() | |
for m in minions: | |
m.render() | |
cc.render() | |
pygame.display.flip() | |
ge = ['position update', playerid, cc.x, cc.y] | |
s.send(pickle.dumps(ge)) | |
s.close() |
import socket | |
import asyncore | |
import select | |
import random | |
import pickle | |
import time | |
BUFFERSIZE = 512 | |
outgoing = [] | |
class Minion: | |
def __init__(self, ownerid): | |
self.x = 50 | |
self.y = 50 | |
self.ownerid = ownerid | |
minionmap = {} | |
def updateWorld(message): | |
arr = pickle.loads(message) | |
print(str(arr)) | |
playerid = arr[1] | |
x = arr[2] | |
y = arr[3] | |
if playerid == 0: return | |
minionmap[playerid].x = x | |
minionmap[playerid].y = y | |
remove = [] | |
for i in outgoing: | |
update = ['player locations'] | |
for key, value in minionmap.items(): | |
update.append([value.ownerid, value.x, value.y]) | |
try: | |
i.send(pickle.dumps(update)) | |
except Exception: | |
remove.append(i) | |
continue | |
print ('sent update data') | |
for r in remove: | |
outgoing.remove(r) | |
class MainServer(asyncore.dispatcher): | |
def __init__(self, port): | |
asyncore.dispatcher.__init__(self) | |
self.create_socket(socket.AF_INET, socket.SOCK_STREAM) | |
self.bind(('', port)) | |
self.listen(10) | |
def handle_accept(self): | |
conn, addr = self.accept() | |
print ('Connection address:' + addr[0] + " " + str(addr[1])) | |
outgoing.append(conn) | |
playerid = random.randint(1000, 1000000) | |
playerminion = Minion(playerid) | |
minionmap[playerid] = playerminion | |
conn.send(pickle.dumps(['id update', playerid])) | |
SecondaryServer(conn) | |
class SecondaryServer(asyncore.dispatcher_with_send): | |
def handle_read(self): | |
recievedData = self.recv(BUFFERSIZE) | |
if recievedData: | |
updateWorld(recievedData) | |
else: self.close() | |
MainServer(4321) | |
asyncore.loop() |
Code + sprites lives here: https://github.com/PlainSight/pygameblog
This project is a complete toy btw, there's not much to see.
This server can not send more than 1 event, only position update works. I would send a reply to ping received from client, and it doesn't work.
if arr[0] == 'ping':
and so on, then I'm sending a reply using i.send(pickle.dumps(['pong', playerid])) and it does not work. Client does not receive it.
I had the same problem as zywek123.
The reason is that the server writes to the socket a second time before the client reads from the socket the first message. This means that the client reads multiple pickled objects at once and pickle.loads just returns the first object.
Fortunately concatenated pickled objects can be easily separated:
https://stackoverflow.com/a/61293678/7658204
When I run the app in the mac terminal on python 3.9.1, I get the error:
s.connect((serverAddr, 4321))
ConnectionRefusedError: [Errno 61] Connection refused
Is there a solution?
When I run the app in the mac terminal on python 3.9.1, I get the error:
s.connect((serverAddr, 4321)) ConnectionRefusedError: [Errno 61] Connection refused
Is there a solution?
You need to change the address to your local ip or your hoes machine name
Your program include sprites, problem, we don't have picture for sprites...