はじめに
こんにちは、GMOアドマーケティングのR.Yです。今回はp5.jsを使用して読み込みの長い画面でも退屈しないようなゲーム風読み込み画面を作成しましたのでその紹介です。
p5.jsとは
p5.jsとはJavaをベースに作られた「Processing」と言う電子アートのプログラミング言語をJavaScriptで使用できるようにしたライブラリになります。p5.jsを使うことでブラウザ上で表示できるアニメーションを作成することができます。サンプル
文字だけではわかりづらいと思うのでp5.jsによるアニメーションのサンプルを用意しました。以下が実際の表示とプログラムになります。※以降の動画は全て当社が作成したものになります。
1 2 3 |
<script src="https://cdn.jsdelivr.net/npm/p5@0.10.2/lib/p5.js"></script> <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"</script> <script src="sample.js"></script> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
var WIDTH_SIZE = 1000 var HEIGHT_SIZE = 600 // 最初に一回呼ばれる関数 function setup(){ createCanvas(WIDTH_SIZE, HEIGHT_SIZE); //表示する領域を確保 displayCount = 0; //カウンタ } // 1フレーム毎に呼ばれる関数 function draw() { background(255,100,0); //背景描画 rect(displayCount, 100, 200, 200); //四角形描画 rect(表示するx座標, 表示するy座標, 横幅, 縦幅) displayCount++; //カウンタ+1 } |
例えば矩形の描画はrect関数で行います。このサンプルではrect関数の引数である「表示するx座標」の値にカウンタの値を指定しているので、draw関数が呼ばれるたびに(1フレーム毎に)カウンタが増えていき右に動いているように見えると言うわけです。
ゲーム風の読み込み画面
まず画面ですが、1, 読み込んでいることが一目でわかるようにする
2, クリック時にアクションを起こす
と言う要件で作ってみました。以下が実際の表示とプログラムになります。
1 2 3 |
<script src="https://cdn.jsdelivr.net/npm/p5@0.10.2/lib/p5.js"></script> <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script> <script src="clickMarkScript.js"></script> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
var WIDTH_SIZE = 1000 var HEIGHT_SIZE = 600 var CENTER_WINDOW_WIDTH = WIDTH_SIZE / 2; var CENTER_WINDOW_HEIGHT = HEIGHT_SIZE / 2; var LOAD_TIME_RESET = 9 var NOW_LOADING = new Array("N", "O", "W", "L", "O", "A", "D", "I", "N", "G"); class Mark { constructor(x, y) { this.deleteCount = 60; this.x = x; this.y = y; this.w = 50; this.fadeout = 1.0; } addDeleteCount(){ this.deleteCount--; this.fadeout -= 1 / 60; this.w += 10; } } var marks = new Array(); function setup() { translate(CENTER_WINDOW_WIDTH , CENTER_WINDOW_HEIGHT); createCanvas(WIDTH_SIZE, HEIGHT_SIZE); $("body").css("margin","0"); displayCount = 0; loadCount = 0; } function draw() { translate(CENTER_WINDOW_WIDTH, CENTER_WINDOW_HEIGHT); background(50); loading(loadCount) displayMark(); displayCount++; if(displayCount % 10 == 0) { if(loadCount > LOAD_TIME_RESET){ loadCount = 0; } else { loadCount++; } } } function loading(loadCount) { textAlign(CENTER); textSize(30); noStroke(); fill(255); var display_width = 200; var display_height = 290; for(var i = 0; i < 10; i++) { if(i == ((loadCount) % 10)) { text(NOW_LOADING[i], display_width + (i*30), display_height - 30) } else { text(NOW_LOADING[i], display_width + (i*30), display_height) } } } function displayMark(){ translate(-CENTER_WINDOW_WIDTH, -CENTER_WINDOW_HEIGHT); for(var i = 0; marks[i] !== undefined ; i++) { mark = marks[i]; if (mark.deleteCount == 0) { marks.splice(i,1); continue; } fill('rgba(255,255,255,' + mark.fadeout + ')'); strokeWeight(0); circle(mark.x, mark.y, mark.w); mark.addDeleteCount(); } } function mousePressed(){ translate(-CENTER_WINDOW_WIDTH, -CENTER_WINDOW_HEIGHT); marks.push(new Mark(mouseX, mouseY)); } |
プログラム解説
1, 読み込んでいることが一目でわかるようにする
この要件に関しては「NOWLOADING」の文字を表示させることにしました。また、ゲームの読み込み画面を参考に各文字を順番にずらして表示させて読み込んでいることをわかりやすくしました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
var NOW_LOADING = new Array("N", "O", "W", "L", "O", "A", "D", "I", "N", "G"); // NOWLOADINGの表示 function loading(loadCount) { // 表示する文字の設定 textAlign(CENTER); // 文字の大きさを指定 textSize(30); // 外枠の表示をなくす noStroke(); // 色を255,255,255に指定 fill(255); var display_width = 200; var display_height = 290; for(var i = 0; i < 10; i++) { if(i == ((loadCount) % 10)) { // 文字を指定の位置からずらして表示 text(NOW_LOADING[i], display_width + (i*30), display_height - 30) } else { // 文字を指定の位置に表示 text(NOW_LOADING[i], display_width + (i*30), display_height) } } } |
loading関数の中では、表示する文字の設定後文字の表示を行なっています。文字表示部分ではloadCountの値によってNOWLOADINGのどの文字をずらして表示させるかを決めており、loadCountの値はdraw関数の中で10フレームごとに+1されます。なので10フレームごとにずれる文字が切り替わるようになっています。
2, クリック時にアクションを起こす
この要件に関してはクリック時に一定時間で消える波紋のようなものを表示させることにしました。これで長い読み込み時間でも飽きずに待てますね!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
class Mark { // 初期化 constructor(x, y) { // 削除までの時間 this.deleteCount = 60; // 表示する場所 this.x = x; this.y = y; // 大きさ this.w = 50; // フェードアウトのレベル this.fadeout = 1.0; } // deleteCountを進め円の大きさとフェードアウトレベルを上昇 addDeleteCount(){ this.deleteCount--; this.fadeout -= 1 / 60; this.w += 10; } } var marks = new Array(); // Markの表示 function displayMark(){ translate(-CENTER_WINDOW_WIDTH, -CENTER_WINDOW_HEIGHT); for(var i = 0; marks[i] !== undefined ; i++) { mark = marks[i]; if (mark.deleteCount == 0) { marks.splice(i,1); continue; } fill('rgba(255,255,255,' + mark.fadeout + ')'); strokeWeight(0); circle(mark.x, mark.y, mark.w); mark.addDeleteCount(); } } // クリック時に配列にMarkを追加 function mousePressed(){ translate(-CENTER_WINDOW_WIDTH, -CENTER_WINDOW_HEIGHT); marks.push(new Mark(mouseX, mouseY)); } |
全体を軽く説明すると、画面クリック時にMarkクラスを配列に入れていき配列に入っているMarkをdraw関数で全て表示するという流れです。
まずクリック時の動作はmousePressed関数で定義できます。この関数ではクリックされた場所(mouseX, mouseY)を引数にMarkクラスを作成しmarks配列に格納していきます。Markクラスは表示位置、大きさ、削除までのカウント、フェードアウトのレベルなどの要素を持っています。
次にdisplayMark関数でmarks配列に入っているMarkをその要素の値に合わせて順番に表示します。この時に全てのMarkでaddDeleteCount関数を呼び出し、削除までのカウントを進めたり、円の大きさやフェードアウトレベルの変更を行なっています。これをdraw関数から呼び出すことで波紋のようなものの描画が完成します。
使用例
最後に
今回はp5.jsを使用したゲーム風読み込み画面の紹介でした。作ってみた感想ですが環境がブラウザで整うので始めやすいのと、
アニメーションなので完成していく過程がわかりやすくとても楽しかったです!
ブラウザでのアニメーション作成に興味がある方は是非お試しください!
明日は星野さんによる「クラウドネイティブな設計の1歩目〜コンテナ・デザインパターン〜」に関しての記事です。
引き続き、GMOアドマーケティング Advent Calendar 2021 をお楽しみください!
■エンジニア採用ページ ~福利厚生や各種制度のご案内はこちら~
https://note.gmo-ap.jp/n/n02cbeb6edb0d
■noteページ ~ブログや採用、イベント情報を公開中!~
https://note.gmo-ap.jp/
フロントエンド見習いです。
犬と猫が好きです。