Hra pro děti: Monopoly
Školení, která pořádám
S 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:
- V náhodě není karta pro vykoupení se z vězení.
- Z vězení se dostanete buď hozením dvou stejných čísel hned nebo automaticky v příštím kole.
- Pokud hodíte dvě stejná čísla, neházíte znovu. Tím pádem se ani třemi hody za sebou nemůžete dostat do vězení.
- S penězi se můžete dostat do mínusu, nemůžete ale pak už nic kupovat.
- Ulice se dá prodat i v případě, že jsou na některé ulici v dané čtvrti nakoupené domy. Další domy se pak ale nedají dokupovat, pokud nemáte celou čtvrť.
- Nelze nic prodat bance, jen jiným hráčům.
- Při vstupu na Energetické závody nebo Vodárnu se nehází znovu kostkami, ale použije se hodnota, jakou se tam hráč dostal.
Ke zdrojovým kódům mám několik postřehů:
- 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é.
- 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.
- 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.
- 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.
Diskuse
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") ?
Na Object.create jsem úplně zapomněl, díky za tip. Předělám to na to.
Ten bind mě tolik netrápí.
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.
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?
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?
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 :)
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.
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)
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.