From 4161844c4cf93c387fa65d1d562ded9139942fa0 Mon Sep 17 00:00:00 2001 From: choelzl Date: Mon, 21 Feb 2022 00:15:03 +0100 Subject: [PATCH] WIP --- web/chatguessr/bus.js | 410 +++++++++++++++++++++++++++++++++++++++++ web/emotewall/index.js | 180 ++++++++++-------- 2 files changed, 511 insertions(+), 79 deletions(-) create mode 100644 web/chatguessr/bus.js diff --git a/web/chatguessr/bus.js b/web/chatguessr/bus.js new file mode 100644 index 0000000..7cfb35d --- /dev/null +++ b/web/chatguessr/bus.js @@ -0,0 +1,410 @@ +// ==UserScript== +// @name PhantomBot-ChatGuessr +// @namespace http://tampermonkey.net/ +// @version 0.1 +// @description try to take over the world! +// @author Sora +// @match https://*.geoguessr.com/* +// @icon https://www.google.com/s2/favicons?domain=geoguessr.com +// @require https://code.jquery.com/jquery-3.6.0.min.js +// @require https://cdnjs.cloudflare.com/ajax/libs/datatables/1.10.21/js/jquery.dataTables.min.js + +// @grant none +// ==/UserScript== +if(localStorage.getItem('lauth')==null || localStorage.getItem('lauth')=="") localStorage.setItem('lauth',prompt("Enter Current Auth token","")) + +var socket = null; +var isInGame = false; +var table; +var guesses = {}; +window.MAP = null; + +class GameHelper { + static isGameURL(url){ return url.includes("/game/"); } + static getGameId(url){ return url.substring(url.lastIndexOf("/") + 1); } + static sortByDistance(guesses){ return guesses.sort((a, b) => a.distance - b.distance); } + static sortByScore(guesses){ return guesses.sort((a, b) => b.score - a.score); } +} + +const toMeter = (distance) => (distance >= 1 ? parseFloat(distance.toFixed(1)) + "km" : parseInt(distance * 1000) + "m"); +const renderGuesses = (guesses) => { + let sguesses = GameHelper.sortByScore(guesses); + const rows = sguesses.map((guess, i) => { + return { + Position: i+1, + Player: `${guess.user}`, + Streak: "-", + Distance: guess.distance, + Score: guess.score, + }; + }); + table.clear().draw(); + table.rows.add(rows).draw(); +}; + + +let markers = []; +let polylines = []; +function populateMap(location, scores) { + + scores = GameHelper.sortByScore(scores); + + const infowindow = new google.maps.InfoWindow(); + const icon = { + path: `M13.04,41.77c-0.11-1.29-0.35-3.2-0.99-5.42c-0.91-3.17-4.74-9.54-5.49-10.79c-3.64-6.1-5.46-9.21-5.45-12.07 + c0.03-4.57,2.77-7.72,3.21-8.22c0.52-0.58,4.12-4.47,9.8-4.17c4.73,0.24,7.67,3.23,8.45,4.07c0.47,0.51,3.22,3.61,3.31,8.11 + c0.06,3.01-1.89,6.26-5.78,12.77c-0.18,0.3-4.15,6.95-5.1,10.26c-0.64,2.24-0.89,4.17-1,5.48C13.68,41.78,13.36,41.78,13.04,41.77z + `, + fillColor: "#de3e3e", + fillOpacity: 0.7, + scale: 1.2, + strokeColor: "#000000", + strokeWeight: 1, + anchor: new google.maps.Point(14, 43), + labelOrigin: new google.maps.Point(13.5, 15), + }; + + const locationMarker = new google.maps.Marker({ + position: location, + url: `http://maps.google.com/maps?q=&layer=c&cbll=${location.lat},${location.lng}`, + icon: icon, + map: MAP, + }); + google.maps.event.addListener(locationMarker, "click", () => { + window.open(locationMarker.url, "_blank"); + }); + markers.push(locationMarker); + + icon.scale = 1; + scores.forEach((score, index) => { + const color = index == 0 ? "#E3BB39" : index == 1 ? "#C9C9C9" : index == 2 ? "#A3682E" : score.color; + icon.fillColor = color; + let pos = {lat:parseFloat(score.location.split(',')[0]),lng:parseFloat(score.location.split(',')[1])} + const guessMarker = new google.maps.Marker({ + position: pos, + icon: icon, + map: MAP, + label: { color: "#000", fontWeight: "bold", fontSize: "16px", text: `${score.user.substr(0,2)}` }, + }); + google.maps.event.addListener(guessMarker, "mouseover", () => { + infowindow.setContent(` +

