n-HIROKIの日常

n-HIROKIの取り組みを記録したものです。

ローカル開発環境 導入メモ VirtualBox Vagrant

こんにちは!
n-hirokiです!



ローカル開発環境について(Mac OS

ローカル開発環境って何?

自分のアプリケーションやホームページなどの作品をいきなりインターネット上に公開するのはリスクが高いです。
サーバーを借りるのにも お金がかかるのでコストもかかります。

「ローカル開発環境」とは手元のPCにレンタルサーバーと同じような環境を作り ローカルでテストや開発ができる環境のことを言います。

ローカル開発環境を作成するためのツール VirtualBox Vagrant

VirtualBox とは PCに仮想環境を構築して 他のOSをインストールすることができる仮想化ソフトのことです。
例えば Virtualboxを導入すると Mac環境で WindowsLinux など複数のOSを切り替えて使用することができます。
Virtualbox は手元のPCの中にいくつもサーバーを立ち上げることができます。
ただ Virtualbox はサーバーの設定やOSのインストールが大変なので 簡単なコマンドを使えるようにするために「Vagrant」というツールを導入できます。
環境構築後に直接さわるのはVagrantだけになります。



ローカル開発環境の構築

VirtualBoxのインストール

VirtualBoxの公式サイトでダウンロードします。
ダウンロードができたらパッケージを開き 指示の通りに入力していけばインストールできます。
詳しく知りたい方は 自分で調べてみてください。

Vagrantのインストール

Vagrantの公式サイトでダウンロードします。
ダウンロードができたらパッケージを開き 指示の通りに入力していけばインストールできます。
詳しく知りたい方は 自分で調べてみてください。


残りの作業

ユーザーのHomeフォルダの下に開発に使うフォルダを作成します。ぼくはMyVagrantという名前にしました。
MyVagrantフォルダの中でサーバーを管理するフォルダを管理していきます。ぼくはMyCentOSにしました。
IPアドレスは192.168.33.10にしています。


ターミナルでの作業に移ります。

1、ホームディレクトリに移動
cd

2、MyVagrantディレクトリ作成
mkdir MyVagrant

3、MyVagrantディレクトリに移動
cd MyVagrant

4、仮想マシンを入れるディレクトリ作成
mkdir MyCentOS

5、MyCentOSに移動
cd MyCentOS

6、Vagrantfileを作成する
vagrant init bento/centos-6.8

7、IPアドレスの設定
sed -i '' -e 's/# config.vm.network "private_network", ip: "192.168.33.10"/config.vm.network "private_network", ip: "192.168.33.10"/' Vagrantfile

8、仮想マシンを起動する
vagrant up

9、ログイン
vagrant ssh


コマンドを打つところがvagrantから始まっていればログインできています。

これでOSのインストールは完了です!


10、OSを最新の状態にアップデート
sudo yum -y update


OSを最新の状態にできました。

あとはPHPRubyなどのアプリケーションを自分の好みでいれていけばOKです!

自分の開発環境に合わせたアプリケーションを調べていれてみてください。

PHPRubyの導入はドットインストールで説明されているのでとても参考になります!

vagrant起動(復習)

1、ターミナル起動
2、cd
3、cd MyVagrant
4、cd MyCentOS
5、vagrant up (起動)
6、vagrant ssh (ログイン)


FezNote #1 最初から躓く

こんにちは!
n-hirokiです!

今日も開発していきます



HTML書いていく

前回のブログ
hiroki-prog.hatenablog.com

簡単なデザイン(index.html) をノートに手書きでできたのでマークアップしていきます!


あ、今気づいたけど他の画面とか機能とか全然考えてないやw
いったん戻る

機能やら画面デザインやら全部洗い出す

サービス名: Plat
代表者 1人 のブログは Plat に載せるけど 他の参加者は Plat じゃなくてtwitterでもいいかもしれない!
ハッシュタグ つけて呟いてもらう感じ
その日によってハッシュタグを変えれば わかりやすそう
それと Plat ではtwitterAPIを使ってそのハッシュタグのツイートを拾って表示すればいいかな

Plat 上でだけブログを載せるよりも twitterも使えば盛り上がりやすい気がする
それに サーバーの負荷が少なそうw

サーバートラブルとか怖いしw

そう言っても ユーザー数はそこまで増えないと思うし 最初からうまくはいかないだろうけどね

。。。。
とにかく作りますw





色々考えた結果
twitterAPIを結構使いそうなので まずはtwitterAPIを勉強してからコーディングに入ることにします
一通りtwitterAPIを理解したら 今一度デザインから考えようと思います


次回からはtwitterAPIの内容を書いていければと思います

最初に開発していきます とか書いたけど 開発っぽいことしてねーw


「みんなで創る」 ブログサイトの開発始めます!!

こんにちは
n-hirokiです



昨年の振り返りとこれからの話

昨年の秋ごろからHTML CSS javascriptの基礎の勉強を始めました(以前勉強していたことあるんだけど)
これからはサービスを開発することで実力をつけて行こうと思います

今は「パーフェクトjavascript」を勉強中です
やっぱり難しくてあまり理解が追いついていない気がします


なので!


コーディングしていきながらテキストを学ぶ体制にしようと思います
そしてブログを書くのが苦手なので、開発記録をブログにしていきます
それとモチベーションにも繋がるので少し広告も貼っていこうと思います(今までも貼っていたので今更なんだけどw)


webサービスを作ります!

タイトルにもありますが、ちょっと変わったブログサイトを作ろうと思います

以前から「みんなで創る」を作りたかったのです

本当は 僕はアニメや漫画などバーチャルな文化が好きなので みんなで「オリジナルキャラクターを創る」を作りたかったのですが まだ実力が足りない気がするので 徐々に積み上げていきます
インフラ や セキュリテーは無知なので少し怖いですが 作らないと始まらないにで ガリガリ作っていきます
もちろん 技術を勉強しながら一人で なので ペースは遅いかもしれませんが とにかくやります


どんなブログサイト??

1日に1ブログをみんなで作り上げるブログサイトです

STEP1 "ブログ"をユーザーの1人が書きます
STEP2 決まった時間にそのブログをサイトに載せます
STEP3 他のユーザーがそのブログを読んだ上で コメント欄 や掲示板 みたいな感じで そのサイトに "ミニブログ" を書きます
STEP4 他のユーザーの"ミニブログ"を読んで また"ミニブログ"を書いてもOK

短く言うと
「1人が "ブログ" を書いて、みんながそのブログについての"ミニブログ"を書いて盛り上げて、1つのブログを作り上げる」
こんな感じ!!

伝わったかな?
伝わってるといいな!

その他

HTML5 + CSS3 + Javascript + (PHP)で作りたい
node.js mySQL twitterAPIを使う予定です
ターゲットはスマホです

ブログのテーマはプログラムで作りたかったけど 自分の好きな「アニメや漫画などのバーチャルなもの(二次元)」をテーマにしようと思います(仮)
特にバーチャルYouTuberを題材にしたブログとか書いてもらいたいw

ちゃんとモックを作りたいのですが 初めてのサービスになるので手書きで簡単に済ませます
やる気が高いうちにコーディングをある程度やらないと 形にならない可能性を感じるためです
それと 僕にはデザインのセンスがないので 気に入ったデザインができずに 挫折しないためでもあります


とにかくスピード重視(僕のペースで)でやっていきます!


終わりに

これからこのブログで開発記録を書いていきます
ブログタイトルの始めはわかりやすく統一させます

「FezNote #1 ◯◯◯◯」こんな感じでFezNote ブログナンバー タイトル で書いていきます!

読んでいただけたら 泣いて喜ぶので ぜひこれからよろしくお願いします!!


グラブルの4択クイズを作りました!! javascript

こんにちは!
n-hirokiです!


グランブルーファンタジーの4択クイズを作成しました!

こちらから試してください↓
グラブルクイズ


クイズの内容は更新していければと思います。
本当は、キャラ特化や、武器特化、マルチ特化で別々に作りたかったのですが、いつかやりたいです!

コードはあとで載せます。

今回苦戦したこと

一番苦戦したことは、ブラウザをクロームでしか試していなかったため、safariで開いた時の背景色が付いていなかったことです。
あと、レスポンシブしたかったのですが今回は行なっていません。
PC向けです。スマホだとかなりキツイですwww
次からはちゃんとCSSにもこだわりたいです!


そして、何より一番時間がかかったのが、クイズの作成ですw
問題数は30問用意しましたが、まだまだ作りたいです!


あと、クイズはjavascriptに全てガリガリ書いたので答えは「要素の検証」でみれますw
本当はPHPなどで問題や答えを隠した方がよかったですw

コード

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>グラブルクイズ</title>
    <link rel="stylesheet" href="css/style.css">
</head>
<body>
    <div id="open">
     Check Answer
    </div>
    
    <div id="mask" class="hidden"></div>
    
    <div id="modal" class="hidden">
        <p id="result">正解 or 不正解</p>
        <p id="ans">答えはこちら</p>
        <p id="score">正解数/問題数</p>
        <div id="close">
            next quiz
        </div>
    </div>
    
    <div id="quizArea">
        <p id="quiz">ここにクイズが表示されます。</p>
    </div>
    
    <div id="ansArea">
        <ul>
            <li id="select1" class="select">選択肢1</li>
            <li id="select2" class="select">選択肢2</li>
            <li id="select3" class="select">選択肢3</li>
            <li id="select4" class="select">選択肢4</li>
        </ul>
    </div>
    <div id="tips">
        <p>Tips:全10問出題されます。答えを選択し、一番上の「Check Answer」を押してください。</p>
    </div>
    <script src="js/main.js"></script>
</body>
</html>



  (function(){
    'use strict';
    var open = document.getElementById("open");
    var mask = document.getElementById("mask");
    var modal = document.getElementById("modal");
    var close = document.getElementById("close");
    var result = document.getElementById("result");
    var ans = document.getElementById("ans");
    var score = document.getElementById("score");
    var quiz = document.getElementById("quiz");
    var selectAns1 = document.getElementById("select1");
    var selectAns2 = document.getElementById("select2");
    var selectAns3 = document.getElementById("select3");
    var selectAns4 = document.getElementById("select4");
    var quizList, QUIZ;
    var userAns = 0;
    var quizAns = 0;
    var quizCount = 0;
    var correctCount = 0;
    var correct = "";
    var Settled = [];
    //問題数
    var max = 30;
    //出題数
    var quizNumber = 10;
    
    
    
    quizList = function(){
        //クイズ1
        this.quiz1 = "問題";
        this.quiz1Select1 = "選択肢1";
        this.quiz1Select2 = "選択肢2";
        this.quiz1Select3 = "選択肢3";
        this.quiz1Select4 = "選択肢4";
        this.quiz1Ans = 答え;
        
  //上記のクイズ1のように好きなだけクイズを作成します
                
        
        this.quizSelect = function(){
        //クイズ選択メソッド
            var num = doubleCheck(Settled);  //同じクイズが出題されないようにチェック
            var temp = [];
            
            if(num != false){ //クイズが全て出題済みだったらfalseがnumに代入されている
                Settled.push(num);
                console.log(Settled);
            }else{
                ending();
            }
            
            //プロパティ呼び出し用変数
            temp.push('quiz' + num);
            temp.push('quiz' + num + 'Select1');
            temp.push('quiz' + num + 'Select2');
            temp.push('quiz' + num + 'Select3');
            temp.push('quiz' + num + 'Select4');
            temp.push('quiz' + num + 'Ans');
            
            //整数numのクイズを出題する
            quiz.innerHTML = QUIZ[temp[0]];
            selectAns1.innerHTML = QUIZ[temp[1]];
            selectAns2.innerHTML = QUIZ[temp[2]];
            selectAns3.innerHTML = QUIZ[temp[3]];
            selectAns4.innerHTML = QUIZ[temp[4]];
            quizAns = QUIZ[temp[5]];
            correct = QUIZ[temp[quizAns]];  //正解は数字じゃなくて文章で表示
            ans.innerHTML = correct;
//            quiz数カウント
            quizCount++;
        };
        
    };
    
    function ending(){
  //結果を表示するだけのPHPファイルに遷移
        window.location.href = 'result.php?correctCount=' + correctCount + "&quizCount=" + quizCount;
    }
    
    function doubleCheck(Settled){
    //出題していないクイズを返す関数 Settledに出題したクイズナンバーを持っている
        var num, temp;
        var check;
        do{
            if(Settled.length == quizNumber){
                console.log(quizNumber + "問全てのクイズを出題しました。");
                return false;
                break;
            }else{
                num = rand(1,max); //乱数発生
                check = true;
            }
            
            if(Settled[0] == undefined){
            //初回は代入されていないのでundefinedになるため回避
                break;
            }else{
                for(var i = 0;i < Settled.length;i++){
                //numが出題済みかチェック
                    if(num == Settled[i]){
                        check = false;
                    }
                }
            }
        }while(check == false) //出題していないクイズが選択されるまでループ
        return num; //クイズナンバーを返す
    }
    function rand(min, max){ //乱数発生
               return min + Math.floor(Math.random() * (max - min + 1));
    }
    
    open.addEventListener('click', function(){
        modal.className = '';
        mask.className = '';
        //答えあわせ
        if(userAns == quizAns){
            result.innerHTML = "正解";
            //正解数カウント
            correctCount++;
        }else{
            result.innerHTML = "不正解";
        }
        score.innerHTML = correctCount + "/" + quizCount; //正解数/出題数表示
        
        //問題数がquizNumberになったらsee resultに変える
        if(quizCount == quizNumber){
            close.innerHTML = "see result";
        }
    });
    
    close.addEventListener('click', function(){
        if(quizCount == quizNumber){
            ending();
        }
        modal.className = 'hidden'; //モーダルウィンドウを非表示
        mask.className = 'hidden'; //モーダル時の背景色を非表示
        QUIZ.quizSelect(); //クイズ選択
        classRemove(); //選択肢リセット
        userAns = 0;
    });
    
    mask.addEventListener('click', function(){
        close.click();
    });
    
    selectAns1.addEventListener('click', function(){
        userAns = 1;
        classRemove();
        selectAns1.classList.add('check');
    });
    selectAns2.addEventListener('click', function(){
        userAns = 2;
        classRemove();
        selectAns2.classList.add('check');
    });
    selectAns3.addEventListener('click', function(){
        userAns = 3;
        classRemove();
        selectAns3.classList.add('check');
    });
    selectAns4.addEventListener('click', function(){
        userAns = 4;
        classRemove();
        selectAns4.classList.add('check');
    });
    function classRemove(){
        selectAns1.classList.remove('check');
        selectAns2.classList.remove('check');
        selectAns3.classList.remove('check');
        selectAns4.classList.remove('check');
    }
    QUIZ = new quizList();
    QUIZ.quizSelect();
})();

HTMLとjavascriptだけですがこんな感じです!
addEventListenerが便利すぎて楽しいですw


javascriptも少しは慣れてきたかな?と思えるようになりました!
3ヶ月前の自分と比べるとかなりレベルアップしていると思います!


近いうちにフレームワークなどにも手を出したいですが、javascriptは基礎をしっかり学びたいのでもう少し我慢しますw


javascript シューティングゲームを作った話

こんにちは!
n-hirokiです!



少し前にシューティングゲームを勉強のために作ったのでブログにまとめます。
僕は、敵を動かすプログラムと、プレイヤー機を動かすプログラムを分けて作りました。
それが以下の過去記事にあります。
今回は、それらを組み合わせて「あたり判定」などを加えてシューティングゲームを完成させます!

hiroki-prog.hatenablog.com
hiroki-prog.hatenablog.com

シューティングゲーム 全体のコード

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>shootingの骨組み</title>
</head>
<body>
    <canvas id="mycanvas" width="500" height="500">
        Canvasに対応したブラウザを使ってください。
    </canvas>
    <p>操作方法:十字キーで移動!! shiftキーで打つ!!</p>
    <script>
        (function(){
            'use strict';
            var canvas, ctx;
            var Enemy, enemys = [];
            var beam, Beams = [];
            var box, Box;
            var Stage, stage;
            
            //flag
            var directionFlag = "RIGHT";
            var flagY = false;
            var ENDFLAG = false;
            var maxRow = 2;
            var gameFlag = "NOW GAME";
            var timer;
            
            //canvas定義
            canvas = document.getElementById('mycanvas');
            if(!canvas || !canvas.getContext) return false;
            ctx = canvas.getContext('2d');
            
            //enemyオブジェクト
            Enemy = function(x, y, row){
                this.x = x;
                this.y = y;
                this.r = 15;
                this.row = row;
                this.color = "#FF6060";
            };
            //enemy drawメソッド
            Enemy.prototype.draw = function(){
                ctx.fillStyle = this.color;
                ctx.fillRect(this.x, this.y, this.r, this.r);
            };
            //enemy x軸移動
            Enemy.prototype.direct = function(value, index){
                value.rowCheck(value, index);
                if(directionFlag == "RIGHT"){
                    value.x += 10;
                }else if(directionFlag == "LEFT"){
                    value.x -= 10;   
                }
            };
            //行判定
            Enemy.prototype.rowCheck = function(value, index){
                if(index == enemys.length - 1){
                    maxRow = value.row;
                }
            };
            //y移動
            Enemy.prototype.moveY = function(value, index){
                value.loseCheck(value, index);
                if(flagY == true){
                    value.y += 10;
                    if(index == enemys.length - 1){
                        flagY = false;
                    }
                }
            };
            //負け判定
            Enemy.prototype.loseCheck = function(value, index){
            //canvasのy軸の70%攻め込まれたら負け
                if(value.y >= canvas.height * 0.7){
                    gameFlag = "LOSE";
                    console.log("LOSE");
                    clearTimeout(timer);
                }
            }
            //一番最後の列の 一番端のenemyが canvasからはみ出しそうになったら左右逆にする
            //一番最後の行を基準にしているためはみ出す
            Enemy.prototype.flagJudge = function(value, index){
                //右→左 xが450以上だったら 全てのenemyを判定
                if(value.x >= 450 && value.row == maxRow){
                    directionFlag = "LEFT";
                    flagY = true;
                }
                //左→右 row == 2だと3行目のenemyがいなくなったらtrueにならないのでmaxRow変数で行数を持っておく
                //xが30以下でかつ最後の行だったら もしくは ENDFLAG(最後の行)がtrueだったら
                if((value.x <= 30 && value.row == maxRow) || ENDFLAG == true){
                    ENDFLAG = true;
                    //ENDFLAGがtrueかつindexが最後(enemyを全部チェックしたか)
                    if(ENDFLAG == true && index == enemys.length - 1){
                        directionFlag = "RIGHT";
                        flagY = true;
                        ENDFLAG = false;
                    }
                }
            };
            
            //boxオブジェクト
            box = function(){
                this.x = 250;
                this.y = 400;
                this.r = 60;
                this.maxX = canvas.width - this.r;
                this.maxY = canvas.height - this.r;
                this.color = "#000000";
                this.draw = function(){
                    ctx.fillStyle = this.color;
                    ctx.fillRect(this.x, this.y, this.r, this.r);
                };
                //canvasからはみ出さないようにする
                this.move = function(){
                    if(this.x >= this.maxX){
                        this.x = this.maxX;
                    }
                    if(this.x < 0){
                        this.x = 0;
                    }
                    if(this.y >= this.maxY){
                        this.y = this.maxY;
                    }
                    if(this.y < 0){
                        this.y = 0;
                    }
                };
            };
            //ビームオブジェクト
            beam = function(){
                this.x = Box.x + Box.r / 2;  //プレイヤー機の中央から発射
                this.y = Box.y - 10;
                this.r = 2;
                this.color = "#FF0000";
                this.draw = function(){
                    ctx.fillStyle = this.color;
                    ctx.fillRect(this.x, this.y, this.r, this.r);
                };
            };
            //キー判定
            document.onkeydown = function(e){
                if(e.keyCode == 37){
                    //←キー判定
                    Box.x -= 5;
                }else if(e.keyCode == 38){
                    //↑キー判定
                    Box.y -= 5;
                }else if(e.keyCode == 39){
                    //→キー判定
                    Box.x += 5;
                }else if(e.keyCode == 40){
                    //↓キー判定
                    Box.y += 5;
                }
                if(e.shiftKey){
                    //ビームを一つ追加 20発まで
                    if(Beams.length < 20){
                        Beams.push(new beam());
                    }
                }
            }
            //enemy生成関数
            function formEnemy(){
                var x = 0, y = 0;
                for(var row = 0;row < 3;row++){
                    for(var num = 0;num < 10;num++){
                        x = 30 * num + 50;
                        y = (15 * row + 20) + (row * 10);
                        enemys.push(new Enemy(x, y, row));
                    }
                }
            }
            //あたり判定
            function contactCheck(){
                Beams.forEach(function(beamValue, beamIndex){
                   enemys.forEach(function(enemyValue, enemyIndex){
                       if(enemyValue.x <= beamValue.x && enemyValue.x + enemyValue.r >= beamValue.x + beamValue.r){
                           if(enemyValue.y <= beamValue.y && enemyValue.y + enemyValue.r >= beamValue.y + beamValue.r){
                                Beams.splice(beamIndex, 1);
                                enemys.splice(enemyIndex, 1);
                                //勝ち判定
                                if(enemys.length == 0){
                                    gameFlag = "WIN";
                                    console.log("WIN");
                                    clearTimeout(timer);
                                }
                           }
                       }
                   }); 
                });
            }
            //基本処理
            stage = function(){
                //画面初期化
                this.clear = function(){
                    ctx.fillStyle = "#ecf0f1";
                    ctx.fillRect(0, 0, canvas.width, canvas.height);
                };
                //基本処理
                this.update = function(){
                    this.clear();
                    //enemy処理
                    enemys.forEach(function(value, index){
                        value.direct(value, index);  //x軸移動
                        value.moveY(value, index); //y軸移動
                        value.flagJudge(value, index);  //左右の判定
                        value.draw(); //描画
                    });
                    //プレイヤー機の処理
                    Box.move();
                    Box.draw();
                    //ビームを描画
                    for(var i = 0; Beams.length >= i + 1; i++){
                        Beams[i].y -= 5;
                        //はみ出し判定
                        if(Beams[i].y <= 0){
                            Beams.splice(i, 1);
                        }else{
                            Beams[i].draw();
                        }
                    }
                    contactCheck(); //あたり判定
                    //タイマー
                    if(gameFlag == "NOW GAME"){
                        //NOW GAMEの間タイマー起動
                        timer = setTimeout(function(){
                            this.update();
                        }.bind(this), 100);
                    }else if(gameFlag == "WIN"){
                        alert("WIN");
                        //WINの時の処理
                    }else if(gameFlag == "LOSE"){
                        alert("LOSE");
                        //LOSEの時の処理
                    }
                }
            };
            
            formEnemy();  //enemy生成
            Box = new box();
            Stage = new stage();
            Stage.update();
        })();
    </script>
</body>
</html>



今回作ってみて1番苦戦したのが、X軸の移動です。
なかなか思ったように方向が変更できませんでした。
あとは、プレイヤー機をboxじゃなく、ちゃんとした画像を用意したり、背景や効果音、挿入歌などを用意できれば結構クォリティが上がると思うので、今度チャレンジしたいです!

シューティングゲームのプレイヤー機を動かすプログラム

こんにちは、n-hirokiです!
今回はシューティングゲームのプレイヤーのプログラムです。



前回の敵のプログラムはこちら
hiroki-prog.hatenablog.com



動作:十字キー or マウスで動き、shiftキーで弾を撃ちます。

完成したものはこちら

boxオブジェクト(プレーヤー)
var box, Box;

box = function(){
    this.x = 250; //x座標
    this.y = 400; //y座標
    this.r = 60; //辺の長さ
    this.maxX = canvas.width - this.r; //canvasでのx軸の移動範囲
    this.maxY = canvas.height - this.r; //canvasでのy軸の移動範囲
    this.color = "#000000"; //プレイヤーの色
    this.draw = function(){ //プレイヤー描画メソッド
        ctx.fillStyle = this.color;
        ctx.fillRect(this.x, this.y, this.r, this.r);
    };
    this.move = function(){ //プレイヤーがcanvasからはみ出さない
        if(this.x >= this.maxX){
            this.x = this.maxX;
        }
        if(this.x < 0){
            this.x = 0;
        }
        if(this.y >= this.maxY){
            this.y = this.maxY;
        }
        if(this.y < 0){
            this.y = 0;
        }
    };
};
boxをドラッグ&ドロップで動かす
var mousedown, mouseX, mouseY;
canvas.addEventListener('mousedown',function(de){ //mousedownしたら実行
    var x, y, rect;
    rect = de.target.getBoundingClientRect(); //windowとcanvasとの差を埋める
    x = de.clientX - rect.left; //canvas上のマウスポインタの座標を取得
    y = de.clientY - rect.top;
    //boxの上でクリックされたか
    if(Box.x < x && Box.x + Box.r > x){ 
        if(Box.y < y && Box.y + Box.r > y){
            mousedown = true; //mousedownしている間true
            mouseX = x; //mouseポインタの初期位置取得
            mouseY = y;
        }
    }
});
canvas.addEventListener('mouseup', function(){ //mouseupしたら実行
    mousedown = false;  //mouseupしたらflagをfalseに
});
canvas.addEventListener('mousemove', function(me){//mousemoveしたら実行
    var x, y, rect;
    var goX, goY;
    if(mousedown == true){ //mousedownしているか
        rect = me.target.getBoundingClientRect(); //windowとcanvasの座標の差を埋める
        x = me.clientX - rect.left; //mouseの座標を取得
        y = me.clientY - rect.top;
        Box.x = Box.x + (x - mouseX); //mouseが動いた分だけboxを動かす
        Box.y = Box.y + (y - mouseY);
        mouseX = x; //基となるmouseの座標を更新
        mouseY = y;
    }
});
キーボードイベント
var mousedown, mouseX, mouseY;
var temp = {
    "key37" : 0,
    "key38" : 0,
    "key39" : 0,
    "key40" : 0
};
document.onkeydown = function(e){ //キーボードが入力されたら実行
    if(e.keyCode == 37){ //←キー判定
        tempClear("key37"); //←キーが連続で押された回数を加算
        if(temp.key37 >= 3){ //連続で3回以上押されていたら加速
            Box.x -= 13;
        }else{
            Box.x -= 5; //通常のスピード
        }
    }else if(e.keyCode == 38){//↑キー判定
        tempClear("key38");
        if(temp.key38 >= 3){ //連続で3回以上押されていたら加速
            Box.y -= 13;
        }else{
            Box.y -= 5; //通常のスピード
        }
    }else if(e.keyCode == 39){//→キー判定
        tempClear("key39");
        if(temp.key39 >= 3){ //連続で3回以上押されていたら加速
            Box.x += 13;
        }else{
            Box.x += 5; //通常のスピード
        }
    }else if(e.keyCode == 40){//↓キー判定
        tempClear("key40");
        if(temp.key40 >= 3){ //連続で3回以上押されていたら加速
            Box.y += 13;
        }else{
            Box.y += 5; //通常のスピード
        }
    }
    function tempClear(index){ //十字キーの連続で押された回数をカウント
        if(index == "key37"){
            temp.key37++;
            temp.key38 = temp.key39 = temp.key40 = 0; //他のキーが押されたらクリア
        }else if(index == "key38"){
            temp.key38++;
            temp.key37 = temp.key39 = temp.key40 = 0;
        }else if(index == "key39"){
            temp.key39++;
            temp.key37 = temp.key38 = temp.key40 = 0;
        }else if(index == "key40"){
            temp.key40++;
            temp.key37 = temp.key38 = temp.key39 = 0;
        }
    }
    if(e.shiftKey){ //shiftキー判定
        console.log("shift");
        //ビームを一つ追加 20発まで
        if(Beams.length < 20){ //弾を撃つ
            Beams.push(new beam());
        }
    }
    if(e.altKey){//altキー判定
        console.log("alt");
    }
    if(e.ctrlKey){//ctrlキー判定
        console.log("ctrl");
    }
};
弾オブジェクト
var beam, Beams = [];
beam = function(){
    this.x = Box.x + Box.r / 2; //boxの真ん中から撃つ(x軸)
    this.y = Box.y - 10; //boxから少し離す(y軸)
    this.r = 2; //辺の長さ
    this.color = "#FF0000"; //弾の色
    this.draw = function(){ //描画
        ctx.fillStyle = this.color;
        ctx.fillRect(this.x, this.y, this.r, this.r);
    };
};
全体の動き
var stage, Stage;
stage = function(){
    //画面初期化
    this.clear = function(){
        ctx.fillStyle = "#ecf0f1";
        ctx.fillRect(0, 0, canvas.width, canvas.height);
    };
    //基本処理
    this.update = function(){
        this.clear(); //canvasクリア
        Box.move(); //boxの位置がcanvasからはみ出していないかチェック
        Box.draw(); //box描画
        //弾を描画
        for(var i = 0; Beams.length >= i + 1; i++){
            Beams[i].y -= 5; //弾のスピード
            //はみ出し判定
            if(Beams[i].y <= 0){
                Beams.splice(i, 1); //canvasからはみ出したら弾を消す
            }else{
                Beams[i].draw(); //はみ出していなければ描画
            }
        }
        //タイマー
        setTimeout(function(){ //100ms間隔で繰り返す
            this.update();
        }.bind(this), 100);
    }
};
全体のコード
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>boxSystem</title>
</head>
<body>
    <canvas id="mycanvas" width="500" height="500">
        Canvasに対応したブラウザを使ってください。
    </canvas>
    <script>
        (function(){
            'use strict';
            var canvas, ctx;
            var box, Box;
            var beam, Beams = [];
            var stage, Stage;
            var mousedown, mouseX, mouseY;
            var temp = {
                "key37" : 0,
                "key38" : 0,
                "key39" : 0,
                "key40" : 0
            };
            
            canvas = document.getElementById('mycanvas');
            if(!canvas || !canvas.getContext) return false;
            ctx = canvas.getContext('2d');
            
            document.onkeydown = function(e){
                if(e.keyCode == 37){
                    tempClear("key37");
                    if(temp.key37 >= 3){
                        Box.x -= 13;
                    }else{
                        Box.x -= 5;
                    }
                }else if(e.keyCode == 38){
                    tempClear("key38");
                    if(temp.key38 >= 3){
                        Box.y -= 13;
                    }else{
                        Box.y -= 5;
                    }
                }else if(e.keyCode == 39){
                    tempClear("key39");
                    if(temp.key39 >= 3){
                        Box.x += 13;
                    }else{
                        Box.x += 5;
                    }
                }else if(e.keyCode == 40){
                    tempClear("key40");
                    if(temp.key40 >= 3){
                        Box.y += 13;
                    }else{
                        Box.y += 5;
                    }
                }
                
                function tempClear(index){
                    if(index == "key37"){
                        temp.key37++;
                        temp.key38 = temp.key39 = temp.key40 = 0;
                    }else if(index == "key38"){
                        temp.key38++;
                        temp.key37 = temp.key39 = temp.key40 = 0;
                    }else if(index == "key39"){
                        temp.key39++;
                        temp.key37 = temp.key38 = temp.key40 = 0;
                    }else if(index == "key40"){
                        temp.key40++;
                        temp.key37 = temp.key38 = temp.key39 = 0;
                    }
                }
                if(e.shiftKey){
                    console.log("shift");
                    if(Beams.length < 20){
                        Beams.push(new beam());
                    }
                }
                if(e.altKey){
                    console.log("alt");
                }
                if(e.ctrlKey){
                    console.log("ctrl");
                }
            };
            canvas.addEventListener('mousedown',function(de){
                var x, y, rect;
                rect = de.target.getBoundingClientRect();
                x = de.clientX - rect.left;
                y = de.clientY - rect.top;
                if(Box.x < x && Box.x + Box.r > x){
                    if(Box.y < y && Box.y + Box.r > y){
                        mousedown = true;
                        mouseX = x;
                        mouseY = y;
                    }
                }
            });
            canvas.addEventListener('mouseup', function(){
                mousedown = false; 
            });
            canvas.addEventListener('mousemove', function(me){
                var x, y, rect;
                var goX, goY;
                if(mousedown == true){
                    rect = me.target.getBoundingClientRect();
                    x = me.clientX - rect.left;
                    y = me.clientY - rect.top;
                    Box.x = Box.x + (x - mouseX);
                    Box.y = Box.y + (y - mouseY);
                    mouseX = x;
                    mouseY = y;
                }
            });
            stage = function(){
                this.clear = function(){
                    ctx.fillStyle = "#ecf0f1";
                    ctx.fillRect(0, 0, canvas.width, canvas.height);
                };
                this.update = function(){
                    this.clear();
                    Box.move();
                    Box.draw();
                    for(var i = 0; Beams.length >= i + 1; i++){
                        Beams[i].y -= 5;
                        if(Beams[i].y <= 0){
                            Beams.splice(i, 1);
                        }else{
                            Beams[i].draw();
                        }
                    }
                    setTimeout(function(){
                        this.update();
                    }.bind(this), 100);
                }
            };
            beam = function(){
                this.x = Box.x + Box.r / 2;
                this.y = Box.y - 10;
                this.r = 2;
                this.color = "#FF0000";
                this.draw = function(){
                    ctx.fillStyle = this.color;
                    ctx.fillRect(this.x, this.y, this.r, this.r);
                };
            };
            box = function(){
                this.x = 250;
                this.y = 400;
                this.r = 60;
                this.maxX = canvas.width - this.r;
                this.maxY = canvas.height - this.r;
                this.color = "#000000";
                this.draw = function(){
                    ctx.fillStyle = this.color;
                    ctx.fillRect(this.x, this.y, this.r, this.r);
                };
                this.move = function(){
                    if(this.x >= this.maxX){
                        this.x = this.maxX;
                    }
                    if(this.x < 0){
                        this.x = 0;
                    }
                    if(this.y >= this.maxY){
                        this.y = this.maxY;
                    }
                    if(this.y < 0){
                        this.y = 0;
                    }
                };
            };
            Box = new box();
            Stage = new stage();
            Stage.update();
        })();
    </script>
</body>
</html>


結構ドラッグアンドドロップで動かすプログラミングに手こずりました。
addEventListenerを初めて使ったのでかなり勉強になりました。

最初はaddEventListener(マウスダウン)の中にaddEventListener(マウスムーブ)を入れればうまく行くんじゃないのか?と思って試したらマウスダウンしてないときにもマウスムーブのaddEventListenerが反応していてうまくいかなかったり、初歩的なことでつまずいたりしていました。

ですが、そのデバッグのおかげで理解が深まり ためになりました!

何よりも、コピペじゃなくて自分で考えて書けたのがとても嬉しかってです!


次は、シューティングゲームの全体のブログを書きますのでよろしくお願いします!


シューティングゲームの敵を動かすプログラム

こんにちは、n-hirokiです。

今回はシューティングゲームの敵を動かすプログラムです。

完成したもの

enemyを10体3行分 生成して動かします。
一番後に全体のコードを載せています。

1、enemy生成

enemyオブジェクトで必要な変数定義
var canvas, ctx;
var Enemy, enemys = [];
canvas定義

htmlに記述します

    <canvas id="mycanvas" width="500" height="500">
        Canvasに対応したブラウザを使ってください。
    </canvas>
canvasを使用するための呪文
    canvas = document.getElementById('mycanvas');
    if(!canvas || !canvas.getContext) return false;
    ctx = canvas.getContext('2d');
enemyオブジェクトを作成
Enemy = function(x, y, row){
    this.x = x; //x座標
    this.y = y; //y座標
    this.r = 15; //辺の長さ
    this.row = row; //行目
    this.color = "#FF6060"; //色
};
enemy描画メソッド
Enemy.prototype.draw = function(){
    ctx.fillStyle = this.color;
    ctx.fillRect(this.x, this.y, this.r, this.r); //箱を描画
};
enemy生成関数

横にenemyを10体を3列生成します

    function formEnemy(){
        var x = 0, y = 0;
        for(var row = 0;row < 3;row++){ //行ループ
            for(var num = 0;num < 10;num++){
                x = 30 * num + 50; //x軸
                y = (15 * row + 20) + (row * 10); //y軸 同じ行のenemyのy軸は統一
                enemys.push(new Enemy(x, y, row)); //配列で管理
            }
        }
    }

ここまでのコードでenemyの表示までできました。
enemys配列で全てのenemyを格納しています。
行の違いはプロパティで持っています。(enemys.row)


次はこのenemyを動かします。

2、enemyを動かす

今回のプログラムで必要な変数定義
var Stage, stage;
var directionFlag = "RIGHT";
var flagY = false;
var ENDFLAG = false;
var maxRow = 2;

Stageでシューティングゲームの動きを管理します

Stageオブジェクト作成
Stage = function(){
    this.clear = function(){
        ctx.fillStyle = "#ecf0f1"; //背景色と同じ色
        ctx.fillRect(0, 0, canvas.width, canvas.height); //canvas全体
    };
    this.update = function(){
        this.clear(); //canvasクリア
        enemys.forEach(function(value, index){
            value.direct(value); //directメソッド(x軸を動かす)
            value.moveY(value, index); //moveYメソッド(y軸を動かす)
            value.flagJudge(value, index); //flagJudgeメソッド(x軸の方向 右か左か)
            value.draw(); //描画
        });
        setTimeout(function(){
            this.update(); //Stageオブジェクトのupdateメソッドを500ms後に実行する
        }.bind(this), 500); //thisをStageに
    };
};

updateメソッドを繰り返してゲームを進行します

・各メソッド
directメソッド
Enemy.prototype.direct = function(value){
    value.rowCheck(value, index); //いま何行あるかチェック
    if(directionFlag == "RIGHT"){ //右方向
        value.x += 10;
    }else if(directionFlag == "LEFT"){ //左方向
        value.x -= 10;   
    }
};
rowCheckメソッド(行判定)
Enemy.prototype.rowCheck = function(value, index){
    if(index == enemys.length - 1){
        maxRow = value.row;
    }
};
moveYメソッド
Enemy.prototype.moveY = function(value, index){
    if(flagY == true){
        value.y += 10;
        if(index == enemys.length - 1)){
            flagY = false;
        }
    }
};
flagJudgeメソッド
Enemy.prototype.flagJudge = function(value, index){
    if(value.x >= 450 && value.row == maxRow){  //x軸が450以上になったら左に
        directionFlag = "LEFT"; //flagを左に
        flagY = true; //左に動く前にy軸を動かす
    }
    if((value.x <= 30 && value.row == maxRow) || ENDFLAG == true){ //x軸が30以下になったら右に
        ENDFLAG = true; //enemyを全部チェックするための変数
        if(ENDFLAG == true && index == enemys.length - 1){
            directionFlag = "RIGHT"; //flagを右に
            flagY = true; //右に動く前にy軸を動かす
            ENDFLAG = false; //enemyを全てチェック
        }
    }
};

