Give us some feedback, any feedback, we just want feedback!

Your name:

Your email:

Your feedback:

 

Firework test

Project Description:

Created: 10 Years ago

Last edited: 5 Years ago

Branch Project

Project name:

Project description:

 

Firework test
HTML <body>
1
<canvas id="canvas">Canvas not supported</canvas>
2
<div id="audio_control" class="control_off" onclick="">Audio</div>
3
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
 
CSS <style>
1
body {
2
  margin: 0;
3
  /*background: black;*/
4
}
5
 
6
canvas {
7
  cursor: crosshair;
8
  display: block;
9
  z-index:0;
10
}
11
 
12
#audio_control{
13
  position: absolute;
14
  top:5px;
15
  right:5px;
16
  z-index:1;
17
  color: white;
18
}
19
 
20
.control_off{
21
  text-decoration: line-through;
22
}
 
JS <script> (jQuery supported)
1
"use strict"
2
 
3
function dump(obj, name, pre, depth) {
4
  pre = pre || "";
5
  name = name || "";
6
  depth = typeof depth !== "undefined" ? depth : 2;
7
  var out = "";
8
  if (typeof obj == "object" && depth > 0){
9
    var prop = false;
10
    for (var i in obj) {
11
      prop = true;
12
      out += dump(obj[i], name, pre+"["+i+"] ", depth-1);
13
    }
14
    if (prop)
15
      return out;
16
    else
17
      out = "{}";
18
  } else {
19
    out += pre + (typeof obj) + ": " + obj;
20
  }
21
  console.log(name+"; "+out);
22
}
23
 
24
function Particle(){
25
  var scope = this;
26
  this.game;
27
  this.drawer;
28
  
29
  this.x = 0;
30
  this.y = 0;
31
  
32
  this.dx = 0;
33
  this.dy = 0;
34
  
35
  this.life = 80;
36
  this.type = 1;
37
  
38
  this.color = "rgba(255, 255, 192";
39
}
40
 
41
Particle.prototype.init = function (game){
42
  this.game = game;
43
  this.drawer = game.drawer;
44
}
45
 
46
Particle.prototype.tick = function (){
47
  --this.life;
48
  if (this.life < 0){
49
    return false;
50
  }
51
  this.x += this.dx;
52
  this.y += this.dy;
53
  this.dy -= this.game.grav + this.dy/15;
54
  this.dx -= this.dx/15;
55
  this.draw();
56
  return true;
57
}
58
  
59
Particle.prototype.draw = function (){
60
  if (this.type == 1){
61
    //dump(this.color);
62
    if (this.life > 30){
63
      this.drawer.fillStyle = this.color+", 1)";
64
    } else {
65
      this.drawer.fillStyle = this.color+", "+Math.min(this.life/30, 1)+")";
66
    }
67
  }
68
  this.drawer.fillRect(this.x, this.y, 1, 1);
69
}
70
 
71
function Shot(){
72
  var scope = this;
73
  this.game;
74
  this.drawer;
75
  
76
  this.x = 0;
77
  this.y = 0;
78
  
79
  this.dx = 0;
80
  this.dy = 0;
81
  
82
  this.life = 0;
83
  this.type = 1;
84
  this.size = 0;
85
  this.draw_type = 1;
86
  
87
  this.color = "rgba(0, 0, 192";
88
}
89
 
90
Shot.prototype.init = function (game){
91
  this.game = game;
92
  this.drawer = game.drawer;
93
}
94
 
95
Shot.prototype.tick = function (){
96
  --this.life;
97
  if (this.life < 0){
98
    if (this.type & 1){// basic burst
99
      var color = "rgba("+Math.ceil(255-200*Math.random())+", "+Math.ceil(255-200*Math.random())+", "+Math.ceil(255-200*Math.random());
100
      for (var num=0;num<this.size*20;num++){
101
        var partic = new Particle();
102
        partic.init(this.game);
103
        partic.x = this.x;
104
        partic.y = this.y;
105
        var t = 2*Math.PI*Math.random();
106
        var r = this.size*3*Math.random()/1.5;
107
        partic.dx = this.dx + r*Math.sin(t);
108
        partic.dy = this.dy + r*Math.cos(t);
109
        partic.life = 40 + 40*Math.random();
110
        partic.color = color;
111
        this.game.particles.push(partic);
112
      }
113
    }
114
    /*setTimeout(function (){
115
        scope.game.audio.play_sound("pop", "firework");
116
      }, 500);*/
117
    return false;
118
  } else {
119
    if (this.type & 2){//streamer
120
      if (true || Math.random() < 0.1){
121
        var partic = new Particle();
122
        partic.init(this.game);
123
        partic.x = this.x;
124
        partic.y = this.y;
125
        var t = 2*Math.PI*Math.random();
126
        var r = this.size*Math.random()/5;
127
        partic.dx = this.dx + r*Math.sin(t);
128
        partic.dy = this.dy + r*Math.cos(t);
129
        partic.life = 20 + 20*Math.random();
130
        partic.color = this.color;
131
        this.game.particles.push(partic);
132
      }
133
    }
134
  }
135
  this.x += this.dx;
136
  this.y += this.dy;
137
  this.dy -= this.game.grav;
138
  this.draw();
139
  return true;
140
}
141
 
