Skip to main content

ガチャを引く

We listed cards and deleted them, now let's add some cards by playing a gacha game. The game must implement the following features

  • The player can pull a gacha a limited amount of times
  • Card rarity is linked to card rank (SS cards are more rare than C cards)

In particular, here's the probability for each card rarity:

Rank SS S A B C
Rarity (%) 5% 10% 20% 30% 35%

Database

Let's start by making a new table in the database to store how many gacha pulls each player has. We need the user id and the number of pulls.

image.png

Notice that we don't need an auto-increment id for this table. The reason why is because each user has only 1 entry in the gacha table, so we can reuse the user_id as the primary key for this table. Let's give user_id = 1 a total of 3 gacha pulls to begin with:

INSERT INTO `gacha` (`user_id`, `count`) VALUES ('1', '3');

image.png

PHP Script

Number of gacha pulls

We need two new APIs. One to check the number of gacha pulls and another one that actually executes the pull. The first one is the simplest, so let's start with a new script called get_gacha_count.php. This is a simple SELECT query that checks how many counts the player has. If there is no entry in the table, we return 0.

As always, we can first test with GET parameters. Let's pass the user_id we want to query as an argument.

<?php
	// JSONを返すべき
	header("Content-Type: application/json; charset=utf-8");

	// 接続 
	$dbh = new PDO('mysql:host=localhost; dbname=card_game', "root", "", [PDO::ATTR_PERSISTENT => true]);
	
	// ユーザーIDを取得
	$userID = $_GET['user_id'];
	
	// SQL文を構築
	$sql = "SELECT * FROM gacha WHERE user_id = " . $userID;
	
	// デフォルトとして 0 を返す
	$json['count'] = 0;
	
	// 見つけたら、回数を取得
	$result = $dbh->query($sql);
	if ($result->rowCount() == 1)
	{
		$record = $result->fetch();
		$json['count'] = $record['count'];
	}
	
	// 返す
	print(json_encode($json));
?>

If we test with user 1 and user 3, we get:

image.png

image.png

Which is the correct output we need.

Gacha pull

The next scrips executes the gacha pull. This is a bit more complex, as it needs to do a few things

  • Randomly generate a card rank from SS to C
  • Query the database for all cards of the selected rank
    • Select 1 card randomly
  • Add the card to the player's list of cards
  • Decrease the number of gacha pulls by 1
  • Return to the game (Unity) a JSON with the newly obtained card

We can break this into 4 different functions and call them one at the time. Let's start with random card generation. Create a new script called gacha_pull.php

Random card rank with probability

// 確率によりランダムランクを作成
// 0:C ~ 4:SS
function createRandomRank()
{
	// 0~100までの乱数を生成
	$chance = rand(0, 100)
	
	// 5% 以下だったら、SSランク(4)のカードになる
	if ($chance < 5) 
		return 4; 
	
	// 15% 以下だったら、Sランク(3)のカードになる
	if ($chance < 15)
		return 3; 

	// 35% 以下だったら、Aランク(2)のカードになる
	if ($chance < 35)
		return 2; 

	// 65% 以下だったら、Bランク(1)のカードになる
	if ($chance < 65)
		return 1; 

	// 残りは C(0)
	return 0;
}

This script generates a random number between 0 and 100 and then checks each cumulative probability until it finds a rank to return between 0 (C) and 4 (SS)

Select random card from database with rank

The next script takes a rank value from 0 to 4, queries the database and returns 1 random card record.

// ランクを用いて、ランダムのカードを返す
// $dbh:  データベースを検索するためのPDO
// $rank: カードのランク
function getCardWithRank($dbh, $rank)
{
    // SQL文を構築
    $sql = "SELECT * FROM cards WHERE rank = " . $rank;
    
    // すべてのレコードを取得
    $result = $dbh->query($sql);
    $records = $result->fetchAll();
    
    // ランダムのを選択
    $count = sizeof($records);
    $idx   = rand(0, $count-1);
    return $records[$idx];
}

Add the card to the player

In this step, we modify user_cards table to update the cards the player has. If the player already had the card, we need to add 1 to the count. However, if the player never owned the card, we need to add a new record with a starting count of 1. Fortunately, SQL has a special statement for that called INSERT ... ON DUPLICATE. It's a bit complex to read, but it looks something like this:

INSERT INTO table (field1, filed2, ...) VALUES (1, "A", ..) ON DUPLICATE KEY UPDATE name="A", age=19, ...

In this case, if