赞
踩
这是一个系列课程,我们将会用不同的机器学习算法,让机器学会玩不同的游戏。
今天要让机器玩的游戏是:陨石坠落(点击试玩)。
课程中,我们将围绕陨石坠落点预测问题,建立机器学习模型。
我们将会用到线性回归、梯度下降、Z-Score数据标准化等机器学习算法。
课程中,我们将使用Javascript作为开发语言,游戏构建在我自己写的一个简单的H5游戏引擎上。
你可以直接登陆我的网站,进行开发,无需安装开发软件和配置开发环境。
打开地址 http://www.insideai.cn/lesson_game1.html 就可以开发了。
课程会分成两个部分:
1. 游戏制作 这部分你将用H5亲手制作一款简单的游戏
2.机器学习建模 这部分你将从零开始,构建一个机器学习模型,并动手实践出来
下面我们就先说下,如何用H5制作一款简单的游戏。
公元4096年,狮子座M1024星发生爆炸,大量陨石向地球飞来。如果陨石撞上地球,将会对地球造成毁灭性的冲击。所幸神盾局已经研制出能抵抗陨石冲击的神盾,但神盾没有办法自动锁定陨石。
因此神盾局找到了你,你是个计算机高手,能为神盾注入灵魂。可以让神盾具有预测能力。 为了配合你的工作,神盾局会实时检测陨石的位置,并将陨石数据告知给你。
你需要利用这些数据,给神盾建立机器学习模型,在陨石坠落到安全线之前,预测出陨石的坠落点,并移动至陨石的坠落。
注:陨石坠落的位置、速度和方向都是随机的,每一颗陨石都不一样。
游戏主要包含三个分镜头:
1. 游戏引导镜头 主要介绍故事背景和引导玩家开始游戏。
2. 游戏主体镜头 为游戏的主体部分,完成游戏的交互逻辑。
3. 游戏结束镜头 游戏的结束画面和引导玩家重新开始游戏。
在制作镜头之前,我们需要先把游戏场景制作出来。游戏场景类似于游戏舞台,有了游戏场景后,游戏镜头才能播放出来。游戏场景的创建和初始化代码如下:
- var scene = new DMScene("gameContainer");
- scene.init();
注:上述代码是基于我写的H5游戏开发引擎编写的,因此需要登陆我的网站上进行开发,打开开发页面
下面我们就逐一把这些分镜头制作出来。
游戏引导镜头中,包含背景图片和引导文字,因此文字会开启逐字打印效果,因此我们还需要播放打字音效。
- //DMImage为图片对象,参数分别是:游戏场景、图片地址、横坐标、纵坐标、图片宽度和图片高度
- var guideImg = new DMImage(scene, "fall.jpg", 0, 0, scene.gwidth, scene.gheight);
- var guideStr = "公元4096年,狮子座M1024星发生爆炸,大量陨石向地球飞来。如果陨石撞上地球,将会对地球造成毁灭性的冲击。" +
- "所幸神盾局已经研制出能抵抗陨石冲击的神盾,但神盾没有办法自动锁定陨石。" +
- "因此需要为神盾注入灵魂,让它自己锁定陨石,并移至降落点。"+
- "经过千挑万选,最终发现只有你能胜任这个任务。" +
- "点击任意区域,开始拯救地球吧!!!";
- //DMTxt为文本对象,参数分别为:游戏场景、文本内容、横坐标、纵坐标、字体样式、
- //字体颜色、行间距,是否开启逐字打印
- var guideTxt = new DMTxt(scene, guideStr, 60, 80, "bold 36px '微软雅黑','宋体'"
- ,"white", 64, true);
-
- //DMAudio为音频对象,参选分别为:音频地址,加载完成回调函数,是否循环播放
- var writeMic = new DMAudio("write.mp3", null, "loop");
-
- //游戏引导镜头
- function guideGame(){
- //将镜头中的元素添加到场景中
- guideImg.addToScene();
- guideTxt.addToScene();
- //播放打字音效
- writeMic.play();
- //15秒后,暂停打字音效
- setTimeout(function(){writeMic.pause();}, 15000);
- }

