はこねのはこ

はこねさんの備忘録

バッチファイルを作成して起動するだけでその日の日付のフォルダを作成する

はじめに

小さなことから楽したいと考えていた時に、このbatファイルを作成しました。

batファイルは食わず嫌いで全く興味なくて調べたことなかったけど、 結構気軽に動かせそうです。

環境

Windows10

なぜつくったの

仕事厨二、その日の日付でフォルダを作ることがよくあるのですが、
毎回作成することがものすごく面倒に感じたので、
ダブルクリックでbatファイルを叩けばその日の日付ファイルが作成できるようにしました。

できたもの

: エコー機能無効
@echo OFF

: 日付を取得し'/'を取り除く
set dirname=%DATE:/=%

: 西暦の千の位、百の位を取り除く
set today=%dirname:~2,6%

: ディレクトリの作成
mkdir %today%

cd %today%

mkdir 01_todo
mkdir 02_done

おわりに

日常の作業を楽できる方法をもっと知りたい。

Unity 画像の向きを反転させる

はじめに

2Dゲームを作っていて、右向きの画像を左向きにするなど、反転させたい時があります。 その時の実現方法のメモです。

動いてる様子

f:id:hakonebox:20181014203254g:plain

実現方法

transform.のScaleのXを1と-1で切り替えると良さそうです。

public class ActorManager : MonoBehaviour
{
    public enum DIR
    {
        NONE,
        LEFT,
        LEFT_UP,
        UP,
        RIGHT_UP,
        RIGHT,
        RIGHT_DOWN,
        DOWN,
        LEFT_DOWN
    }
    public static Vector3 SetObjectDir(DIR dir)
    {
        Vector3 vector3 = new Vector3(1, 1, 1);
        switch (dir)
        {
            case DIR.RIGHT: 
                vector3 = new Vector3(-1, 1, 1); //右方向を向く
                break;
            case DIR.LEFT: 
                vector3 = new Vector3(1, 1, 1); //左方向を向く
                break;
            default:
                //do nothing
                break;
        }
        return vector3;
    }
}
        switch (charMoveSi)
        {
            case MOVE_DIR.STOP:
                break;
            case MOVE_DIR.LEFT:
                transform.localScale = ActorManager.SetObjectDir(ActorManager.DIR.LEFT);
                break;
            case MOVE_DIR.RIGHT:
                transform.localScale = ActorManager.SetObjectDir(ActorManager.DIR.RIGHT);
                break;
        }

おわりに

実現できるようにはなりましたが、なんだか納得できていません。
戻り値にVector3つかって、transform.localScaleに入れるのはどうなんでしょう?
もっとスマートにかけるような....

Unity Invokeの使い方メモ

はじめに

普段Unity開発してた時に、なんとなく使ってたInvoke
現在セットされているかや、キャンセルの仕方等がわかっていなかったので、 やり方を確認しました。
その時のメモです。

Invoke使い方

セットする

Invoke("CallFunction",5)

Invoke(関数名,時間)で実行します。
時間の単位は秒です。
5とすると5秒になります。
0.5fとすると0.5秒になります。

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.I)) 
        {
            Debug.Log("Invokeセットしました。");
            Invoke("CallFunction",5);
        }
    }

    void CallFunction()
    {
        Debug.Log("時間が経過しました。");
    }

f:id:hakonebox:20181013210918p:plain
5秒後に実行されました。

セットされているか確認する

IsInvoking("CallFunction")

isInvoking(関数名)を使用します。

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.I)) 
        {
            Debug.Log("Invokeセットしました。");
            Invoke("CallFunction",10);
        }
        if (Input.GetKeyDown(KeyCode.C))
        {
            Debug.Log(IsInvoking("CallFunction"));
        }

    }

    void CallFunction()
    {
        Debug.Log("時間が経過しました。");
    }

f:id:hakonebox:20181013210546p:plain
セットされている場合には戻り値はTrueになります。
CallFunction関数が実行後は戻り値はFalseになります。

キャンセルする

特定の関数のみキャンセルする

CancelInvoke("CallFunction")

cancelInvoke(関数名)を使用します。

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.I)) 
        {
            Debug.Log("Invokeセットしました。");
            Invoke("CallFunction",5);
            Invoke("CallFunctionCheck",5);
        }
        if (Input.GetKeyDown(KeyCode.C))
        {
            Debug.Log("キャンセルしました。");
            CancelInvoke("CallFunction");
        }
    }

    void CallFunction()
    {
        Debug.Log("時間が経過しました。");
    }
    void CallFunctionCheck()
    {
        Debug.Log("(確認用)時間が経過しました。");
    }

f:id:hakonebox:20181013211554p:plain
キャンセルしたCallFunction関数は実行されず、 CallFunctionCheck関数のみが実行されました。

全てキャンセルする

