こんにちは、コンスキです。
Processingでゲームが終わった後に、ランキングを表示させたいことがあると思います。
今回は、ゲーム中のスコアを使ってランキングを表示させる方法をご紹介します。
ランキングを表示させるコード
まずはスケッチに次のコードを書いたpdeファイルを入れください。このファイル名は「Ranking.pde」にします。
import java.io.BufferedWriter;
import java.util.Collections;
import java.util.Comparator;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
String filename = "ranks.txt";//ファイルの読み込みに使うパス
ArrayList<String> tmpRanks = new ArrayList<String>();//ファイルから読み込んだ3種類の文字列を分けて入れておくためのArrayList
ArrayList<String> tmpScores = new ArrayList<String>();
ArrayList<String> tmpNames = new ArrayList<String>();
boolean rankingScene = false;
int count = 0;
int tmpcount = 0;
String newRank, newName, newScore;
//----------------------------------------- Rankerクラス ---------------------------------------------------
class Ranker {
String rank, name, score;
Ranker(String rank, String name, String score) {
this.rank = rank;
this.name = name;
this.score = score;
}
void displayRanks() {
fill(255);
rect(width/2, 200*(ranks.indexOf(this)+1), 500, 50);
fill(0); //文字の色は黒
text(rank+". "+name, 280, 210+200*(ranks.indexOf(this)));
text(" "+score+"点", 280, 210+200*(ranks.indexOf(this)));
}
}
//----------------------------------------- Rankerクラス ---------------------------------------------------
Ranker ranker;
ArrayList<Ranker> ranks = new ArrayList<Ranker>();
//-----------------------------------------同じ種類の文字列に分類する----------------------------------------------------------
void classify(String[] lines) {
tmpRanks = new ArrayList<String>();
tmpNames = new ArrayList<String>();
tmpScores = new ArrayList<String>();
for(int i=0 ; i<lines.length; i++) {
String[] words = lines[i].split(", "); //行からrank, name, scoreを「, 」を境に分ける
tmpRanks.add(words[0]); //要素がrankだけのArrayListに入れる
tmpNames.add(words[1]); //要素がnameだけのArrayListに入れる
tmpScores.add(words[2]); //要素がscoreだけのArrayListに入れる
}
}
//-----------------------------------------同じ種類の文字列に分類する----------------------------------------------------------
//-----------------------------------------ランキング画面を表示する関数----------------------------------------------------------
void setRankingScene() {
//background(0);
count++;
rankingScene = true;
newRank = String.valueOf(ranks.size()+1); //順位はひとまず最下位にしておく
newName = "NewName"+count;
newScore = String.valueOf(int(random(5, 60) ));
}
//-----------------------------------------ランキング画面を表示する関数----------------------------------------------------------
void settings() {
// fullScreen();
size(1000, 800);
}
void setup() {
PFont font = createFont("YuGothic", 32);
textFont(font);
rectMode(CENTER);
}
void draw() {
if(rankingScene) {
if(count!=tmpcount) { //前フレームのcountと今のフレームのcountが違っていたら
String[] lines = loadStrings(filename);
tmpcount = count;
classify(lines); //同じ種類の文字列に分類する
ranks = new ArrayList<Ranker>();
for(int i=0; i<lines.length; i++) {
ranks.add(new Ranker(tmpRanks.get(i), tmpNames.get(i), tmpScores.get(i))); //tmpRanksは順位を、tmpNamesは名前を、tmpScoresはランクをまとめたArrayListスコア
}
ranks.add(new Ranker(newRank, newName, newScore));
//並べ替える前
System.out.println("▼並べ替える前");
for (int i=0; i<ranks.size(); i++) {
print(ranks.get(i).name);
System.out.print(" "); //見やすくするためにスペースを空ける
}
println("");//改行
//インスタンスが持つ変数scoreを使ってranksを並べ替える
Comparator<Ranker> comparator = new Comparator<Ranker>() {
@Override
public int compare(Ranker O1, Ranker O2) {
Integer o1 = Integer.parseInt(O1.score); //Integer.parseInt(String型の変数) でString型からint型に変換できる
Integer o2 = Integer.parseInt(O2.score);
Integer judgement = Integer.valueOf(o1).compareTo(Integer.valueOf(o2)); //o1とo2を比較して同じなら0、o1の方が小さければ-1、大きければ1
return -judgement; //降順にする。照準なら「-」を外したjudgement
}
};
Collections.sort(ranks, comparator); //sortメソッドの第2引数に並べ替え方を渡す
//並べ替えた後
System.out.println("▼並べ替えた後");
for (int i=0; i<ranks.size(); i++) {
print(ranks.get(i).name);
System.out.print(" "); //見やすくするためにスペースを空ける
}
//変数rankを更新する
for(int i=0; i<ranks.size(); i++) {
ranks.get(i).rank = i+1+""; //文字列として入れる
}
}
for(int i=0; i<ranks.size(); i++) {
ranks.get(i).displayRanks();
}
}
}
void keyPressed() {
if(key==ENTER) {
setRankingScene();
}
//-------------------------------------------- ↑キーが押されたらランキング情報をranks.txtに書き出す --------------------------------------------
if(keyCode==UP) {
try {
FileWriter output = new FileWriter("/Users/konnsuki/Documents/Processing/src/Ranking/ranks.txt");//引数には、ファイル名や相対パスではなく、絶対パスを渡します
PrintWriter pw = new PrintWriter(new BufferedWriter(output));
StringBuilder buff = new StringBuilder();
for(int i=0; i<ranks.size(); i++) {
buff.append(ranks.get(i).rank+", "+ranks.get(i).name+", "+ranks.get(i).score);
if(i<ranks.size()-1) {
buff.append("\n");
}
}
String saves = buff.toString();
println(saves);
pw.print(saves);
pw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
//-------------------------------------------- ↑キーが押されたらランキング情報をranks.txtに書き出す --------------------------------------------
}
このコードをもとに、ご自分の用途に合うように変更していきます。
ランキングのデータを保存するファイルを作る
「Ranking.pde」が入っているフォルダに「ranks.txt」ファイルを作成します。
このファイルには、次の形式でデータが書き込まれるようになっています。
順位, 名前, スコア(整数を想定しています)
順位, 名前, スコア(整数を想定しています)
.
.
.
あらかじめ、このファイルに2つだけデータを入れておきます。
具体的な例を挙げてみます。
1, コ太朗, 40 //データ1つ目(このコメントは書かないでください。)
2, ン太朗, 30 //データ2つ目
名前やスコアは自由に決めても大丈夫ですが、順位は上から順に1と2を設定してください。
ranks.txtのパスを設定
初めの方に書いた「Ranking.pde」の139行目を見てください。
FileWriter output = new FileWriter("/Users/konnsuki/Documents/Processing/src/Ranking/ranks.txt");//引数には、ファイル名や相対パスではなく、絶対パスを渡します
new FileWriter(“ranks.txtのパス“)のように書かれていますが、これは僕の環境でのパスです。
ご自身の環境に合わせたパスを書いてください。
このパスはファイル名や相対パスではなく絶対パスで設定してください。
一旦実行
実行すると何が起こるのかを確認しておきます。
▼実行すると、ウィンドウだけが表示されて、他は何も表示されません。
それで大丈夫です。
次に、Enterキーを1回だけ押してください。
すると下のようなランキングが表示されます。
NewName1の得点はランダムに設定するようにしています。
そのため、上の画像とは少し違うように表示されるかもしれません。
下のデータ2つは、先ほど「ranks.txt」に書いておいたデータです。
次に矢印キーの↑を押してください。
すると、ランキングのデータが「ranks.txt」に保存されます。
「ranks.txt」を開いてみると、「NewName1」のデータが追加されていると思います。
1, NewName1, 48
2, コ太朗, 40
3, ン太朗, 30
仕組み
一度実行したことでなんとなく動作がわかったかもしれません。
このプログラムでは、次のようなことをやってます。
- ranks.txtからランキングデータを読み込む
- Enterキーが押されたら新しいデータを追加して、ランキングを表示
- ↑キーが押されたら、そのランキングデータをranks.txtに保存
ゲームと合体させる
ゲームが終了したらランキングを表示させるためには次のようなことが必要です。
- 変数newNameに、プレーヤー名を入れる
- 変数newScoreに、ゲームのスコアを入れる
- ゲームが終了したらsetRankingScene関数を呼び出す
変数newNameとnewScoreは、どこからでも設定できるように宣言されています。
ゲーム中にこれらの2つの変数に、プレーヤー名やそのプレーヤーのスコアを入れておきましょう。
ゲーム終了後にsetRankingScene関数を呼び出せば、ランキング画面が表示されます。
最後に
この状態だと、見た目が非常に質素です。
実際に使用するときは、見た目を変更するなどして、活用していただけたら嬉しいです。
また、上位3プレーヤーしか表示されないのもなかなか問題なので、そこも改良するといいかもしれません。
いい感じのランキングが作れたら、ぜひコメントで教えてください!
コメント