游戏引导镜头制作完成后,调用函数guideGame,游戏场景中,就会播放引导镜头画面啦。
注:游戏中的图片和音频资源均来自于搜索引擎,如有侵权,请告知。游戏中,用到的图片和音频,我已放到我的网站上了。打开开发页面
游戏主体镜头中,包含陨石、神盾、得分文本和背景图片,此外我们还会循环播放游戏背景音乐。
- var yunshi = new DMBox(scene,100,100, 10,10,"white");
- //安全线位置,在屏幕的3/4处
- var safeHeight = scene.gheight*0.75;
- var shendun = new DMBox(scene, 0, safeHeight, 100, 30, "gray");
- var earthImg = new DMImage(scene,"earth.jpg", 0, safeHeight-30, scene.gwidth,
- scene.gwidth/4);
- var score = 0;
- var scoreTxt = new DMTxt(scene, "得分: " + score + " ", scene.gwidth - 120, 60,
- "bold 24px '微软雅黑','宋体'", "red");
-
- var bgMic = new DMAudio("bg.mp3", null, "loop");
-
- function startGame(){
- //清空游戏场景,清除上一个镜头中的元素
- scene.clear();
- //暂停上一个镜头中的音效
- writeMic.pause();
- earthImg.addToScene();
- yunshi.addToScene();
- shendun.addToScene();
- scoreTxt.addToScene();
- bgMic.play();
- }

游戏主体镜头制作完成后,调用startGame就可以在游戏场景中,播放主体镜头了。
游戏结束镜头中,包括重玩引导文本和背景图片,其中重玩文本会开启逐字打印效果,因此需要播放打字音效。
- var overImg = new DMImage(scene,"over.jpg",0,0,scene.gwidth,scene.gheight);
- var overStr = "很遗憾,因为您的算法不当,陨石撞上了地球,地球发生了爆炸。不服!"
- + "点击任意区域,让时光倒退,重新开始!!!";
- var overTxt = new DMTxt(scene, overStr, 60, 80, "bold 36px '微软雅黑','宋体'",
- "white", 64, true);
- function gameOver(){
- scene.clear();
- bgMic.pause();
- overImg.addToScene();
- //设置逐字打印的起始字符
- overTxt.charAt = 0;
- //设置逐字打印速度
- overTxt.writeSpeed=10;
- overTxt.addToScene();
- writeMic.play();
- setTimeout(function(){writeMic.pause();}, 10000);
- }
-
- gameOver();

好了,三个游戏镜头制作完成了,接下来,我们要已经玩家的交互行为,实现交互效果了。
目前为止,所有的元素都是静止的,下面我们就陨石动起来。这一节,我们实现陨石坠落特效。
陨石坠落的位置、速度和方向都是随机的,因此陨石的初始坐标和速度都要随机产生。
此外,为了提升游戏体验,陨石需要拖着尾巴,逐渐变亮,形成燃烧的效果,并播放坠落音效。
- //使用线性过渡颜色,模拟陨石逐渐变亮
- yunshi.useGrad("black","white",100, scene.gheight*0.6);
- //陨石坠落音效
- var fallMic = new DMAudio("fall.mp3");
- function fall(){
- //在游戏场景的中间80%区域随机产生横坐标
- yunshi.x = Math.random()*scene.gwidth*0.8 + scene.gwidth*0.1;
- yunshi.y = 0;
- //水平方向的速度随机产生,可正可负,与场景宽度相关
- yunshi.xSpeed = (Math.random() - 0.5)*scene.gwidth/80;
- //竖直方向的速度随机产生,为正数,与场景高度相关
- yunshi.ySpeed = Math.random()*scene.gheight/160 + scene.gheight/160;
- //在陨石运动的反方向加上音频,模拟尾巴
- yunshi.useShadow(20, "yellow", -1*yunshi.xSpeed, -1*yunshi.ySpeed);
- fallMic.play();
- }

