37
33

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

vue.jsで作るぷよぷよ

Last updated at Posted at 2017-02-10

簡易版 デモ

index.jpeg

<!doctype html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>vue.js 落ち物パズルゲーム  ver.2</title>
<style>
   table {background-color:gray;}
   td {width: 30px;height: 30px;border-radius: 15px;}
   .box{display: flex;}
</style>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.0.7/vue.min.js"></script>
</head>
<body>
<div id="app">
   <h3>vue.js 落ち物パズルゲーム ver.2</h3>
   <p>startを押してからキーボードの矢印キーで操作します</p>
   <input type="button" @click="startFn" value="START" v-if="!gameStart">
   <input type="button" @click="restartFn" value="RESTART"  v-if="gameOver">
   <div class="box" v-if="gameStart">
      <table>
           <tr v-for="i in H">
               <td v-for="j in W" :style="{ backgroundColor:colors[yx[i-1][j-1]] }"></td>
           </tr>
      </table>
      <table>
           <tr v-for="i in 2">
               <td :style="{ backgroundColor: colors[next[i - 1]] }"></td>
           </tr>
      </table>
   </div>
</div>
<script>
var vm = new Vue({
   el: '#app',
   data: {
      H: 13,
      W: 6,
      yx: [],
      block: [],
      blockX: 0,
      blockY: 0,
      blockMemo: [],
      blockColor: [],
      next : [Math.floor(Math.random() * 5) + 1, Math.floor(Math.random() * 5) + 1],
      timerID: null,
      otitaFlag:false,
      gameStart: false,
      gameOver: false,
      colors: ['gray', 'red', 'blue', 'green', 'yellow', 'purple'],
      saveData : null,
   },
   methods: {
      startFn: function() {
         this.saveData = JSON.stringify(this.$data);
         for (var i = 0; i < this.H; i++) {
            this.yx[i] = [];
            for (var j = 0; j < this.W; j++) this.yx[i][j] = 0;
         }
         this.gameStart = true;
         this.createFn();
         this.timerID = setInterval(this.fallFn, 500);
      },
      createFn: function() {
         this.blockMemo = [];
         this.blockX = 2;
         this.blockY = 1;
         this.block = [[0, 0], [0, -1]];
         this.blockColor = [this.next[1], this.next[0]];
         this.next = [Math.floor(Math.random() * 5) + 1, Math.floor(Math.random() * 5) + 1];
         this.drawFn(false, 0, 0);
      },
      fallFn: function() {
         if (this.isMoveFn(false, 0, 1)) this.drawFn(false, 0, 1);
         else {
            this.otitaFlag = true;
            clearInterval(this.timerID);
            this.timerID = setInterval(this.rensaFn, 200);
         }
      },
      isMoveFn: function(rotate, dx, dy) {
         var yx = this.yx.map(v => v.slice());
         var block = this.block.map(v => v.slice());
         this.blockMemo.forEach(v => {
            yx[v[1]][v[0]] = 0;
         });
         if (rotate) block = block.map(v => [v[1] * -1, v[0]]);
         var flag = block.every(v => {
            var x = v[0] + this.blockX + dx;
            var y = v[1] + this.blockY + dy;
            return (y >= 0 && y < this.H && x >= 0 && x < this.W && yx[y][x] == 0);
         });
         return flag;
      },
      drawFn: function(rotate, dx, dy) {
         this.blockMemo.forEach(v => {
            this.yx[v[1]][v[0]] = 0;
         });
         this.blockMemo = [];
         if (rotate) this.block = this.block.map(v => [v[1] * -1, v[0]]);
         this.blockX += dx;
         this.blockY += dy;
         this.block.forEach((v, i) => {
            var x = v[0] + this.blockX;
            var y = v[1] + this.blockY;
            if (this.yx[y][x] != 0) this.gameOver = true;
            this.yx[y][x] = this.blockColor[i];
            this.blockMemo.push([x, y]);
         });
         if (this.gameOver) clearInterval(this.timerID);
         this.$forceUpdate();
      },
      rensaFn:function(){
         if (this.kuzureruFn() || this.removeFn()) this.$forceUpdate();
         else {
            clearInterval(this.timerID);
             this.timerID = setInterval(this.fallFn, 500);
             this.createFn();
             this.otitaFlag = false;
         }
      },
      kuzureruFn: function() {
         var flag= false;
            for (var i = this.H - 2; i >= 0; i--) for (var j = 0; j < this.W; j++) {
               if (this.yx[i + 1][j] == 0 && this.yx[i][j] != 0) {
                  this.yx[i + 1][j] = this.yx[i][j];
                  this.yx[i][j] = 0;
                  flag = true;
               }
            }
         return flag;
      },
      removeFn: function() {
         var flag = false;
         var dydx = [[-1, 0], [0, 1], [1, 0], [0, -1]];
         for (var i = 0; i < this.H; i++) for (var j = 0; j < this.W; j++) {
            var iro = this.yx[i][j];
            if (iro == 0) continue;
            var yx = this.yx.map(v => v.slice());
            yx[i][j] = 0;
            var onazi = 1;
            var memo = [[i, j]];
            while (memo.length != 0) {
               var m = memo.shift();
               dydx.forEach(v => {
                  var y = m[0] + v[0];
                  var x = m[1] + v[1];
                  if (y >= 0 && y < this.H && x >= 0 && x < this.W && yx[y][x] == iro) {
                     onazi++;
                     memo.push([y, x]);
                     yx[y][x] = 0;
                  }
               });
            }
            if (onazi >= 4) {
               flag = true;
               this.yx = yx.map(v => v.slice());
            }
         }
         return  flag;
      },
      keydownFn: function(rotate, dx, dy) {
         if (!this.gameOver && !this.otitaFlag && this.isMoveFn(rotate, dx, dy)) this.drawFn(rotate, dx, dy);
      },
      restartFn: function() {
         var obj = JSON.parse(this.saveData);
         for (var k in obj) this[k] = obj[k];
         this.startFn();
      },
   }
});

