# kill-virus-origin
**Repository Path**: dyree/kill-virus-origin
## Basic Information
- **Project Name**: kill-virus-origin
- **Description**: 使用JavaScript DOM API开发的打字游戏。该项目是一个教学项目,非常适合前端初学者学习。
- **Primary Language**: Unknown
- **License**: MIT
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 1
- **Created**: 2024-10-31
- **Last Updated**: 2024-10-31
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# kill virus 杀死病毒

适配移动端:
## 预览:https://davie.gitee.io/kill-virus-origin/
关注公众号:

# 教程文档:
## 1. 创建项目
* 创建项目文件夹,导入图片资源,使用git初始化仓库
* 创建master分支
* 创建远程仓库,关联远程仓库,并且推送到远程仓库
* 创建dev分支
* 在dev分支上开发
* 合并到master分支
## 2. 创建页面
创建index.html
首页页面结构:
```html
0
屏幕上方有带字母的“病毒”落下,按下键盘对应的按键,消灭病毒,否则,你将被“病毒”消灭😈
```
**【提交git】**
## 3. 页面样式
实现页面的样式代码
```css
* {
padding: 0;
margin: 0;
user-select: none;
}
html,
body {
width: 100%;
height: 100%;
}
body {
overflow: hidden;
background-color: #fff;
}
/* 😈病毒样式 */
.iconfont {
font-size: 80px;
}
.virus {
width: 80px;
height: 80px;
position: absolute;
left: 200px;
top: 200px;
background-image: url(./imgs/virus.png);
background-repeat: no-repeat;
background-size: 100%;
}
.virus .letter {
position: absolute;
width: 60px;
height: 60px;
background-image: radial-gradient(rgba(255, 150, 150, 0), rgba(255, 0, 0, 1));
text-align: center;
color: #fff;
line-height: 60px;
border-radius: 60px;
font-size: 28px;
font-weight: 800;
left: 10px;
top: 10px;
box-shadow: 0 0 15px #f00;
}
/* 舞台样式 */
#stage {
width: 100%;
height: 100%;
margin: 0 auto;
border: solid 1px #333;
position: relative;
overflow: hidden;
background-image: url(./imgs/bg.jpg);
background-repeat: no-repeat;
background-size: 100% 100%;
}
#game {
width: 100%;
height: 100%;
position: absolute;
}
/* ui 样式 */
#ui {
width: 100%;
height: 100%;
position: absolute;
z-index: 10;
}
/* 得分 */
#ui .score-ui {
width: 120px;
height: 40px;
margin-left: 20px;
/* border: solid 1px red; */
line-height: 40px;
border-bottom: solid 2px #40c061;
padding: 5px;
}
#ui .score-ui img {
width: 40px;
height: 40px;
}
#ui .score-ui #score-label {
color: #fff;
font-size: 30px;
position: absolute;
left: 80px;
}
/* 开始页面 */
#ui #start-alert {
width: 100%;
height: 100%;
position: absolute;
z-index: 30;
}
#start-alert .game-desc {
width: 80%;
margin: 100px auto;
text-align: center;
}
#start-alert .game-desc .logo {
width: 300px;
}
#start-alert .game-desc p {
width: 300px;
margin: 0 auto;
font-size: 16px;
font-weight: 300;
line-height: 30px;
color: #fff;
margin-top: 20px;
}
#start-alert footer {
text-align: center;
color: #fff;
}
#start-alert footer #start-btn {
font-size: 36px;
color: #fff;
/* text-shadow: 0 0 10px #fff, 0 0 15 #1bdd4b,0 0 20 #03651c; */
text-shadow: 0 0 1px #fff, 0 0 2px #fff, 0 0 3px #fff, 0 0 4px #B6FF00, 0 0 5px #B6FF00, 0 0 10px #B6FF00, 0 0 14px #B6FF00, 0 0 18px #B6FF00;
}
#start-alert footer p {
margin-top: 100px;
color: aaa;
font-size: 12px;
}
#start-alert footer p::after {
content: '';
display: block;
width: 40px;
height: 40px;
position: absolute;
bottom: 100px;
left: 50%;
margin-left: -20px;
background-image: url(./imgs/virus.png);
background-repeat: no-repeat;
background-size: 100%;
opacity: .7;
}
/* 任务失败页面 */
#game-over-alert {
width: 240px;
height: 80px;
border: solid 1px rgb(85, 255, 227);
border-radius: 10px;
color: #fff;
text-align: center;
position: absolute;
top: 50%;
left: 50%;
margin-left: -120px;
margin-top: -100px;
z-index: 30;
display: none;
/* box-shadow: 0 0 15px rgb(85, 255, 227); */
background-color:rgba(0,0,0,0.3);
}
#game-over-alert h1 {
width: 150px;
margin: 0 auto;
margin-top: -40px;
/* color: rgb(85, 255, 227); */
text-shadow: 0 0 15px rgb(85, 255, 227);
}
#game-over-alert #restart-btn {
font-size: 24px;
margin-top: 20px;
}
/* ⚠️警告页面 */
.warning {
width: 100%;
height: 100%;
position: absolute;
background-image: linear-gradient(to right, rgba(255, 0, 0, .5) 0%, rgba(255, 0, 0, 0) 20%, rgba(0, 0, 0, 0) 80%, rgba(255, 0, 0, .5) 100%);
z-index: 10;
animation: color-fade 0.5s 3;
opacity: 0;
}
/* 警告动画 */
@keyframes color-fade {
0% {
opacity: 0;
}
50% {
opacity: 1;
}
100% {
opacity: 0;
}
}
/* 上滑动画 */
.slide-up {
transform: translateY(-400px);
transition: transform .4s ease-in-out;
}
.slide-down {
transform: translateY(400px);
transition: transform .4s ease-in-out;
}
.fade-out{
opacity: 0;
transition: all 1s;
}
```
**【提交git】**
## 4. 实现游戏开始逻辑
```javascript
let config = {
status: 0, // 0:游戏未开始 1:游戏进行中 2: 游戏结束
speed: 3, //病毒下落速度
interval: 800 //病毒生成时间间隔
}
// 开始页面
let startAlert = document.getElementById('start-alert')
// logo
let gameDesc = document.getElementsByClassName('game-desc')[0];
//footer
let footer = document.getElementsByTagName('footer')[0];
// 点击游戏开始按钮
startAlert.onclick = function () {
startGame()
config.status = 1;
gameDesc.classList.add('slide-up')
footer.classList.add('slide-down')
setTimeout(() => {
startAlert.style.display = 'none';
}, 500);
}
function startGame(){
}
```
**【提交git】**
## 5. 游戏开始函数
```javascript
let timer, updater;
// 开始游戏
function startGame() {
timer = setInterval(function () {
makeVirus()
}, config.interval)
updater = setInterval(function () {
update()
}, 16)
}
//游戏元素层,新生成的病毒添加到这个层中
let game = document.getElementById('game')
//病毒数组,保存新生成的病毒元素
let virues = []
//字母数组,用来生成病毒的值
let letters = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
'T', 'U', 'V', 'W', 'X', 'Y', 'Z'
]
// 制造病毒
function makeVirus() {
let virus = document.createElement('div')
virus.setAttribute('class', 'virus')
let p = document.createElement('p')
p.classList.add('letter')
switch (Math.floor(Math.random() * 6)) {
case 0:
p.style.backgroundImage = 'radial-gradient(rgba(255, 0, 0, 0),rgba(255,0,0,1))';
p.style.boxShadow = '0 0 15px #f00'; break;
case 1:
p.style.backgroundImage = 'radial-gradient(rgba(0, 255, 0, 0),rgba(0,255,0,1))';
p.style.boxShadow = '0 0 15px #f00'; break;
case 2:
p.style.backgroundImage = 'radial-gradient(rgba(0, 0, 255, 0),rgba(0,0,255,1))';
p.style.boxShadow = '0 0 15px #f00'; break;
case 3:
p.style.backgroundImage = 'radial-gradient(rgba(255, 255, 0, 0),rgba(255,255,0,1))';
p.style.boxShadow = '0 0 15px #f00'; break;
case 4:
p.style.backgroundImage = 'radial-gradient(rgba(0, 255, 255, 0),rgba(0,255,255,1))';
p.style.boxShadow = '0 0 15px #f00'; break;
case 5:
p.style.backgroundImage = 'radial-gradient(rgba(255, 0, 255, 0),rgba(255,0,255,1))';
p.style.boxShadow = '0 0 15px #f00'; break;
}
let letter = letters[Math.floor(Math.random() * 26)]
p.innerHTML = letter;
virus.style.left = Math.random() * (stage.offsetWidth - 100) + 'px'
virus.letter = letter;
virus.appendChild(p);
game.appendChild(virus)
virues.push(virus)
}
```
**【提交git】**
## 6. update
病毒运动动画:
```javascript
let winH = stage.offsetHeight;
let uilayer = document.getElementById('ui')
function update() {
for (let i = 0; i < virues.length; i++) {
let virus = virues[i];
virus.style.top = virus.offsetTop + config.speed + 'px';
if (virus.offsetTop >= (winH - 200) && !uilayer.warning) {
showWarning()
uilayer.warning = true
} else if (virus.offsetTop >= winH) {
// 游戏结束
// gameOver()
}
}
}
```
警告
```javascript
// 显示警告
function showWarning(){
let warningLayer = document.createElement('div')
warningLayer.setAttribute('class', 'warning')
uilayer.appendChild(warningLayer)
}
```
**【提交git】**
## 7. 玩家输入
玩家点击键盘字母,如果和场景中病毒的字符相同,则消灭该病毒
```javascript
// audio
let xmEffect = document.getElementById('xm')
let score = 0;
let scoreLabel = document.getElementById('score-label')
// 监听键盘事件,判断玩家是否正确点击病毒上的字母
window.addEventListener('keyup', function (e) {
let key = e.key;
for (let i = 0; i < virues.length; i++) {
let virus = virues[i];
if (virus.letter.toLowerCase() == key.toLowerCase()) {
// 切换病毒图片
let dieImg = document.createElement('img')
game.appendChild(dieImg)
dieImg.src = "./imgs/virus-die.png"
dieImg.style.position = 'absolute';
dieImg.style.left = virus.offsetLeft + 'px'
dieImg.style.top = virus.offsetTop + 'px'
dieImg.classList.add('fade-out')
// 延时一秒钟移除死亡的病毒
setTimeout(function () {
game.removeChild(dieImg)
}, 1000)
// 从病毒层中移除病毒
game.removeChild(virus)
// 从病毒数组中移除
virues.splice(i, 1)
// 更新分数
score++;
scoreLabel.innerHTML = score;
// 播放音效
xmEffect.currentTime = 0;
xmEffect.play()
}
}
})
```
**【提交git】**
## 8. 游戏结束
```javascript
// 游戏失败页面
let gameOverAlert = document.getElementById('game-over-alert')
// 游戏结束
function gameOver() {
clearInterval(timer)
clearInterval(updater)
config.status = 3;
gameOverAlert.style.display = 'block'
}
```
**【提交git】**
## 9. 重新开始
```javascript
// 点击重置游戏按钮
restartBtn.onclick = function () {
gameOverAlert.style.display = 'none'
resetGame()
}
// 重置游戏
function resetGame() {
config.status = 1;
score = 0;
scoreLabel.innerHTML = score;
game.innerHTML = ''
virues = []
uilayer.removeChild(document.querySelector('.warning'))
uilayer.warning = false;
startGame()
}
```