Pixi.js : обработка столкновений

Вот и вылез огромный минус работы с этим 2D движком: в «базе» нет функционала по определению столкновений двух объектов. Можно конечно самому дописать этот функционал если нужно..НО..вот моя реализация распознавания столкновения двух кружков получилась совсем не оптимальной по быстродействию.

Первым делом напишем алгоритм столкновения двух окружностей. А именно вспомним школу: Две окружности пересекаются,если расстояние между центрами меньше либо равно сумме радиусов

 function CircleHit(c0,c1){
        res=false;
         r0=c0.getBounds().height/2;
         r1=c1.getBounds().height/2;
         x0=c0.getBounds().x+r0;
         x1=c1.getBounds().x+r1;
         y0=c0.getBounds().y+r0;
         y1=c1.getBounds().y+r1;                 
         len= Math.sqrt( Math.pow(x0-x1,2) + Math.pow(y0-y1,2) ); //расстояние между центрами
         sum=Math.abs(r0+r1);   //сумма радиусов
         if (len<=sum) return true;         
        return res;
    }

Далее нарисуем на холсте случайным образом кружочки. Проследим, чтоб во время разрисовки они не накладывались и не пересекались:

        for (let i = 0; i < count_grand_mamas; i++) { 
           graphics = new PIXI.Graphics();           
           graphics.beginFill(0xDE3249);
           graphics.lineStyle(2, 0xFEEB77, 1);
           graphics.beginFill(0x650A5A, 1);
           radius=randomIntFromInterval(5,30);
           graphics.drawCircle(0,0, radius);       
           need_random=true;           
           while (need_random==true){               
            x=randomIntFromInterval(1,width-2*radius);
            y=randomIntFromInterval(1,height-2*2*radius);
            if (i>0){
                need_random=false; 
                for (let it = 0; it < i-1; it++) { 
                   if (FutureCircleHit(grand_mamas[it],x,y,radius)==true) {
                      need_random=true; 
                   };
                }
            } else {
                need_random=false;
            }
           };
           graphics.position.set(x, y);          
           graphics.stepx=GetRandomStep(); // определяем направление движения по оси х          
           graphics.stepy=GetRandomStep(); // определяем направление движения по оси y
           graphics.endFill();        
           grand_mamas.push(graphics); 
           app.stage.addChild(grand_mamas[i]);            
        }  

И теперь каждый «тик» двигаем кружок, проверяя не сталкиваются ли кружки. Если сталкиваются — то меняем направление движения обоих:

        ticker.add(function (time) {     
            FPSText.text='FPS:'+ticker.FPS; // выводим FPS
            for (let i = 0; i < grand_mamas.length; i++) {                                 
                grand_mamas[i].position.x=grand_mamas[i].position.x+grand_mamas[i].stepx;
                grand_mamas[i].position.y=grand_mamas[i].position.y+grand_mamas[i].stepy;
                
                if (((grand_mamas[i].getBounds().x+grand_mamas[i].getBounds().height)>width)||(grand_mamas[i].getBounds().x<0)){
                  grand_mamas[i].stepx=-grand_mamas[i].stepx;  
                };
                if (((grand_mamas[i].getBounds().y+grand_mamas[i].getBounds().height)>height)||(grand_mamas[i].getBounds().y<0)){
                  grand_mamas[i].stepy=-grand_mamas[i].stepy;  
                };
                grand_mamas[i].hit=false;
            };                            
                // обрабатываем столкновения
                for (let i1 = 0; i1 < grand_mamas.length; i1++) { 
                    for (let i2 = 0; i2 < grand_mamas.length; i2++) { 
                        if (i1!=i2){
                            if (CircleHit(grand_mamas[i1],grand_mamas[i2])==true){                                 
                                if (grand_mamas[i1].hit==false) {   
                                    grand_mamas[i1].stepx=-1*grand_mamas[i1].stepx;  
                                    grand_mamas[i2].stepx=-1*grand_mamas[i2].stepx;  
                                    grand_mamas[i1].stepy=-1*grand_mamas[i1].stepy;  
                                    grand_mamas[i2].stepy=-1*grand_mamas[i2].stepy;                              
                                    
                                    grand_mamas[i1].hit=true;
                                    grand_mamas[i2].hit=true;
                                };
                            };
                        };
                    }
                }
                

        });

Pixi.js : первые шаги

Pixi.js — это движёк 2D графики на JavaScript. Позволяет использовать WebGL или Canvas если первый не доступен.

