Following Cohort 9’s group presentations, Rory looks back on the process of creating a Pokémon project with his team.
Day one of our project started with probably the easiest decision we had all week: deciding on what app to create. The first idea suggested was a simplistic Pokémon-meets-Top Trumps game utilising the Pokémon api.
As soon as we realised this was feasible (and not too ambitious), the enthusiasm of becoming a Pokémon master took over and all other ideas were quickly forgotten.
The planning process began and quickly progressed from diagrams, constructors and arrays to the really important details, such as which CodeClan Instructors were going to be photoshopped on to what Pokémon Gym leader’s bodies… and whether Professor Matthew would be dancing (Spoiler: He was).
To sum up the less interesting planning stage, I think the group as a whole came away with a really solid plan of what a completed “game” would look like and a rough idea of what we had defined as a minimum viable product we could present just seven days later.
We fully expected to land somewhere between those margins in no doubt that we would meet our relatively challenging MVP.
The group’s discussion about what we expected to have to allocate the most amount of time to, and what would be relatively simple was…slightly…or rather completely… wrong.
A meme that has lived on beyond this project, as a now infamous line, was: “I will solve this in five minutes before bed tonight”.
Unfortunately, the following day, with four group members’ focus and assistance from instructors, we eventually solved that problem after seven hours work… and the five minutes, of course.
We were struggling to find a way to not make too many requests to the Pokémon API.The Pokémon API was divided in such a way that the list of the 151 Pokémon were provided by one address, but the details about each specific Pokémon that needed to fight against each other were provided by another address. We really anticipated this would be as simple as making a request to one api, then based on that response make a request to another.
The responses we received weren’t at all what we were expecting, rather than receiving an error or zero Pokémon objects back, we were receiving different quantities… 87…89…84…92 on each request for 151 Pokémon objects.
Whilst this did put us a bit behind schedule, realising that we were making our requests consecutively, yet receiving our 151 responses simultaneously, we learned a valuable lesson and this certainly wasn’t something we had planned to overcome.
We eventually reached a compromise with the server of it collecting 148 of the Pokémon we asked for, then we would find out which Pokémon it missed and make a request for just those three. This was a brute force method that we weren’t delighted to have to use, but we had now built our own API of all 151 Pokémon with all the relevant statistics we needed for each Pokémon.
A secondary stumbling block we hadn’t planned for was getting the data from the response to the scope of the “game” file. After some assistance, we understood the problem and attempted to solve this ourselves.
Our solution wasn’t the most elegant and was the beginning of some quite repetitive code. It was at this point we accepted we may be producing quite ugly code that was definitely due for refactoring, however with a seven day deadline we were satisfied with our code getting the job done from that point on.
Our Main Rival
While our API woes were unexpected, eventually they were solved once we understood the problems. However, a constant thorn in our side from day one to day seven was GitHub. Extremely useful and versatile…once you figure out what you are doing.
In the first 12 weeks at CodeClan, GitHub usage had become second nature. Being the sole contributor to a single branch was the perfect way for ‘git push’ing my blissful ignorance to the point I thought I “knew how to use GitHub”.
I was wrong.
Collaborating on GitHub turned out to be the topic I learnt the most about, the CheatSheet for group Git usage we followed for the project was pretty foreign to me on day one. I was following the steps, it was working, but it wasn’t until day five or six I really felt confident in what I was doing.
Then I was comfortable missing out steps because I knew what they were doing and that they weren’t about to set the master branch on fire.
Building Pallet Town
As fun as GitHub torture and problems were, the coolest part of this project for me was seeing the Pokémon canvas/map we created interact with the logic and API to make a game.
To create the canvas below, we took screenshots of different elements within a Pokémon emulator and added them to certain x,y coordinates.
For the image above: the three buildings and the central person were placed and then using their outline, a block was placed on the canvas which prevented the user (bottom-left) from walking through the house walls with the directional buttons.
At this point, our logic wasn’t ready to incorporate into the canvas, so we set up a framework for triggering different functions based on the users x,y coordinates on the canvas and whether they pressed the A-button (offscreen). For instance, standing in front of the door in the top left and pressing A-button would trigger gym-one’s fight scene.
With this canvas/framework being far beyond what we required for completing our MVP, it was time to go back to completing the logic to assign each trigger before spending any more time on the aesthetics.
Pokemon Logic: Poké Doké Is Confused
The Pokémon logic that we built was simple, pressing the A-button in different places (a long IF statement) triggered different events (a function). Great.
The downsides of this, as stated earlier, was that our code became incredibly long winded and we found ourselves copy-pasting certain functions with slight changes, rather than a more elegant replicable function.
To speak about the overall game logic of what we would consider “beating” the game, we began by setting up our database and then populating an array of Unused Pokemon. On creation, all 151 Pokémon are “unused” and from there one Pokémon is assigned as a starter.
It is now up to the player to collect the next Pokémon from the grass, which will spawn a wild Pokémon to be caught from the remaining 150. By catching this Pokémon, they will be removed from the “unused” Pokémon array and pushed to the Pokédex array of the player.
The end screen, or the game being beaten, will only be triggered when the “unused” Pokémon equals zero, as this would mean the players Pokédex equals 151.
The building of each aspect of the gym, grass and home’s logic can be read more thoroughly on GitHub. To explain the intricacies of a fight in the grass, the user is within the grassy area in the bottom right of the canvas and there is a 1/10 chance that a fight will be initiated. From here, an “unused” Pokémon is placed against the first Pokémon in the player’s hand (a chosen subset of his Pokédex).
A turn based formula is utilised to determine a winner by comparing their Current Health Points, Attack and Defence. If the wild Pokémon wins, the player is forced to use his next Pokémon or return home to heal his squad. If the player wins, the wild Pokémon is then added to the Pokédex.
The first challenge of this section of work was finding a way for Pokémon’s current HP to persist between fights whilst remembering what the initial HP was for healing back to full health at home. To do this we assigned each Pokémon object another property called fightHP, this way we could utilise two different HP’s to solve our problem as well as allow us to make a progress bar for the fight screen interface.
The most difficult problem we encountered in the logic was finding a way to have the A-Button perform different actions depending on what screen it was on. For instance, when on the canvas, we are using the A-Button to enter houses. However, when we are in a fight screen, we are using the A-Button to move to the next turn.
My favourite piece of code in the entire project was the solution to this problem: If statements based on z-Index. To this point we had been utilising the z-index and viewToggles to switch easily between which layer was being shown. An example of this would be, whilst the canvas is the main view the z-Index of the canvas is 100 and all other screens z-Index is 1, when a fight would initiate, the fight screen would change to 100 and the canvas would return its z-Index to 1.
Eventually, we realised we could utilise our A-Button together with the z-Index so that the A-Button would lead to different functions depending on what screen was visible (at z-Index 100).
All Aboard The C-S.S Anne
The section I had been looking forward to since day one, adding Pokémon styling to an app. Having spent quite a few hours attempting to make the CSS as impressive or pointlessly flashy as I could on a lot of the homework and lab’s over the past few weeks, I was really excited to produce something with a given theme that more than two people might actually see and be able to give feedback on.
The most important lesson I was forced to learn regarding CSS, was to preview and customise elements in the browser and copy the styling to the .css file. Attempting to style the end screen which (even with cheats on) took a full two minutes to play through to inspect made me really appreciate how useful a tool the in browser preview was.
My favourite aspect of styling was the fight screen, utilising the sizes of the front and back pictures of the Pokémon to give a slightly 3D feel to the page. I had previously struggled with figuring out the animation of elements on past homework, but fortunately managed to implement transitions in this project.
Using keyframes allowed us to have the fight screen begin with each Pokémon sliding into the screen from the borders with a 0% brightness.
Transitions aside, I didn’t necessarily learn a great deal of new CSS tools during this project. However, I did spend a good deal of time working with the styling and produced something I was proud of and thought looked as close to the original Pokémon as I was capable.
Caught Them All
Overall, I think our presentation of the project went as well as we could have hoped. We went in with a loose structure of the topics we wanted to cover and it eventually turned into a discussion between our group about the certain aspects we found difficult and how we overcame them.
That was the end of an exhausting week and had the group not been so committed and worked from 9am (or 10…ish) till 8pm in CodeClan all 7 days I doubt we would have been able to complete as much as we did. Of our initial plan, I believe we easily met our MVP and accomplished 95% of our bonus functionality in our “would add if we had time” section.
From a personal point of view, I had the seven most enjoyable days of CodeClan so far working on this project and it resulted in an app I was incredibly proud of. I realise not every project I work on may make me as enthusiastic as Pokémon did, but the feeling of creating an app to a level I was happy to present really motivated me to want to be in CodeClan working till closing time every day.
— CodeClan (@CodeClanScot) March 1, 2017
Final thoughts on the project: I’d really like to host the project online somewhere for showing to both employers and friends outside of coding. As of yet, I haven’t found a place to host the Mongo database for free but hopefully I will be able to find a work around for Heroku or a separate site altogether.
As Blastoise would say, Poké Doké was just right.
Thanks to team Poké Doké for working so hard!