repl.it
Nodejs

One life. One shot. Survive!

fork
loading
Files
  • index.js
  • public
  • shot_controller.js
  • Packager files
  • package.json
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
const express = require('express');
const socket = require('socket.io');

// Local modules
const ShotController = require('./shot_controller');

// Local modules shared with client
const config = require('./public/game/js/config');
const getShipName = require('./public/game/js/names');

// Setup webfile server
var app = express();
app.use(express.static('public'));

// Setup websocket server
var server = app.listen(3000, () => {
	console.log('Game server server listening on port 3000');
});

// Setup websockets
var io = socket(server);

io.on('connect', socket => {
	console.log(socket.id + ' connected!');
	io.emit(
		'commsMessage',
		getShipName(socket.id.substring(0, 3)) + 'entered the sector. '
	);

	socket.on('shot', data => {
		shotsList.push(new ShotController(data.x, data.y, data.a, data.id));
	});

	socket.on('playerSync', data => {
    if (data.shots > 1) {
      data.shots = 1
    }
		shipsList[socket.id] = data;
	});

	socket.on('suicide', () => {
		io.emit(
			'commsMessage',
			getShipName(socket.id.substring(0, 3)) + 'suicided. '
		);
		io.emit('die', { id: socket.id, killerId: '*' }); //Not base64 char * indicates suicide

		if (shipsList[socket.id]) shipsList[socket.id].alive = false;
	});

	socket.on('disconnect', () => {
		console.log(socket.id + ' disconnected!');

		if (shipsList[socket.id]) {
			if (!shipsList[socket.id].alive)
				io.emit(
					'commsMessage',
					getShipName(socket.id.substring(0, 3)) + 'exited the sector. '
				);

			shipsList[socket.id].alive = false; // queue ship for removal
		}
	});
});

// Main game code etc

var shipsList = {};
var shotsList = [];
var powerupsList = [];

var gameInterval, start, delta;
function gameLoop() {
	// track time since last call to ensure consistency
	let now = Date.now();
	delta = start !== undefined ? now - start : config.syncInterval;
	start = now;

	// Update shots
	for (let shotId in shotsList) {
		let shot = shotsList[shotId];
		shot.tick(delta);
		if (!shot.alive) {
			shotsList.splice(shotId, 1);
		}
	}

	// Randomly generate powerup. Generate none if no players and scale amout proportinally if many players
	if (Math.floor((Math.random() * 1) / (config.powerupChance)) === 0) {
		powerupsList.push({
			x: Math.random() * config.world,
			y: Math.random() * config.world,
			alive: true,
      birthTime: Date.now()
		});
	}

	// Update powerups
	for (let powerupId in powerupsList) {
		let powerup = powerupsList[powerupId];
    // If powerup consumed or lived too longa
		if (!powerup.alive || Date.now() - powerup.birthTime > config.powerupLife * 1000) {
			powerupsList.splice(powerupId, 1);
		}
	}

	// Check ships
	for (let shipId in shipsList) {
		let ship = shipsList[shipId];

		// Check for nearby shots
		for (let shotId in shotsList) {
			let shot = shotsList[shotId];
			if (shot.checkNearby(ship.x, ship.y) && shot.ownerId !== ship.id) {
				io.emit(
					'commsMessage',
					ship.name +
						'was destroyed by ' +
						getShipName(shot.ownerId.substring(0, 3))
				);
				io.emit('die', {
					id: ship.id,
					killerId: shot.ownerId
				});

				shotsList[shotId].alive = false; // Queue shot for deletion
			}
		}

		// Check for nearby powerups
		for (let powerupId in powerupsList) {
			let powerup = powerupsList[powerupId];
			if (
				ShotController.prototype.checkNearby.call(powerup, ship.x, ship.y) &&
				ship.shots < 1
			) {
				// If powerup has hit ship
				io.emit('addShot', ship.id);

				powerupsList[powerupId].alive = false; // Queue powerup for deletion
			}
		}

		if (!ship.alive) {
			delete shipsList[shipId];
		}
	}

	// Find highscores
	let highscores = Object.keys(shipsList)
		.map(key => {
			// Extract relevant information
			return {
				id: shipsList[key].id,
				name: shipsList[key].name,
				t: Math.round((now - shipsList[key].birthTime) / 1000)
			};
		})
		.sort((a, b) => b.t - a.t) // sort in descending order by obj.t
		.slice(0, 5); // Use top 5

	// Transmit syncs
	io.emit('shotSync', shotsList);
	io.emit('powerupSync', powerupsList);
	io.emit('shipSync', shipsList);
	io.emit('highscoreSync', highscores);
}

setInterval(gameLoop, config.serverInterval);