SS6Player使ってみたよレポ② 実行時のセル差し替え

前回の記事でSS6Playerは良い感じだよという話をしたんですが、一件紹介し忘れていた技術ネタがあったので投下しておこうと思います。

対局開始時のテロップもSpriteStudioで製作したんですが、「東一局」等の表示はプログラム側で制御できるのではないかと思い、マニュアルを漁ったところAPIはあるようだが説明がない。とはいえそんなに難しいものではなさそうなので、IntelliSenseを頼りにがんばってみることにしました。
f:id:dnasoftwares:20180418114219p:plain
あんまりもったいぶるもんではないので、とりあえずソースコード全文いきます。

KyokuStartTelopController.cs

using System.Collections;
using System.Collections.Generic;
using System.Linq;
using DNASoftwares.Mahjong;
using UnityEngine;

namespace DNASoftwares.Mahjong
{
    public class KyokuStartTelopController : MonoBehaviour
    {
        private Script_SpriteStudio6_Root _ss;
        private int[] _kyoku_cell = new int[4];
        private int[] _wind_cell = new int[3];
        private int[] _honba_cell = new int[10];
        private int[] _yourwind_cell = new int[4];

        private int _kyoku_sprite;
        private int _wind_sprite;
        private int[] _honba_sprite=new int[2];
        private int _honba_footer_sprite;
        private int _yourwind_sprite;

        //セルの名称
        public string[] KyokuWindCellNames = {"wind_east", "wind_south", "wind_west"}; //○一局 の場風の部分
        public string KyokuCellNameFormat = "kyoku_{0}"; // 東○局 の漢数字
        public string HonbaCellNameFormat = "honba_{0}"; // ○○本場 の数字
        public string[] YourWindCellNames = {"yourwind_east", "yourwind_south", "yourwind_west", "yourwind_north"}; //「あなたは○家です」の表示

        //各部位のスプライトパーツ名(SpriteStudio側で決めたのを転記)
        public string KyokuWindSpriteName = "kyoku_wind";
        public string KyokuNumberSpriteName = "kyoku_num";
        public string[] HonbaSpriteNames = {"honba_1","honba_10"};
        public string HonbaFooterSpriteName = "honba_foot";
        public string YourWindSpriteName = "wind";

        // Use this for initialization
        void Start ()
        {
            _ss = GetComponent<Script_SpriteStudio6_Root>();
            Library_SpriteStudio6.Data.CellMap c = _ss.DataGetCellMap(0);

            //都度参照だと重そうなのでチップ名からIDを引いておく
            for (int i = 0; i < _kyoku_cell.Length; i++)
            {
                _kyoku_cell[i] = c.IndexGetCell(string.Format(KyokuCellNameFormat, i + 1));
            }

            for (int i = 0; i < _wind_cell.Length; i++)
            {
                 _wind_cell[i] = c.IndexGetCell(KyokuWindCellNames[i]);
            }
            for (int i = 0; i < _honba_cell.Length; i++)
            {
                _honba_cell[i] = c.IndexGetCell(string.Format(HonbaCellNameFormat,i));
            }

            for (int i = 0; i < _yourwind_cell.Length; i++)
            {
                _yourwind_cell[i] = c.IndexGetCell(YourWindCellNames[i]);
            }

            //パーツ名も都度参照は重そうなんでIDを引いとく
            _wind_sprite = _ss.IDGetParts(KyokuWindSpriteName);
            _kyoku_sprite = _ss.IDGetParts(KyokuNumberSpriteName);
            for (int i = 0; i < _honba_sprite.Length; i++)
            {
                _honba_sprite[i] = _ss.IDGetParts(HonbaSpriteNames[i]);
            }

            _honba_footer_sprite = _ss.IDGetParts(HonbaFooterSpriteName);
            _yourwind_sprite = _ss.IDGetParts(YourWindSpriteName);

            //卓の様子をみて表示を直す
            //一旦再生させてからセルを変更しないとリセットされちゃう
            _ss.AnimationPlay(0,-1,1);
                
            //局(Taku.Instance.CurrentWind には場風が入ってる 0=東 1=南 2=西)
            if (_wind_sprite >= 0)
            {
                _ss.CellChangeParts(_wind_sprite, 0, _wind_cell[(int) Taku.Instance.CurrentWind],
                    Library_SpriteStudio6.KindIgnoreAttribute.NON);
            }
                // Taku.Instance.CurrentKyoku は何局目かが入ってる(1~4)
            if (_kyoku_sprite>= 0)
            {
                _ss.CellChangeParts(_kyoku_sprite, 0, _kyoku_cell[Taku.Instance.CurrentKyoku-1],
                    Library_SpriteStudio6.KindIgnoreAttribute.NON);
            }

            //~~本場(Taku.Instance.Honba には積み棒の数が入ってる)
            // 0本場なら関係するスプライトを全部隠す
            if (Taku.Instance.Honba == 0)
            {
                foreach (var i in _honba_sprite)
                {
                    _ss.HideSet(i, true);
                }

                _ss.HideSet(_honba_footer_sprite, true);
            }
            else
            {
                //1本以上積まれてるなら~~本場を表示
                var tmp = Taku.Instance.Honba;
                for (int i = 0; i < _honba_sprite.Length; i++)
                {
                    var num = tmp % 10;
                    tmp = tmp / 10;
                    if (num==0 && tmp == 0)
                    {
                        _ss.HideSet(_honba_sprite[i], true);
                    }
                    else
                    {
                        _ss.CellChangeParts(_honba_sprite[i], 0, _honba_cell[num],
                            Library_SpriteStudio6.KindIgnoreAttribute.NON);
                    }
                }
            }

            //プレイヤーの自風("あなたは○家です")
            //人間が操作している席を取得し、その席の自風を得て、自風のenumをintにキャスト(0,1,2,3が東南西北に対応)
            Seat seat = Taku.Instance.Seats
                .FirstOrDefault(x => x.Algorithm == Seat.AlgorithmType.HumanInterface) ?? CameraViewController.Instance.TargetSeat; 
            _ss.CellChangeParts(_yourwind_sprite, 0, _yourwind_cell[(int)seat.MyWind], 
                Library_SpriteStudio6.KindIgnoreAttribute.NON);

        }
    }
}

パーツを操作する前にAnimationPlayメソッドをまず呼ぶというところさえ間違わなければ多分そんな難しいところはないです。

public bool CellChangeParts(int idParts, int indexCellMap, int indexCell, Library_SpriteStudio6.KindIgnoreAttribute ignoreAttribute);

CellChangePartsメソッドでスプライトパーツのチップを差し替えられます。

  • idParts ……パーツID。名前で引きたかったらIDGetParts(name)で名前からIDを取得すること
  • indexCellMap ……セルマップID。セルマップ1つだけなら0で可、-1にすると今パーツが使っているセルマップを指定
  • indexCell ……セルID。名前で引きたかったらIndexGetCell(name)でID取得。-1にするとアニメーションに元々設定されていたセルを指定
  • ignoreAttribute ……これがいまいちわからんのだが「Library_SpriteStudio6.KindIgnoreAttribute.NON」としておけばとりあえず何事もない

実行時のセル指定変更は色々な応用が利くのですがマニュアルが間に合ってないのはとても残念なのでここだけ説明しました。参考になれば幸いです。