[]【简单跑酷--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(){
    
    /**
     * 地板类
     */
    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);
        }
    }
})();再修改一下MapFloor.js(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
赞同来自: