Skip to content

Commit 0a60869

Browse files
committed
Добавлен пример онлайн игры
1 parent 54c822e commit 0a60869

File tree

3 files changed

+381
-0
lines changed

3 files changed

+381
-0
lines changed
Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
use "std"
2+
use "canvas"
3+
use "socket"
4+
5+
/// --- PIPES CELL ---
6+
CELL_START = 0
7+
HORIZONTAL = 0
8+
VERTICAL = 1
9+
LEFT_TO_DOWN = 2
10+
LEFT_TO_UP = 3
11+
RIGHT_TO_UP = 4
12+
RIGHT_TO_DOWN = 5
13+
CROSS = 6
14+
CELL_LAST = 6
15+
16+
Cells = [
17+
{"index": HORIZONTAL, "next": VERTICAL},
18+
{"index": VERTICAL, "next": HORIZONTAL},
19+
{"index": LEFT_TO_DOWN, "next": LEFT_TO_UP},
20+
{"index": LEFT_TO_UP, "next": RIGHT_TO_UP},
21+
{"index": RIGHT_TO_UP, "next": RIGHT_TO_DOWN},
22+
{"index": RIGHT_TO_DOWN, "next": LEFT_TO_DOWN},
23+
{"index": CROSS, "next": CROSS}
24+
];
25+
26+
27+
def draw(v, cellSize) {
28+
c2 = cellSize / 2
29+
match v {
30+
case HORIZONTAL : fillRect(0, c2 - 2, cellSize, 4)
31+
case VERTICAL : fillRect(c2 - 2, 0, 4, cellSize)
32+
case LEFT_TO_DOWN : {
33+
fillRect(0, c2 - 2, c2, 4)
34+
fillRect(c2 - 2, c2 - 2, 4, c2 + 2)
35+
}
36+
case LEFT_TO_UP : {
37+
fillRect(0, c2 - 2, c2, 4)
38+
fillRect(c2 - 2, 0, 4, c2 + 2)
39+
}
40+
case RIGHT_TO_UP : {
41+
fillRect(c2 - 2, c2 - 2, c2 + 2, 4)
42+
fillRect(c2 - 2, 0, 4, c2 + 2)
43+
}
44+
case RIGHT_TO_DOWN : {
45+
fillRect(c2 - 2, c2 - 2, c2 + 2, 4)
46+
fillRect(c2 - 2, c2 - 2, 4, c2 + 2)
47+
}
48+
case CROSS : {
49+
fillRect(c2 - 2, 0, 4, cellSize)
50+
fillRect(0, c2 - 2, cellSize, 4)
51+
}
52+
}
53+
}
54+
55+
56+
/// --- PIPES BOARD ---
57+
SIZE = 10
58+
59+
// Creating game board
60+
board = newarray(SIZE, SIZE)
61+
boardGhost = newarray(SIZE, SIZE)
62+
63+
def switchCell(x, y) {
64+
board[x][y] = Cells[board[x][y]].next
65+
}
66+
def setGhostCell(x, y) {
67+
boardGhost[x][y] = Cells[boardGhost[x][y]].next
68+
}
69+
70+
71+
/// --- PIPES MAIN ---
72+
translateX = 0 translateY = 0
73+
isGameFinished = false
74+
isWin = false
75+
76+
/* frect with translate ability */
77+
def fillRect(x,y,w,h) {
78+
frect(translateX+x, translateY+y, w, h)
79+
}
80+
81+
WIDTH = 320 HEIGHT = 320
82+
WINDOW_WIDTH = WIDTH * 2
83+
window("Pipes Online", WINDOW_WIDTH, HEIGHT)
84+
cellSize = WIDTH / SIZE
85+
86+
// cursor
87+
curX = 0 curY = 0
88+
curGhostX = 0 curGhostY = 0
89+
90+
// Initialize client
91+
socket = newSocket("http://localhost:6469")
92+
socket.on("gameStart", def(data) {
93+
data = data[0]
94+
for i=0, i<SIZE, i++
95+
for j=0, j<SIZE, j++
96+
boardGhost[i][j] = board[i][j] = data[i][j]
97+
thread(::gameLoop)
98+
})
99+
.on("updateGhostCell", def(data) {
100+
data = data[0]
101+
setGhostCell(data.x, data.y);
102+
})
103+
.on("updateGhostCursor", def(data) {
104+
data = data[0]
105+
curGhostX = data.x
106+
curGhostY = data.y
107+
})
108+
.on("gameFinished", def(data) {
109+
isGameFinished = true
110+
isWin = data[0]
111+
})
112+
socket.connect()
113+
114+
def gameLoop() {
115+
run = 1
116+
while run {
117+
key = keypressed()
118+
if (!isGameFinished) {
119+
if (key == VK_LEFT && curX > 0) {
120+
curX--
121+
socket.emit("updateCursor", {"x": curX, "y": curY})
122+
} else if (key == VK_RIGHT && curX < SIZE - 1) {
123+
curX++
124+
socket.emit("updateCursor", {"x": curX, "y": curY})
125+
} else if (key == VK_UP && curY > 0) {
126+
curY--
127+
socket.emit("updateCursor", {"x": curX, "y": curY})
128+
} else if (key == VK_DOWN && curY < SIZE - 1) {
129+
curY++
130+
socket.emit("updateCursor", {"x": curX, "y": curY})
131+
} else if (key == VK_FIRE) {
132+
switchCell(curX, curY)
133+
socket.emit("switchCell", {"x": curX, "y": curY})
134+
}
135+
else if (key == 48) run = 0
136+
}
137+
138+
// background
139+
color(isGameFinished ? (isWin ? #66FF66 : #FF6666) : #FFFFFF)
140+
frect(0, 0, WIDTH, HEIGHT)
141+
color(isGameFinished ? (!isWin ? #66FF66 : #FF6666) : #DDDDDD)
142+
frect(WIDTH, 0, WIDTH, HEIGHT)
143+
// cursor
144+
color(#4444FF)
145+
frect(curX*cellSize, curY*cellSize, cellSize, cellSize)
146+
color(#4040DD)
147+
frect(WIDTH + curGhostX*cellSize, curGhostY*cellSize, cellSize, cellSize)
148+
for (i=0, i<SIZE, i++) {
149+
color(0)
150+
ic = i*cellSize
151+
// ourrent board
152+
line(0, ic, cellSize*SIZE, ic)
153+
line(ic, 0, ic, cellSize*SIZE)
154+
// ghost board
155+
line(WIDTH, ic, WIDTH + cellSize*SIZE, ic)
156+
line(WIDTH + ic, 0, WIDTH + ic, cellSize*SIZE)
157+
color(#FF0000)
158+
for j=0, j<SIZE, j++ {
159+
translateX = ic
160+
translateY = j*cellSize
161+
draw(board[i][j], cellSize)
162+
translateX = -ic
163+
translateY = -j*cellSize
164+
// ghost cells
165+
translateX = WIDTH + ic
166+
translateY = j*cellSize
167+
draw(boardGhost[i][j], cellSize)
168+
translateX = - WIDTH - ic
169+
translateY = -j*cellSize
170+
}
171+
}
172+
repaint()
173+
sleep(50)
174+
}
175+
socket.disconnect()
176+
}
Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
var app = require('express')();
2+
var server = require('http').Server(app);
3+
var io = require('socket.io')(server);
4+
5+
server.listen(6469, function () {
6+
console.log("Server is now running...");
7+
});
8+
9+
var SIZE = 10;
10+
var CELL_START = 0;
11+
var HORIZONTAL = 0;
12+
var VERTICAL = 1;
13+
var LEFT_TO_DOWN = 2;
14+
var LEFT_TO_UP = 3;
15+
var RIGHT_TO_UP = 4;
16+
var RIGHT_TO_DOWN = 5;
17+
var CROSS = 6;
18+
var CELL_LAST = 6;
19+
20+
var Cells = [
21+
{support: [1, 1, 0, 0], index: HORIZONTAL, next: VERTICAL},
22+
{support: [0, 0, 1, 1], index: VERTICAL, next: HORIZONTAL},
23+
{support: [1, 0, 0, 1], index: LEFT_TO_DOWN, next: LEFT_TO_UP},
24+
{support: [1, 0, 1, 0], index: LEFT_TO_UP, next: RIGHT_TO_UP},
25+
{support: [0, 1, 1, 0], index: RIGHT_TO_UP, next: RIGHT_TO_DOWN},
26+
{support: [0, 1, 0, 1], index: RIGHT_TO_DOWN, next: LEFT_TO_DOWN},
27+
{support: [1, 1, 1, 1], index: CROSS, next: CROSS}
28+
];
29+
function supportLeft(v) { return Cells[v].support[0]; };
30+
function supportRight(v) { return Cells[v].support[1]; };
31+
function supportUp(v) { return Cells[v].support[2]; };
32+
function supportDown(v) { return Cells[v].support[3]; };
33+
34+
function create2DArray(size, value) {
35+
var result = new Array(size);
36+
for (var i = 0; i < size; i++) {
37+
result[i] = new Array(size);
38+
for (var j = 0; j < size; j++)
39+
result[i][j] = value;
40+
}
41+
return result;
42+
}
43+
44+
var Board = function (size) {
45+
var self = {};
46+
47+
self.board1 = create2DArray(size, CELL_START);
48+
self.board2 = create2DArray(size, CELL_START);
49+
50+
self.create = function () {
51+
for (var i = 0; i < size; i++) {
52+
for (var j = 0; j < size; j++) {
53+
var cell = Math.floor(Math.random() * CELL_LAST + 1);
54+
self.board1[i][j] = cell;
55+
self.board2[i][j] = cell;
56+
}
57+
}
58+
};
59+
60+
self.switchCell = function (x, y, isGhost) {
61+
if (isGhost)
62+
self.board2[x][y] = Cells[self.board2[x][y]].next;
63+
else
64+
self.board1[x][y] = Cells[self.board1[x][y]].next;
65+
};
66+
67+
var isConnected = function (board, curX, curY, visited) {
68+
// If it is a last cell - game is finished
69+
if ( (curX === SIZE - 1) && (curY === SIZE - 1) ) return true;
70+
71+
// Already visited - exit
72+
if (visited[curX][curY]) return false;
73+
// Mark visited
74+
visited[curX][curY] = true;
75+
// Check pipes matching
76+
var current = board[curX][curY];
77+
if ( supportLeft(current) && (curX > 0) && (supportRight(board[curX - 1][curY])) ) {
78+
if (isConnected(board, curX - 1, curY, visited)) return true;
79+
}
80+
if ( supportRight(current) && (curX < SIZE - 1) && (supportLeft(board[curX + 1][curY])) ) {
81+
if (isConnected(board, curX + 1, curY, visited)) return true;
82+
}
83+
if ( supportUp(current) && (curY > 0) && (supportDown(board[curX][curY - 1])) ) {
84+
if (isConnected(board, curX, curY - 1, visited)) return true;
85+
}
86+
if ( supportDown(current) && (curY < SIZE - 1) && (supportUp(board[curX][curY + 1])) ) {
87+
if (isConnected(board, curX, curY + 1, visited)) return true;
88+
}
89+
return false;
90+
};
91+
92+
var isFinished = function(board) {
93+
// Start pipe must have left touchpoint
94+
if (!supportLeft(board[0][0])) return false;
95+
// Finish pipe - right touchpoint
96+
if (!supportRight(board[SIZE - 1][SIZE - 1])) return false;
97+
98+
var visited = new Array(SIZE);
99+
for (var i = 0; i < SIZE; i++) {
100+
visited[i] = new Array(SIZE);
101+
for (var j = 0; j < SIZE; j++) visited[i][j] = false;
102+
}
103+
// Recursive traversal from left upper pipe
104+
return isConnected(board, 0, 0, visited);
105+
};
106+
107+
self.isGameFinished = function (isGhost) {
108+
return isFinished(isGhost ? self.board2 : self.board1);
109+
};
110+
111+
return self;
112+
};
113+
114+
var board = {};
115+
var players = [];
116+
117+
io.on('connection', function (socket) {
118+
if (players.length >= 2) {
119+
console.log('Sorry, server is full.');
120+
return;
121+
}
122+
123+
socket.playerId = players.length + 1;
124+
players.push({socket: socket});
125+
console.log('Player ' + socket.playerId + ' Connected!');
126+
127+
socket.on('switchCell', function (data) {
128+
var isGhost = socket.playerId === 2;
129+
var current = isGhost ? 1 : 0;
130+
var opposite = isGhost ? 0 : 1;
131+
board.switchCell(data.x, data.y, isGhost);
132+
players[opposite].socket.emit('updateGhostCell', data);
133+
if (board.isGameFinished(isGhost)) {
134+
players[current].socket.emit('gameFinished', true);
135+
players[opposite].socket.emit('gameFinished', false);
136+
} else if (board.isGameFinished(!isGhost)) {
137+
players[opposite].socket.emit('gameFinished', true);
138+
players[current].socket.emit('gameFinished', false);
139+
}
140+
});
141+
socket.on('updateCursor', function (data) {
142+
var isGhost = socket.playerId === 2;
143+
var opposite = isGhost ? 0 : 1;
144+
players[opposite].socket.emit('updateGhostCursor', data);
145+
});
146+
socket.on('connect_timeout', function (exception) {
147+
console.log('SOCKET TIMEOUT ' + exception);
148+
socket.destroy();
149+
});
150+
socket.on('disconnect', function () {
151+
console.log('disconnect Player ' + socket.playerId);
152+
players.splice(socket.playerId - 1, 1);
153+
});
154+
155+
// start game
156+
if (players.length === 2) {
157+
board = Board(SIZE);
158+
board.create();
159+
160+
players[0].socket.emit('gameStart', board.board1);
161+
players[1].socket.emit('gameStart', board.board2);
162+
}
163+
});
164+
165+
/*io.on('connection', function(socket) {
166+
console.log('New connection');
167+
socket.on('greetings', function(data) {
168+
console.log('Got greetings from client');
169+
socket.emit('pong', "Hello from server");
170+
});
171+
socket.on('complex_object', function(data) {
172+
console.log('Got object: ' + data);
173+
socket.emit('complex_object', {key1: data.key2, key2: data.key1, arr: [0,1,2,"34"]});
174+
});
175+
});*/
176+
/*io.on('connection', function(socket) {
177+
console.log('New connection');
178+
socket.emit('pong', "Hello");
179+
180+
socket.on('ping', function(data) {
181+
console.log('Got ping from client');
182+
socket.emit('pong', "Hello from server, " + data);
183+
});
184+
socket.on('pong', function(data) {
185+
console.log('Got pong from client');
186+
console.log('pong');
187+
});
188+
});*/
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"name": "TestSocketIOServer",
3+
"version": "1.0.0",
4+
"keywords": [
5+
"util",
6+
"functional",
7+
"server",
8+
"client",
9+
"browser"
10+
],
11+
"author": "aNNiMON",
12+
"contributors": [],
13+
"dependencies": {
14+
"express": "^4.13.4",
15+
"socket.io": "^1.4.5"
16+
}
17+
}

0 commit comments

Comments
 (0)