This is a documentation for Board Game Arena: play board games online !
Туториал хеартс
Wорк ин Прогресс
Тхис паге ис wорк ин прогресс дон'т усе ит унтил тхис баннер ис гоне
Интродуцтион
Усинг тхис туториал, yоу цан буилд а цомплете wоркинг гаме он тхе БГА енвиронмент: Хеартс.
Бефоре yоу реад тхис туториал, yоу муст:
- Реад тхе овералл пресентатионс оф тхе БГА Фрамеwорк (сее хере).
- Кноw тхе рулес фор Хеартс
- Соме-wхат кноw тхе лангуагес усед он БГА: ПХП, СQЛ, ХТМЛ, ЦСС, Јавасцрипт
- Сетуп yоу девелопмент енвиронмент Фирст Степс wитх БГА Студио
Цреате yоур фирст гаме
Иф yоу хаве нот алреадy, yоу хаве то цреате а пројецт ин БГА Студио. Фор тхис туториал yоу цан цреате а пројецт хеартсYОУНАМЕ wхере YОУНАМЕ ис yоур девелопер логин наме. Yоу цан алсо ре-усе тхе пројецт yоу хаве цреатед фор "Фирст Степс" туториал абове. Wитх тхе инитиал скелетон оф цоде провидед инитиаллy, yоу цан алреадy старт а гаме фром тхе БГА Студио.
Финд анд старт тхе гаме ин турн басед моде, маке суре ит wоркс.
Сецонд модифy тхе теxт ин хеартсYОУНАМЕ_хеартсYОУНАМЕ.тпл, релоад тхе паге ин тхе броwсер анд маке суре yоур фтп сyнц wоркс ас еxпецтед. Ноте: иф yоу хаве нот сетуп ауто-сyнц до ит ноw, мануаллy цопyинг филес ис а но-стартер.
Хоок версион цонтрол сyстем
Иф итс а реал гаме ор евен фор тхис туториал I wоулд цоммит тхе цоде то версион цонтрол ригхт ат старт. Yоу гоинг то финд yоурселф ин тхе ситуатион wхен гаме доес нот евен старт анyморе анд но wаy оф дебуггинг ит унлесс yоу хаве а wаy то реверт. Тхат ис wхере версион цонтрол бецомес верy хандy. Иф yоу дон'т кноw wхат I ам талкинг абоут тхен ат леаст бацк-уп yоур филес афтер еацх оф мајор степс. Стартинг ноw.
Цоде фор тхис туториал аваилабле он гитхуб ат https://github.com/elaskavaia/bga-heartsla
Дифферент ревисионс репресент дифферент степс алонг тхе процесс, стартинг фром оригинал темплате то а цомплете гаме.
Упдате гаме инфос анд боx грапхицс
Евен ит доес нот нотхинг yет I алwаyс старт wитх макинг суре гаме лоокс десцент ин тхе гаме селецтор, меанинг ит хас нице боx грапхицс анд информатион ис цоррецт. Фор тхат wе неед то едит гамеинфос.инц.пхп. Wхат yоу wоулд до фор реал гаме yоу wоулд го то http://boardgamegeek.com финд тхе гаме анд усе тхе информатион фром wеб-сите то филл тхе гамеинфос. Со летс до тхат. Финд "хеартс" он боардгамегеек. Оригинал релеасе 1850 :) Yоу цан филл ин yеар оф публисхинг, бгг ид, yоу цан пут Публиц Домаин ас публисхер анд публисхер ид ис 171 фор публиц домаин. Анд ас десигнер анд аутхор yоу цан јуст пут yоур оwн наме јуст фор фун. Сет нумбер оф плаyерс то 4.
// Players configuration that can be played (ex: 2 to 4 players) 'players' => array( 4 ),
Тхе неxт степ ис то реплаце гаме_боx.пнг wитх ницер имагес. Фор тхис туториал јуст цопy алл филес фром имг/ фолдер оф хеартс/ темплате инто имг/ дирецторy оф yоур пројецт. Анд реплаце публисхер.пнг wитх ницер имаге фор еxампле https://github.com/elaskavaia/bga-sharedcode/blob/master/img/publisher.png. Детаилс абоут имагес цан бе фоунд хере: Гаме арт: имг дирецторy
Ноw импортант степ. Yоу хаве то ЛОАД тхесе филес ин студио wебсите тхроугх цонтрол панел. Со го то Цонтрол Панел -> Манагер Гамес -> хеартсYОУНАМЕ анд пресс Релоад фор 'Релоад гаме информатионс' анд 'Релоад гаме боx имаге'
Ноw трy то старт тхе гаме агаин. Иф yоу соме-хоw интродуцед а сyнтаx еррор ин гамеинфос филе ит маy нот ацтуаллy wорк (гаме wон'т старт). Алwаyс усе "Еxпресс Старт" буттон то старт тхе гаме. Yоу схоулд сее а стандард стате промпт фром темплате. Yоу схоулд сее 4 плаyерс он тхе ригхт, тестдуде0 .. тестдуде3. То сwитцх бетwеен тхем пресс тхе ред арроw буттон неар тхеир намес, ит wилл опен анотхер таб. Тхис wаy yоу дон'т неед то логин анд логоут фром мултипле аццоунтс!
Цоде Рев [1]
Лаyоут анд Грапхицс
Ин тхис сецтион wе wилл до грапхицс оф тхе гаме, анд маин лаyоут оф тхе гаме.
Фирст цопy а сприте wитх цардс фром хеартс имг/цардс.јпг инто имг/ фолдер оф yоур пројецт.
Едит .тпл то адд соме дивс то репресент плаyер таблеау анд ханд ареа
<div id="myhand_wrap" class="whiteblock"> <h3>My Hand</h3> <div id="myhand"> </div> </div>
Иф yоу рефресх yоу схоулд сее ноw wхите ареа wитх Мy Ханд титле.
Ноw летс адд а цард инто тхе ханд, јуст yоу цан феел ит. Едит .тпл анд а
...
...
Едит .цсс филе
.playertablecard { display: inline-block; position: relative; margin-top: 5px; width: 72px; height: 96px; background-image: url('img/cards.jpg'); }
Wхен yоу едит ЦСС ремембер тхат yоу хаве то ФОРЦЕ-релоад паге, и.е. Схифт-Ф5, отхерwисе итс цацхед. Саме wхен yоу цханге еxистинг грапхицс филес.
Yоу схоулд сее тхис:
Аwесоме! Ноw летс до тхе рест оф лаyоут.
Тхере аре феw wаyс оф хоw хтмл цоулд хаве беен генератед, yоу цоулд хаве старт wитх нотхинг анд генерате алл бy јава сцрипт. Ор yоу цоулд хаве стартед wитх цомплете гаме маркуп ин хтмл анд маке јава сцрипт јуст хиде анд мове пиецес ароунд. БГА фрамеwорк провидес алсо а тхирд wаy wхицх ис миx оф ботх плус темплате енгине то генерате ХТМЛ усинг пхп. Со летс до тхат.
Цханге .тпл филе то хаве тхис инсиде
<div id="playertables"> <!-- BEGIN player --> <div class="playertable whiteblock playertable_{DIR}"> <div class="playertablename" style="color:#{PLAYER_COLOR}"> {PLAYER_NAME} </div> <div class="playertablecard" id="playertablecard_{PLAYER_ID}"> </div> </div> <!-- END player --> </div> <div id="myhand_wrap" class="whiteblock"> <h3>{MY_HAND}</h3> <div id="myhand"> </div> </div>
Тхат wе дид ис wе аддед "блоцк" плаyер, итс маркед уп усинг хтмл цомментс. {ВАР} нотатион ис усед то ињецт вариаблес анд инсиде еффецтивелy аллоwс уп то до лоопс.
Ин .виеw.пхп инсерт тхис цоде афтер 'Плаце yоур цоде белоw' цоммент
$template = self::getGameName() . "_" . self::getGameName(); $directions = array( 'S', 'W', 'N', 'E' ); // this will inflate our player block with actual players data $this->page->begin_block($template, "player"); foreach ( $players as $player_id => $info ) { $dir = array_shift($directions); $this->page->insert_block("player", array ("PLAYER_ID" => $player_id, "PLAYER_NAME" => $players [$player_id] ['player_name'], "PLAYER_COLOR" => $players [$player_id] ['player_color'], "DIR" => $dir )); } // this will make our My Hand text translatable $this->tpl['MY_HAND'] = self::_("My hand");
Анд релоад. Иф еверyтхинг wент wелл yоу схоулд сее тхис:
Тхесе аре "таблеау" ареас фор 4 плаyерс плус Мy ханд висибле онлy то оне плаyер. Тхеy нот еxацтлy хоw wе wантед тхем то бе бецаусе wе дид нот едит .цсс yет.
Ноw едит .цсс, адд тхесе лине афтер импорт бефоре оур превиоус дефинитион
/** Table layout **/ #playertables { position: relative; width: 710px; height: 340px; } .playertablename { font-weight: bold; } .playertable { position: absolute; text-align: center; width: 180px; height: 130px; } .playertable_N { left: 50%; top: 0px; margin-left: -90px; /* half of 180 */ } .playertable_S { left: 50%; bottom: 0px; margin-left: -90px; /* half of 180 */ } .playertable_W { left: 0px; top: 50%; margin-top: -55px; /* half of 130 */ } .playertable_E { right: 0px; top: 50%; margin-top: -55px; /* half of 130 */ }
Ноw yоу Схифт-Релоад анд yоу схоулд сее тхис:
Летс алмост алл wе неед фор грапхицс анд лаyоут, тхере аре феw тwеакс лефт тхере бут летс до соме море хеавy лифтинг ноw.
Гаме Интерфаце ЈС Стоцк
БГА фрамеwорк провидес феw оут оф тхе боx цлассес то деал wитх цардс. Тхе цлиент сиде цонтаинс цласс цаллед Стоцк анд ит цан бе усед фор анy дyнамиц хтмл 'пиецес' манагемент тхат усес цоммон сприте имаге. Он тхе сервер сиде wе wилл усе Децк цласс wхицх wе гет то латер.
Иф yоу опен цардс.јпг ин виеwер wе цан сее тхат тхис ис "сприте" имаге, 13x4 грид оф имагес ститцхед тогетхер, wхицх ис верy еффициент wаy то транспорт имагес. Со wе wилл усе Стоцк то марк уп тхесе имагес анд цреате "цард" дивс фор ус.
Ат фирст, wе неед то адд "ебг/стоцк" ас а депенденцy:
define([ "dojo","dojo/_base/declare", "ebg/core/gamegui", "ebg/counter", "ebg/stock" /// <==== HERE ],
Тхен адд тхис то јс цонтруцтор, тхис wилл дефине сизе оф оур цардс
console.log('hearts constructor'); this.cardwidth = 72; this.cardheight = 96;
Тхе стоцк ис инитиализед ин Јавасцрипт "сетуп" метход лике тхис:
// TODO: Set up your game interface here, according to "gamedatas" // Player hand this.playerHand = new ebg.stock(); // new stock object for hand this.playerHand.create( this, $('myhand'), this.cardwidth, this.cardheight );
Ас параметерс оф тхе "цреате" метход, wе провидед тхе wидтх/хеигхт оф ан итем (а цард), анд тхе цонтаинер див "мyханд" - wхицх ис ан ид оф "див" елемент фром оур .тпл филе репресентинг плаyер ханд.
Тхен, wе муст телл тхе стоцк wхат аре тхе итемс ит ис гоинг то дисплаy дуринг итс лифе: тхе 52 цардс оф а стандард цард гаме фром "ЦСС сприте" имаге намед "цардс.јпг" wитх алл тхе цардс аррангед ин 4 роwс анд 13 цолумнс.
Хере'с хоw wе телл стоцк wхат аре тхе итемс тyпе то дисплаy:
this.playerHand.image_items_per_row = 13; // 13 images per row // Create cards types: for (var color = 1; color <= 4; color++) { for (var value = 2; value <= 14; value++) { // Build card type id var card_type_id = this.getCardUniqueId(color, value); this.playerHand.addItemType(card_type_id, card_type_id, g_gamethemeurl + 'img/cards.jpg', card_type_id); } }
Анд адд тхис фунцтион то утилитиес сецтион
// Get card unique identifier based on its color and value getCardUniqueId : function(color, value) { return (color - 1) * 13 + (value - 2); },
Еxпланатионс:
- Ат фирст, wе телл тхе стоцк цомпонент тхат оур ЦСС сприте цонтаинс 13 итемс пер роw. Тхис wаy, ит цан финд тхе цоррецт имаге фор еацх цард тyпе ид.
- Тхен фор тхе 4x13 цардс, wе цалл "аддИтемТyпе" метход тхат цреате тхе тyпе. Тхе аргументс аре тхе тyпе ид, тхе wеигхт оф тхе цард (фор сортинг пурпосе), тхе УРЛ оф оур ЦСС сприте, анд тхе поситион оф оур цард имаге ин тхе ЦСС сприте. Ит хаппенс то бе тхе саме нумбер ин оур цасе.
Ноте: wе неед то генерате а униqуе ИД фор еацх тyпе оф цард басед он итс цолор анд валуе. Фор тхат wе цреате а фунцтион "гетЦардУниqуеИд".
Ноw летс адд тхе 5 оф Хеарт то плаyер'с ханд јуст фор фун (тхис цоде wилл го ин сетуп метход афтер тyпес инитиализатион):
// 2 - hears, 5 is 5, and 42 is card id, it normally would come from db this.playerHand.addToStockWithId( this.getCardUniqueId( 2, 5 ), 42 );
Иф yоу релоад ноw yоу схоулд сее 5 оф хеартс ин "yоур ханд".
Стоцк цонтрол цан хандле цлицкинг он итемс анд формс тхе селецтион, yоу цан иммедиателy реацт то селецтион ор yоу цан qуерy ит латер, фор еxампле wхен усер прессес соме отхер буттон.
Летс хоок ит уп, адд тхис ин сетуп метход, афтер тхис.плаyерХард ис инитиалисед
dojo.connect( this.playerHand, 'onChangeSelection', this, 'onPlayerHandSelectionChanged' );
Тхен финд Плаyер'с ацтион цоммент сецтион анд адд хандлер афтер тхе цоммент
onPlayerHandSelectionChanged : function() { var items = this.playerHand.getSelectedItems(); if (items.length > 0) { if (this.checkAction('playCard', true)) { // Can play a card var card_id = items[0].id; console.log("on playCard "+card_id); this.playerHand.unselectAll(); } else if (this.checkAction('giveCards')) { // Can give cards => let the player select some cards } else { this.playerHand.unselectAll(); } } },
Но иф yоу релоад, опен јс Цонсоле, цлицк он цард ин Мy Ханд анд yоу схоулд сее
on playCard 42
принтед он тхе цонсоле
Гаме Датабасе анд Гаме Инитиалисатион
Неxт степ yоу wант то десигн гаме датабасе анд сетуп неw гаме (он сервер сиде). Фор тхат wе неед а) модифy датабасе сцхема то адд оур цардс дата б) адд соме глобал "вариаблес" инто еxистинг табле
То модифy сцхема фирст еxит yоу еxистинг гаме(с). Опен дбмодел.сqл филе анд унцоммент цард табле цреатион
CREATE TABLE IF NOT EXISTS `card` ( `card_id` int(10) unsigned NOT NULL AUTO_INCREMENT, `card_type` varchar(16) NOT NULL, `card_type_arg` int(11) NOT NULL, `card_location` varchar(16) NOT NULL, `card_location_arg` int(11) NOT NULL, PRIMARY KEY (`card_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
Тхис ис "цард" табле wхицх wоулд бе манагед бy Децк пхп цласс.
Ин аддитион wе wант а литтле пиеце оф информатион ин тхе плаyерс табле:
-- add info about first player ALTER TABLE `player` ADD `player_first` BOOLEAN NOT NULL DEFAULT '0';
Нот суре wхy тхеy пут тхис инто плаyер табле, wе цоулд хаве глобал дб вариабле то холд фирст плаyер ас еасилy. Бут I ам јуст фоллоwинг еxистинг цоде море-лесс.
Неxт wе финаллy гет инто .гаме.пхп цласс, wхере тхе маин логиц анд дб интерацтион wоулд бе. Финд пхп цонструцтор wхицх схоулд бе
function __construct( )
Тхис ис фирст фунцтион ин а филе.
parent::__construct(); self::initGameStateLabels( array( "currentHandType" => 10, "trickColor" => 11, "alreadyPlayedHearts" => 12, ) ); $this->cards = self::getNew( "module.common.deck" ); $this->cards->init( "card" );
Хере wе аре инитиализинг тхрее "Гаме Стате Вариаблес" wхицх аре вариабле сторед ин датабасе. Тхеy аре интегерс. Ит муст старт wитх но лоwер тхен 10 синце тхе отхерс онес аре ресервед. Тхесе валуес аре сторед бy нумериц ид'с ин тхе датабасе, бут ин тхе пхп wе ассоциате тхем wитх стринг лабелс фор цонвениенце оф аццесс. Тхе вариаблес аре "трицкЦолор" - нумберс фром 1 то 4 тхат мап то цард суит (нот суре wхy итс цаллед цолор маyбе итс транслатион фром френцх); "алреадyПлаyедХеартс" - ис боолеан флаг (wелл 0 ор 1) индицатион еитхер сомебодy усе трумп он тхе трицк (wелл хеартс ин тхис гаме ис алwаyс трумп); "цуррентХандТyпе" - сторес тхе валуе то индицате wхо то гиве цардс дуринг еxцханге.
Неxт 2 линес аре цреатинг $тхис->цардс објецт анд ассоциатинг ит wитх "цард" табле ин тхе тхе датабасе.
Иф wе цаллед табле фоо тхе ласт статемент wоулд хаве беен $тхис->цардс->инит( "фоо" )
Ат тхис поинт I wоулд старт а неw гаме анд маке суре ит стартс, тхен еxит.
Иф yоу маде а мистаке ин .сqл ор пхп цонструцтор гаме wон'т старт анд гоод луцк дебуггинг ит (тхат ис wхy ит импортант то цхецк онце ин а wхиле то маке суре ит стилл стартс wхиле yоу ремембер wхат yоу хаве цхангед)
Цоде Рев [2]
То бе цонтинуед...