/web/socket.js~
/web/test.html~
/web/test.js~
+/server/game.js~
+/server/node_modules/*
+server/node_modules/*
+/server/gamestate.js~
+/server/matchmaker.js~
+/server/player.js~
+++ /dev/null
-
-
-import asyncio
-import websockets
-import threading
-
-
-async def getconnection(websocket, path):
-
-
+++ /dev/null
-
-
-SPF = 0.5 # half second for testing purposes
-# MS_PER_FRAME = 67 # 15 fps?
-
-
-import threading
-
-# not a (subclass of) thread, all this has to be is a timer that calls itself or whatever, hope it doesn't take too long to run or whatever
-
-import gamestate
-
-class Game():
- def __init__(self, players):
- self.players = players
- self.game_state = gamestate.GameState()
- for player in self.players: # CAUTION HERE, MIGHT NEED TO MODIFY
- player.run()
- def run(self):
- threading.Timer(SPF, self.run).start()
- # okay, things to do here:
- # check all the inputs in the player classes
- # update global game state
- # send data to players
- inputs = []
- for idx, val in enumerate(self.players):
- inputs.append(val.get_status())
- self.game_state.update_state(inputs)
- self.game_state.advance_frame()
- state = self.game_state.get_state()
- for player in self.players:
- player.send_data(state)
- print(state)
+++ /dev/null
-
-
-class GameState():
- def __init__(self):
- self.inputs = []
- def update_state(self, inputs):
- self.inputs = inputs
- def get_state(self):
- return ''.join(self.inputs)
- def advance_frame(self):
- pass
-
+++ /dev/null
-
-
-
-import matchmaker
-
-
-
-if __name__ == "__main__":
- mm = matchmaker.Matchmaker()
+++ /dev/null
-
-WS_HOST = 'localhost'
-WS_PORT = 6789
-NUM_PLAYERS = 4
-
-import asyncio
-import websockets
-import threading
-
-import logging
-
-logger = logging.getLogger('websockets')
-logger.setLevel(logging.INFO)
-logger.addHandler(logging.StreamHandler())
-
-import player
-import game
-
-class Matchmaker():
- def manage_incoming(self,websocket, path):
- # init a player, etc etc
- new_player = player.Player(websocket)
- self.players.append(new_player)
- if len(self.players) > (NUM_PLAYERS - 1): # shenanigans to fix potential problem of stranding some (n+1)th player
- with self.lock:
- new_game = game.Game(self.players[:NUM_PLAYERS])
- new_game.run()
- self.players = self.players[NUM_PLAYERS:]
- print("did it")
- def __init__(self):
- # todo: this is where I initialise the listening stuff for websockets, where I pass manage_incoming (or whatev) to the thing
- self.players = []
- self.lock = threading.Lock()
- async def manager(ws,p):
- self.manage_incoming(ws,p)
- start_server = websockets.serve(manager,WS_HOST,WS_PORT)
- asyncio.get_event_loop().run_until_complete(start_server)
- asyncio.get_event_loop().run_forever()
--- /dev/null
+
+
+import asyncio
+import websockets
+import threading
+
+
+async def getconnection(websocket, path):
+
+
-import websockets
+
+SPF = 0.5 # half second for testing purposes
+# MS_PER_FRAME = 67 # 15 fps?
+
+
import threading
-class GamePlayer(threading.Thread):
+# not a (subclass of) thread, all this has to be is a timer that calls itself or whatever, hope it doesn't take too long to run or whatever
+
+import gamestate
+
+class Game():
def __init__(self, players):
- threading.Thread.__init__()
self.players = players
+ self.game_state = gamestate.GameState()
+ for player in self.players: # CAUTION HERE, MIGHT NEED TO MODIFY
+ player.run()
def run(self):
- print("starting a thread or whatever: " + name)
+ threading.Timer(SPF, self.run).start()
+ # okay, things to do here:
+ # check all the inputs in the player classes
+ # update global game state
+ # send data to players
+ inputs = []
+ for idx, val in enumerate(self.players):
+ inputs.append(val.get_status())
+ self.game_state.update_state(inputs)
+ self.game_state.advance_frame()
+ state = self.game_state.get_state()
+ for player in self.players:
+ player.send_data(state)
+ print(state)
--- /dev/null
+
+
+class GameState():
+ def __init__(self):
+ self.inputs = []
+ def update_state(self, inputs):
+ self.inputs = inputs
+ def get_state(self):
+ return ''.join(self.inputs)
+ def advance_frame(self):
+ pass
+
--- /dev/null
+
+
+
+import matchmaker
+
+
+
+if __name__ == "__main__":
+ mm = matchmaker.Matchmaker()
+WS_HOST = 'localhost'
+WS_PORT = 6789
+NUM_PLAYERS = 4
+
import asyncio
import websockets
import threading
-import pbr_constants
+import logging
+
+logger = logging.getLogger('websockets')
+logger.setLevel(logging.INFO)
+logger.addHandler(logging.StreamHandler())
+
+import player
+import game
class Matchmaker():
+ def manage_incoming(self,websocket, path):
+ # init a player, etc etc
+ new_player = player.Player(websocket)
+ self.players.append(new_player)
+ if len(self.players) > (NUM_PLAYERS - 1): # shenanigans to fix potential problem of stranding some (n+1)th player
+ with self.lock:
+ new_game = game.Game(self.players[:NUM_PLAYERS])
+ new_game.run()
+ self.players = self.players[NUM_PLAYERS:]
+ print("did it")
def __init__(self):
- self.lock = threading.Lock()
+ # todo: this is where I initialise the listening stuff for websockets, where I pass manage_incoming (or whatev) to the thing
self.players = []
- async def get_game(self,p):
- with self.lock:
- self.players.append(p)
- if len(self.players) ==pbr_constants.num_players:
- self.new_game()
- def new_game(self):
- with self.lock:
- print(self.players)
-
- self.players = []
-
-
-
-
-
-
-
-if __name__=="__main__":
- mm = Matchmaker()
+ self.lock = threading.Lock()
+ async def manager(ws,p):
+ self.manage_incoming(ws,p)
+ start_server = websockets.serve(manager,WS_HOST,WS_PORT)
+ asyncio.get_event_loop().run_until_complete(start_server)
+ asyncio.get_event_loop().run_forever()
--- /dev/null
+
+
+import asyncio
+import websockets
+import threading
+
+# planning:
+# I think I can properly initialise the async websocket stuff in the init method, then the other methods will probably be fine? There may be problems with send_data and asyncio stuff, but get_status is definitely fine as-is
+class Player():
+ def __init__(self, socket):
+ self.socket = socket
+ self.status = 'x'
+ self.status_lock = threading.Lock()
+ def send_data(self, data):
+ # to be used by the game thread thingy
+ asyncio.run(self.socket.send(data))
+ def get_status(self):
+ with self.status_lock:
+ stat = self.status
+ self.status = 'x'
+ return stat
+++ /dev/null
-
-
-import asyncio
-import websockets
-import threading
-
-# planning:
-# I think I can properly initialise the async websocket stuff in the init method, then the other methods will probably be fine? There may be problems with send_data and asyncio stuff, but get_status is definitely fine as-is
-class Player():
- def __init__(self, socket):
- self.socket = socket
- self.status = 'x'
- self.status_lock = threading.Lock()
- def send_data(self, data):
- # to be used by the game thread thingy
- asyncio.run(self.socket.send(data))
- def get_status(self):
- with self.status_lock:
- stat = self.status
- self.status = 'x'
- return stat
--- /dev/null
+
+const GameState = require('./gamestate.js');
+
+function Game(players) {
+ this.players = players;
+ this.state = new GameState();
+ this.timeout = null;
+}
+
+Game.prototype.start = function(ms) {
+ this.timeout = setInterval(this.getNextFrame, ms);
+}
+
+Game.prototype.getNextFrame = function() {
+ //
+ var inputs = this.players.map(function(p) {return p.get_status();});
+ this.state.updateState(inputs);
+ var state = this.state.getState();
+ for(var i=0; i<this.players.length;i++) {
+ this.players[i].socket.send(i.toString() + ", " + state);
+ }
+}
+
+
+module.exports = Game;
--- /dev/null
+
+function GameState() {
+ this.inputs = [];
+}
+
+GameState.prototype.update = function(inputs) {
+ this.inputs = inputs;
+ // TODO: all of the rest of this
+}
+GameState.prototype.getState = function() {
+ // returns a string suitable to be broadcast to all the players
+ return this.inputs.join("");
+}
+
+module.exports = GameState;
--- /dev/null
+
+const WS_PORT = 6789;
+const NUM_PLAYERS = 3;
+const MS_PER_FRAME = 500;
+
+const WebSocket = require('ws');
+
+const wss = WebSocket.Server({port: WS_PORT});
+
+const Player = require('./player.js');
+const Game = require('./game.js');
+
+players = [];
+
+
+wss.on('connection', manage_incoming);
+
+
+var manage_incoming = function(ws) {
+ var new_player = new Player(ws);
+ players.push(new_player);
+ if(players.length > NUM_PLAYERS) {
+ // is the slicing necessary? I'm not sure I understand js's mechanisms without threads
+ game = new Game(players.slice(0, NUM_PLAYERS));
+ //
+ game.start(MS_PER_FRAME);
+ //
+ players = players.slice(NUM_PLAYERS);
+ }
+}
--- /dev/null
+{
+ "requires": true,
+ "lockfileVersion": 1,
+ "dependencies": {
+ "async-limiter": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz",
+ "integrity": "sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg=="
+ },
+ "ws": {
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz",
+ "integrity": "sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==",
+ "requires": {
+ "async-limiter": "~1.0.0"
+ }
+ }
+ }
+}
--- /dev/null
+
+
+function Player(ws) {
+ this.status = 'x';
+ this.socket = ws;
+ this.socket.onmessage = this.listener;
+}
+
+Player.prototype.listener = function(msg) {
+ var data = msg.data;
+ if(typeof data == "string" && data.length > 0) {
+ if(data[0] == 'u')
+ this.status = 'u';
+ else if(data[0] == 'd')
+ this.status = 'd';
+ else
+ this.status = 'x';
+ }
+}
+
+Player.prototype.send_data = function(data) {
+ if(this.socket.readyState==1) { // TODO: replace the '1' with the proper identifier (the ready state constant)
+ this.socket.send(data);
+ }
+}
+
+Player.prototype.get_status = function() {
+ var stat = this.status;
+ this.status = 'x';
+ return stat;
+}
+
+
+module.exports = Player;