142
Shot.prototype.draw = function (){
143
  if (this.draw_type == 1){
144
    this.drawer.fillStyle = "rgba(255, 255, 180, 1)";
145
    this.drawer.beginPath();
146
    this.drawer.arc(this.x, this.y, 1.5, 0, 2 * Math.PI, false);
147
    this.drawer.fill();
148
    this.drawer.fillStyle = "rgba(255, 255, 255, 1)";
149
    this.drawer.beginPath();
150
    this.drawer.arc(this.x, this.y, 0.5, 0, 2 * Math.PI, false);
151
    this.drawer.fill();
152
  }
153
}
154
 
155
function Shell(){
156
  var scope = this;
157
  this.game;
158
  this.drawer;
159
  
160
  this.x = 0;
161
  this.y = 0;
162
  
163
  this.dx = 0;
164
  this.dy = 0;
165
  
166
  this.life = 0;
167
  this.type = 1;
168
  this.size = 0;
169
  this.draw_type = 0;
170
}
171
 
172
Shell.prototype.init = function (game){
173
  this.game = game;
174
  this.drawer = game.drawer;
175
}
176
 
177
Shell.prototype.tick = function (){
178
  --this.life;
179
  if (this.life < 0){
180
    if (this.type & 1){// basic burst
181
      var color = "rgba("+Math.ceil(255-200*Math.random())+", "+Math.ceil(255-200*Math.random())+", "+Math.ceil(255-200*Math.random());
182
      for (var num=0;num<this.size*10;num++){
183
        var partic = new Particle();
184
        partic.init(this.game);
185
        partic.x = this.x;
186
        partic.y = this.y;
187
        var t = 2*Math.PI*Math.random();
188
        var r = this.size*3*Math.random()/1.5;
189
        partic.dx = this.dx + r*Math.sin(t);
190
        partic.dy = this.dy + r*Math.cos(t);
191
        partic.life = 40 + 40*Math.random();
192
        partic.color = color;
193
        this.game.particles.push(partic);
194
      }
195
    }
196
    if (this.type & 4){// basic burst
197
      var color = "rgba("+Math.ceil(255-200*Math.random())+", "+Math.ceil(255-200*Math.random())+", "+Math.ceil(255-200*Math.random());
198
      for (var num=0;num<this.size*10;num++){
199
        var partic = new Particle();
200
        partic.init(this.game);
201
        partic.x = this.x;
202
        partic.y = this.y;
203
        var t = 2*Math.PI*Math.random();
204
        var r = this.size*3*Math.random()/1.5;
205
        partic.dx = this.dx + r*Math.sin(t);
206
        partic.dy = this.dy + r*Math.cos(t);
207
        partic.life = 40 + 40*Math.random();
208
        partic.color = color;
209
        this.game.particles.push(partic);
210
      }
211
    }
212
    if (this.type & 8){// basic burst
213
      var color = "rgba("+Math.ceil(255-200*Math.random())+", "+Math.ceil(255-200*Math.random())+", "+Math.ceil(255-200*Math.random());
214
      for (var num=0;num<this.size*10;num++){
215
        var partic = new Particle();
216
        partic.init(this.game);
217
        partic.x = this.x;
218
        partic.y = this.y;
219
        var t = 2*Math.PI*Math.random();
220
        var r = this.size*3*Math.random()/1.5;
221
        partic.dx = this.dx + r*Math.sin(t);
222
        partic.dy = this.dy + r*Math.cos(t);
223
        partic.life = 40 + 40*Math.random();
224
        partic.color = color;
225
        this.game.particles.push(partic);
226
      }
227
    }
228
    if (this.type & 16){// basic burst
229
      var color = "rgba("+Math.ceil(255-200*Math.random())+", "+Math.ceil(255-200*Math.random())+", "+Math.ceil(255-200*Math.random());
230
      for (var num=0;num<this.size*80;num++){
231
        var partic = new Particle();
232
        partic.init(this.game);
233
        partic.x = this.x;
234
        partic.y = this.y;
235
        var t = 2*Math.PI*Math.random();
236
        var r = this.size*6*Math.random()/1.5;
237
        partic.dx = this.dx + r*Math.sin(t);
238
        partic.dy = this.dy + r*Math.cos(t);
239
        partic.life = 40 + 40*Math.random();
240
        partic.color = color;
241
        this.game.particles.push(partic);
242
      }
243
    }
244
    if (this.type & 2){// multi burst
245
      for (var num=0;num<this.size;num++){
246
        var shot = new Shot();
247
        shot.init(this.game);
248
        shot.x = this.x;
249
        shot.y = this.y;
250
        var t = 2*Math.PI*Math.random();
251
        var r = this.size*Math.random()/2;
252
        shot.dx = this.dx + r*Math.sin(t);
253
        shot.dy = this.dy + r*Math.cos(t);
254
        shot.size = this.size/4;
255
        shot.life = 40+20*Math.random();
256
        shot.type = Math.floor(1+Math.random()*2);
257
        shot.draw_type = Math.floor(Math.random()*2);
258
        shot.color = "rgba("+Math.ceil(255-200*Math.random())+", "+Math.ceil(255-200*Math.random())+", "+Math.ceil(255-200*Math.random());
259
        this.game.shots.push(shot);
260
      }
261
    }
262
    if (this.type & 32){// multi burst
263
      for (var num=0;num<this.size*2;num++){
264
        var shot = new Shot();
265
        shot.init(this.game);
266
        shot.x = this.x;
267
        shot.y = this.y;
268
        var t = 2*Math.PI*Math.random();
269
        var r = this.size*Math.random();
270
        shot.dx = this.dx + r*Math.sin(t);
271
        shot.dy = this.dy + r*Math.cos(t);
272
        shot.size = this.size/4;
273
        shot.life = 40+20*Math.random();
274
        shot.type = Math.floor(1+Math.random()*2);
275
        shot.draw_type = Math.floor(Math.random()*2);
276
        shot.color = "rgba("+Math.ceil(255-200*Math.random())+", "+Math.ceil(255-200*Math.random())+", "+Math.ceil(255-200*Math.random());
277
        this.game.shots.push(shot);
278
      }
279
    }
280
    setTimeout(function (){
281
      g.audio.play_sound("firework", "firework");
282
    }, 500);
283
    return false;
284
  }
285
  this.x += this.dx;
286
  this.y += this.dy;
287
  this.dy -= this.game.grav;
288
  this.draw();
289
  return true;
290
}
291
 