这么复杂的效果,使用游戏引擎后,几句代码就完成了。打开开发页面
下面我们就把各个镜头串联起来,依据游戏逻辑,进行镜头切换。
在游戏引导镜头,用户点击时,进入游戏主体镜头,在游戏主体镜头,用户点击时,依据游戏状态,播放或暂停游戏。
在主体镜头中,如果陨石坠落到安全线以下,则认为游戏撞上了地球,游戏结束。
- //定义游戏镜头索引,1引导镜头,2主体镜头,3结束镜头
- var gameStatus = 1;
-
- //添加鼠标点击监听事件
- scene.setClickListener(function(){
- if(gameStatus == 1){
- startGame();
- fall();
- gameStatus = 2;
- }else if(gameStatus == 2){
- //如果有些正在进行,则暂停有些,否则播放游戏
- if(scene.isPlay){
- scene.pause();
- }else{
- scene.play();
- }
- }else if(gameStatus == 3){
- scene.clear();
- startGame();
- fall();
- gameStatus = 2;
- }
- });
-
- //游戏场景回调函数,绘制每一帧之前都会调用该函数
- function onDraw(){
- if(gameStatus != 2){
- return;
- }
-
- //判断陨石的纵坐标是否在安全线以下
- if(yunshi.y > safeHeight + shendun.height){
- gameOver();
- gameStatus = 3;
- }
- }
-
- //设置游戏场景的回调函数
- scene.onDraw = onDraw;

好了,现在游戏可以在各个镜头之间切换了,但是神盾还没有办法移动,因此陨石总是撞上地球。
我们先用键盘控制神盾移动,后面我们再说如何让机器预测陨石坠落点,让神盾自主移动。
可以移动神盾后,我们就需要检测神盾与陨石是否发生了砰撞,如果发生了砰撞,我们需要播放陨石爆炸特效,并让神盾发出保护光环,播放撞击音效,此外我们还需对玩家进行计分。
- //定义神盾移动速度
- var shendunSpeed = scene.gwidth/100;
- function goLeft(){
- shendun.moveTo(shendun.x - shendunSpeed, shendun.y);
- }
- function goRight(){
- shendun.moveTo(shendun.x + shendunSpeed, shendun.y);
- }
-
- //监听用户按键事件,如果是左箭头,则向左移动,如果是右箭头,则向右移动
- window.addEventListener("keydown",function(e){
- var keycode = scene.getKeyCode(e);
- if(keycode == 37){
- goLeft();
- }else if(keycode == 39){
- goRight();
- }
- }, false);
-
- //重写场景回调函数,增加砰撞检测和陨石爆炸特效
- function onDraw(){
- if(gameStatus != 2){
- return;
- }
-
- if(explordeTime > 0){
- explode();
- }else if(!yunshi.isInScene()){
- fall();
- }else if(yunshi.hitOnSprite(shendun)){
- hitOn();
- }else if(yunshi.y > safeHeight + shendun.height){
- gameOver();
- gameStatus = 3;
- }
- }
-
- //陨石爆炸持续时长
- var explordeTime = 0;
- //陨石爆炸函数
- function explode(){
- explordeTime--;
- yunshi.width = explordeTime;
- yunshi.height = explordeTime;
- if(explordeTime == 0){
- yunshi.width = 10;
- yunshi.height = 10;
- shendun.useShadow(0,"blue",0,0);
- fall();
- }
- }
-
- //陨石击中神盾音效
- var hitMic = new DMAudio("hit.mp3");
-
- //陨石击中神盾处理函数
- function hitOn(){
- score++;
- scoreTxt.txt = "得分: " + score;
- shendun.useShadow(20, "blue", 0, -5);
- hitMic.play();
- explordeTime = 20;
- yunshi.xSpeed = 0;
- yunshi.ySpeed = 0;
- }
-
- //更新场景回调函数
- scene.onDraw = onDraw;

好了,现在有些已经制作完成了,写了这么长事件代码,也有点小累了,玩会游戏吧。
下篇文章,我们将介绍如何针对游戏,进行机器学习建模,并利用机器学习模型,让神盾具有预测能力,自主移动到坠落点。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。