CancelInvoke()

cancelInvoke()引数なしで実行します。

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.I)) 
        {
            Debug.Log("Invokeセットしました。");
            Invoke("CallFunction",5);
            Invoke("CallFunctionCheck",5);
        }
        if (Input.GetKeyDown(KeyCode.C))
        {
            Debug.Log("キャンセルしました。");
            CancelInvoke();
        }
        if (Input.GetKeyDown(KeyCode.T))
        {
            Debug.Log("経過時間確認用");
        }
    }

    void CallFunction()
    {
        Debug.Log("時間が経過しました。");
    }
    void CallFunctionCheck()
    {
        Debug.Log("(確認用)時間が経過しました。");
    }

f:id:hakonebox:20181013212226p:plain

CallFunction関数もCallFunctionCheck関数も実行されませんでした。

おわりに

Invokeは使いやすくて私は好きです。

はてなブログにGoogleアナリティクスを導入する

はじめに

アクセス解析をみていて、どんな検索ワードで、どんなルートでこのページに辿り着いているのかを知りたいと思いました。

どうやらGoogleアナリティクスが良いらしいので導入してみようと思います。

導入したその時のメモです。

f:id:hakonebox:20181012192029j:plain

導入してみる

アナリティクスの申し込み

marketingplatform.google.com

公式のページからGoogle アナリティクスの使用を開始の申し込みをします。

ラッキングIDの取得

必要事項を記入するだけでした。 登録が終わるとトラッキングIDが表示されました。 f:id:hakonebox:20181012190532p:plain

はてなブログに登録する

設定→詳細設定を開き、 f:id:hakonebox:20181012193033p:plain

解析ツール→Google Analytics 埋め込みに 先ほど取得したIDを貼り付け f:id:hakonebox:20181012191142p:plain

ページ最後の"変更する"を押して設定完了です。

おわりに

思ったよりも簡単に導入できました。
本当に導入できたか不安になるくらいです。
しばらく使ってみようと思います。

HTML,Javascriptでブラウザで動く4択問題集アプリを作ってみた。(CSV読み込み)

はじめに

今日、仕事中に5時間弱ぽっかりと時間ができました。
Javascriptは以前にねこアプリを作って以来1年ほど全く触っていなかったのですが、またなにかしら遊んでみようと思い、 5時間である程度動くところまで開発するチャレンジをしてみました。

JSはしっかりと勉強したことはなく、ググりながらゴリ押しで作っているので、そのへんご了承ください。
また、このスクリプトに関しての解説は全くありません。
また、検査等もほぼほぼ行っていません。

なぜ4択問題集アプリ?

タイトルにもあるように、4択問題集アプリを作りました。
社内でちょっとした年2回試験があるのですが、それの対策のために問題集アプリをちょうど欲しいと思っていました。

できました。

GitHub

github.com

こんな感じで動きます

JS Question 4

index.html

<!DOCTYPE HTML>
<html>
<head>
   <meta charset="utf-8">
   <title>JS Question 4</title>
   <link rel="stylesheet" type="text/css" href="styles.css">
