本红包雨项目是基于HTML5的游戏框架Phaser写的,最终形成的是一个canvas,所以性能很好,但是必须要说的是这个框架比较大,压缩后也有700K左右,所以请慎用.
代码地址: https://github.com/AmosXu/red-packet-rain
图片依次是倒计时页面,抢红包页面,拆红包页,红包展示页,这些页面都是写在一个canvas里面的,无刷新的切换效果,性能超级棒
贴上主要的代码js代码和注释
//初始化图片 let imgjishi = &#39;assets/img/daojishi.png&#39; let bgPlan = &#39;assets/img/bg-plan.jpg&#39; let bgRainer = &#39;assets/img/bg-rainer.jpg&#39; let redpacket = &#39;assets/img/redpacket.png&#39; let close = &#39;assets/img/close.png&#39; let dialogExit = &#39;assets/img/dialog-exit.png&#39; let buttOnCancel= &#39;assets/img/button-cancel.png&#39; let buttOnExit= &#39;assets/img/button-exit.png&#39; let openRedpacket = &#39;assets/img/open-redpacket.png&#39; let open = &#39;assets/img/open.png&#39; let redpacketResult = &#39;assets/img/redpacket-result.png&#39; let buttOnUseTicket= &#39;assets/img/button-use-ticket.png&#39; let buttOnContinue= &#39;assets/img/button-continue.png&#39; let cursorAnimation = &#39;assets/img/cursor-animation.png&#39; let states = {} let QingLvGroup; let hitNum = 0; let cOnfig= { selfPool:40, selfPic:&#39;redpacket&#39;, rate:0.5, maxSpeed:1200, minSpeed:400, max:95 } let ids = [0, 1, 2, 3, 4, 5] let redpackets = [&#39;全场优惠50元&#39;, &#39;20元代金券&#39;, &#39;全场优惠50元&#39;, &#39;20元代金券&#39;, &#39;全场优惠50元&#39;, &#39;20元代金券&#39;] let time = 25; let getIds = [] let radio = document.documentElement.clientWidth/375; let e; function rfuc(n){ return n*radio; } //初始化红包 function QingLv(config, game){ this.init = function(){ this.cOnfig= config; QingLvGroup = game.add.group(); QingLvGroup.enableBody = true; QingLvGroup.createMultiple(config.selfPool, config.selfPic); //初始化多个红包 QingLvGroup.setAll(&#39;anchor.y&#39;,1) QingLvGroup.setAll(&#39;outOfBoundsKill&#39;, true); QingLvGroup.setAll(&#39;checkWorldBounds&#39;, true); this.maxWidth = game.width + 300; game.time.events.loop(Phaser.Timer.SECOND * config.rate, this.createQL, this); }; this.createQL = function(){ e = QingLvGroup.getFirstExists(false); if(e) { if(hitNum >= config.max) { return; } hitNum++; e.events.onInputDown.removeAll(); var ram= Math.random(); ram =ram<0.5?ram+=0.5: ram; e.loadTexture(this.config.selfPic) e.alpha = 1; e.angle = 30 // e.scale.setTo(rfuc(ram)); e.reset(game.rnd.integerInRange(100, this.maxWidth), 100) //红包生成的位置 e.body.velocity.x = game.rnd.integerInRange(-300, -150); //红包移动的速度 e.body.velocity.y = game.rnd.integerInRange(config.minSpeed, config.maxSpeed); e.inputEnabled = true; e.events.onInputDown.add(this.hitted, this) } }; this.hitted = function(sprite){ if(Math.random() <1/4 && ids.length > 0) { sprite.kill(); //点击获得红包,游戏暂停 game.paused = true; //背景 let hexGraphics = new Phaser.Graphics().beginFill(0x000000, 0.5).drawRect(0,0,document.documentElement.clientWidth,document.documentElement.clientHeight + 2); let pausedMask = game.add.sprite(0, 0, hexGraphics.generateTexture()) let openDialog = game.add.sprite(rfuc(62), rfuc(150), &#39;openRedpacket&#39;) let open = game.add.sprite(rfuc(130), rfuc(300), &#39;open&#39;) open.inputEnabled = true; let result = game.add.sprite(rfuc(0), rfuc(120), &#39;redpacketResult&#39;) result.visible = false let userTicket = game.add.sprite(rfuc(78), rfuc(445), &#39;buttonUseTicket&#39;) userTicket.visible = false let goOn = game.add.sprite(rfuc(198), rfuc(445), &#39;buttonContinue&#39;) goOn.visible = false let ticketText = {}; let link = &#39;&#39; //拆红包 let clickOpen = function() { //游戏暂停时,点击事件无效,只能通过这种画热点的形式来绑定事件 let openRect = new Phaser.Rectangle(rfuc(130), rfuc(315), 239, 239).copyFrom(open); if (openRect.contains(game.input.x, game.input.y)) { let currentWidth = open.width //拆红包动画 let tempArr = [2, 4, 8, 4, 2, 1] let index = 0; let timer = setInterval(function() { if (index > tempArr.length-1) { index = 0 } open.width = currentWidth / tempArr[index] open.height = open.height open.left = game.world.centerX - open.width / 2 ++index }, 200) game.input.onDown.remove(clickOpen, this); let arrIndex = Math.floor(Math.random() * ids.length) let redpacketId = ids.splice(arrIndex, 1) getIds.push(redpacketId[0]) setTimeout(()=> { timer && clearInterval(timer) document.getElementById(&#39;audioOpen&#39;).play() let text = redpackets[redpacketId[0]] ticketText=game.add.text(0, rfuc(338),text,{fill:&#39;#ffe67d&#39;,fontSize:&#39;46px&#39;,fontWeight: &#39;bolder&#39;}) ticketText.left = game.world.centerX - ticketText.width / 2 //文字相对于屏幕左右居中 openDialog.visible = false open.visible = false result.visible = true userTicket.visible = true goOn.visible = true game.input.onDown.add(clickButton, this) }, 1000) } }; let clickButton = function() { let userTicketRect = new Phaser.Rectangle(rfuc(78), rfuc(445), 194, 66).copyFrom(userTicket); let cOntinueRect= new Phaser.Rectangle(rfuc(198), rfuc(445), 194, 66).copyFrom(goOn); if (userTicketRect.contains(game.input.x, game.input.y)) { window.location.replace(link) game.input.onDown.remove(clickButton, this); } else if (continueRect.contains(game.input.x, game.input.y)) { result.visible = false userTicket.visible = false goOn.visible = false pausedMask.visible = false ticketText.visible = false game.paused = false game.input.onDown.remove(clickButton, this); } } game.input.onDown.add(clickOpen, this) } else { sprite.inputEnabled = false; var anim = sprite.animations.add(config.selfPic); sprite.play(config.selfPic, 40, false); anim.onComplete.add(this.fade, this, sprite) } }; this.fade = function(sprite){ var tween = game.add.tween(sprite).to({alpha:0}, 300, &#39;Linear&#39;, true) tween.onComplete.add(this.killed, this, sprite); }; this.killed = function(sprite){ sprite.kill(); } } states.boot = function(game) { this.preload = function() { if (typeof(GAME) !== "undefined") { this.load.baseURL = GAME + "/"; } if (!game.device.desktop) { this.scale.scaleMode = Phaser.ScaleManager.EXACT_FIT; this.scale.forcePortrait = true; this.scale.refresh(); } }; this.create = function() { game.stage.backgroundColor = &#39;#FFF&#39;; game.state.start(&#39;preload&#39;); }; }; states.preload = function(game) { this.preload = function(game) { //加载图片 game.load.spritesheet(&#39;daojishi&#39;, imgjishi, 250,120, 4) game.load.image(&#39;bgPlan&#39;, bgPlan) game.load.image(&#39;bgRainer&#39;, bgRainer) game.load.spritesheet(&#39;redpacket&#39;, redpacket, 144, 173, 2) game.load.image(&#39;close&#39;, close) game.load.image(&#39;dialogExit&#39;, dialogExit) game.load.image(&#39;buttonExit&#39;, buttonExit) game.load.image(&#39;buttonCancel&#39;, buttonCancel) game.load.image(&#39;openRedpacket&#39;, openRedpacket) game.load.image(&#39;open&#39;, open) game.load.image(&#39;redpacketResult&#39;, redpacketResult) game.load.image(&#39;buttonContinue&#39;, buttonContinue) game.load.image(&#39;buttonUseTicket&#39;, buttonUseTicket) game.load.spritesheet(&#39;cursorAnimation&#39;, cursorAnimation, 74, 108, 2) }; this.create = function() { game.state.start(&#39;main&#39;); }; }; states.main = function(game) { this.create = function() { // 物理系统 game.physics.startSystem(Phaser.Physics.ARCADE); // 背景图 var bgPlan = game.add.sprite(0, 0, &#39;bgPlan&#39;); bgPlan.width = game.width; bgPlan.height = game.height; var cursorPointer = game.add.sprite(game.world.centerX - 36, game.world.centerY + 86, &#39;cursorAnimation&#39;); var anim = cursorPointer.animations.add(&#39;cursorAnimation&#39;); cursorPointer.play(&#39;cursorAnimation&#39;, 2, true); document.getElementById(&#39;audioCountDown&#39;).play() // 开始游戏倒计时 var daojishi = game.add.sprite(game.world.centerX - 140, game.world.centerY - 400, &#39;daojishi&#39;); var anim = daojishi.animations.add(&#39;daojishi&#39;); daojishi.play(&#39;daojishi&#39;, 1, false); anim.onComplete.add(this.startGame, this, daojishi); }; this.startGame = function(daojishi){ this.leftTime = time let bgRainer = game.add.sprite(0, 0, &#39;bgRainer&#39;); bgRainer.width = game.width; bgRainer.height = game.height; daojishi.visible = false; this.createQingLv(); //添加按钮,并绑定事件 let closeImg = game.add.button(rfuc(20), rfuc(20), &#39;close&#39;, function(){ game.paused = true pausedMask.visible = true exitDialog.visible = true exitButton.visible = true cancelButton.visible = true game.input.onDown.add(buttonClick, this) }.bind(this)) // 剩余时间 this.leftTimeText = game.add.text(0, 0, this.leftTime, {fill: &#39;#FFF&#39;, fontSize: &#39;40px&#39;, fontWeight: &#39;bolder&#39;}) this.leftTimeText.scale.setTo(rfuc(1)) this.leftTimeText.fixedToCamera = true; this.leftTimeText.cameraOffset.setTo(game.camera.width - rfuc(80), rfuc(20)); let hexGraphics = new Phaser.Graphics().beginFill(0x000000, 0.5).drawRect(0,0,document.documentElement.clientWidth,document.documentElement.clientHeight + 2); let pausedMask = game.add.sprite(0, 0, hexGraphics.generateTexture()) pausedMask.visible = false; let exitDialog = game.add.sprite(rfuc(62), rfuc(150), &#39;dialogExit&#39;) exitDialog.visible = false; let exitButton = game.add.button(rfuc(80), rfuc(315), &#39;buttonExit&#39;) exitButton.visible = false; let isExit = false let cancelButton = game.add.button(rfuc(200), rfuc(315), &#39;buttonCancel&#39;) cancelButton.visible = false; game.time.events.repeat(Phaser.Timer.SECOND, this.leftTime, this.refreshTime, this) let buttOnClick= function() { let cancelRect = new Phaser.Rectangle(rfuc(200), rfuc(315), 194, 66).copyFrom(cancelButton); if (cancelRect.contains(game.input.x, game.input.y)) { game.input.onDown.remove(buttonClick, this) game.paused = false pausedMask.visible = false exitDialog.visible = false exitButton.visible = false cancelButton.visible = false } } }; this.createQingLv = function(){ this.qinglv = new QingLv(config, game); this.qinglv.init(); this.qinglv = new QingLv(config, game); this.qinglv.init(); }; this.refreshTime = function(){ this.leftTime--; var tem = this.leftTime; this.leftTimeText.text = tem; if(this.leftTime === 0) { game.paused = true; } } }; //生成游戏 let game = null if (game == null) { game = new Phaser.Game(document.documentElement.clientWidth, document.documentElement.clientHeight + 2, Phaser.AUTO, document.getElementById(&#39;gameScreen&#39;)); game.state.add(&#39;boot&#39;, states.boot.bind(game)); game.state.add(&#39;preload&#39;, states.preload.bind(game)); game.state.add(&#39;main&#39;, states.main.bind(game)); game.state.start(&#39;boot&#39;); }
答: 通过全局事件画热点的形式绑定事件,一定要记得移除事件,一定一定要记得
game.input.onDown.add(clickOpen, this) //给游戏绑定全局事件 let userTicket = game.add.sprite(rfuc(78), rfuc(445), &#39;buttonUseTicket&#39;) let userTicketRect = new Phaser.Rectangle(78, 445, 194, 66).copyFrom(userTicket); //获得button的区域 //如果点击的位置为button的位置就执行下一步 if (userTicketRect.contains(game.input.x, game.input.y)) { //移除全局事件 game.input.onDown.remove(clickButton, this); }
答: 添加文字到游戏中,文字向左的偏移量等于游戏屏幕的宽度减去文字宽度的一般,就能达到居中的效果
ticketText = game.add.text(0, rfuc(338), &#39;我想居中&#39;, {fill: &#39;#ffe67d&#39;, fontSize: &#39;46px&#39;, fontWeight: &#39;bolder&#39;}) ticketText.left = game.world.centerX - ticketText.width / 2 //文字相对于屏幕左右居中
代码地址: https://github.com/AmosXu/red-packet-rain
总结:以上就是本篇文的全部内容,希望能对大家的学习有所帮助。更多相关教程请访问 HTML视频教程,Html5视频教程,bootstrap视频教程!
以上就是html5仿淘宝,京东实现红包雨效果(代码实例)的详细内容,更多请关注 第一PHP社区 其它相关文章!