'use strict'; game.import('play',function(lib,game,ui,get,ai,_status){ return { name:'coin', init:function(){ if(lib.config.mode!='chess'||get.config('chess_mode')!='leader'){ _status.coin=0; } }, arenaReady:function(){ if(_status.video||_status.connectMode) return; if(lib.config.mode!='chess'||get.config('chess_mode')!='leader'){ var str; if(lib.config.coin_display_playpackconfig=='text'){ str=''+lib.config.coin+'' } else{ str=''+lib.config.coin+''; } if(lib.config.coin_canvas_playpackconfig){ ui.window.classList.add('canvas_top'); } ui.coin=ui.create.system(str,null,true); if(lib.config.snowFall){ game.haveFun.list.snow.bought=true; setTimeout(function(){ game.haveFun.snow(); },500); } lib.setPopped(ui.coin,function(){ var uiintro=ui.create.dialog('hidden'); uiintro.classList.add('coin_menu') uiintro.add('商店'); uiintro.listen(function(e){ e.stopPropagation(); }); var clickBuy=function(){ if(this.innerHTML=='停止'){ game.haveFun[this.name+'Stop'](); } else if(this.innerHTML=='开始'){ game.haveFun[this.name](); } else if(this.innerHTML.indexOf('金')!=-1){ if(lib.config.coin>=this.content.cost){ this.content.bought=true; game.changeCoin(-this.content.cost); game.haveFun[this.name](); if(this.content.onbuy){ this.content.onbuy.call(this); } } else{ return; } } ui.click.window(); }; for(var i in game.haveFun.list){ var item=game.haveFun.list[i]; uiintro.add('
'+item.name+'
'); var buy=uiintro.content.lastChild.lastChild.lastChild; if(lib.config.coin本局获胜'); var bet=uiintro.content.lastChild.lastChild.lastChild; bet.listen(function(){ if(_status.betWin) return; _status.betWin=true; game.changeCoin(-20); this.innerHTML='已下注'; }); if(_status.betWin){ bet.innerHTML='已下注'; } } else if(_status.betWin){ uiintro.add('下注'); uiintro.add('
本局获胜
'); } uiintro.classList.add('noleave'); return uiintro; },220,400); } }, game:{ changeCoin:function(num){ if(typeof num=='number'&&ui.coin){ game.saveConfig('coin',lib.config.coin+num); var str; if(lib.config.coin_display_playpackconfig=='text'){ str=''+lib.config.coin+'' } else{ str=''+lib.config.coin+''; } ui.coin.innerHTML=str; } }, haveFun:{ list:{ firework:{ name:'烟花', cost:50, }, snow:{ name:'下雪', cost:20, size:'large', control:function(){ var size=ui.create.div('.menubutton'); if(game.haveFun.list.snow.size=='small'){ size.innerHTML='大雪'; } else{ size.innerHTML='小雪'; } size.listen(game.haveFun.snowSize); return size; } }, star:{ name:'星云', cost:10 }, blink:{ name:'闪烁', cost:10 } }, alwaysSnow:function(){ game.saveConfig('snowFall',!lib.config.snowFall); game.reload(); }, blink:function(){ if(game.haveFun.list.blink.running) return; game.haveFun.list.blink.running=true; if(game.haveFun.blinkLoop){ game.haveFun.blinkLoop(); } else{ var canvas = document.createElement("canvas"); ui.window.appendChild(canvas); canvas.classList.add('fun'); canvas.style.zIndex=20; var ctx = canvas.getContext("2d"); //Make the canvas occupy the full page var W = ui.window.offsetWidth, H = ui.window.offsetHeight; canvas.width = W; canvas.height = H; lib.onresize.push(function(){ var W = ui.window.offsetWidth, H = ui.window.offsetHeight; canvas.width = W; canvas.height = H; }); var particles = []; var mouse = {}; //Lets create some particles now var particle_count = 25; //finally some mouse tracking ui.window.addEventListener('mousemove', function(e) { //since the canvas = full page the position of the mouse //relative to the document will suffice mouse.x = e.pageX/game.documentZoom; mouse.y = e.pageY/game.documentZoom; }); ui.window.addEventListener('touchmove',function(e){ mouse.x = e.touches[0].clientX/game.documentZoom; mouse.y = e.touches[0].clientY/game.documentZoom; }); var particle=function() { //speed, life, location, life, colors //speed.x range = -2.5 to 2.5 //speed.y range = -15 to -5 to make it move upwards //lets change the Y speed to make it look like a flame this.speed = {x: -2.5+Math.random()*5, y: -5+Math.random()*10}; this.speed.x/=4; this.speed.y/=4; //location = mouse coordinates //Now the flame follows the mouse coordinates if(mouse.x && mouse.y) { this.location = {x: mouse.x, y: mouse.y}; } else { this.location = {x: W/2, y: H/2}; } //radius range = 10-30 this.radius = 10+Math.random()*20; //life range = 20-30 this.radius/=4; this.life = 20+Math.random()*10; this.life*=4; this.remaining_life = this.life; //colors this.r = Math.round(Math.random()*255); this.g = Math.round(Math.random()*255); this.b = Math.round(Math.random()*255); } for(var i = 0; i < particle_count; i++) { particles.push(new particle()); } var draw=function() { if(!game.haveFun.list.blink.running){ canvas.width=W; canvas.height=H; return; } ctx.clearRect(0, 0, W, H); //Painting the canvas black //Time for lighting magic //particles are painted with "lighter" //In the next frame the background is painted normally without blending to the //previous frame ctx.globalCompositeOperation = "lighter"; for(var i = 0; i < particles.length; i++) { var p = particles[i]; ctx.beginPath(); //changing opacity according to the life. //opacity goes to 0 at the end of life of a particle p.opacity = Math.round(p.remaining_life/p.life*100)/100 //a gradient instead of white fill var gradient = ctx.createRadialGradient(p.location.x, p.location.y, 0, p.location.x, p.location.y, p.radius); gradient.addColorStop(0, "rgba("+p.r+", "+p.g+", "+p.b+", "+p.opacity+")"); gradient.addColorStop(0.5, "rgba("+p.r+", "+p.g+", "+p.b+", "+p.opacity+")"); gradient.addColorStop(1, "rgba("+p.r+", "+p.g+", "+p.b+", 0)"); ctx.fillStyle = gradient; ctx.arc(p.location.x, p.location.y, p.radius, Math.PI*2, false); ctx.fill(); //lets move the particles p.remaining_life--; p.radius-=0.2; p.location.x += p.speed.x; p.location.y += p.speed.y; //regenerate particles if(p.remaining_life < 0 || p.radius < 0) { //a brand new particle replacing the dead one particles[i] = new particle(); } } requestAnimationFrame(draw); } draw(); game.haveFun.blinkLoop=draw; game.haveFun.blinkStop=function(){ game.haveFun.list.blink.running=false; } } }, star:function(){ if(game.haveFun.list.star.running) return; game.haveFun.list.star.running=true; if(game.haveFun.starLoop){ game.haveFun.starLoop(); } else{ //****************************************************** // Yet Another Particle Engine var cos = Math.cos, sin = Math.sin, sqrt = Math.sqrt, abs = Math.abs, atan2 = Math.atan2, log = Math.log, random = Math.random, PI = Math.PI, sqr = function(v){return v*v;}, particles = [], drawScale = 1, emitters = [], forces = [], collidedMass = 0, maxParticles = 100, emissionRate = 1, minParticleSize = 2; //------------------------------------------------------- // Vectors, and not the kind you put stuff in var Vector=function(x, y, z) { this.x = x || 0; this.y = y || 0; this.z = z || 0; } Vector.prototype = { add : function(vector) { this.x += vector.x; this.y += vector.y; this.z += vector.z; return this; }, subtract : function(vector) { this.x -= vector.x; this.y -= vector.y; this.z -= vector.z; return this; }, multiply : function(another) { this.x /= another.x; this.y /= another.y; this.z /= another.z; return this; }, divide : function(another) { this.x /= another.x; this.y /= another.y; this.z /= another.z; return this; }, scale : function(factor) { this.x *= factor; this.y *= factor; this.z *= factor; return this; }, magnitude : function () { return sqrt(sqr(this.x + this.y)); }, distance : function (another) { return abs(sqrt(sqr(this.x - another.x) + sqr(this.y - another.y))); }, angle : function (angle, magnitude) { if(angle && magnitude) return Vector.fromAngle(angle, magnitude); return atan2(this.y, this.x); }, clone : function() { return new Vector(this.x, this.y, this.z); }, equals : function(another) { return this.x === another.x&& this.y === another.y&& this.z === another.z; }, random : function(r) { this.x += (random() * r * 2) - r; this.y += (random() * r * 2) - r; return this; } }; Vector.fromAngle = function (angle, magnitude) { return new Vector( magnitude * cos(angle), magnitude * sin(angle), magnitude * sin(angle)); }; //****************************************************** // A thing with mass, position, and velocity - like your mom var Particle=function(pt, vc, ac, mass) { this.pos = pt || new Vector(0, 0); this.vc = vc || new Vector(0, 0); this.ac = ac || new Vector(0, 0); this.mass = mass || 1; this.alive = true; } Particle.prototype.move = function () { this.vc.add(this.ac); this.pos.add(this.vc); }; Particle.prototype.reactToForces = function (fields) { var totalAccelerationX = 0; var totalAccelerationY = 0; for (var i = 0; i < fields.length; i++) { var field = fields[i]; var vectorX = field.pos.x - this.pos.x; var vectorY = field.pos.y - this.pos.y; var distance = this.pos.distance(field.pos); if(distance < 1) field.grow(this); if(distance < 100) this.doubleSize = true; var force = G(this.forceBetween(field, distance)); totalAccelerationX += vectorX * force; totalAccelerationY += vectorY * force; } this.ac = new Vector(totalAccelerationX, totalAccelerationY); totalAccelerationX = 0; totalAccelerationY = 0; for (var i = 0; i < particles.length; i++) { var field = particles[i]; if(field === this || !field.alive) continue; var vectorX = field.pos.x - this.pos.x; var vectorY = field.pos.y - this.pos.y; var distance = this.pos.distance(field.pos); if(distance < 1) { if(this.mass >= field.mass) { var massRatio = this.mass / field.mass; if(particles.length <= maxParticles && this.mass>40) { this.alive = false; this.nova = true; collidedMass += this.mass; } else this.grow(field); } else this.alive = false; } if(this.alive) { var force = G(this.forceBetween(field, distance)); totalAccelerationX += vectorX * G(force); totalAccelerationY += vectorY * G(force); } } var travelDist = this.pos.distance(this.lastPos ? this.lastPos : this.pos); this.velocity = travelDist - (this.lastDistance ? this.lastDistance : travelDist); this.lastDistance = travelDist; this.lastPos = this.pos.clone(); this.ac.add(new Vector(totalAccelerationX, totalAccelerationY)); this.lastPos = this.pos.clone(); // if(this.mass > 20) { // var chance = 1 / (this.mass - 20); // if(Math.random()>chance) { // this.supernova = true; // this.supernovaDur = 10; // this.alive = false; // if(particles.length <= maxParticles) collidedMass += this.mass; // delete this.size; // } // } }; Particle.prototype.grow = function (another) { this.mass += another.mass; this.nova = true; another.alive = false; delete this.size; }; Particle.prototype.breakApart = function(minMass, maxParts) { if(!minMass) minMass = 1; if(!maxParts) maxParts = 2; var remainingMass = this.mass; var num = 0; while(remainingMass > 0) { var np = new Particle(this.pos.clone().random(this.mass), new Vector(0,0)); np.mass = 1 + Math.random() * (remainingMass - 1); if(num>=maxParts-1) np.mass = remainingMass; np.mass = np.mass < minMass ? minMass : np.mass; remainingMass -= np.mass; num++; } this.nova = true; delete this.size; this.alive = false; }; Particle.prototype.forceBetween = function(another, distance) { var distance = distance? distance : this.pos.distance(another.pos); return (this.mass * another.mass) / sqr(distance); }; //****************************************************** //This certainly doesn't *sub*mit to particles, that's for sure var ParticleEmitter=function(pos, vc, ang) { // to do config options for emitter - random, static, show emitter, emitter color, etc this.pos = pos; this.vc = vc; this.ang = ang || 0.09; this.color = "#999"; } ParticleEmitter.prototype.emit = function() { var angle = this.vc.angle() + this.ang - (Math.random() * this.ang * 2); var magnitude = this.vc.magnitude(); var position = this.pos.clone(); position.add( new Vector( ~~((Math.random() * 100) - 50) * drawScale, ~~((Math.random() * 100) - 50) * drawScale )); var velocity = Vector.fromAngle(angle, magnitude); return new Particle(position,velocity); }; //****************************************************** // Use it, Luke // to do collapse functionality into particle var Force=function(pos, m) { this.pos = pos; this.mass = m || 100; } Force.prototype.grow = function (another) { this.mass += another.mass; this.burp = true; another.alive = false; }; var G=function(data) { return 0.00674 * data; } //****************************************************** var canvas = document.createElement('canvas'); canvas.classList.add('fun'); ui.window.appendChild(canvas); var ctx = canvas.getContext('2d'); canvas.width = ui.window.offsetWidth; canvas.height = ui.window.offsetHeight; var canvasWidth = canvas.width; var canvasHeight = canvas.height; lib.onresize.push(function() { canvas.width = ui.window.offsetWidth; canvas.height = ui.window.offsetHeight; canvasWidth = canvas.width; canvasHeight = canvas.height; }); var renderToCanvas = function (width, height, renderFunction) { var buffer = document.createElement('canvas'); buffer.width = width; buffer.height = height; renderFunction(buffer.getContext('2d')); return buffer; }; maxParticles = 500; emissionRate = 1; drawScale = 1.3; minParticleSize = 2; emitters = [ //br new ParticleEmitter( new Vector( canvasWidth / 2 * drawScale + 400, canvasHeight / 2 * drawScale ), Vector.fromAngle(2, 5), 1 ), // // bl // new ParticleEmitter( // new Vector( // canvasWidth / 2 * drawScale - 400, // canvasHeight / 2 * drawScale + 400 // ), // Vector.fromAngle(1.5, 1), // 1 // ), // tl new ParticleEmitter( new Vector( canvasWidth / 2 * drawScale - 400, canvasHeight / 2 * drawScale ), Vector.fromAngle(5, 5), 1 ), // // tr // new ParticleEmitter( // new Vector( // canvasWidth / 2 * drawScale + 400, // canvasHeight / 2 * drawScale - 400 // ), // Vector.fromAngle(4.5, 1), // 1 // ) ]; forces = [ new Force( new Vector((canvasWidth / 2 * drawScale) , (canvasHeight / 2 * drawScale)), 1800) ]; var loop=function() { if(!game.haveFun.list.star.running){ canvas.width=ui.window.offsetWidth; canvas.height=ui.window.offsetHeight; return; } clear(); update(); draw(); queue(); } game.haveFun.starLoop=loop; game.haveFun.starStop=function(){ game.haveFun.list.star.running=false; }; var clear=function() { ctx.clearRect(0, 0, canvas.width, canvas.height); } var ctr = 0; var c = [ 'rgba(255,255,255,', 'rgba(0,150,255,', 'rgba(255,255,128,', 'rgba(255,255,255,' ]; var rndc=function() { return c[~~(Math.random() * c.length-1)]; } var c2 = 'rgba(255,64,32,'; var addNewParticles=function() { var _emit = function() { var ret = 0; for (var i = 0; i < emitters.length; i++) { for (var j = 0; j < emissionRate; j++) { var p = emitters[i].emit(); p.color = ( ctr % 10 === 0 )? ( Math.random() * 5 <= 1 ? c2 : rndc() ) : rndc(); p.mass = ~~(Math.random() * 5); particles.push(p); ret += p.mass; ctr++; } } return ret; }; if(collidedMass !== 0) { while(collidedMass !== 0) { collidedMass -= _emit(); collidedMass = collidedMass<0 ? 0 :collidedMass; } } if (particles.length > maxParticles) return; _emit(); } var CLIPOFFSCREEN = 1, BUFFEROFFSCREEN = 2, LOOPSCREEN = 3; var isPositionAliveAndAdjust=function(particle,check) { return true; // var pos = particle.pos; // if(!check) check = BUFFEROFFSCREEN; // if(check === CLIPOFFSCREEN) { // return !(!particle.alive || // pos.x < 0 || // (pos.x / drawScale) > boundsX || // pos.y < 0 || // (pos.y / drawScale) > boundsY); // } else if(check === BUFFEROFFSCREEN) { // return !(!particle.alive || // pos.x < -boundsX * drawScale || // pos.x > 2 * boundsX * drawScale || // pos.y < -boundsY * drawScale || // pos.y > 2 * boundsY * drawScale); // } else if(check === LOOPSCREEN) { // if (pos.x < 0) pos.x = boundsX * drawScale; // if ((pos.x / drawScale) > boundsX) pos.x = 0; // if (pos.y < 0) pos.y = boundsY * drawScale; // if ((pos.y / drawScale) > boundsY) pos.y = 0; // return true; // } } var plotParticles=function(boundsX, boundsY) { var currentParticles = []; for (var i = 0; i < particles.length; i++) { var particle = particles[i]; particle.reactToForces(forces); if(!isPositionAliveAndAdjust(particle)) continue; particle.move(); currentParticles.push(particle); } } var offscreenCache = {}; var renderParticle=function(p) { var position = p.pos; if(!p.size) p.size = Math.floor(p.mass / 100); if(!p.opacity) p.opacity = 0.05; if(p.velocity > 0) { if(p.opacity<=0.18) p.opacity += 0.04; } if(p.opacity>0.08) p.opacity -= 0.02; var actualSize = p.size / drawScale; actualSize = actualSize < minParticleSize ? minParticleSize : actualSize; if(p.mass>8) actualSize *= 2; if(p.nova) { actualSize *= 4; p.nova = false; } if(p.doubleSize) { p.doubleSize = false; actualSize *= 2; } // if(p.supernova) { // actualSize *= 6; // opacity = 0.15; // p.supernovaDur = p.supernovaDur - 1; // if(p.supernovaDur === 0) // p.supernova = false; // } var cacheKey = actualSize + '_' + p.opacity + '_' + p.color; var cacheValue = offscreenCache[cacheKey]; if(!cacheValue) { cacheValue = renderToCanvas(actualSize * 32, actualSize * 32, function(ofsContext) { var opacity = p.opacity; var fills = [ {size:actualSize/2, opacity:1}, {size:actualSize, opacity:opacity}, {size:actualSize * 2, opacity:opacity / 2}, {size:actualSize * 4, opacity:opacity / 3}, {size:actualSize * 8, opacity:opacity / 5}, {size:actualSize * 16, opacity:opacity / 16} ]; ofsContext.beginPath(); for(var f in fills) { f = fills[f]; ofsContext.fillStyle = p.color + f.opacity + ')'; ofsContext.arc( actualSize * 16, actualSize * 16, f.size , 0, Math.PI*2, true); ofsContext.fill(); } ofsContext.closePath(); }); offscreenCache[cacheKey] = cacheValue; } var posX = p.pos.x / drawScale; var posY = p.pos.y / drawScale; ctx.drawImage(cacheValue, posX, posY); } var fills = [ {size:15,opacity:1 }, {size:25,opacity:0.3}, {size:50,opacity:0.1} ]; var renderScene=function(ofsContext) { for (var i = 0; i < forces.length; i++) { var p = forces[i]; var position = p.pos; var opacity = 1; ofsContext.beginPath(); for(var f in fills) { f = fills[f]; var o = p.burp === true ? 1 : f.opacity; p.burp = false; // ofsContext.fillStyle = 'rgba(255,255,255,' + o + ')'; // ofsContext.arc(position.x / drawScale, // position.y / drawScale, // f.size / drawScale, 0, Math.PI*2, true); // ofsContext.fill(); } ofsContext.closePath(); } for (var i = 0; i < particles.length; i++) { var p = particles[i]; renderParticle(p); } } var draw=function() { renderScene(ctx); } var update=function() { addNewParticles(); plotParticles(canvas.width, canvas.height); } var queue=function() { window.requestAnimationFrame(loop); } loop(); } }, snow:function(){ game.haveFun.list.snow.running=true; if(game.haveFun.snowStart){ game.haveFun.snowStart(); } else{ /* * 自由下雪 snowFall * author:xuanfeng * time: 2014-01-11 */ // 控制下雪 var canvas; var snowFall=function(snow) { // 可配置属性 snow = snow || {}; this.maxFlake = snow.maxFlake || 200; //最多片数 this.flakeSize = snow.flakeSize || 10; //雪花形状 this.fallSpeed = snow.fallSpeed || 2; //坠落速度 this.status = 0; //0-初始化、1-开始下雪、2-停止下雪、3-暂停下雪、4-继续下雪 } // 兼容写法 var requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame || window.oRequestAnimationFrame || function(callback) { setTimeout(callback, 1000 / 60); }; var cancelAnimationFrame = window.cancelAnimationFrame || window.mozCancelAnimationFrame || window.webkitCancelAnimationFrame || window.msCancelAnimationFrame || window.oCancelAnimationFrame; // 开始下雪 snowFall.prototype.start = function(){ if(this.status == 1 || this.status == 4){ // 已经在下雪则不作处理 return false; } this.status = 1; // 创建画布 snowCanvas.apply(this); // 创建雪花形状 createFlakes.apply(this); // 画雪 drawSnow.apply(this) } // 停止下雪 snowFall.prototype.stop = function(){ if(this.status == 2 || this.status == 0 || !this.canvas){ return false; } // 停止动画循环 this.pause(); this.status = 2; // 删除画布 this.canvas.parentNode.removeChild(this.canvas); this.canvas = null; } // 暂停下雪 snowFall.prototype.pause = function(){ if(this.status == 3){ return false; } this.status = 3; cancelAnimationFrame(this.loop) }; // 继续下雪 snowFall.prototype.resume = function(){ if(this.status == 3 && this.canvas){ this.status = 4; // 动画的计时控制 var that=this; this.loop = requestAnimationFrame(function() { drawSnow.apply(that) }); } }; // 创建画布 var snowCanvas=function() { // 添加Dom结点 var snowcanvas = document.createElement("canvas"); snowcanvas.classList.add('fun'); snowcanvas.id = "snowfall"; ui.window.appendChild(snowcanvas); canvas=snowcanvas; this.canvas = snowcanvas; this.ctx = snowcanvas.getContext("2d"); // 窗口大小改变的处理 lib.onresize.push(function() { snowcanvas.width = ui.window.offsetWidth; snowcanvas.height = ui.window.offsetHeight }); snowcanvas.width = ui.window.offsetWidth; snowcanvas.height = ui.window.offsetHeight; } // 雪运动对象 var flakeMove=function(canvasWidth, canvasHeight, flakeSize, fallSpeed) { this.x = Math.floor(Math.random() * canvasWidth); //x坐标 this.y = Math.floor(Math.random() * canvasHeight); //y坐标 this.size = Math.random() * flakeSize + 2; //形状 this.maxSize = flakeSize; //最大形状 this.speed = Math.random() * 1 + fallSpeed; //坠落速度 this.fallSpeed = fallSpeed; //坠落速度 this.velY = this.speed; //Y方向速度 this.velX = 0; //X方向速度 this.stepSize = Math.random() / 30; //步长 this.step = 0 //步数 } flakeMove.prototype.update = function() { var x = this.x, y = this.y; // 左右摆动(余弦) this.velX *= 0.98; if (this.velY <= this.speed) { this.velY = this.speed } this.velX += Math.cos(this.step += 0.05) * this.stepSize; this.y += this.velY; this.x += this.velX; // 飞出边界的处理 if (this.x >= canvas.width || this.x <= 0 || this.y >= canvas.height || this.y <= 0) { this.reset(canvas.width, canvas.height) } }; // 飞出边界-放置最顶端继续坠落 flakeMove.prototype.reset = function(width, height) { this.x = Math.floor(Math.random() * width); this.y = 0; this.size = Math.random() * snow.flakeSize + 2; this.speed = Math.random() * 1 + snow.fallSpeed; this.velY = this.speed; this.velX = 0; }; // 渲染雪花-随机形状 flakeMove.prototype.render = function(ctx) { var snowFlake = ctx.createRadialGradient(this.x, this.y, 0, this.x, this.y, this.size); snowFlake.addColorStop(0, "rgba(255, 255, 255, 0.9)"); snowFlake.addColorStop(0.5, "rgba(255, 255, 255, 0.5)"); snowFlake.addColorStop(1, "rgba(255, 255, 255, 0)"); ctx.save(); ctx.fillStyle = snowFlake; ctx.beginPath(); ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2); ctx.fill(); ctx.restore(); }; // 创建雪花-定义形状 var createFlakes=function() { var maxFlake = this.maxFlake, flakes = this.flakes = [], canvas = this.canvas; for (var i = 0; i < 200; i++) { flakes.push(new flakeMove(canvas.width, canvas.height, this.flakeSize, this.fallSpeed)) } } // 画雪 var drawSnow=function() { var maxFlake = this.maxFlake, flakes = this.flakes; var ctx = this.ctx, canvas = this.canvas, that = this; // 清空雪花 ctx.clearRect(0, 0, canvas.width, canvas.height); for (var e = 0; e < maxFlake; e++) { flakes[e].update(); flakes[e].render(ctx); } // 一帧一帧的画 this.loop = requestAnimationFrame(function() { drawSnow.apply(that); }); } // 调用及控制方法 var snow = new snowFall(); game.haveFun.snowStart=function(){ snow.start(); } game.haveFun.snowStop=function(){ game.haveFun.list.snow.running=false; snow.stop(); } game.haveFun.snowSize=function(){ if(game.haveFun.list.snow.size=='large'){ game.haveFun.list.snow.size='small'; snow.maxFlake=80; snow.flakeSize=3; snow.fallSpeed=1; if(this&&this.innerHTML){ this.innerHTML='大雪'; } game.saveConfig('coinSnowSize',true); } else{ game.haveFun.list.snow.size='large'; snow.maxFlake=200; snow.flakeSize=10; snow.fallSpeed=2; if(this&&this.innerHTML){ this.innerHTML='小雪'; } game.saveConfig('coinSnowSize',false); } } if(lib.config.coinSnowSize){ game.haveFun.snowSize(); } snow.start(); } }, firework:function(){ if(game.haveFun.list.firework.running) return; game.haveFun.list.firework.running=true; if(game.haveFun.fireworkLoop){ game.haveFun.fireworkLoop(); } else{ // when animating on canvas, it is best to use requestAnimationFrame instead of setTimeout or setInterval // not supported in all browsers though and sometimes needs a prefix, so we need a shim var requestAnimFrame = ( function() { return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || function( callback ) { window.setTimeout( callback, 1000 / 60 ); }; })(); // now we will setup our basic variables for the demo var canvas = document.createElement( 'canvas' ), ctx = canvas.getContext( '2d' ), // full screen dimensions cw = ui.window.offsetWidth, ch = ui.window.offsetHeight, // firework collection fireworks = [], // particle collection particles = [], // starting hue hue = 120, // when launching fireworks with a click, too many get launched at once without a limiter, one launch per 5 loop ticks limiterTotal = 5, limiterTick = 0, // this will time the auto launches of fireworks, one launch per 80 loop ticks timerTotal = 80, timerTick = 0, mousedown = false, // mouse x coordinate, mx, // mouse y coordinate my; // set canvas dimensions canvas.width = cw; canvas.height = ch; ui.window.appendChild(canvas); canvas.classList.add('fun'); lib.onresize.push(function(){ cw=ui.window.offsetWidth; ch=ui.window.offsetHeight; canvas.width = cw; canvas.height = ch; }); // now we are going to setup our function placeholders for the entire demo // get a random number within a range var random=function( min, max ) { return Math.random() * ( max - min ) + min; } // calculate the distance between two points var calculateDistance=function( p1x, p1y, p2x, p2y ) { var xDistance = p1x - p2x, yDistance = p1y - p2y; return Math.sqrt( Math.pow( xDistance, 2 ) + Math.pow( yDistance, 2 ) ); } // create firework var Firework=function( sx, sy, tx, ty ) { // actual coordinates this.x = sx; this.y = sy; // starting coordinates this.sx = sx; this.sy = sy; // target coordinates this.tx = tx; this.ty = ty; // distance from starting point to target this.distanceToTarget = calculateDistance( sx, sy, tx, ty ); this.distanceTraveled = 0; // track the past coordinates of each firework to create a trail effect, increase the coordinate count to create more prominent trails this.coordinates = []; this.coordinateCount = 3; // populate initial coordinate collection with the current coordinates while( this.coordinateCount-- ) { this.coordinates.push( [ this.x, this.y ] ); } this.angle = Math.atan2( ty - sy, tx - sx ); this.speed = 2; this.acceleration = 1.05; this.brightness = random( 50, 70 ); // circle target indicator radius this.targetRadius = 1; } // update firework Firework.prototype.update = function( index ) { // remove last item in coordinates array this.coordinates.pop(); // add current coordinates to the start of the array this.coordinates.unshift( [ this.x, this.y ] ); // cycle the circle target indicator radius if( this.targetRadius < 8 ) { this.targetRadius += 0.3; } else { this.targetRadius = 1; } // speed up the firework this.speed *= this.acceleration; // get the current velocities based on angle and speed var vx = Math.cos( this.angle ) * this.speed, vy = Math.sin( this.angle ) * this.speed; // how far will the firework have traveled with velocities applied? this.distanceTraveled = calculateDistance( this.sx, this.sy, this.x + vx, this.y + vy ); // if the distance traveled, including velocities, is greater than the initial distance to the target, then the target has been reached if( this.distanceTraveled >= this.distanceToTarget ) { createParticles( this.tx, this.ty ); // remove the firework, use the index passed into the update function to determine which to remove fireworks.splice( index, 1 ); } else { // target not reached, keep traveling this.x += vx; this.y += vy; } } // draw firework Firework.prototype.draw = function() { ctx.beginPath(); // move to the last tracked coordinate in the set, then draw a line to the current x and y ctx.moveTo( this.coordinates[ this.coordinates.length - 1][ 0 ], this.coordinates[ this.coordinates.length - 1][ 1 ] ); ctx.lineTo( this.x, this.y ); ctx.strokeStyle = 'hsl(' + hue + ', 100%, ' + this.brightness + '%)'; ctx.stroke(); ctx.beginPath(); // draw the target for this firework with a pulsing circle ctx.arc( this.tx, this.ty, this.targetRadius, 0, Math.PI * 2 ); ctx.stroke(); } // create particle var Particle=function( x, y ) { this.x = x; this.y = y; // track the past coordinates of each particle to create a trail effect, increase the coordinate count to create more prominent trails this.coordinates = []; this.coordinateCount = 5; while( this.coordinateCount-- ) { this.coordinates.push( [ this.x, this.y ] ); } // set a random angle in all possible directions, in radians this.angle = random( 0, Math.PI * 2 ); this.speed = random( 1, 10 ); // friction will slow the particle down this.friction = 0.95; // gravity will be applied and pull the particle down this.gravity = 1; // set the hue to a random number +-20 of the overall hue variable this.hue = random( hue - 20, hue + 20 ); this.brightness = random( 50, 80 ); this.alpha = 1; // set how fast the particle fades out this.decay = random( 0.015, 0.03 ); } // update particle Particle.prototype.update = function( index ) { // remove last item in coordinates array this.coordinates.pop(); // add current coordinates to the start of the array this.coordinates.unshift( [ this.x, this.y ] ); // slow down the particle this.speed *= this.friction; // apply velocity this.x += Math.cos( this.angle ) * this.speed; this.y += Math.sin( this.angle ) * this.speed + this.gravity; // fade out the particle this.alpha -= this.decay; // remove the particle once the alpha is low enough, based on the passed in index if( this.alpha <= this.decay ) { particles.splice( index, 1 ); } } // draw particle Particle.prototype.draw = function() { ctx. beginPath(); // move to the last tracked coordinates in the set, then draw a line to the current x and y ctx.moveTo( this.coordinates[ this.coordinates.length - 1 ][ 0 ], this.coordinates[ this.coordinates.length - 1 ][ 1 ] ); ctx.lineTo( this.x, this.y ); ctx.strokeStyle = 'hsla(' + this.hue + ', 100%, ' + this.brightness + '%, ' + this.alpha + ')'; ctx.stroke(); } // create particle group/explosion var createParticles=function( x, y ) { // increase the particle count for a bigger explosion, beware of the canvas performance hit with the increased particles though var particleCount = 30; while( particleCount-- ) { particles.push( new Particle( x, y ) ); } } // main demo loop var loop=function() { // if(lib.config.coin_free_playpackconfig&&!_status.imchoosing){ // canvas.style.display='none'; // } // else{ // canvas.style.display=''; // } // this function will run endlessly with requestAnimationFrame if(!game.haveFun.list.firework.running){ canvas.width=cw; canvas.height=ch; return; } else{ requestAnimFrame( loop ); } // increase the hue to get different colored fireworks over time hue += 0.5; // normally, clearRect() would be used to clear the canvas // we want to create a trailing effect though // setting the composite operation to destination-out will allow us to clear the canvas at a specific opacity, rather than wiping it entirely ctx.globalCompositeOperation = 'destination-out'; // decrease the alpha property to create more prominent trails ctx.fillStyle = 'rgba(0, 0, 0, 0.5)'; ctx.fillRect( 0, 0, cw, ch ); // change the composite operation back to our main mode // lighter creates bright highlight points as the fireworks and particles overlap each other ctx.globalCompositeOperation = 'lighter'; // loop over each firework, draw it, update it var i = fireworks.length; while( i-- ) { fireworks[ i ].draw(); fireworks[ i ].update( i ); } // loop over each particle, draw it, update it var i = particles.length; while( i-- ) { particles[ i ].draw(); particles[ i ].update( i ); } // launch fireworks automatically to random coordinates, when the mouse isn't down if( timerTick >= timerTotal ) { if( !mousedown ) { // start the firework at the bottom middle of the screen, then set the random target coordinates, the random y coordinates will be set within the range of the top half of the screen fireworks.push( new Firework( cw / 2, ch, random( 0, cw ), random( 0, ch / 2 ) ) ); timerTick = 0; } } else { timerTick++; } // limit the rate at which fireworks get launched when mouse is down if( limiterTick >= limiterTotal ) { if( mousedown ) { // start the firework at the bottom middle of the screen, then set the current mouse coordinates as the target fireworks.push( new Firework( cw / 2, ch, mx, my ) ); limiterTick = 0; } } else { limiterTick++; } } if(lib.config.touchscreen){ ui.window.addEventListener( 'touchmove', function( e ) { mx = e.touches[0].clientX/game.documentZoom - canvas.offsetLeft; my = e.touches[0].clientY/game.documentZoom - canvas.offsetTop; }); ui.window.addEventListener( 'touchstart', function( e ) { mousedown = true; }); ui.window.addEventListener( 'touchend', function( e ) { mousedown = false; }); } else{ // mouse event bindings // update the mouse coordinates on mousemove ui.window.addEventListener( 'mousemove', function( e ) { mx = e.pageX/game.documentZoom - canvas.offsetLeft; my = e.pageY/game.documentZoom - canvas.offsetTop; }); // toggle mousedown state and prevent canvas from being selected ui.window.addEventListener( 'mousedown', function( e ) { e.preventDefault(); mousedown = true; }); ui.window.addEventListener( 'mouseup', function( e ) { e.preventDefault(); mousedown = false; }); } // once the window loads, we are ready for some fireworks! game.haveFun.fireworkLoop=loop; game.haveFun.fireworkStop=function(){ game.haveFun.list.firework.running=false; }, loop(); } } } }, help:{ '富甲天下':'