ラベル プログラミング の投稿を表示しています。 すべての投稿を表示
ラベル プログラミング の投稿を表示しています。 すべての投稿を表示

2023年12月31日日曜日

【Unity】アスペクト比を維持して固定値を使わずに整列させる

アスペクト比を維持して固定値を使わずに整列させる方法をなんと2つも説明します。

問題設定

まずは目指す状態について説明します。

上の画像では半透明の範囲に本の画像とその白背景のセットが2つ描かれています。また白背景は正方形で、本の画像はその中に収まります。つまり、本+白背景の縦横比は1:1になります。

整列の設定を上手く施すことで、中身を増減させても自動的に間隔を調整してくれます。実際私は、以下の画像を作る時に位置や大きさを入力しませんでした。


以降の章でこの自動整列の設定方法について解説します。

なお、この記事では横に整列させる方法を解説しますが、Horizontal←→Vertical、Width←→Heigh(t)と適宜変換すれば縦にも同様に整列させられます。

共通部分

自動整列を実装する方法は複数ありますので、まずはそれらの共通部分について説明します。

上の画像は本の画像と白背景のセットが2つある場合のヒエラルキーです。

上のヒエラルキーに登場するCanvas内のGameObjectが有するComponentを以下に示します。

  • Area(親オブジェクト)
    • Horizontal Layout Group
      • 横に整列させるやつ。今回の主役
      • Control Child SizeのHeighをTrueにして、子の縦の長さを親に合わせるようにする
      • Child Force ExpandはいずれもTrueに
    • Image
      • 半透明なやつ
  • GameObject 1(子オブジェクト)
    • 今は何もつけない
  • Background(孫オブジェクト)
    • Image
      • ただの白背景なので、Spriteは何も入れない
  • Book(孫オブジェクト)
    • Image
      • 本の画像を挿す
      • 画像の比を維持するため、Preserve Aspectをtrueに

これらに追加でComponentを加えるケースもあります。

Aspect Ratio Filterを子オブジェクトにつける方法

Areaに紐づける"Horizontal Layout Group"の"Control Child Size"のHeighがTrueになっている場合(上の画像)、子のオブジェクト(GameObject1)のHeightには何も入力できない状態になります。"Control Child Size"はその名の通り、子のWidthやHeightを親が決定するかどうかのフラグであり、Trueになると子オブジェクトに対するWidth/Heightの入力を受け付けなくなります。

子オブジェクトにてHeightが入力できない状態

本と白画像のセットの縦横比は1:1にするためには、Widthの値をHeightからコピーしてくる必要があります。そこで、子オブジェクトに"Aspect Ratio Filter"を適用します。

Aspect Ratio Filterはそのオブジェクトのアスペクト比を自動で決定するためのComponentです。Aspect Modeで"Height Controls Width"を選択すると、WidthがHeightの値から自動入力されます。このように設定することで、本+白背景を複製しても同じ親にある限り上手に間隔を作ってくれます。

しかし残念なことに、子オブジェクト以下をPrefab化してスクリプト上から複製すると自動整列が機能しません。Aspect Ratio FilterとHorizontal Layout Groupが共存すると発生する問題のようで、入力をロックする箇所が異なっていても動作しないようです(実際警告が出てる)。Aspect Ratio Filterが先にWidthやHeightをロックすることで後のLayoutGroupが動作できなくなり、機能しないのではないかと睨んでいます。Prefabから生成する場合は次の方法を試してみてください。

Aspect Ratio Filterを孫オブジェクトにつける

代替案として、子オブジェクトの代わりに孫オブジェクト(Background)にAspect Ratio Filterをつけることでも自動整列が可能です。その際、Aspect Modeを"Envelope Parent"に設定しましょう。Envelope Parentモード下では、元々設定していた孫オブジェクトの大きさを子の大きさによって拡大することが可能になります。

孫オブジェクト(Background)のComponent

上の画像ではW Deltaに82.79999と入力されています。これは親オブジェクトのHeightが182.79999で、元々設定されていた子オブジェクトのWidthが100であり、Envelope Parentによって引き伸ばされた分がW Deltaに入力されます。

この方法ではPrefabから生成しても自動整列が機能します。Aspect Ratio FilterとHorizontal Layout Groupが同じ箇所をロックすることもないので、警告も発生しません

余談

