어떻게 VUE 와 Canvas 로 뇌 정전 기 타자 게임 을 실현 합 니까?

25264 단어 VUECanvas게임.
오늘 은 뇌 정 전투기 타자 게임 을 실현 합 니 다.게임 방법 은 매우 간단 합 니 다.모든'적'은 영어 단어 입 니 다.키보드 가 단어의 자 모 를 정확하게 치면 비행 기 는 총알 을 하나씩 발사 하여'적'을 소멸 합 니 다.매번 현재 의'적'을 사살 해 야 다음 을 죽 일 수 있 습 니 다.손 속도 와 단어 숙련 도 를 비교 하 는 게임 입 니 다.
우선 최종 효과 도 를 살 펴 보 자.

emmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
먼저 인터페이스 구성 을 분석 하 러 왔 습 니 다.
(1)화면 밑 에 고정된 비행기;
(2)화면 위 에서 무 작위 로 발생 하 는 적(단어);
(3)비행기 머리 에서 발사 하여 적 을 향 해 달 려 가 는 총알;
(4)게임 종료 후 점수 표시.
이번 게임 은 이전 보다 운동 부분 이 더 많 고 복잡 해 보 였 다.flappy bird 에서 파 이 프 는 운동 적 이지 만 작은 새 의 x 좌표 와 파이프 의 간격,너 비 는 변 하지 않 고 경 계 를 계산 하기 쉽다.공 을 튕 기 고 벽돌 을 없 애 는 게임 에서 널빤지 와 벽돌 은 상대 적 으로 간단 하거나 고정된 좌표 로 공의 경계 와 벽돌의 접촉 면적 만 판정 하면 된다.뇌 정 전투기 단어 제거 게임 에 서 는 착륙 하 는 목표 단어 든 날 아 가 는 총알 이 든 각자 의 운동 궤적 을 가지 고 있 지만 총알 은 목 표를 찾 아 가 야 하기 때문에 실시 간 으로 궤 도 를 계산 하 는 조작 이 존재 한다.
만 장의 고 층 건물 평지 부터 그렇게 많은 말 을 했 으 니 가장 간단 한 것 부터 시작 하 자!
1.화면 아래 중간 에 고정 되 어 있 는 비행기
이것 은 매우 간단 해서 할 말 이 없다.여 기 는 비행기의 너비 와 높이 가 40 픽 셀 단위 인 것 을 기본 으로 하고 비행 기 를 화면의 밑부분 중간 에 그린다.

drawPlane() {
      let _this = this;
      _this.ctx.save();
      _this.ctx.drawImage(
        _this.planeImg,
        _this.clientWidth / 2 - 20,
        _this.clientHeight - 20 - 40,
        40,
        40
      );
      _this.ctx.restore();
},
2.화면 위 에서 무 작위 로 발생 하 는 적
여기 서 기본 설정 은 화면 에 최대 3 개의 단어 표적 만 나타 나 고 과녁 의 y 축 이동 속 도 는 1.3 이 며 과녁 의 반지름 크기 는 10 이다.

const _MAX_TARGET = 3; //             

const _TARGET_CONFIG = {
  //        

  speed: 1.3,

  radius: 10

};
그리고 우 리 는 처음부터 무 작위 로 어고 배열 에서 꺼 내야 한다MAX_TARGET 는 반복 되 지 않 는 단 어 를 사용 하고 나머지 단 어 를 순환 어고 this.words Pool 에 넣 습 니 다.

