この記事はAteam Brides Inc. Advent Calendar 2020の20日目の記事です。
はじめに
Qiitaに投稿すること自体初めてで、どんなことを書こうか迷っていたところ「PokeAPI」という、面白そうかつ、初心者の自分にも扱いやすそうなものを見つけたのでこのAPIとRailsを使って簡単なポケモンアプリを作ってみようと思います。
PokeAPI
[PokeAPI](https://pokeapi.co/)はポケモンに関する大量のデータを取得することのできるAPIです。 図鑑ナンバーや名前だけでなく、ゲーム上のイラストだったり、タイプや重さ、生態の説明など、ポケモンに関するあらゆる情報を持っており、それぞれが紐づいている画期的なAPIです。つくるもの
DockerでRailsの環境構築をし、PokeAPIを使って、ポケモンを捕まえるゲームと捕まえたポケモンを確認できる簡単なアプリを作成します。
Dockerで環境構築
今回はDockerを使って環境構築をしました。
Dockerfileとdocker-compose.ymlは以下の仕様です。
まだ勉強中なので至らぬ点がありますが、多めにみてください。
FROM ruby:2.6.3
ENV LANG C.UTF-8
RUN apt-get update -qq && \
apt-get install -y build-essential \
libpq-dev \
RUN mkdir /app
RUN mkdir /app/src
ENV APP_ROOT /app/src
WORKDIR $APP_ROOT
ADD ./src/Gemfile $APP_ROOT/Gemfile
ADD ./src/Gemfile.lock $APP_ROOT/Gemfile.lock
RUN bundle install
ADD . $APP_ROOT
version: '3'
services:
postgres:
image: postgres
ports:
- "3306:3306"
volumes:
- ./postgres-data:/var/lib/postgresql/data
environment:
POSTGRES_USER: 'admin'
POSTGRES_PASSWORD: 'admin-pass'
restart: always
app:
build: .
image: rails
container_name: 'app'
command:
- sh
- -c
- bundle install && bundle exec rails s -p 5000 -b '0.0.0.0'
ports:
- "5000:5000"
environment:
VIRTUAL_PORT: 5000
volumes:
- ./src:/app/src
depends_on:
- postgres
restart: always
アプリ開発
テンプレートの紹介は各アクションから取得したインスタンス変数を使うだけで実装できるので今回は省略します。
自分が持っているポケモン周りと野生のポケモン周りで2つのコントローラを使って作成していきます。
まずは、自分が持っているポケモン周りのアクションです。
class MyPokemonsController < ApplicationController
def index #手持ちのポケモン一覧
@my_pokemons = Pokemon.order('id')
end
def show #ポケモンの詳細
@my_pokemon = Pokemon.find(params[:id])
raw_response = Faraday.get "https://pokeapi.co/api/v2/pokemon-species/#{@my_pokemon['number']}/"
@my_pokemon_data = JSON.parse(raw_response.body)
end
def partner #ポケモンをパートナーにする
session[:partner_pokemon_number] = params[:partner_pokemon_number]
redirect_to action: "index"
end
def set_free #ポケモンを逃す
@pokemon = Pokemon.find_by(number: params[:set_free_pokemon_number])
@pokemon.destroy
redirect_to action: "index"
end
end
基本的な処理を書くだけで簡単に実装できます。
パートナーポケモンを実装するためにsessionを用いました。
次に、野生のポケモン周りのアクションです。
class AdventuresController < ApplicationController
def top #冒険に行くときのトップページ、パートナーポケモンの情報を取得
raw_response = Faraday.get "https://pokeapi.co/api/v2/pokemon/#{session[:partner_pokemon_number]}"
@partner_pokemon_data = JSON.parse(raw_response.body) # パートナーポケモンの画像データ
end
def wild_area #野生のポケモンに出会う
raw_response = Faraday.get "https://pokeapi.co/api/v2/pal-park-area/#{params[:area_code]}/"
list = JSON.parse(raw_response.body) # そのエリアに出現するポケモンリスト取得
pokemon_url_list = []
appearance_rate_list = []
list['pokemon_encounters'].each do |data| # 各ポケモンの詳細データのURLと出現率をそれぞれリストにいれていく
pokemon_url_list.push(data["pokemon_species"]["url"])
appearance_rate_list.push(data["rate"])
end
pokemon_number = get_random_index(appearance_rate_list) # 出現率のリストを元に出現する野生のポケモンのナンバーを取得
wild_pokemon_url = pokemon_url_list[pokemon_number]
raw_response = Faraday.get wild_pokemon_url
@wild_pokemon = JSON.parse(raw_response.body) # 野生のポケモンのナンバーや名前のデータ
raw_response = Faraday.get "https://pokeapi.co/api/v2/pokemon/#{@wild_pokemon['id']}"
@wild_pokemon_data = JSON.parse(raw_response.body) # 野生のポケモンの画像データ
raw_response = Faraday.get "https://pokeapi.co/api/v2/pokemon/#{session[:partner_pokemon_number]}"
@partner_pokemon_data = JSON.parse(raw_response.body) # パートナーポケモンの画像データ
end
def catch #ポケモンを捕まえる
status_number_list = [1,1,1,2,2] #ポケモンを捕まえられるかの割合リスト
status_number = status_number_list.sample
if status_number == 1
@get_pokemon_name = params[:get_pokemon_name]
@get_pokemon_image = params[:get_pokemon_image]
Pokemon.create(number: params[:get_pokemon_id], name: params[:get_pokemon_name], image: params[:get_pokemon_image]) # 捕まえたポケモンのデータを保存
else
render action: :failure # 失敗したら失敗ページへ
end
end
def failure #捕獲失敗
end
def get_random_index(weight_table) # 引数の配列から1つの値をランダム抽出
total_weight = weight_table.sum
value = rand(1..total_weight)
ret_index = -1
for i in 0..weight_table.length - 1 do
if weight_table[i] >= value
ret_index = i
break
end
value -= weight_table[i]
end
return ret_index
end
end
ここで工夫したことは、PokeAPIから取得した各ポケモンの出現レートをappearance_rate_listに入れ、その出現レートの配列を元に、出現するポケモンを重み付きでランダムに抽出する機能を実装したことです。
例えば、ポッポ、ピカチュウ、ミュウのレートがそれぞれ50、20、1であるとすると、それぞれが選ばれる確率は50/71、20/71、1/71のようになります。
ここでランダムに選ばれた配列のインデックスを、pokemon_url_listに紐付け、野生のポケモン情報を取得します。
また、ポケモンを捕まえられるか、逃げられるかの確率はcatchアクションのstatus_number_listの中身をいじれば変更することができます。
アプリ画面
つくったアプリの画面紹介です。
cssの実装をしていないので簡素な見た目ですが、ご了承ください。
冒険へ行くトップ画面です。
この画面から、5つのエリアへ行きポケモンを探しにいくことができ、手持ちのポケモンとパートナーポケモンを確認することができます。
自分で何回か動かしているときにエンテイを捕まえたのでちょっと自慢します。
手持ちのポケモン一覧です。
ポケモンナンバーと名前とイラストを表示しています。
名前をクリックすることで詳細ページへ飛びます。
APIデータのずれによりポッチャマのように日本語でない名前がとれてきてしまうこともありますが愛嬌です。笑
カビゴンの詳細ページはこんな感じです。
なんちゃらポケモンと説明が表示されます。ここでパートナーにしたり、逃したりできます。
カビゴンをパートナーにしてみましょう。
変わりましたね!
冒険に出てみましょう。
「やま」ボタンをクリック。
チャーレムが現れました。
ここで「モンスターボールを投げる」と設定した確率でポケモンを捕まえられます。「逃げる」を押すとトップに戻ります。
ボールを投げてみましょう。
- - - 捕まえました👏 - - -
逃げられてしまった場合はこちらの画面がでます。
以上、アプリの紹介でした!
最後に
幼い頃ポケモンで遊んでいたのでこの実装をしていて楽しかったです。
ポケモンの攻略サイトもこのAPIが使われてたりするのでしょうか。
興味があれば情報量が多くて使いやすい「PokeAPI」を是非触ってみてください!
明日は、新卒同期の@ma-niが担当します!