自動整列問題がややこしいのは、WidthやHeightを画面の大きさに応じて変化させようとするからです。WidthやHeightに固定値を入力させられれば、Layout Elementなどを利用してもっとわかりやすく自動整列を実装できます。まずは画面のサイズを最初に決めて、WidthやHeightに固定値を入力させるのが良いと思います(一敗)。

まとめ

  • XXX Layout Groupを親に設定して整列させる
  • Aspect Ratio Filterを子か孫に設定してアスペクトを維持させる
  • 画面のサイズは最初に決めよう


以上です。

2023年7月2日日曜日

【プログラミング】ヘクス座標系でのマスの管理方法

 
こんにちは、あすらと(@__asurato__)です。

モダンなゲームではあまり見かけなくなりましたが、大戦略やCivilizationのような戦略シミュレーションではヘクス座標系が採用されています。ヘクス座標系では1つのマスが正六角形になっており、正六角形の各マスは隙間なくマップに敷き詰められます。本日はヘクス座標系のマスの管理方法について考察しましたのでご覧ください。



ヘクスマップの例

前提


本記事では以下を前提としています。これらの前提が容易・高速に達成できるアルゴリズムが良い手法であるとここでは定義します。
  • Tileクラスが各マスの情報を表す
  • Tile型のインスタンスは配列や二次元配列に格納される
  • マスが指定されたらそのマスに関するTile型のインスタンスを取得したい
  • あるマスに隣接しているマスも取得したい

例えば tiles[id] 等でそのidに関するTile型のインスタンスを取得することができれば前の3つについて達成されます。言い方を変えると、関数f: id→Tile となる関数が作れるならOKです。

またマスXに隣接したマスYを取得できれば最後の項目は達成されます。前3つの項目によりidからTileへの変換は前提とするため、XのidからYのidが取得できれば達成されます。


以下からマスの管理方法について章立てで説明します。


並んでる方向にIDを振る手法(一次元)


すごく自然なIDの振り方で、右上のマスは+3、右下は+4と隣接マスも計算しやすいです。ただし以下のような上下で対称でないマップの場合、右上のマスはIDが+4 or +5され固定値になりません。

上下が非対称なヘクスマップ

このような場合はIDを振る方向を横に変えるとなんと解決します。


すごくない?
  • 特徴
    • 隣接マスのIDの取得が簡単
    • 自然な発想
    • メモリの無駄がない
    • マップが長方形の場合のみ使用可能

二次元直交座標に変換する手法


一次元的にIDを与えるのではなく、二次元座標を用いて各マスを二次元配列に格納することもできます。座標[a, b]のマスはtiles[a][b]として取得します。

問題点として、tiles[0][0]とは異なりtiles[0][1]には値が存在しません。tiles[a][b]が存在するかを常にチェックする必要があります。

  • 特徴
    • 隣接マスのIDの取得が簡単
      • 例)a→a+1、b→b+1で右下のマスを取得できる
    • 全てのマップ系で使用可能
    • 座標にマイナスの値が含まれるときは別途対処の必要あり
    • 配列の戻り値がTileとNullの2種類があり、Nullチェックが必要
    • 二次元配列のうち半分が死にマスとなり、メモリの無駄遣い♠️


二次元直交座標+Map法


上の手法の派生系で、二次元座標を文字列に変換してMapに格納する手法です。ちなみにPythonのようにタプルをキーにできる言語や、座標を示す構造体をMapのキーに自前で設定する場合は文字列への変換は不要です。メリットはメモリの無駄がないこと、デメリットは座標とMapのキーとの相互変換が面倒な点でしょう。

  • 特徴
    • 隣接マスのIDの取得には座標とMapのキーとの相互変換が必要
    • メモリの無駄がない
    • 座標がマイナスを含む場合も対応できる
    • 全てのマップ系で使用可能


二次元座標+配列法


私が考えたイケイケアルゴリズムです。

まず上図のように軸を設定し座標を計算します。B軸の位置について、Aの要素が0以上になるように設定しましょう。

次に2つの配列を用意します。1つ目の配列には全てのマスが格納され、もう1つの配列には前者の配列のキー(ID)が入ります。