+ ${score.user}
+ ${score.distance >= 1 ? parseFloat(score.distance.toFixed(1)) + "km" : parseInt(score.distance * 1000) + "m"}
+ ${score.score} +

+ `); + infowindow.open(MAP, guessMarker); + }); + google.maps.event.addListener(guessMarker, "mouseout", () => { + infowindow.close(); + }); + markers.push(guessMarker); + + polylines.push( + new google.maps.Polyline({ + strokeColor: color, + strokeWeight: 4, + strokeOpacity: 0.6, + geodesic: true, + map: MAP, + path: [pos, location], + }) + ); + }); +} + +function clearMarkers() { + while (markers[0]) { + markers.pop().setMap(null); + } + while (polylines[0]) { + polylines.pop().setMap(null); + } +} + +function hijackMap() { + const MAPS_API_URL = "https://maps.googleapis.com/maps/api/js?"; + const GOOGLE_MAPS_PROMISE = new Promise((resolve, reject) => { + let scriptObserver = new MutationObserver((mutations) => { + for (const mutation of mutations) { + for (const node of mutation.addedNodes) { + if (node.tagName === "SCRIPT" && node.src.startsWith(MAPS_API_URL)) { + node.onload = () => { + scriptObserver.disconnect(); + scriptObserver = undefined; + resolve(); + }; + } + } + } + }); + + let bodyDone = false; + let headDone = false; + + new MutationObserver((_, observer) => { + if (!bodyDone && document.body) { + if (scriptObserver) { + scriptObserver.observe(document.body, { + childList: true, + }); + bodyDone = true; + } + } + if (!headDone && document.head) { + if (scriptObserver) { + scriptObserver.observe(document.head, { + childList: true, + }); + headDone = true; + } + } + if (headDone && bodyDone) { + observer.disconnect(); + } + }).observe(document.documentElement, { + childList: true, + subtree: true, + }); + }); + + function runAsClient(f) { + const script = document.createElement("script"); + script.type = "text/javascript"; + script.text = `(${f.toString()})()`; + document.body.appendChild(script); + } + + GOOGLE_MAPS_PROMISE.then(() => { + runAsClient(() => { + const google = window.google; + const isGamePage = () => location.pathname.startsWith("/results/") || location.pathname.startsWith("/game/"); + const onMapUpdate = (map) => { + try { + if (!isGamePage()) return; + MAP = map; + } catch (error) { + console.error("GeoguessrHijackMap Error:", error); + } + }; + + const oldMap = google.maps.Map; + google.maps.Map = Object.assign( + function (...args) { + const res = oldMap.apply(this, args); + this.addListener("idle", () => { + if (MAP != null) return; + onMapUpdate(this); + }); + return res; + }, + { + prototype: Object.create(oldMap.prototype), + } + ); + }); + }); +} + + +const markerRemover = document.createElement("style"); +markerRemover.innerHTML = ".map-pin{display:none}"; + +let gameState='none' +const handleGameState = async()=>{ + let prevGameState = gameState; + let nextRoundBtn = document.querySelector('[data-qa="close-round-result"]'); + let addGuessBtn = document.querySelector('[data-qa="perform-guess"]'); + let playAgainBtn = document.querySelector('[data-qa="play-same-map"]'); + if(gameState=='none'){ + if(nextRoundBtn) gameState='result'; + if(addGuessBtn) gameState='guess'; + if(playAgainBtn) gameState='end'; + } + if(gameState=='guess' && addGuessBtn){ + markerRemover.remove(); + addGuessBtn.addEventListener("click", async() => { + await new Promise(r => setTimeout(r, 500)) + gameState='result'; + socket.sendCommand('cg_refresh_gs_g', 'cga refresh', ()=>{}); + handleGameState(); + }); + }else if(gameState=='result' && nextRoundBtn){ + document.body.appendChild(markerRemover); + nextRoundBtn.addEventListener("click", async() => { + await new Promise(r => setTimeout(r, 500)) + gameState='guess'; + socket.sendCommand('cg_refresh_gs_r', 'cga refresh', ()=>{}); + handleGameState(); + }); + }else if(gameState=='end' && playAgainBtn){ + document.body.appendChild(markerRemover); + clearMarkers(); + if(guesses){ + renderGuesses(guesses.final); + for(let i = 0; i<= guesses.round; ++i){ + populateMap(guesses.rounds[i],guesses[i]) + } + } + playAgainBtn.addEventListener("click", async() => { + await new Promise(r => setTimeout(r, 500)) + gameState='none'; + socket.sendCommand('cg_refresh_gs_r', 'cga end', ()=>{ }); + }); + }else{ + await new Promise(r => setTimeout(r, 500)) + gameState='none' + handleGameState(); + } + console.log(gameState) +} + + +const head = document.getElementsByTagName("head")[0]; + +const styles = document.createElement("style"); +styles.innerHTML = ` +.container_content__H3tXS > div:nth-child(1),.container_content__H3tXS > div:nth-child(2),.container_content__H3tXS > div:nth-child(3){display:none} +[data-qa=result-view-top]{max-height:100vh} +[data-qa=result-view-bottom]>div>div:last-child{display:none} +[data-qa=score]{display:none} +[data-qa=result-view-bottom]{position:fixed;width:100%;left:0;bottom:0} +[data-qa=result-view-bottom]>div{background:linear-gradient(transparent,#000),linear-gradient(90deg,#28374c36,#221d6ca1)} +.classic_section__19Ttr{display:none}button:focus{outline:0}.hud-button-group:last-child{display:none}.result-map__line{display:none} +.gm-ui-hover-effect{display:none!important}.gm-style-iw-c{top:-4px!important;padding:10px 0 0 17px!important} +.gm-style-iw-t::after{top:-4px!important} +.gm-iw__content{color:#000;text-align:center;font-weight:700; width:100%;} +#showScoreboard:hover{cursor:pointer;background:rgba(0,0,0,.7)}#settingsIcon span,#showScoreboard span{margin:-1px 0 0 1px}#scoreboardContainer{display:none;width:420px;position:absolute;top:0;left:0;right:0;bottom:0;overflow:hidden;pointer-events:none}#scoreboard{font-family:Montserrat,sans-serif;position:relative;min-width:380px;min-height:180px;max-width:1800px;max-height:1000px;padding:5px;background-color:rgba(0,0,0,.4);box-shadow:2px 2px 7px -2px #000;color:#fff;text-align:center;border-radius:10px;pointer-events:auto;user-select:none;overflow:hidden;z-index:999999}.dataTables_scrollHeadInner{width:100%!important}#scoreboardHeader{display:grid;grid-template-columns:90px auto 80px;justify-items:center;height:35px;font-size:18px;align-items:center}#scoreboardTitle{margin-top:-8px}.dataTables_scrollBody::-webkit-scrollbar{display:none}.dataTables_scrollBody{padding-top:2px;-ms-overflow-style:none;scrollbar-width:none}table{font-size:15px;line-height:.8;font-weight:700;width:100%!important;margin:0 auto;clear:both;border-collapse:collapse;table-layout:fixed;word-wrap:break-word;overflow:hidden}thead{font-size:14px;background-color:rgba(0,0,0,.5)}tbody td,thead th{padding:8px 0;line-height:1em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}tbody .odd{background-color:rgba(0,0,0,.1)}tbody .even{background-color:rgba(0,0,0,.2)}tbody>tr:hover{-webkit-transition:.2s;transition:.2s;background-color:rgba(0,0,0,.4)}tbody tr:hover>.sorting_1,tbody tr>.sorting_1{background-color:rgba(0,0,0,.1)}th.sorting,th.sorting_asc,th.sorting_desc{cursor:pointer}th.sorting:hover,th.sorting_asc:hover,th.sorting_desc:hover{-webkit-transition:.1s;transition:.2s;color:#d6d6d6}.dataTables_empty{display:none}.icon{font-size:20px;line-height:0}.username{text-shadow:.05em 0 .05em #fff}.expand{animation:expand .3s ease-in-out}@keyframes expand{from{transform:scale(0);opacity:0}}.ui-draggable .ui-dialog-titlebar{cursor:move}.ui-draggable-handle{-ms-touch-action:none;touch-action:none}.ui-resizable{position:relative}.ui-resizable-handle{position:absolute;font-size:.1px;touch-action:none}.ui-resizable-autohide .ui-resizable-handle,.ui-resizable-disabled .ui-resizable-handle{display:none}.ui-resizable-n{cursor:n-resize;height:12px;width:100%;top:-5px;left:0}.ui-resizable-s{cursor:s-resize;height:12px;width:100%;bottom:0;left:0}.ui-resizable-e{cursor:e-resize;width:12px;height:100%;right:-3px;top:0}.ui-resizable-w{cursor:w-resize;width:12px;height:100%;left:0;top:0}.ui-resizable-se{cursor:se-resize;width:12px;height:12px;right:0;bottom:0}.ui-resizable-sw{cursor:sw-resize;width:12px;height:12px;left:0;bottom:0}.ui-resizable-nw{cursor:nw-resize;width:12px;height:12px;left:0;top:0}.ui-resizable-ne{cursor:ne-resize;width:12px;height:12px;right:-3px;top:-3px}.dt-buttons{position:absolute;top:0;margin-top:16px;width:100%;text-align:left}.dt-button{vertical-align:middle;font-size:14px;cursor:pointer;border-radius:5px;border:1px solid #000;background-size:200% auto;background-image:linear-gradient(to right,#2e2e2e 0,#454545 51%,#2e2e2e 100%);transition:.3s;-webkit-transition:.3s}.dt-button:hover{background-position:right center;box-shadow:2px 2px 5px -2px #000}.dt-button-collection{margin-top:-29px;position:absolute;padding-left:45px}.dt-button-collection div{background-color:#333;border-radius:8px;padding:4px 6px 4px 6px}.buttons-columnVisibility{color:#fff;padding:3px 7px}.buttons-columnVisibility.active{background-image:linear-gradient(to right,#1cd997 0,#33b09b 51%,#1cd997 100%)}.colvis-btn{width:40px;height:25px}.scrollBtn{text-align:center;width:38px;height:23px;margin-right:4px;float:left}.scrollBtn label span{margin-top:2px;height:100%;display:block;cursor:pointer}.scrollBtn label input{position:absolute;top:-50px}.scrollBtn input:checked+span{color:#1cd997}#switchContainer{margin-top:-9px;margin-left:auto;z-index:99;position:relative;display:inline-block;width:37px;height:21px;-webkit-transition:.1s;transition:.1s}#switchContainer:hover{box-shadow:2px 2px 7px -2px #000}#switchContainer input{display:none}.slider{position:absolute;cursor:pointer;top:0;left:0;right:0;bottom:0;border-radius:4px;background-color:#e04352;-webkit-transition:.1s;transition:.1s}.slider:before{position:absolute;content:"";height:16px;width:16px;left:2px;bottom:3px;border-radius:3px;background-color:#fff;-webkit-transition:.2s;transition:.2s}input:checked+.slider{background-color:#1cd997;box-shadow:2px 2px 7px -2px #000}input:checked+.slider:before{-webkit-transform:translateX(17px)}#scrollSpeedSlider{display:none;height:3px;padding:0;-webkit-appearance:none;width:calc(100% - 12px);background:#fff;outline:0;opacity:.2;-webkit-transition:.3s;transition:opacity .3s;direction:rtl}#scrollSpeedSlider:hover{opacity:1}#scrollSpeedSlider::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;width:30px;height:7px;background:#63db85;cursor:pointer}#scrollSpeedSlider::-moz-range-thumb{width:30px;height:7px;background:#63db85;cursor:pointer}.btn{margin:30px;padding:5px;background-color:#22da8d;color:#fff;font-weight:700}.btn:hover{background-color:#18cc81}.btn:active{background-color:#15b472}` +head.appendChild(styles); + +hijackMap(); +const scoreboardContainer = document.createElement("div"); +scoreboardContainer.setAttribute("id", "scoreboardContainer"); +scoreboardContainer.innerHTML = ` +
+
+ + Guesses + +
+ + + + + + + + + + + +
#PlayerStreakDistanceScore
+
`; +document.body.appendChild(scoreboardContainer); + + + + +const script1 = document.createElement('script') +script1.src = 'https://twitchbot.helcel.net/common/reconnecting-websocket/reconnectingWS.min.js'; +const script2= document.createElement('script') +script2.src = 'https://twitchbot.helcel.net/common/js/wsConfig.js'; +const script3 = document.createElement('script') +script3.src ='https://twitchbot.helcel.net/custom/js/socketWrapper.js' +document.body.appendChild(script1) +document.body.appendChild(script2) +document.body.appendChild(script3) +script3.addEventListener('load', async () => { + while(!window.socket){await new Promise(r => setTimeout(r, 500))} + socket = window.socket; + if(socket){ + socket.addFamilyHandler("chatguessr", (e)=>{ + try { + let rawMessage = e.data, message = JSON.parse(rawMessage); + if(!message.hasOwnProperty('eventFamily') || message.eventFamily != 'chatguessr' || + !message.hasOwnProperty('eventType') || !message.hasOwnProperty('data')) return; + if(message.eventType == 'guesses') { + const gd = JSON.parse(message.data) + guesses = gd; + if(gd.round!=undefined && gd[gd.round] && gd.rounds){ + clearMarkers(); + renderGuesses(gd[gd.round]); + if(gameState=="result"){ + populateMap(gd.rounds[gd.round],gd[gd.round]) + } + }else if(gd.round!= undefined && gd[gd.round - 1]){ + clearMarkers(); + renderGuesses([]); + } + } + } catch (ex) {console.log(ex)} + }); + while(socket.getReadyState() === 0){await new Promise(r => setTimeout(r, 500))} + socket.sendCommand('cga_gg', 'cga gg', ()=>{}); + + var ccc = ''; + setInterval(async()=>{ + if(ccc != $('#__next > div').attr('class')){ + + if(GameHelper.isGameURL(window.location.href)){ + $('#scoreboardContainer').show(); + if(isInGame){ + socket.sendCommand('cg_refresh', 'cga refresh', ()=>{}); + }else { + isInGame = true; + socket.sendCommand('cga_start', 'cga start '+GameHelper.getGameId(window.location.href), ()=>{}); + handleGameState(); + } + isInGame = true; + }else if(isInGame){ + isInGame = false; + socket.sendCommand('cga_end', 'cga end', ()=>{}); + $('#scoreboardContainer').hide(); + }else{ + $('#scoreboardContainer').hide(); + } + } + ccc = $('#__next > div').attr('class') + }, 1000); + } + socket.getDBValue('cga_init_btn', 'cgstatus', 'isOpen', (v)=>$('#switchBtn').prop("checked","true"==v.cgstatus)) + $('#switchBtn').change(()=>{ + if($('#switchBtn').prop('checked')) socket.sendCommand('cga_open_btn', 'cga open', ()=>{}); + else socket.sendCommand('cga_close_btn', 'cga close', ()=>{}); + }); + + + table = $("#datatable").DataTable({ + info: false, + searching: false, + autoWidth: true, + paging: false, + scrollY: 166, + scrollResize: true, + scrollCollapse: true, + language: { zeroRecords: " " }, + dom: "Bfrtip", + buttons: [], + columns: [ + { data: "Position" }, + { data: "Player" }, + { data: "Streak" }, + { + data: "Distance", + render: (data, type) => ((type === "display" || type === "filter")? toMeter(data) : data) + }, + { data: "Score" }, + ], + columnDefs: [ + { targets: 0, width: "35px"}, + { targets: 1, width: "auto"}, + { targets: 2, width: "55px" }, + { targets: 3, width: "100px" }, + { targets: 4, width: "75px", type: "natural" }, + ], + }); +}); diff --git a/web/emotewall/index.js b/web/emotewall/index.js index a2d1147..07ce88c 100644 --- a/web/emotewall/index.js +++ b/web/emotewall/index.js @@ -9,7 +9,7 @@ $(function () { const webSocket = window.socket; const emote_str = ["peepo", 'nod'] - const emote_url = ['https://cdn.7tv.app/emote/603cac391cd55c0014d989be/2x', 'https://cdn.7tv.app/emote/60ae4bb30e35477634610fda/1x'] + const emote_url = ['https://cdn.7tv.app/emote/603cac391cd55c0014d989be/4x', 'https://cdn.7tv.app/emote/60ae4bb30e35477634610fda/4x'] var img_map = {}; var lastframe = 0; @@ -48,27 +48,38 @@ $(function () { const part_speed = 50; const part_bounce_el = 0.9 + const fdt = 1; + const drt = 8; + const tWave = (t) => (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 tWave = (t) => (t<0 || t>8 )? 0 : (t<2 ? t/2 : (t>6 ? (8-t)/2 : 1)) + const randRange = (min,max) => (Math.random()* (max-min) + min) class Particle { constructor(emote,data){ this.size = 64; this.data = data; - this.x = Math.random() * canvas.width - this.size; - this.y = Math.random() * canvas.height - this.size; - this.vx = this.vy = 0; - this.ax = this.ay = 0; + this.setPhysics(randRange(0,canvas.width), + randRange(0,canvas.height), + 0,0,0,0); this.emote = emote; this.time = 0; - particles.push(this); - setTimeout(()=>{particles.pop()}, 10000); + } + + 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, this.size, this.size); + ctx.drawImage(img_map[this.emote], this.x, this.y, + sWave(this.time,this.size), sWave(this.time,this.size)); } update(tick){ @@ -84,12 +95,11 @@ $(function () { class RainP extends Particle { constructor(emote,data) { super(emote,data) - this.x = Math.random() * canvas.width; - this.y = - this.size; - this.vx = 0; - this.vy = 15; - this.ax = 0, this.ay = 0; - this.time = 2; + 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) @@ -99,11 +109,13 @@ $(function () { class BounceP extends Particle { constructor(emote,data) { super(emote,data) - this.x = Math.random() * canvas.width; - this.y = Math.random() * canvas.height; - this.vx = (Math.random() * 2 - 1) *15; - this.vy = (Math.random() * 2 - 1) * 15; - this.ax = 0, this.ay = 0; + 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){ @@ -128,76 +140,92 @@ $(function () { class BounceGP extends BounceP { constructor(emote,data) { super(emote,data) - this.x = Math.random() * canvas.width; - this.y = Math.random() * canvas.height; - this.vx = Math.random() * 20 - 10; - this.vy = Math.random() * 20 - 10; - this.ax = 0, this.ay = 10; + 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); } + } - update(tick){ - super.update(tick); + 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.x = canvas.width/2; - this.y = canvas.height; - this.vx = 0; - this.vy = -15; - this.ax = 0; - this.ay = 0; - this.time=4; - this.boom = false; + 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.boom){ - let angle = Math.random() *2 * Math.PI; - this.vx = Math.sin(angle) * (Math.random()*4 + 10); - this.vy = Math.cos(angle) * (Math.random()*4 + 10); - this.ay = 10; - this.boom = true; + 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() { - - new RainP('peepo', {}); - new RainP('peepo', {}); - new RainP('peepo', {}); - new RainP('peepo', {}); - new RainP('peepo', {}); - new BounceGP('nod', {}); - new BounceP('nod', {}); - new FireworkP('nod', {}); - new FireworkP('nod', {}); - new FireworkP('nod', {}); - new FireworkP('nod', {}); - new FireworkP('nod', {}); - new FireworkP('nod', {}); - new FireworkP('nod', {}); - new FireworkP('nod', {}); - new FireworkP('nod', {}); - new FireworkP('nod', {}); - new FireworkP('nod', {}); - new FireworkP('nod', {}); - new FireworkP('nod', {}); - new FireworkP('nod', {}); - new FireworkP('nod', {}); - new FireworkP('nod', {}); - new FireworkP('nod', {}); - new FireworkP('nod', {}); - new FireworkP('nod', {}); - new FireworkP('nod', {}); - new FireworkP('nod', {}); + createParticule(BounceGP, "nod", {}, {}) + createParticule(BounceP, "nod", {}, {}) + createParticule(BounceP, "nod", {}, {}) + createParticule(BombP, "nod", {}, {}) + createParticule(FireworkP, "nod", {}, {}) + //genRain(); main(0); } @@ -209,16 +237,10 @@ $(function () { ctx.clearRect(0, 0, canvas.width, canvas.height); if (!initialized) { - if (preloaded) { - setTimeout(function(){initialized = true;}, 1000); - } + if (preloaded) setTimeout(function(){initialized = true;}, 1000); } else { - particles.forEach((particle) => { - particle.update(dt); - }); - particles.forEach((particle) => { - particle.draw(); - }); + particles.forEach(p => p.update(dt)); + particles.forEach(p => p.draw()); } }