generateWord(number) {
      //            ,         
      let arr = [];
      for (let i = 0; i < number; i++) {
        let random = Math.floor(Math.random() * this.wordsPool.length);
        arr.push(this.wordsPool[random]);
        this.wordsPool.splice(random, 1);
      }
      return arr;
},
generateTarget() {
      //       
      let _this = this;
      let length = _this.targetArr.length;
      if (length < _MAX_TARGET) {
        let txtArr = _this.generateWord(_MAX_TARGET - length);
        for (let i = 0; i < _MAX_TARGET - length; i++) {
          _this.targetArr.push({
            x: _this.getRandomInt(
              _TARGET_CONFIG.radius,
              _this.clientWidth - _TARGET_CONFIG.radius
            ),
            y: _TARGET_CONFIG.radius * 2,
            txt: txtArr[i],
            typeIndex: -1,
            hitIndex: -1,
            dx: (_TARGET_CONFIG.speed * Math.random().toFixed(1)) / 2,
            dy: _TARGET_CONFIG.speed * Math.random().toFixed(1),
            rotate: 0
          });
        }
      }
}
this.targetArr 는 대상 을 저장 하 는 배열 임 을 알 수 있 습 니 다.
초기 목 표 는 화면 너비 에 무 작위 로 분포 되 어 있 는 x 가 있 습 니 다.
y 축 값 은 지름;
txt 는 과녁 이 대표 하 는 단 어 를 기록 합 니 다.
typeIndex 는'폭격'이라는 단 어 를 기록 할 때 두 드 리 고 있 는 문자 인덱스 아래 표 시 를 기록 합 니 다.(두 드 리 지 않 은 문자 와 두 드 리 지 않 은 문 자 를 분리 하 는 데 사 용 됩 니 다.)
hitIndex 가'폭격'이라는 단 어 를 기록 할 때 총알 폭격 의 색인 아래 표 시 됩 니 다.(총알 이 진정 으로 목 표를 폭격 한 것 은 단 어 를 다 친 후에 총알 이 비행 시간 이 있 기 때문에 hitIndex 를 통 해 총알 이 언제 깨 져 사 라 졌 는 지 판단 합 니 다)
dx 는 과녁 의 각 프레임 이 x 축 에서 이동 하 는 거리 이다.
dy 는 과녁 의 각 프레임 이 y 축 에서 이동 하 는 거리 이다.
rotate 는 과녁 의 자전 각 도 를 설정 합 니 다.
자,세 개의 표적 이 생 성 되 었 으 니,우 리 는 과녁 을 먼저 위 에서 아래로 움 직 이게 합 시다.

drawTarget() {
      //      
      let _this = this;
      _this.targetArr.forEach((item, index) => {
        _this.ctx.save();
        _this.ctx.translate(item.x, item.y); //        
        _this.ctx.beginPath();
        _this.ctx.font = "14px Arial";
        if (
          index === _this.currentIndex ||
          item.typeIndex === item.txt.length - 1
        ) {
          _this.drawText(
            item.txt.substring(0, item.typeIndex + 1),
            -item.txt.length * 3,
            _TARGET_CONFIG.radius * 2,
            "gray"
          );
          let width = _this.ctx.measureText(
            item.txt.substring(0, item.typeIndex + 1)
          ).width; //          
          _this.drawText(
            item.txt.substring(item.typeIndex + 1, item.txt.length),
            -item.txt.length * 3 + width,
            _TARGET_CONFIG.radius * 2,
            "red"
          );
        } else {
          _this.drawText(
            item.txt,
            -item.txt.length * 3,
            _TARGET_CONFIG.radius * 2,
            "yellow"
          );
        }
 
        _this.ctx.closePath();
        _this.ctx.rotate((item.rotate * Math.PI) / 180);
        _this.ctx.drawImage(
          _this.targetImg,
          -1 * _TARGET_CONFIG.radius,
          -1 * _TARGET_CONFIG.radius,
          _TARGET_CONFIG.radius * 2,
          _TARGET_CONFIG.radius * 2
        );
        _this.ctx.restore();
        item.y += item.dy;
        item.x += item.dx;
        if (item.x < 0 || item.x > _this.clientWidth) {
          item.dx *= -1;
        }
        if (item.y > _this.clientHeight - _TARGET_CONFIG.radius * 2) {
          //      
          _this.gameOver = true;
        }
        //   
        item.rotate++;
      });
}
이 단 계 는 과녁 을 그 리 는 데 특별한 것 이 없 으 며,무 작위 로 dx 와 dy 를 증가 시 켜 좌우 가장자리 에 부 딪 혔 을 때 튕 겨 야 한다.중요 한 것 은 단어의 그리 기 입 니 다.type:Index 를 통 해 단 어 를 둘 로 나 누고 두 드 린 문 자 를 회색 으로 설정 한 다음 measuretext 를 통 해 두 드 리 지 않 은 문자 의 폭 을 가 져 와 두 드 리 지 않 은 문자 의 x 축 오프셋 을 설정 하고 두 드 리 지 않 은 문 자 를 빨간색 으로 설정 합 니 다.이 단 어 는 공격 중인 목표 임 을 알려 줍 니 다.
3.비행기 머리 에서 발사 하여 적 을 향 해 달 려 가 는 총알
총알 은 이 게임 의 관건 적 인 부분 인 데 총알 을 그 릴 때 어떤 부분 을 고려 해 야 합 니까?
(1)목 표 는 항상 운동 을 하고 발사 한 총알 은 목 표를 계속 추적 해 야 하기 때문에 경 로 는 동태 적 으로 변화 한다.
(2)한 목 표 는 몇 개의 총알 에 의 해 소멸 되 어야 하기 때문에 언제 총알 이 화면 에서 지 워 집 니까?
(3)목표 단어 가 두 드 려 진 후에 다음 총알 은 다음 목 표를 향 해 사격 해 야 하기 때문에 총알 의 경 로 는 단독 이다.
(4)총알 의 끌 림 효 과 를 어떻게 그립 니까?
(5)두 드 리 고 있 는 대상 단 어 를 잠 그 면 유저 가 현재 단 어 를 다 두 드 려 야 다음 단 어 를 격파 할 수 있 습 니 다.
여기에 먼저 몇 개의 변 수 를 설정 합 니 다.
bulletArr:[],//총알 저장 대상
currentIndex: -1  //현재 잠 겨 있 는 대상 이 targetArr 에 있 는 색인
우선 키보드 가 눌 렀 을 때 터치 할 함 수 를 적어 보 겠 습 니 다.

