Hra pro děti: Monopoly

Školení, která pořádám

ukázka ze hryS dětmi jsem naprogramoval další hru: Monopoly. Hra je podle pravidel verze, kterou jsme dostali někde v sámošce. Herní plán byl strašně malý, figurky z něj padaly a písmena byla sotva čitelná. Proto jsme se rozhodli hru přesunout na počítač, čímž jsme navíc oproštěni od monotónních činností jako házení kostkou, posouvání figurky nebo počítání částek. Můžeme se tak soustředit na to, co je na hře nejzábavnější – uvážené investování (hlavně v menším počtu hráčů nelze kupovat vše, protože vám dojdou peníze a nezbude na nákup nemovitostí, které políčka zhodnocují) a obchody mezi sebou. Pokud už jsou navíc „karty rozdány“ a nikdo nechce nic prodávat, tak jde hru jednoduše dosimulovat a zjistit, kdo vyhraje. Pravidla jsou oproti stolní verzi trochu upravená, někdy záměrně, jindy z lenosti:

Ke zdrojovým kódům mám několik postřehů:

  1. Samotného mě překvapilo, jak volně se prolínají data a funkce. Např. pole karet s náhodami je definované takto: [goToNearestRail, goTo.bind(this, 11), function get50FromEveryone(player) { /* ... */ }, ...]. Hodnoty v poli jsou funkce, které se při vytažení karty prostě zavolají. V jiném jazyce bych asi zvolil jiné řešení, ale v JavaScriptu mi to přišlo přirozené.
  2. Dost mi chyběla normální dědičnost, která je k dispozici až v ES6. Zazdít staré prohlížeče nebo používat emulaci se mi nechtělo, tak jsem to nakonec vyřešil definicí globální funkce a jejím zavoláním např. pomocí visitRailOrService.call(this, this.amounts, player), ale dvakrát nadšený z toho nejsem.
  3. Animaci pohybu figurek jsem vyřešil triviálním transition: top 1s, left 1s. Ještě jsem chtěl udělat, aby figurka v případě zahájení dalšího tahu skočila na cílové místo a znovu se začla animovat tam odtud, to se mi ale nepovedlo.
  4. V kódu hodně používám bind, což si vynucuje pořadí parametrů funkcí. Např. funkci earn bych měl radši se signaturou earn(player, amount). Ale vzhledem k tomu, že ji často používám jako earn.bind(this, 50), což pak volám s argumentem player, tak musí být pořadí parametrů obráceně.

Hru si můžete zahrát online. Ještě se chystám udělat Dostihy a sázky, které se hrají velmi podobně, což by mohlo pomoci s oddělením herního enginu od herních dat. Dodělal jsem také Dostihy a sázky.

Jakub Vrána, Výuka, 21.4.2017, diskuse: 13 (nové: 0)

Diskuse

ikona Ondra:

Ahoj,

rád si nechám ještě detailněji vysvětlit, co přesně nového přináší "normální dědičnost", když ES6 classes jsou jen syntax sugar.

Tedy, definice potomka:

Potomek.prototype = Object.create(Predek.prototype);

A volání metody předka:

Potomek.prototype.a = function() {
  /* ... */
  return Predek.prototype.a.call(this);
}

Časté použití .bind u posluchačů událostí lze vyřešit pomocí rozhraní https://developer.mozilla.org/en-US/docs/Web/API/EventListener, tj.

node.addEventListener("event", this);

...a nebo prostě pomocí arrow functions, ale to jsem dle textu článku pochopil jako zapovězené ("emulace" = "babel") ?

Martin Prokeš:

Jakub by si měl nastudovat https://github.com/getify/You-Dont-Know-JS

ikona Jakub Vrána OpenID:

Na Object.create jsem úplně zapomněl, díky za tip. Předělám to na to.

Ten bind mě tolik netrápí.

ikona Jakub Vrána OpenID:

Kašlu na to, u Object.create se musí ještě ručně přenastavit .constructor, což to dělá komplikovanější, než jsem ochoten snést.

ikona Ondra:

To je sice pravda, ale ne vždy se .constructor k něčemu skutečně použije. Vlastně asi jen pokud chci v prototypových metodách přistupovat k "statickým" vlastnostem vytvořující funkce. A to už můžu použít konstantu (a nějakou vhodnou formu izolace). Nebo máš nějaký další use case pro .constructor?

