先日、トウガラシが山ほど入った焼きそばを平気な顔で食べている学生を目にしました。
3日連続で激辛トウガラシ焼きそばを食べている、との事でした。
こんにちは、武田です。
7月に入り、わたしの受け持つ「Webアプリ」の授業ではオブジェクト指向のプログラムについて学んでいます。
Arcというクラスを作った
実は、JavaScriptという言語でもオブジェクト指向は学べます。
ゆくゆくは記述方法がClassとなるようですが、現在は記述が関数と同じFunctionでの記述なので、これがクラスなのか?という気持ちになりますが、立派にインスタンス化(new)することができ、かつ独立して動きます。
たとえばArcというクラスを作ったら、こんな感じで生成します。
var bubble = new Arc();
これをインスタンス化といいいます。クラスが設計図とすれば、インスタンスは、実体ということになります。
専門用語抜きに言うなら、家の設計図から家を建てるみたいな感じです。
これをホームページ読み込み時に生成します。(こんな感じ)
// 円を生成 for(var i=0; i<100; i++){ var bubble = new Arc(); objects.push(bubble); }
100個作っています。
生成するときは、ただの変数(bubble)で作っていますが、次の行でobjectsという配列に入れています。
これは、沢山インスタンスを作ったとき、一度に処理をしたいときに便利だからです。
実際に一度に処理をする場合は、こんな風に行います。
// オブジェクト更新処理 for(var i in objects){ objects[i].update(); }
ここでは、作ったインスタンス全てのupdateメソッドを呼び出しています。
「オブジェクト」と書いてあったり「インスタンス」と書いてあったりしますが、どちらも同じ意味です。実体です。(設計図を使って建てた家の方)
Arcクラスでは、このupdateメソッドを空の(何も処理をしない)メソッドとして定義しています。JavaScriptでは、関数に関数を代入できます。外部(クラスの外)からは、updateメソッドを呼び出すだけにしておき、内部(クラスの中)では、moveメソッドが呼ばれています。新しくメソッドを追加してなにか処理させたいときは、updateメソッドに代入すれば済むからです。
何を言っているか分からない文章になってしまいましたが、とにかく後でプログラムを拡張したいときは便利です。ホント!
setTimeout関数を使って更新処理を行います。
var mainLoop = function(){ // 画面をクリア g.clearRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); // オブジェクト更新処理 for(var i in objects){ objects[i].update(); } // メインループ再帰呼び出し setTimeout(mainLoop, TICK); };
サンプルでは、100個の円を生成していますが、for文の回数を変えれば何個でも生成されます。クラスを一つ作ると同じ性質を持つ物(オブジェクト)がいくつでも作ることが出来て便利です。
泡のように見えるプログラムになりました。
以下がプログラム全体です。
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Bubble</title> <script src="Arc.js"></script> <script src="main.js"></script> <style> *{ margin: 0; padding: 0; } #canvas{ border:solid 1px #000; } </style> </head> <body> <canvas id="canvas" width="320" height="480"></canvas> </body> </html>
Arcクラス(Arc.js)
/* * Arc.js 円が跳ね返るクラス */ var Arc = function(){ // 初期位置 var x = Math.floor(Math.random() * SCREEN_WIDTH); var y = Math.floor(Math.random() * SCREEN_HEIGHT); // xy方向の加速度を設定 var vx = Math.floor(Math.random() * 3) + 1; var vy = Math.floor(Math.random() * 3) + 1; // 円の半径を設定 var r = Math.floor(Math.random() *20) + 1; // 描画メソッド this.draw = function(){ g.beginPath(); g.arc(x, y, r, 0, Math.PI*2, false); g.stroke(); }; // 移動メソッド this.move = function(){ this.draw(); // 移動量計算 x = x + vx; y = y + vy; // 壁にぶつかったら跳ね返る if(x < 0 || x > SCREEN_WIDTH){ vx = -vx; } if(y < 0 || y > SCREEN_HEIGHT){ vy = -vy; } return true; }; // 更新処理 this.update = function(){ }; this.update = this.move; };
オブジェクトの生成と更新を行うメイン処理部分(main.js)
/* * main.js キャンバスの取得、オブジェクトの生成と更新 */ var canvas = null; // キャンバス var g = null; // コンテキスト var $id = function(id){ return document.getElementById(id); }; var objects = []; // オブジェクト配列 var frame = 0; /* * 定数 */ var SCREEN_WIDTH = 320; var SCREEN_HEIGHT = 480; var TICK = 1000/30; // 描画間隔 /* * メイン処理 */ var mainLoop = function(){ // 画面をクリア g.clearRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); // オブジェクト更新処理 for(var i in objects){ objects[i].update(); } // メインループ再帰呼び出し setTimeout(mainLoop, TICK); }; /* * 起動処理 */ window.onload = function(){ // キャンバス情報取得 canvas = $id("canvas"); g = canvas.getContext("2d"); // 円を生成 for(var i=0; i<100; i++){ var ball = new Arc(); objects.push(ball); } // メインループ実行 mainLoop(); };
1000個作りました!