ランダムパターンの種類を色々紹介するよ!
ランダムパターンの種類を色々紹介するよ!
→キーで色々見れるよ。
今回は仕組みが違うから出さなかったけど、このほかにも、ゲーム制作でよく使うものとして
前回出た結果と同じものの確率が減っていく、抽選ランダムというものもあるよ。
/**
* Copyright tail_y ( http://wonderfl.net/user/tail_y )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/Aloh
*/
package {
/*
ランダムパターンの種類を色々紹介するよ!
→キーで色々見れるよ。
今回は仕組みが違うから出さなかったけど、このほかにも、ゲーム制作でよく使うものとして
前回出た結果と同じものの確率が減っていく、抽選ランダムというものもあるよ。
*/
import flash.display.Sprite;
import flash.display.StageQuality;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.text.TextField;
public class RandomPattern extends Sprite
{
public static const STAGE_W:uint = 465;
public static const STAGE_H:uint = 465;
public static const CHART_W:uint = 300;
public static const CHART_H:uint = 300;
private var _randomFunction:Function; // ランダム実験する関数を入れるよ
private var _titleTf:TextField;
private var _captionTf:TextField;
private var _chart:RandomChart;
private var _calc:Boolean = false;
private var _patternNum:int = -1;
public function RandomPattern()
{
addEventListener(Event.ADDED_TO_STAGE, init); // flexBuilderとの互換性。
}
public function init(event:Event):void{
// キャプチャを止めます
Wonderfl.disable_capture();
// SWF設定
stage.frameRate = 24
stage.quality = StageQuality.HIGH;
var bg:Sprite = new Sprite();
bg.graphics.beginFill(0xffffff);
bg.graphics.drawRect(0, 0, STAGE_W, STAGE_H);
addChild(bg);
// ランダム用関数
_randomFunction = null;
// タイトル表示
_titleTf = new TextField();
_titleTf.width = STAGE_W;
_titleTf.height = 20;
_titleTf.text = "ランダムパターンのテストと紹介をするよ!";
addChild(_titleTf);
// 説明文表示
_captionTf = new TextField();
_captionTf.width = STAGE_W;
_captionTf.height = 80;
_captionTf.y = 25;
_captionTf.text = "キーの左右で、ランダムの種類を切り替えるよ。\n下のグラフに、ランダムの分布結果が出るよ";
addChild(_captionTf);
// グラフを用意
_chart = new RandomChart(CHART_W, CHART_H);
_chart.x = 82;
_chart.y = 100;
addChild(_chart);
// キーイベント
stage.addEventListener(KeyboardEvent.KEY_DOWN, key);
// フレームイベント
stage.addEventListener(Event.ENTER_FRAME, frame);
}
private function key(event:KeyboardEvent):void{ // キーイベント
// キーの左右で切り替え
if (event.keyCode == 39) changeRandomList(1);
if (event.keyCode == 37) changeRandomList(-1);
}
private function changeRandomList(lr:int):void{ // ランダムの関数を切り替えて、グラフをリセットするよ。
if (_patternNum == -1) _patternNum = 0;
else _patternNum = (_patternNum + lr + _patternList.length)%_patternList.length;
var pattern:Object = _patternList[_patternNum];
_titleTf.text = pattern.name;
_captionTf.text = pattern.caption;
_randomFunction = pattern.func;
_chart.reset(); // リセット;
_calc = true; // 計算ループ開始
}
private function frame(event:Event):void{ // フレームイベント
if (_calc) calcChart();
}
private function calcChart():void{ // ランダムを計算して、グラフに反映
for (var i:int = 0; i < 500; i++){
_chart.addValue(_randomFunction());
if (_chart.isMax()){ // どこかが一番上まで行ったら
_calc = false; // 計算ループ終了
break;
}
}
}
// =======================================================以下がランダム関数
private var _patternList:Array = [
{name:"普通のランダム", func:normalRandom, caption:"0~1の出現率が一定になる。\n上に行くにしたがってバラつきが出るのは全共通。"},
{name:"平方ランダム1", func:powerRandom, caption:"ランダムを2乗したもの。\n0付近が露骨に多くなるのが特徴。"},
{name:"平方ランダム2", func:powerRandom2, caption:"ランダムを2回出し、それをかけたもの。\n前のものより、0の露骨さが減り、なめらかになる。"},
{name:"平方根ランダム", func:sqrtRandom, caption:"ランダムをルートで囲ったもの。\n0に近づくにつれ、綺麗に出現度が減る。\n使いやすい。"},
{name:"2ランダムの和", func:plusRandom2, caption:"ランダムを2回出し、足したもの。\n中央付近が高い3角形になる。\nサイコロを2個振ると合計6付近が出やすいのはこのため。"},
{name:"3ランダムの和", func:plusRandom3, caption:"ランダムを3回出し、足したもの。\n中央付近が高い、正規分布に似た形になる。\n自然物などをそれっぽく見せるのに有用。"},
{name:"指定割合ランダム", func:oddsRandom_0,
caption:"ゲームによく使われる整数指定のランダム。\n指定した数の割合でランダムを出してくれる。\n今回の指定は[5, 10, 10, 20, 10, 8, 5, 0, 10, 20]\n戻り値が整数なのでグラフ上は飛び飛びになる。"},
{name:"変形4平方ランダム balance=0.5 velvet=0.3", func:transRandom4_0,
caption:"ちょっと自由なランダム分布が作れるオリジナル関数。\nbalance=0.5 velvet=0.3を指定すると、中央の高い正規分布風に。"},
{name:"変形4平方ランダム balance=0.3 velvet=0.2", func:transRandom4_1,
caption:"ちょっと自由なランダム分布が作れるオリジナル関数。\nbalance=0.3 velvet=0.6を指定すると、左側にずれたドーム型分布に。"},
{name:"変形4平方ランダム balance=1.0 velvet=0.5", func:transRandom4_2,
caption:"ちょっと自由なランダム分布が作れるオリジナル関数。\nbalance=1.0 velvet=0.5を指定すると、1付近がなだらかに高い分布に。"},
]
// 普通のランダム。
public function normalRandom():Number{
return Math.random();
}
// 平方ランダム。
public function powerRandom():Number{
return Math.pow(Math.random(), 2);
}
// 平方ランダムその2。
public function powerRandom2():Number{
return Math.random()*Math.random();
}
// 平方根ランダム。
public function sqrtRandom():Number{
return Math.sqrt(Math.random());
}
// 2ランダムの和。
public function plusRandom2():Number{
return (Math.random()+Math.random())/2
}
// 3ランダムの和。
public function plusRandom3():Number{
return (Math.random()+Math.random()+Math.random())/3
}
// 指定割合ランダム
public function oddsRandom_0():Number{
var odds:Array = [5, 10, 10, 20, 10, 8, 5, 0, 10, 20];
return oddsRandom(odds) / odds.length; // グラフ描画の関係上、1以下の数にして返す。
}
/*
指定割合ランダム
指定された配列の割合に沿って整数値を返す。
*/
public static function oddsRandom(arg:Array):int{
if (arg.length == 0) return 0;
var maxNum:Number = 0;
var i:int;
for (i = 0; i < arg.length; i++){
if (isNaN(arg[i])) continue;
maxNum += arg[i];
}
var mainRandom:Number = int(Math.random()*maxNum);
for (i = 0; i < arg.length; i++){
if (isNaN(arg[i])) continue;
mainRandom -= arg[i];
if (mainRandom < 0){
return i;
}
}
return -1; // 数値なしError
}
// 変形4平方ランダム。balance=0.5 velvet=0.3
public function transRandom4_0():Number{
return transRandom4(0.5, 0.3);
}
// 変形4平方ランダム。balance=0.3 velvet=0.6
public function transRandom4_1():Number{
return transRandom4(0.3, 0.6);
}
// 変形4平方ランダム。balance=1.0 velvet=0.5
public function transRandom4_2():Number{
return transRandom4(1.0, 0.5);
}
/*
変形4平方ランダム。
値に沿ってrandomの割合を変換して返す。
中心点に設定した部分が一番確率が高く、両脇の確率がほぼ0になる。
balance - 中心点の位置。0~1で指定する。省略すれば0.5
velvet - なだらかさ。0~1で指定する。
0で尖った形(人←こんなん)、0.2で3角形、0.3で正規分布に近く、
0.5~0.7でドーム型、0.9で台形になり、1は普通のランダムと同じ一様な分布となる
省略すれば0.3
*/
public function transRandom4(balance:Number = 0.5, velvet:Number = 0.3):Number{
var ans:Number;
var sqrtFunctionY:Number;
var reBalance:Number;
var x:Number;
x = Math.random();
if (x < balance){
sqrtFunctionY = sqrt4(x / balance) * balance;
}else{
reBalance = 1 - balance;
sqrtFunctionY= -sqrt4((1 - x)/reBalance) * reBalance + 1;
}
ans = sqrtFunctionY*(1 - velvet) + x * velvet;
return ans;
}
private function sqrt4(arg:Number):Number{
return Math.sqrt(Math.sqrt(arg));
}
}
}
import flash.display.Sprite;
class RandomChart extends Sprite{
private var _w:int;
private var _h:int;
private var _rate:Number;
private var _isMax:Boolean = false;
private var _valueList:Array;
private var _markerList:Array;
function RandomChart(w:int, h:int, rate:Number = 1){
_w = w;
_h = h;
_rate = rate;
_markerList = [];
for (var i:int = 0; i < _w; i++){
var marker:Marker = new Marker();
_markerList.push(marker);
addChild(marker);
marker.x = i;
}
graphics.lineStyle(0, 0xffaa22);
graphics.moveTo(0, 0);
graphics.lineTo(0, h);
graphics.lineTo(w, h);
reset();
}
public function reset():void{
_isMax = false;
_valueList = [];
for (var i:int = 0; i < _w; i++){
_valueList.push(0);
moveMarkerY(i);
}
}
public function addValue(value:Number):void{
var num:int = int(value * _w);
_valueList[num]+=_rate;
moveMarkerY(num);
if (_h <= _valueList[num]) _isMax = true;
}
private function moveMarkerY(num:int):void{
var marker:Marker = _markerList[num];
marker.y = _h - _valueList[num];
}
public function isMax():Boolean{
return _isMax;
}
}
class Marker extends Sprite{
function Marker(){
graphics.beginFill(0x88cc22, 0.4);
graphics.drawRect(-3, -3, 6, 6);
graphics.endFill();
}
}