This is a documentation for Board Game Arena: play board games online !
Tutorial roadtothreehoundred: Difference between revisions
Marc bertran (talk | contribs) (initial edit) |
Marc bertran (talk | contribs) No edit summary |
||
Line 1: | Line 1: | ||
This tutorial will guide you through the basics of creating a simple game on BGA Studio, through the example of [https://ablagestapel.blogspot.com/p/road-to-300-spielregeln.html Road To Three Hundred] | |||
<<INSERT CONTENT>> | |||
== Set up the board == | |||
Edit .tpl to add divs in the HTML for the main board, which is divided in three: area for the dice (we will code details later), area for this player, and area for the other player. | |||
<nowiki><div id="rt300_mainboard"></nowiki> | |||
<nowiki><div id="rt300_spacer" class="rt300_zone"></div></nowiki> | |||
<nowiki><div id="rt300_dice"></nowiki> | |||
<nowiki></div></nowiki> | |||
<!-- BEGIN mainplboard --> | |||
<nowiki><div id="rt300_mainplboard" class="rt300_zone" style="--player-color: #{PLAYER_COLOR}"></nowiki> | |||
<nowiki><div id="rt300_playerboard_{PLAYER_ID}" class="rt300_playerboard" style="order: 0"></nowiki> | |||
<nowiki><div class="rt300_playerheader"></nowiki> | |||
<nowiki><div class="rt300_nameholder"></nowiki> | |||
<nowiki><div id="rt300_plname_{PLAYER_ID}" class="rt300_plname">{PLAYER_NAME}</div></nowiki> | |||
<nowiki></div></nowiki> | |||
<nowiki></div></nowiki> | |||
<nowiki><div id="rt300_metropad_{PLAYER_ID}" class="rt300_metropad" style="opacity: 1"></nowiki> | |||
<nowiki></div></nowiki> | |||
<nowiki></div></nowiki> | |||
<nowiki></div></nowiki> | |||
<!-- END mainplboard --> | |||
<nowiki><div id="rt300_opponents" class="rt300_zone"></nowiki> | |||
<!-- BEGIN opponentBoard --> | |||
<nowiki><div id="rt300_mainplboard_{PLAYER_ID}" class="rt300_zone" style="--player-color: #{PLAYER_COLOR}"></nowiki> | |||
<nowiki><div id="rt300_playerboard_{PLAYER_ID}" class="rt300_playerboard" style="order: 0"></nowiki> | |||
<nowiki><div class="rt300_playerheader"></nowiki> | |||
<nowiki><div class="rt300_nameholder"></nowiki> | |||
<nowiki><div id="rt300_plname_{PLAYER_ID}" class="rt300_plname">{PLAYER_NAME}</div></nowiki> | |||
<nowiki></div></nowiki> | |||
<nowiki></div></nowiki> | |||
<nowiki><div id="rt300_metropad_{PLAYER_ID}" class="rt300_metropad" style="opacity: 1"></nowiki> | |||
<nowiki></div></nowiki> | |||
<nowiki></div></nowiki> | |||
<nowiki></div></nowiki> | |||
<!-- END opponentBoard --> | |||
<nowiki></div></nowiki> | |||
<nowiki></div></nowiki> | |||
Edit .css to set the div sizes and positions and upload "field.png" in the 'img' folder of your SFTP access to show the image of the board as background for both this player and the other player (smaller). | |||
You can find the board image here : <<UPLOAD FILE>> | |||
#rt300_mainboard { | |||
display: flex; | |||
flex-wrap: wrap; | |||
justify-content: space-around; | |||
gap: 1em; | |||
} | |||
#rt300_mainplboard { | |||
--padsize: 60vh; | |||
--padratio: 1; | |||
} | |||
.rt300_playerboard { | |||
border-left: 1px solid gray; | |||
border-top: 1px solid gray; | |||
filter: drop-shadow(2px 4px 6px black); | |||
position: relative; | |||
} | |||
.rt300_zone { | |||
align-items: center; | |||
display: flex; | |||
flex-direction: column; | |||
justify-content: space-evenly; | |||
padding: 1vh; | |||
} | |||
#rt300_opponents { | |||
--padsize: 19vh; | |||
--padratio: 1; | |||
display: flex; | |||
justify-content: space-evenly; | |||
width: 20vh; | |||
} | |||
@media only screen and (max-width: 560px) { | |||
#rt300_spacer { | |||
display: none; | |||
} | |||
} | |||
.rt300_playerheader { | |||
background-color: #46a12a; | |||
height: calc(var(--padsize) * var(--padratio) * 0.05); | |||
position: relative; | |||
width: calc(var(--padsize) * var(--padratio)); | |||
} | |||
#rt300_dice { | |||
display: flex; | |||
flex-direction: column; | |||
justify-content: space-evenly; | |||
align-items: center; | |||
filter: drop-shadow(2px 4px 6px black); | |||
} | |||
.rt300_nameholder { | |||
align-items: center; | |||
display: flex; | |||
font-family: Indie Flower, sans-serif; | |||
font-weight: bolder; | |||
height: 38%; | |||
justify-content: center; | |||
left: 33%; | |||
position: absolute; | |||
top: 29%; | |||
width: 31%; | |||
} | |||
.rt300_plname { | |||
font-size: calc(var(--padsize) * var(--padratio) * 0.04); | |||
height: fit-content; | |||
color: var(--player-color); | |||
} | |||
.rt300_metropad { | |||
background-image: url(img/field.png); | |||
background-size: contain; | |||
background-repeat: no-repeat; | |||
height: calc(var(--padsize) * var(--padratio) * 1.252); | |||
position: relative; | |||
width: calc(var(--padsize) * var(--padratio)); | |||
} | |||
== Set up the backbone of your game == | |||
Edit dbmodel.sql to create a table for board squares. We need coordinates for each square and a field to store their status. | |||
CREATE TABLE `board` ( | |||
`player_id` int(11) NOT NULL, | |||
`col` int(11) NOT NULL, | |||
`row` int(11) NOT NULL, | |||
`status` int(11) NOT NULL | |||
); | |||
ALTER TABLE `board` ADD PRIMARY KEY(`player_id`, `col`, `row`); | |||
Edit .game.php->setupNewGame() to insert the empty squares (6x6) with coordinates into the database. | |||
$sql1 = "INSERT INTO board (player_id, row, col, status) VALUES "; | |||
$sql2 = "INSERT INTO board_undo (player_id, row, col, status) VALUES "; | |||
$values = []; | |||
foreach ($players as $player_id => $player) { | |||
for ($r = 1; $r <= 6; $r++) { | |||
for ($c = 1; $c <= 6; $c++) { | |||
$values[] = "('" . $player_id . "', '$r', '$c', 0) "; | |||
} | |||
} | |||
} | |||
$sql1 .= implode($values, ","); | |||
self::DbQuery($sql1); | |||
$sql2 .= implode($values, ","); | |||
self::DbQuery($sql2); | |||
Edit .game.php->getAllDatas() to retrieve the state of the squares from the database. | |||
$result["board"] = []; | |||
foreach ($result["players"] as $playerInfo) { | |||
$result["board"][$playerInfo["id"]] = DBManager::getBoardForPlayer($playerInfo["id"]); | |||
} | |||
We define the DBManager class in a separate module modules\DBManager.php to keep a clean code. | |||
<?php | |||
class DBManager extends APP_GameClass { | |||
public static function getAllPlayerDatas() { | |||
$sql = "SELECT player_id id, player_score score, player_pass_count AS pass_count FROM player "; | |||
return self::getCollectionFromDb($sql); | |||
} | |||
} | |||
?> | |||
We will add more database management related functions to this file later on. | |||
To make sure functions in modules are reachable from the game, add a call in material.inc.php: | |||
require_once "modules/DBManager.php"; | |||
Edit .tpl to create a template for squares. | |||
var jstpl_panelItemWrapper = '<nowiki><div class="rt300_grid_wrapper" id="panelItem_wrapper_${plId}"> </div></nowiki>'; |
Revision as of 01:12, 25 March 2024
This tutorial will guide you through the basics of creating a simple game on BGA Studio, through the example of Road To Three Hundred
<<INSERT CONTENT>>
Set up the board
Edit .tpl to add divs in the HTML for the main board, which is divided in three: area for the dice (we will code details later), area for this player, and area for the other player.
<div id="rt300_mainboard"> <div id="rt300_spacer" class="rt300_zone"></div> <div id="rt300_dice"> </div> <div id="rt300_mainplboard" class="rt300_zone" style="--player-color: #{PLAYER_COLOR}"> <div id="rt300_playerboard_{PLAYER_ID}" class="rt300_playerboard" style="order: 0"> <div class="rt300_playerheader"> <div class="rt300_nameholder"> <div id="rt300_plname_{PLAYER_ID}" class="rt300_plname">{PLAYER_NAME}</div> </div> </div> <div id="rt300_metropad_{PLAYER_ID}" class="rt300_metropad" style="opacity: 1"> </div> </div> </div> <div id="rt300_opponents" class="rt300_zone"> <div id="rt300_mainplboard_{PLAYER_ID}" class="rt300_zone" style="--player-color: #{PLAYER_COLOR}"> <div id="rt300_playerboard_{PLAYER_ID}" class="rt300_playerboard" style="order: 0"> <div class="rt300_playerheader"> <div class="rt300_nameholder"> <div id="rt300_plname_{PLAYER_ID}" class="rt300_plname">{PLAYER_NAME}</div> </div> </div> <div id="rt300_metropad_{PLAYER_ID}" class="rt300_metropad" style="opacity: 1"> </div> </div> </div> </div> </div>
Edit .css to set the div sizes and positions and upload "field.png" in the 'img' folder of your SFTP access to show the image of the board as background for both this player and the other player (smaller).
You can find the board image here : <<UPLOAD FILE>>
#rt300_mainboard { display: flex; flex-wrap: wrap; justify-content: space-around; gap: 1em; } #rt300_mainplboard { --padsize: 60vh; --padratio: 1; } .rt300_playerboard { border-left: 1px solid gray; border-top: 1px solid gray; filter: drop-shadow(2px 4px 6px black); position: relative; } .rt300_zone { align-items: center; display: flex; flex-direction: column; justify-content: space-evenly; padding: 1vh; } #rt300_opponents { --padsize: 19vh; --padratio: 1; display: flex; justify-content: space-evenly; width: 20vh; } @media only screen and (max-width: 560px) { #rt300_spacer { display: none; } } .rt300_playerheader { background-color: #46a12a; height: calc(var(--padsize) * var(--padratio) * 0.05); position: relative; width: calc(var(--padsize) * var(--padratio)); } #rt300_dice { display: flex; flex-direction: column; justify-content: space-evenly; align-items: center; filter: drop-shadow(2px 4px 6px black); } .rt300_nameholder { align-items: center; display: flex; font-family: Indie Flower, sans-serif; font-weight: bolder; height: 38%; justify-content: center; left: 33%; position: absolute; top: 29%; width: 31%; } .rt300_plname { font-size: calc(var(--padsize) * var(--padratio) * 0.04); height: fit-content; color: var(--player-color); } .rt300_metropad { background-image: url(img/field.png); background-size: contain; background-repeat: no-repeat; height: calc(var(--padsize) * var(--padratio) * 1.252); position: relative; width: calc(var(--padsize) * var(--padratio)); }
Set up the backbone of your game
Edit dbmodel.sql to create a table for board squares. We need coordinates for each square and a field to store their status.
CREATE TABLE `board` ( `player_id` int(11) NOT NULL, `col` int(11) NOT NULL, `row` int(11) NOT NULL, `status` int(11) NOT NULL ); ALTER TABLE `board` ADD PRIMARY KEY(`player_id`, `col`, `row`);
Edit .game.php->setupNewGame() to insert the empty squares (6x6) with coordinates into the database.
$sql1 = "INSERT INTO board (player_id, row, col, status) VALUES "; $sql2 = "INSERT INTO board_undo (player_id, row, col, status) VALUES "; $values = []; foreach ($players as $player_id => $player) { for ($r = 1; $r <= 6; $r++) { for ($c = 1; $c <= 6; $c++) { $values[] = "('" . $player_id . "', '$r', '$c', 0) "; } } } $sql1 .= implode($values, ","); self::DbQuery($sql1); $sql2 .= implode($values, ","); self::DbQuery($sql2);
Edit .game.php->getAllDatas() to retrieve the state of the squares from the database.
$result["board"] = []; foreach ($result["players"] as $playerInfo) { $result["board"][$playerInfo["id"]] = DBManager::getBoardForPlayer($playerInfo["id"]); }
We define the DBManager class in a separate module modules\DBManager.php to keep a clean code.
<?php class DBManager extends APP_GameClass { public static function getAllPlayerDatas() { $sql = "SELECT player_id id, player_score score, player_pass_count AS pass_count FROM player "; return self::getCollectionFromDb($sql); } } ?>
We will add more database management related functions to this file later on.
To make sure functions in modules are reachable from the game, add a call in material.inc.php:
require_once "modules/DBManager.php";
Edit .tpl to create a template for squares.
var jstpl_panelItemWrapper = '<div class="rt300_grid_wrapper" id="panelItem_wrapper_${plId}"> </div>';