handleKeyPress(key) {
      //     ,      
      let _this = this;
      if (_this.currentIndex === -1) {
        //           
        let index = _this.targetArr.findIndex(item => {
          return item.txt.indexOf(key) === 0;
        });
        if (index !== -1) {
          _this.currentIndex = index;
          _this.targetArr[index].typeIndex = 0;
          _this.createBullet(index);
        }
      } else {
        //          
        if (
          key ===
          _this.targetArr[_this.currentIndex].txt.split("")[
            _this.targetArr[_this.currentIndex].typeIndex + 1
          ]
        ) {
          //        
          _this.targetArr[_this.currentIndex].typeIndex++;
          _this.createBullet(_this.currentIndex);
 
          if (
            _this.targetArr[_this.currentIndex].typeIndex ===
            _this.targetArr[_this.currentIndex].txt.length - 1
          ) {
            //            
            _this.currentIndex = -1;
          }
        }
      }
},
//       
    createBullet(index) {
      let _this = this;
      this.bulletArr.push({
        dx: 1,
        dy: 4,
        x: _this.clientWidth / 2,
        y: _this.clientHeight - 60,
        targetIndex: index
      });
}
이 함수 가 하 는 일 은 매우 명확 합 니 다.현재 키보드 가 누 른 문 자 를 가 져 옵 니 다.currentIndex==-1 이 공격 당 하고 있 는 표적 이 없다 는 것 을 증명 하기 때문에 과녁 배열 에 가서 보 세 요.어떤 단어의 이니셜 이 이 문자 와 같 으 면 currentIndex 를 이 단어의 색인 으로 설정 하고 총알 을 발사 합 니 다.공격 당 하고 있 는 표적 이 있다 면 아직 두 드 리 지 않 은 단어의 첫 번 째 문자 가 맞 는 지,맞 으 면 이 표적 대상 의 type:Index 를 추가 하고 총알 을 발사 합 니 다.현재 표적 이 두 드 렸 다 면 currentIndex 를-1 로 초기 화 합 니 다.
다음은 총알 을 그 리 는 거 야.

