2024-04-15 16:50:54 +00:00
import { lib , game , ui , get , ai , _status } from "../../noname.js" ;
game . import ( "play" , function ( ) {
2017-04-15 00:25:50 +00:00
return {
2024-04-15 16:50:54 +00:00
name : "coin" ,
init : function ( ) {
if (
lib . config . mode != "chess" ||
get . config ( "chess_mode" ) != "leader"
) {
_status . coin = 0 ;
2015-12-28 07:30:15 +00:00
}
2017-04-15 00:25:50 +00:00
} ,
2024-04-15 16:50:54 +00:00
arenaReady : function ( ) {
if ( _status . video || _status . connectMode ) return ;
if (
lib . config . mode != "chess" ||
get . config ( "chess_mode" ) != "leader"
) {
2017-04-15 00:25:50 +00:00
var str ;
2024-04-15 16:50:54 +00:00
if ( lib . config . coin _display _playpackconfig == "text" ) {
str = "<span>" + lib . config . coin + "</span><span>金</span>" ;
} else {
str =
'<span style="position:absolute">㉤</span><span style="margin-left:18px;font-family:xinwei;line-height:10px">' +
lib . config . coin +
"</span>" ;
2017-04-15 00:25:50 +00:00
}
2024-04-15 16:50:54 +00:00
if ( lib . config . coin _canvas _playpackconfig ) {
ui . window . classList . add ( "canvas_top" ) ;
2017-04-15 00:25:50 +00:00
}
2024-04-15 16:50:54 +00:00
ui . coin = ui . create . system ( str , null , true ) ;
if ( lib . config . snowFall ) {
game . haveFun . list . snow . bought = true ;
setTimeout ( function ( ) {
2017-04-15 00:25:50 +00:00
game . haveFun . snow ( ) ;
2024-04-15 16:50:54 +00:00
} , 500 ) ;
2017-04-15 00:25:50 +00:00
}
2024-04-15 16:50:54 +00:00
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 == "开始" ) {
2017-04-15 00:25:50 +00:00
game . haveFun [ this . name ] ( ) ;
2024-04-15 16:50:54 +00:00
} 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 ;
2017-04-15 00:25:50 +00:00
}
}
2024-04-15 16:50:54 +00:00
ui . click . window ( ) ;
} ;
for ( var i in game . haveFun . list ) {
var item = game . haveFun . list [ i ] ;
uiintro . add (
'<div class="coin_buy">' +
item . name +
'<div class="menubutton">' +
item . cost +
"金</span></div></div>"
) ;
var buy =
uiintro . content . lastChild . lastChild . lastChild ;
if ( lib . config . coin < item . cost && ! item . bought ) {
buy . classList . add ( "disabled" ) ;
2015-12-30 04:00:49 +00:00
}
2024-04-15 16:50:54 +00:00
if ( item . bought ) {
if ( item . running ) {
buy . innerHTML = "停止" ;
if ( item . control ) {
var node = item . control ( ) ;
if ( node ) {
buy . parentNode . appendChild (
node ,
buy
) ;
}
2017-04-15 00:25:50 +00:00
}
2024-04-15 16:50:54 +00:00
} else {
buy . innerHTML = "开始" ;
2015-12-31 07:03:13 +00:00
}
}
2024-04-15 16:50:54 +00:00
buy . name = i ;
buy . content = item ;
buy . listen ( clickBuy ) ;
2015-12-28 09:08:52 +00:00
}
2015-12-30 04:00:49 +00:00
2024-04-15 16:50:54 +00:00
if ( ! game . phaseNumber && ! game . online ) {
uiintro . add ( "下注" ) ;
uiintro . add (
'<div class="coin_buy">本局获胜<div class="menubutton">20金</span></div></div>'
) ;
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 (
'<div class="coin_buy">本局获胜<div class="menubutton">已下注</span></div></div>'
) ;
2017-04-15 00:25:50 +00:00
}
2015-12-28 09:08:52 +00:00
2024-04-15 16:50:54 +00:00
uiintro . classList . add ( "noleave" ) ;
2015-12-30 04:00:49 +00:00
2024-04-15 16:50:54 +00:00
return uiintro ;
} ,
220 ,
400
) ;
2015-12-15 05:13:47 +00:00
}
2018-04-17 07:32:43 +00:00
} ,
2024-04-15 16:50:54 +00:00
game : {
changeCoin : function ( num ) {
if ( typeof num == "number" && ui . coin ) {
game . saveConfig ( "coin" , lib . config . coin + num ) ;
2017-04-15 00:25:50 +00:00
var str ;
2024-04-15 16:50:54 +00:00
if ( lib . config . coin _display _playpackconfig == "text" ) {
str =
"<span>" +
lib . config . coin +
"</span><span>金</span>" ;
} else {
str =
'<span style="position:absolute">㉤</span><span style="margin-left:18px;font-family:xinwei;line-height:10px">' +
lib . config . coin +
"</span>" ;
2017-04-15 00:25:50 +00:00
}
2024-04-15 16:50:54 +00:00
ui . coin . innerHTML = str ;
2017-04-15 00:25:50 +00:00
}
} ,
2024-04-15 16:50:54 +00:00
haveFun : {
list : {
firework : {
name : "烟花" ,
cost : 50 ,
2017-04-15 00:25:50 +00:00
} ,
2024-04-15 16:50:54 +00:00
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 = "小雪" ;
2017-04-15 00:25:50 +00:00
}
size . listen ( game . haveFun . snowSize ) ;
return size ;
2024-04-15 16:50:54 +00:00
} ,
2017-04-15 00:25:50 +00:00
} ,
2024-04-15 16:50:54 +00:00
star : {
name : "星云" ,
cost : 10 ,
} ,
blink : {
name : "闪烁" ,
cost : 10 ,
2017-04-15 00:25:50 +00:00
} ,
2015-12-30 04:00:49 +00:00
} ,
2024-04-15 16:50:54 +00:00
alwaysSnow : function ( ) {
game . saveConfig ( "snowFall" , ! lib . config . snowFall ) ;
2017-04-15 00:25:50 +00:00
game . reload ( ) ;
2015-12-30 04:00:49 +00:00
} ,
2024-04-15 16:50:54 +00:00
blink : function ( ) {
if ( game . haveFun . list . blink . running ) return ;
game . haveFun . list . blink . running = true ;
if ( game . haveFun . blinkLoop ) {
2017-04-15 00:25:50 +00:00
game . haveFun . blinkLoop ( ) ;
2024-04-15 16:50:54 +00:00
} else {
2017-04-15 00:25:50 +00:00
var canvas = document . createElement ( "canvas" ) ;
ui . window . appendChild ( canvas ) ;
2024-04-15 16:50:54 +00:00
canvas . classList . add ( "fun" ) ;
canvas . style . zIndex = 20 ;
2017-04-15 00:25:50 +00:00
var ctx = canvas . getContext ( "2d" ) ;
//Make the canvas occupy the full page
2024-04-15 16:50:54 +00:00
var W = ui . window . offsetWidth ,
H = ui . window . offsetHeight ;
2015-12-30 04:00:49 +00:00
canvas . width = W ;
canvas . height = H ;
2024-04-15 16:50:54 +00:00
lib . onresize . push ( function ( ) {
var W = ui . window . offsetWidth ,
H = ui . window . offsetHeight ;
2017-04-15 00:25:50 +00:00
canvas . width = W ;
canvas . height = H ;
} ) ;
2015-12-30 04:00:49 +00:00
2017-04-15 00:25:50 +00:00
var particles = [ ] ;
var mouse = { } ;
2015-12-30 04:00:49 +00:00
2017-04-15 00:25:50 +00:00
//Lets create some particles now
var particle _count = 25 ;
2015-12-30 04:00:49 +00:00
2017-04-15 00:25:50 +00:00
//finally some mouse tracking
2024-04-15 16:50:54 +00:00
ui . window . addEventListener ( "mousemove" , function ( e ) {
2017-04-15 00:25:50 +00:00
//since the canvas = full page the position of the mouse
//relative to the document will suffice
2024-04-15 16:50:54 +00:00
mouse . x = e . pageX / game . documentZoom ;
mouse . y = e . pageY / game . documentZoom ;
2017-04-15 00:25:50 +00:00
} ) ;
2024-04-15 16:50:54 +00:00
ui . window . addEventListener ( "touchmove" , function ( e ) {
mouse . x = e . touches [ 0 ] . clientX / game . documentZoom ;
mouse . y = e . touches [ 0 ] . clientY / game . documentZoom ;
2017-04-15 00:25:50 +00:00
} ) ;
2015-12-30 04:00:49 +00:00
2024-04-15 16:50:54 +00:00
var particle = function ( ) {
2017-04-15 00:25:50 +00:00
//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
2024-04-15 16:50:54 +00:00
this . speed = {
x : - 2.5 + Math . random ( ) * 5 ,
y : - 5 + Math . random ( ) * 10 ,
} ;
this . speed . x /= 4 ;
this . speed . y /= 4 ;
2017-04-15 00:25:50 +00:00
//location = mouse coordinates
//Now the flame follows the mouse coordinates
2024-04-15 16:50:54 +00:00
if ( mouse . x && mouse . y ) {
this . location = { x : mouse . x , y : mouse . y } ;
} else {
this . location = { x : W / 2 , y : H / 2 } ;
2017-04-15 00:25:50 +00:00
}
//radius range = 10-30
2024-04-15 16:50:54 +00:00
this . radius = 10 + Math . random ( ) * 20 ;
2017-04-15 00:25:50 +00:00
//life range = 20-30
2024-04-15 16:50:54 +00:00
this . radius /= 4 ;
this . life = 20 + Math . random ( ) * 10 ;
this . life *= 4 ;
2017-04-15 00:25:50 +00:00
this . remaining _life = this . life ;
//colors
2024-04-15 16:50:54 +00:00
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 ++ ) {
2017-04-15 00:25:50 +00:00
particles . push ( new particle ( ) ) ;
2015-12-30 04:00:49 +00:00
}
2024-04-15 16:50:54 +00:00
var draw = function ( ) {
if ( ! game . haveFun . list . blink . running ) {
canvas . width = W ;
canvas . height = H ;
2017-04-15 00:25:50 +00:00
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" ;
2024-04-15 16:50:54 +00:00
for ( var i = 0 ; i < particles . length ; i ++ ) {
2017-04-15 00:25:50 +00:00
var p = particles [ i ] ;
ctx . beginPath ( ) ;
//changing opacity according to the life.
//opacity goes to 0 at the end of life of a particle
2024-04-15 16:50:54 +00:00
p . opacity =
Math . round (
( p . remaining _life / p . life ) * 100
) / 100 ;
2017-04-15 00:25:50 +00:00
//a gradient instead of white fill
2024-04-15 16:50:54 +00:00
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)"
) ;
2017-04-15 00:25:50 +00:00
ctx . fillStyle = gradient ;
2024-04-15 16:50:54 +00:00
ctx . arc (
p . location . x ,
p . location . y ,
p . radius ,
Math . PI * 2 ,
false
) ;
2017-04-15 00:25:50 +00:00
ctx . fill ( ) ;
//lets move the particles
p . remaining _life -- ;
2024-04-15 16:50:54 +00:00
p . radius -= 0.2 ;
2017-04-15 00:25:50 +00:00
p . location . x += p . speed . x ;
p . location . y += p . speed . y ;
//regenerate particles
2024-04-15 16:50:54 +00:00
if ( p . remaining _life < 0 || p . radius < 0 ) {
2017-04-15 00:25:50 +00:00
//a brand new particle replacing the dead one
particles [ i ] = new particle ( ) ;
}
2015-12-30 04:00:49 +00:00
}
2017-04-15 00:25:50 +00:00
requestAnimationFrame ( draw ) ;
2024-04-15 16:50:54 +00:00
} ;
2015-12-30 04:00:49 +00:00
2017-04-15 00:25:50 +00:00
draw ( ) ;
2024-04-15 16:50:54 +00:00
game . haveFun . blinkLoop = draw ;
game . haveFun . blinkStop = function ( ) {
game . haveFun . list . blink . running = false ;
} ;
2015-12-30 04:00:49 +00:00
}
2017-04-15 00:25:50 +00:00
} ,
2024-04-15 16:50:54 +00:00
star : function ( ) {
if ( game . haveFun . list . star . running ) return ;
game . haveFun . list . star . running = true ;
if ( game . haveFun . starLoop ) {
2017-04-15 00:25:50 +00:00
game . haveFun . starLoop ( ) ;
2024-04-15 16:50:54 +00:00
} else {
2017-04-15 00:25:50 +00:00
//******************************************************
// Yet Another Particle Engine
var cos = Math . cos ,
2018-04-17 07:32:43 +00:00
sin = Math . sin ,
sqrt = Math . sqrt ,
abs = Math . abs ,
atan2 = Math . atan2 ,
log = Math . log ,
random = Math . random ,
PI = Math . PI ,
2024-04-15 16:50:54 +00:00
sqr = function ( v ) {
return v * v ;
} ,
2018-04-17 07:32:43 +00:00
particles = [ ] ,
drawScale = 1 ,
emitters = [ ] ,
2024-04-15 16:50:54 +00:00
forces = [ ] ,
2018-04-17 07:32:43 +00:00
collidedMass = 0 ,
maxParticles = 100 ,
emissionRate = 1 ,
2017-04-15 00:25:50 +00:00
minParticleSize = 2 ;
//-------------------------------------------------------
// Vectors, and not the kind you put stuff in
2024-04-15 16:50:54 +00:00
var Vector = function ( x , y , z ) {
this . x = x || 0 ;
this . y = y || 0 ;
this . z = z || 0 ;
} ;
2017-04-15 00:25:50 +00:00
Vector . prototype = {
2024-04-15 16:50:54 +00:00
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 ;
} ,
2017-04-15 00:25:50 +00:00
} ;
Vector . fromAngle = function ( angle , magnitude ) {
2024-04-15 16:50:54 +00:00
return new Vector (
magnitude * cos ( angle ) ,
magnitude * sin ( angle ) ,
magnitude * sin ( angle )
) ;
2017-04-15 00:25:50 +00:00
} ;
//******************************************************
// A thing with mass, position, and velocity - like your mom
2024-04-15 16:50:54 +00:00
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 ;
} ;
2017-04-15 00:25:50 +00:00
Particle . prototype . move = function ( ) {
2024-04-15 16:50:54 +00:00
this . vc . add ( this . ac ) ;
this . pos . add ( this . vc ) ;
2017-04-15 00:25:50 +00:00
} ;
Particle . prototype . reactToForces = function ( fields ) {
2024-04-15 16:50:54 +00:00
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 ;
2018-04-17 07:32:43 +00:00
}
2024-04-15 16:50:54 +00:00
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 ) ;
}
2018-04-17 07:32:43 +00:00
}
2024-04-15 16:50:54 +00:00
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;
// }
// }
2017-04-15 00:25:50 +00:00
} ;
Particle . prototype . grow = function ( another ) {
2024-04-15 16:50:54 +00:00
this . mass += another . mass ;
this . nova = true ;
another . alive = false ;
delete this . size ;
2017-04-15 00:25:50 +00:00
} ;
2024-04-15 16:50:54 +00:00
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 ;
2017-04-15 00:25:50 +00:00
} ;
2024-04-15 16:50:54 +00:00
Particle . prototype . forceBetween = function (
another ,
distance
) {
var distance = distance
? distance
: this . pos . distance ( another . pos ) ;
return ( this . mass * another . mass ) / sqr ( distance ) ;
2017-04-15 00:25:50 +00:00
} ;
//******************************************************
//This certainly doesn't *sub*mit to particles, that's for sure
2024-04-15 16:50:54 +00:00
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 (
2018-04-17 07:32:43 +00:00
new Vector (
2024-04-15 16:50:54 +00:00
~ ~ ( Math . random ( ) * 100 - 50 ) * drawScale ,
~ ~ ( Math . random ( ) * 100 - 50 ) * drawScale
)
) ;
var velocity = Vector . fromAngle ( angle , magnitude ) ;
return new Particle ( position , velocity ) ;
2017-04-15 00:25:50 +00:00
} ;
//******************************************************
// Use it, Luke
// to do collapse functionality into particle
2024-04-15 16:50:54 +00:00
var Force = function ( pos , m ) {
this . pos = pos ;
this . mass = m || 100 ;
} ;
2017-04-15 00:25:50 +00:00
Force . prototype . grow = function ( another ) {
2024-04-15 16:50:54 +00:00
this . mass += another . mass ;
this . burp = true ;
another . alive = false ;
2017-04-15 00:25:50 +00:00
} ;
2015-12-30 04:00:49 +00:00
2024-04-15 16:50:54 +00:00
var G = function ( data ) {
return 0.00674 * data ;
} ;
2015-12-30 04:00:49 +00:00
2017-04-15 00:25:50 +00:00
//******************************************************
2024-04-15 16:50:54 +00:00
var canvas = document . createElement ( "canvas" ) ;
canvas . classList . add ( "fun" ) ;
2017-04-15 00:25:50 +00:00
ui . window . appendChild ( canvas ) ;
2024-04-15 16:50:54 +00:00
var ctx = canvas . getContext ( "2d" ) ;
2015-12-30 04:00:49 +00:00
canvas . width = ui . window . offsetWidth ;
canvas . height = ui . window . offsetHeight ;
2017-04-15 00:25:50 +00:00
var canvasWidth = canvas . width ;
var canvasHeight = canvas . height ;
2024-04-15 16:50:54 +00:00
lib . onresize . push ( function ( ) {
2017-04-15 00:25:50 +00:00
canvas . width = ui . window . offsetWidth ;
canvas . height = ui . window . offsetHeight ;
canvasWidth = canvas . width ;
canvasHeight = canvas . height ;
} ) ;
2015-12-30 04:00:49 +00:00
2024-04-15 16:50:54 +00:00
var renderToCanvas = function (
width ,
height ,
renderFunction
) {
var buffer = document . createElement ( "canvas" ) ;
2018-04-17 07:32:43 +00:00
buffer . width = width ;
buffer . height = height ;
2024-04-15 16:50:54 +00:00
renderFunction ( buffer . getContext ( "2d" ) ) ;
2018-04-17 07:32:43 +00:00
return buffer ;
2017-04-15 00:25:50 +00:00
} ;
maxParticles = 500 ;
emissionRate = 1 ;
drawScale = 1.3 ;
minParticleSize = 2 ;
emitters = [
2024-04-15 16:50:54 +00:00
//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
// ),
2018-04-17 07:32:43 +00:00
// tl
2024-04-15 16:50:54 +00:00
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
// )
2017-04-15 00:25:50 +00:00
] ;
2024-04-15 16:50:54 +00:00
forces = [
new Force (
new Vector (
( canvasWidth / 2 ) * drawScale ,
( canvasHeight / 2 ) * drawScale
) ,
1800
) ,
2017-04-15 00:25:50 +00:00
] ;
2024-04-15 16:50:54 +00:00
var loop = function ( ) {
if ( ! game . haveFun . list . star . running ) {
canvas . width = ui . window . offsetWidth ;
canvas . height = ui . window . offsetHeight ;
2017-04-15 00:25:50 +00:00
return ;
}
clear ( ) ;
update ( ) ;
draw ( ) ;
queue ( ) ;
2024-04-15 16:50:54 +00:00
} ;
game . haveFun . starLoop = loop ;
game . haveFun . starStop = function ( ) {
game . haveFun . list . star . running = false ;
2017-04-15 00:25:50 +00:00
} ;
2015-12-30 04:00:49 +00:00
2024-04-15 16:50:54 +00:00
var clear = function ( ) {
ctx . clearRect ( 0 , 0 , canvas . width , canvas . height ) ;
} ;
2015-12-30 04:00:49 +00:00
2017-04-15 00:25:50 +00:00
var ctr = 0 ;
var c = [
2024-04-15 16:50:54 +00:00
"rgba(255,255,255," ,
"rgba(0,150,255," ,
"rgba(255,255,128," ,
"rgba(255,255,255," ,
2017-04-15 00:25:50 +00:00
] ;
2024-04-15 16:50:54 +00:00
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 ;
}
2018-04-17 07:32:43 +00:00
}
2024-04-15 16:50:54 +00:00
if ( particles . length > maxParticles ) return ;
_emit ( ) ;
} ;
2015-12-30 04:00:49 +00:00
2017-04-15 00:25:50 +00:00
var CLIPOFFSCREEN = 1 ,
2018-04-17 07:32:43 +00:00
BUFFEROFFSCREEN = 2 ,
LOOPSCREEN = 3 ;
2017-04-15 00:25:50 +00:00
2024-04-15 16:50:54 +00:00
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;
// }
} ;
2015-12-30 04:00:49 +00:00
2024-04-15 16:50:54 +00:00
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 ) ;
}
} ;
2015-12-30 04:00:49 +00:00
2017-04-15 00:25:50 +00:00
var offscreenCache = { } ;
2024-04-15 16:50:54 +00:00
var renderParticle = function ( p ) {
2018-04-17 07:32:43 +00:00
var position = p . pos ;
2024-04-15 16:50:54 +00:00
if ( ! p . size ) p . size = Math . floor ( p . mass / 100 ) ;
2018-04-17 07:32:43 +00:00
2024-04-15 16:50:54 +00:00
if ( ! p . opacity ) p . opacity = 0.05 ;
if ( p . velocity > 0 ) {
if ( p . opacity <= 0.18 ) p . opacity += 0.04 ;
2018-04-17 07:32:43 +00:00
}
2024-04-15 16:50:54 +00:00
if ( p . opacity > 0.08 ) p . opacity -= 0.02 ;
2018-04-17 07:32:43 +00:00
var actualSize = p . size / drawScale ;
2024-04-15 16:50:54 +00:00
actualSize =
actualSize < minParticleSize
? minParticleSize
: actualSize ;
if ( p . mass > 8 ) actualSize *= 2 ;
if ( p . nova ) {
actualSize *= 4 ;
p . nova = false ;
2018-04-17 07:32:43 +00:00
}
2024-04-15 16:50:54 +00:00
if ( p . doubleSize ) {
p . doubleSize = false ;
actualSize *= 2 ;
2018-04-17 07:32:43 +00:00
}
// if(p.supernova) {
// actualSize *= 6;
// opacity = 0.15;
// p.supernovaDur = p.supernovaDur - 1;
// if(p.supernovaDur === 0)
// p.supernova = false;
// }
2024-04-15 16:50:54 +00:00
var cacheKey =
actualSize + "_" + p . opacity + "_" + p . color ;
2018-04-17 07:32:43 +00:00
var cacheValue = offscreenCache [ cacheKey ] ;
2024-04-15 16:50:54 +00:00
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 ;
2018-04-17 07:32:43 +00:00
}
2024-04-15 16:50:54 +00:00
var posX = p . pos . x / drawScale ;
2018-04-17 07:32:43 +00:00
var posY = p . pos . y / drawScale ;
ctx . drawImage ( cacheValue , posX , posY ) ;
2024-04-15 16:50:54 +00:00
} ;
2015-12-30 04:00:49 +00:00
2017-04-15 00:25:50 +00:00
var fills = [
2024-04-15 16:50:54 +00:00
{ size : 15 , opacity : 1 } ,
{ size : 25 , opacity : 0.3 } ,
{ size : 50 , opacity : 0.1 } ,
] ;
2017-04-15 00:25:50 +00:00
2024-04-15 16:50:54 +00:00
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 ( ) ;
2018-04-17 07:32:43 +00:00
}
2017-04-15 00:25:50 +00:00
2024-04-15 16:50:54 +00:00
for ( var i = 0 ; i < particles . length ; i ++ ) {
var p = particles [ i ] ;
renderParticle ( p ) ;
}
} ;
2015-12-30 04:00:49 +00:00
2024-04-15 16:50:54 +00:00
var draw = function ( ) {
renderScene ( ctx ) ;
} ;
2015-12-30 04:00:49 +00:00
2024-04-15 16:50:54 +00:00
var update = function ( ) {
addNewParticles ( ) ;
plotParticles ( canvas . width , canvas . height ) ;
} ;
2015-12-30 04:00:49 +00:00
2024-04-15 16:50:54 +00:00
var queue = function ( ) {
window . requestAnimationFrame ( loop ) ;
} ;
2015-12-30 04:00:49 +00:00
2017-04-15 00:25:50 +00:00
loop ( ) ;
2015-12-28 09:08:52 +00:00
}
2017-04-15 00:25:50 +00:00
} ,
2024-04-15 16:50:54 +00:00
snow : function ( ) {
game . haveFun . list . snow . running = true ;
if ( game . haveFun . snowStart ) {
2017-04-15 00:25:50 +00:00
game . haveFun . snowStart ( ) ;
2024-04-15 16:50:54 +00:00
} else {
2017-04-15 00:25:50 +00:00
/ *
2024-04-15 16:50:54 +00:00
* 自由下雪 snowFall
* author : xuanfeng
* time : 2014 - 01 - 11
* /
2017-04-15 00:25:50 +00:00
// 控制下雪
var canvas ;
2024-04-15 16:50:54 +00:00
var snowFall = function ( snow ) {
2017-04-15 00:25:50 +00:00
// 可配置属性
snow = snow || { } ;
2024-04-15 16:50:54 +00:00
this . maxFlake = snow . maxFlake || 200 ; //最多片数
this . flakeSize = snow . flakeSize || 10 ; //雪花形状
this . fallSpeed = snow . fallSpeed || 2 ; //坠落速度
this . status = 0 ; //0-初始化、1-开始下雪、2-停止下雪、3-暂停下雪、4-继续下雪
} ;
2015-12-28 09:08:52 +00:00
2017-04-15 00:25:50 +00:00
// 兼容写法
2024-04-15 16:50:54 +00:00
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 ;
2017-04-15 00:25:50 +00:00
// 开始下雪
2024-04-15 16:50:54 +00:00
snowFall . prototype . start = function ( ) {
if ( this . status == 1 || this . status == 4 ) {
2017-04-15 00:25:50 +00:00
// 已经在下雪则不作处理
return false ;
}
this . status = 1 ;
// 创建画布
snowCanvas . apply ( this ) ;
// 创建雪花形状
createFlakes . apply ( this ) ;
// 画雪
2024-04-15 16:50:54 +00:00
drawSnow . apply ( this ) ;
} ;
2015-12-28 09:08:52 +00:00
2017-04-15 00:25:50 +00:00
// 停止下雪
2024-04-15 16:50:54 +00:00
snowFall . prototype . stop = function ( ) {
if (
this . status == 2 ||
this . status == 0 ||
! this . canvas
) {
2017-04-15 00:25:50 +00:00
return false ;
}
// 停止动画循环
this . pause ( ) ;
this . status = 2 ;
// 删除画布
this . canvas . parentNode . removeChild ( this . canvas ) ;
this . canvas = null ;
2024-04-15 16:50:54 +00:00
} ;
2015-12-28 09:08:52 +00:00
2017-04-15 00:25:50 +00:00
// 暂停下雪
2024-04-15 16:50:54 +00:00
snowFall . prototype . pause = function ( ) {
if ( this . status == 3 ) {
2017-04-15 00:25:50 +00:00
return false ;
}
this . status = 3 ;
2024-04-15 16:50:54 +00:00
cancelAnimationFrame ( this . loop ) ;
2017-04-15 00:25:50 +00:00
} ;
// 继续下雪
2024-04-15 16:50:54 +00:00
snowFall . prototype . resume = function ( ) {
if ( this . status == 3 && this . canvas ) {
2017-04-15 00:25:50 +00:00
this . status = 4 ;
// 动画的计时控制
2024-04-15 16:50:54 +00:00
var that = this ;
this . loop = requestAnimationFrame ( function ( ) {
drawSnow . apply ( that ) ;
2017-04-15 00:25:50 +00:00
} ) ;
}
} ;
2015-12-28 09:08:52 +00:00
2017-04-15 00:25:50 +00:00
// 创建画布
2024-04-15 16:50:54 +00:00
var snowCanvas = function ( ) {
2017-04-15 00:25:50 +00:00
// 添加Dom结点
var snowcanvas = document . createElement ( "canvas" ) ;
2024-04-15 16:50:54 +00:00
snowcanvas . classList . add ( "fun" ) ;
2017-04-15 00:25:50 +00:00
snowcanvas . id = "snowfall" ;
ui . window . appendChild ( snowcanvas ) ;
2024-04-15 16:50:54 +00:00
canvas = snowcanvas ;
2017-04-15 00:25:50 +00:00
this . canvas = snowcanvas ;
this . ctx = snowcanvas . getContext ( "2d" ) ;
// 窗口大小改变的处理
2024-04-15 16:50:54 +00:00
lib . onresize . push ( function ( ) {
2017-04-15 00:25:50 +00:00
snowcanvas . width = ui . window . offsetWidth ;
2024-04-15 16:50:54 +00:00
snowcanvas . height = ui . window . offsetHeight ;
2017-04-15 00:25:50 +00:00
} ) ;
snowcanvas . width = ui . window . offsetWidth ;
snowcanvas . height = ui . window . offsetHeight ;
2024-04-15 16:50:54 +00:00
} ;
2015-12-28 09:08:52 +00:00
2017-04-15 00:25:50 +00:00
// 雪运动对象
2024-04-15 16:50:54 +00:00
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 ; //步数
} ;
2015-12-28 09:08:52 +00:00
2024-04-15 16:50:54 +00:00
flakeMove . prototype . update = function ( ) {
2017-04-15 00:25:50 +00:00
var x = this . x ,
2018-04-17 07:32:43 +00:00
y = this . y ;
2015-12-28 09:08:52 +00:00
2017-04-15 00:25:50 +00:00
// 左右摆动(余弦)
this . velX *= 0.98 ;
if ( this . velY <= this . speed ) {
2024-04-15 16:50:54 +00:00
this . velY = this . speed ;
2017-04-15 00:25:50 +00:00
}
2024-04-15 16:50:54 +00:00
this . velX +=
Math . cos ( ( this . step += 0.05 ) ) * this . stepSize ;
2015-12-28 09:08:52 +00:00
2017-04-15 00:25:50 +00:00
this . y += this . velY ;
this . x += this . velX ;
// 飞出边界的处理
2024-04-15 16:50:54 +00:00
if (
this . x >= canvas . width ||
this . x <= 0 ||
this . y >= canvas . height ||
this . y <= 0
) {
this . reset ( canvas . width , canvas . height ) ;
2017-04-15 00:25:50 +00:00
}
} ;
// 飞出边界-放置最顶端继续坠落
2024-04-15 16:50:54 +00:00
flakeMove . prototype . reset = function ( width , height ) {
2017-04-15 00:25:50 +00:00
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 ;
} ;
// 渲染雪花-随机形状
2024-04-15 16:50:54 +00:00
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)"
) ;
2017-04-15 00:25:50 +00:00
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 ( ) ;
} ;
// 创建雪花-定义形状
2024-04-15 16:50:54 +00:00
var createFlakes = function ( ) {
2017-04-15 00:25:50 +00:00
var maxFlake = this . maxFlake ,
2024-04-15 16:50:54 +00:00
flakes = ( this . flakes = [ ] ) ,
2017-04-15 00:25:50 +00:00
canvas = this . canvas ;
for ( var i = 0 ; i < 200 ; i ++ ) {
2024-04-15 16:50:54 +00:00
flakes . push (
new flakeMove (
canvas . width ,
canvas . height ,
this . flakeSize ,
this . fallSpeed
)
) ;
2017-04-15 00:25:50 +00:00
}
2024-04-15 16:50:54 +00:00
} ;
2015-12-28 09:08:52 +00:00
2017-04-15 00:25:50 +00:00
// 画雪
2024-04-15 16:50:54 +00:00
var drawSnow = function ( ) {
2017-04-15 00:25:50 +00:00
var maxFlake = this . maxFlake ,
flakes = this . flakes ;
2024-04-15 16:50:54 +00:00
var ctx = this . ctx ,
canvas = this . canvas ,
that = this ;
2017-04-15 00:25:50 +00:00
// 清空雪花
ctx . clearRect ( 0 , 0 , canvas . width , canvas . height ) ;
for ( var e = 0 ; e < maxFlake ; e ++ ) {
flakes [ e ] . update ( ) ;
flakes [ e ] . render ( ctx ) ;
}
// 一帧一帧的画
2024-04-15 16:50:54 +00:00
this . loop = requestAnimationFrame ( function ( ) {
2017-04-15 00:25:50 +00:00
drawSnow . apply ( that ) ;
} ) ;
2024-04-15 16:50:54 +00:00
} ;
2015-12-28 09:08:52 +00:00
2017-04-15 00:25:50 +00:00
// 调用及控制方法
var snow = new snowFall ( ) ;
2024-04-15 16:50:54 +00:00
game . haveFun . snowStart = function ( ) {
2017-04-15 00:25:50 +00:00
snow . start ( ) ;
2024-04-15 16:50:54 +00:00
} ;
game . haveFun . snowStop = function ( ) {
game . haveFun . list . snow . running = false ;
2017-04-15 00:25:50 +00:00
snow . stop ( ) ;
2024-04-15 16:50:54 +00:00
} ;
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 = "大雪" ;
2017-04-15 00:25:50 +00:00
}
2024-04-15 16:50:54 +00:00
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 = "小雪" ;
2017-04-15 00:25:50 +00:00
}
2024-04-15 16:50:54 +00:00
game . saveConfig ( "coinSnowSize" , false ) ;
2017-04-15 00:25:50 +00:00
}
2024-04-15 16:50:54 +00:00
} ;
if ( lib . config . coinSnowSize ) {
2017-04-15 00:25:50 +00:00
game . haveFun . snowSize ( ) ;
2015-12-30 04:00:49 +00:00
}
2017-04-15 00:25:50 +00:00
snow . start ( ) ;
2015-12-30 04:00:49 +00:00
}
2017-04-15 00:25:50 +00:00
} ,
2024-04-15 16:50:54 +00:00
firework : function ( ) {
if ( game . haveFun . list . firework . running ) return ;
game . haveFun . list . firework . running = true ;
if ( game . haveFun . fireworkLoop ) {
2017-04-15 00:25:50 +00:00
game . haveFun . fireworkLoop ( ) ;
2024-04-15 16:50:54 +00:00
} else {
2017-04-15 00:25:50 +00:00
// 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
2024-04-15 16:50:54 +00:00
var requestAnimFrame = ( function ( ) {
return (
window . requestAnimationFrame ||
window . webkitRequestAnimationFrame ||
window . mozRequestAnimationFrame ||
function ( callback ) {
window . setTimeout ( callback , 1000 / 60 ) ;
}
) ;
2017-04-15 00:25:50 +00:00
} ) ( ) ;
// now we will setup our basic variables for the demo
2024-04-15 16:50:54 +00:00
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 ;
2017-04-15 00:25:50 +00:00
// set canvas dimensions
2015-12-28 07:30:15 +00:00
canvas . width = cw ;
canvas . height = ch ;
2017-04-15 00:25:50 +00:00
ui . window . appendChild ( canvas ) ;
2024-04-15 16:50:54 +00:00
canvas . classList . add ( "fun" ) ;
lib . onresize . push ( function ( ) {
cw = ui . window . offsetWidth ;
ch = ui . window . offsetHeight ;
2017-04-15 00:25:50 +00:00
canvas . width = cw ;
canvas . height = ch ;
} ) ;
2015-12-28 07:30:15 +00:00
2017-04-15 00:25:50 +00:00
// now we are going to setup our function placeholders for the entire demo
2015-12-28 07:30:15 +00:00
2017-04-15 00:25:50 +00:00
// get a random number within a range
2024-04-15 16:50:54 +00:00
var random = function ( min , max ) {
return Math . random ( ) * ( max - min ) + min ;
} ;
2015-12-28 07:30:15 +00:00
2017-04-15 00:25:50 +00:00
// calculate the distance between two points
2024-04-15 16:50:54 +00:00
var calculateDistance = function ( p1x , p1y , p2x , p2y ) {
2017-04-15 00:25:50 +00:00
var xDistance = p1x - p2x ,
2024-04-15 16:50:54 +00:00
yDistance = p1y - p2y ;
return Math . sqrt (
Math . pow ( xDistance , 2 ) + Math . pow ( yDistance , 2 )
) ;
} ;
2015-12-28 07:30:15 +00:00
2017-04-15 00:25:50 +00:00
// create firework
2024-04-15 16:50:54 +00:00
var Firework = function ( sx , sy , tx , ty ) {
2017-04-15 00:25:50 +00:00
// 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
2024-04-15 16:50:54 +00:00
this . distanceToTarget = calculateDistance (
sx ,
sy ,
tx ,
ty
) ;
2017-04-15 00:25:50 +00:00
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
2024-04-15 16:50:54 +00:00
while ( this . coordinateCount -- ) {
this . coordinates . push ( [ this . x , this . y ] ) ;
2017-04-15 00:25:50 +00:00
}
2024-04-15 16:50:54 +00:00
this . angle = Math . atan2 ( ty - sy , tx - sx ) ;
2017-04-15 00:25:50 +00:00
this . speed = 2 ;
this . acceleration = 1.05 ;
2024-04-15 16:50:54 +00:00
this . brightness = random ( 50 , 70 ) ;
2017-04-15 00:25:50 +00:00
// circle target indicator radius
2015-12-28 07:30:15 +00:00
this . targetRadius = 1 ;
2024-04-15 16:50:54 +00:00
} ;
2015-12-28 07:30:15 +00:00
2017-04-15 00:25:50 +00:00
// update firework
2024-04-15 16:50:54 +00:00
Firework . prototype . update = function ( index ) {
2017-04-15 00:25:50 +00:00
// remove last item in coordinates array
this . coordinates . pop ( ) ;
// add current coordinates to the start of the array
2024-04-15 16:50:54 +00:00
this . coordinates . unshift ( [ this . x , this . y ] ) ;
2017-04-15 00:25:50 +00:00
// cycle the circle target indicator radius
2024-04-15 16:50:54 +00:00
if ( this . targetRadius < 8 ) {
2017-04-15 00:25:50 +00:00
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
2024-04-15 16:50:54 +00:00
var vx = Math . cos ( this . angle ) * this . speed ,
vy = Math . sin ( this . angle ) * this . speed ;
2017-04-15 00:25:50 +00:00
// how far will the firework have traveled with velocities applied?
2024-04-15 16:50:54 +00:00
this . distanceTraveled = calculateDistance (
this . sx ,
this . sy ,
this . x + vx ,
this . y + vy
) ;
2017-04-15 00:25:50 +00:00
// if the distance traveled, including velocities, is greater than the initial distance to the target, then the target has been reached
2024-04-15 16:50:54 +00:00
if (
this . distanceTraveled >= this . distanceToTarget
) {
createParticles ( this . tx , this . ty ) ;
2017-04-15 00:25:50 +00:00
// remove the firework, use the index passed into the update function to determine which to remove
2024-04-15 16:50:54 +00:00
fireworks . splice ( index , 1 ) ;
2017-04-15 00:25:50 +00:00
} else {
// target not reached, keep traveling
this . x += vx ;
this . y += vy ;
}
2024-04-15 16:50:54 +00:00
} ;
2015-12-28 07:30:15 +00:00
2017-04-15 00:25:50 +00:00
// draw firework
2024-04-15 16:50:54 +00:00
Firework . prototype . draw = function ( ) {
2017-04-15 00:25:50 +00:00
ctx . beginPath ( ) ;
// move to the last tracked coordinate in the set, then draw a line to the current x and y
2024-04-15 16:50:54 +00:00
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 +
"%)" ;
2017-04-15 00:25:50 +00:00
ctx . stroke ( ) ;
2015-12-28 07:30:15 +00:00
2017-04-15 00:25:50 +00:00
ctx . beginPath ( ) ;
// draw the target for this firework with a pulsing circle
2024-04-15 16:50:54 +00:00
ctx . arc (
this . tx ,
this . ty ,
this . targetRadius ,
0 ,
Math . PI * 2
) ;
2017-04-15 00:25:50 +00:00
ctx . stroke ( ) ;
2024-04-15 16:50:54 +00:00
} ;
2015-12-28 07:30:15 +00:00
2017-04-15 00:25:50 +00:00
// create particle
2024-04-15 16:50:54 +00:00
var Particle = function ( x , y ) {
2017-04-15 00:25:50 +00:00
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 ;
2024-04-15 16:50:54 +00:00
while ( this . coordinateCount -- ) {
this . coordinates . push ( [ this . x , this . y ] ) ;
2017-04-15 00:25:50 +00:00
}
// set a random angle in all possible directions, in radians
2024-04-15 16:50:54 +00:00
this . angle = random ( 0 , Math . PI * 2 ) ;
this . speed = random ( 1 , 10 ) ;
2017-04-15 00:25:50 +00:00
// 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
2024-04-15 16:50:54 +00:00
this . hue = random ( hue - 20 , hue + 20 ) ;
this . brightness = random ( 50 , 80 ) ;
2017-04-15 00:25:50 +00:00
this . alpha = 1 ;
// set how fast the particle fades out
2024-04-15 16:50:54 +00:00
this . decay = random ( 0.015 , 0.03 ) ;
} ;
2015-12-28 07:30:15 +00:00
2017-04-15 00:25:50 +00:00
// update particle
2024-04-15 16:50:54 +00:00
Particle . prototype . update = function ( index ) {
2017-04-15 00:25:50 +00:00
// remove last item in coordinates array
this . coordinates . pop ( ) ;
// add current coordinates to the start of the array
2024-04-15 16:50:54 +00:00
this . coordinates . unshift ( [ this . x , this . y ] ) ;
2017-04-15 00:25:50 +00:00
// slow down the particle
this . speed *= this . friction ;
// apply velocity
2024-04-15 16:50:54 +00:00
this . x += Math . cos ( this . angle ) * this . speed ;
this . y +=
Math . sin ( this . angle ) * this . speed +
this . gravity ;
2017-04-15 00:25:50 +00:00
// fade out the particle
this . alpha -= this . decay ;
// remove the particle once the alpha is low enough, based on the passed in index
2024-04-15 16:50:54 +00:00
if ( this . alpha <= this . decay ) {
particles . splice ( index , 1 ) ;
2017-04-15 00:25:50 +00:00
}
2024-04-15 16:50:54 +00:00
} ;
2015-12-28 07:30:15 +00:00
2017-04-15 00:25:50 +00:00
// draw particle
2024-04-15 16:50:54 +00:00
Particle . prototype . draw = function ( ) {
ctx . beginPath ( ) ;
2017-04-15 00:25:50 +00:00
// move to the last tracked coordinates in the set, then draw a line to the current x and y
2024-04-15 16:50:54 +00:00
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 +
")" ;
2017-04-15 00:25:50 +00:00
ctx . stroke ( ) ;
2024-04-15 16:50:54 +00:00
} ;
2015-12-28 07:30:15 +00:00
2017-04-15 00:25:50 +00:00
// create particle group/explosion
2024-04-15 16:50:54 +00:00
var createParticles = function ( x , y ) {
2017-04-15 00:25:50 +00:00
// increase the particle count for a bigger explosion, beware of the canvas performance hit with the increased particles though
var particleCount = 30 ;
2024-04-15 16:50:54 +00:00
while ( particleCount -- ) {
particles . push ( new Particle ( x , y ) ) ;
2017-04-15 00:25:50 +00:00
}
2024-04-15 16:50:54 +00:00
} ;
2015-12-28 07:30:15 +00:00
2017-04-15 00:25:50 +00:00
// main demo loop
2024-04-15 16:50:54 +00:00
var loop = function ( ) {
2017-04-15 00:25:50 +00:00
// if(lib.config.coin_free_playpackconfig&&!_status.imchoosing){
// canvas.style.display='none';
// }
// else{
// canvas.style.display='';
// }
// this function will run endlessly with requestAnimationFrame
2024-04-15 16:50:54 +00:00
if ( ! game . haveFun . list . firework . running ) {
canvas . width = cw ;
canvas . height = ch ;
2017-04-15 00:25:50 +00:00
return ;
2024-04-15 16:50:54 +00:00
} else {
requestAnimFrame ( loop ) ;
2017-04-15 00:25:50 +00:00
}
2015-12-28 07:30:15 +00:00
2017-04-15 00:25:50 +00:00
// 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
2024-04-15 16:50:54 +00:00
ctx . globalCompositeOperation = "destination-out" ;
2017-04-15 00:25:50 +00:00
// decrease the alpha property to create more prominent trails
2024-04-15 16:50:54 +00:00
ctx . fillStyle = "rgba(0, 0, 0, 0.5)" ;
ctx . fillRect ( 0 , 0 , cw , ch ) ;
2017-04-15 00:25:50 +00:00
// change the composite operation back to our main mode
// lighter creates bright highlight points as the fireworks and particles overlap each other
2024-04-15 16:50:54 +00:00
ctx . globalCompositeOperation = "lighter" ;
2017-04-15 00:25:50 +00:00
// loop over each firework, draw it, update it
var i = fireworks . length ;
2024-04-15 16:50:54 +00:00
while ( i -- ) {
fireworks [ i ] . draw ( ) ;
fireworks [ i ] . update ( i ) ;
2015-12-28 07:30:15 +00:00
}
2017-04-15 00:25:50 +00:00
// loop over each particle, draw it, update it
var i = particles . length ;
2024-04-15 16:50:54 +00:00
while ( i -- ) {
particles [ i ] . draw ( ) ;
particles [ i ] . update ( i ) ;
2017-04-15 00:25:50 +00:00
}
// launch fireworks automatically to random coordinates, when the mouse isn't down
2024-04-15 16:50:54 +00:00
if ( timerTick >= timerTotal ) {
if ( ! mousedown ) {
2017-04-15 00:25:50 +00:00
// 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
2024-04-15 16:50:54 +00:00
fireworks . push (
new Firework (
cw / 2 ,
ch ,
random ( 0 , cw ) ,
random ( 0 , ch / 2 )
)
) ;
2017-04-15 00:25:50 +00:00
timerTick = 0 ;
}
} else {
timerTick ++ ;
}
// limit the rate at which fireworks get launched when mouse is down
2024-04-15 16:50:54 +00:00
if ( limiterTick >= limiterTotal ) {
if ( mousedown ) {
2017-04-15 00:25:50 +00:00
// start the firework at the bottom middle of the screen, then set the current mouse coordinates as the target
2024-04-15 16:50:54 +00:00
fireworks . push (
new Firework ( cw / 2 , ch , mx , my )
) ;
2017-04-15 00:25:50 +00:00
limiterTick = 0 ;
}
} else {
limiterTick ++ ;
2015-12-28 07:30:15 +00:00
}
2024-04-15 16:50:54 +00:00
} ;
2015-12-28 07:30:15 +00:00
2024-04-15 16:50:54 +00:00
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 {
2017-04-15 00:25:50 +00:00
// mouse event bindings
// update the mouse coordinates on mousemove
2024-04-15 16:50:54 +00:00
ui . window . addEventListener (
"mousemove" ,
function ( e ) {
mx =
e . pageX / game . documentZoom -
canvas . offsetLeft ;
my =
e . pageY / game . documentZoom -
canvas . offsetTop ;
}
) ;
2015-12-28 07:30:15 +00:00
2017-04-15 00:25:50 +00:00
// toggle mousedown state and prevent canvas from being selected
2024-04-15 16:50:54 +00:00
ui . window . addEventListener (
"mousedown" ,
function ( e ) {
e . preventDefault ( ) ;
mousedown = true ;
}
) ;
2015-12-28 07:30:15 +00:00
2024-04-15 16:50:54 +00:00
ui . window . addEventListener ( "mouseup" , function ( e ) {
2017-04-15 00:25:50 +00:00
e . preventDefault ( ) ;
mousedown = false ;
} ) ;
}
2015-12-28 07:30:15 +00:00
2017-04-15 00:25:50 +00:00
// once the window loads, we are ready for some fireworks!
2024-04-15 16:50:54 +00:00
game . haveFun . fireworkLoop = loop ;
( game . haveFun . fireworkStop = function ( ) {
game . haveFun . list . firework . running = false ;
} ) ,
loop ( ) ;
2017-04-15 00:25:50 +00:00
}
2024-04-15 16:50:54 +00:00
} ,
} ,
} ,
help : {
富甲天下 :
"<ul><li>每完成一次对局,可获得一定数量的金币" +
"<li>战斗胜利可额外获得20金币, 每杀死一个敌人可获得10金币( 托管无效) " +
"<li>使用的武将越强,获得的金币数越少" +
"<li>执行以下操作时,将扣除金币:<ul><li>作弊: 20金币<li>换将卡: 3金币<li>" +
"自由选将: 10金币<li>手气卡: 3金币<li>换人: 10金币</ul>" +
"<li>金币可用于购买烟花等游戏特效(点击右上角的金币按钮)" +
"<li>修改金币:<br>game.changCoin" +
"<li>默认下雪:<br>game.haveFun.alwaysSnow" ,
2017-04-15 00:25:50 +00:00
} ,
} ;
2017-04-14 23:35:56 +00:00
} ) ;