これでenemyを動かせます
次はコードを組み合わせます

3、コードを組み合わせる

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>enemySystem</title>
</head>
<body>
    <canvas id="mycanvas" width="500" height="500">
        Canvasに対応したブラウザを使ってください。
    </canvas>
    <script>
        (function(){
            'use strict';
            var canvas, ctx;
            var Enemy, enemys = [];
            var Stage, stage;
            var directionFlag = "RIGHT";
            var flagY = false;
            var ENDFLAG = false;
            var maxRow = 2;
            
            canvas = document.getElementById('mycanvas');
            if(!canvas || !canvas.getContext) return false;
            ctx = canvas.getContext('2d');
            
            Enemy = function(x, y, row){
                this.x = x;
                this.y = y;
                this.r = 15;
                this.row = row;
                this.color = "#FF6060";
            };
            Enemy.prototype.draw = function(){
                ctx.fillStyle = this.color;
                ctx.fillRect(this.x, this.y, this.r, this.r);
            };
            Enemy.prototype.direct = function(value){
                if(directionFlag == "RIGHT"){
                    value.x += 10;
                }else if(directionFlag == "LEFT"){
                    value.x -= 10;   
                }
            };
            Enemy.prototype.moveY = function(value, index){
                if(flagY == true){
                    value.y += 10;
                    if(index == enemys.length - 1){
                        flagY = false;
                    }
                }
            };
            Enemy.prototype.flagJudge = function(value, index){
                if(value.x >= 450 && value.row == 2){
                    directionFlag = "LEFT";
                    flagY = true;
                }
                if((value.x <= 30 && value.row == 2) || ENDFLAG == true){
                    ENDFLAG = true;
                    if(ENDFLAG == true && index == enemys.length - 1){
                        directionFlag = "RIGHT";
                        flagY = true;
                        ENDFLAG = false;
                    }
                }
            };
            //行判定
            Enemy.prototype.rowCheck = function(value, index){
                if(index == enemys.length - 1){
                    maxRow = value.row;
                }
            }
            function formEnemy(){
                var x = 0, y = 0;
                for(var row = 0;row < 3;row++){
                    for(var num = 0; num < 10;num++){
                        x = 30 * num + 50;
                        y = (15 * row + 20) + (row * 10);
                        enemys.push(new Enemy(x, y, row));
                    }
                }
            }
            Stage = function(){
                this.clear = function(){
                    ctx.fillStyle = "#ecf0f1";
                    ctx.fillRect(0, 0, canvas.width, canvas.height);
                };
                this.update = function(){
                    this.clear();
                    enemys.forEach(function(value, index){
                        value.direct(value);
                        value.moveY(value, index);
                        value.flagJudge(value, index);
                        value.draw();
                    });
                    setTimeout(function(){
                        this.update();
                    }.bind(this), 500);
                };
            };
            formEnemy();
            stage = new Stage();
            stage.update();
        })();
    </script>
</body>
</html>

簡単にですがこのコードでenemyを動かすことができました。
シューティングゲーム作り方などで検索しないで、自分で全部考えて書きました。
まだ日本語から書かないとうまく作れないですが、自分の成長がわかり嬉しいです!

多分シューティングゲームのオーソドックスな書き方とかあると思いますが、それは調べずに我流でのコードです。
なのであまり参考にならないかもしれません。

enemy以外の機能も簡単にはできたので、またこのブログに書きたいと思います!

追記:
プレイヤー機を動かすプログラムのブログ書きました!!
hiroki-prog.hatenablog.com