積(掛け算した値)がオーバーフローするかチェックする
はじめに
ABC169のBで躓いたので。
冷静じゃなくなると間違いが見えなくなる。
結論
一度掛け算し、その積をかけた数の片方で割った場合同じ値になるかをみている。
#define ul unsigned long bool IsOverflow(ul a, ul b){ ul x = b * a; return (x/a != b); }
補足
負の数が含まれると不正解パターンがある。
というかコンテスト中にlonglongを用いていて失敗した。
#define ll long long bool IsOverflow(ll a, ll b){ ll x = b * a; return (x/a != b); }
これを使ってしまうと下のようになる。
割とトラウマ...。
コード
// こっちでも行ける bool IsOver(ll a, ll b, ll lim){ return (b > lim/a); } // 成功した関数 bool IsOverflow(ul a, ul b){ ul x = b * a; return (x/a != b); } // コンテスト中の関数 bool IsOver_ng(ll a, ll b){ ll x = b * a; if(x/a != b){ return true; }else{ return false; } } void Main(){ ul limit = pow(10,18); ul n; cin >> n; vector<ul> a(n); for(ul i = 0; i<n;i++){ cin >> a[i]; if(a[i] == 0){ ct(0); return; } } ul ans = 1; for(ul i = 0; i < n; i++){ //if(IsOver(ans,a[i], limit)){ if(IsOverflow(ans,a[i])){ ct(-1); return; }else { ans *= a[i]; if ( ans > limit ){ ct(-1); return; } } } ct(ans); return; } int main() { Main(); }
C++の少数の出力結果が丸められてしまったのでsetprecisionマニピュレータをつかった。
はじめに
先日AtCoderさんのABC168に参加した時、
問題Cの出力結果の精度がどうしても欲しいところまで出なくて悩んでいた。
atcoder.jp
4.56425719433005553554 ...と割り切れない値のはずが、 4.56426 と表示されていた。
結論
setprecisionマニピュレータを使って解決した。
cout << fixed << setprecision(20) << getHoge() << endl;
コンテスト中に悩んでいたコード
仕様がわからずとりあえず精度を上げればなんとかならないかと考えて無意味にキャストしている。
#define ld long double ld getSqrtl(ld x1,ld y1,ld x2,ld y2){ ld x = x1 - x2; ld y = y1 - y2; ld ans = (ld)sqrtl( x*x + y*y ); return ans; } int main() { ld A,B,H,M; // 時間 分 cin >> A >> B >> H >> M; ld do2 = (ld)360.0 * ((ld)M/(ld)60.0); ld ra2 = do2 * ((ld)M_PI/(ld)180.0); ld x2 = B * cosl(ra2); ld y2 = B * sinl(ra2); ld do1 = (ld)360.0 * ((ld)H/(ld)12.0) + ((ld)30.0*((ld)M/(ld)60.0)); ld ra1 = do1 * ((ld)M_PI/(ld)180.0); ld x1 = A * cosl(ra1); ld y1 = A * sinl(ra1); cout << getSqrtl(x1,y1,x2,y2) << endl; }
出力結果
4.56426
出力の条件として、以下を満たす必要があるため不正解となってしまう。
setprecisionマニピュレータを使う
混乱しながらたどり着いた解決策がsetprecisionを使うことでした。
浮動小数点数を出力する精度を設定できる。
下記の例では少数第20位まで出力している。
cout << fixed << setprecision(20) << getSqrtl(x1,y1,x2,y2) << endl;
出力結果
4.56425719433005553554
おまけ
一回setprecisionすると次の出力では使わなくてもその出力結果になった。
cout << getSqrtl(x1,y1,x2,y2) << endl; cout << fixed << setprecision(20) << getSqrtl(x1,y1,x2,y2) << endl; cout << getSqrtl(x1,y1,x2,y2) << endl;
出力結果
4.56426 4.56425719433005553554 4.56425719433005553554
ABC167のCですごい時間使った。
— はこね (@hakone_san) May 17, 2020
C++の仕様の理解が足りなかった。
精度が足りなくて時間使ってたから悔しい。
けどsetprecisionを覚えた。 pic.twitter.com/bwvMQLWmy6
Unity InputSystemの導入(XBox,PS4コントローラで動作チェック)
はじめに
InputSystemを用いてXboxとPS4のコントローラ入力をしようと思います。
今回使用するInputSystemはPreview版です。
経緯
以前にXBoxコントローラからの入力を確認してRLトリガーの入力だけどうしていいのかわからず2年弱が経過していました。
そんな中最近ふと思いました。またプレビュー版だけどInputSystem使えばシンプルに取得できるんじゃないか..?
そんなわけで確認してみようと思いました。
環境
InputSystemにはUnity2019.1以上と。NET4ランタイムが必要とのことです。
インストール
InputSystemのインストール
PackageManagerからインストールします。
preview版なので注意してください。
InputBackendを有効にする
Edit > Project Settings > Player
先にApiCompatibillityLevelを確認し、".NET 4.x"に設定します。
ActiveInputHandlingを"Input System Paclage(New)"に設定します。
すると自動でUnityが再起動すると思います。
この設定を有効にするためには、UnityEditorを再起動する必要があるため、
自動で再起動が行われなかった場合には自身で再起動してください。
入力デバイスから直接入力を取得
まずは入力デバイスからの現在の入力状況を直接読み取りをしてみます。
using UnityEngine; using UnityEngine.InputSystem; public class CurrentInputTest : MonoBehaviour { void Update() { var gamepad = Gamepad.current; if (gamepad == null) return; // No gamepad connected. if (gamepad.rightTrigger.wasPressedThisFrame) { Debug.Log($"rightTrigger:{gamepad}"); } } }
PCに接続しているXboxコントローラとPS4コントローラのRトリガーを引いてみます。
どちらも認識できているようです。
しかもどのコントローラから入力があったのかも判別できているようですね。
下記URLを参考にほかの入力を取得することができました。 docs.unity3d.com
前回InputManagerでLRトリガーの同時押しがうまくいかなかったのですが、 InputSystemでは簡単に取得できそうです。
InputActionを介して間接的に入力を取得
PlayerInputコンポーネントの追加
AddComponentからPlayerInputコンポーネントを追加します
Actionsを作成する
CreateActions..を押すことで作成できます。
このActionsのRightTriggerを取得してみます。
InputActionからスクリプトで取得
using UnityEngine; using UnityEngine.InputSystem; [RequireComponent(typeof(PlayerInput))] public class InputActionTest : MonoBehaviour { private InputAction m_fire; private void Awake() { var actionMap = GetComponent<PlayerInput>().currentActionMap; m_fire = actionMap["Fire"]; } private void Update() { if (m_fire.triggered) { Debug.Log($"fire: {m_fire}"); } } }
今回はCreate Actionsを押してInputActionを作成しましたが、
Projectウィンドウからの右クリックから新規作成できます。
補足
Listenを使うことで、押したボタンが候補として出てくるので、 登録は簡単みたいです。
参考
Unity1週間ゲームジャム[逆]"逆上がりJUMPERS"をHingeJoint2DとUniRxを使って作った話
はじめに
今回も作りました。
イラスト:はいき丸さん
unityroom.com
逆上がりで回転して遠心力でできるだけ遠くに飛ぶゲームです。
逆上がりするのに手が短すぎるのでつり革を持たせています。
これじゃ逆上がりに見えないね。
このはこねこの動きはHingeJoint2Dを採用しています。
また、何か新しいこと学びたいなと思って、
使おう使おうと思いながら全く使ってなかったUniRxを使ってみることにしました。
こちらは着地の様子。
かわいいので実際に遊んでみてほしいです。
そして遊んだ後にきっと思うと思います。 ”逆じゃん...” と。
HingeJoint2D
はこねこの動きはアニメーションを作るのではなく、
物理演算に身を任せた動きのほうが見てて楽しいし、
遊ぶうえで楽しい要素になると思い、体のパーツをHingeJoint2Dを採用しました。
特に曲がる角度に制限を設けないことにしました。
動かすとこんな感じです。
はこねことポール接続の接続は以下のようになってます。
ばらしてみるとこんな感じ
ポールの固定について
ConnectedRigitBodyをNoneとすることで
Connected Anchor 設定で定義した空間上の点に固定しています。
はこねこの接続について
こちらはポールに固定したつり革部分を設定しています。 同じようにはこねこの体におさげ、両足、しっぽを接続しています。
UniRx
ついでにMV(R)Pパターンを意識して開発しました。
ここではスコア表示の部分の紹介です。(一部抜粋)
View
気持ち程度のラベル初期化を行い、
ラベル更新用の関数を用意。
using UnityEngine; using TMPro; public class ScoreView : MonoBehaviour { [SerializeField] private TextMeshProUGUI _scoreText; // Start is called before the first frame update void Start() { _scoreText.text = 0.ToString("#,#0"); } // 値が更新されたときにラベル更新 public void OnScoreChanged(int score) { _scoreText.text = score.ToString("#,#0"); } }
Model
ReactivePropertyでストリームソースの準備。
using UnityEngine; using UniRx; public class GameModel : MonoBehaviour { private static ReactiveProperty<int> _score = new ReactiveProperty<int>(0); public IReadOnlyReactiveProperty<int> Score => _score; public static void SetScore(int score) { _score.Value = score; } }
Presenter
値が変更になった時にラベルを変更するように設定。
using UnityEngine; using UniRx; public class MenuPresenter : MonoBehaviour { // View [SerializeField] private ScoreView _scoreView; // Model [SerializeField] private GameModel _gameModel; void Awake() { Bind(); } private void Bind() { _gameModel.Score .Subscribe(_scoreView.OnScoreChanged) .AddTo(gameObject); } }
まだ自信をもって記述できてないので、
少しずつ触っていこうと思います。
1週間振り返り
2/24
今回こそはスキージャンプ台を逆走するゲームでオンライン対戦ありにしようとしてました。
意気揚々とオンライン対戦ボタンを準備。
また、PUN2の動作確認を進める。
しかし、今回もオンライン要素は見送りとなりました。不穏なボタンが見える #unity1week pic.twitter.com/pc9Dlv53MU
— はこね (@hakone_san) 2020年2月24日
3/1
しばらく時間が空いて3/1。
このゲーム面白いのか?病が発症。
ゲームデザインの再考をし、悩んだ挙句変更を決意。
#unity1week pic.twitter.com/O3c7VzrhCb
— はいき丸 (@haikimaru) 2020年3月1日
3/2
締め切り日20:00には間に合わず、翌日深夜4時までかけて開発しきりました。
びっくりするくらい進捗報告してませんでした。今ビルドしてるわけだから。 #unityroom
— はこね (@hakone_san) 2020年3月1日
さいごに
私としては、この作品はとてもよくできたと思っています。
物理演算を活かした動きは見ててかわいらしいし、
結果が出るまでの時間が短く、何度もリトライしやすいデザイン。
ここ最近、難しいことをしようとして複雑で最後まで遊びにくいものばかりでした。
かわいいイラストを描いてくれたはいき丸さんと
ゲーム内容の相談に乗ってくれた友人に感謝。
MacのCLionで#include <bits/stdc++.h>を使えるようにする。
はじめに
前回、MacのCLionでコンパイラの設定をしていました。 しかし、いざ使ってみると、
#include <bits/stdc++.h>
が読み込み得ずに下記のエラーがでてしまっていました。 その解決策です。
fatal error: 'bits/stdc++.h' file not found #include <bits/stdc++.h> ^~~~~~~~~~~~~~~ 1 error generated.
hakonebox.hatenablog.com 前回の設定ではインストールしたコンパイラは使えていなかったみたいですね。
解決策
c++ComPilerに下記のパスを記入。
/usr/local/opt/gcc/bin/g++-9
これで無事ビルドできました。
MacでもCLionを動かそうとしたらmissing xcrun at: /Library/Developer/CommandLineTools/usr/bin/xcrunと言われた話
はじめに
タイトルの通りです。
MacbookでもCLion使いたいので環境整えようとしました。
そしたらタイトルのエラーがでてあわあわしてました。
確認手順
Clion→Preferences→Toolchains コンパイラ見つかんないって怒られているみたい。
確認してみる。
gcc --version xcrun: error: invalid active developer path (/Library/Developer/CommandLineTools), missing xcrun at: /Library/Developer/CommandLineTools/usr/bin/xcrun
エラーでてきた。
コマンドラインツールは入れてたと思ったのですが...
調べてみるとmacOSのアップデートが原因で発生するみたいです。
下記コマンドで
xcode-select --install
インストール完了後CLionで確認したら無事認識できました。
ついでにアップデートもしておきます。
brew install gcc
無事ビルドできるようになりました。
追記
しかしこれではインストールしたコンパイラは使えていなかったみたいです。 ↓↓ hakonebox.hatenablog.com
CLionの実行結果の文字化けを直す
はじめに
CLion入れました。 www.jetbrains.com
文字化けが起きてしまったのでその解決方法。
環境
- Windows10
結論
文字コードの設定をUTF-8に合わせました。 chcpで切り替えてもダメみたいだった(起動時に戻ってしまう。)ので 断腸の思いでベータの機能を採用。
ベータ:ワールドワイド言語サポートでUnicode UTF-8を使用
にチェックをつける。
検証コード
#include <bits/stdc++.h> using namespace std; int main() { cout << "競プロ" << endl; cout << "Hello CLion" << endl; }