Очки жизни и смерти
Приснилась мне ночи 2 назад странная сущность в "очках жизни и смерти", совершенно круглых и с левым светлым стеклом, а правым тёмным. И на кого смотрела она, видела в левом стекле его жизнь, а в правом смерть.
Она знала всё о будущем, но не умела изобразить его. Пришлось сегодня напрячься и помочь ей, задействовав примерно те же образы, что там были. Ну, с точностью до параметров, конечно :)
Отчасти скрипт построен на кодах из Galaga. Модель можно дальше балансировать, чтобы заменить вероятности исходов, особенно в местах, помеченных в исходнике знаком !!!
.
Ниже показан скрипт в работе и прикреплён исходник на момент написания, который можно сохранить как файл .html
(без стандартного обрамления) в кодировке Юникода UTF-8. Наверное, это может быть достаточно медленно на слабом компьютере, у меня быстро. Остановки в коде не предусмотрено, как и в жизни, ну, сдохнет когда-нибудь браузер да и всё. Проверил сейчас только в Firefox и Microsoft Edge, других браузеров на компе не держу. Кто дождётся конца процесса, узнает ответ на волнующий всех вопрос (долго). Ну, и я ожидал другого результата.
Чтобы начать всё сначала достаточно обновить страницу в браузере нажатием клавиши F5
.
<div id="glassesDiv" style="margin: 0 auto; text-align: center;"></div> <script> function glassesMain (id,createCanvas) { let container = document.getElementById (id); let canvas; if (createCanvas) { //В первый раз создать канву canvas = document.createElement('canvas'); canvas.id = id + '_canvas'; container.appendChild (canvas); } else canvas = document.getElementById (id + '_canvas'); //Затем получать id готовой let ctx = canvas.getContext('2d'); let w = canvas.width = 600; let h = canvas.height = 600; //Размеры канвы let cx = w/2, cy=h/2; function clearCanvas() { ctx.fillStyle = '#000'; ctx.fillRect(0, 0, w, h); } function linkedListElement(id) { //Один элемент this.next = null; this.prev = null; this.obj = null; this.id = id; this.get = function() { return this.obj; } } function linkedList() { //Список элементов this.first = null; this.last = null; this.counter = 0; this.length = 0; this.add = function(obj) { this.counter++; let element = new linkedListElement(this.counter); element.obj = obj; if (this.first == null) { this.first = element; this.last = element; } else { this.last.next = element; element.prev = this.last; this.last = element; } this.length++; return this.counter; } this.remove = function(id) { let element = this.get(id); if (element == null) return false; this.length--; if (element.prev == null && element.next == null) { this.first = null; this.last = null; delete element; return true; } if (element.prev == null) { this.first = element.next; element.next.prev = null; } if (element.prev != null) element.prev.next = element.next; if (element.next == null) { this.last = element.prev; element.prev.next = null; } if (element.next != null) element.next.prev = element.prev; delete element; return true; } this.clear = function() { while (this.first != null) this.remove(this.first.id); } this.get = function(id) { if (this.first == null) return null; var element = this.first; do { if (element.id == id) return element; element = element.next; } while (element != null); return null; } this.getIt = function(count) { count--; element = this.first; if (!element || count >= this.length) return null; for (var i=0; i<count; i++) element = element.next; return element; } } function dist(p1,p2) { return Math.sqrt( Math.pow((p1.x-p2.x), 2) + Math.pow((p1.y-p2.y), 2) ); } function toRadians (degree,addition) { return (degree + addition) * Math.PI / 180.0; } let oAliens = new linkedList(); //Чужаки let oStars = new linkedList(); //Звездочки function glass() { //Стёкла реальности this.iColor = new Array( 'rgba(224,224,224,0.5)','rgba(53,53,53,0.5)' ); //заполнение this.aColor = new Array( '#eee','#666' ); //сетка к окружности this.msg = ''; this.radius = new Array (h/8, h/8); this.grow = true; this.init = function () { this.clk = 0; let div = 20; this.gx = new Array (cx-h/8-div, cx+h/8+div); } this.init(); this.setPos = function() { if (this.clk>10) { this.clk = -1; this.init(); } this.clk++; } this.draw = function() { for (let i=0; i<2; i++) { ctx.beginPath(); ctx.fillStyle=this.iColor[i]; ctx.arc(this.gx[i], cy, this.radius[i], 0, Math.PI * 2, true); ctx.fill(); ctx.closePath(); } ctx.setLineDash(new Array(2,5)); for (let i=0; i<2; i++) { ctx.beginPath(); for (let deg=0; deg<=360; deg+=30) { let rad = toRadians(deg,-90); let x1 = this.gx[i] + this.radius[i] * Math.cos(rad); let y1 = cy + this.radius[i] * Math.sin(rad); ctx.strokeStyle = this.aColor[i]; ctx.moveTo (this.gx[i],cy); ctx.lineTo (x1,y1); ctx.stroke(); } ctx.closePath(); } ctx.fillStyle='#fff'; let fontSize = 16; ctx.font = fontSize+"px sans-serif"; ctx.textAlign = "center"; ctx.textBaseline="middle"; if (this.msg.length==0) ctx.fillText(''+oAliens.length,cx,cy); else ctx.fillText(this.msg,cx,cy); } } let MyGlass = new glass(); function star() { //Звёздочка this.aColors = new Array( 'rgb(0,0,0)', 'rgb(0,0,204)', 'rgb(0,191,0)', 'rgb(204,0,204)', 'rgb(0,245,245)', 'rgb(191,191,191)', 'rgb(204,0,0)', 'rgb(0,204,0)', 'rgb(191,191,0)', 'rgb(245,245,0)', 'rgb(191,0,191)', 'rgb(191,0,0)'); this.iColor = Math.round(Math.random()*3.4); this.clk = 0; this.x = Math.floor(Math.random() * w); this.y = Math.floor(Math.random() * h); this.id = oStars.add(this); this.setPos = function() { this.y++; if (this.y>h) this.y = 0; if (this.clk>10) { this.clk = 0; this.iColor = (this.iColor + 1) % this.aColors.length; } this.clk+=(Math.random()*7); } this.draw = function() { ctx.fillStyle = this.aColors[this.iColor]; ctx.fillRect(this.x, this.y, 1, 1); } } for (let i = 0; i < 33; i++) new star(); function alien(sx,sy) { //Чужак this.aColors = new Array( 'rgb(0,191,0)','rgb(0,218,0)','rgb(0,209,0)','rgb(91,191,0)','rgb(0,191,91)','rgb(91,218,0)','rgb(0,218,91)' ); this.init = function (sx,sy) { this.iColor = Math.floor(Math.random()*this.aColors.length); this.clk = 0; this.p0 = {"x": Math.floor(Math.random() * w), "y": Math.floor(Math.random() * h)}; this.x = this.p0.x; this.y = this.p0.y; this.rad = 15; this.p1 = {"x": Math.floor(Math.random() * w), "y": Math.floor(Math.random() * h)}; this.p2 = {"x": Math.floor(Math.random() * w), "y": Math.floor(Math.random() * h)}; if (sx==0 && sy==0) //начнем движение с p3 this.p3 = {"x": Math.floor(Math.random() * w), "y": Math.floor(Math.random() * h)}; else this.p3 = {"x": sx, "y": sy}; } this.init(sx,sy); this.mother = false; this.id = oAliens.add(this); this.setPos = function() { let d = dist({"x": this.x, "y": this.y},this.p0); if (d<0.1 || this.clk>10) { this.clk = -0.02; let oldx = this.p0.x, oldy = this.p0.y; this.init(oldx,oldy); if (Math.round(Math.random())==1) this.mother = true;//восстановил заражабельность с вероятностью !!! this.p3.x = oldx; this.p3.y = oldy; //начнем движение с p3 } this.clk+=0.02; } this.draw = function() { let green1x = this.p0.x * this.clk + this.p1.x * (1-this.clk); let green1y = this.p0.y * this.clk + this.p1.y * (1-this.clk); let green2x = this.p1.x * this.clk + this.p2.x * (1-this.clk); let green2y = this.p1.y * this.clk + this.p2.y * (1-this.clk); let green3x = this.p2.x * this.clk + this.p3.x * (1-this.clk); let green3y = this.p2.y * this.clk + this.p3.y * (1-this.clk); let blue1x = green1x * this.clk + green2x * (1-this.clk); let blue1y = green1y * this.clk + green2y * (1-this.clk); let blue2x = green2x * this.clk + green3x * (1-this.clk); let blue2y = green2y * this.clk + green3y * (1-this.clk); let finalx = blue1x * this.clk + blue2x * (1-this.clk); let finaly = blue1y * this.clk + blue2y * (1-this.clk); this.x = finalx; this.y = finaly; ctx.fillStyle = this.aColors[this.iColor]; ctx.beginPath(); ctx.arc(this.x, this.y, this.rad-4, 0, 2 * Math.PI, false); ctx.fill(); ctx.closePath(); ctx.strokeStyle = this.iColor; ctx.setLineDash(new Array(2,2)); for (let deg=0; deg<=360; deg+=60) { let rad = toRadians(deg,-90); let x1 = this.x + this.rad * Math.cos(rad); let y1 = this.y + this.rad * Math.sin(rad); ctx.beginPath(); ctx.moveTo (this.x,this.y); ctx.lineTo (x1,y1); ctx.stroke(); ctx.closePath(); ctx.beginPath(); ctx.arc(x1, y1, 2, 0, 2 * Math.PI, false); ctx.fill(); ctx.closePath(); } } this.detect = function() { if ( dist({"x":this.x,"y":this.y},{"x":MyGlass.gx[0],"y":cy})<Math.min(MyGlass.radius[0],this.rad) ) { //попал в белый круг oAliens.remove(this.id); //сдох if (MyGlass.grow) { (MyGlass.radius[0])++; if (MyGlass.radius[1]>1) (MyGlass.radius[1])--; } } if ( dist({"x":this.x,"y":this.y},{"x":MyGlass.gx[1],"y":cy})<Math.min(MyGlass.radius[1],2.33*this.rad) ) { //попал в черный круг !!! if (this.mother) { this.mother = false; //активный на время потерял заражабельность new alien(this.x,this.y); //но новый родился if (MyGlass.grow) { if (MyGlass.radius[0]>1) (MyGlass.radius[0])--; (MyGlass.radius[1])++; } } } } } for (let i = 0; i<50; i++) new alien(0,0); //!!! let GlobalClock = 0; function draw() { // Главная отрисовка GlobalClock++; if (GlobalClock % 10 == 0) { let oElement = oAliens.first; while (oElement != null) { oElement.get().setPos(); oElement = oElement.next; } } if (GlobalClock % 3 == 0) { let oElement = oStars.first; while (oElement != null) { oElement.get().setPos(); oElement = oElement.next; } } clearCanvas(); let oElement = oStars.first; while (oElement != null) { oElement.get().draw(); oElement = oElement.next; } oElement = oAliens.first; while (oElement != null) { oElement.get().draw(); oElement.get().detect(); oElement = oElement.next; } if (oAliens.length==0) { MyGlass.grow = false; MyGlass.msg = 'Мы победили, все чужаки умерли'; } else if (oAliens.length>500) { MyGlass.grow = false; MyGlass.msg = 'Мы все умерли, чужаки съели наш мир'; //!!! } MyGlass.setPos(); MyGlass.draw(); } let clk = setInterval(function() {draw()}, 10); } window.addEventListener ('load', function (e) { glassesMain ('glassesDiv',true); }); </script> <noscript> <div style="margin: 0 auto; text-align: center;"> Включите в браузере JavaScript для работы приложения! </div> </noscript>
18.04.2020, 22:53 [1395 просмотров]