こんにちは。アメーバ事業本部ゲーム部門の須田(@daasuu)です。
フロントエンドディベロッパーとして、ファーミーの開発・運用を担当しております。

今回は、ファーミーでとても愛されている、プラネットデコ機能の実装に関して工夫した点を少しだけ紹介します。

プラネットデコ機能とは

プラネットデコ機能とは、デコを置いたり"ほし(本体)"や"そら(背景)"を入れ替えたりしてそれぞれがお好みのプラネットを作れる機能です。

planet3planet2


ユーザーが思い思いにデコを飾り、とても可愛いプラネットが毎日たくさん生まれています。

デコを編集する

ユーザーが思い思いにデコをかざるには、ストレスなくデコを置ける仕組みが必要になります。
プラネットデコでは場所を変更したいデコをタップし、指でなぞって移動させます。
指の位置に合わせてデコのY座標、X座標、角度が替わり、デコが動きます。

planet5planet6


ぐりんぐりん指に合わせて動きますので、是非ともスマホブラウザで触ってみてください。

指の位置とデコの位置を合わせる工夫

まずはデコの位置を決める座標となる配列を用意します。
ユーザーが細かく配置できるようにするため、角度は5°ずつ替わり、全部で座標は72個と細かく作ります。また、三角関数を用い半径と角度から傾き、X座標、Y座標を計算します。

コードのサンプルは下記になります
//@param_radius デコを置く際の半径
var returnPositionAry = function(param_radius){
  
  var returnAry = [],
      centerY = 280,//中心座標例
      centerX = 240,//中心座標例
      i;

  
  //座標を生成
  for (i = 0; i < 72; i = i ++){
  
    var _angle = 5 * i,
        _dblRadian = (Math.round((_angle * (Math.PI/180)) * 100) * 0.01),
        _y = (param_radius * Math.sin(_dblRadian) * -1) + centerY,
        _x = param_radius * Math.cos(_dblRadian) + centerX,
        _rotate;
        
    _y = Math.round(_y);
    _x = Math.round(_x);
    
    if(_angle < 90){
    
      _rotate = 90 - _angle;
    
    }else if(_angle >= 90 && _angle < 180){
    
      _rotate = 270 + (90 - (_angle - 90));
    
    }else if(_angle >= 180 && _angle < 270){
    
      _rotate = 180 + (90 - (_angle - 180));
    
    }else if(_angle >= 270 && _angle < 360){
    
      _rotate = 90 + (90 - (_angle - 270));
    
    }
    //画像配置のx、y、角度のセット
    returnAry[i] = {x : _x , y : _y , rotate : _rotate};
  
  }
    
  return returnAry;

};

ARY_POSIITON = returnPositionAry(160);

次に、指の位置と上記で作成した座標の位置を合わせる実装をします。
ここでの注意点は、円の位置は座標は5度ずつずれていても、X座標、Y座標はそれぞれ等間隔でずれていかないため、Y座標、X座標それぞれ幅が大きい部分で判定をします。

座標説明


指の位置と座標の位置を合わせる実装コードのサンプルは下記になります。
//@param_stageX 指のX座標の位置
//@param_stageY 指のY座標の位置
var returnDecoPosition = function(param_stageX, param_stageY){

  var _loopStart = null,
      _loopEnd = null,
      _sizeAdjust = 5,
      centerY = 280,//中心座標例
      centerX = 240,//中心座標例
      _halfRadiusLength = 160 * 0.5,//半径が160の際の計算
      returnPositionNum;

  if(param_stageX > centerX && param_stageY <= centerY){

    _loopStart = 0;
    _loopEnd = 19;

  } else if(param_stageX <= centerX && param_stageY < centerY){

    _loopStart = 18;
    _loopEnd = 37;

  } else if(param_stageX <= centerX && param_stageY >= centerY){

    _loopStart = 36;
    _loopEnd = 55;

  } else if(param_stageX > centerX && param_stageY > centerY){

    _loopStart = 54;
    _loopEnd = 72;

  }


  //配列の位置を決定させるfor文
  for(var i = _loopStart; i < _loopEnd; i ++){

    var _moveEnableFlag = false;

    //X軸で判定する領域と、Y軸で判定する領域のチェンジ
    if(param_stageX < centerX + _halfRadiusLength 
      && param_stageX > centerX - _halfRadiusLength ){       //X軸でポジション判定       if((ARY_POSIITON[i].x + _sizeAdjust) >= param_stageX
      && (ARY_POSIITON[i].x - _sizeAdjust) <= param_stageX ){                  _moveEnableFlag = true;       }     } else {       //Y軸でポジション判定       if((ARY_POSIITON[i].y + _sizeAdjust) >= param_stageY
      && (ARY_POSIITON[i].y - _sizeAdjust)<= param_stageY){                  _moveEnableFlag = true;       }     }     //_moveEnableFlagが指の位置のポジション判定      if(_moveEnableFlag){       returnPositionNum = i;       break;            }   }      //指の位置にあう座標番号を返す。   return returnPositionNum;    };

最後に上述のARY_POSIITONに座標番号を返し、そのx座標、y座標、角度にデコを動かします。

終わりに

プラネットデコ機能の一部分を少しだけ紹介させていただきました。

また、キャプチャ画像ではうまく表現できませんが、プラネットデコは1つ1つアニメーションしており、見ていてとても癒されます

是非ファーミーをプレイし、たくさんのプラネットを覗いてみたり、自分だけのプラネットを飾ってみてください。