drawBullet() {
      //      
      let _this = this;
      //             
      if (_this.bulletArr.length === 0) {
        return;
      }
      _this.bulletArr = _this.bulletArr.filter(_this.firedTarget);
      _this.bulletArr.forEach(item => {
        let targetX = _this.targetArr[item.targetIndex].x;
        let targetY = _this.targetArr[item.targetIndex].y;
        let k =
          (_this.clientHeight - 60 - targetY) /
          (_this.clientWidth / 2 - targetX); //          
        let b = targetY - k * targetX; //   b
        item.y = item.y - bullet.dy; // y       
        item.x = (item.y - b) / k;
        for (let i = 0; i < 15; i++) {
          //       
          _this.ctx.beginPath();
          _this.ctx.arc(
            (item.y + i * 1.8 - b) / k,
            item.y + i * 1.8,
            4 - 0.2 * i,
            0,
            2 * Math.PI
          );
          _this.ctx.fillStyle = `rgba(193,255,255,${1 - 0.08 * i})`;
          _this.ctx.fill();
          _this.ctx.closePath();
        }
      });
},
firedTarget(item) {
      //         
      let _this = this;
      if (
        item.x > _this.targetArr[item.targetIndex].x - _TARGET_CONFIG.radius &&
        item.x < _this.targetArr[item.targetIndex].x + _TARGET_CONFIG.radius &&
        item.y > _this.targetArr[item.targetIndex].y - _TARGET_CONFIG.radius &&
        item.y < _this.targetArr[item.targetIndex].y + _TARGET_CONFIG.radius
      ) {
        //        
        let arrIndex = item.targetIndex;
        _this.targetArr[arrIndex].hitIndex++;
        if (
          _this.targetArr[arrIndex].txt.length - 1 ===
          _this.targetArr[arrIndex].hitIndex
        ) {
          //            
          let word = _this.targetArr[arrIndex].txt;
          _this.targetArr[arrIndex] = {
            //       
            x: _this.getRandomInt(
              _TARGET_CONFIG.radius,
              _this.clientWidth - _TARGET_CONFIG.radius
            ),
            y: _TARGET_CONFIG.radius * 2,
            txt: _this.generateWord(1)[0],
            typeIndex: -1,
            hitIndex: -1,
            dx: (_TARGET_CONFIG.speed * Math.random().toFixed(1)) / 2,
            dy: _TARGET_CONFIG.speed * Math.random().toFixed(1),
            rotate: 0
          };
          _this.wordsPool.push(word); //             
          _this.score++;
        }
        return false;
      } else {
        return true;
      }
}
사실은 간단 하 다.우 리 는 총알 대상 에서 targetIndex 로 이 총알 이 공격 하 는 목표 색인 을 기록 한 다음 에 Y=kx+b 의 방정식 을 풀 어 비행기 머리(총알 출발점)와 과녁 의 궤도 함 수 를 얻어 각 프레임 에 있 는 모든 총알 의 이동 좌 표를 계산 하면 총알 을 그 릴 수 있다.
끌 림 효 과 는 궤도 y 축의 성장 방향 에 따라 약간의 투명도 와 반경 이 점점 작 아 지 는 원 을 그리 면 끌 림 효 과 를 실현 할 수 있다.
fired Target()함수 에 서 는 과녁 에 맞 은 총알 을 걸 러 내 는 데 사 용 됩 니 다.공격 당 하고 있 는 다른 표적 이 targetArr 에 있 는 색인 에 영향 을 주지 않 기 위해 splice 를 삭제 하지 않 고 소 멸 된 표적 의 값 을 직접 리 셋 합 니 다.wordpool 에서 새로운 단 어 를 선택 하고 현재 깨 진 단 어 를 다시 연못 에 던 져 화면 에 중복 되 는 표적 이 나타 나 지 않도록 합 니 다.

