I Built An API For My Favorite Fighting Game (MVC2)

Dalvin Josias Sejour
codeburst
Published in
6 min readJan 3, 2019

--

The Plan

I love learning through passion projects. As you can read from one of my previous blog posts, I was able to secure an internship with a dope side project I worked on. To keep on this wave of passion projects, I got the bright idea to make an API (Application Program Interface) for Marvel Vs Capcom 2, a fighting game I played at the arcade when I was younger.

The thing about a passion project is that it does not ever have to be completed. You are able to work on it at your own pace and add new technologies to the fray as they gain more popularity.

My initial plan for this application was to make it an arcade game where you can select the character similar to how it was in the video game and put two characters together in order to fight. However, I scaled back on that initial dream and made it into an API that is able to do the following:

1. Display a list of all characters in the game

https://secure-hamlet-19722.herokuapp.com/api/v1/characters

{"name": "Blackheart","head_shot": "https://vignette.wikia.nocookie.net/marvelvscapcom/images/3/34/MVC2_Blackheart.jpg/revision/latest?cb=20110914071301","universe": "Marvel"},
{"name": "Cable","head_shot": "https://vignette.wikia.nocookie.net/marvelvscapcom/images/b/be/MVC2_Cable.jpg/revision/latest?cb=20110914072054","universe": "Marvel"}
,{"name": "Captain America","head_shot": "https://vignette.wikia.nocookie.net/marvelvscapcom/images/2/21/MVC2_Captain_America.jpg/revision/latest?cb=20110914072107","universe": "Marvel"}..etc

2. Display one record for a specific character

https://secure-hamlet-19722.herokuapp.com/api/v1/characters/{:name}

{"name": "Akuma","head_shot": "https://vignette.wikia.nocookie.net/marvelvscapcom/images/7/77/MVC2_Gouki.jpg/revision/latest?cb=20110923045906","universe": "Capcom"
}

3. Display moves for a specific character

https://secure-hamlet-19722.herokuapp.com/api/v1/characters/{:name}/moves

{"character_name": "Akuma","move_name": "Gohadoken","image": "/images/Move_Images/Akuma/Gohadoken.PNG"},{"character_name": "Akuma","move_name": "Zanku Hadoken","image": "/images/Move_Images/Akuma/Zanku Hadoken.PNG"}
Select Screen for Fighters
Moves for Selected Fighter

If you go to the following link, you can see a demo of the API in action. I used a React-Rails 💎 Gem for the front end because I wanted to learn React. In the demo all I simply do is iterate through each name in model and use the head_shot attribute to retrieve the image for each character. Then, in a separate show action, I use the name of the character as a parameter to find them and display all the associated moves.

Getting The Data

The first iteration of this project began a year ago. I wanted to learn how to parse data from the web, so I used a popular Ruby Gem 💎 Nokogiri, which is parse HTML. I referred to this guide to help me figure out how to use the gem and began to try and find a way to automate the process of getting the data from the web.

document = Nokogiri::HTML.parse(open('https://marvelvscapcom.fandom.com/wiki/Marvel_vs._Capcom_2:_New_Age_of_Heroes'))characters = document.css("b")characters.each do |character|
puts character.text
end

This code snippet above is the essence of Nokogiri, the first line loads the entire document of the page, the second line narrows down the document to only tags that have <b> around them. Lastly, I loop over all the <b> elements and print out the text, which so happen to be the name of characters.

Structuring The Project

Before I rushed into automating the scraping of a web page, it was important that I investigated the structure of the document to see if it was even possible to grab the data given the structure of how the webpage is laid out.

You are at the mercy of another developer when it comes to web scraping because they could have structured the elements poorly and did not name them properly. Likewise, data is never always pretty which requires it to be massaged into the shape you need it to be.

For example, when Nokogiri was not playing nice with me when it came to scraping the images for character’s moves. I needed to manually screenshot some of the images for the moves and add them to the assets folder.

Akuma’s Ashura Senku Move

Supplying The Data

After messing around with Nokogiri and brainstorming the possible structure for my application, I was able to get the model laid out and began to save all the data into a csv file. The csv served as a temporary database for me especially since I worked so hard to get the data formatted, I wanted to be able to easily access and edit the fields. Likewise, since I had the data available, it was easy for me to seed the database in Ruby on Rails with the files that were in my csv folder.

puts "Seeding Characters table"
csv_text = File.read(Rails.root.join('public', 'MVC2','final_list.csv'))
csv = CSV.parse(csv_text, :headers => true, :encoding => 'ISO-8859-1')
csv.each do |row|
# puts row.to_hash
c = Character.new
c.name = row['name']
c.head_shot = row['head_shot']
c.universe = row['universe']
c.save
puts "#{c.name}, #{c.universe}, #{c.head_shot} saved"
end
puts "There are now #{Character.count} rows in the character table"

This snippet of code illustrates how I loaded data from the csv file and seeded Ruby on Rails with the information.

Creating the API

All an API really does is provide an easily digestible way for other developers to access data. Therefore, all the heavy lifting done in the sections above made it easy for me to convert my existing application into something else other people could use. It took a year after my initial commit to the repo to realize that I could make something bigger out of this application I made.

After seeding the database, it was easy to create models for each characters along with the moves that they have using the relationship modeling Rails offers out of the box.

With that data, I was able to use another Ruby Gem called 💎 Grape that made it easy to create an API from an existing Rails application. I followed an amazing tutorial by Sophie Debenedetto which was able to help me get the code up in running for the API.

module API
module V1
class Character < Grape::API
include API::V1::Defaults
resource :characters do
desc "Return all characters"
get "", root: :character do
CharactersController::Character.all
end
desc "Return all characters moves"
puts params
params do
requires :name, type: String, desc: "Name of Character"
end
get "/:name/moves", root: "character" do
CharactersController::Character.where("name like?", "%#{permitted_params[:name]}%").move
end
desc "Return a character"
params do
requires :name, type: String, desc: "Name of Character"
end
get ":name", root: "character" do
CharactersController::Character.where("name like?", "%#{permitted_params[:name]}%").first!
end
end
end
end
end

The Call To Action

This side project literally started off as a simple idea. It also shows the process it takes to take a mere idea and creating it into a reality. That is the beauty of a side project, because there is no rush to get it done and you can always add on new code to your previous implementations. Hopefully, going into this new year you are able to look back into your old repos and work on a dream app, or even encourage you to start something new.

That being said, if you are interested in contributing to this API, feel free to check out my repo and make a pull request. I do not know how far I want to take this, so any other input on the project will be greatly appreciated.

Follow me on Twitter @officialdalvinj

Check out my business page

Check out my business Instagram @dalvindigitaldesign

--

--