Без шума и пыли…

Пинкод. Игровой уровень

..вышла игра от издательства «Новый диск» под названием «Смешарики. Пинкод. Получи патент первым!» одним из создателей которой являюсь я, автор этого блога. Во время создания этого проекта, мы черпали вдохновение из шедевра игростроя TIM (The Incredible Machine).

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

Пинкод. Бонусная игра

Это одна из немногих игр, которой, я считаю, можно гордится. Категорически рекомендую пройти игру целиком, до финала. Потому что только после завершения всех уровне показывается клевая заставка «Об авторах». В общем желаю всем приятного времяпрепровождения. Если будут какие-то проблемы в игрой — не стесняйтесь спрашивать меня в комментариях. Ни один вопрос не останется безнаказанным без ответа. Спасибо за внимание.

Внимание: если у вас вылетает игра после нажатия кнопки «Играть» в главном меню, то вам нужно скачать этот файл и положить его в папку с игрой.

P.S. Как выглядит диск с игрой можно посмотреть вот здесь.

Скрипт для проверки интернета
#!/bin/sh
 
# Какие хосты проверяем (через пробел).
hosts="8.8.8.8 ya.ru www.ru"
# Файл, который будет создаваться, если интернета нет.
offline="/tmp/inetoff"
 
# Функция проверяет с помощью ping доступность хостов. 
# Возвращает 0, если хотя бы один хост доступен.
check_hosts() {
    for host in ${hosts}; do
        # Запускаем ping с 4-мя запросами
        /sbin/ping -c 4 $host > /dev/null 2>&1
        if [ $? -eq 0 ]; then
            return 0;
        fi
    done
    return 1;
}
 
# Процедура, которая пишет сообщение 
# в /var/log/message с тегом INTERNET.
message() {
    /usr/bin/logger -t INTERNET $1
}
 
check_hosts
 
# Хотя бы один хост доступен?
if [ $? -eq 0 ]; then
    # Флаг отсутствия интернета существует?
    if [ -e ${offline} ]; then
        # Значит интернет только что появился.
        message "Network is up"
        # Удаляем флаг отсутствия интернета.
        /bin/rm -f ${offline}
    fi
else
    # Ни один хост не ответил и флага еще нет.
    if [ ! -e ${offline} ]; then
        # Значит интернет только что пропал.
        message "Network is down"
        # Создаем флаг отсутствия интернета.
        /usr/bin/touch ${offline}
    fi
fi

Засовываем вызов скрипта в крон:

# Запускать каждые 5 минут
*/5  *  *  *  *  /path_to_script/lancheck.sh

Теперь в /var/log/message видно, когда интернет появился или пропал.

Как подсчитать на четырех пальцах до пятнадцати

Кисть левой руки

В этом нам поможет двоичная система счисления.

Берем левую руку (изображение скелета из википедии) и сжимаем в кулак. Это ноль. Поднимаем указательный палец, это единица. Сжимаем в кулак — опять ноль. Поднимаем средний палец (многие делают это не задумываясь) — это двойка. Сжимаем кулак и (внезапно!) снова ноль. Указательный и средний (типа V) — это три. И так далее…

…l 00012=110
..l. 00102=210
..ll 00112=310
.l.. 01002=410
.l.l 01012=510
.ll. 01102=610
.lll 01112=710
l… 10002=810
l..l 10012=910
l.l. 10102=1010
l.ll 10112=1110
ll.. 11002=1210
ll.l 11012=1310
lll. 11102=1410
llll 11112=1510

О библиотеке сжатия zlib

Сегодня я хочу рассказать о замечательной библиотеке zlib.

Мне, как программисту игрушек, раньше приходилось решать проблему быстрой распаковки ресурсов при загрузке игровых уровней. Самое неприятное, что может принести игра пользователю, кроме падения и ошибок, это заставить его долго ожидать загрузки уровня (хотя 10-15 лет назад загрузка одного уровня по 5-10 минут было совершенно нормальным явлением).

Впервые в жизни мне пришлось столкнуться с компрессией данных в игре «Петрович и все, все, все», которую мы делали в Trickster Games для Андрея Бильжо.

Все изображения в игре используют от двух до десяти цветов (а музыка восемь нот, ага). Вот пример:

Петрович и инопланетянин

На этом скриншоте присутствуют: Петрович (два цвета), Инопланетянин aka «логотип Trickster Games» (2 цвета), фон (4 цвета). Каждое изображение может занимать от 256 килобайт до 4-х мегабайт (потому что DDS). Загрузка одного уровня, состоявшего из 50-200 таких изображений, занимала от 10 до 45 секунд. Разумеется, это нас в корне не устраивало.

После мозгового штурма на эту тему было найдено решение — использовать алгоритм RLE. Этот алгоритм позволяет очень эффективно сжимать длинную цепочку одинаковых бит, что наглядно показано в википедии: блок данных «AAAAAAAAAAAAAAABBBBBC» мы записываем вот так «15A5BC». Экономия, как говорится, налицо.

Интерфейс для работы с этим алгоритмом был выбран очень простой. Как оказалось впоследствии, такой интерфейс с мелкими различиями предоставляют практически все библиотеки сжатия без потерь.

/* Сжимает данные из буфера src в dst.
 * src - входной буфер
 * srcSize - размер входного буфера в байтах
 * dst - выходной буфер
 * dstSize - перед вызовом должен быть установлен в размер буфера dst, 
 *     после вызова туда записывается реальное количество сжатых байт
 *
 * Функция возвращает true, если данные были сжаты успешно 
 * (это значит, что уровень сжатия меньше или равен единице)
 */
bool compressRLE( void *dst, int *dstSize, const void *src, int srcSize);
 
/* Расжимает данные из буфера src в dst.
 * src - входной буфер
 * srcSize - размер входного буфера в байтах
 * dst - выходной буфер
 * dstSize - перед вызовом должен быть установлен в размер буфера dst, 
 *     после вызова туда записывается реальное количество распакованных байт
 *
 * Функция возвращает true, если данные были расжаты успешно 
 */
bool uncompressRLE( void *dst, int *dstSize, const void *src, int dstSize);

Разумеется, я не могу показать нашу реализацию алгоритма без разрешения начальства, но, думаю, вы справитесь сами. Коэффициент сжатия на наших данных составлял где-то 0.01 процента (то есть тысяча байт сжимались в десять).

..И тут мы плавно переходим к zlib.

Библиотека zlib используется практически везде, где есть CPU: мобильные телефоны, компьютеры, микроволновки, современные автомобили, телевизоры — список можно продолжать бесконечно. Кто знает, может она сейчас трудится на Марсе внутри ровера Curiosity, сжимая, передаваемые на Землю, данные.

Библиотека может сжимать блок данных или поток. Рассмотрим вкратце сжатие блока данных. Описание метода вот такое:

// Сжимает данные методом deflate из буфера src в dst
// dest - выходной буфер
// destLen - размер выходного буфера (после удачного сжатия 
//     сюда сохраняется размер сжатых данных)
// source - входной буфер
// sourceLen - размер входного буфера
// Возвращает Z_OK в случае удачи, записывает размер сжатых данных в destLen
ZEXTERN int ZEXPORT compress OF((Bytef *dest,   uLongf *destLen,
                                 const Bytef *source, uLong sourceLen));

Пример вызова этой функции. Он ничего полезного не делает, просто для наглядности.

#include <zlib.h>
#include <memory.h>
#include <stdio.h>
 
#define SRC_SIZE 512
#define DST_SIZE 512
 
int main()
{
    // Входной буфер размером SRC_SIZE
    unsigned char source[SRC_SIZE];
    // Тут мы будем хранить размер входного буфера 
    // (переменная просто для наглядности)
    const unsigned long sourceLen = SRC_SIZE;
    // Выходной буфер
    unsigned char dest[DST_SIZE];
    // Размер выходного буфера
    unsigned long destLen = DST_SIZE;
 
    // Будем сжимать буфер забитый нулями
    memset(source, 0, SRC_SIZE * sizeof(source[0]));
 
    if (Z_OK == compress(dest, &destLen, source, sourceLen))
    {
        // Все успешно
        printf("Compress ratio: %.2f\n", destLen/(float) sourceLen);
    }
    else
    {
        // Тут можете разобрать код ошибки и вывести более подробную информацию
        printf("Compress failed\n");
    }
 
    return 0;
}

Пример сжатия потока данных вы можете посмотреть в маленькой утилитке zpipe.

Есть вопросы? Спрашивайте, не стесняйтесь.

P.S. Если вы дочитали досюда, рекомендую изучить libdeflate.

Блог Евгения Жирнова