4.게임 종료 후 점수 문자 효과
게임 이 끝 난 것 은 목표 표적 이 바닥 에 닿 으 면 끝 나 는 것 이다.
여 기 는 사실 달걀 입 니 다.어떻게 canvas 로 이런 반 짝 이 고 빛 나 는 문 자 를 그 릴 수 있 습 니까?색상 을 바 꾸 고 buff 를 접 으 면 됩 니 다.아 닙 니 다.윤곽 stroke 를 접 으 면 됩 니 다.

drawGameOver() {
      let _this = this;
      //          
      _this.ctx.save();
      _this.ctx.font = "34px Arial";
      _this.ctx.strokeStyle = _this.colors[0];
      _this.ctx.lineWidth = 2;
      //  
      _this.ctx.shadowColor = "#FFFFE0";
      let txt = "    ,  :" + _this.score;
      let width = _this.ctx.measureText(txt).width;
      for (let i = 60; i > 3; i -= 2) {
        _this.ctx.shadowBlur = i;
        _this.ctx.strokeText(txt, _this.clientWidth / 2 - width / 2, 300);
      }
      _this.ctx.restore();
      _this.colors.reverse();
}
자,됐 습 니 다.여기까지 만 하면 완전한 게임 입 니 다.UI 가 약간 거 칠 어 보일 뿐 입 니 다.진짜 뇌 정 전투기 가 폭발 적 인 효 과 를 내 려 면 많은 소재 와 canvas 의 그림 이 필요 합 니 다.
canvas 는 강하 고 재 미 있 습 니 다.뇌 구멍 만 크 면 이 캔버스 에 원 하 는 것 을 그 릴 수 있 습 니 다~
오래된 규칙,po 상 vue 의 전체 코드 는 여러분 이 참고 하여 공부 할 수 있 도록 제공 합 니 다.

<template>
  <div class="type-game">
    <canvas id="type" width="400" height="600"></canvas>
  </div>
</template>
 
