Tuesday, November 29, 2011

Pulsate

Решил продолжить тему потрясающе простой и красивой флешки Pulsate, после того как AViktorov сделал её клон на Lua.

Идея данной флешки заключается в следующем: при клике мышкой на поле происходит добавление нового круга. Радиус круга начинает плавно увеличиваться, до столкновения с другим кругом. После столкновении происходит воспроизведение звукового сигнала в соответствии с радиусами кругов и радиусы обеих кругов начинают уменьшаться, до того пока не станут равны нулю или же круги не столкнутся с другими кругами. Таким образом можно сказать, что после столкновения радиусы кругов меняют способ роста на противоположный.

Математика для расчёта столкновений двух кругов подразумевает два варианта.
Первый — когда происходит внешнее столкновение двух кругов, и второй — при котором один круг находится внутри другого, то есть происходит внутреннее столкновение.

В первом варианте определить столкновение можно узнав расстояние d между центрами кругов и проверив является ли сумма радиуса большего круга R и радиуса меньшего круга r больше или равной расстояния d. То есть при столкновении L = 0.
Для того чтобы определить находится ли один круг находится внутри другого нужно определить больший из двух кругов по радиусу и затем проверить меньше ли расстояние d между центрами кругов, чем радиус большего круга R. Если d < R, то один круг находится внутри другого.

Во втором варианте для того чтобы определить столкновение необходим предпринять следующее. Определив расстояние между центрами кругов d, и зная радиусы обеих кругов, нужно проверить является ли сумма d и r больше или равной R. В случае столкновения L = 0.
В ходе экспериментов задав интервалы радиусов и соответствующие им ноты, получаются очень атмосферные мелодии.


Добавив линии соединяющие центры всех кругов получается такой вот красивый рисунок:


Исходный код основных методов столкновений представлен ниже:

struct Circle {

    Circle(
int x, int y) : x(x), y(y), radius(0), color(D3DCOLOR_RGBA(0,155,225,255)), is_grow(true) { }

    
int x;
    
int y;
    
float radius;
    
int color;
    
bool is_grow;
};

const int MAX_CIRCLES_NUM = 32;

std::vector
circles;
//-----------------------------------------------------------------------------
// Checks circles for intersection and update its sizes
//-----------------------------------------------------------------------------
void updateCircles() {
    
for (int i = 0; i < circles.size(); i++) {
        
for (int j = 0; j < circles.size(); j++) {
            
// prevent checking with self
            
if (i == j) continue;

            
// get the squared distances between centers of circles
            
float distance_squared = (circles[i].x - circles[j].x) * (circles[i].x - circles[j].x) + (circles[i].y - circles[j].y) * (circles[i].y - circles[j].y);   
            
// get radiuses and distance
            
float max_radius = max(circles[i].radius, circles[j].radius);
            
float min_radius = min(circles[i].radius, circles[j].radius);
            
float distance = sqrt(distance_squared);
            
float radius =
circles[i].radius + circles[j].radius;

            
// circle inside another circle
            
if (max_radius >= distance) {
                
if (max_radius - (distance + min_radius) <= 0) {
                    
// prevent overgrow
                    
if (circles[i].radius > circles[j].radius) {
                        circles[i].radius = max_radius;
                        circles[j].radius = max_radius - distance;
                    }
                    circles[i].is_grow = !circles[i].is_grow;
                    circles[j].is_grow = !circles[j].is_grow;                               
           
                    playIntersectionSound(max_radius);
                }           
            }
else {               
                
// circles outside
                
if (distance - radius <= 0) {
                    circles[i].is_grow =
false;
                    circles[j].is_grow =
false;
                    playIntersectionSound(max_radius);
                }
            }
        }

        
// update circles
        
if (circles[i].is_grow) {
            circles[i].radius += grow_speed;
        }
else {
            circles[i].radius -= grow_speed;
        }
        
if (circles[i].radius <= 0) {
            circles[i].radius = 0;
            circles[i].is_grow =
true;
        }

    }
}

//-----------------------------------------------------------------------------
// Update Game
//-----------------------------------------------------------------------------
void updateGame() {

    // add one more circle
    
if (mouse_lbutton_clicked) {
        
if (circles.size() < MAX_CIRCLES_NUM) {
            circles.push_back(Circle(mouse_lbutton_down.x,mouse_lbutton_down.y));
        }
    }

    
// crear circles
    
if (rbutton_clicked) {
        circles.clear();
    }

    
// draw circles
    
for (int i = 0; i < circles.size(); i++) {
        primitive->setPenColor(circles[i].color);
        primitive->drawCircle(circles[i].x,circles[i].y,circles[i].radius,50);
// 50 sections
    }

    
// check for intersections and update circles sizes
    updateCircles();
}

* This source code was highlighted with Source Code Highlighter.

Sunday, November 27, 2011

School CTF 2011

School CTF — это соревнования по защите информации, проводимые SiBears, с целью популяризации движения CTF. В этом году соревнования будут проводиться во второй раз. Принять участие в соревнованиях может каждый. Соревнования проводятся на русском и английском языках. В качестве платформы для проведения соревнований используется сайт проекта BlackBox.
School CTF 2011 будут проходить 4-го декабря 2011 года с 12:00 до 19:00 (GMT+7).
Более подробно с правилами проведения соревнований можно ознакомится здесь.
Официальный сайт соревнований — School CTF.

Для того чтобы принять участие в соревнованиях необходимо зарегистрироваться на сайте BlackBox и создать свою команду. Для создания команды необходимо привязать PGP ключ к своему аккаунту. Команда может состоять лишь из одного человека.
Найти ID своего PGP ключа можно на сайте subkeys.pgp.net. Можно также использовать и PGP ключ созданный на сервере ключей pgp.mit.edu.

Для тренировки перед соревнованиями можно размяться решив задания School CTF 2011 Warmup.

Sunday, November 20, 2011

Столик в углу

По совету друга решил посмотреть сериал "Столик в углу" (англ. The Booth At The End). Сериал представляет собой мистический триллер и повествует о загадочном человеке, сидящем за столиком в углу закусочной. К этому человеку приходят разные люди с просьбами осуществить желания, а он в свою очередь говорит им, что необходимо сделать для осуществления желаний.
Скажу сразу, что сериал имеет очень необычный формат серий. Одна серия занимает 2-3 минуты. Было бы смешно, если бы они выходили раз в неделю)) Но авторы решили объединить эти микросерии группами (по 12 штук) в эпизоды, что делает просмотр более удобным (если конечно убрать интро и аутро серий).
Самое интересное, что всё действие происходит только в закусочной, но, тем не менее, целостность и вся картина происходящего в сериале, о котором узнаёшь в ходе диалогов, сохраняется.
Первый сезон закончился очень интересно. Жду продолжения.