机器学习:让机器学会打游戏之陨石坠落

陨石坠落画面

这是一个系列课程,我们将会用不同的机器学习算法,让机器学会玩不同的游戏。

今天要让机器玩的游戏是:陨石坠落(点击试玩)。

课程概述

课程中,我们将围绕陨石坠落点预测问题,建立机器学习模型。

我们将会用到线性回归、梯度下降、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;

好了,现在有些已经制作完成了,写了这么长事件代码,也有点小累了,玩会游戏吧。

下篇文章,我们将介绍如何针对游戏,进行机器学习建模,并利用机器学习模型,让神盾具有预测能力,自主移动到坠落点。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值