</head>
<script type="text/javascript">
   // 読み込んだデータを1行ずつ格納する配列
   var allData = [];
   var sW,sH,s;
   var now_question = 0;
   if (window.File && window.FileReader && window.FileList && window.Blob) {
   //alert('JS対応');
   } else {
   alert('JS未対応のブラウザです。たぶん動作しません');
   }

   loadCSV("./data.csv");
   setTimeout("setQuestion(now_question)", 10);//ms //一瞬間隔がないとダメみたい

   //ウィンドウサイズを取得する
   function getWindowSize() {
       sW = window.innerWidth;
       sH = window.innerHeight;
   }

   function setQuestion(number){
       document.getElementById("id_question").innerHTML=allData[number].question;
       document.getElementById("id_ChoiceA").innerHTML=allData[number].A;
       document.getElementById("id_ChoiceB").innerHTML=allData[number].B;
       document.getElementById("id_ChoiceC").innerHTML=allData[number].C;
       document.getElementById("id_ChoiceD").innerHTML=allData[number].D;
       if(allData[now_question].Q_gazo != 'none'){
           mondairesize();
           document.getElementById("id_mondaigazo").src='./gazo/'+allData[now_question].Q_gazo;
       }else{
           document.getElementById("id_mondaigazo").scr='';
           document.getElementById("id_mondaigazo").width=0;
       }
       document.getElementById("id_pf").innerHTML='';
       document.getElementById("id_kotae").innerHTML='';
       document.getElementById("id_mondaigazo").scr='';
       document.getElementById("id_kaitougazo").src='';
   }

   function next_question(){
       //現状ではループさせている
       if(allData.length-1 > now_question){
           now_question++;
       }else{
           now_question = 0;
       }
       setQuestion(now_question);
   }

   function kaitouresize(){
       getWindowSize();
       document.getElementById("id_kaitougazo").width=sW;
   }
   function mondairesize(){
       getWindowSize();
       document.getElementById("id_mondaigazo").width=sW;
   }

   function myCheck(){
       var seikai = allData[now_question].ANS;
       var kaitou = '';

       if(document.form1.elements[0].checked){
           kaitou = kaitou + 'A';
       }
       if(document.form1.elements[1].checked){
           kaitou = kaitou + 'B';
       }
       if(document.form1.elements[2].checked){
           kaitou = kaitou + 'C';
       }
       if(document.form1.elements[3].checked){
           kaitou = kaitou + 'D';
       }

       if(kaitou == seikai){
           document.getElementById("id_pf").innerHTML='正解です';
       }else{
           // 不正解の時は背景色を変えたい
           document.getElementById("id_pf").innerHTML='不正解です';
       }
       getWindowSize();
       document.getElementById("id_kotae").innerHTML=seikai;
       document.getElementById("id_kaitougazo").width=sW;
       if(allData[now_question].A_gazo != 'none'){
           document.getElementById("id_kaitougazo").src='./gazo/'+allData[now_question].A_gazo;
       }
   }

   function loadCSV(targetFile) {
       var request = new XMLHttpRequest();
       request.open("get", targetFile, false);
       request.send(null);
       var csvData = request.responseText;
       var lines = csvData.split("\n");
       for (var i = 0; i < lines.length; i++) {
           var wordSet = lines[i].split(",");
           var wordData = {
               question: wordSet[0],
               A: wordSet[1],
               B: wordSet[2],
               C: wordSet[3],
               D: wordSet[4],
               ANS: wordSet[5],
               Q_gazo: wordSet[6],
               A_gazo: wordSet[7],
           };
           allData.push(wordData);
       }
}

</script>
<body>
    <section>
        <hgroup>
            <h1>JS Question</h1>
        </hgroup>
        <section class="section-sub">
            <h4>問題</h4>
            <P id='id_question'>起動中</P>
            <img src="" alt="" id="id_mondaigazo" width="100" onclick="mondairesize();" />
            <form name="form1">
                <input type="checkbox" name="questions" value="A"><label id='id_ChoiceA'>A:選択肢A</label><br>
            <input type="checkbox" name="questions" value="B"><label id='id_ChoiceB'>B:選択肢B</label><br>
            <input type="checkbox" name="questions" value="C"><label id='id_ChoiceC'>C:選択肢C</label><br>
            <input type="checkbox" name="questions" value="D"><label id='id_ChoiceD'>D:選択肢D</label><br>
            <input type="button" value="解答" onclick="myCheck();">
            </form>
        </section>
        <section class="section-sub">
            <h4>解答</h4>
            <p id='id_pf'>-</p>
            <p id='id_kotae'>-</p>
            <img src="" alt="" id="id_kaitougazo" width="100" onclick="kaitouresize()" />
            <form name="form2">
            <input type="button" value="次の問題へ" onclick="next_question()" >
            </form>
        </section>
        <p>画像をクリックでサイズウィンドウ横幅に合わせます</p>
</body>

styles.css

.section-sub{
    background-color: #d8bfd8;
}

つかいかた

CSVに問題と選択肢、解答、参考画像の設定をします。
回答はA,B,AB,BCDなど、どれか一つ選ぶ問題でも複数選ぶ問題も対応しています。
問題の参考画像、解説の参考画像を載せたい場合は、 "gazo"というフォルダを作成し、そこに載せたい画像を保存します。 CSVに画像ファイル名を記載すれば表示できます。
記載しない場合はnoneと記載してください。

5時間チャレンジで達成できなかったこと

またぽっかり時間ができたら更新します。

おまけ宣伝ねこアプリ(クリーンキャット)

1年前に作成したアプリ。
それは癒しのwebアプリ。
たぶん仕事以外に初めて公開したアプリ。 github.com

https://yuikanoyu.github.io/cleanCat/

GitHubで有料プランに登録して毎日の進捗のチェックリストにしている話

はじめに

GitHubに課金して、およそ1.5ヵ月ほど経過しました。
草生やすの楽しいです。

※注意

この記事は、チームでGitHubを運用した話ではなく、個人でしかもプライベート運用の話です。 職場では使えないので...。

GitHub有料プラン

f:id:hakonebox:20181010233404p:plain 私は個人での運用なのでDeveloperプランです。 月額$7で無制限のプライベートリポジトリが使用できます。

なぜ有料プランにしようと思ったか

以前読んだ"独学プログラマー"という本にこのようなチャレンジがありました。

プログラミングの練習を毎日継続できるようにするためのチェックリストを作ろう。

これを実現するために、カレンダーにシールを張ったりとか、excelのような表計算ソフトも考えましたが、なるべく手間をかけずに実現したかったので、プッシュするだけで草が生えて記録となるGitHubを使おうと思いました。

しかし、無料プランではプライベートリポジトリが作成できません。
個人で開発中のものやテキストを使いながら作成したプロジェクトはプッシュしたくなかったので、試しに有料プランに登録してプライベートリポジトリ運用をしてみようと思いました。

プッシュ内容について

プログラミングの練習とありますが、何かしら自己開発で進捗があるものは全てリモートリポジトリを作成するようにして、パソコンに向かってコードを打ち込むほぼ全てを対象にしました。

意識していること

  • 改行やコメントなど、頭を使わない変更をだけでコミット&プッシュしない。

  • 明日の自分が進捗ありますか?と聞いて進捗ありますと答えられる程度の変更を目標にする。

  • 飲み会等でその日の夜に作業時間をとれなさそうなら、その日の朝早く起きて作業しておく。

  • 息を吐く様に意識せずに進捗を上げられるようになりたい。

ちょっと振り返り

よかったこと

毎日何かしら進捗を出すという習慣ができてきた気がします。 無制限にプライベートリポジトリが作成できるので、 ちょっとしたプロジェクトもガンガン履歴として残せます。

今日の夜の作業では〇〇を実装しよう。など、移動中にアイディアだしする習慣ができました。

開発&学習した跡が見えるのはやはりたのしいです。 今後も続けようという気になります。

今後への課題

更新することが目的とならないように気を付けたい。

おわりに

1.5ヶ月くらい毎日続けられてます。 f:id:hakonebox:20181010233157p:plain

おまけ

独学プログラマー

独学プログラマーこちらです。
最低限書いてあることはできるようにておいたほうがいいと思います(個人的感想)

独学プログラマー Python言語の基本から仕事のやり方まで

独学プログラマー Python言語の基本から仕事のやり方まで

プライベート草の見える化

デフォルトの設定だと、他のアカウントから、プライベートリポジトリで生えた草は見えないようです。

f:id:hakonebox:20181010233948p:plain

Contribution SettingsのPrivate contributionsを有効にしてください。 ここを設定すると他の人からも見えるようになります。

トドネロさんに教えていただきました。

Unity 1週間ゲームジャム[ぎりぎり] レースゲーム"NekoWay"公開しました。

はじめに

今回の開催期間は 2018-0-04 〜 2018-06-10でした。

遊んでいただいた方ありがとうございます。 コメント読みながら喜んでます!!

開催期間のツイートをまとめて、 振り返りをしておこうと思います。

完成したもの

公開先のリンクです。

NekoWay | 無料ゲーム投稿サイト unityroom - Unityのゲームをアップロードして公開しよう

7作目のゲームになりました。

一週間のふりかえり

1日目成果

レースゲームを作りたかったのでNekoWayつくりました。

2日目成果

3日目成果

4日目成果

5日目成果

進捗ありません。 お酒飲みたかったし。しかたないね。

6日目成果

7日目成果

アップデート

v1.1アプデしました。

ランキングの名前入力にRとTキーが使えない問題があったので修正しました。 コメントで教えていただき感謝です。

思ったことをつらつらと

反省点 面白さの肝となるコース作成に時間をかけることができなった。 Probuilderで作成する予定だったが、曲線を描くような使い方を理解できていなかった。

移動の制御は自動車のサンプルから使用。中身がわからないまま使ってしまっていた。

リプレイ機能が実装できなかった。 タイムアタック形式のゲームは リプレイがあったほうが他プレイヤーの動きを参考にできるので必要と感じたが、実装できていない。 できるかどうかの検証作業もできなかった。

WASDとJキーの入力をフレーム毎に保存しておいて、その入力を再現することでできそうだが、 壁にぶつかったときや加速床、ターボの動きが物理演算を使用しての動きとなっているため、 完全に同じような動きはできなさそう。壁にぶつかるし。

コントローラの対応が間に合わなかった。 ハンドルがキー入力だと、 どのくらい曲がるとかの制御がしにくい。

ランキング実装したかったね。

よかったこと 予想外の動きを減らすことで、ゴールまでのストレスを軽減できた。 何度もやってクリアは1面だけのコースで実装する気がしたのでぎりぎりで修正してよかった。

全体を通して、 最低目標までは期限内に実装できたが、満足できていない。 音楽とかエフェクトとか、もっとできることがあったと思うが、 もっと簡単な仕様でよかったと感じる

最後に

ハコネコー | 無料ゲーム投稿サイト unityroom - Unityのゲームをアップロードして公開しよう

PuddingJump α版 | 無料ゲーム投稿サイト unityroom - Unityのゲームをアップロードして公開しよう

シューティング、アクションに続いてレースができて、いろんなジャンルがそろい始めた。