ikona Jakub Vrána OpenID:

Používám to na hledání objektů stejného typu: field instanceof this.constructor.

Martin Prokeš:

Co znamená "s dětmi jsem naprogramoval"?

Kolik jim je, jaká je metodika výuky?

ikona Jakub Vrána OpenID:

Zrovna u této hry jsem je jen nechal vymýšlet, jak se to bude ovládat, třeba jak se budou prodávat místa (jaké, komu a za kolik). Taky jsem je nechal zadat data (ceny míst a podobně). U psaní kódu se na mě občas koukaly a čas od času jsem jim vysvětlil, proč něco dělám daným způsobem, např. proč něco přiřazuji do proměnné nebo proč z něčeho dělám funkci. U jednodušších her jsem je nechal i napsat nějaký jednoduchý kus kódu, např. podmínku nebo cyklus.

Jinak na učení používám spíš https://codecombat.com/, to jde po malých kousíčkách, hodně to napovídá a je v tom herní prvek, že si za úspěchy můžou něco kupovat.

Je jim 8 a 12.

Matej:

Skusam to "hrat" drzanim entru :) a vyzera to ze kazdy hrac iba zaraba :) dobra to ekonomika :)

ikona Aleš Dostál OpenID:

Ahoj Jakube,
Zrovna dneska jsem si řekl, že zkusím přepsat "Dostihy a sázky", což jsou vlastně komunistické Monopoly, protože tenkrát bylo pro "komanče" příliš velké sousto, aby si děti hraly na kapitalisty :D

https://www.youtube.com/watch?v=ZP8AkLIzqbc

Jestli se k těm dostihům dostaneš, tak bude alespoň nějaká konkurence :) Popřípadě se můžeme domluvit a udělat to společně.

Já tedy šel rovnou do osvědčeného stacku (React, Redux, Typescript) v ES6 s transpilací do ES5. Přeci jen, nevyužívat nové vlastnosti JS jazyka je velká škoda.

Každopádně musím smeknout, jestli takhle malé děti jsou schopny to pochopit a tvořit.

ikona Jakub Vrána OpenID:

Dostihy a sázky jsem vyrobil: https://vrana.github.io/games/monopoly/dostihy.html. Zásadní věc navíc proti Monopolům tam je sázení (na koně s alespoň třemi dostihy, pokud má sázející taky někde tři dostihy), to hru dost oživuje.

Já s tím nemám žádné ambice, jen si to chci zahrát s dětmi. Spousta věcí je tam jen narychlo spíchnutých, přeci jen musím vážit mezi časem věnovaným programování a časem věnovaným dětem.

Kód píšu obvykle já. U některých jiných her jsem je nechal i něco napsat, ale vyžaduje to dost pečlivosti, kterou ještě moc nemají. U této hry spíš mluvily do toho, jak se to bude ovládat, co budeme programovat a tak.

Danny:

Monopoly neznám a Dostihy si pamatuji z dětství jen matně, ale nemělo by se něco stát, když někomu dojdou peníze? Zkušebně si to hraju a Jakub vydrtil nákupy Kryštofa a Prokopa tak, že jsou oba v mínusu a hra stále jede...

(Pro debug: nejsou ještě obsazeny všechny nemovitosti)

ikona Jakub Vrána OpenID:

Podle normálních pravidel ano, ale my jsme si je trochu uzpůsobili. Hráči se stejně nevyplatí být dlouhodobě v mínusu (nemůže nic kupovat ani vsázet), takže má sám zájem na tom se z mínusu dostat. Není ho tak třeba trestat tím, že by třeba musel něco prodat, což mu hru většinou velmi rychle prohraje.

Diskuse je zrušena z důvodu spamu.

avatar © 2005-2024 Jakub Vrána. Publikované texty můžete přetiskovat pouze se svolením autora. Ukázky kódu smíte používat s uvedením autora a URL tohoto webu bez dalších omezení Creative Commons. Můžeme si tykat. Skripty předpokládají nastavení: magic_quotes_gpc=Off, magic_quotes_runtime=Off, error_reporting=E_ALL & ~E_NOTICE a očekávají předchozí zavolání mysql_set_charset. Skripty by měly být funkční v PHP >= 4.3 a PHP >= 5.0.