document.onkeydown = function(e) {
   if (e.keyCode == 38) vm.keydownFn(true, 0, 0); //up
   else if (e.keyCode == 37) vm.keydownFn(false, -1, 0); //left
   else if (e.keyCode == 40) vm.keydownFn(false, 0, 1); //down
   else if (e.keyCode == 39) vm.keydownFn(false, 1, 0); //right
};
</script>
</body>
</html>

CSS3 ぷよぷよ

<!doctype html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>CSS3 ぷよぷよ</title>
<style>
.box {
   width: 50px;
   height: 50px;
   animation: bounce 1.0s infinite ease-in-out;
   box-shadow: 5px 5px 15px 5px rgba(0,0,0,0.6) inset;
   font-size: 15px;
   color:white;
   font-weight: bold; 
   text-align: center; 
}
@keyframes bounce {
  0%, 100% { transform: scale(0.9) }
  50% { transform: scale(1.0) }
}
.red {background-color:red;border-radius: 20px;}
.blue {background-color:blue;border-radius: 10px 20px 10px 25px / 10px 30px 10px 40px;}
.green {background-color:green;border-radius: 20px;}
.yellow {background-color:yellow;border-radius: 25px 25px 10px 10px / 50px 50px 10px 10px;}
.purple {background-color:purple;border-radius: 20px;}
</style>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.0.7/vue.min.js"></script>
</head>
<body>
   <div id="app">
      <div v-for="i in 5" :class="['box', arr[i-1]]">0_0</div>
   </div>
<script>
   var vm = new Vue({
      el: '#app',
      data: {
         arr : ["red","blue","green","yellow","purple"]
      }
   });
</script>
</body>
</html>
37
33
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
37
33

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?