292
Shell.prototype.draw = function (){
293
  if (this.draw_type == 0){
294
    this.drawer.fillStyle = "rgb(255, 255, 192)";
295
    this.drawer.fillRect(this.x, this.y, this.size/4, this.size/4);
296
  }
297
}
298
 
299
function audio(){
300
  var scope = this;
301
  var buffers;
302
  var context;
303
  var channels;
304
  
305
  this.init = function (){
306
    this.buffers = {};
307
    
308
    window.AudioContext = window.AudioContext || window.webkitAudioContext;
309
    this.context = new AudioContext();
310
    this.channels = {};
311
    this.channels['main'] = this.context.createGain();
312
    this.channels['main'].connect(this.context.destination);
313
    this.channels['main'].gain.value = 0.00;
314
    
315
    this.channels['firework'] = this.context.createGain();
316
    this.channels['firework'].connect(this.channels['main']);
317
    this.channels['firework'].gain.value = 1.0;
318
    
319
    this.channels['other'] = this.context.createGain();
320
    this.channels['other'].connect(this.channels['main']);
321
    this.channels['other'].gain.value = 0.3;
322
  }
323
  
324
  this.load_sound = function (url, name, num){
325
    num = num || 1;
326
    
327
    for (var a=0; a<num; a++){
328
      this.buffers[name] = Array();
329
      var request = new XMLHttpRequest();
330
      request.open('GET', url.replace("_#", "_"+a), true);
331
      request.responseType = 'arraybuffer';
332
      
333
      request.onload = function() {
334
        scope.context.decodeAudioData(this.response, function(buffer) {
335
          scope.buffers[name].push(buffer);
336
        });
337
      }
338
      request.send();
339
    }
340
  }
341
  
342
  this.play_sound = function (name, channel) {
343
    channel = channel || "main";
344
    var source = this.context.createBufferSource();
345
    if (this.buffers[name].length > 1){
346
      source.buffer = this.buffers[name][Math.floor(Math.random()*this.buffers[name].length)];
347
    } else if (this.buffers[name].length){
348
      source.buffer = this.buffers[name][0];
349
    }
350
    source.connect(this.channels[channel]);
351
    if (!source.start)
352
      source.start = source.noteOn;
353
    source.start(0);
354
  }
355
}
356
 
