$(function () { const SEVENTV_GLOBAL_URL = "https://api.7tv.app/v2/emotes/global"; const SEVENTV_CHANNEL_URL = "https://api.7tv.app/v2/users/" + "..." + "/emotes"; const FFZ_GLOBAL_URL = "https://api.frankerfacez.com/v1/set/global"; const FFZ_CHANNEL_URL = "https://api.frankerfacez.com/v1/room/" + "..."; const BTTV_GLOBAL_URL = "https://api.betterttv.net/3/cached/emotes/global"; const BTTV_CHANNEL_URL = "https://api.betterttv.net/3/cached/users/twitch/" + "..."; const webSocket = window.socket; const emote_str = ["peepo", 'nod'] const emote_url = ['https://cdn.7tv.app/emote/603cac391cd55c0014d989be/4x', 'https://cdn.7tv.app/emote/60ae4bb30e35477634610fda/4x'] var img_map = {}; var lastframe = 0; var preloaded = false, initialized = false; var mode = "rain" || "bounce" || "explosion" || "firework" || "..."; var particles = []; const canvas = document.getElementById('wall'); const ctx = canvas.getContext('2d'); const resizeCanvas = () => { canvas.width = window.innerWidth-8; canvas.height = window.innerHeight-8; } window.addEventListener('resize', resizeCanvas, false); resizeCanvas(); function loadImages(strs, urls) { let loadcount = 0, loadtotal = urls.length; preloaded = false; var loadedimages = {}; for (let i=0; i (t<0 || t>drt )? 0 : (t(drt-fdt) ? (drt-t)/fdt : 1)) const sWave = (t, s) => (t<0 || t>drt) ? 1 : (t(drt-fdt) ? (drt-t)*s/fdt : s)) const randRange = (min,max) => (Math.random()* (max-min) + min) class Particle { constructor(emote,data){ this.size = 64; this.data = data; this.setPhysics(randRange(0,canvas.width), randRange(0,canvas.height), 0,0,0,0); this.emote = emote; this.time = 0; } setPhysics(x,y,vx,vy,ax,ay){ this.x = x || this.x || 0; this.y = y || this.y || 0; this.vx = vx || this.vx || 0; this.vy = vy || this.vy || 0; this.ax = ax || this.ax || 0; this.ay = ay || this.ay || 0; } draw(){ ctx.globalAlpha = tWave(this.time); if(img_map[this.emote]) ctx.drawImage(img_map[this.emote], this.x, this.y, sWave(this.time,this.size), sWave(this.time,this.size)); } update(tick){ this.time += tick; this.vx += tick * this.ax; this.vy += tick * this.ay; this.x += tick * this.vx * part_speed; this.y += tick * this.vy * part_speed; } } class RainP extends Particle { constructor(emote,data) { super(emote,data) this.setPhysics(randRange(0, canvas.width), randRange(0, canvas.height-this.size), 0,15, 0,0) this.time = 5.5+this.y/canvas.height*2; } update(tick){ super.update(tick) } } class BounceP extends Particle { constructor(emote,data) { super(emote,data) let speed = randRange(5,10); let ang = randRange(0, 2*Math.PI); this.setPhysics(randRange(0, canvas.width), randRange(0, canvas.height), Math.cos(ang)*speed, Math.sin(ang)*speed, 0,0) } update(tick){ super.update(tick); if (this.x < 0) { this.vx = this.vx < 0 ? -this.vx * part_bounce_el : this.vx; this.x = 0; } else if (this.x + this.size > canvas.width) { this.vx = this.vx > 0 ? -this.vx * part_bounce_el : this.vx; this.x = canvas.width - this.size; } if (this.y <0) { this.vy = this.vy < 0 ? -this.vy * part_bounce_el : this.vy; this.y = 0; } else if (this.y + this.size > canvas.height) { this.vy = this.vy > 0 ? -this.vy * part_bounce_el : this.vy; this.y = canvas.height - this.size; } } } class BounceGP extends BounceP { constructor(emote,data) { super(emote,data) let speed = randRange(5,10); let ang = randRange(0,2*Math.PI); this.setPhysics(randRange(0,canvas.width), randRange(0,canvas.height), Math.cos(ang)*speed, Math.sin(ang)*speed, 0,10); } } class ExplosionP extends Particle { constructor(emote,data,args){ super(emote,data) let speed = randRange(0,6) + 7; let fang = 2*Math.PI* (args.angle/360) let ang = randRange(-fang/2, +fang/2)+Math.PI/2 ;//+ 2*(angle/360)*Math.PI; this.setPhysics(args.x,args.y, Math.cos(ang)*speed, -Math.sin(ang)*speed, 0,10); this.time = drt - fdt*1.5; } } class FireworkP extends Particle { constructor(emote,data) { super(emote,data) this.setPhysics(canvas.width/2,canvas.height, 0,-15, 0,0); this.time=fdt; } update(tick){ super.update(tick); if(this.y <= canvas.height/4 && this.time < drt){ this.time = drt; genExplosion(this.x,this.y,360) } } } class BombP extends Particle { constructor(emote,data) { super(emote,data) this.setPhysics(randRange(0, canvas.width-this.size), -this.size, 0,15, 0,0) this.time=fdt; } update(tick){ super.update(tick); if(this.y >= canvas.height - this.size && this.time < drt){ this.time = drt; genExplosion(this.x,this.y,60) } } } const createParticule = (partP, emote, data, args) => { let a = new partP(emote,data,args) particles.push(a); setTimeout(()=>{particles.pop()}, drt*1000+2000); } const genExplosion = (x,y,ang) =>{ for(let i=0; i<50; ++i) new ExplosionP('nod', {},x,y,ang); } const genRain = () => { for(let i = 0; i<50; ++i) new RainP('nod', {}); } function init() { createParticule(BounceGP, "nod", {}, {}) createParticule(BounceP, "nod", {}, {}) createParticule(BounceP, "nod", {}, {}) createParticule(BombP, "nod", {}, {}) createParticule(FireworkP, "nod", {}, {}) //genRain(); main(0); } function main(tframe) { window.requestAnimationFrame(main); var dt = (tframe - lastframe) / 1000; lastframe = tframe; ctx.clearRect(0, 0, canvas.width, canvas.height); if (!initialized) { if (preloaded) setTimeout(function(){initialized = true;}, 1000); } else { particles.forEach(p => p.update(dt)); particles.forEach(p => p.draw()); } } init() const handleSocketMessage = (e)=>{ try { let rawMessage = e.data, message = JSON.parse(rawMessage); if(!message.hasOwnProperty('eventFamily') || message.eventFamily != 'emotewall' || !message.hasOwnProperty('eventType') || !message.hasOwnProperty('data')) return; console.log(message.eventType, message.data) if(message.eventType == 'message') { //.... } } catch (ex) { console.log(ex) } }; jQuery(async ()=>{ try{ socket.addFamilyHandler("overlay", handleSocketMessage); if(socket){ while(socket.getReadyState() === 0){ await new Promise(r => setTimeout(r, 500)); } } }catch(e) {console.log(e)} }) });