[]【简单跑酷--JS版】---Lv.3 添加地板
说得不好的地方请及时指正
第一节
第二节
//======================= 美丽的分割线 =======================
前节教程完成了循环滚动背景的实现,本节我们将运动的地板加上
下图是我们要用到的资源
地板素材是这样的 宽度为960 在游戏里面我目前将它分成32份 也就是由30个小的组成
我们把素材复制到资源目录 如下图
打开LayaSample.js 既然多了一个资源 那就要预加载 上一节有讲到
修改加载的地方
//加载图片
Laya.loader.load(["res/background.png", "res/m_background.png", "res/floor.png"], laya.utils.Handler.create(this, onLoaded), laya.utils.Handler.create(this, onLoading, null, false));
首先同样我们到runGame目录新建一个Floor.js
开始编写代码
这里 我们想一下地板有哪些功能?
1、自身从右到左运动 超出左边边界 就移除存入对象池
2、地板上可以添加东西
(function(){
/**
* 地板类
*/
function Floor(){
Floor.__super.call(this);
}
//Floor 是一个显示对象 继承此 Sprite
Laya.class(Floor, "Floor", laya.display.Sprite);
var _proto = Floor.prototype;
_proto.init = function(type){
//创建一个帧循环处理函数
Laya.timer.frameLoop(1, this, this.onLoop);
}
//在地板上面添加物品
_proto.addItem = function(){
}
_proto.onLoop = function(){
}
})();
因为是一个跑酷的游戏 所以 我们之前提到过 这个地板最好有一个类专门负责管理她们
因此 我们再创建一个地板管理类 MapFloor.js
地板管理类 主要干嘛呢
1、增加地板
2、删除地板
3、获取地板
这里我把这个MapFloor当成所有floor的父级显示对象 (其实也有其他方式 这里暂不考虑)
嗯 那我们根据上面的三个功能可以写下如下代码
(function () {
/**
* 地板地图类
*
*/
function MapFloor(){
MapFloor.__super.call(this);
this.init();
}
//MapFloor 是一个显示对象 继承此 Sprite
Laya.class(MapFloor,"MapFloor", laya.display.Sprite);
var _proto = MapFloor.prototype;
_proto.init = function(){
//创建一个帧循环处理函数
Laya.timer.frameLoop(1, this, this.onLoop);
}
_proto.onLoop = function(){
}
/**
* 增加地板
*/
_proto.addFloor = function(){
}
/**
* 获取地板
*/
_proto.getFloor = function(){
}
/**
* 删除地板
*/
_proto.delFloor = function(){
}
})();
地板和 地板管理类都搭好了 既然是显示对象 那我们就得添加到舞台
打开RunGame.js
(function () {
/**
* 游戏入口
*/
function RunGame(){
RunGame.__super.call(this);
this.init();
}
//RunGame 是一个显示对象 继承此 Sprite
Laya.class(RunGame,"RunGame", laya.display.Sprite);
//定义RunGame的prototype
var _proto = RunGame.prototype;
//初始化
_proto.init = function(){
console.log('RunGame Init');
//添加背景
var bg = new Background();
this.addChild(bg);
//添加地板集合
var mapFloor = new MapFloor();
this.addChild(mapFloor);
}
})();
前期工作都做好了~~ 接下来就是把地板显示到舞台上面
打开Floor.js 我们来给floor设置皮肤
(function(){
/**
* 地板类
*/
function Floor(){
//背景贴图纹理
this.bgTexture = null;
//背景
this.bg = null;
Floor.__super.call(this);
}
//Floor 是一个显示对象 继承此 Sprite
Laya.class(Floor, "Floor", laya.display.Sprite);
var _proto = Floor.prototype;
_proto.init = function(){
//如果不开启autoSize 父容器的宽度和高度无法获取
this.autoSize = true;
//初始化的时候将坐标放到屏幕右边
this.x = 852;
//y坐标取一个随机值 为什么是32 因为我们的整个素材是 32 * 20 拼起来的
this.y = 32 * 6 + 32 * parseInt(8 * Math.random());
if(this.bg == null){
//贴图纹理
this.bgTexture = Laya.loader.getRes("res/floor.png");
this.bg = new laya.display.Sprite();
this.bg.graphics.clear();
//将当前的坐标向上移动32 方便后面处理人物的位置
this.bg.y = -32;
this.addChild(this.bg);
}
this.bg.graphics.drawTexture(this.bgTexture, 0, 0, 960, 96);
//创建一个帧循环处理函数
Laya.timer.frameLoop(1, this, this.onLoop);
}
//在地板上面添加物品
_proto.addItem = function(){
}
//获取当前地板上面的所有物品
_proto.getItems = function(){
return ;
}
_proto.onLoop = function(){
//让地板的速度和移动比背景快一点
this.x -= 5 * 1.2;
if((this.x + this.width) < 0){
//判断整个floor是否不在屏幕里面了 如果不在了 移除当前floor
Laya.timer.clear(this, this.onLoop);
this.visible = false;
this.removeSelf();
}
}
})();
地板有了 我们打开MapFloor.js 来添加地板
(function () {
/**
* 地板地图类
*
*/
function MapFloor(){
MapFloor.__super.call(this);
this.init();
}
//MapFloor 是一个显示对象 继承此 Sprite
Laya.class(MapFloor,"MapFloor", laya.display.Sprite);
var _proto = MapFloor.prototype;
_proto.init = function(){
//添加地板
this.addFloor();
//创建一个帧循环处理函数
Laya.timer.frameLoop(1, this, this.onLoop);
}
_proto.onLoop = function(){
}
/**
* 增加地板
*/
_proto.addFloor = function(){
var floor = new Floor();
floor.init();
this.addChild(floor);
}
/**
* 获取地板
*/
_proto.getFloor = function(){
}
/**
* 删除地板
*/
_proto.delFloor = function(){
}
})();
对了~~ 我们这里右新增了两个模块 所以别忘记 上一节我们说到的 要在页面引用响应的JS哦
我们刷新页面看看
我们会看到地板从屏幕右边慢慢的跑出来了
~~~ 既然是跑酷 一个地板肯定是不够的~~
我们来增加多一点地板
首先我们想一下 如何增加地板
1、通过时间间隔来生成
2、通过上一个地板左边移除屏幕外面的后 右边剩余的宽度
我们先简单分析一下这两种方式的利与弊
首先 “通过时间间隔来生成”
我们需要一个时间控制器来判断(例如每隔1秒生成一个)
看起来没有什么问题 但是后期我们游戏的地板宽度是随机的 假设上一个地板随机的时候很短 导致与下一个地板之间的间距过大 这个时候 后期玩家从地板之间跳跃就成为一个问题了
因此我们考虑第二个方案“通过上一个地板左边移除屏幕外面的后 右边剩余的宽度”
接下来我们会用到自定义事件的方式 让Floor通知它父类MapFloor 什么时候改生成新的地板 什么时候删除屏幕外面的地板
既然如此 我们来写一下代码
(function(){再修改一下MapFloor.js
/**
* 地板类
*/
function Floor(){
//背景贴图纹理
this.bgTexture = null;
//最大右边距离
this.maxRight = 0;
this.isOutComplete = false;
//背景
this.bg = null;
Floor.__super.call(this);
}
//事件名称
//超过屏幕一定值出发新的floor事件
Floor.OUT_COMPLETE = "floor_out_complete";
//整个地板都不在屏幕里面事件
Floor.OUT_DIE = "floor_out_die";
//Floor 是一个显示对象 继承此 Sprite
Laya.class(Floor, "Floor", laya.display.Sprite);
var _proto = Floor.prototype;
_proto.init = function(){
this.maxRight = 0;
//如果不开启autoSize 父容器的宽度和高度无法获取
this.autoSize = true;
//初始化的时候将坐标放到屏幕右边
this.x = 852;
//y坐标取一个随机值 为什么是32 因为我们的整个素材是 32 * 20 拼起来的
this.y = 32 * 6 + 32 * parseInt(8 * Math.random());
if(this.bg == null){
//贴图纹理
this.bgTexture = Laya.loader.getRes("res/floor.png");
this.bg = new laya.display.Sprite();
this.bg.graphics.clear();
//将当前的坐标向上移动32 方便后面处理人物的位置
this.bg.y = -32;
this.addChild(this.bg);
}
this.bg.graphics.drawTexture(this.bgTexture, 0, 0, 960, 96);
//计算一下右边还剩下多少 用来判断什么时候生成新的floor
//这里是通过游戏宽度 减去 固定 2个 32的宽度 再随机一个长度 这样 可以让地板时间点的出现 更加随机性
this.maxRight = 852 - 32 * 2 - 32 * parseInt(10 * Math.random());
//创建一个帧循环处理函数
Laya.timer.frameLoop(1, this, this.onLoop);
}
//在地板上面添加物品
_proto.addItem = function(){
}
//获取当前地板上面的所有物品
_proto.getItems = function(){
return ;
}
_proto.onLoop = function(){
//让地板的速度和移动比背景快一点
this.x -= 5 * 1.2;
//判断是否除了边界 如果出了 就通知生成新的floor 这里增加一个变量来判断当前是否已经通知外部了
//因为此处是一个循环的处理
if(!this.isOutComplete && (this.x + this.width) < this.maxRight){
this.isOutComplete = true;
this.event(Floor.OUT_COMPLETE, this);
}else if((this.x + this.width) < 0){
//判断整个floor是否不在屏幕里面了 如果不在了 移除当前floor
Laya.timer.clear(this, this.onLoop);
this.visible = false;
this.event(Floor.OUT_DIE, this);
}
}
})();
(function () {
/**
* 地板地图类
*
*/
function MapFloor(){
//要移除的地板
this.dieFloorList = ;
MapFloor.__super.call(this);
this.init();
}
//MapFloor 是一个显示对象 继承此 Sprite
Laya.class(MapFloor,"MapFloor", laya.display.Sprite);
var _proto = MapFloor.prototype;
_proto.init = function(){
//添加地板
this.addFloor();
//创建一个帧循环处理函数
Laya.timer.frameLoop(1, this, this.onLoop);
}
_proto.onLoop = function(){
//监听有没有地板要移除
while(this.dieFloorList.lenght > 0){
var floor = this.dieFloorList.shift();
floor.removeSelf();
}
}
/**
* 增加地板
*/
_proto.addFloor = function(){
var floor = new Floor();
floor.init();
floor.once(Floor.OUT_COMPLETE, this, this.getFloor);
floor.once(Floor.OUT_DIE, this, this.delFloor);
this.addChild(floor);
}
/**
* 获取地板
*/
_proto.getFloor = function(floor){
this.addFloor();
}
/**
* 删除地板
*/
_proto.delFloor = function(floor){
this.dieFloorList.push(floor);
}
})();
刷新页面看看效果哈~~ 是不是地板开始动了 而且 还有新的
~~
好像每个地板都一样宽度 我们改善一下代码 在生成地板的时候我们随即一下地板的绘制宽度
打开Floor.js 找到
this.bg.graphics.drawTexture(this.bgTexture, 0, 0, 960, 96);
修改为:
//随机一个范围值刷新页面试一试
var _w = 32 * (3 + parseInt(19 * Math.random()));
this.bg.graphics.clear();
//这里用到了 Texture.createFromTexture 就是根据宽度和高度来截取一个图片并且返回一个Texture对象
this.bg.graphics.drawTexture(laya.resource.Texture.createFromTexture(this.bgTexture,0,0,_w,96), 0, 0, _w, 96);
嗯 宽度是变短了 但是发现没有 右边好假~~~
怎么办。。。。。。。。。。。。。。
//======================= 喝杯水想一想有什么办法 =======================
我们看看原图是什么样子的
右边是好的 ~~
。。。。
有办法了~~ 我们把右边 用同样的手法绘制出来 和 上面的背景放在一起 是不是就解决了?
之前有收到 这个背景是 32 * 30 的
上面我们控制地板的宽度的时候用到了
laya.resource.Texture.createFromTexture
我们看下API
这里我们只要最右边的图片 也就是 从 32 *29 的位置开始截取图片
我们来试一下
最终Floor.js代码如下
这里我们只要最右边的图片 也就是 从 32 *29 的位置开始截取图片
我们来试一下
最终Floor.js代码如下
(function(){
/**
* 地板类
*/
function Floor(){
//背景贴图纹理
this.bgTexture = null;
//最大右边距离
this.maxRight = 0;
//判断是否超过右边最大距离了
this.isOutComplete = false;
//背景
this.bg = null;
//背景右边补丁
this.rightBg = null;
Floor.__super.call(this);
}
//事件名称
//超过屏幕一定值出发新的floor事件
Floor.OUT_COMPLETE = "floor_out_complete";
//整个地板都不在屏幕里面事件
Floor.OUT_DIE = "floor_out_die";
//Floor 是一个显示对象 继承此 Sprite
Laya.class(Floor, "Floor", laya.display.Sprite);
var _proto = Floor.prototype;
_proto.init = function(){
this.maxRight = 0;
//如果不开启autoSize 父容器的宽度和高度无法获取
this.autoSize = true;
//初始化的时候将坐标放到屏幕右边
this.x = 852;
//y坐标取一个随机值 为什么是32 因为我们的整个素材是 32 * 20 拼起来的
this.y = 32 * 6 + 32 * parseInt(8 * Math.random());
if(this.bg == null){
//贴图纹理
this.bgTexture = Laya.loader.getRes("res/floor.png");
this.bg = new laya.display.Sprite();
this.bg.graphics.clear();
//将当前的坐标向上移动32 方便后面处理人物的位置
this.bg.y = -32;
this.addChild(this.bg);
//因为上面的图片是截取的 所以右边可能没有图片了 这里补一个
this.rightBg = new laya.display.Sprite();
this.rightBg.graphics.drawTexture(laya.resource.Texture.createFromTexture(this.bgTexture,32*29,0,32,96), 0, 0, 32, 96);
this.rightBg.width = 32;
this.rightBg.y = -32;
this.addChild(this.rightBg);
}
//随机一个范围值
var _w = 32 * (3 + parseInt(19 * Math.random()));
this.bg.graphics.clear();
//这里用到了 laya.resource.Texture.createFromTexture 就是根据宽度和高度来截取一个图片并且返回一个Texture对象
this.bg.graphics.drawTexture(laya.resource.Texture.createFromTexture(this.bgTexture,0,0,_w,96), 0, 0, _w, 96);
this.rightBg.visible = true;
//这个是用来补上右边的图片 所以X轴坐标正好是bg的宽度
this.rightBg.x = _w;
// this.bg.graphics.drawTexture(this.bgTexture, 0, 0, 960, 96);
//计算一下右边还剩下多少 用来判断什么时候生成新的floor
//这里是通过游戏宽度 减去 固定 2个 32的宽度 再随机一个长度 这样 可以让地板时间点的出现 更加随机性
this.maxRight = 852 - 32 * 2 - 32 * parseInt(10 * Math.random());
//创建一个帧循环处理函数
Laya.timer.frameLoop(1, this, this.onLoop);
}
//在地板上面添加物品
_proto.addItem = function(){
}
//获取当前地板上面的所有物品
_proto.getItems = function(){
return ;
}
_proto.onLoop = function(){
//让地板的速度和移动比背景快一点
this.x -= 5 * 1.2;
//判断是否除了边界 如果出了 就通知生成新的floor 这里增加一个变量来判断当前是否已经通知外部了
//因为此处是一个循环的处理
if(!this.isOutComplete && (this.x + this.width) < this.maxRight){
this.isOutComplete = true;
this.event(Floor.OUT_COMPLETE, this);
}else if((this.x + this.width) < 0){
//判断整个floor是否不在屏幕里面了 如果不在了 移除当前floor
Laya.timer.clear(this, this.onLoop);
this.visible = false;
this.event(Floor.OUT_DIE, this);
}
}
})();
是不是很完美了
下节我们讲一下 玩家~~~ 谢谢~~~~
源码在附件里面~~~
没有找到相关结果
要回复问题请先登录
7 个回复
Monica - 知识达人
赞同来自:
cuixueying
赞同来自:
curry1sgod
赞同来自:
cinos
赞同来自:
thebackpacker
赞同来自:
xh4343
赞同来自:
beyond5l
赞同来自: