首先去官方下载并安装 VSCODE,下载地址 https://code.visualstudio.com/。安装后打开会发现是英文版的,需要去安装插件来汉化。具体是在扩展插件搜索chinese
,选择第一个安装然后重启软件,这样打开就是中文界面了。
去这个网站 https://getbootstrap.com/docs/4.4/examples/album/ 将源代码 Copy 下来,然后打开 VSCODE 选择项目文件夹
在你的项目目录新建个src
文件夹用来存放源代码,并在src
下新建个index.html
文件,将复制的代码拷贝进去
如果想要实时看到页面可以在扩展插件中安装个live server
作为本地服务器
安装后在回到项目文件夹里的index.html
文件,右键选择Open with live server
就可以查看了,但是你会发现样式乱了这时候需要去修改一下代码,将代码第15
行修改成下面的样子
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
保存后再次打开网页就好了
但是你会发现导航按钮好像不能使用这是因为没用正确的引用 js,还需要修改一下代码。替换</body>
前面的三个<script>
标签,替换代码如下:
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
这样保存之后导航菜单就可以使用了。接下来新建一个img
文件夹在src
目录,并放入这张图片
再新建一个style.css
样式文件在src
目录,填入如下内容
#dog, #fox{
position: absolute;
font-size: xx-large;
}
#forest{
background-image: url("./img/forest.jpg");
height: 160px;
}
span.arrow-key {
font-size: xx-large;
cursor: pointer
}
现在正式开始进入 Vue 开发,这是 Vue 的开发文档 https://cn.vuejs.org/v2/guide/。在index.html
的</body>
前面添加
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="custom.js"></script>
代码中 custom.js 文件需要在项目中自己建一个,接下来替换<div class="album py-5 bg-light">
为
<div class="album py-5 bg-light" id="app">
在<div id="forest">...</div>
添加如下内容
<span id="dog" :style="{left: dog.x + 'px', top: dog.y + 'px'}">🐶</span>
顺便把这里修改下
<small class="text-muted">抓捕时间:{{ dog.抓捕时间 }}</small>
文件custom.js
内容如下
var app = new Vue({
el: '#app',
data: {
forest: {
width: $('#forest')[0].offsetWidth,
height: $('#forest')[0].offsetHeight
},
dog: {
width: $('#dog')[0].offsetWidth,
height: $('#dog')[0].offsetHeight,
x: 0,
y: 0,
step: {
x: 10,
y: 2
},
抓捕时间: 0
}
},
methods: {
move_dog(){
this.dog.x += this.dog.step.x
this.dog.y += this.dog.step.y
this.dog.抓捕时间 = Math.round((this.dog.抓捕时间 + 0.1) * 10) / 10
}
},
mounted: function(){
this.timer1 = setInterval(this.move_dog, 100)
},
watch: {
'dog.x': function(){
let x = this.dog.x
let w = this.forest.width
if(x <= 0 || x >= (w - this.dog.width)){
this.dog.step.x = - this.dog.step.x
}
},
'dog.y': function(){
let y = this.dog.y
let h = this.forest.height
if(y <= 0 || y >= (h - this.dog.height)){
this.dog.step.y = - this.dog.step.y
}
}
}
})
保存后预览就会发现狗狗动起来了。接下来实现按键的功能,将操作说明的内容改为
<p class="card-text"> 操作说明: 点击
<span class="arrow-key" @click="change_dog_direct(37)">⬅</span>
<span class="arrow-key" @click="change_dog_direct(39)">➡</span>
<span class="arrow-key" @click="change_dog_direct(38)">⬆</span>
<span class="arrow-key" @click="change_dog_direct(40)">⬇</span> 控制狗狗方向 </p>
然后将js
的内容改成
var app = new Vue({
...
methods: {
...
change_dog_direct(k) {
if (k === 37 && this.dog.step.x > 0 || k === 39 && this.dog.step.x < 0) {
this.dog.step.x = -this.dog.step.x
}
if (k === 38 && this.dog.step.y > 0 || k === 40 && this.dog.step.y < 0) {
this.dog.step.y = -this.dog.step.y
}
},
change_dog_direct_keyboard(event) {
this.change_dog_direct(event.keyCode)
}
},
mounted: function(){
...
window.addEventListener('keyup', this.change_dog_direct_keyboard)
},
...
})
保存后就会发现可以通过键盘或者点击图标来控制狗狗移动了。接下来要在森林中添加狐狸,在狗狗图标下添加
<span id="fox" :class="fox.class" :style="{ left: fox.x + 'px', top: fox.y + 'px'}">🦊</span>
并且添加动画样式文件
<link href="https://cdn.bootcss.com/animate.css/3.7.2/animate.css" rel="stylesheet">
在js
文件定义狐狸对象,并且让狐狸随机移动且“得瑟起来”
var app = new Vue({
...
data: {
...
fox: {
width: $('#fox')[0].offsetWidth,
height: $('#fox')[0].offsetHeight,
x: 0,
y: 100,
class: ''
},
},
methods: {
...
random_fox() {
this.fox.x = Math.ceil(Math.random() * this.forest.width / 2)
this.fox.y = Math.ceil(Math.random() * (this.forest.height - this.fox.height))
this.fox.class = this.fox.class ? '': 'animated jello'
},
},
mounted: function(){
this.timer1 = setInterval(this.move_dog, 100)
this.timer2 = setInterval(this.random_fox, 1000)
window.addEventListener('keyup', this.change_dog_direct_keyboard)
},
...
})
可以看到动画其效果了。那么继续接下来就是如何抓捕狐狸,我们需要在js
文件中添加功能
var app = new Vue({
...
data: {
...
dog: {
...
与狐狸的距离: 999,
抓捕成功: false,
class: ''
},
...
},
methods: {
move_dog(){
if (this.dog.抓捕成功) return
...
this.dog.与狐狸的距离 = getDistanceBetweenTwoPoints(
this.dog.x,
this.dog.y,
this.fox.x,
this.fox.y
)
},
...
bounce_dog() {
if (this.dog.抓捕成功) {
this.dog.class = this.dog.class ? '' : 'animated bounce'
}
},
...
random_fox() {
if (this.dog.抓捕成功) return
...
},
},
mounted: function(){
this.timer1 = setInterval(this.move_dog, 100)
this.timer2 = setInterval(this.random_fox, 1000)
this.timer3 = setInterval(this.bounce_dog, 2000);
window.addEventListener('keyup', this.change_dog_direct_keyboard)
},
watch: {
...
'dog.与狐狸的距离': function(val) {
let min_d = this.dog.width / 2 + this.fox.width / 2
if(val < min_d){
this.dog.抓捕成功 = true
}
},
'dog.抓捕成功': function(val) {
if (val) {
this.fox.class = 'animated rotateOut delay-2s'
} else {
this.fox.class = ''
this.dog.class = ''
}
}
}
})
//计算平面中两点距离
function getDistanceBetweenTwoPoints(x1, y1, x2, y2) {
var a = x1 - x2;
var b = y1 - y2;
// c^2 = a^2 + b^2
// a^2 = Math.pow(a, 2)
// b^2 = Math.pow(b, 2)
var result = Math.sqrt(Math.pow(a, 2) + Math.pow(b, 2));
return Math.round(result);
}
保存刷新一下界面,可以看到当狗狗碰到狐狸的时候会被捕获成功监听器捕获到。接下来开发再来一次功能,把html
代码中的再来一次按钮修改成
<button type="button" :class="btn_play_again.class" @click="play_again" class="btn btn-sm btn-outline-secondary">
<span v-if=" !dog.抓捕成功 ">正在抓捕 。。。</span>
<span v-if=" dog.抓捕成功 "> 抓捕成功!再来一次</span>
</button>
然后是js
文件需要为再来一次添加功能
var app = new Vue({
...
data: {
...
btn_play_again: {
class: ''
}
},
methods: {
...
bounce_dog() {
if (this.dog.抓捕成功) {
this.dog.class = this.dog.class ? '' : 'animated bounce'
this.btn_play_again.class = this.btn_play_again.class ? '' : 'animated swing delay-1s'
}
},
...
play_again() {
if (!this.dog.抓捕成功) return
this.dog.抓捕成功 = false
this.dog.抓捕时间 = 0
this.fox.x = 0
this.fox.y = 100
}
},
...
})
...
然后开发记录抓捕时间功能,下面我直接贴出完整的js
代码和html
代码
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
<meta name="description" content="" />
<meta name="author" content="Mark Otto, Jacob Thornton, and Bootstrap contributors" />
<meta name="generator" content="Jekyll v3.8.6" />
<title>🐶 Dog & 🦊 Fox - 美图博客</title>
<link rel="canonical" href="https://getbootstrap.com/docs/4.4/examples/album/" />
<link href="https://cdn.bootcss.com/animate.css/3.7.2/animate.css" rel="stylesheet" />
<!-- Bootstrap core CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous" />
<!-- Favicons -->
<meta name="theme-color" content="#563d7c" />
<style>
.bd-placeholder-img {
font-size: 1.125rem;
text-anchor: middle;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
@media (min-width: 768px) {
.bd-placeholder-img-lg {
font-size: 3.5rem;
}
}
</style>
<!-- Custom styles for this template -->
<link href="style.css" rel="stylesheet" />
</head>
<body>
<header>
<div class="collapse bg-dark" id="navbarHeader">
<div class="container">
<div class="row">
<div class="col-sm-8 col-md-7 py-4">
<h4 class="text-white">故事</h4>
<p class="text-muted">通常,人们认为,狗狗是我们人类的朋友,而狐狸则相反,它代表着奸诈,狡猾,人们都想除掉它,让美丽的森林恢复宁静 ... 于是人们派出了狗狗,开始了一场铲除邪恶的战斗 ...</p>
</div>
</div>
</div>
</div>
<div class="navbar navbar-dark bg-dark shadow-sm">
<div class="container d-flex justify-content-between">
<a href="#" class="navbar-brand d-flex align-items-center">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" aria-hidden="true" class="mr-2" viewbox="0 0 24 24" focusable="false">
<path d="M23 19a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h4l2-3h6l2 3h4a2 2 0 0 1 2 2z" />
<circle cx="12" cy="13" r="4" />
</svg> <strong>🐶 Dog & 🦊 Fox</strong> </a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarHeader" aria-controls="navbarHeader" aria-expanded="false" aria-label="Toggle navigation"> <span class="navbar-toggler-icon"></span> </button>
</div>
</div>
</header>
<main role="main">
<section class="jumbotron text-center">
<div class="container">
<h1>通过游戏学编程</h1>
<p class="lead text-muted">这是一个由 Vue.js 开发的游戏小案例。课程链接 https://www.bilibili.com/video/BV1V7411R7dP?p=5</p>
<p> <a href="https://www.meitubk.com/" class="btn btn-primary my-2">访问我的博客</a></p>
</div>
</section>
<div class="album py-5 bg-light" id="app">
<div class="container">
<div class="row">
<div class="col-md-12">
<div class="card mb-4 shadow-sm">
<div id="forest">
<span id="dog" :class="dog.class" :style="{left: dog.x + 'px', top: dog.y + 'px'}">🐶</span>
<span id="fox" :class="fox.class" :style="{left: fox.x + 'px', top: fox.y + 'px'}">🦊</span>
</div>
<div class="card-body">
<p class="card-text"> 操作说明: 点击 <span class="arrow-key" @click="change_dog_direct(37)">⬅</span> <span class="arrow-key" @click="change_dog_direct(39)">➡</span> <span class="arrow-key" @click="change_dog_direct(38)">⬆</span> <span class="arrow-key" @click="change_dog_direct(40)">⬇</span> 控制狗狗方向 </p>
<div class="d-flex justify-content-between align-items-center">
<div class="btn-group">
<button type="button" :class="btn_play_again.class" @click="play_again" class="btn btn-sm btn-outline-secondary"> <span v-if=" !dog.抓捕成功 ">正在抓捕 。。。</span> <span v-if=" dog.抓捕成功 "> 抓捕成功!再来一次</span> </button>
</div>
<small class="text-muted">抓捕时间:{{ dog.抓捕时间 }}</small>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<table class="table table-striped">
<thead>
<tr>
<th>No.</th>
<th>抓捕时间(秒)</th>
</tr>
</thead>
<tbody>
<tr v-for="(seconds, index) of dog.logs">
<td>{{index+1}}</td>
<td>{{seconds}}</td>
</tr>
</tbody>
<tfoot>
<tr>
<td>平均时间:</td>
<td>{{dog.平均抓捕时间}}</td>
</tr>
</tfoot>
</table>
</div>
</div>
</div>
</div>
</main>
<footer class="text-muted">
<div class="container py-4">
<p class="float-right"> <a href="#">⬆</a> </p>
<p>祝您玩得愉快。</p>
<p>www.meitubk.com</p>
</div>
</footer>
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="custom.js"></script>
</body>
</html>
custom.js
var app = new Vue({
el: '#app',
data: {
forest: {
width: $('#forest')[0].offsetWidth,
height: $('#forest')[0].offsetHeight
},
dog: {
width: $('#dog')[0].offsetWidth,
height: $('#dog')[0].offsetHeight,
x: 0,
y: 0,
step: {
x: 10,
y: 2
},
抓捕时间: 0,
与狐狸的距离: 999,
抓捕成功: false,
class: '',
平均抓捕时间: 0,
logs: []
},
fox: {
width: $('#fox')[0].offsetWidth,
height: $('#fox')[0].offsetHeight,
x: 0,
y: 100,
class: ''
},
btn_play_again: {
class: ''
}
},
methods: {
move_dog(){
if (this.dog.抓捕成功) return
this.dog.x += this.dog.step.x
this.dog.y += this.dog.step.y
this.dog.抓捕时间 = Math.round((this.dog.抓捕时间 + 0.1) * 10) / 10
this.dog.与狐狸的距离 = getDistanceBetweenTwoPoints(
this.dog.x,
this.dog.y,
this.fox.x,
this.fox.y
)
},
change_dog_direct(k) {
if (k === 37 && this.dog.step.x > 0 || k === 39 && this.dog.step.x < 0) {
this.dog.step.x = -this.dog.step.x
}
if (k === 38 && this.dog.step.y > 0 || k === 40 && this.dog.step.y < 0) {
this.dog.step.y = -this.dog.step.y
}
},
change_dog_direct_keyboard(event) {
this.change_dog_direct(event.keyCode)
},
bounce_dog() {
if (this.dog.抓捕成功) {
this.dog.class = this.dog.class ? '' : 'animated bounce'
this.btn_play_again.class = this.btn_play_again.class ? '' : 'animated swing delay-1s'
}
},
random_fox() {
if (this.dog.抓捕成功) return
this.fox.x = Math.ceil(Math.random() * this.forest.width / 2)
this.fox.y = Math.ceil(Math.random() * (this.forest.height - this.fox.height))
this.fox.class = this.fox.class ? '': 'animated jello'
},
play_again() {
if (!this.dog.抓捕成功) return
this.dog.抓捕成功 = false
this.dog.抓捕时间 = 0
this.fox.x = 0
this.fox.y = 100
}
},
mounted: function(){
this.timer1 = setInterval(this.move_dog, 100)
this.timer2 = setInterval(this.random_fox, 1000)
this.timer3 = setInterval(this.bounce_dog, 2000);
window.addEventListener('keyup', this.change_dog_direct_keyboard)
},
watch: {
'dog.x': function(){
let x = this.dog.x
let w = this.forest.width
if(x <= 0 || x >= (w - this.dog.width)){
this.dog.step.x = - this.dog.step.x
}
},
'dog.y': function(){
let y = this.dog.y
let h = this.forest.height
if(y <= 0 || y >= (h - this.dog.height)){
this.dog.step.y = - this.dog.step.y
}
},
'dog.与狐狸的距离': function(val) {
let min_d = this.dog.width / 2 + this.fox.width / 2
if(val < min_d){
this.dog.抓捕成功 = true
this.dog.logs.push(this.dog.抓捕时间)
}
},
'dog.抓捕成功': function(val) {
if (val) {
this.fox.class = 'animated rotateOut delay-2s'
} else {
this.fox.class = ''
this.dog.class = ''
}
},
'dog.logs': function(val) {
let sum = 0
for (s of val) sum += s
this.dog.平均抓捕时间 = Math.round(sum / val.length * 100) / 100
}
}
})
//计算平面中两点距离
function getDistanceBetweenTwoPoints(x1, y1, x2, y2) {
var a = x1 - x2;
var b = y1 - y2;
// c^2 = a^2 + b^2
// a^2 = Math.pow(a, 2)
// b^2 = Math.pow(b, 2)
var result = Math.sqrt(Math.pow(a, 2) + Math.pow(b, 2));
return Math.round(result);
}
这样一来这个小游戏就开发完成了!
如果想要预览该项目可以在 https://www.meitubk.com/my/demo1/ 此链接访问。
本文章是根据 https://www.bilibili.com/video/BV1V7411R7dP?p=10 教程所记录的笔记。