Sign in to follow this  
Followers 0
Guest

Урок №2 Форматирование и показ сообщений

2 posts in this topic

Форматирование и показ сообщений



Одной из самых распространённых задач в программировании являетсявывод данных для пользователей в текстовом виде. При этом вместе с текстом приходится выводить значения каких-либо переменных.
Для подобных задач можно использовать функцию printf, однако в SA:MP от неё не будет никакого толку: printf выводит текст только в консоль сервера, пользователи (т.е. игроки) этот текст не увидят.

Для вставки в текст значений переменных (форматирования) в SA:MP есть функция format:

format(<строковая переменная>, <размер>, <форматная строка>, <список>)
 

 

  • <строковая переменная> - переменная, в которую будет записан отформатированный текст
  • <размер> - размер строковой переменный (нужен функции, чтобы предотвратить случайный выход за пределы строковой переменной), желательно указывать в виде sizeof(<строковая переменная>)
  • <форматная строка> - строка для вставки значений переменных
  • <список> - значения, которые нужно вставить в форматный текст


Принцип работы функции format схож с принципом работы printf, однако format не выводит отформатированный текст в консоль, а сохраняет его в строковой переменной.

С форматированием разобрались, но как показывать отформатированный текст игрокам?
Для показа сообщений игрокам разработчики SA:MP сделали функции SendClientMessage и SendClientMessageToAll.

 

// отправка сообщения указанному игроку

SendClientMessage(<id игрока>, <цвет>, <строка>)

// отправка сообщения всем игрокам

SendClientMessageToAll(<цвет>, <строка>)
  • <id игрока> - номер игрока, которому требуется показать сообщение
  • <цвет> - число (обычно в шестнадцатеричном представлении), в котором закодирован цвет текста сообщения
  • <строка> - текст сообщения, который будет показан игроку

Чаще всего цвет записывают в форме

0xAARRGGBB
  • A (alpha) - степень прозрачности (от 0 до FF, чем меньше - тем прозрачнее)
  • R (red) - оттенок красного (от 0 до FF)
  • G (green) - оттенок зелёного
  • B (blue) - оттенок синего

Для удобного выбора цвета можно использовать инструмент "Подбор цвета" в программе SimplePawn.


Теперь перейдём к практике.
Сделаем простую команду /stats, в которой выведем игроку его ID, имя и кол-во игровых очков:

CMD:stats(playerid, params[])
{
    // строковая переменная для хранения имени игрока, длиной в
    // MAX_PLAYER_NAME (константа из a_samp.inc, обозначающая макс.
    // длину имени игрока) + 1 ячейка под завершающий нуль-символ
    new playername[MAX_PLAYER_NAME+1];

    // получаем кол-во игровых очков с помощью функции GetPlayerScore
    new score = GetPlayerScore(playerid);

    // строка для форматирования сообщения
    new string[128];

    // получить имя игрока
    GetPlayerName(playerid, playername, sizeof(playername));

    // форматирование текста сообщения
    format( string, sizeof(string), "ID: %d, имя: %s, очки: %d",
            playerid, playername, score);

    // вывод сообщения игроку
    SendClientMessage(playerid, 0xFFFFFFFF, string);

    // завершение работы команды
    return 1;
}

 

Разберём некоторые детали:

  • Количество игровых очков мы узнаём с помощью функции GetPlayerScore, которая имеет следующий синтаксис:
  • GetPlayerScore(<id игрока>)

     

  • Имя игрока получаем с помощью функции GetPlayerName:
  • GetPlayerName(<id игрока>, <строковая переменная>, <размер>)

     

  • Число 0xFFFFFFFF означает белый цвет (alpha=255 (FF), R=255, G=255, B=255).

Теперь посмотрим на вышеприведённый код ещё раз, многие вещи можно упростить:

  1. Вместо playername можно получать имя игрока в строковую переменную string, после чего строка может участвовать в форматировании (format) самой себя.
  2. Использовать переменную score необязательно, вместо этого можно подставить вызов функции GetPlayerScore напрямую в format.

Теперь упростим код:

CMD:stats(playerid, params[])
{
    static const fmt_str[] = "ID: %d, имя: %s, очки: %d";
    new string[sizeof(fmt_str)-2+4-2+MAX_PLAYER_NAME-2+11];
    GetPlayerName(playerid, string, sizeof string );
    format( string, sizeof string , fmt_str, playerid, string, GetPlayerScore(playerid));
    SendClientMessage(playerid, 0xFFFFFFFF, string);
    return 1;
}

Но даже после этого остаётся один серьёзный недочёт: размер переменной string оставляет желать лучшего. Однако, вручную подсчитывать необходимый размер строковой переменной - не самая простая задача. К тому же, если нужно будет изменить форматный текст, придётся пересчитывать размер строки заново.
Впрочем, выход есть. Сделаем так, чтобы компилятор сам подсчитал необходимый размер строки:

CMD:stats(playerid, params[])
{
    static const fmt_str[] = "ID: %d, имя: %s, очки: %d";
    new string[sizeof(fmt_str)-2+4-2+MAX_PLAYER_NAME-2+11];
    GetPlayerName(playerid, string, sizeof string );
    format( string, sizeof string , fmt_str, playerid, string, GetPlayerScore(playerid));
    SendClientMessage(playerid, 0xFFFFFFFF, string);
    return 1;
}

Принцип работы:

Создаётся строковая константа fmt_str (сокр. от "format string" - форматная строка), чтобы компилятор мог подсчитать её размер с помощью оператора sizeof.
Затем от размера строки отнимается 2 (длина "%d", "%s" и т.п. отрывков) и прибавляется максимальная длина форматируемого значения: для чисел это 11 (минимальное отрицательное значение: -2147483647 - 11 символов), для имён игроков - MAX_PLAYER_NAME, для ID игроков - на данный момент 3 (в коде поставлено 4, чтобы не пришлось его переделывать, если в будущих версиях SA:MP будет более 1000 игроков, who knows...).
В результате получаем необходимую длину переменной string.

Edited by Artemio

Share this post


Link to post
Share on other sites

@Artemio, про спецификаторы было бы неплохо сказать. Сделать это можно даже в WIKI: тык.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0

  • Recently Browsing   0 members

    No registered users viewing this page.