This is a documentation for Board Game Arena: play board games online !

Tutorial roadtothreehoundred

From Board Game Arena
Revision as of 02:12, 25 March 2024 by Marc bertran (talk | contribs)
Jump to navigation Jump to search

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>';