implemented basic interface
This commit is contained in:
parent
7956fad8e9
commit
4696421923
11
game_manager.js
Normal file
11
game_manager.js
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
class GameManager
|
||||||
|
{
|
||||||
|
constructor(grid)
|
||||||
|
{
|
||||||
|
this.grid = grid;
|
||||||
|
|
||||||
|
this.dummy_player = new Player("test_player", "rgb(0,128,0)");
|
||||||
|
|
||||||
|
this.grid.player_change_listener(this.dummy_player);
|
||||||
|
}
|
||||||
|
}
|
124
grid.js
Normal file
124
grid.js
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
class Grid
|
||||||
|
{
|
||||||
|
constructor(n, grid_container_div, tile_width, tile_height, ground_color)
|
||||||
|
{
|
||||||
|
this.n = n;
|
||||||
|
this.grid_container_div = grid_container_div;
|
||||||
|
this.tile_width = tile_width;
|
||||||
|
this.tile_height = tile_height;
|
||||||
|
this.ground_color = ground_color;
|
||||||
|
|
||||||
|
this.subgrids = []
|
||||||
|
|
||||||
|
console.log("create grid of size " + this.n);
|
||||||
|
|
||||||
|
this.create();
|
||||||
|
}
|
||||||
|
|
||||||
|
create()
|
||||||
|
{
|
||||||
|
var x,y;
|
||||||
|
for (y = 0; y < this.n; y++)
|
||||||
|
{
|
||||||
|
var div_row = this.grid_container_div.appendChild(document.createElement("div"));
|
||||||
|
var row = [];
|
||||||
|
for (x = 0; x < this.n; x++)
|
||||||
|
{
|
||||||
|
var div_subgrid = div_row.appendChild(document.createElement("div"));
|
||||||
|
div_subgrid.className = "subgrid-container";
|
||||||
|
|
||||||
|
row.push(new Subgrid(this.n, x,y,div_subgrid,this.tile_width, this.tile_height, this.ground_color));
|
||||||
|
row[x].register_click_callback((i,j,k,l) => this.click_listener(i,j,k,l));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
this.subgrids.push(row);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
register_click_callback(func)
|
||||||
|
{
|
||||||
|
this.click_callback = func;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
click_listener(sub_x, sub_y, x,y)
|
||||||
|
{
|
||||||
|
this.click_callback(sub_x, sub_y, x,y);
|
||||||
|
}
|
||||||
|
|
||||||
|
player_change_listener(player)
|
||||||
|
{
|
||||||
|
var x,y;
|
||||||
|
for (y = 0; y < this.n; y++)
|
||||||
|
{
|
||||||
|
for (x = 0; x < this.n; x++)
|
||||||
|
{
|
||||||
|
this.subgrids[y][x].player_change_listener(player);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
activate_all()
|
||||||
|
{
|
||||||
|
var x,y;
|
||||||
|
for (y = 0; y < this.n; y++)
|
||||||
|
{
|
||||||
|
for (x = 0; x < this.n; x++)
|
||||||
|
{
|
||||||
|
this.subgrids[y][x].activate_all();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
deactivate_all()
|
||||||
|
{
|
||||||
|
var x,y;
|
||||||
|
for (y = 0; y < this.n; y++)
|
||||||
|
{
|
||||||
|
for (x = 0; x < this.n; x++)
|
||||||
|
{
|
||||||
|
this.subgrids[y][x].deactivate_all();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
block()
|
||||||
|
{
|
||||||
|
var x,y;
|
||||||
|
for (y = 0; y < this.n; y++)
|
||||||
|
{
|
||||||
|
for (x = 0; x < this.n; x++)
|
||||||
|
{
|
||||||
|
this.subgrids[y][x].block();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unblock()
|
||||||
|
{
|
||||||
|
var x,y;
|
||||||
|
for (y = 0; y < this.n; y++)
|
||||||
|
{
|
||||||
|
for (x = 0; x < this.n; x++)
|
||||||
|
{
|
||||||
|
this.subgrids[y][x].unblock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
on_screen_orientation_change(tile_w,tile_h)
|
||||||
|
{
|
||||||
|
this.tile_width = tile_w;
|
||||||
|
this.tile_h = tile_h;
|
||||||
|
|
||||||
|
var x,y;
|
||||||
|
for (y = 0; y < this.n; y++)
|
||||||
|
{
|
||||||
|
for (x = 0; x < this.n; x++)
|
||||||
|
{
|
||||||
|
this.subgrids[y][x].on_screen_orientation_change(tile_w, tile_h);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
27
index.html
Normal file
27
index.html
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
<html>
|
||||||
|
<link rel="stylesheet" type="text/css" href="style.css">
|
||||||
|
<head>
|
||||||
|
<meta name="viewport" content="width=device-width, user-scalable=no" />
|
||||||
|
<!-- <link rel="manifest" href="manifest.json" /> -->
|
||||||
|
<!-- <link rel="icon" href="icon.png" type="image/png"/> -->
|
||||||
|
<!-- <script defer src="site.js"></script> -->
|
||||||
|
<title>ultimate tictactoe</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="main-container" class="main-container">
|
||||||
|
<!-- <div id="sidebar-container" class="sidebar-container"> -->
|
||||||
|
<!-- <div id="control-container" class="control-container"></div> -->
|
||||||
|
<!-- <div id="info-container" class="info-container"></div> -->
|
||||||
|
<!-- </div> -->
|
||||||
|
<div id="grid-container" class="grid-container"></div>
|
||||||
|
</div>
|
||||||
|
<script src="player.js"></script>
|
||||||
|
<script src="tile.js"></script>
|
||||||
|
<script src="grid.js"></script>
|
||||||
|
<script src="subgrid.js"></script>
|
||||||
|
<script src="game_manager.js"></script>
|
||||||
|
<script src="sidebar.js"></script>
|
||||||
|
<script src="main.js"></script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
13
main.js
Normal file
13
main.js
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
var style = getComputedStyle(document.body);
|
||||||
|
var n = style.getPropertyValue("--tictactoe_n");
|
||||||
|
var tilesize = style.getPropertyValue("--tile-size");
|
||||||
|
var default_opacity = style.getPropertyValue("--opacity");
|
||||||
|
var ground_color = style.getPropertyValue("--ground-color");
|
||||||
|
|
||||||
|
var grid = new Grid(n, document.getElementById("grid-container"), tilesize, tilesize, ground_color);
|
||||||
|
var game_manager = new GameManager(grid);
|
||||||
|
|
||||||
|
window.addEventListener("resize", function() {
|
||||||
|
var tilesize = getComputedStyle(document.body).getPropertyValue("--tile-size");
|
||||||
|
grid.on_screen_orientation_change(tilesize, tilesize);
|
||||||
|
})
|
30
player.js
Normal file
30
player.js
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
class Player
|
||||||
|
{
|
||||||
|
constructor(name, color)
|
||||||
|
{
|
||||||
|
this.name = name;
|
||||||
|
this.color = color;
|
||||||
|
}
|
||||||
|
|
||||||
|
set_name(name)
|
||||||
|
{
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
set_color(color)
|
||||||
|
{
|
||||||
|
this.color = color;
|
||||||
|
}
|
||||||
|
|
||||||
|
get_name()
|
||||||
|
{
|
||||||
|
return this.name
|
||||||
|
}
|
||||||
|
|
||||||
|
get_color()
|
||||||
|
{
|
||||||
|
return this.color;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
0
sidebar.js
Normal file
0
sidebar.js
Normal file
95
style.css
Normal file
95
style.css
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
html, body {
|
||||||
|
overflow-x: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
background: rgb(39, 34, 39);
|
||||||
|
outline: 0;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root{
|
||||||
|
--tictactoe_n: 3;
|
||||||
|
--button-margin: 0.5vh;
|
||||||
|
--tile-size: calc((100vh / (var(--tictactoe_n) * var(--tictactoe_n))) - 2 * var(--button-margin));
|
||||||
|
--opacity: 0.2;
|
||||||
|
--border-radius: 1vh;
|
||||||
|
--sidebar-width: 25vh;
|
||||||
|
--ground-color: rgb(58, 67, 73);
|
||||||
|
--board-size: calc(var(--tictactoe_n) * var(--tictactoe_n) * var(--tile-size) + var(--tictactoe_n) * var(--button-margin) * 4);
|
||||||
|
--sidebar-height: none; /* unused if not in portrait mode */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* override settings on portrait mode: */
|
||||||
|
@media (orientation: portrait) {
|
||||||
|
|
||||||
|
:root{
|
||||||
|
--button-margin: 0.5vw;
|
||||||
|
--tile-size: calc((100vw / (var(--tictactoe_n) * var(--tictactoe_n))) - 2 * var(--button-margin));
|
||||||
|
--border-radius: 1vw;
|
||||||
|
--sidebar-width: 40vw;
|
||||||
|
--sidebar-height: 15vw;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.main-container {
|
||||||
|
text-align: center;
|
||||||
|
white-space: nowrap;
|
||||||
|
padding-top: calc(50vh - 0.5 * (var(--grid-height) * var(--tile-size)) - var(--border-radius));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* override settings on portrait mode: */
|
||||||
|
@media (orientation: portrait) {
|
||||||
|
|
||||||
|
.main-container {
|
||||||
|
white-space: normal;
|
||||||
|
padding-top: calc(50vh - 0.5 * (var(--grid-height) * var(--tile-size) + 2 * var(--sidebar-height)) - 2 * var(--border-radius));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid-tile {
|
||||||
|
position: absolute;
|
||||||
|
width: var(--tile-size);
|
||||||
|
height: var(--tile-size);
|
||||||
|
float: center;
|
||||||
|
background: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid-button {
|
||||||
|
border-radius: var(--button-margin);
|
||||||
|
margin: var(--button-margin);
|
||||||
|
width: calc(var(--tile-size) - (var(--button-margin) * 2));
|
||||||
|
height: calc(var(--tile-size) - (var(--button-margin) * 2));
|
||||||
|
display: inline-block;
|
||||||
|
outline: 0;
|
||||||
|
transition-duration: 0.1s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid-button:focus {
|
||||||
|
outline: 0!important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid-container {
|
||||||
|
border-radius: var(--border-radius);
|
||||||
|
padding: var(--border-radius);
|
||||||
|
margin: auto;
|
||||||
|
width: calc(var(--board-size));
|
||||||
|
height: calc(var(--board-size));
|
||||||
|
background: rgba(0, 0, 0, var(--opacity));
|
||||||
|
display: inline-block;
|
||||||
|
transition-duration: 0.5s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.subgrid-container {
|
||||||
|
border-radius: var(--border-radius);
|
||||||
|
padding: var(--border-radius);
|
||||||
|
margin: auto;
|
||||||
|
width: calc(var(--tictactoe_n) * var(--tile-size));
|
||||||
|
height: calc(var(--tictactoe_n) * var(--tile-size));
|
||||||
|
background: rgba(0, 0, 0, var(--opacity));
|
||||||
|
display: inline-block;
|
||||||
|
transition-duration: 0.5s;
|
||||||
|
}
|
144
subgrid.js
Normal file
144
subgrid.js
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
class Subgrid
|
||||||
|
{
|
||||||
|
constructor(n, sub_x, sub_y,subgrid_container_div, tile_width, tile_height, ground_color)
|
||||||
|
{
|
||||||
|
this.n = n;
|
||||||
|
this.subgrid_container_div = subgrid_container_div;
|
||||||
|
this.tile_height = tile_height;
|
||||||
|
this.tile_width = tile_width;
|
||||||
|
|
||||||
|
this.cells = [];
|
||||||
|
|
||||||
|
this.sub_x = sub_x;
|
||||||
|
this.sub_y = sub_y;
|
||||||
|
|
||||||
|
this.ground_color = ground_color;
|
||||||
|
|
||||||
|
this.create();
|
||||||
|
|
||||||
|
console.log("new subgrid created");
|
||||||
|
}
|
||||||
|
|
||||||
|
create()
|
||||||
|
{
|
||||||
|
var x,y;
|
||||||
|
for (y = 0; y < this.n; y++)
|
||||||
|
{
|
||||||
|
var div_row = this.subgrid_container_div.appendChild(document.createElement("div"));
|
||||||
|
var row = [];
|
||||||
|
for (x = 0; x < this.n; x++)
|
||||||
|
{
|
||||||
|
var div_button = div_row.appendChild(document.createElement("div"));
|
||||||
|
div_button.className = "grid-tile";
|
||||||
|
var button = document.createElement("button");
|
||||||
|
button.className = "grid-button";
|
||||||
|
div_button.appendChild(button);
|
||||||
|
|
||||||
|
var b_x = x;
|
||||||
|
var b_y = y;
|
||||||
|
var b_w = this.tile_width;
|
||||||
|
var b_h = this.tile_height;
|
||||||
|
|
||||||
|
row.push(new Tile(b_x, b_y, b_w, b_h, button, this.ground_color, div_button));
|
||||||
|
// TODO: register listener?
|
||||||
|
row[x].register_click_callback((i,j) => this.click_listener(i,j));
|
||||||
|
|
||||||
|
}
|
||||||
|
this.cells.push(row);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
register_click_callback(func)
|
||||||
|
{
|
||||||
|
this.click_callback = func;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
click_listener(x,y)
|
||||||
|
{
|
||||||
|
this.click_callback(this.sub_x, this.sub_y, x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
player_change_listener(player)
|
||||||
|
{
|
||||||
|
var x,y;
|
||||||
|
for (y = 0; y < this.n; y++)
|
||||||
|
{
|
||||||
|
for (x = 0; x < this.n; x++)
|
||||||
|
{
|
||||||
|
this.cells[y][x].player_change_listener(player);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unlock_request_listener(x,y)
|
||||||
|
{
|
||||||
|
// TODO: unused so far
|
||||||
|
|
||||||
|
//return this.unlock_request_callback(x,y);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
activate_all()
|
||||||
|
{
|
||||||
|
var x,y;
|
||||||
|
for (y = 0; y < this.n; y++)
|
||||||
|
{
|
||||||
|
for (x = 0; x < this.n; x++)
|
||||||
|
{
|
||||||
|
this.cells[y][x].activate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
deactivate_all()
|
||||||
|
{
|
||||||
|
var x,y;
|
||||||
|
for (y = 0; y < this.n; y++)
|
||||||
|
{
|
||||||
|
for (x = 0; x < this.n; x++)
|
||||||
|
{
|
||||||
|
this.cells[y][x].deactivate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
block()
|
||||||
|
{
|
||||||
|
var x,y;
|
||||||
|
for (y = 0; y < this.n; y++)
|
||||||
|
{
|
||||||
|
for (x = 0; x < this.n; x++)
|
||||||
|
{
|
||||||
|
this.cells[y][x].lock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unblock()
|
||||||
|
{
|
||||||
|
var x,y;
|
||||||
|
for (y = 0; y < this.n; y++)
|
||||||
|
{
|
||||||
|
for (x = 0; x < this.n; x++)
|
||||||
|
{
|
||||||
|
this.cells[y][x].unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
on_screen_orientation_change(tile_w,tile_h)
|
||||||
|
{
|
||||||
|
this.tile_width = tile_w;
|
||||||
|
this.tile_h = tile_h;
|
||||||
|
|
||||||
|
var x,y;
|
||||||
|
for (y = 0; y < this.n; y++)
|
||||||
|
{
|
||||||
|
for (x = 0; x < this.n; x++)
|
||||||
|
{
|
||||||
|
this.cells[y][x].update_css_transform(tile_w, tile_h);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
130
tile.js
Normal file
130
tile.js
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
class Tile
|
||||||
|
{
|
||||||
|
constructor(x,y,w,h, elem, ground_color, div)
|
||||||
|
{
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
|
||||||
|
this.w = w;
|
||||||
|
this.h = h;
|
||||||
|
|
||||||
|
// reference to element
|
||||||
|
this.elem = elem;
|
||||||
|
this.ground_color = ground_color;
|
||||||
|
this.div = div;
|
||||||
|
|
||||||
|
this.locked = false;
|
||||||
|
|
||||||
|
this.div.style.transform = "translate( calc( " + x + "*" + w + "), calc(" + y + "*" + h + "))";
|
||||||
|
|
||||||
|
this.player = null;
|
||||||
|
this.reset();
|
||||||
|
this.bind();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
update_css_transform(w,h)
|
||||||
|
{
|
||||||
|
this.w = w;
|
||||||
|
this.h = h;
|
||||||
|
this.div.style.transform = "translate( calc( " + this.x + "*" + this.w + "), calc(" + this.y + "*" + this.h + "))";
|
||||||
|
}
|
||||||
|
|
||||||
|
register_click_callback(func)
|
||||||
|
{
|
||||||
|
this.click_callback = func;
|
||||||
|
}
|
||||||
|
|
||||||
|
register_unlock_request_callback(func)
|
||||||
|
{
|
||||||
|
this.unlock_request_callback = func;
|
||||||
|
}
|
||||||
|
|
||||||
|
player_change_listener(player)
|
||||||
|
{
|
||||||
|
this.player = player;
|
||||||
|
}
|
||||||
|
|
||||||
|
bind()
|
||||||
|
{
|
||||||
|
this.elem.addEventListener("mouseenter", c => this.on_mouseenter(c));
|
||||||
|
this.elem.addEventListener("mouseleave", c => this.on_mouseleave(c));
|
||||||
|
this.elem.addEventListener("mousedown", c => this.on_click(c));
|
||||||
|
|
||||||
|
// TODO: bind player listener
|
||||||
|
}
|
||||||
|
|
||||||
|
reset()
|
||||||
|
{
|
||||||
|
this.elem.style.backgroundColor = this.ground_color;
|
||||||
|
this.elem.style.opacity = 1;
|
||||||
|
this.deactivate();
|
||||||
|
}
|
||||||
|
|
||||||
|
lock()
|
||||||
|
{
|
||||||
|
this.locked = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
unlock()
|
||||||
|
{
|
||||||
|
this.locked = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
deactivate()
|
||||||
|
{
|
||||||
|
this.is_activated = false;
|
||||||
|
this.elem.style.opacity = 0.3;
|
||||||
|
this.elem.style.border = "none";
|
||||||
|
}
|
||||||
|
|
||||||
|
activate()
|
||||||
|
{
|
||||||
|
this.is_activated = true;
|
||||||
|
this.elem.style.background = this.player.get_color();
|
||||||
|
this.elem.style.opacity = 1.0;
|
||||||
|
this.elem.style.border = "2px solid rgba(255,255,255,0.3)";
|
||||||
|
}
|
||||||
|
|
||||||
|
on_mouseenter()
|
||||||
|
{
|
||||||
|
if (!this.is_activated && !this.locked)
|
||||||
|
{
|
||||||
|
this.elem.style.background = this.player.get_color();
|
||||||
|
this.elem.style.opacity = 0.7;
|
||||||
|
this.elem.style.border = "1px solid rgba(255,255,255,0.3)";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
on_mouseleave()
|
||||||
|
{
|
||||||
|
if (!this.is_activated && !this.locked)
|
||||||
|
{
|
||||||
|
this.elem.style.background = this.ground_color;
|
||||||
|
this.elem.style.opacity = 0.3;
|
||||||
|
this.elem.style.border = "none";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
on_click()
|
||||||
|
{
|
||||||
|
if (this.locked)
|
||||||
|
{
|
||||||
|
// just check whether we can request an unlock. if not we're
|
||||||
|
// doing nothing!
|
||||||
|
if (!this.unlock_request_callback(this.x, this.y))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var active_before = this.is_activated;
|
||||||
|
this.activate();
|
||||||
|
if (!active_before)
|
||||||
|
{
|
||||||
|
this.click_callback(this.x, this.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user