function dump(obj, name, pre, depth) {
depth = typeof depth !== "undefined" ? depth : 2;
if (typeof obj == "object" && depth > 0){
out += dump(obj[i], name, pre+"["+i+"] ", depth-1);
out += pre + (typeof obj) + ": " + obj;
console.log(name+"; "+out);
this.color = "rgba(255, 255, 192";
Particle.prototype.init = function (game){
this.drawer = game.drawer;
Particle.prototype.tick = function (){
this.dy -= this.game.grav + this.dy/15;
Particle.prototype.draw = function (){
this.drawer.fillStyle = this.color+", 1)";
this.drawer.fillStyle = this.color+", "+Math.min(this.life/30, 1)+")";
this.drawer.fillRect(this.x, this.y, 1, 1);
this.color = "rgba(0, 0, 192";
Shot.prototype.init = function (game){
this.drawer = game.drawer;
Shot.prototype.tick = function (){
var color = "rgba("+Math.ceil(255-200*Math.random())+", "+Math.ceil(255-200*Math.random())+", "+Math.ceil(255-200*Math.random());
for (var num=0;num<this.size*20;num++){
var partic = new Particle();
var t = 2*Math.PI*Math.random();
var r = this.size*3*Math.random()/1.5;
partic.dx = this.dx + r*Math.sin(t);
partic.dy = this.dy + r*Math.cos(t);
partic.life = 40 + 40*Math.random();
this.game.particles.push(partic);
if (true || Math.random() < 0.1){
var partic = new Particle();
var t = 2*Math.PI*Math.random();
var r = this.size*Math.random()/5;
partic.dx = this.dx + r*Math.sin(t);
partic.dy = this.dy + r*Math.cos(t);
partic.life = 20 + 20*Math.random();
partic.color = this.color;
this.game.particles.push(partic);
this.dy -= this.game.grav;
Shot.prototype.draw = function (){
if (this.draw_type == 1){
this.drawer.fillStyle = "rgba(255, 255, 180, 1)";
this.drawer.arc(this.x, this.y, 1.5, 0, 2 * Math.PI, false);
this.drawer.fillStyle = "rgba(255, 255, 255, 1)";
this.drawer.arc(this.x, this.y, 0.5, 0, 2 * Math.PI, false);
Shell.prototype.init = function (game){
this.drawer = game.drawer;
Shell.prototype.tick = function (){
var color = "rgba("+Math.ceil(255-200*Math.random())+", "+Math.ceil(255-200*Math.random())+", "+Math.ceil(255-200*Math.random());
for (var num=0;num<this.size*10;num++){
var partic = new Particle();
var t = 2*Math.PI*Math.random();
var r = this.size*3*Math.random()/1.5;
partic.dx = this.dx + r*Math.sin(t);
partic.dy = this.dy + r*Math.cos(t);
partic.life = 40 + 40*Math.random();
this.game.particles.push(partic);
var color = "rgba("+Math.ceil(255-200*Math.random())+", "+Math.ceil(255-200*Math.random())+", "+Math.ceil(255-200*Math.random());
for (var num=0;num<this.size*10;num++){
var partic = new Particle();
var t = 2*Math.PI*Math.random();
var r = this.size*3*Math.random()/1.5;
partic.dx = this.dx + r*Math.sin(t);
partic.dy = this.dy + r*Math.cos(t);
partic.life = 40 + 40*Math.random();
this.game.particles.push(partic);
var color = "rgba("+Math.ceil(255-200*Math.random())+", "+Math.ceil(255-200*Math.random())+", "+Math.ceil(255-200*Math.random());
for (var num=0;num<this.size*10;num++){
var partic = new Particle();
var t = 2*Math.PI*Math.random();
var r = this.size*3*Math.random()/1.5;
partic.dx = this.dx + r*Math.sin(t);
partic.dy = this.dy + r*Math.cos(t);
partic.life = 40 + 40*Math.random();
this.game.particles.push(partic);
var color = "rgba("+Math.ceil(255-200*Math.random())+", "+Math.ceil(255-200*Math.random())+", "+Math.ceil(255-200*Math.random());
for (var num=0;num<this.size*80;num++){
var partic = new Particle();
var t = 2*Math.PI*Math.random();
var r = this.size*6*Math.random()/1.5;
partic.dx = this.dx + r*Math.sin(t);
partic.dy = this.dy + r*Math.cos(t);
partic.life = 40 + 40*Math.random();
this.game.particles.push(partic);
for (var num=0;num<this.size;num++){
var t = 2*Math.PI*Math.random();
var r = this.size*Math.random()/2;
shot.dx = this.dx + r*Math.sin(t);
shot.dy = this.dy + r*Math.cos(t);
shot.life = 40+20*Math.random();
shot.type = Math.floor(1+Math.random()*2);
shot.draw_type = Math.floor(Math.random()*2);
shot.color = "rgba("+Math.ceil(255-200*Math.random())+", "+Math.ceil(255-200*Math.random())+", "+Math.ceil(255-200*Math.random());
this.game.shots.push(shot);
for (var num=0;num<this.size*2;num++){
var t = 2*Math.PI*Math.random();
var r = this.size*Math.random();
shot.dx = this.dx + r*Math.sin(t);
shot.dy = this.dy + r*Math.cos(t);
shot.life = 40+20*Math.random();
shot.type = Math.floor(1+Math.random()*2);
shot.draw_type = Math.floor(Math.random()*2);
shot.color = "rgba("+Math.ceil(255-200*Math.random())+", "+Math.ceil(255-200*Math.random())+", "+Math.ceil(255-200*Math.random());
this.game.shots.push(shot);
g.audio.play_sound("firework", "firework");
this.dy -= this.game.grav;
Shell.prototype.draw = function (){
if (this.draw_type == 0){
this.drawer.fillStyle = "rgb(255, 255, 192)";
this.drawer.fillRect(this.x, this.y, this.size/4, this.size/4);
window.AudioContext = window.AudioContext || window.webkitAudioContext;
this.context = new AudioContext();
this.channels['main'] = this.context.createGain();
this.channels['main'].connect(this.context.destination);
this.channels['main'].gain.value = 0.00;
this.channels['firework'] = this.context.createGain();
this.channels['firework'].connect(this.channels['main']);
this.channels['firework'].gain.value = 1.0;
this.channels['other'] = this.context.createGain();
this.channels['other'].connect(this.channels['main']);
this.channels['other'].gain.value = 0.3;
this.load_sound = function (url, name, num){
for (var a=0; a<num; a++){
this.buffers[name] = Array();
var request = new XMLHttpRequest();
request.open('GET', url.replace("_#", "_"+a), true);
request.responseType = 'arraybuffer';
request.onload = function() {
scope.context.decodeAudioData(this.response, function(buffer) {
scope.buffers[name].push(buffer);
this.play_sound = function (name, channel) {
channel = channel || "main";
var source = this.context.createBufferSource();
if (this.buffers[name].length > 1){
source.buffer = this.buffers[name][Math.floor(Math.random()*this.buffers[name].length)];
} else if (this.buffers[name].length){
source.buffer = this.buffers[name][0];
source.connect(this.channels[channel]);
source.start = source.noteOn;
this.shell_again = false;
this.particles = Array();
this.canvas = document.getElementById("canvas");
this.drawer = canvas.getContext("2d");
this.audio = new audio();
this.audio.load_sound("https://notomono.onnix.net/21410__heigh-hoo__blow.ogg", "launch", 1);
this.audio.load_sound("https://notomono.onnix.net/99200__dobroide__20100612-fireworks.wav", "firework", 1);
this.audio.load_sound("https://notomono.onnix.net/186958__readeonly__explosion7.wav", "pop", 1);
this.width = window.innerWidth;
this.height = window.innerHeight;
this.canvas.width = this.width;
this.canvas.height = this.height;
this.drawer.fillStyle = 'rgba(0, 0, 0)';
this.drawer.fillRect(0, 0, this.width, this.height);
this.start = function (){
setTimeout(function (){ g.tick() }, 16);
if (Math.random() < 0.02 || this.shell_again){
this.fire_shell(this.shell_again[0], this.shell_again[1]);
this.fire_shell((Math.random()+Math.random())/2*this.width, -Math.random()*this.height/180-this.height/200);
if (Math.random() < 0.02){
scope.audio.play_sound("launch", "other");
for(var i = this.particles.length-1; i>=0;i--){
if (!this.particles[i].tick()){
this.particles.splice(i, 1);
for(var i = this.shots.length-1; i>=0;i--){
if (!this.shots[i].tick()){
for(var i = this.shells.length-1; i>=0;i--){
if (!this.shells[i].tick()){
this.shells.splice(i, 1);
this.fire_shell = function (x, dy){
var t = (new Date()).getTime();
if (t-200 > this.last_shell){
var nshell = new Shell();
nshell.dx = Math.random()*.5-.25;
nshell.life = -nshell.dy*20;
nshell.size = nshell.life/20;
nshell.type = Math.floor(1+Math.random()*63);
this.shells.push(nshell);
scope.audio.play_sound("launch", "firework");
this.next_shell = [x, dy];
this.drawer.fillStyle = "rgba(0, 0, 0, .51)";
this.drawer.fillRect(0, 0, this.width, this.height);
this.set_audio = function (val){
this.audio.channels['main'].gain.value = val;
$("#audio_control").on("click touchend", function (){
if ($("#audio_control").hasClass("control_off")){
$("#audio_control").removeClass("control_off");
$("#audio_control").addClass("control_off");
$("#canvas").on("click touchstart", function (e){
if (e.originalEvent.touches && e.originalEvent.touches[0])
e = e.originalEvent.touches[0];
g.fire_shell(e.clientX, -Math.log(($(window).height()-e.clientY)/15)*1.8);