어떻게 VUE 와 Canvas 로 뇌 정전 기 타자 게임 을 실현 합 니까?
우선 최종 효과 도 를 살 펴 보 자.
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 뇌 정전 기 작은 게임 에 관 한 자 료 는 우리 의 다른 관련 글 을 주목 하 세 요!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
VUE 기반 장치가 PC인지 모바일 포트인지 판단실제 개발 과정에서 자주 발생하는 수요는 현재 웹 페이지에 로그인한 장치가 PC인지 이동인지를 판단하고 PC 측과 모바일 측이 서로 다른 웹 내용을 표시하도록 요구하는 것이다. 그러면 현재 로그인 장치에 대한 판단이...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.