まず要素Aが小さい順に、要素Aが同値の場合は要素Bが小さい順にマスを配列1へ格納します。その格納の際に、要素B=0となるマスの(配列1における)IDを配列2に格納します。2つの配列を用いて、座標(a, b)のマスは arr1[arr2[a] + b] として取得できます。


  • 特徴
    • 隣接マスのIDの取得が簡単
      • 例)a→a-1、b→b+1で右下のマスを取得できる
    • ほとんどのマップ系で使用可能
      • ただし間が空くマップ系だと「二次元直交座標に変換する手法」と同様にNullチェックが必要になる
    • メモリの無駄がない
    • 軸が斜めになっているので直感的ではない
      • でも頑張れば直交座標でも使えそう

まとめ

  • マップが長方形ならIDを縦or横方向に振る方法でよい
    • 縦か横かはその時のマップの性質によって見極める必要がある
  • 二次元直交座標+Map法は任意のマップで使えるので、最終手段として検討しよう
  • 二次元座標+配列法はコードが少し難しくなるが色々効率的

参考サイト

http://higesusk.blog.fc2.com/blog-entry-146.html
https://ninagreen.hatenablog.com/entry/2015/11/14/193417
https://sinsei.space/blog/11747
https://www.redblobgames.com/grids/hexagons/

2023年5月6日土曜日

【Rust】IteratorとVecの関数が多すぎ?


RustはC言語並みの実行速度、モダンな言語特有の安全性、堅牢な型システムを有するプログラミング言語です。

Stack Overflowの調査ではRustは最も愛される言語に選ばれましたが、Rust固有の概念や型システムは難解で言語の性能に比べて愛用者は少ない印象です。「好きな言語?まぁ、Rustかな。」と言った日には圧倒的玄人感で周囲を威圧させ、その眩き威光には流石の水戸黄門も平伏すしかありません。

そんな厨二病患者へのサポートも欠かさない言語、Rust。私も最近勉強を始めました。しかしサクッと競プロも問題を数問解いてみたところ、このような感想を持ちました。



ということで検証しました。


Rust


Rustの関数の個数は以下でした。(手作業のため誤差があるかもしれません)
  • Iterator: 75個
  • Vec: 50個
  • Array: 12個

やっぱりVecとIteratorの数が多いですね。これはRustがオーバーロードを実装していない点が原因の一つです。reduce関数fold関数は顕著な例で、初期値の有無のみで2つの関数に分かれています。


続いてRust以外の言語の関数の数について紹介します。


JavaScript


  • Array: 45個

(そうだよ!これだよこれ!)

JavaScriptのArrayはVecとIteratorの役割を同時に果たすことも相俟って、関数の数は少ないです。まあブラウザで動かし続けないといけないからね。そりゃ慎重にもなる。


Java


  • Stream: 33個(オーバーロードの関数名重複ありで39個)
  • List: 22個(オーバーロードの関数名重複ありで28個)
  • Arrays: 17個(オーバーロードの関数名重複ありで155個)


155個!?

これは私の推測ですが、Arraysクラスの関数の多さはJavaが互換性を残しているためだと考えられます。binarySearch関数は全部で18個存在し、T[]のようなジェネリクス以外にint[]やdouble[]を引数として用意する徹底ぶり。

しかし、比較的新しいStreamクラスについてはRustに比して関数は少なく、Listクラスについても同様です。


C#


  • LINQ(IEnumerator): 66個(オーバーロードの関数名重複ありで213個)
  • List: 32個(オーバーロードの関数名重複ありで48個)
  • Array: 32個(オーバーロードの関数名重複ありで94個)


さて私の愛するC#ですが、意外と関数が多い。競プロで使うくらいLINQ好きなんですけどね...

なんか雲行きが怪しくなりました。


Scala


さて、Pythonは組み込み関数だから比較は難しいし、あと触ったことがある言語は......Scalaかぁ。




  • Collection: 150個




結論



疑ってすまないRustくん。君も多い方なんだろうけど......

あと今日からScala叩きに転身します。


P.S. Pythonのリストの関数は11個でした。



終わり

2020年4月22日水曜日

【C#】競プロ用にSegmentTreeのライブラリを作ったよ!

SegmentTreeってセグメント木とかセグ木とか色々に呼ばれているので検索するの苦労しません?
あなたはどのワードでここに辿り着きましたか?

