比率

最小値と最大値と比率を指定して、最小値から最大値の間の、指定比率の数値を戻す関数です。ゲームのアニメーションの動きなどでよく用います。 2018-07-06

 ゲームを開発していると、「A座標からB座標まで20%移動」といった処理が多く出てきます。そうした際に「rate(25, 60, 0.2)」のように書けると便利です。

 今回用意した関数は、第4引数に値を指定しなかった場合は、比率が「0.0~1.0」の間になるように動作します。「true」を指定した場合は「0.0~1.0」の範囲外でも、そのまま計算を行います。

 ファイル構成は以下の通りです。>>ダウンロード

※ 初期化用関数「init」の処理については「Webブラウザ/Node.js 互換関数」をご覧下さい。

サンプル動作

sample/rate.js

'use strict';

(function() {
	const _t = init('com.crocro.util');

	// rate | 比率
	_t.rate = function(min, max, rate, canOver) {
		if (! canOver) {
			if (rate < 0) {rate = 0}
			if (rate > 1) {rate = 1}
		}
		return min * (1 - rate) + max * rate
	};

	// 初期化用関数
	function init(p) {
		try {return module.exports = {}} catch(e) {}
		return ((o, p) => {
			p.split('.').forEach(k => o = o[k]||(o[k]={}));
			return o})(window, p);
	};
})();

解説

 ゲームのエフェクトの座標計算では、始点から終点まで、時間とともに移動していくといった処理が多いです。

 また、リアルタイムのゲームでは、時間とともに、ユニットが移動していくことがあります。

 そうした際に、始点、終点、比率で座標を計算できる関数は、コードの可読性を上げてくれます。

 地味な処理ですが、関数化しておくと生産性が上がります。

rate | 比率

最小値と最大値を指定して、その間のどの数値になるか、0.0~1.0の比率で指定します。

第4引数がない場合は、0.0~1.0の範囲に収まるように計算されます。

第4引数が「true」の場合、0.0~1.0の範囲外の数値の際も、そのままの比率で計算されます。0.0~1.0の範囲に収まるかどうかは、考慮されません。

@param {Number} min - 最小値。
比率が0.0の時の値です。

@param {Number} max - 最大値。
比率が1.0の時の値です。

@param {Number} max - 比率。
0.0~1.0の比率です。

@param {Boolean} canOver - 範囲外許容の有無。
0.0~1.0の範囲外を許容するかを設定するフラグです。

@return 最小値と最大値の間で、指定の比率の数値を計算して戻します。

サンプル

// Webブラウザ
const rate = com.crocro.util.rate;

console.log('第4引数なし(0.0~1.0の範囲)');
for (let i = -2; i < 7; i ++) {
	console.log((i * 0.2).toFixed(2), rate(5, 15, i * 0.2 ) | 0);
}
// -0.40 5 
// -0.20 5 
// 0.00 5 
// 0.20 7 
// 0.40 9 
// 0.60 11 
// 0.80 13 
// 1.00 15 
// 1.20 15 

console.log('\n----------\n');

console.log('第4引数あり(0.0~1.0の範囲外も許容)');
for (let i = -2; i < 7; i ++) {
	console.log((i * 0.2).toFixed(2), rate(5, 15, i * 0.2, true) | 0);
}
// -0.40 1 
// -0.20 3 
// 0.00 5 
// 0.20 7 
// 0.40 9 
// 0.60 11 
// 0.80 13 
// 1.00 15 
// 1.20 17 


// Node.js
const rate = require('./rate.js').rate;

// 実行
console.log('第4引数なし(0.0~1.0の範囲)');
for (let i = -2; i < 7; i ++) {
	console.log((i * 0.2).toFixed(2), rate(5, 15, i * 0.2 ) | 0);
}
// -0.40 5 
// -0.20 5 
// 0.00 5 
// 0.20 7 
// 0.40 9 
// 0.60 11 
// 0.80 13 
// 1.00 15 
// 1.20 15 

