想要做网页游戏怎么办 ?PixiJs 篇(四)
作者:互联网
序
在之前学了一部分的pixi之后,还是希望稍微写点和别人不一样的东西,有关碰撞检测之类的文章先略过不写了
现在小游戏中的拳皇因为是flash的原因,在我电脑上面已经玩不了了。那我能做一个仿制的么,想想看还是挺有趣的。真的是太年轻了
(脑子:我会了 手:不,你不会!!!)
使用pixi.js做一个拳皇游戏,我逐步发现需要的东西有好多呀!
目前就做出一个最简单的实验品no1,只有最简单的前进、后退、跳、蹲、跑,轻拳,重拳,轻脚,重脚这几个动作
下面是目前有的效果:
因为上传图片大小限制,所以将gif图分开进行展示
初始化和前进
后退和跳跃
下蹲和跑动
轻拳和重拳
轻脚和重脚
正文开始
素材来源
素材来源依旧是爱给网,当然我在爱给网下载下来的是gif图,通过将GIF分解成帧图片,然后使用纹理打包器TexturePacker制作为雪碧图
下面是我的vue页面和处理好的素材,如果要使用的话,还需要各位网友自己配置好文件和相对位置
链接:https://pan.baidu.com/s/1zYaLQTRdt_4P7J6vAMZb6g
提取码:7fbd
基础布局添加
这部分和之前的《想要做网页游戏怎么办 ?PixiJs 篇(二)》较像
首先,先创建好pixi.Application场景
initState() {
this.loader = new pixi.Loader();
//Create a Pixi Application 创建一个pixi应用
this.app = new pixi.Application({
width: window.innerWidth, // default: 800 宽度
height: window.innerHeight, // default: 600 高度
antialias: true, // default: false 反锯齿
// transparent: true, // default: false 透明度
resolution: 1 , // default: 1 分辨率
backgroundAlpha: 0 // 设置背景颜色透明度 0是透明
});
this.app.renderer.backgroundColor = 0x000000;
document.getElementById('game1').appendChild(this.app.view)
this.app.renderer.view.style.display = "block";
this.app.renderer.view.style.marginLeft = "30px";
this.app.renderer.autoResize = true;
this.bumpInit(); //碰撞检测
// 画布全屏 后面加一个参数可以设置背景色
scaleToWindow(this.app.renderer.view);
}
然后创建一个添加精灵方法,
let bg = './gameImg/bg.png', start = './gameImg/start.png', stand = './gameImg/stand.png', walkqian = './gameImg/walkqian.png', walkhou = './gameImg/walkhou.png', setdown = './gameImg/setdown.png', jump = './gameImg/jump.png', run = './gameImg/run.png', attack = './gameImg/attack.png';
this.loader.add([{name:'bg', url: bg}, {name:'start', url: start},{ name:'stand', url: stand },{ name:'walkqian', url: walkqian } ,{ name:'walkhou', url: walkhou }, { name:'setdown', url: setdown }, { name:'jump', url: jump }, { name:'run', url: run } , { name:'attack', url: attack }]).load(()=>{
//具体的添加事件
// 先定义一个SpriteUtilities,这里的this.$SpriteUtilities是在main.js导入的原因
let sput = new this.$SpriteUtilities(pixi);
})
在main.js当中添加spriteUtilities全局,这里我已经在spriteUtilities.js添加了export default SpriteUtilities;
import SpriteUtilities from './assets/spriteUtilities'
Vue.prototype.$SpriteUtilities = SpriteUtilities //将SpriteUtilities放入全局
战斗场景添加
场景精灵的创建也较为简单,这里注意将场景精灵的宽高设置为屏幕相同即可
并且使用animationSpeed去调节精灵的运动速度,注意启动精灵的play()方法让精灵动起来
//创建纹理数组 将雪碧图变成纹理数组 624, 384
// 创建战斗场景
let bgframes = sput.filmstrip(bg, 624, 384);
let bgsprite = sput.sprite(bgframes);
bgsprite.width = window.innerWidth; //场景精灵的宽高和屏幕相同
bgsprite.height = window.innerHeight;
bgsprite.animationSpeed = 0.1; //调节速度
bgsprite.play(); // 让精灵运动起来
// 精灵加入场景
this.addSprite(stage, [bgsprite])
场景效果
人物精灵
人物精灵的添加因为有许多雪碧图,如果像添加战斗场景一样写,那重复语句会很多。所以这里可以封装一个创建人物精灵的方法
// 封装创建精灵方法
createSprite(sput, spng, pwidth, pheight, width, height, animationSpeed, isshow, name, wheight) {
let playerframes = sput.filmstrip(spng, pwidth, pheight); //解析雪碧图
let sprite = sput.sprite(playerframes);
sprite.width = width; //设置精灵的宽高
sprite.height = height;
sprite.animationSpeed=animationSpeed; //精灵的运动速度
sprite.position.set(82, wheight * 0.93 - sprite.height) //精灵初始位置
sprite.visible = isshow; //精灵是否显示
sprite.name = name //精灵的别名
return sprite;
}
这样就可以使用像下面这样的方式大量创建精灵了
因为并不是一副完整的雪碧图,各个动作之间都是存在差别的。所以精灵的大小需要注意,这个可能要自己调试一下,差别比较明显
// 人物前进
let walkqiansprite = this.createSprite(sput, walkqian, 68, 104, 210, 288, 0.2, false, 'walkqian', wheight)
// 人物后退
let walkhousprite = this.createSprite(sput, walkhou, 70, 107, 210, 288, 0.2, false, 'walkhou', wheight)
// 人物下蹲
let setdownsprite = this.createSprite(sput, setdown, 65, 64, 200, 195, 0.2, false, 'setdown', wheight)
// 人物跳动
let jumpsprite = this.createSprite(sput, jump, 68, 190, 210, 570, 0.3, false, 'jump', wheight)
// 人物跑动
let runsprite = this.createSprite(sput, run, 123, 90, 350, 270, 0.3, false, 'run', wheight)
playersCont.addChild(walkqiansprite);
playersCont.addChild(walkhousprite);
playersCont.addChild(setdownsprite);
playersCont.addChild(jumpsprite);
playersCont.addChild(runsprite);
动作精灵的切换
因为是不同的精灵,所以通过玩家操控人物的动作会需要进行的不同切换。我将人物精灵都添加入一个Container()集合当中
通过控制Container()中的精灵的visible显隐来显示不同的人物动作。
这里要介绍一下pixi.js的API中的内容,如何去判断精灵动画的结束和开始,正在运行当前动画的哪一帧。通过这样的方式去判断切换不同的动作
这里的运动状态方法和属性还是比较多的,可以进行参考
属性名 | 默认值 | 作用 |
animationSpeed | 1 | 动画的运动速度,也就是帧改变速度 |
autoUpdate | 是否使用PIXI.Ticker.shared自动更新动画时间 | |
currentFrame | 当前AnimatedSprites运行的帧编号 | |
loop | true | 动画是否循环 |
onComplete | 当动画精灵完成播放时,用户指定要调用的函数 | |
onFrameChange | 当AnimatedSprite更改要渲染的纹理时,用户指定要调用的函数 | |
onLoop | 当循环为真时,用户指定要调用的函数,播放动画精灵并循环以重新开始 | |
playing | 判断当前动画是否正在播放 | |
textures | 用于此动画精灵的纹理数组 | |
totalFrames | 0 | 当前动画精灵的总帧数 |
updateAnchor | false | 当帧更改时,将锚点更新为纹理的defaultAnchor。 对于使用工具创建的精灵图纸动画非常有用。更改每个帧的锚允许将精灵原点固定到帧的某些移动特征(例如左脚)。 注意:启用此选项将覆盖之前在每个帧更改上设置的任何定位 |
例子:人物一开始出场动作消失后,在onComplete动画结束事件中改变动画精灵。注意要设置出场动画不循环 playersprite.loop = false;
// 初始化动画结束后,显示人物站立动作
playersprite.onComplete = () => {
playersCont.removeChild(playersprite);
playersCont.addChild(standsprite);
this.currIndex = 'stand'
standsprite.play();
this.keyMove(playersCont);
}
按键切换
之后在使用按键切换动作时也是类似的原理,关于按键控制动作可以参考:
keyboard方法判断按下的是什么按键
let left = keyboard('a'), up = keyboard('w'), right = keyboard('d'), down = keyboard('s'), quanattack1 = keyboard('u'), jiaoattack1 = keyboard('i'), quanattack2 = keyboard('j'), jiaoattack2 = keyboard('k');
例子: 按下键盘A键,人物从站立状态变成向后走的状态。 使用getChildByName来获取当前的精灵,使用visible改变显隐
调整vx来改变Container的位置
// 按键A按下
left.press = () => {
playersCont.getChildByName(this.currIndex).visible = false;
playersCont.getChildByName('walkhou').visible = true
playersCont.getChildByName('walkhou').play();
this.currIndex = 'walkhou';
playersCont.vx = -4;
};
// 按键松开
left.release = () => {
playersCont.vx = 0;
playersCont.getChildByName(this.currIndex).visible = false;
playersCont.getChildByName('stand').visible = true;
this.currIndex = 'stand';
};
当然在按键切换中,有许多判断还是比较麻烦的
比如说跑动动画的切换,其实是连续按两下D键实现的,所以这里就需要我判断按键连续点击。
在两次按下D键之间的时间间隔大于0和小于600ms即可
let ot = 0;
right.press = () => {
// getChildAt通过index索引 getChildByName通过name
playersCont.getChildByName(this.currIndex).visible = false;
playersCont.getChildByName('walkqian').visible = true
playersCont.getChildByName('walkqian').play();
this.currIndex = 'walkqian';
playersCont.vx = 4;
// 判断是否双击
let nt = new Date().getTime();
let ct = nt - ot;
if (ct > 0 && ct < 600) {
playersCont.getChildByName(this.currIndex).visible = false;
playersCont.getChildByName('run').visible = true
playersCont.getChildByName('run').play();
this.currIndex = 'run';
playersCont.vx = 12;
}
ot = nt;
};
还有像跳跃动作,需要这一次跳跃动作结束后,才可以进行下一次跳跃动作,不然就会变得十分鬼畜
正常动作:
鬼畜动作:
其实在按键这一块切换判断时,需要做的判断还有很多,比如说攻击判断等等,当前只是完成了最基础的部分,毕竟Pixi虽说性能比较高,但是开发成本一些方法需要自己完善。
小节
真的是路漫漫其修远兮,不过关于做前端游戏,我学习pixi.js其实也只是自己慢慢练手,毕竟真的去做,还是Cocos Creator和Unity方便。
如果说接下来我把自己的学习计划完成,去真正学前端游戏的话,目标应该会是Cocos Creator
标签:playersCont,网页,游戏,动画,精灵,let,false,PixiJs,name 来源: https://blog.csdn.net/qq_36171287/article/details/116454248