先にコードを載せます。超普通のセグ木になります。

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4.  
  5. namespace Library
  6. {
  7. public class SegmentTree<T> where T: struct
  8. {
  9. private readonly T[] data;
  10. private int size = 1;
  11. private T defaultValue;
  12. private Func<T, T, T> function;
  13.  
  14. public SegmentTree(int size, T defaultValue, Func<T, T, T> function)
  15. {
  16. while(this.size < size) this.size *= 2;
  17. this.defaultValue = defaultValue;
  18. this.function = function;
  19. data = Enumerable.Repeat(defaultValue, this.size * 2 - 1).ToArray();
  20. }
  21.  
  22. // [a, b)
  23. public T RangedValue(int a, int b) { return RangedValue(a, b, 0, 0, size); }
  24.  
  25. private T RangedValue(int a, int b, int now, int l, int r)
  26. {
  27. if (r <= a || b <= l) return defaultValue;
  28. if (a <= l && r <= b) return data[now];
  29.  
  30. return function(RangedValue(a, b, now * 2 + 1, l, (l + r) / 2), RangedValue(a, b, now * 2 + 2, (l + r) / 2, r));
  31. }
  32.  
  33. public T this[int index]
  34. {
  35. get
  36. {
  37. return data[size + index - 1];
  38. }
  39. set
  40. {
  41. index += size - 1;
  42. data[index] = value;
  43. while (index > 0)
  44. {
  45. index = (index - 1) / 2;
  46. data[index] = function(data[index * 2 + 1], data[index * 2 + 2]);
  47. }
  48. }
  49. }
  50. }
  51. }

以下工夫した点

  • Genericsの型であるTに値型の制約を与えた
  • indexによるアクセスでより直感的に
  • ぐう短い

2020年3月31日火曜日

「Atcoderで水色になるまでにやったこと」を書きます


グラフが歪すぎる。

自己紹介



名前:アスラト
言語:C#
コンテスト出場回数:22回
入水時点のACCount:330

画像の通り競プロはやったり辞めたりしていました。
個人ではほとんどありませんがゲーム製作でプログラムを書いています。
ちなみに製作でのC#は二年ほどのブランクがあります。実質競プロ専用言語。

やったこと



大きく三段階に分かれています。
時系列順に並べましたが、「この順番でやるべき」という意味ではありません。
  1. AtCoderProbremsで古い時期のC問題と簡単なD問題を毎日解いた
  2. 125番目以前でD問題のDifficultyが水〜青色なABCを時間制限をつけて解いた
  3. 「レッドコーダーが教える、競プロ・AtCoder上達のガイドライン」を半分くらい解いた
上の三点とC#の話について書きたいと思います。


AtCoderProbremsで古い時期のC問題と簡単なD問題を毎日解いた



具体的にはABC64以前のC, D問題を1日1問以上を目安に解きました。
Streak数は驚異の41!すごい!ほめて!





誰も褒めないので私が褒めます!えらい!
大学で帰る前に図書館に行って問題を解いてから帰るという生活を送っていたおかげですね。
このように競プロを強制的に触れる環境を作り習慣化させました。
最初のアプローチとしては正しかったと思います。

一方でアルゴリズムに関しては大学の授業程度の知識しかありませんでした。(蟻本未購入勢)
過去問中に知らない解き方が出てきたらグーグルで検索する......といったことを繰り返し行ってきました。
これは非常に無駄が多くお勧めできません。
先に体系立ったアルゴリズムの学習または速解きの練習から始めることをお勧めします。


125番目以前でD問題のDifficultyが水〜青色なABCを時間制限をつけて解いた



古い時期でそこそこ簡単なC, D問題が枯渇し始めてからこちらに移行しました。
AtCoderのバーチャルコンテスト機能を利用してA〜D問題まで解きました。
こちらの目的は専ら速解きです。

特に茶〜緑色で
「D(orE)問題は無理!しかもC(orD)問題で大量に時間を消費した!」
という時はぴえん😭な結果になることを身を持って体験してきたはずです。
ある程度解けるようになったらどこかで速解きの練習はした方がいいと思います。
あとバーチャルコンテストで私と対戦しましょう!


「レッドコーダーが教える、競プロ・AtCoder上達のガイドライン」を半分くらい解いた




みなさんこれをやりましょう。学習に向いている問題ばかりです。
ちなみに「半分」である理由は、解いている最中に水色に昇格しただけで深い理由はありません。
これのおかげかは分かりませんが、解き始めた3/5辺りからレートが急上昇したのでみなさんやりましょう。

振り返って



