In deze applicatie kunnen pokemon-trainers het tegen elkaar opnemen en een gevecht starten in een realtime Pokemon arena.
In deze applicatie kunnen de gebruikers een Pokemon battle met elkaar beginnen. Wanneer een gebruiker in de lobby komt, moet er een Pokemon uitgekozen worden die aan hun zijde gaat vechten. Wanneer een pokemon aanvalt, zal de damage worden gebaseerd op de typering van de pokemons (zie Damage-chart) . De pokemon battle gaat door totdat een van de pokemons niet meer kan vechten, wat zal gebeuren wanneer de health bar
nul bereikt. Na een gevecht krijgt de winnende gebruiker een victory
scherm en worden beide spelers terug gestuurd naar het begin scherm.
Als de gebruiker zich aanmeldt om een pokemon trainer te worden, wordt die doorverwezen naar de geselecteerde lobby. Wanneer er twee gebruikers in de lobby zijn en ze aan de voorwaardes voldoen, is het mogelijk om een battle te starten.
Damage-chart
Hierbij ga ik voornamelijk gebruik maken van de eerste drie in deze lijst.
- 2 super-effective Super Effective
- 1 normal-damage Normal
- 0.5 not-very-effective Not Very Effective
- 0 no-effect No Effect
- Het concept
- Features
- Installatie
- Ultieme applicatie schetsen
- Data lifecycle diagram
- Socket server events
- Socket client listeners
- The RESTful Pokémon API
- Conclusie
- Bronnen
- Credits
Dit zijn de verschillende features die ik wil gaan toevoegen aan mijn applicatie (MOSCOW)
[M] Must haves
deze eisen moeten in het eindresultaat terugkomen, zonder deze eisen is het product niet bruikbaar
- Het kunnen starten van een Pokemon battle wanneer er twee gebruikers aanwezig zijn in een lobby.
- Het kunnen uitvechten als twee pokemon trainers in een battle waar maar een iemand de winnaar kan zijn.
- Het kunnen ophalen van
health
uit de Poké API. - Beurten systeem waar gebruikers elkaar om de beurt kunnen aanvallen en door middel van deze aanvallen gaat de Pokemon
health
naar beneden (player one starts).
- Het kunnen ophalen van
- Victory/defeat message naar beide spelers.
[S] Should haves
deze eisen zijn zeer gewenst, maar zonder is het product wel bruikbaar
- Het kunnen inloggen als Pokemon-trainer.
- Naam: Jouw eigen pokemon-trainer naam.
- Gym: Dit zijn de verschillende lobbies die toegetreden kunnen worden.
- Gender: De mogelijkheid om een vrouwelijke of mannelijke personage te kiezen.
- Het kunnen zien van een gebruikers lijst van de huidige lobby.
- Het kunnen zien van lobby notificaties.
- Gebruikers krijgen een welkomst notificatie te zien als ze de lobby toetreden
- Gebruikers krijgen een notificatie te zien wanneer er een gebruiker toetreedt of weggaat.
- Het kunnen zoeken en kiezen van een Pokemon om mee te gaan strijden.
- Het weergeven van een Pokemon gerelateerde huisstijl.
- Het kunnen zien van
game-messages
tijdens de Pokemon battle. - Het kunnen zien van een visuele
health-bar
die gelinkt is aan de Pokemonhealth
- Als een gebruiker de battle room verlaat, heeft de andere speler automatisch gewonnen.
- Victory/Defeat pop-up nadat de battle over is.
[C] Could haves
deze eisen zullen alleen aan bod komen als er tijd genoeg is
- Het battle Interface design laten lijken op de ouderwetse Pokemon battles.
- Een limiet aan de lobbies toevoegen van twee spelers (Disable option when full)
- Er kunnen meerdere battles tegelijkertijd plaats vinden.
- Pokemon attacks worden gebasseerd op de typering van de Pokemons.
- Super Effective (Water > Fire)
- Normal (Water = Normal)
- Not Very Effective (Fire < Water)
- No Effect (Normal < Ghost)
- Tijdens een Pokemon battle kunnen gebruikers eenmaal hun eigen Pokemon
healen
. - Tooltip die de gebruiker navigeert naar de
search
functionaliteit - Error bericht wanneer gebruiker foute input geeft tijdens het zoeken van een pokemon.
[C] Wont haves
deze eisen zullen alleen aan bod komen als er tijd genoeg is
Lobby
- Het kunnen bewegen van jouw gekozen personage op de
city map
. - Punten systeem dat wordt bijgehouden in een scoreboard systeem.
- Winkels maken waar gebruikers hun punten kunnen spenderen. (Heal/ATT_BOOST/DEF_BOOST items)
- Wanneer gebruikers tegen elkaar aanlopen of op elkaar klikken opent er een menu.
- Gebruikers kunnen een battle starten.
- Gebruikers kunnen elkaar toevoegen als vrienden (Profile/friend system).
- Gebruikers kunnen elkaars Pokemon zien.
- Gebruikers kunnen in-game items met elkaar traden.
- Gebruikers kunnen elkaars
balance
zien.
- Mogelijkheid om tegen een
AI gym
te vechten om op deze manierpunten
te verdienen.
Battle
- De gebruiker heeft de keuze uit vier Pokemon attacks die gerelateerd zijn aan de gekozen Pokemon.
- Tijdens een Pokemon battle kan de gebruiker items gebruiken die hij/zij heeft gekocht.
Clone de repository van het project
git clone https://github.com/RooyyDoe/real-time-web-1920.git
Navigeer naar de map
cd real-time-web-1920
Installeer dependencies
npm install
Run de server in je terminal
npm run dev
Server runt dan op: localhost:5000
Demo kun je ook bekijken op: Poké fight
Poké fight lobby
-
Iedere socket die de lobby joined, krijgt een persoonlijke personage die hij/zij kan voortbewegen. Dit zou gebeuren via de
pijltjes
of deWASD
toesten.- Gebruikers zouden alleen kunnen lopen op gebieden waar dit mogelijk is en door tegen bepaalde elementen aan te lopen zou er een interactie ontstaan.
-
Wanneer gebruikers tegen elkaar aan lopen of op elkaar klikken komt er een selectie menu tevoorschijn. In dit menu staan verschillende interactie opties:
- Battle now: Hier kunnen gebruikers elkaar uitdagen om een battle te starten
- Add friend: Dit zou een systeem moeten zijn om elkaar toe te voegen in een vriendenlijst. Dit zou het dan makkelijk maken om elkaar weer uit te nodigen voor een rematch battle.
- Show pokemon: Hier kan je de pokemon zien die deze gebruiker heeft gekozen.
- Trade now: Een mogelijk trade systeem waar je items kan traden met elkaar voor bijvoorbeeld
in-game money
- Balance: ... Hier zie je hoeveel punten/geld de gebruiker heeft
- Inventory: Deze is alleen zichtbaar wanneer je op je eigen personage klikt. Op deze manier kan je kijken wat voor items je in je inventory hebt zitten.
-
Het is mogelijk om met de punten die je verdient tijdens het vechten van battles items te kopen die je kan gebruiken tijdens een battle. Hierbij kan je denken aan een
healing potion
of eenstrength boost
. -
Om het wat makkelijker te maken voor gebruikers wil ik AI custom battles maken door middel van de interactie met de
gym
van de city. Wanneer een gebruiker naar degym
toeloopt kan hij/zij een battle starten en wanneer je deze wint verdien je muntjes waar je dus uiteindelijk items mee kan kopen of kan ruilen.Er zijn hoogst waarschijnlijk genoeg develop functionaliteiten waar ik rekening mee moet houden. Zelf heb ik zitten denken aan functionaliteiten zoals: localStorage, Iets wat een live positie kan bijhouden, Punten systeem, Interactie met elkaar, Anti cheat ( timers op AI custom battles, etc )
Poké fight battle
- Wanneer de gebruiker op de
attack
button klikt veranderen de vier menu items naar vier verschillende aanvallen van jou geselecteerde pokemon. Deze aanvallen hebben een max aantal selecties, zodat je ze niet kan spammen. Elke aanval heeft zijn eigen damage en zal meer damage doen als het tegen een zwakkertype
is. - Tijdens een battle kan je driemaal van items gebruik maken. Dit kan een boost voor je pokemon geven of hem/haar healen voor een bepaald percentage.
- Als je geen zin meer hebt in de battle kun je altijd leaven. Het geldt dan wel dat je automatisch hebt verloren en de punten dus naar de tegenstander gaan.
- Hier wordt er feedback gegeven aan de gebruiker door kleine pop-ups die vertellen wat er allemaal gedaan kan worden.
- Hier komen de feedback messages binnen die er komen tijdens een battle. Ook staat hier precies in wat er gaat gebeuren of moet gebeuren.
- Het algemene battle screen. Hier komen twee pokemons tegenover elkaar te staan die het tegen elkaar gaan opnemen. Vanuit je eigen view zal je altijd onder aan staan en is het rechter HP element van jou. Je zal zien wanneer er HP af gaat bij je pokemon en ook wanneer er HP afgaat bij de tegenstander.
notification
Elke keer wanneer een gebruiker de kamer toetreedt, zal hij een welkomst bericht krijgen. Als een nieuwe gebruiker zijn lobby
toetreedt, komt hier een notificatie van. Deze notificatie is ook zichtbaar wanneer er een gebruiker de lobby
verlaat.
gym-users
Met dit event wordt er een array
doorgestuurd met hierin een lijst van gebruikers die in een bepaalde gym zijn toegetreden. Deze array
wordt uitgelezen en weergegeven op het scherm van de gebruikers. De gebruikers zullen in de lobby een lijst zien met zichzelf en de tegenstander waar hij/zij tegen moet spelen.
return-search-results
Nadat alle API
calls zijn gedaan, wordt de benodigde data naar de client
gestuurd. In de API
calls wordt een object
gemaakt waar alle nodige informatie instaat over de gekozen pokemon. Door deze door te sturen naar de client
kan alle data worden toegevoegd aan elementen in het lobby/battle scherm.
battle-start
Wanneer beide gebruikers op de start
knop hebben gedrukt, begint de battle. De lobby layout verandert naar de battle room
layout en alle elementen die nodig zijn voor de battle worden ingeladen. Hiermee moet je dus denken aan de health-bar
, Pokemon naam
, Pokemon image
en battle-messages
/ attack-button
health-checker
Elke keer wanneer er een aanval is geweest, wordt de nieuwe health
doorgestuurd naar de client en hier geupdate. Op deze manier ziet de gebruiker precies hoeveel damage hij heeft aangericht bij zijn tegenstander.
turn-checker
In een pokemon battle moet je natuurlijk om de beurt kunnen aanvallen en dit event zorgt hiervoor. Hij checkt elke keer wanneer er een aanval is geweest welke speler er nu aan de beurt is. Dit doe ik door middel van een turn_player1
boolean. Deze houdt bij wanneer speler 1 aan de beurt is en op deze manier geeft die dit door aan de client-side
game-over
Wanneer een van de Pokemons op 0 health
komt te staan heeft deze speler verloren. Dit wordt in elke aanval gecheckt en wanneer de if
statement op true
komt te staan geeft die een victory
/defeat
scherm door aan de winnaar en verliezer.
leave-lobby
Wanneer een gebruiker de applicatie verlaat wordt hij/zij uit de user-list
verwijderd. Ook wordt de leave message
afgevuurd waardoor de andere spelers hier een notificatie over krijgen.
leave-buster
Deze socket houd bij hoeveel gebruikers er in de lobby zitten tijdens de battle. Wanneer een gebruiker de battle verlaat zonder hem af te maken zal de andere speler een victory scherm te zien krijgen.
join-lobby
Als de gebruikers de benodigde gegevens hebben ingevuld op het inlog scherm en de lobby toetreden, wordt de ingevulde informatie direct doorgestuurd naar de server-side
. De gebruikers informatie wordt bijgehouden in een user-array
. Op deze manier houd ik bij hoeveel gebruikers er aanwezig zijn en in welke lobby
ze zitten.
search-results
De gebruikers kunnen hun Pokemon uitkiezen door deze op te zoeken in de search-bar
. Wanneer ze de Pokemon naam hebben geschreven in de search-bar
en daarna op de knop hebben gedrukt, wordt de input
waarde naar de server-side
gestuurd.
join-battle
Wanneer de gebruikers op de start-battle
knop drukken begint de battle en verandert het lobby
scherm naar het battle
scherm. Alle data verkregen vanaf de server-side
wordt in elementen geladen, zodat de gebruikers een bruikbare interface krijgen.
on-attack
Elke keer wanneer een gebruiker op de attack
knop drukt, wordt er een event gestuurd naar de server-side
. Hier worden alle functionaliteiten zoals de health-checker
en turn-checker
afgehandeld.
on-heal
Elke keer wanneer een gebruiker op de heal
knop drukt, wordt er een event gestuurd naar de server-side
. Hier worden alle functionaliteiten zoals de health-checker
en turn-checker
afgehandeld.
Dit is een RESTful API
die zeer gedetailleerde objecten teruggeeft die opgebouwd zijn uit duizenden regels. De informatie uit deze API is volledig gerelateerd aan Pokémon en alles wat hierbij komt kijken. Om deze API
te gebruiken heb je geen authenticatie nodig en alle bronnen zijn volledig open en beschikbaar.
Welke data kan je uit deze API verkrijgen?
- Moves
- Abilities
- Pokémon (Including various forms)
- Types
- Game versions
- Items
- Pokédexes
- Pokémon Evolution Chains
Wanneer je de API
aanroept zonder een ID of naam mee te geven, krijg je het object
hier beneden terug. Hier maken ze gebruik van pagination en je krijgt 20 resultaten per API aanroep. Als je het limiet van de resultaten wil vergroten, kan je een query parameter
mee geven om op deze manier meer resultaten terug te krijgen.
{
"count": 248,
"next": "https://pokeapi.co/api/v2/ability/?limit=20&offset=20",
"previous": null,
"results": [
{
"name": "stench",
"url": "https://pokeapi.co/api/v2/ability/1/"
}
]
}
In eerste instantie heb ik de API (endpoint) nodig die één specifieke pokemon ophaalt doordat de gebruiker een search uitvoert. Als deze API call is gedaan kijk ik naar de typering
die de pokémon heeft en doe met deze informatie nogmaals een API call om de damage_relations
te verkrijgen uit de poké API.
GET https://pokeapi.co/api/v2/pokemon/{id or name}/ // For the pokemon data
GET https://pokeapi.co/api/v2/type/{id or name}/ // For the damage_relations data
RAW Json Pokémon API call
{
"id": 12,
"name": "butterfree",
"base_experience": 178,
"height": 11,
"is_default": true,
"order": 16,
"weight": 320,
"abilities": [
{
"is_hidden": true,
"slot": 3,
"ability": {
"name": "tinted-lens",
"url": "https://pokeapi.co/api/v2/ability/110/"
}
}
],
"forms": [
{
"name": "butterfree",
"url": "https://pokeapi.co/api/v2/pokemon-form/12/"
}
],
"game_indices": [
{
"game_index": 12,
"version": {
"name": "white-2",
"url": "https://pokeapi.co/api/v2/version/22/"
}
}
],
"held_items": [
{
"item": {
"name": "silver-powder",
"url": "https://pokeapi.co/api/v2/item/199/"
},
"version_details": [
{
"rarity": 5,
"version": {
"name": "y",
"url": "https://pokeapi.co/api/v2/version/24/"
}
}
]
}
],
"location_area_encounters": "https://pokeapi.co/api/v2/pokemon/12/encounters",
"moves": [
{
"move": {
"name": "flash",
"url": "https://pokeapi.co/api/v2/move/148/"
},
"version_group_details": [
{
"level_learned_at": 0,
"version_group": {
"name": "x-y",
"url": "https://pokeapi.co/api/v2/version-group/15/"
},
"move_learn_method": {
"name": "machine",
"url": "https://pokeapi.co/api/v2/move-learn-method/4/"
}
}
]
}
],
"species": {
"name": "butterfree",
"url": "https://pokeapi.co/api/v2/pokemon-species/12/"
},
"sprites": {
"back_female": "http://pokeapi.co/media/sprites/pokemon/back/female/12.png",
"back_shiny_female": "http://pokeapi.co/media/sprites/pokemon/back/shiny/female/12.png",
"back_default": "http://pokeapi.co/media/sprites/pokemon/back/12.png",
"front_female": "http://pokeapi.co/media/sprites/pokemon/female/12.png",
"front_shiny_female": "http://pokeapi.co/media/sprites/pokemon/shiny/female/12.png",
"back_shiny": "http://pokeapi.co/media/sprites/pokemon/back/shiny/12.png",
"front_default": "http://pokeapi.co/media/sprites/pokemon/12.png",
"front_shiny": "http://pokeapi.co/media/sprites/pokemon/shiny/12.png",
"other": {
"dream_world": {},
"official-artwork": {}
},
"versions": {
"generation-i": {
"red-blue": {},
"yellow": {}
},
"generation-ii": {
"crystal": {},
"gold": {},
"silver": {}
},
"generation-iii": {
"emerald": {},
"firered-leafgreen": {},
"ruby-sapphire": {}
},
"generation-iv": {
"diamond-pearl": {},
"heartgold-soulsilver": {},
"platinum": {}
},
"generation-v": {
"black-white": {}
},
"generation-vi": {
"omegaruby-alphasapphire": {},
"x-y": {}
},
"generation-vii": {
"icons": {},
"ultra-sun-ultra-moon": {}
},
"generation-viii": {
"icons": {}
}
}
},
"stats": [
{
"base_stat": 70,
"effort": 0,
"stat": {
"name": "speed",
"url": "https://pokeapi.co/api/v2/stat/6/"
}
}
],
"types": [
{
"slot": 2,
"type": {
"name": "flying",
"url": "https://pokeapi.co/api/v2/type/3/"
}
}
]
}
Wat ik uiteindelijk nodig had voor mijn project was niet de volledige JSON. Daarom heb ik hiervoor een apart object
gemaakt met hierin de benodigde informatie voor mijn applicatie.
Mijn Pokémon object
{
name: **String**,
sprites: {
display: **String**,
back: **String**,
front: **String**,
},
health: **String**,
in_health: **String**,
type: **String**,
weight: **String**,
}
Uiteindelijk wilde ik dat de damage_relations
ook bij dit object kwamen om op deze manier te beïnvloeden welke types er meer of minder damage deden tegen elkaar.
Mijn uiteindelijke pokémon Object
{
name: **String**,
damage_relations: {
double_damage_from: [ Array ],
double_damage_to: [ Array ],
half_damage_from: [ Array ],
half_damage_to: [ Array ],
no_damage_from: [ Array ],
no_damage_to: [ Array ],
}.
sprites: {
display: **String**,
back: **String**,
front: **String**,
},
health: **String**,
in_health: **String**,
type: **String**,
weight: **String**,
}
Voordat ik aan dit vak was begonnen had ik een doel voor mijzelf gesteld. Dit doel was om een zo uitgebreid mogelijke real-time applicatie te bouwen. Vorig jaar is me dit niet gelukt en ik wilde mijzelf bewijzen dit jaar. Dit is mij zeker gelukt en ben hartstikke trots op het eind resultaat wat ik heb neer gezet. In eerste instantie wilde ik gewoon een pokemon battle maken waar twee speler tegen elkaar konden gaan spelen zonder teveel moeilijke functionaliteiten. Uiteindelijk is de applicatie toch een stuk groter geworden dan ik had verwacht en kwamen hier verschillende moeilijkheden bij kijken. Het bijhouden van player1
en player2
en alles wat hierbij kwam kijken vond ik lastig, maar deste meer tijd ik in het project had besteedt, lukte het me steeds beter. Ook het begrijpen van de sockets ging me steeds beter af, waardoor ik nog meer functionaliteiten kon toevoegen aan de applicatie.
De manier waarop de rubric is gemaakt vond ik erg lastig. Je wordt erg open gelaten in wat je kan doen en je moet eigenlijk zelf uitzoeken hoe je een hoger cijfer haalt dan een 5.5. Ik heb er natuurlijk zoveel mogelijk uitgehaald en heb geprobeerd wel degelijk meer te doen dan de basis van de rubric, maar toch weet ik nog steeds niet precies waar ik sta. Achteraf had ik hier misschien wat meer sturing in gehad.
al met al heb ik weer erg van dit vak genoten, ook al heb ik veel lastige momenten gehad waar ik echt niet meer wist hoe ik verder kon gaan. Door het volhouden en hulp vragen wanneer nodig heb ik het goed voor elkaar gekregen.
- Mozilla Developer Network - Hier haal ik de meeste Javascript kennis vandaan
- Socket IO documentatie - Basis socket IO documentatie
- API documentatie - Alles wat ik nodig had om deze API te gebruiken
- Thijs Spijker - Heeft me geholpen met een
could have
voor het lobby limiet en meer.. - Isabella - Mijn Rubberduck en metale steun.