almost working for new version
This commit is contained in:
parent
acb1781a9f
commit
0040d7df1e
@ -1,199 +0,0 @@
|
|||||||
class GameServerConnection
|
|
||||||
{
|
|
||||||
constructor(ip, port)
|
|
||||||
{
|
|
||||||
this.ip = ip;
|
|
||||||
this.port = port;
|
|
||||||
this.player = null;
|
|
||||||
this.socket = null;
|
|
||||||
this.registered = false;
|
|
||||||
|
|
||||||
this.game_manager = null;
|
|
||||||
this.connected = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
set_player(p)
|
|
||||||
{
|
|
||||||
this.player = p;
|
|
||||||
}
|
|
||||||
|
|
||||||
set_game_manager(gm)
|
|
||||||
{
|
|
||||||
this.game_manager = gm;
|
|
||||||
}
|
|
||||||
|
|
||||||
is_registered()
|
|
||||||
{
|
|
||||||
return this.registered;
|
|
||||||
}
|
|
||||||
|
|
||||||
is_connected()
|
|
||||||
{
|
|
||||||
return this.connected;
|
|
||||||
}
|
|
||||||
|
|
||||||
on_open(callback_func)
|
|
||||||
{
|
|
||||||
// TODO
|
|
||||||
console.log("connected to " + this.ip + ":" + this.port);
|
|
||||||
this.connected = true;
|
|
||||||
callback_func();
|
|
||||||
}
|
|
||||||
|
|
||||||
on_close()
|
|
||||||
{
|
|
||||||
this.game_manager.end_game_listener()
|
|
||||||
}
|
|
||||||
|
|
||||||
on_error()
|
|
||||||
{
|
|
||||||
console.log("error in websocket connection");
|
|
||||||
this.game_manager.connection_error_listener();
|
|
||||||
}
|
|
||||||
|
|
||||||
on_message(event)
|
|
||||||
{
|
|
||||||
var json_msg = event.data;
|
|
||||||
var msg = JSON.parse(json_msg);
|
|
||||||
|
|
||||||
if (!msg.hasOwnProperty("type") || !msg.hasOwnProperty("data"))
|
|
||||||
{
|
|
||||||
console.log("received wrong formatted message");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch(msg.type)
|
|
||||||
{
|
|
||||||
case "register_response":
|
|
||||||
this.on_register_response(msg.data);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "game_starts":
|
|
||||||
this.on_game_starts(msg.data);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "move":
|
|
||||||
this.on_move(msg.data);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "move_response":
|
|
||||||
this.on_move_response(msg.data);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "end_game":
|
|
||||||
this.on_end_game(msg.data);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
on_register_response(data)
|
|
||||||
{
|
|
||||||
var success = data.success;
|
|
||||||
this.game_manager.register_response_listener(success);
|
|
||||||
|
|
||||||
if (!success)
|
|
||||||
{
|
|
||||||
this.socket.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
on_game_starts(data)
|
|
||||||
{
|
|
||||||
var op_name = data.opponent_name;
|
|
||||||
var is_first_move = data.is_first_move;
|
|
||||||
|
|
||||||
this.game_manager.start_game_listener(op_name, is_first_move);
|
|
||||||
}
|
|
||||||
|
|
||||||
on_move(data)
|
|
||||||
{
|
|
||||||
var sub_x = data.sub_x;
|
|
||||||
var sub_y = data.sub_y;
|
|
||||||
var x = data.x;
|
|
||||||
var y = data.y;
|
|
||||||
|
|
||||||
this.game_manager.move_listener(sub_x, sub_y, x, y);
|
|
||||||
}
|
|
||||||
|
|
||||||
on_move_response(data)
|
|
||||||
{
|
|
||||||
if (data.success)
|
|
||||||
{
|
|
||||||
console.log("move accepted");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
console.error("move not accepted");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
on_end_game(data)
|
|
||||||
{
|
|
||||||
this.game_manager.end_game_listener();
|
|
||||||
this.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
connect(callback_func)
|
|
||||||
{
|
|
||||||
this.socket = new WebSocket("wss://" + this.ip + ":" + this.port);
|
|
||||||
this.socket.onmessage = (e => this.on_message(e));
|
|
||||||
this.socket.onopen = (() => this.on_open(callback_func));
|
|
||||||
this.socket.onerror = (() => this.on_error());
|
|
||||||
this.socket.onclose = (() => this.on_close());
|
|
||||||
}
|
|
||||||
|
|
||||||
send_move(sub_x, sub_y, x, y)
|
|
||||||
{
|
|
||||||
var msg_object = {
|
|
||||||
type: "move",
|
|
||||||
data: {
|
|
||||||
sub_x: "" + sub_x,
|
|
||||||
sub_y: "" + sub_y,
|
|
||||||
x: "" + x,
|
|
||||||
y: "" + y
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
this.socket.send(JSON.stringify(msg_object));
|
|
||||||
}
|
|
||||||
|
|
||||||
register()
|
|
||||||
{
|
|
||||||
// register for game queue
|
|
||||||
var msg_object = {
|
|
||||||
type: "register",
|
|
||||||
data: {
|
|
||||||
id: this.player.get_id(),
|
|
||||||
name: this.player.get_name()
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
this.socket.send(JSON.stringify(msg_object));
|
|
||||||
}
|
|
||||||
|
|
||||||
send_disconnect()
|
|
||||||
{
|
|
||||||
if (!this.is_connected)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var msg_object = {
|
|
||||||
type: "end_game",
|
|
||||||
data: {
|
|
||||||
msg: ""
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
this.socket.send(JSON.stringify(msg_object));
|
|
||||||
}
|
|
||||||
|
|
||||||
close()
|
|
||||||
{
|
|
||||||
if (this.is_connected)
|
|
||||||
{
|
|
||||||
this.is_connected = false;
|
|
||||||
this.socket.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
31
grid.js
31
grid.js
@ -1,9 +1,9 @@
|
|||||||
class Grid
|
class Grid
|
||||||
{
|
{
|
||||||
constructor(n, grid_container_div, tile_width, tile_height, ground_color)
|
constructor(n, parent, tile_width, tile_height, ground_color)
|
||||||
{
|
{
|
||||||
this.n = n;
|
this.n = n;
|
||||||
this.grid_container_div = grid_container_div;
|
this.grid_container_div = null;
|
||||||
this.tile_width = tile_width;
|
this.tile_width = tile_width;
|
||||||
this.tile_height = tile_height;
|
this.tile_height = tile_height;
|
||||||
this.ground_color = ground_color;
|
this.ground_color = ground_color;
|
||||||
@ -11,6 +11,8 @@ class Grid
|
|||||||
this.won_player = null;
|
this.won_player = null;
|
||||||
this.n_complete_subgrids = 0;
|
this.n_complete_subgrids = 0;
|
||||||
|
|
||||||
|
this.parent = parent;
|
||||||
|
|
||||||
this.subgrids = []
|
this.subgrids = []
|
||||||
|
|
||||||
console.log("create grid of size " + this.n);
|
console.log("create grid of size " + this.n);
|
||||||
@ -20,6 +22,10 @@ class Grid
|
|||||||
|
|
||||||
create()
|
create()
|
||||||
{
|
{
|
||||||
|
this.grid_container_div = document.createElement("div");
|
||||||
|
this.grid_container_div.className = "grid-container";
|
||||||
|
this.parent.appendChild(this.grid_container_div);
|
||||||
|
|
||||||
var x,y;
|
var x,y;
|
||||||
for (y = 0; y < this.n; y++)
|
for (y = 0; y < this.n; y++)
|
||||||
{
|
{
|
||||||
@ -49,7 +55,10 @@ class Grid
|
|||||||
{
|
{
|
||||||
this.check_win(sub_x, sub_y, x, y);
|
this.check_win(sub_x, sub_y, x, y);
|
||||||
this.check_complete(sub_x, sub_y, x, y);
|
this.check_complete(sub_x, sub_y, x, y);
|
||||||
this.click_callback(sub_x, sub_y, x, y);
|
if (this.click_callback != null)
|
||||||
|
{
|
||||||
|
this.click_callback(sub_x, sub_y, x, y);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
player_change_listener(player)
|
player_change_listener(player)
|
||||||
@ -211,6 +220,22 @@ class Grid
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unblock_all_non_completed()
|
||||||
|
{
|
||||||
|
var x,y;
|
||||||
|
for (y = 0; y < this.n; y++)
|
||||||
|
{
|
||||||
|
for (x = 0; x < this.n; x++)
|
||||||
|
{
|
||||||
|
if (this.subgrids[y][x].is_won() || this.subgrids[y][x].is_draw())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
this.subgrids[y][x].unblock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
block(x,y)
|
block(x,y)
|
||||||
{
|
{
|
||||||
this.subgrids[y][x].block();
|
this.subgrids[y][x].block();
|
||||||
|
18
index.html
18
index.html
@ -8,23 +8,17 @@
|
|||||||
<title>ultimate tictactoe</title>
|
<title>ultimate tictactoe</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="main-container" class="main-container">
|
<div id="main-container" class="main-container"></div>
|
||||||
<div id="grid-container" class="grid-container"></div>
|
|
||||||
<div id="sidebar-container" class="sidebar-container">
|
|
||||||
<div id="create-game-container" class="create-game-container"></div>
|
|
||||||
<div id="setting-container" class="setting-container"></div>
|
|
||||||
<div id="control-container" class="control-container"></div>
|
|
||||||
<div id="info-container" class="info-container"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<script src="settings.js"></script>
|
<script src="settings.js"></script>
|
||||||
<script src="player.js"></script>
|
<script src="player.js"></script>
|
||||||
<script src="tile.js"></script>
|
<script src="tile.js"></script>
|
||||||
<script src="grid.js"></script>
|
<script src="grid.js"></script>
|
||||||
<script src="subgrid.js"></script>
|
<script src="subgrid.js"></script>
|
||||||
<script src="game_manager.js"></script>
|
<script src="local_match_manager.js"></script>
|
||||||
<script src="game_server_connection.js"></script>
|
<script src="online_match_manager.js"></script>
|
||||||
<script src="sidebar.js"></script>
|
<script src="websocket_connection.js"></script>
|
||||||
|
<script src="infobar.js"></script>
|
||||||
|
<script src="infocontainer.js"></script>
|
||||||
<script src="main.js"></script>
|
<script src="main.js"></script>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
|
15
infobar.js
Normal file
15
infobar.js
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
class Infobar
|
||||||
|
{
|
||||||
|
constructor(parent)
|
||||||
|
{
|
||||||
|
this.parent = parent;
|
||||||
|
this.container = document.createElement("div");
|
||||||
|
this.container.className = "infobar-container";
|
||||||
|
this.parent.appendChild(this.container);
|
||||||
|
}
|
||||||
|
|
||||||
|
create_infocontainer()
|
||||||
|
{
|
||||||
|
return new Infocontainer(this.container);
|
||||||
|
}
|
||||||
|
}
|
49
infocontainer.js
Normal file
49
infocontainer.js
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
class Infocontainer
|
||||||
|
{
|
||||||
|
constructor(parent)
|
||||||
|
{
|
||||||
|
this.parent = parent;
|
||||||
|
this.container = document.createElement("div");
|
||||||
|
this.container.className = "info-container";
|
||||||
|
this.parent.appendChild(this.container);
|
||||||
|
}
|
||||||
|
|
||||||
|
create_button(text)
|
||||||
|
{
|
||||||
|
var b = document.createElement("button");
|
||||||
|
b.className = "infobar-button";
|
||||||
|
b.appendChild(document.createTextNode(text));
|
||||||
|
this.container.appendChild(b)
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
create_input(placeholder, pw=false)
|
||||||
|
{
|
||||||
|
var i = document.createElement("input");
|
||||||
|
i.className = "infobar-input";
|
||||||
|
i.placeholder = placeholder;
|
||||||
|
i.type = pw ? "password" : "text";
|
||||||
|
|
||||||
|
this.container.appendChild(i);
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
create_label(text)
|
||||||
|
{
|
||||||
|
var l = document.createElement("label");
|
||||||
|
l.className = "infobar-label";
|
||||||
|
l.innerHTML = text;
|
||||||
|
this.container.appendChild(l);
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
|
||||||
|
hide()
|
||||||
|
{
|
||||||
|
this.container.style.display = "none";
|
||||||
|
}
|
||||||
|
|
||||||
|
show()
|
||||||
|
{
|
||||||
|
this.container.style.display = "inline-block";
|
||||||
|
}
|
||||||
|
}
|
69
local_match_manager.js
Normal file
69
local_match_manager.js
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
class LocalMatchManager
|
||||||
|
{
|
||||||
|
constructor(grid, status_label, control_container)
|
||||||
|
{
|
||||||
|
this.grid = grid;
|
||||||
|
this.status_label = status_label;
|
||||||
|
|
||||||
|
this.control_container = control_container;
|
||||||
|
|
||||||
|
this.control_container.show();
|
||||||
|
|
||||||
|
this.local_player_a = new Player("red player", 255,0,0);
|
||||||
|
this.local_player_b = new Player("green player", 0,255,0);
|
||||||
|
this.is_local_player_a = false;
|
||||||
|
|
||||||
|
this.grid.register_click_callback((i,j,k,l) => this.click_listener(i,j,k,l));
|
||||||
|
|
||||||
|
this.grid.deactivate_all();
|
||||||
|
this.grid.unblock_all();
|
||||||
|
|
||||||
|
|
||||||
|
this.toggle_local_player();
|
||||||
|
}
|
||||||
|
|
||||||
|
click_listener(sub_x, sub_y, x,y)
|
||||||
|
{
|
||||||
|
// check whether the game is over:
|
||||||
|
if (grid.is_won())
|
||||||
|
{
|
||||||
|
this.status_change_listener("" + grid.get_won_player().get_name() + " has won.", "Game Over")
|
||||||
|
this.end_game();
|
||||||
|
}
|
||||||
|
else if (grid.is_complete())
|
||||||
|
{
|
||||||
|
this.status_change_listener("Draw. Everybody looses!", "Game Over");
|
||||||
|
this.end_game();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.toggle_local_player();
|
||||||
|
this.grid.block_all()
|
||||||
|
if (this.grid.subgrids[y][x].is_draw() || this.grid.subgrids[y][x].is_won())
|
||||||
|
{
|
||||||
|
this.grid.unblock_all_non_completed();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.grid.subgrids[y][x].unblock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
toggle_local_player()
|
||||||
|
{
|
||||||
|
this.is_local_player_a = !this.is_local_player_a;
|
||||||
|
var next_player = this.is_local_player_a ? this.local_player_a : this.local_player_b;
|
||||||
|
|
||||||
|
this.status_label.innerHTML = "" + "it's " + next_player.get_name() + "'s turn...";
|
||||||
|
this.grid.player_change_listener(next_player);
|
||||||
|
}
|
||||||
|
|
||||||
|
end_game()
|
||||||
|
{
|
||||||
|
this.status_label.innerHTML = "Game Over. Game Closed";
|
||||||
|
this.grid.block_all();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
225
main.js
225
main.js
@ -3,16 +3,225 @@ var n = style.getPropertyValue("--tictactoe_n");
|
|||||||
var tilesize = style.getPropertyValue("--tile-size");
|
var tilesize = style.getPropertyValue("--tile-size");
|
||||||
var default_opacity = style.getPropertyValue("--opacity");
|
var default_opacity = style.getPropertyValue("--opacity");
|
||||||
var ground_color = style.getPropertyValue("--ground-color");
|
var ground_color = style.getPropertyValue("--ground-color");
|
||||||
|
var main_container = document.getElementById("main-container");
|
||||||
|
|
||||||
var create_game_container = document.getElementById("create-game-container");
|
|
||||||
var setting_container = document.getElementById("setting-container");
|
|
||||||
var control_container = document.getElementById("control-container");
|
|
||||||
var info_container = document.getElementById("info-container");
|
|
||||||
|
|
||||||
var grid = new Grid(n, document.getElementById("grid-container"), tilesize, tilesize, ground_color);
|
var main_menu = new Infobar(main_container);
|
||||||
var server_connection = new GameServerConnection(server_url, server_port);
|
var grid = new Grid(n, main_container, tilesize, tilesize, ground_color);
|
||||||
var game_manager = new GameManager(grid, server_connection);
|
var sub_menu = new Infobar(main_container);
|
||||||
var sidebar = new Sidebar(create_game_container, setting_container, control_container, info_container, game_manager);
|
|
||||||
|
|
||||||
|
// fill containers with buttons and containers:
|
||||||
|
|
||||||
|
// empty dummy container on top (to force other containers to be at the bottom)
|
||||||
|
dummy_main = main_menu.create_infocontainer();
|
||||||
|
dummy_sub = sub_menu.create_infocontainer();
|
||||||
|
|
||||||
|
// start container:
|
||||||
|
create_game_container = main_menu.create_infocontainer();
|
||||||
|
create_game_container.create_label("Start Local Game");
|
||||||
|
b_local_game = create_game_container.create_button("Local Game");
|
||||||
|
|
||||||
|
// register container:
|
||||||
|
register_container = main_menu.create_infocontainer();
|
||||||
|
register_container.create_label("Register or login to play online");
|
||||||
|
i_register_username = register_container.create_input("username");
|
||||||
|
i_register_pw = register_container.create_input("password", true);
|
||||||
|
b_register = register_container.create_button("register/login");
|
||||||
|
|
||||||
|
// logout:
|
||||||
|
logout_container = sub_menu.create_infocontainer();
|
||||||
|
l_username = logout_container.create_label("logged in as: ");
|
||||||
|
b_logout = logout_container.create_button("logout");
|
||||||
|
|
||||||
|
|
||||||
|
// match control
|
||||||
|
match_control = sub_menu.create_infocontainer();
|
||||||
|
b_end_game = match_control.create_button("End Game");
|
||||||
|
|
||||||
|
// fill subcontainer:
|
||||||
|
match_slot_container = sub_menu.create_infocontainer();
|
||||||
|
match_slot_container.create_label("online matches");
|
||||||
|
|
||||||
|
// search match:
|
||||||
|
search_match_container = main_menu.create_infocontainer();
|
||||||
|
search_match_container.create_label("Create Online Match");
|
||||||
|
b_match_search = search_match_container.create_button("random match");
|
||||||
|
search_match_container.create_label("<p> </p>");
|
||||||
|
|
||||||
|
l_match_op = search_match_container.create_input("player name");
|
||||||
|
b_match_invite = search_match_container.create_button("invite player");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//status:
|
||||||
|
status_container = main_menu.create_infocontainer();
|
||||||
|
l_status_head = status_container.create_label("status:");
|
||||||
|
l_status = status_container.create_label("...");
|
||||||
|
|
||||||
|
// global vars:
|
||||||
|
|
||||||
|
game_manager = null;
|
||||||
|
|
||||||
|
logged_in = false;
|
||||||
|
|
||||||
|
// connection stuff:
|
||||||
|
|
||||||
|
var connection = null;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// global funcs:
|
||||||
|
|
||||||
|
disable_all_containers = function()
|
||||||
|
{
|
||||||
|
create_game_container.hide();
|
||||||
|
register_container.hide();
|
||||||
|
logout_container.hide();
|
||||||
|
match_slot_container.hide();
|
||||||
|
search_match_container.hide();
|
||||||
|
match_control.hide();
|
||||||
|
status_container.hide();
|
||||||
|
|
||||||
|
dummy_main.hide();
|
||||||
|
dummy_sub.hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
end_local_game = function()
|
||||||
|
{
|
||||||
|
disable_all_containers();
|
||||||
|
create_game_container.show();
|
||||||
|
status_container.show();
|
||||||
|
if (logged_in)
|
||||||
|
{
|
||||||
|
logout_container.show();
|
||||||
|
search_match_container.show();
|
||||||
|
match_slot_container.show();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
register_container.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
game_manager = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
on_close_click = function() {
|
||||||
|
if (game_manager != null)
|
||||||
|
{
|
||||||
|
game_manager.end_game();
|
||||||
|
end_local_game();
|
||||||
|
}
|
||||||
|
else if (connection != null)
|
||||||
|
{
|
||||||
|
connection.on_close_click();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
start_local_game = function()
|
||||||
|
{
|
||||||
|
console.log("clicked");
|
||||||
|
disable_all_containers();
|
||||||
|
match_control.show();
|
||||||
|
dummy_main.show();
|
||||||
|
dummy_sub.show();
|
||||||
|
|
||||||
|
status_container.show();
|
||||||
|
|
||||||
|
game_manager = new LocalMatchManager(grid, l_status, match_control, end_local_game);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// connection stuff:
|
||||||
|
|
||||||
|
login_callback = function()
|
||||||
|
{
|
||||||
|
logged_in = true;
|
||||||
|
if (game_manager != null)
|
||||||
|
{
|
||||||
|
game_manager.end_game();
|
||||||
|
|
||||||
|
}
|
||||||
|
end_local_game();
|
||||||
|
l_username.innerHTML = "logged in as: " + connection.player.get_name();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
login = function(){
|
||||||
|
|
||||||
|
if (connection != null)
|
||||||
|
{
|
||||||
|
connection.close();
|
||||||
|
}
|
||||||
|
connection = new WebsocketConnection(server_url, server_port, grid, l_status, match_slot_container, match_control, login_callback);
|
||||||
|
connection.connect(i_register_username.value, i_register_pw.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
logout = function()
|
||||||
|
{
|
||||||
|
logged_in = false;
|
||||||
|
if (connection != null)
|
||||||
|
{
|
||||||
|
|
||||||
|
connection.close();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
connection = null;
|
||||||
|
grid.unblock_all();
|
||||||
|
grid.deactivate_all();
|
||||||
|
grid.block_all();
|
||||||
|
end_local_game();
|
||||||
|
}
|
||||||
|
|
||||||
|
search_match = function()
|
||||||
|
{
|
||||||
|
if (connection != null)
|
||||||
|
{
|
||||||
|
connection.send_match_request(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
invite_player = function()
|
||||||
|
{
|
||||||
|
if (connection != null)
|
||||||
|
{
|
||||||
|
if (l_match_op.value == "")
|
||||||
|
{
|
||||||
|
l_status.innerHTML = "choose your opponent first!";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
connection.send_match_request(l_match_op.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// initiate stuff and connect events:
|
||||||
|
|
||||||
|
end_local_game();
|
||||||
|
|
||||||
|
|
||||||
|
b_local_game.addEventListener("click", start_local_game);
|
||||||
|
b_end_game.addEventListener("click", on_close_click);
|
||||||
|
b_register.addEventListener("click", login);
|
||||||
|
b_logout.addEventListener("click", logout);
|
||||||
|
|
||||||
|
b_match_search.addEventListener("click", search_match);
|
||||||
|
b_match_invite.addEventListener("click", invite_player);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
var websocket_connection = new WebsocketConnection('127.0.0.1', 5556);
|
||||||
|
websocket_connection.connect();
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
// register resize event:
|
||||||
|
|
||||||
window.addEventListener("resize", function() {
|
window.addEventListener("resize", function() {
|
||||||
var tilesize = getComputedStyle(document.body).getPropertyValue("--tile-size");
|
var tilesize = getComputedStyle(document.body).getPropertyValue("--tile-size");
|
||||||
|
199
online_match_manager.js
Normal file
199
online_match_manager.js
Normal file
@ -0,0 +1,199 @@
|
|||||||
|
class OnlineMatchManager
|
||||||
|
{
|
||||||
|
constructor(grid, status_label, matches_container, control_container, game_server_connection, match_id, match_state, player_name)
|
||||||
|
{
|
||||||
|
this.grid = grid;
|
||||||
|
this.status_label = status_label;
|
||||||
|
|
||||||
|
this.match_id = match_id;
|
||||||
|
|
||||||
|
this.game_server_connection = game_server_connection;
|
||||||
|
|
||||||
|
|
||||||
|
this.match_state = match_state;
|
||||||
|
this.player_name = player_name
|
||||||
|
|
||||||
|
var player_a = this.match_state.player_a;
|
||||||
|
var player_b = this.match_state.player_b;
|
||||||
|
|
||||||
|
this.online_opponent = new Player(player_a == this.player_name ? player_b : player_a, 255,0,0);
|
||||||
|
this.local_player = new Player(this.player_name, 0,255,0);
|
||||||
|
|
||||||
|
// create match button in match list:
|
||||||
|
this.control_container = control_container;
|
||||||
|
this.matches_container = matches_container
|
||||||
|
this.match_button = matches_container.create_button("" + this.online_opponent.get_name());
|
||||||
|
this.match_button.addEventListener("click", () => this.open_match());
|
||||||
|
this.match_button.style.background = "rbg(0,255,0)";
|
||||||
|
|
||||||
|
this.match_button.className = "infobar-button-active";
|
||||||
|
|
||||||
|
this.is_closed = false;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
click_listener(sub_x, sub_y, x,y)
|
||||||
|
{
|
||||||
|
this.grid.block_all();
|
||||||
|
|
||||||
|
this.game_server_connection.send_move(sub_x, sub_y, x, y, this.match_id);
|
||||||
|
|
||||||
|
this.status_label.innerHTML = "waiting for " + this.online_opponent.get_name() + "'s move";
|
||||||
|
}
|
||||||
|
|
||||||
|
on_user_close()
|
||||||
|
{
|
||||||
|
|
||||||
|
// send end match message:
|
||||||
|
if (!this.match_state.game_over)
|
||||||
|
{
|
||||||
|
this.game_server_connection.send_end_match(this.match_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.matches_container.container.removeChild(this.match_button);
|
||||||
|
this.status_label.innerHTML = "match is closed";
|
||||||
|
this.control_container.hide();
|
||||||
|
this.is_closed = true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
remove_match()
|
||||||
|
{
|
||||||
|
if (!this.is_closed)
|
||||||
|
{
|
||||||
|
this.matches_container.container.removeChild(this.match_button);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
update_match_state(match_state)
|
||||||
|
{
|
||||||
|
this.match_state = match_state;
|
||||||
|
this.match_button.className = "infobar-button-active";
|
||||||
|
|
||||||
|
if (this.match_state.current_player != this.current_player_name)
|
||||||
|
{
|
||||||
|
this.game_server_connection.notify("" + this.online_opponent.get_name() + " moved");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
open_match()
|
||||||
|
{
|
||||||
|
this.grid.register_click_callback(null);
|
||||||
|
|
||||||
|
this.grid.deactivate_all();
|
||||||
|
this.grid.unblock_all();
|
||||||
|
|
||||||
|
this.match_button.className = "infobar-button";
|
||||||
|
|
||||||
|
this.game_server_connection.set_active_match(this.match_id);
|
||||||
|
|
||||||
|
this.control_container.show();
|
||||||
|
|
||||||
|
var complete_field = this.match_state.complete_field;
|
||||||
|
var global_field = this.match_state.global_field;
|
||||||
|
|
||||||
|
var sub_x = null;
|
||||||
|
var sub_y = null;
|
||||||
|
var x = null;
|
||||||
|
var y = null;
|
||||||
|
|
||||||
|
if (this.match_state.last_move != null)
|
||||||
|
{
|
||||||
|
sub_x = this.match_state.last_move.sub_x;
|
||||||
|
sub_y = this.match_state.last_move.sub_y;
|
||||||
|
x = this.match_state.last_move.x;
|
||||||
|
y = this.match_state.last_move.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
var game_over = this.match_state.game_over;
|
||||||
|
var player_won = this.match_state.player_won;
|
||||||
|
var current_player_name = this.match_state.active_player;
|
||||||
|
|
||||||
|
var player_a = this.match_state.player_a;
|
||||||
|
var player_b = this.match_state.player_b;
|
||||||
|
|
||||||
|
console.log(game_over);
|
||||||
|
console.log(current_player);
|
||||||
|
|
||||||
|
var FIELD_EMPTY = 0
|
||||||
|
var FIELD_USER = player_a == this.player_name ? 1 : 2;
|
||||||
|
var FIELD_OPPONENT = player_a == this.player_name ? 2 : 1;
|
||||||
|
var FIELD_DRAW = 3
|
||||||
|
|
||||||
|
this.online_opponent = new Player(player_a == this.player_name ? player_b : player_a, 255,0,0);
|
||||||
|
this.local_player = new Player(this.player_name, 0,255,0);
|
||||||
|
|
||||||
|
var i,j;
|
||||||
|
for(j = 0; j < 9; j++)
|
||||||
|
{
|
||||||
|
for(i = 0; i < 9; i++)
|
||||||
|
{
|
||||||
|
var si = Math.floor(i / 3);
|
||||||
|
var sj = Math.floor(j / 3);
|
||||||
|
if (complete_field[j][i] == FIELD_USER)
|
||||||
|
{
|
||||||
|
this.grid.subgrids[sj][si].player_change_listener(this.local_player);
|
||||||
|
this.grid.subgrids[sj][si].cells[j % 3][i % 3].on_click();
|
||||||
|
}
|
||||||
|
if (complete_field[j][i] == FIELD_OPPONENT)
|
||||||
|
{
|
||||||
|
this.grid.subgrids[sj][si].player_change_listener(this.online_opponent);
|
||||||
|
this.grid.subgrids[sj][si].cells[j % 3][i % 3].on_click();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.grid.block_all();
|
||||||
|
this.grid.register_click_callback((i,j,k,l) => this.click_listener(i,j,k,l));
|
||||||
|
|
||||||
|
if (game_over && player_won != null)
|
||||||
|
{
|
||||||
|
if (player_won == this.player_name)
|
||||||
|
{
|
||||||
|
this.status_label.innerHTML = "Congratulation, you won!";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.status_label.innerHTML = "Game over, you lost!";
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if(game_over)
|
||||||
|
{
|
||||||
|
this.status_label.innerHTML = "Game was closed by server or opponent";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var current_player = this.player_name == current_player_name ? this.local_player : this.online_opponent;
|
||||||
|
this.grid.player_change_listener(current_player);
|
||||||
|
|
||||||
|
|
||||||
|
if (this.player_name == current_player_name)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (this.match_state.last_move != null)
|
||||||
|
{
|
||||||
|
if (this.grid.subgrids[y][x].is_won() || this.grid.subgrids[y][x].is_draw())
|
||||||
|
{
|
||||||
|
this.grid.unblock_all_non_completed();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.grid.unblock(x,y);
|
||||||
|
}
|
||||||
|
this.status_label.innerHTML = "It's your turn!";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.grid.unblock_all();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.status_label.innerHTML = "waiting for " + this.online_opponent.get_name() + "'s move";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -1,2 +1,2 @@
|
|||||||
var server_url = "the-cake-is-a-lie.net";
|
var server_url = "the-cake-is-a-lie.net";
|
||||||
var server_port = "5555";
|
var server_port = "5556";
|
184
sidebar.js
184
sidebar.js
@ -1,184 +0,0 @@
|
|||||||
class Sidebar
|
|
||||||
{
|
|
||||||
constructor(create_game_container, setting_container, control_container, info_container, game_manager)
|
|
||||||
{
|
|
||||||
this.create_game_container = create_game_container;
|
|
||||||
this.setting_container = setting_container;
|
|
||||||
this.control_container = control_container;
|
|
||||||
this.info_container = info_container;
|
|
||||||
|
|
||||||
this.game_manager = game_manager;
|
|
||||||
|
|
||||||
this.fill_containers();
|
|
||||||
this.bind_events();
|
|
||||||
|
|
||||||
this.activate_create_game();
|
|
||||||
this.activate_setting();
|
|
||||||
this.activate_info();
|
|
||||||
}
|
|
||||||
|
|
||||||
create_button(text)
|
|
||||||
{
|
|
||||||
var b = document.createElement("button");
|
|
||||||
b.className = "sidebar-button";
|
|
||||||
b.appendChild(document.createTextNode(text));
|
|
||||||
return b;
|
|
||||||
}
|
|
||||||
|
|
||||||
create_input(text)
|
|
||||||
{
|
|
||||||
var i = document.createElement("input");
|
|
||||||
i.className = "sidebar-input";
|
|
||||||
i.type = "text";
|
|
||||||
i.value = text;
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
|
|
||||||
create_label(text)
|
|
||||||
{
|
|
||||||
var l = document.createElement("label");
|
|
||||||
l.className = "sidebar-label";
|
|
||||||
l.innerHTML = text;
|
|
||||||
return l;
|
|
||||||
}
|
|
||||||
|
|
||||||
fill_containers()
|
|
||||||
{
|
|
||||||
|
|
||||||
// create new game area:
|
|
||||||
this.create_game_container.appendChild(this.create_label("Choose game type"));
|
|
||||||
this.b_local = this.create_button("local game")
|
|
||||||
this.create_game_container.appendChild(this.b_local);
|
|
||||||
|
|
||||||
this.b_remote = this.create_button("remote game");
|
|
||||||
this.create_game_container.appendChild(this.b_remote);
|
|
||||||
|
|
||||||
this.create_game_container.style.display = "none";
|
|
||||||
|
|
||||||
|
|
||||||
// settings area
|
|
||||||
this.setting_container.appendChild(this.create_label("select online name:"));
|
|
||||||
|
|
||||||
this.i_player_name = this.create_input("");
|
|
||||||
this.setting_container.appendChild(this.i_player_name);
|
|
||||||
|
|
||||||
this.setting_container.style.display = "none";
|
|
||||||
|
|
||||||
// control area:
|
|
||||||
|
|
||||||
this.b_end_game = this.create_button("end game");
|
|
||||||
this.control_container.appendChild(this.b_end_game);
|
|
||||||
|
|
||||||
this.control_container.style.display = "none";
|
|
||||||
|
|
||||||
|
|
||||||
// status area:
|
|
||||||
this.status_title = this.create_label("");
|
|
||||||
this.info_container.appendChild(this.status_title);
|
|
||||||
|
|
||||||
this.status_text = this.create_label("select gamemode. <br> <a href=https://en.wikipedia.org/wiki/Ultimate_tic-tac-toe#Rules>here are the rules </a>");
|
|
||||||
this.info_container.appendChild(this.status_text);
|
|
||||||
|
|
||||||
this.info_container.style.display = "none";
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
bind_events()
|
|
||||||
{
|
|
||||||
// TODO
|
|
||||||
this.game_manager.register_game_mode_change_listener((c) => this.game_mode_change_listener(c));
|
|
||||||
this.game_manager.register_status_change_listener((c,t=null) => this.status_change_listener(c, t));
|
|
||||||
|
|
||||||
this.b_local.addEventListener("click", () => this.game_manager.start_local_game());
|
|
||||||
this.b_end_game.addEventListener("click", () => this.game_manager.end_game(true));
|
|
||||||
this.b_remote.addEventListener("click", () => this.game_manager.register_remote_game(this.get_player_name()));
|
|
||||||
}
|
|
||||||
|
|
||||||
set_status(text)
|
|
||||||
{
|
|
||||||
this.status_text.innerHTML = text;
|
|
||||||
}
|
|
||||||
|
|
||||||
get_player_name()
|
|
||||||
{
|
|
||||||
return this.i_player_name.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
activate_create_game()
|
|
||||||
{
|
|
||||||
this.create_game_container.style.display = "inline-block";
|
|
||||||
}
|
|
||||||
|
|
||||||
activate_setting()
|
|
||||||
{
|
|
||||||
this.setting_container.style.display = "inline-block";
|
|
||||||
}
|
|
||||||
|
|
||||||
activate_control()
|
|
||||||
{
|
|
||||||
this.control_container.style.display = "inline-block";
|
|
||||||
}
|
|
||||||
|
|
||||||
activate_info()
|
|
||||||
{
|
|
||||||
this.info_container.style.display = "inline-block";
|
|
||||||
}
|
|
||||||
|
|
||||||
deactivate_create_game()
|
|
||||||
{
|
|
||||||
this.create_game_container.style.display = "none";
|
|
||||||
}
|
|
||||||
|
|
||||||
deactivate_setting()
|
|
||||||
{
|
|
||||||
this.setting_container.style.display = "none";
|
|
||||||
}
|
|
||||||
|
|
||||||
deactivate_control()
|
|
||||||
{
|
|
||||||
this.control_container.style.display = "none";
|
|
||||||
}
|
|
||||||
|
|
||||||
deactivate_info()
|
|
||||||
{
|
|
||||||
this.info_container.style.display = "none";
|
|
||||||
}
|
|
||||||
|
|
||||||
game_mode_change_listener(gamemode)
|
|
||||||
{
|
|
||||||
if (gamemode == "none")
|
|
||||||
{
|
|
||||||
this.activate_create_game();
|
|
||||||
this.activate_setting();
|
|
||||||
this.deactivate_control();
|
|
||||||
this.activate_info();
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (gamemode == "local")
|
|
||||||
{
|
|
||||||
this.deactivate_create_game();
|
|
||||||
this.deactivate_setting();
|
|
||||||
this.activate_control();
|
|
||||||
this.activate_info();
|
|
||||||
}
|
|
||||||
if (gamemode == "remote")
|
|
||||||
{
|
|
||||||
this.deactivate_create_game();
|
|
||||||
this.deactivate_setting();
|
|
||||||
this.activate_control();
|
|
||||||
this.activate_info();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
status_change_listener(statustext, title=null)
|
|
||||||
{
|
|
||||||
this.status_text.innerHTML = statustext;
|
|
||||||
if (title != null)
|
|
||||||
{
|
|
||||||
this.status_title.innerHTML = "<p>" + title + "</p>";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
147
style.css
147
style.css
@ -4,7 +4,7 @@ html, body {
|
|||||||
|
|
||||||
body {
|
body {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
background: rgb(30, 36, 119) ;
|
background: rgb(49, 54, 74) ;
|
||||||
outline: 0;
|
outline: 0;
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
@ -15,21 +15,36 @@ body {
|
|||||||
--tile-size: calc((100vh / (var(--tictactoe_n) * var(--tictactoe_n))) - 2 * var(--button-margin));
|
--tile-size: calc((100vh / (var(--tictactoe_n) * var(--tictactoe_n))) - 2 * var(--button-margin));
|
||||||
--opacity: 1;
|
--opacity: 1;
|
||||||
--border-radius: 1vh;
|
--border-radius: 1vh;
|
||||||
--sidebar-width: 25vh;
|
--sidebar-width: 26vh;
|
||||||
--ground-color: rgb(30, 36, 119) ;
|
--ground-color: rgb(41, 45, 62) ;
|
||||||
--board-size: calc(var(--tictactoe_n) * var(--tictactoe_n) * var(--tile-size) + (var(--tictactoe_n) * var(--tictactoe_n) + var(--tictactoe_n)) * var(--button-margin) );
|
--board-size: calc(var(--tictactoe_n) * var(--tictactoe_n) * var(--tile-size) + (var(--tictactoe_n) * var(--tictactoe_n) + var(--tictactoe_n)) * var(--button-margin) );
|
||||||
--sidebar-height: calc(var(--board-size) - 2 * var(--border-radius));
|
--sidebar-height: calc(var(--board-size) - 2 * var(--border-radius));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* override settings on portrait mode: */
|
/* override settings on portrait mode: */
|
||||||
@media (orientation: portrait) {
|
@media (max-aspect-ratio: 16/10) {
|
||||||
|
|
||||||
|
:root{
|
||||||
|
--button-margin: 0.35vh;
|
||||||
|
--tile-size: calc(((70vh / (var(--tictactoe_n) * var(--tictactoe_n))) - 2 * var(--button-margin)));
|
||||||
|
--border-radius: 0.7vh;
|
||||||
|
--sidebar-width: 18.2vh;
|
||||||
|
--board-size: calc((var(--tictactoe_n) * var(--tictactoe_n) * var(--tile-size) + (var(--tictactoe_n) * var(--tictactoe_n) + var(--tictactoe_n)) * var(--button-margin)));
|
||||||
|
--sidebar-height: calc(var(--board-size) - 2 * var(--border-radius));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* override settings on portrait mode: */
|
||||||
|
@media (max-aspect-ratio: 1/1) {
|
||||||
|
|
||||||
:root{
|
:root{
|
||||||
--button-margin: 0.5vw;
|
--button-margin: 0.5vw;
|
||||||
--tile-size: calc((100vw / (var(--tictactoe_n) * var(--tictactoe_n))) - 2 * var(--button-margin));
|
--tile-size: calc(((100vw / (var(--tictactoe_n) * var(--tictactoe_n))) - 2 * var(--button-margin)));
|
||||||
--border-radius: 1vw;
|
--border-radius: 1vw;
|
||||||
|
--board-size: calc(var(--tictactoe_n) * var(--tictactoe_n) * var(--tile-size) + (var(--tictactoe_n) * var(--tictactoe_n) + var(--tictactoe_n)) * var(--button-margin) );
|
||||||
--sidebar-width: calc(var(--board-size) - 2 * var(--border-radius));
|
--sidebar-width: calc(var(--board-size) - 2 * var(--border-radius));
|
||||||
--sidebar-height: 15vw;
|
--sidebar-height: 25vw;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -51,11 +66,11 @@ a:visited {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* override settings on portrait mode: */
|
/* override settings on portrait mode: */
|
||||||
@media (orientation: portrait) {
|
@media (max-aspect-ratio: 1/1) {
|
||||||
|
|
||||||
.main-container {
|
.main-container {
|
||||||
white-space: normal;
|
white-space: normal;
|
||||||
padding-top: calc(50vh - 0.5 * var(--board-size));
|
padding-top: calc(50vh - 0.5 * var(--board-size) - var(--sidebar-height) - 2 * var(--button-margin));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -114,11 +129,11 @@ a:visited {
|
|||||||
transition-duration: 0.5s;
|
transition-duration: 0.5s;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebar-container {
|
.infobar-container {
|
||||||
border-radius: var(--border-radius);
|
border-radius: var(--border-radius);
|
||||||
padding: var(--border-radius);
|
padding: var(--border-radius);
|
||||||
vertical-align: top;
|
vertical-align: top;
|
||||||
background: rgba(255, 255, 255, 0.05);
|
background: none;
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
flex-direction:column;
|
flex-direction:column;
|
||||||
@ -129,44 +144,15 @@ a:visited {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* override settings on portrait mode: */
|
/* override settings on portrait mode: */
|
||||||
@media (orientation: portrait) {
|
@media (max-aspect-ratio: 1/1) {
|
||||||
|
|
||||||
.sidebar-container {
|
.infobar-container {
|
||||||
flex-direction:row;
|
flex-direction:row;
|
||||||
padding: none;
|
padding: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.create-game-container {
|
|
||||||
border-radius: var(--border-radius);
|
|
||||||
padding: var(--border-radius);
|
|
||||||
top: 0;
|
|
||||||
background: none;
|
|
||||||
display: inline-block;
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.control-container {
|
|
||||||
border-radius: var(--border-radius);
|
|
||||||
padding: var(--border-radius);
|
|
||||||
top: 0;
|
|
||||||
background: none;
|
|
||||||
display: inline-block;
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.setting-container {
|
|
||||||
border-radius: var(--border-radius);
|
|
||||||
padding: var(--border-radius);
|
|
||||||
top: 0;
|
|
||||||
background: none;
|
|
||||||
display: inline-block;
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
|
||||||
|
|
||||||
.info-container {
|
.info-container {
|
||||||
border-radius: var(--border-radius);
|
border-radius: var(--border-radius);
|
||||||
padding: var(--border-radius);
|
padding: var(--border-radius);
|
||||||
@ -178,7 +164,7 @@ a:visited {
|
|||||||
white-space: normal;
|
white-space: normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebar-label {
|
.infobar-label {
|
||||||
color: white;
|
color: white;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
@ -187,14 +173,14 @@ a:visited {
|
|||||||
text-align: left;
|
text-align: left;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (orientation: portrait) {
|
@media (max-aspect-ratio: 1/1) {
|
||||||
.sidebar-label
|
.infobar-label
|
||||||
{
|
{
|
||||||
width: calc(var(--sidebar-width) * 0.3);
|
width: calc(var(--sidebar-width) * 0.25);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebar-button {
|
.infobar-button {
|
||||||
border-radius: var(--border-radius);
|
border-radius: var(--border-radius);
|
||||||
margin: var(--border-radius);
|
margin: var(--border-radius);
|
||||||
border: none;
|
border: none;
|
||||||
@ -202,7 +188,7 @@ a:visited {
|
|||||||
transition-duration: 0.3s;
|
transition-duration: 0.3s;
|
||||||
background: rgba(0, 0, 0, 0.5);
|
background: rgba(0, 0, 0, 0.5);
|
||||||
color: rgb(255, 255, 255);
|
color: rgb(255, 255, 255);
|
||||||
font-size: calc(3 * var(--border-radius));
|
font-size: calc(2.8 * var(--border-radius));
|
||||||
height: calc(4 * var(--border-radius));
|
height: calc(4 * var(--border-radius));
|
||||||
width: calc(var(--sidebar-width) - 4 * var(--border-radius));
|
width: calc(var(--sidebar-width) - 4 * var(--border-radius));
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
@ -210,30 +196,59 @@ a:visited {
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (orientation: portrait) {
|
@media (max-aspect-ratio: 1/1) {
|
||||||
|
|
||||||
.sidebar-button{
|
.infobar-button{
|
||||||
width: calc(0.25 * var(--sidebar-width));
|
width: calc(0.25 * var(--sidebar-width));
|
||||||
height: calc(0.3 * var(--sidebar-height));
|
height: calc(0.18 * var(--sidebar-height));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.infobar-button-active {
|
||||||
.sidebar-button:hover {
|
|
||||||
background: rgba(255, 255, 255, 0.2);
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar-button:active {
|
|
||||||
background: rgba(255, 255, 255, 0.4);
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar-input {
|
|
||||||
border-radius: var(--border-radius);
|
border-radius: var(--border-radius);
|
||||||
margin: var(--border-radius);
|
margin: var(--border-radius);
|
||||||
border: none;
|
border: none;
|
||||||
outline: 0;
|
outline: 0;
|
||||||
transition-duration: 0.3s;
|
transition-duration: 0.3s;
|
||||||
background: rgba(0, 0, 0, 0.5);
|
background: rgba(0, 255, 0, 0.5);
|
||||||
|
color: rgb(255, 255, 255);
|
||||||
|
font-size: calc(2.8 * var(--border-radius));
|
||||||
|
height: calc(4 * var(--border-radius));
|
||||||
|
width: calc(var(--sidebar-width) - 4 * var(--border-radius));
|
||||||
|
vertical-align: middle;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-aspect-ratio: 1/1) {
|
||||||
|
|
||||||
|
.infobar-button-active{
|
||||||
|
width: calc(0.25 * var(--sidebar-width));
|
||||||
|
height: calc(0.18 * var(--sidebar-height));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.infobar-button:hover {
|
||||||
|
background: rgba(255, 255, 255, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.infobar-button:active {
|
||||||
|
background: rgba(255, 255, 255, 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
.infobar-button:disabled {
|
||||||
|
background: rgba(0, 0, 0, 0.1);
|
||||||
|
color: rgb(64,64,64);
|
||||||
|
}
|
||||||
|
|
||||||
|
.infobar-input {
|
||||||
|
border-radius: var(--border-radius);
|
||||||
|
margin: var(--border-radius);
|
||||||
|
border: none;
|
||||||
|
outline: 0;
|
||||||
|
transition-duration: 0.3s;
|
||||||
|
background: rgba(0, 0, 0, 0.2);
|
||||||
color: rgb(255, 255, 255);
|
color: rgb(255, 255, 255);
|
||||||
font-size: calc(3 * var(--border-radius));
|
font-size: calc(3 * var(--border-radius));
|
||||||
height: calc(4 * var(--border-radius));
|
height: calc(4 * var(--border-radius));
|
||||||
@ -244,10 +259,14 @@ a:visited {
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (orientation: portrait) {
|
.infobar-input::placeholder {
|
||||||
|
color: rgba(255,255,255,0.3);
|
||||||
|
}
|
||||||
|
|
||||||
.sidebar-input{
|
@media (max-aspect-ratio: 1/1) {
|
||||||
height: calc(0.3 * var(--sidebar-height));
|
|
||||||
|
.infobar-input{
|
||||||
|
height: calc(0.18 * var(--sidebar-height));
|
||||||
width: calc(0.25 * var(--sidebar-width));
|
width: calc(0.25 * var(--sidebar-width));
|
||||||
}
|
}
|
||||||
}
|
}
|
303
websocket_connection.js
Normal file
303
websocket_connection.js
Normal file
@ -0,0 +1,303 @@
|
|||||||
|
class WebsocketConnection
|
||||||
|
{
|
||||||
|
constructor(ip, port, grid, status_label, matches_container, control_container, login_callback_func)
|
||||||
|
{
|
||||||
|
this.ip = ip;
|
||||||
|
this.port = port;
|
||||||
|
this.session_id = null;
|
||||||
|
this.player = new Player("player", 128, 0,0);
|
||||||
|
this.socket = null;
|
||||||
|
this.registered = false;
|
||||||
|
|
||||||
|
this.grid = grid;
|
||||||
|
this.status_label = status_label;
|
||||||
|
this.matches_container = matches_container;
|
||||||
|
this.control_container = control_container;
|
||||||
|
|
||||||
|
this.active_match = null;
|
||||||
|
|
||||||
|
this.connected = false;
|
||||||
|
|
||||||
|
this.current_end_button = null;
|
||||||
|
|
||||||
|
this.login_callback_func = login_callback_func;
|
||||||
|
|
||||||
|
this.openmatches = {};
|
||||||
|
|
||||||
|
this.
|
||||||
|
|
||||||
|
matches_container.hide();
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
set_player(p)
|
||||||
|
{
|
||||||
|
this.player = p;
|
||||||
|
}
|
||||||
|
|
||||||
|
set_game_manager(gm)
|
||||||
|
{
|
||||||
|
this.game_manager = gm;
|
||||||
|
}
|
||||||
|
|
||||||
|
is_registered()
|
||||||
|
{
|
||||||
|
return this.registered;
|
||||||
|
}
|
||||||
|
|
||||||
|
is_connected()
|
||||||
|
{
|
||||||
|
return this.connected;
|
||||||
|
}
|
||||||
|
|
||||||
|
on_open(username, pw)
|
||||||
|
{
|
||||||
|
this.connected = true;
|
||||||
|
this.login(username, pw)
|
||||||
|
}
|
||||||
|
|
||||||
|
on_close()
|
||||||
|
{
|
||||||
|
this.registered = false;
|
||||||
|
this.connected = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
on_error()
|
||||||
|
{
|
||||||
|
console.log("error in websocket connection");
|
||||||
|
this.registered = false;
|
||||||
|
this.connected = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
on_message(event)
|
||||||
|
{
|
||||||
|
var json_msg = event.data;
|
||||||
|
var msg = JSON.parse(json_msg);
|
||||||
|
|
||||||
|
if (!msg.hasOwnProperty("type") || !msg.hasOwnProperty("data"))
|
||||||
|
{
|
||||||
|
console.log("received wrong formatted message");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("raw_msg: " + json_msg);
|
||||||
|
|
||||||
|
switch(msg.type)
|
||||||
|
{
|
||||||
|
case "login_response":
|
||||||
|
this.on_register_response(msg.data);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "temp_session_response":
|
||||||
|
console.log(json_msg)
|
||||||
|
this.on_temp_session_response(msg.data);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "match_update":
|
||||||
|
this.on_match_update(msg.data);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "match_request_response":
|
||||||
|
this.on_match_request_response(msg.data);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
set_active_match(id)
|
||||||
|
{
|
||||||
|
this.active_match = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
on_close_click()
|
||||||
|
{
|
||||||
|
if (this.active_match != null && (this.active_match in this.openmatches))
|
||||||
|
{
|
||||||
|
this.openmatches[this.active_match].on_user_close();
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
on_match_update(data)
|
||||||
|
{
|
||||||
|
var id = data.id
|
||||||
|
var match_state = data.match_state;
|
||||||
|
|
||||||
|
if (match_state == null)
|
||||||
|
{
|
||||||
|
// checking whether we can delete our dict object
|
||||||
|
if (id in this.openmatches)
|
||||||
|
{
|
||||||
|
delete this.openmatches[id];
|
||||||
|
if (this.active_match == id)
|
||||||
|
{
|
||||||
|
if (this.current_end_button != null)
|
||||||
|
{
|
||||||
|
this.control_container.container.deleteChild(this.current_end_button);
|
||||||
|
this.current_end_button = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (id in this.openmatches)
|
||||||
|
{
|
||||||
|
this.openmatches[id].update_match_state(match_state)
|
||||||
|
console.log("update!!!");
|
||||||
|
if (this.active_match == id)
|
||||||
|
{
|
||||||
|
this.openmatches[id].open_match();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!match_state.game_over)
|
||||||
|
{
|
||||||
|
this.openmatches[id] = new OnlineMatchManager(this.grid, this.status_label, this.matches_container, this.control_container, this, id, match_state, this.player.get_name());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
on_register_response(data)
|
||||||
|
{
|
||||||
|
if (data.success)
|
||||||
|
{
|
||||||
|
this.registered = true;
|
||||||
|
this.session_id = data.id;
|
||||||
|
this.login_callback_func();
|
||||||
|
}
|
||||||
|
this.status_label.innerHTML = data.msg;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
on_temp_session_response(data)
|
||||||
|
{
|
||||||
|
console.log("not supported yet");
|
||||||
|
}
|
||||||
|
|
||||||
|
on_match_request_response(data)
|
||||||
|
{
|
||||||
|
if (data.success)
|
||||||
|
{
|
||||||
|
this.status_label.innerHTML = "match request sent";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.status_label.innerHTML = "could not send request: " + data.msg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
connect(username, pw)
|
||||||
|
{
|
||||||
|
this.socket = new WebSocket("wss://" + this.ip + ":" + this.port);
|
||||||
|
this.socket.onmessage = (e => this.on_message(e));
|
||||||
|
this.socket.onopen = (() => this.on_open(username, pw));
|
||||||
|
this.socket.onerror = (() => this.on_error());
|
||||||
|
this.socket.onclose = (() => this.on_close());
|
||||||
|
}
|
||||||
|
|
||||||
|
send_move(sub_x, sub_y, x, y, match_id)
|
||||||
|
{
|
||||||
|
var msg_object = {
|
||||||
|
type: "move",
|
||||||
|
data: {
|
||||||
|
id: match_id,
|
||||||
|
sub_x: "" + sub_x,
|
||||||
|
sub_y: "" + sub_y,
|
||||||
|
x: "" + x,
|
||||||
|
y: "" + y
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.socket.send(JSON.stringify(msg_object));
|
||||||
|
}
|
||||||
|
|
||||||
|
send_end_match(match_id)
|
||||||
|
{
|
||||||
|
var msg_object = {
|
||||||
|
type: "end_match",
|
||||||
|
data: {
|
||||||
|
id: match_id,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.socket.send(JSON.stringify(msg_object));
|
||||||
|
}
|
||||||
|
|
||||||
|
send_match_request(player_name)
|
||||||
|
{
|
||||||
|
var msg_object = {
|
||||||
|
type: "match_request",
|
||||||
|
data: {
|
||||||
|
player: player_name
|
||||||
|
}
|
||||||
|
};
|
||||||
|
this.socket.send(JSON.stringify(msg_object));
|
||||||
|
}
|
||||||
|
|
||||||
|
login(username, pw)
|
||||||
|
{
|
||||||
|
this.player.set_name(username);
|
||||||
|
// register for game queue
|
||||||
|
var msg_object = {
|
||||||
|
type: "login",
|
||||||
|
data: {
|
||||||
|
name: this.player.get_name(),
|
||||||
|
pw: pw
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.socket.send(JSON.stringify(msg_object));
|
||||||
|
}
|
||||||
|
|
||||||
|
send_disconnect()
|
||||||
|
{
|
||||||
|
if (!this.is_connected)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var msg_object = {
|
||||||
|
type: "end_game",
|
||||||
|
data: {
|
||||||
|
msg: ""
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.socket.send(JSON.stringify(msg_object));
|
||||||
|
}
|
||||||
|
|
||||||
|
close()
|
||||||
|
{
|
||||||
|
for (var key in this.openmatches)
|
||||||
|
{
|
||||||
|
this.openmatches[key].remove_match();
|
||||||
|
}
|
||||||
|
this.socket.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
notify(text) {
|
||||||
|
|
||||||
|
Notification.requestPermission(function(result) {
|
||||||
|
if (result === 'granted') {
|
||||||
|
navigator.serviceWorker.ready.then(function(registration) {
|
||||||
|
registration.showNotification(text, {
|
||||||
|
icon: './icon.png',
|
||||||
|
vibrate: [200, 200],
|
||||||
|
tag: "tictactoe-notification"
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user