357
function game(){
358
  var scope = this;
359
  
360
  this.canvas = false;
361
  this.drawer = false;
362
  this.audio = false;
363
  
364
  this.width = 0;
365
  this.height = 0;
366
  
367
  this.grav = -9.81 / 240;
368
  
369
  this.shell_again = false;
370
  this.last_shell = 0;
371
  
372
  this.shells = Array();
373
  this.shots = Array();
374
  this.particles = Array();
375
  
376
  this.init = function (){
377
    this.canvas = document.getElementById("canvas");
378
    this.drawer = canvas.getContext("2d");
379
    this.audio = new audio();
380
    this.audio.init();
381
    this.audio.load_sound("https://notomono.onnix.net/21410__heigh-hoo__blow.ogg", "launch", 1);
382
    this.audio.load_sound("https://notomono.onnix.net/99200__dobroide__20100612-fireworks.wav", "firework", 1);
383
    this.audio.load_sound("https://notomono.onnix.net/186958__readeonly__explosion7.wav", "pop", 1);
384
    
385
    this.width = window.innerWidth;
386
    this.height = window.innerHeight;
387
    this.canvas.width = this.width;
388
    this.canvas.height = this.height;
389
    
390
    this.drawer.fillStyle = 'rgba(0, 0, 0)';
391
    this.drawer.fillRect(0, 0, this.width, this.height);
392
  }
393
  
394
  this.start = function (){
395
    this.tick();
396
  }
397
  
398
  this.tick = function (){
399
    setTimeout(function (){ g.tick() }, 16);
400
    
401
    this.draw();
402
    
403
    if (Math.random() < 0.02 || this.shell_again){
404
      if (this.shell_again){
405
        this.fire_shell(this.shell_again[0], this.shell_again[1]);
406
      } else {
407
        this.fire_shell((Math.random()+Math.random())/2*this.width, -Math.random()*this.height/180-this.height/200);
408
      }
409
    }
410
    
411
    if (Math.random() < 0.02){
412
        scope.audio.play_sound("launch", "other");
413
    }
414
    
415
    for(var i = this.particles.length-1; i>=0;i--){
416
      if (!this.particles[i].tick()){
417
        this.particles.splice(i, 1);
418
      }
419
    }
420
    
421
    for(var i = this.shots.length-1; i>=0;i--){
422
      if (!this.shots[i].tick()){
423
        this.shots.splice(i, 1);
424
      }
425
    }
426
    
427
    for(var i = this.shells.length-1; i>=0;i--){
428
      if (!this.shells[i].tick()){
429
        this.shells.splice(i, 1);
430
      }
431
    }
432
  }
433
  
434
  this.fire_shell = function (x, dy){
435
    var t = (new Date()).getTime();
436
    if (t-200 > this.last_shell){
437
      this.last_shell = t;
438
      var nshell = new Shell();
439
      nshell.init(this);
440
      nshell.x = x;
441
      nshell.y = this.height;
442
      nshell.dx = Math.random()*.5-.25;
443
      nshell.dy = dy;
444
      nshell.life = -nshell.dy*20;
445
      nshell.size = nshell.life/20;
446
      nshell.type = Math.floor(1+Math.random()*63);
447
      this.shells.push(nshell);
448
      setTimeout(function (){
449
        scope.audio.play_sound("launch", "firework");
450
      }, 500);
451
    } else {
452
      this.next_shell = [x, dy];
453
    }
454
  }
455
  
456
  this.draw = function (){
457
    this.drawer.fillStyle = "rgba(0, 0, 0, .51)";//"+(0.2+Math.random()/3)+")";
458
    this.drawer.fillRect(0, 0, this.width, this.height);
459
  }
460
  
461
  this.set_audio = function (val){
462
    this.audio.channels['main'].gain.value = val;
463
  }
464
}
465
 
466
var g = new game();
467
 
468
$(function (){
469
  g.init();
470
  g.start();
471
  $("#audio_control").on("click touchend", function (){
472
    if ($("#audio_control").hasClass("control_off")){
473
      $("#audio_control").removeClass("control_off");
474
      g.set_audio(0.2);
475
    } else {
476
      $("#audio_control").addClass("control_off");
477
      g.set_audio(0);
478
    }
479
  }).trigger("click");
480
  $("#canvas").on("click touchstart", function (e){
481
    if (e.originalEvent.touches && e.originalEvent.touches[0])
482
      e = e.originalEvent.touches[0];
483
    g.fire_shell(e.clientX, -Math.log(($(window).height()-e.clientY)/15)*1.8);
484
  });
485
});