振り返ると「体系的学習→演習」の流れを完全に崩してしまった気がします。
蟻本等で勉強した上で上述のリンクをクリアし、その後速解きの練習をすると要領良く水色に昇格できると思います。
ただ1, 2番目の演習を先であっても私の血肉になりえたことはここに明言させていただきます。

C#はぶっちゃけどうなの?



C#の良い点はそこそこ速くて綺麗に書けることです。
LINQの暴力だけでなく、入力部分を工夫するだけでもC++より簡潔に記述できます。(関連:【C#】手抜き競プロライブラリ〜入力編〜
其を侮る勿れ、短く書け得ることはそれだけ伸び代を残していることを意味します。
C++よりも一歩先のレートに足を伸ばせるかもしれませんね。実際私も水色になれたわけで。

とはいえ、速さ及びライブラリの充実度においてC++には到底叶いません。
速さは言わずもがな、C#には優先度付きキューも平衡二分木も順列列挙も存在しません。
加えてどマイナーな問題を解くとC#で提出している人が極端に減ります。

ではなぜC#を使うのか。理由は「使えた」ことと「関数型」です。
そもそも「関数型を使って綺麗に速くかけるようになりたい」という願望から私の競プロ生活が始まりました。
そして新たに言語を学ぶ気になれなかった私は、当時使えたC, C#, Java, JavaScriptの中からLINQがあるC#を選択したという歴史的な背景が存在します。

最後にC#もとい競プロの言語についてめちゃくちゃ良いこと言うので聞いてください。

競プロをする目的が競プロならC++にしろ。そうでないならなんでも良い。

これが私の結論です。
何をするにも言えますが、目的や目標の明確化を心がけると良いと思います。

今後



私の当初の目標は水色になることでしたが、まだ上昇の余地が残されているのでもう少しだけ続けてみようと思います。
青に昇進できてもできなくてもまた記事を書きたいですね。

P.S.
水色に昇進することを入水って表現するのすこ

2019年12月27日金曜日

【C#】手抜き競プロライブラリ〜入力編〜

最近競プロを再開しました。
競プロやってたって言えたらかっこいいじゃないですか。
目標は水色。

今日は基本中の基本かつ速度の大幅な向上を期待できる入力のライブラリをご紹介します。

といってもStreamを使ってどうたらこうたら......とかはしないです。

あくまで自分の理解を越えない範囲で、コスパの良い書き方を目指しました。
  1. class Input {
  2. static IEnumerator<string> enumerator = new string[] { }.AsEnumerable().GetEnumerator();
  3.  
  4. public static string Line => Console.ReadLine();
  5.  
  6. public static string[] StrArr => Line.Split(' ');
  7.  
  8. public static int NextInt => int.Parse(NextWord());
  9.  
  10. public static long NextLong => long.Parse(NextWord());
  11.  
  12. public static List<int> IntList => StrArr.Select(int.Parse).ToList();
  13.  
  14. public static List<long> LongList => StrArr.Select(long.Parse).ToList();
  15.  
  16. public static string NextWord() {
  17. while (!enumerator.MoveNext()) {
  18. enumerator = StrArr.AsEnumerable().GetEnumerator();
  19. }
  20. return enumerator.Current;
  21. }
  22. }

うーん、NextWordだけ"()"が必要なあたりすごく手を抜いてる感が出てますね。

NextInt等はJavaのScannerに挙動が近いです。(Scannerの宣言ないけど)
  1. var a = NextInt;
  2. Console.WriteLine(a);

こんな感じ。

賢い点はenumeratorの初期値に空のstringを入れていること。
これによってwhile文の条件式が簡潔に済ませられます。

コードはご自由にどうぞ。間違いがあったらごめんね。

2018年7月14日土曜日

【PixiJS】 learningPixi(チュートリアル)の最初を解説


「pixijs」で検索すると一番上に出てくるサイトがこちら

ここから resources > view tutorials > Getting started with PixiJS と開くことで、

https://github.com/kittykatattack/learningPixi

こちらのサイトが表示されます。

PixiJSを使おうと思うと一度は見るページになるでしょう。
私も始めて見たんですが導入まで結構時間がかかってしまいました。

今日はPixiJSを使えるようにするための導入部分を解説したいと思います。
あとは自分でがんばって

1. インストールするもの(pixi.min.js)


まずPixiJSを動かすために専用のファイルが必要になります。
重要なのがインストールするものはホームページにでっかく出ているこっちではなく、




必要なのは pixi.min.js というファイルです。
しかし、上の方をインストールしてもこのファイルは得られません。なんじゃそりゃ

チュートリアルの"Installing Pixi"に従ってそれ専用のサイトに飛んでインストールするか、チュートリアルのサイトの一番上からインストールできます。

チュートリアルを進めるために結局これをインストールすることになります。
どうせならこっちの方を落とした方がいいと思います。

緑色のボタンで"Clone or Download"と書いてあるところを選択し、ダウンロードしましょう。

2. webサーバーを介そう



Introductionを読んで、Setting up、Pixi Applicationとstageを作った!
さーて次は画像を表示するのかー



画像が表示されないなぁ〜〜?

ローカルな環境でhtmlを開いても画像は表示されません!
"file:~"ではない方法で開かなくてはいけません。

https://qiita.com/massie_g/items/2913066e596dae197539

こちらのサイトで紹介されているので解説は省略します。
ちなみに私はVSCodeを使った方法で解決しました。VSCodeはさいつよ

(追記)
firefoxを使えばローカルな環境でhtmlを開いても画像が表示されます!
firefox以外のブラウザだと上記の作業が必要になります。

3. まとめ

  1. pixi.min.js をインストールする!
  2. webサーバーを介す!

おわり!

2018年6月28日木曜日

【unity】コルーチンの中でwhile文を書いたら

  1. IEnumerator DealHard () {
  2. while (time > 0) {
  3. time -= Time.deltaTime;
  4.  
  5. lefttime.text = ((int)time).ToString ();
  6. }
  7. time = 0;
  8.  
  9. Debug.Log ("タイムアップ");
  10. }

このスクリプトは残り時間を計測しその秒数をテキストに出しています。

このコードではunityが途中でバグります。(それか一瞬でtimeが0になる)

どこが間違っているかお分かりですか?

  1. IEnumerator DealHard () {
  2. while (time > 0) {
  3. time -= Time.deltaTime;
  4.  
  5. lefttime.text = ((int)time).ToString ();
  6.  
  7. yield return null; // ここ
  8. }
  9. time = 0;
  10.  
  11. Debug.Log ("タイムアップ");
  12. }

正解は yield return null をwhileの中に書いていないことです。

そもそも Time.deltaTime は前のフレームと次のフレームの時間差を取るものです。
最初のコードでは無数の繰り返し処理が1フレームで行われてしまいます。
そして何やかんやでunityが死ぬ。

yield return null はそのフレームの作業を中断し次のフレームから再開させます。
つまり、 Time.deltaTime との相性がよくなるわけです。
よかった、これで解決ですね

2018年6月19日火曜日

【unity】GUI上でButtonの状態に応じてtextの色を変える

タイトルの問題に関して以下の英語の記事を参考にしました
というかほぼ答え感ある
https://answers.unity.com/questions/940456/how-to-change-text-color-on-hover-in-new-gui.html




ボタンにマウスを重ねた時にボタンじゃなくてテキストの色が変わってほしい!
黒色から赤色に変わってほしい!

テキストの色を変えるのは結構簡単に変えることができます。

ButtonコンポーネントのTransitionが "Color Tint" になっていることを確認して、
Transitionの中のTargetGraphicをTextを持っているオブジェクトに変えればいいだけです。

それでできるんかーい

ちなみにTargetGraphicにTextが出てこない場合はButtonとTextの親子関係を確かめてください。
デフォルトなら大丈夫です。

デフォルトの親子関係


しかーーーーし!!!

マウスを重ねている状態

これだと黒色から赤っぽい黒色に変わっただけです。
マウスを重ねた時に黒色から完全な赤色に変えるにはどうしたらいいのでしょうか。

答えはTextのフォントの色を白にし、ButtonのNomalColorを黒にすればいいのです。



ButtonのTrasitionでの色の変更はあくまで元々の色に新しい色でかけ算を行なっているだけです。
なのでもしフォントの色が完全な黒(=RGBが全て0)では、Buttonから色の変更を試みても掛けたら0になるので真っ黒のままになります(Buttonの色変更を受け付けない)。
黒色から赤っぽい黒色になったのもこれが原因。

それなら元々のフォントの色を完全な白(=RGBが全て1)にして、後から色を変えるときは全てButton側から行えば良いのです。


余談ですがこれの本領を発揮するのはButtonの表示を透明にすることにあります。

これが

こうじゃ


スクリプトなしでもそれっぽいUIが作れそうですね。これは強い。

2018年5月13日日曜日

AtCoder Beginner Contest 097 に初心者ながら参加しました

アスラトです。

「もっとコードを綺麗に書きたいなー」と漠然と考えるようになってきた今日この頃。
アルゴリズムを勉強しようと思い立ちそれ関係の本を探していました。
が、その中でAtcoderというアルゴリズム学習に適したサイトを見つけたので
ワイ「ま、後で考えましょ」ポーイ
......ということでそれ関係の本は後回しにしてとりあえず参加してみました。

今日はその結果と感想です。ちなみにC言語で書きました

A問題


A問題

A問題はそんなに難しくはなかったです。(なおかかった時間)

絶対値の関数ってなんだっけ?
大きい方を出力する関数って何をincludeしなきゃいけないんだっけ?
ファ!?Xcodeがなんかおかしい

ということを調べていたらA問題に13分ぐらいかかってしまいました。悲しい


B問題


B問題

「正整数 X 以下の最大のべき乗数を求めてください。」という問題です。

リンク先に書いてありますが、べき乗数の底と指数は任意です。

これを私は平方数だと勘違いしていました。

だって入出力例がうまく通っちゃったんですもの...

aという変数に入力されたデータを代入したら、
printf("%d", (int)sqrt(a)*(int)sqrt(a));
こうやれば終わりじゃね?はっやーいと思って提出したら弾かれました。

問題文はしっかり見ような(戒め)


C問題


C問題

A,B共に問題を見たらすぐに道筋が思いつきましたがCはそうはいきませんでした。

途中でC言語きつくね?C#かjavaでlistを使ったらいけそう...?とか考えましたがやめました。
夕食食べてなかったんですよ。残り時間が半分になったところで夕食にしました。

...で戻ってきたのはコンテスト終了直前。当然できるはずもなく。
悲しいというかそれはそうという感想。


まとめ


コンテストに関しての感想は

  • 問題文はしっかり読もう
  • C問題からはもう少し典型問題勉強してから挑みたい
  • C言語の基礎がよくわかっていないと思った
  • 先に夕食を食べよう

やってみて分かったこともあります。
が、何よりアルゴリズムの勉強をしようというやる気が生まれたのは大きかったです。
皆様も是非。

2018年5月8日火曜日

【unity】ボタンのクリック領域がずれた

自分のホームページを作ってみたものの何もゲームがなくて寂しい...
ということで急遽ゲームを作っています。GW?知らないなぁそんなものは
その作業中ボタンの領域判定がずれてしまったことを記事にします。



これは1~15まで書かれたボタンをプレハブを使って設置しています。
グラデーションは気にしないでください。
これだけだと問題あるようには見えませんがカーソルを近づけると、



自分のカーソルとは違う場所に色がついています。
グラデーションは(ry

1. canvasの描画順


私が見落としていた部分がいくつかあって、その1つがcanvasの描画順です。



この画像では上から1,2,3,...,15とCloneが作られています。
数字は子オブジェクトのテキストに表示させています。
canvas内で上にある方が一番奥に描画されるので、ここでは"1"が最も奥に描画されます。
先ほど見ていただいた動画では10や15などの右端の数字の判定領域が大きくなっていました。
これは10や15がその行で最も手前に描画されるためです。

2. 子オブジェクトの範囲


次は知らなかったのですが、ボタンの有効範囲は子オブジェクトに影響されることです。
子オブジェクトが広かったらその分クリックされる範囲も大きくなります。
実は他サイト様を参考にしながら透明な画像を追加してみたり迷走していましたが、うまく行かず、試行錯誤すること30分。



ワイ「だめや......いろいろ追加してみたけど表示がおかしいままや.......ん?」



ワイ「めっちゃ広いやんけええええええええええええええええええ」

というわけでwidthを親オブジェクトと同じにするとうまくいきました。
テキストもクリックの領域に含まれるんですね。



3. まとめ


今まで何を喋ってきたのかというのを横からの投影図で表しました。
緑がボタンの範囲(= 本来押されてほしい場所)で、
青がその数字のクリックが有効な場所で、
灰色が描画順により無効になっている部分です。



(この図で余計にわかりにくくなったらすみません)