<script>
const _MAX_TARGET = 3; //             
const _TARGET_CONFIG = {
  //        
  speed: 1.3,
  radius: 10
};
const _DICTIONARY = ["apple", "orange", "blue", "green", "red", "current"];
export default {
  name: "TypeGame",
  data() {
    return {
      ctx: null,
      clientWidth: 0,
      clientHeight: 0,
      bulletArr: [], //       
      targetArr: [], //       
      targetImg: null,
      planeImg: null,
      currentIndex: -1,
      wordsPool: [],
      score: 0,
      gameOver: false,
      colors: ["#FFFF00", "#FF6666"]
    };
  },
  mounted() {
    let _this = this;
    _this.wordsPool = _DICTIONARY.concat([]);
    let container = document.getElementById("type");
    _this.clientWidth = container.width;
    _this.clientHeight = container.height;
    _this.ctx = container.getContext("2d");
    _this.targetImg = new Image();
    _this.targetImg.src = require("@/assets/img/target.png");
 
    _this.planeImg = new Image();
    _this.planeImg.src = require("@/assets/img/plane.png");
 
    document.onkeydown = function(e) {
      let key = window.event.keyCode;
      if (key >= 65 && key <= 90) {
        _this.handleKeyPress(String.fromCharCode(key).toLowerCase());
      }
    };
 
    _this.targetImg.onload = function() {
      _this.generateTarget();
      (function animloop() {
        if (!_this.gameOver) {
          _this.drawAll();
        } else {
          _this.drawGameOver();
        }
        window.requestAnimationFrame(animloop);
      })();
    };
  },
  methods: {
    drawGameOver() {
      let _this = this;
      //          
      _this.ctx.save();
      _this.ctx.font = "34px Arial";
      _this.ctx.strokeStyle = _this.colors[0];
      _this.ctx.lineWidth = 2;
      //  
      _this.ctx.shadowColor = "#FFFFE0";
      let txt = "    ,  :" + _this.score;
      let width = _this.ctx.measureText(txt).width;
      for (let i = 60; i > 3; i -= 2) {
        _this.ctx.shadowBlur = i;
        _this.ctx.strokeText(txt, _this.clientWidth / 2 - width / 2, 300);
      }
      _this.ctx.restore();
      _this.colors.reverse();
    },
    drawAll() {
      let _this = this;
      _this.ctx.clearRect(0, 0, _this.clientWidth, _this.clientHeight);
      _this.drawPlane(0);
      _this.drawBullet();
      _this.drawTarget();
      _this.drawScore();
    },
    drawPlane() {
      let _this = this;
      _this.ctx.save();
      _this.ctx.drawImage(
        _this.planeImg,
        _this.clientWidth / 2 - 20,
        _this.clientHeight - 20 - 40,
        40,
        40
      );
      _this.ctx.restore();
    },
    generateWord(number) {
      //            ,         
      let arr = [];
      for (let i = 0; i < number; i++) {
        let random = Math.floor(Math.random() * this.wordsPool.length);
        arr.push(this.wordsPool[random]);
        this.wordsPool.splice(random, 1);
      }
      return arr;
    },
    generateTarget() {
      //       
      let _this = this;
      let length = _this.targetArr.length;
      if (length < _MAX_TARGET) {
        let txtArr = _this.generateWord(_MAX_TARGET - length);
        for (let i = 0; i < _MAX_TARGET - length; i++) {
          _this.targetArr.push({
            x: _this.getRandomInt(
              _TARGET_CONFIG.radius,
              _this.clientWidth - _TARGET_CONFIG.radius
            ),
            y: _TARGET_CONFIG.radius * 2,
            txt: txtArr[i],
            typeIndex: -1,
            hitIndex: -1,
            dx: (_TARGET_CONFIG.speed * Math.random().toFixed(1)) / 2,
            dy: _TARGET_CONFIG.speed * Math.random().toFixed(1),
            rotate: 0
          });
        }
      }
    },
    getRandomInt(n, m) {
      return Math.floor(Math.random() * (m - n + 1)) + n;
    },
    drawText(txt, x, y, color) {
      let _this = this;
      _this.ctx.fillStyle = color;
      _this.ctx.fillText(txt, x, y);
    },
    drawScore() {
      //   
      this.drawText("  :" + this.score, 10, this.clientHeight - 10, "#fff");
    },
    drawTarget() {
      //      
      let _this = this;
      _this.targetArr.forEach((item, index) => {
        _this.ctx.save();
        _this.ctx.translate(item.x, item.y); //        
        _this.ctx.beginPath();
        _this.ctx.font = "14px Arial";
        if (
          index === _this.currentIndex ||
          item.typeIndex === item.txt.length - 1
        ) {
          _this.drawText(
            item.txt.substring(0, item.typeIndex + 1),
            -item.txt.length * 3,
            _TARGET_CONFIG.radius * 2,
            "gray"
          );
          let width = _this.ctx.measureText(
            item.txt.substring(0, item.typeIndex + 1)
          ).width; //          
          _this.drawText(
            item.txt.substring(item.typeIndex + 1, item.txt.length),
            -item.txt.length * 3 + width,
            _TARGET_CONFIG.radius * 2,
            "red"
          );
        } else {
          _this.drawText(
            item.txt,
            -item.txt.length * 3,
            _TARGET_CONFIG.radius * 2,
            "yellow"
          );
        }
 
        _this.ctx.closePath();
        _this.ctx.rotate((item.rotate * Math.PI) / 180);
        _this.ctx.drawImage(
          _this.targetImg,
          -1 * _TARGET_CONFIG.radius,
          -1 * _TARGET_CONFIG.radius,
          _TARGET_CONFIG.radius * 2,
          _TARGET_CONFIG.radius * 2
        );
        _this.ctx.restore();
        item.y += item.dy;
        item.x += item.dx;
        if (item.x < 0 || item.x > _this.clientWidth) {
          item.dx *= -1;
        }
        if (item.y > _this.clientHeight - _TARGET_CONFIG.radius * 2) {
          //      
          _this.gameOver = true;
        }
        //   
        item.rotate++;
      });
    },
    handleKeyPress(key) {
      //     ,      
      let _this = this;
      if (_this.currentIndex === -1) {
        //           
        let index = _this.targetArr.findIndex(item => {
          return item.txt.indexOf(key) === 0;
        });
        if (index !== -1) {
          _this.currentIndex = index;
          _this.targetArr[index].typeIndex = 0;
          _this.createBullet(index);
        }
      } else {
        //          
        if (
          key ===
          _this.targetArr[_this.currentIndex].txt.split("")[
            _this.targetArr[_this.currentIndex].typeIndex + 1
          ]
        ) {
          //        
          _this.targetArr[_this.currentIndex].typeIndex++;
          _this.createBullet(_this.currentIndex);
 
          if (
            _this.targetArr[_this.currentIndex].typeIndex ===
            _this.targetArr[_this.currentIndex].txt.length - 1
          ) {
            //            
            _this.currentIndex = -1;
          }
        }
      }
    },
    //       
    createBullet(index) {
      let _this = this;
      this.bulletArr.push({
        dx: 1,
        dy: 4,
        x: _this.clientWidth / 2,
        y: _this.clientHeight - 60,
        targetIndex: index
      });
    },
    firedTarget(item) {
      //         
      let _this = this;
      if (
        item.x > _this.targetArr[item.targetIndex].x - _TARGET_CONFIG.radius &&
        item.x < _this.targetArr[item.targetIndex].x + _TARGET_CONFIG.radius &&
        item.y > _this.targetArr[item.targetIndex].y - _TARGET_CONFIG.radius &&
        item.y < _this.targetArr[item.targetIndex].y + _TARGET_CONFIG.radius
      ) {
        //        
        let arrIndex = item.targetIndex;
        _this.targetArr[arrIndex].hitIndex++;
        if (
          _this.targetArr[arrIndex].txt.length - 1 ===
          _this.targetArr[arrIndex].hitIndex
        ) {
          //            
          let word = _this.targetArr[arrIndex].txt;
          _this.targetArr[arrIndex] = {
            //       
            x: _this.getRandomInt(
              _TARGET_CONFIG.radius,
              _this.clientWidth - _TARGET_CONFIG.radius
            ),
            y: _TARGET_CONFIG.radius * 2,
            txt: _this.generateWord(1)[0],
            typeIndex: -1,
            hitIndex: -1,
            dx: (_TARGET_CONFIG.speed * Math.random().toFixed(1)) / 2,
            dy: _TARGET_CONFIG.speed * Math.random().toFixed(1),
            rotate: 0
          };
          _this.wordsPool.push(word); //             
          _this.score++;
        }
        return false;
      } else {
        return true;
      }
    },
    drawBullet() {
      //      
      let _this = this;
      //             
      if (_this.bulletArr.length === 0) {
        return;
      }
      _this.bulletArr = _this.bulletArr.filter(_this.firedTarget);
      _this.bulletArr.forEach(item => {
        let targetX = _this.targetArr[item.targetIndex].x;
        let targetY = _this.targetArr[item.targetIndex].y;
        let k =
          (_this.clientHeight - 60 - targetY) /
          (_this.clientWidth / 2 - targetX); //          
        let b = targetY - k * targetX; //   b
        item.y = item.y - 4; // y       
        item.x = (item.y - b) / k;
        for (let i = 0; i < 15; i++) {
          //       
          _this.ctx.beginPath();
          _this.ctx.arc(
            (item.y + i * 1.8 - b) / k,
            item.y + i * 1.8,
            4 - 0.2 * i,
            0,
            2 * Math.PI
          );
          _this.ctx.fillStyle = `rgba(193,255,255,${1 - 0.08 * i})`;
          _this.ctx.fill();
          _this.ctx.closePath();
        }
      });
    }
  }
};
</script>
 
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped lang="scss">
.type-game {
  #type {
    background: #2a4546;
  }
}
</style>
이상 은 어떻게 VUE 와 Canvas 로 뇌 정전 기 타자 류 의 작은 게임 을 실현 하 는 지 에 대한 상세 한 내용 입 니 다.더 많은 VUE 뇌 정전 기 작은 게임 에 관 한 자 료 는 우리 의 다른 관련 글 을 주목 하 세 요!

좋은 웹페이지 즐겨찾기