mirror of
https://github.com/aNNiMON/Own-Programming-Language-Tutorial.git
synced 2024-09-20 08:44:20 +03:00
Добавлен пример онлайн игры
This commit is contained in:
parent
54c822e7d2
commit
0a6086949b
176
examples/game/pipes-online/pipes_online.own
Normal file
176
examples/game/pipes-online/pipes_online.own
Normal file
@ -0,0 +1,176 @@
|
|||||||
|
use "std"
|
||||||
|
use "canvas"
|
||||||
|
use "socket"
|
||||||
|
|
||||||
|
/// --- PIPES CELL ---
|
||||||
|
CELL_START = 0
|
||||||
|
HORIZONTAL = 0
|
||||||
|
VERTICAL = 1
|
||||||
|
LEFT_TO_DOWN = 2
|
||||||
|
LEFT_TO_UP = 3
|
||||||
|
RIGHT_TO_UP = 4
|
||||||
|
RIGHT_TO_DOWN = 5
|
||||||
|
CROSS = 6
|
||||||
|
CELL_LAST = 6
|
||||||
|
|
||||||
|
Cells = [
|
||||||
|
{"index": HORIZONTAL, "next": VERTICAL},
|
||||||
|
{"index": VERTICAL, "next": HORIZONTAL},
|
||||||
|
{"index": LEFT_TO_DOWN, "next": LEFT_TO_UP},
|
||||||
|
{"index": LEFT_TO_UP, "next": RIGHT_TO_UP},
|
||||||
|
{"index": RIGHT_TO_UP, "next": RIGHT_TO_DOWN},
|
||||||
|
{"index": RIGHT_TO_DOWN, "next": LEFT_TO_DOWN},
|
||||||
|
{"index": CROSS, "next": CROSS}
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
def draw(v, cellSize) {
|
||||||
|
c2 = cellSize / 2
|
||||||
|
match v {
|
||||||
|
case HORIZONTAL : fillRect(0, c2 - 2, cellSize, 4)
|
||||||
|
case VERTICAL : fillRect(c2 - 2, 0, 4, cellSize)
|
||||||
|
case LEFT_TO_DOWN : {
|
||||||
|
fillRect(0, c2 - 2, c2, 4)
|
||||||
|
fillRect(c2 - 2, c2 - 2, 4, c2 + 2)
|
||||||
|
}
|
||||||
|
case LEFT_TO_UP : {
|
||||||
|
fillRect(0, c2 - 2, c2, 4)
|
||||||
|
fillRect(c2 - 2, 0, 4, c2 + 2)
|
||||||
|
}
|
||||||
|
case RIGHT_TO_UP : {
|
||||||
|
fillRect(c2 - 2, c2 - 2, c2 + 2, 4)
|
||||||
|
fillRect(c2 - 2, 0, 4, c2 + 2)
|
||||||
|
}
|
||||||
|
case RIGHT_TO_DOWN : {
|
||||||
|
fillRect(c2 - 2, c2 - 2, c2 + 2, 4)
|
||||||
|
fillRect(c2 - 2, c2 - 2, 4, c2 + 2)
|
||||||
|
}
|
||||||
|
case CROSS : {
|
||||||
|
fillRect(c2 - 2, 0, 4, cellSize)
|
||||||
|
fillRect(0, c2 - 2, cellSize, 4)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// --- PIPES BOARD ---
|
||||||
|
SIZE = 10
|
||||||
|
|
||||||
|
// Creating game board
|
||||||
|
board = newarray(SIZE, SIZE)
|
||||||
|
boardGhost = newarray(SIZE, SIZE)
|
||||||
|
|
||||||
|
def switchCell(x, y) {
|
||||||
|
board[x][y] = Cells[board[x][y]].next
|
||||||
|
}
|
||||||
|
def setGhostCell(x, y) {
|
||||||
|
boardGhost[x][y] = Cells[boardGhost[x][y]].next
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// --- PIPES MAIN ---
|
||||||
|
translateX = 0 translateY = 0
|
||||||
|
isGameFinished = false
|
||||||
|
isWin = false
|
||||||
|
|
||||||
|
/* frect with translate ability */
|
||||||
|
def fillRect(x,y,w,h) {
|
||||||
|
frect(translateX+x, translateY+y, w, h)
|
||||||
|
}
|
||||||
|
|
||||||
|
WIDTH = 320 HEIGHT = 320
|
||||||
|
WINDOW_WIDTH = WIDTH * 2
|
||||||
|
window("Pipes Online", WINDOW_WIDTH, HEIGHT)
|
||||||
|
cellSize = WIDTH / SIZE
|
||||||
|
|
||||||
|
// cursor
|
||||||
|
curX = 0 curY = 0
|
||||||
|
curGhostX = 0 curGhostY = 0
|
||||||
|
|
||||||
|
// Initialize client
|
||||||
|
socket = newSocket("http://localhost:6469")
|
||||||
|
socket.on("gameStart", def(data) {
|
||||||
|
data = data[0]
|
||||||
|
for i=0, i<SIZE, i++
|
||||||
|
for j=0, j<SIZE, j++
|
||||||
|
boardGhost[i][j] = board[i][j] = data[i][j]
|
||||||
|
thread(::gameLoop)
|
||||||
|
})
|
||||||
|
.on("updateGhostCell", def(data) {
|
||||||
|
data = data[0]
|
||||||
|
setGhostCell(data.x, data.y);
|
||||||
|
})
|
||||||
|
.on("updateGhostCursor", def(data) {
|
||||||
|
data = data[0]
|
||||||
|
curGhostX = data.x
|
||||||
|
curGhostY = data.y
|
||||||
|
})
|
||||||
|
.on("gameFinished", def(data) {
|
||||||
|
isGameFinished = true
|
||||||
|
isWin = data[0]
|
||||||
|
})
|
||||||
|
socket.connect()
|
||||||
|
|
||||||
|
def gameLoop() {
|
||||||
|
run = 1
|
||||||
|
while run {
|
||||||
|
key = keypressed()
|
||||||
|
if (!isGameFinished) {
|
||||||
|
if (key == VK_LEFT && curX > 0) {
|
||||||
|
curX--
|
||||||
|
socket.emit("updateCursor", {"x": curX, "y": curY})
|
||||||
|
} else if (key == VK_RIGHT && curX < SIZE - 1) {
|
||||||
|
curX++
|
||||||
|
socket.emit("updateCursor", {"x": curX, "y": curY})
|
||||||
|
} else if (key == VK_UP && curY > 0) {
|
||||||
|
curY--
|
||||||
|
socket.emit("updateCursor", {"x": curX, "y": curY})
|
||||||
|
} else if (key == VK_DOWN && curY < SIZE - 1) {
|
||||||
|
curY++
|
||||||
|
socket.emit("updateCursor", {"x": curX, "y": curY})
|
||||||
|
} else if (key == VK_FIRE) {
|
||||||
|
switchCell(curX, curY)
|
||||||
|
socket.emit("switchCell", {"x": curX, "y": curY})
|
||||||
|
}
|
||||||
|
else if (key == 48) run = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// background
|
||||||
|
color(isGameFinished ? (isWin ? #66FF66 : #FF6666) : #FFFFFF)
|
||||||
|
frect(0, 0, WIDTH, HEIGHT)
|
||||||
|
color(isGameFinished ? (!isWin ? #66FF66 : #FF6666) : #DDDDDD)
|
||||||
|
frect(WIDTH, 0, WIDTH, HEIGHT)
|
||||||
|
// cursor
|
||||||
|
color(#4444FF)
|
||||||
|
frect(curX*cellSize, curY*cellSize, cellSize, cellSize)
|
||||||
|
color(#4040DD)
|
||||||
|
frect(WIDTH + curGhostX*cellSize, curGhostY*cellSize, cellSize, cellSize)
|
||||||
|
for (i=0, i<SIZE, i++) {
|
||||||
|
color(0)
|
||||||
|
ic = i*cellSize
|
||||||
|
// ourrent board
|
||||||
|
line(0, ic, cellSize*SIZE, ic)
|
||||||
|
line(ic, 0, ic, cellSize*SIZE)
|
||||||
|
// ghost board
|
||||||
|
line(WIDTH, ic, WIDTH + cellSize*SIZE, ic)
|
||||||
|
line(WIDTH + ic, 0, WIDTH + ic, cellSize*SIZE)
|
||||||
|
color(#FF0000)
|
||||||
|
for j=0, j<SIZE, j++ {
|
||||||
|
translateX = ic
|
||||||
|
translateY = j*cellSize
|
||||||
|
draw(board[i][j], cellSize)
|
||||||
|
translateX = -ic
|
||||||
|
translateY = -j*cellSize
|
||||||
|
// ghost cells
|
||||||
|
translateX = WIDTH + ic
|
||||||
|
translateY = j*cellSize
|
||||||
|
draw(boardGhost[i][j], cellSize)
|
||||||
|
translateX = - WIDTH - ic
|
||||||
|
translateY = -j*cellSize
|
||||||
|
}
|
||||||
|
}
|
||||||
|
repaint()
|
||||||
|
sleep(50)
|
||||||
|
}
|
||||||
|
socket.disconnect()
|
||||||
|
}
|
188
examples/game/pipes-online/server/main.js
Normal file
188
examples/game/pipes-online/server/main.js
Normal file
@ -0,0 +1,188 @@
|
|||||||
|
var app = require('express')();
|
||||||
|
var server = require('http').Server(app);
|
||||||
|
var io = require('socket.io')(server);
|
||||||
|
|
||||||
|
server.listen(6469, function () {
|
||||||
|
console.log("Server is now running...");
|
||||||
|
});
|
||||||
|
|
||||||
|
var SIZE = 10;
|
||||||
|
var CELL_START = 0;
|
||||||
|
var HORIZONTAL = 0;
|
||||||
|
var VERTICAL = 1;
|
||||||
|
var LEFT_TO_DOWN = 2;
|
||||||
|
var LEFT_TO_UP = 3;
|
||||||
|
var RIGHT_TO_UP = 4;
|
||||||
|
var RIGHT_TO_DOWN = 5;
|
||||||
|
var CROSS = 6;
|
||||||
|
var CELL_LAST = 6;
|
||||||
|
|
||||||
|
var Cells = [
|
||||||
|
{support: [1, 1, 0, 0], index: HORIZONTAL, next: VERTICAL},
|
||||||
|
{support: [0, 0, 1, 1], index: VERTICAL, next: HORIZONTAL},
|
||||||
|
{support: [1, 0, 0, 1], index: LEFT_TO_DOWN, next: LEFT_TO_UP},
|
||||||
|
{support: [1, 0, 1, 0], index: LEFT_TO_UP, next: RIGHT_TO_UP},
|
||||||
|
{support: [0, 1, 1, 0], index: RIGHT_TO_UP, next: RIGHT_TO_DOWN},
|
||||||
|
{support: [0, 1, 0, 1], index: RIGHT_TO_DOWN, next: LEFT_TO_DOWN},
|
||||||
|
{support: [1, 1, 1, 1], index: CROSS, next: CROSS}
|
||||||
|
];
|
||||||
|
function supportLeft(v) { return Cells[v].support[0]; };
|
||||||
|
function supportRight(v) { return Cells[v].support[1]; };
|
||||||
|
function supportUp(v) { return Cells[v].support[2]; };
|
||||||
|
function supportDown(v) { return Cells[v].support[3]; };
|
||||||
|
|
||||||
|
function create2DArray(size, value) {
|
||||||
|
var result = new Array(size);
|
||||||
|
for (var i = 0; i < size; i++) {
|
||||||
|
result[i] = new Array(size);
|
||||||
|
for (var j = 0; j < size; j++)
|
||||||
|
result[i][j] = value;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
var Board = function (size) {
|
||||||
|
var self = {};
|
||||||
|
|
||||||
|
self.board1 = create2DArray(size, CELL_START);
|
||||||
|
self.board2 = create2DArray(size, CELL_START);
|
||||||
|
|
||||||
|
self.create = function () {
|
||||||
|
for (var i = 0; i < size; i++) {
|
||||||
|
for (var j = 0; j < size; j++) {
|
||||||
|
var cell = Math.floor(Math.random() * CELL_LAST + 1);
|
||||||
|
self.board1[i][j] = cell;
|
||||||
|
self.board2[i][j] = cell;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
self.switchCell = function (x, y, isGhost) {
|
||||||
|
if (isGhost)
|
||||||
|
self.board2[x][y] = Cells[self.board2[x][y]].next;
|
||||||
|
else
|
||||||
|
self.board1[x][y] = Cells[self.board1[x][y]].next;
|
||||||
|
};
|
||||||
|
|
||||||
|
var isConnected = function (board, curX, curY, visited) {
|
||||||
|
// If it is a last cell - game is finished
|
||||||
|
if ( (curX === SIZE - 1) && (curY === SIZE - 1) ) return true;
|
||||||
|
|
||||||
|
// Already visited - exit
|
||||||
|
if (visited[curX][curY]) return false;
|
||||||
|
// Mark visited
|
||||||
|
visited[curX][curY] = true;
|
||||||
|
// Check pipes matching
|
||||||
|
var current = board[curX][curY];
|
||||||
|
if ( supportLeft(current) && (curX > 0) && (supportRight(board[curX - 1][curY])) ) {
|
||||||
|
if (isConnected(board, curX - 1, curY, visited)) return true;
|
||||||
|
}
|
||||||
|
if ( supportRight(current) && (curX < SIZE - 1) && (supportLeft(board[curX + 1][curY])) ) {
|
||||||
|
if (isConnected(board, curX + 1, curY, visited)) return true;
|
||||||
|
}
|
||||||
|
if ( supportUp(current) && (curY > 0) && (supportDown(board[curX][curY - 1])) ) {
|
||||||
|
if (isConnected(board, curX, curY - 1, visited)) return true;
|
||||||
|
}
|
||||||
|
if ( supportDown(current) && (curY < SIZE - 1) && (supportUp(board[curX][curY + 1])) ) {
|
||||||
|
if (isConnected(board, curX, curY + 1, visited)) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
var isFinished = function(board) {
|
||||||
|
// Start pipe must have left touchpoint
|
||||||
|
if (!supportLeft(board[0][0])) return false;
|
||||||
|
// Finish pipe - right touchpoint
|
||||||
|
if (!supportRight(board[SIZE - 1][SIZE - 1])) return false;
|
||||||
|
|
||||||
|
var visited = new Array(SIZE);
|
||||||
|
for (var i = 0; i < SIZE; i++) {
|
||||||
|
visited[i] = new Array(SIZE);
|
||||||
|
for (var j = 0; j < SIZE; j++) visited[i][j] = false;
|
||||||
|
}
|
||||||
|
// Recursive traversal from left upper pipe
|
||||||
|
return isConnected(board, 0, 0, visited);
|
||||||
|
};
|
||||||
|
|
||||||
|
self.isGameFinished = function (isGhost) {
|
||||||
|
return isFinished(isGhost ? self.board2 : self.board1);
|
||||||
|
};
|
||||||
|
|
||||||
|
return self;
|
||||||
|
};
|
||||||
|
|
||||||
|
var board = {};
|
||||||
|
var players = [];
|
||||||
|
|
||||||
|
io.on('connection', function (socket) {
|
||||||
|
if (players.length >= 2) {
|
||||||
|
console.log('Sorry, server is full.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
socket.playerId = players.length + 1;
|
||||||
|
players.push({socket: socket});
|
||||||
|
console.log('Player ' + socket.playerId + ' Connected!');
|
||||||
|
|
||||||
|
socket.on('switchCell', function (data) {
|
||||||
|
var isGhost = socket.playerId === 2;
|
||||||
|
var current = isGhost ? 1 : 0;
|
||||||
|
var opposite = isGhost ? 0 : 1;
|
||||||
|
board.switchCell(data.x, data.y, isGhost);
|
||||||
|
players[opposite].socket.emit('updateGhostCell', data);
|
||||||
|
if (board.isGameFinished(isGhost)) {
|
||||||
|
players[current].socket.emit('gameFinished', true);
|
||||||
|
players[opposite].socket.emit('gameFinished', false);
|
||||||
|
} else if (board.isGameFinished(!isGhost)) {
|
||||||
|
players[opposite].socket.emit('gameFinished', true);
|
||||||
|
players[current].socket.emit('gameFinished', false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
socket.on('updateCursor', function (data) {
|
||||||
|
var isGhost = socket.playerId === 2;
|
||||||
|
var opposite = isGhost ? 0 : 1;
|
||||||
|
players[opposite].socket.emit('updateGhostCursor', data);
|
||||||
|
});
|
||||||
|
socket.on('connect_timeout', function (exception) {
|
||||||
|
console.log('SOCKET TIMEOUT ' + exception);
|
||||||
|
socket.destroy();
|
||||||
|
});
|
||||||
|
socket.on('disconnect', function () {
|
||||||
|
console.log('disconnect Player ' + socket.playerId);
|
||||||
|
players.splice(socket.playerId - 1, 1);
|
||||||
|
});
|
||||||
|
|
||||||
|
// start game
|
||||||
|
if (players.length === 2) {
|
||||||
|
board = Board(SIZE);
|
||||||
|
board.create();
|
||||||
|
|
||||||
|
players[0].socket.emit('gameStart', board.board1);
|
||||||
|
players[1].socket.emit('gameStart', board.board2);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/*io.on('connection', function(socket) {
|
||||||
|
console.log('New connection');
|
||||||
|
socket.on('greetings', function(data) {
|
||||||
|
console.log('Got greetings from client');
|
||||||
|
socket.emit('pong', "Hello from server");
|
||||||
|
});
|
||||||
|
socket.on('complex_object', function(data) {
|
||||||
|
console.log('Got object: ' + data);
|
||||||
|
socket.emit('complex_object', {key1: data.key2, key2: data.key1, arr: [0,1,2,"34"]});
|
||||||
|
});
|
||||||
|
});*/
|
||||||
|
/*io.on('connection', function(socket) {
|
||||||
|
console.log('New connection');
|
||||||
|
socket.emit('pong', "Hello");
|
||||||
|
|
||||||
|
socket.on('ping', function(data) {
|
||||||
|
console.log('Got ping from client');
|
||||||
|
socket.emit('pong', "Hello from server, " + data);
|
||||||
|
});
|
||||||
|
socket.on('pong', function(data) {
|
||||||
|
console.log('Got pong from client');
|
||||||
|
console.log('pong');
|
||||||
|
});
|
||||||
|
});*/
|
17
examples/game/pipes-online/server/package.json
Normal file
17
examples/game/pipes-online/server/package.json
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"name": "TestSocketIOServer",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"keywords": [
|
||||||
|
"util",
|
||||||
|
"functional",
|
||||||
|
"server",
|
||||||
|
"client",
|
||||||
|
"browser"
|
||||||
|
],
|
||||||
|
"author": "aNNiMON",
|
||||||
|
"contributors": [],
|
||||||
|
"dependencies": {
|
||||||
|
"express": "^4.13.4",
|
||||||
|
"socket.io": "^1.4.5"
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user