console.log('\n----------\n');

console.log('第4引数あり(0.0~1.0の範囲外も許容)');
for (let i = -2; i < 7; i ++) {
	console.log((i * 0.2).toFixed(2), rate(5, 15, i * 0.2, true) | 0);
}
// -0.40 1 
// -0.20 3 
// 0.00 5 
// 0.20 7 
// 0.40 9 
// 0.60 11 
// 0.80 13 
// 1.00 15 
// 1.20 17

sample/index.html

<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <title>最小最大 - JavaScript実用サンプルコード解説付き</title>

    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js">
    </script>

    <script src="rate.js"></script>
    <script src="main.js"></script>
    <link rel="stylesheet" href="main.css">
  </head>
  <body>
    <textarea id="src" style="height: 14em;"></textarea>
    <button id="exec">実行</button>
    <textarea id="dst" style="height: 19em;"></textarea>
  </body>
</html>

sample/main.js

'use strict';

$(function() {
	// 変数の初期化
	const $src   = $('#src');
	const $dst   = $('#dst');
	const $exec  = $('#exec');
	const $reset = $('#reset');

	// 値のセット
	$src.val(String.raw`
const rate = com.crocro.util.rate;

console.log('第4引数なし(0.0~1.0の範囲)');
for (let i = -2; i < 7; i ++) {
	console.log((i * 0.2).toFixed(2), rate(5, 15, i * 0.2 ) | 0);
}

console.log('\n----------\n');

console.log('第4引数あり(0.0~1.0の範囲外も許容)');
for (let i = -2; i < 7; i ++) {
	console.log((i * 0.2).toFixed(2), rate(5, 15, i * 0.2, true) | 0);
}
	`.trim());

	// コンソール ログのラップ
	const log = console.log;
	console.log = function() {
		for (let i = 0; i < arguments.length; i ++) {
			$dst.append(arguments[i] + ' ');
		}
		$dst.append('\n');
		log.apply(console, arguments);
	};

	// クリック時の処理
	$exec.click(() => {
		$dst.empty();
		eval($src.val());
	});
});

sample/main.css

html,
body {
	margin: 0;
	padding: 0;
}

textarea,
button {
	box-sizing: border-box;
	width: 100%;
	vertical-align:bottom;
}
textarea {
	height: 5em;
}

sample/node_sample.js

// モジュールの読み込み
const rate = require('./rate.js').rate;

// 実行
console.log('第4引数なし(0.0~1.0の範囲)');
for (let i = -2; i < 7; i ++) {
	console.log((i * 0.2).toFixed(2), rate(5, 15, i * 0.2 ) | 0);
}

console.log('\n----------\n');

console.log('第4引数あり(0.0~1.0の範囲外も許容)');
for (let i = -2; i < 7; i ++) {
	console.log((i * 0.2).toFixed(2), rate(5, 15, i * 0.2, true) | 0);
}

紹介

Steamでゲームをリリースした時の経験をマニュアル的にまとめた本です。
8bit風RTS「TinyWar」のアルゴリズムを、コード付きで解説した本です。
JavaScriptから手軽に扱える形態素解析器『kuromoji.js』を使い、日本語を分解して遊ぶ本です。
node.jsを使い、「Google Chrome」のユーザーデータを、自動処理でメンテナンスするプログラムを開発する本です。
HTML5でローカルアプリが作れるNW.jsで、同人ゲームを作るための基礎知識の本です。
シミュレーションRPG「TinySRPG」のアルゴリズムを、コード付きで解説した本です。
JavaScriptの実行時エラーを分類して、ワンライナーのソースコードとエラーメッセージを収録した本です。
禁止文字つきコードゴルフを1年以上出題して、その解答ノウハウをまとめた本です。
2011年の春ごろに、Javaで「NyARToolKit」互換のARマーカー認識プログラムを書いた時のレポートです。