Ну что, попробуем его в действии. Нарисуем 2000 кружков и попробуем их подвигать.

Подключим движёк через CDN:

<script src="https://cdn.jsdelivr.net/npm/pixi.js@7.x/dist/pixi.min.js"></script>

Обьявим массив кружков, определим размер экрана:

    grand_mamas=[];
    count_grand_mamas=2000;
    
    var width = window.innerWidth; //получаем ширину экрана
    var height = window.innerHeight; // получаем высоту экрана

Инициируем экран приложения:

    const app = new PIXI.Application({ 
        width:width,
        height:height,
        background: '#1099bb' ,
        antialias: true
    });
    document.body.appendChild(app.view);

Нарисуем 2000 кружков и поместим эти обьекты в массив, чтобы дальше с ними играться:

    for (let i = 0; i < count_grand_mamas; i++) { 
        graphics = new PIXI.Graphics();           
        graphics.beginFill(0xDE3249);
        graphics.lineStyle(2, 0xFEEB77, 1);
        graphics.beginFill(0x650A5A, 1);
        graphics.drawCircle(0,0, randomIntFromInterval(1,10));       
        graphics.position.set(randomIntFromInterval(-width,width), randomIntFromInterval(1,height));
        graphics.endFill();        
        grand_mamas.push(graphics);
        app.stage.addChild(grand_mamas[i]);
        
    };

Далее используем класс ticker для периодических действий с кружками. По умолчанию класс эвент класса выполняется 60 раз в секунду. Что делаем в эвенте? Пробегаемся по массиву кружков и двигаем их. Если кружок выходит за пределы экрана, то передвигаем его случайным образом вверх экрана. Бонусом выведем FPS:

  FPSText = new PIXI.Text('FPS:0');
  FPSText.x = 10;
  FPSText.y = 10;   
  app.stage.addChild(FPSText);
   
  let ticker = PIXI.Ticker.shared;   
  ticker.autoStart = false;
  ticker.start();
  
   step=0.01;
   ticker.add(function (time) {
        FPSText.text='FPS:'+ticker.FPS;
        for (let i = 0; i < count_grand_mamas; i++) {                 
            count=count+step;
            if (count>10){step=-step;};        
            if (count<0){step=-step;};        
            grand_mamas[i].position.x=grand_mamas[i].position.x+count;
            grand_mamas[i].position.y=grand_mamas[i].position.y+count;
            //console.log(grand_mamas[i].getBounds());
            if ((grand_mamas[i].position.x>width)||(grand_mamas[i].position.y>height)){
                grand_mamas[i].position.x=randomIntFromInterval(-width,width);
                grand_mamas[i].position.y=randomIntFromInterval(1,1);
            };
        }  
   });

В результате получим движущиеся кружочки с разной скоростью

PostgreeSQL: формат даты

Для форматирования даты в стоку нужного формата в PGSQL предусмотрена функция to_char(дата,формат). Использовать в запросе можно примерно так:

select 
comments.comment,
to_char(comments.dt, 'DD.MM.YYYY HH24:MI:SS'),
ls.ls,
users.login
from comments
inner join ls on ls.id=comments.lsid
inner join users on users.id=comments.userid
where ls.ls='1234' order by dt desc limit 10

При этом поддерживаются следующие паттерны форматирования:

ПаттернОписание
HHчас дня (01-12)
HH12час дня (01-12)
HH24час дня (00-23)
MIминуты (00–59)
SSсекунды (00–59)
MSмилисекунды (000–999)
USмикросекунды (000000–999999)
FF1десятые доли секунды (0-9)
FF2сотая доля секунды (00-99)
FF3милисекунлы (000–999)
FF4десятая часть миллисекунды (0000-9999)
FF5сотая доля миллисекунды (00000-99999)
FF6микросекунды (000000–999999)
SSSS, SSSSSсекунды после полуночи (0-86399)
AM , am , PM или pmмеридианный индикатор (без периодов)
A.M. , a.m. , P.M. или p.m.меридианный индикатор (с периодами)
Y,YYYгод (4 и более цифры)с запятой
YYYYгод (4 и более цифры)
YYYпоследние 3 цифры года
YYпоследние 2 цифры года
Yпоследняя цифра года
IYYYISO 8601 год с номером недели (4 или более цифр)
IYYпоследние 3 цифры года по стандарту ISO 8601 год с номером недели
IYпоследние 2 цифры года по ISO 8601 номер недели
Iпоследняя цифра года недели по ISO 8601
BC , bc , AD или adиндикатор эры (без периодов)
B.C. , b.c. , A.D. или a.d.индикатор эры (с периодами)
MONTHполное название месяца в верхнем регистре (с пустыми кнопками до 9 символов)
Monthполное название месяца с заглавными буквами (с пустыми кнопками до 9 символов)
monthполное название месяца в нижнем регистре (с пустыми кнопками до 9 символов)
MONсокращенное название месяца в верхнем регистре (3 символа на английском языке,локализованная длина варьируется)
Monсокращенное название месяца с заглавными буквами (3 символа на английском языке,локальная длина варьируется)
monсокращенное название месяца в нижнем регистре (3 символа на английском языке,локализованная длина варьируется)
MMномер месяца (01-12)
DAYполное название дня в верхнем регистре (с пустыми кнопками до 9 символов)
Dayполное название дня с заглавной буквы (пустое,до 9 символов)
dayполное название дня в нижнем регистре (с пустыми кнопками до 9 символов)
DYсокращенное название дня в верхнем регистре (3 символа на английском языке,локализованная длина варьируется)
Dyсокращенное название дня с заглавными буквами (3 символа на английском языке,локальная длина варьируется)
dyсокращенное название дня в нижнем регистре (3 символа на английском языке,локализованная длина варьируется)
DDDдень года (001-366)
IDDDдень года с нумерацией недель ISO 8601 (001-371;день 1 года-понедельник первой недели ISO)
DDдень месяца (01-31)
Dдень недели, с воскресенья ( 1 ) по субботу ( 7 )
IDISO 8601 день недели, с понедельника ( 1 ) по воскресенье ( 7 )
Wнеделя месяца (1-5)(первая неделя начинается в первый день месяца)
WWномер недели года (1-53)(первая неделя начинается в первый день года)
IWномер недели года с нумерацией недель ISO 8601 (01-53;первый четверг года приходится на неделю 1)
CCвек (2 цифры)(XXI век начинается с 2001-01-01 гг.)
JЮлианская дата (целое число дней с 24 ноября 4714 г. до н.э. в местную полночь; см. Раздел B.7 )
Qquarter
RMмесяц римскими цифрами в верхнем регистре (I-XII;I=январь)
rmмесяц в нижнем регистре римскими цифрами (i-xii;i=январь)
TZАббревиатура часового пояса в верхнем регистре (поддерживается только в to_char )
tzаббревиатура часового пояса в нижнем регистре (поддерживается только в to_char )
TZHсмещение зоны в часах
TZMсмещение зоны в минутах
OFсмещение часового пояса от UTC (поддерживается только в to_char )

Получение email пользователя ИБ

Задача: получение email пользователя ИБ по известному пользователю конфигурации

При разработке на платформе 1С, в рано или поздно сталкиваешся с данностью, что нужно работать с двумя разными сущностями: пользователь информационной базы (задаётся в конфигураторе), и пользователь справочника «Пользователь» в используемой конфигурации. При использовании стандартной БСП, они обычно связаны между собой при помощи реквизита «ИдентификаторПользователяИБ».

Получение email пользователя ИБ

Email пользователя может храниться в двух местах:

  1. В контактной информации пользователя в справочнике Пользователи
  2. Как реквизит Пользователя информационной базы.

И самое удивительное, что они не синхронизируются между собой, т.е. могут быть в принципе и разными.

В моём случае, нужно получение email пользователя ИБ. Решается это так:

			ПользовательИБ=ПользователиИнформационнойБазы.НайтиПоУникальномуИдентификатору(ВыборкаДетальныеЗаписи.ОтветственныйСотрудник.ИдентификаторПользователяИБ);
			email=ПользовательИБ.АдресЭлектроннойПочты;			

Javascript: Открыть страницу на новой вкладке, передав на неё данные через POST

Есть несколько вариантов решения данной задачи Самым простым из них является размещение на странице скрытой формы, заполнение её данными в нужный момент, и принудительный submit. Например как-то так:

<form id="my_form" method="post" action="?view=new_page" target="Новое окно">
	<input type="hidden" id="my_var" name="my_var" value="" />
</form>

<script type="text/javascript">
	my_var="Мои данные в POST";
	window.open('', 'Новое окно');
	document.getElementById('my_form').submit();
</script>
1 43 44 45 46 47 299