pahan73rus
Умник
Приветствую друзья портала Pawno-Info.Ru
Я хотел бы поделиться несколькими вещами, которые я использую в SA:MP
Если у вас есть что можно ещё добавить, дайте мне знать!
Я буду обсуждать такие темы как:
Тернарный оператор
Тернарный оператор является оператором, который принимает 3 аргумента; если первый аргумент верный, то аргумент стоящий за ним будет использоваться, если нет, то будет использоваться последний аргумент.
Структура оператора заключается в следующем:
состояние ? правда : ложь
Вот несколько примеров:
С тернарным оператором:
Еще пару примеров
Int -> преобразование в Boolean
Если вам необходимо будет преобразовать Int в Boolen, то это делается вот так:
myBool будет равняться 0, если myInt будет равняться 0, иначе myBool будет равняться 1
Самый быстрый перебор строки
По моему опыту, самый быстрый способ для перебора строки:
Самый быстрый перебор игроков
Обратите внимание, что Foreach быстрее, чем это.
Короткие функции
Если функция имеет только один оператор - её можно объявить так:
Несколько действия в одном stock'e
В Pawn, как вы могли заметить, все действия отделены точкой с запятой ( ; ) Если вы хотите, чтобы ваш код был только на одной строке, то вот как это сделать:
Как избавиться от глупых предупреждающих тегов
Вставляя 3DText, и прочее внутри функций, таких как Printf, Format, SetTimerEx, CallLocalFunction, CallRemoteFunction вы могли заметить, что вы получаете предупреждающие теги.
Чтобы избавиться от них вам нужно сделать очистку тега, поставив знак подчеркивания в качестве тега.
Пример:
Char-массивы
PAWN имеет функцию для доступа одиночных байтов в массивах, предназначенных для использования с упакованными строками. Большинство программистов SA-MP не используют упакованные строки.
Однако, вы можете использовать эти массивы для оптимизации памяти. Нормальный массив может хранить значения между -2147483648 и 2147483647. Вам не всегда это нужно, не так ли?
В упакованных строках можно хранить значения между 0-255. (Нет отрицательных значений) Когда вы знаете, что вам не нужны отрицательные значения и никогда не будете превышать 255, почему бы не сэкономить немного памяти?
Примечание!
При использовании этих массивов, вам нужно использовать фигурные скобки, в отличие от нормальных квадратных скобках.
Пример:
Использование логических операторов для маленьких IF-условий
Вы можете использовать логические операторы, как будто if-условие, но делать все это внутри одного условия!
Например:
Как вы видите, мы используем логические операторы (&& и ||) просто в открытую.
Код выше, без этой маленькой уловки, будет выглядеть примерно так:
Еще примеры:
Эффективное управление памятью со stock const
Автор Y_Less.
"stock const".
Это то, что я обнаружил некоторое время назад. Все пишут:
Если мы компилируем это с "-a" мы получаем:
Я пометил две линии. Первая толкает число "0", вторая толкает номер "12" ("C"). "print", поскольку это первый (и единственный) параметр, получает адрес в строку print. Все строковые литералы преобразуются в данные и хранятся в глобальной памяти (я не буду вдаваться в детализацию истинных последствиях этого, но достаточно сказать, чтобы вы изменили их). "dunp" является нынешней глобальной памятью для этой крошечной программы:
Если перевести эти цифры в ASCII мы вдруг видим:
Т.е. наши две "hi" строки - две копии одной и той же строки. Это не очень эффективно, так что давайте улучшать это управления памятью:
Расположение "dump" изменилось, но это не важно - большая программа будет иметь много "dump" по всему коду.
Несмотря на то, что мы используем переменную, это еще ой какой эффективный и мудрый код, потому что мы все еще используем постоянные строки. Тем не менее, требования к памяти для хранения двух строк сократилось вдвое.
Вы можете также использовать "new const" или "statick stock const", но "stock const", вероятно, лучше для этого кода, чтобы избежать предупреждения.
Битовые флаги в enum
Вы знаете, что можно хранить 32 true/false значений в одной переменной? Вы не только сэкономите память, но также получаете меньше беспорядка в коде.
Вам не обязательно знать, как работает двоичная система счисления. Однако, я рекомендую вам узнать. Вы можете прочитать в этой теме, если вы заинтересованы.
Если у вас есть, скажем, 100 true/false (BOOL) переменных для игроков, вы используете 195 КБ память. Однако, если бы вы использовали 4 массива с битовыми флагами, только 8 КБ памяти будут использоваться. Из этого получаем, что мы сэкономили 187 KБ памяти!
Вот примеры, содержащие макросы для упрощения использования:
Спасибо за внимание, с вами был pahan73rus, удачного скриптинга
Автор оригинального урока: Slice
Перевод на понятный русский язык: pahan73rus
Я хотел бы поделиться несколькими вещами, которые я использую в SA:MP
Если у вас есть что можно ещё добавить, дайте мне знать!
Я буду обсуждать такие темы как:
- Тернарный оператор
- Int -> преобразование в Boolean
- Самый быстрый перебор строки
- Самый быстрый перебор игроков
- Короткие функции
- Несколько действия в одном stock'e
- Как избавиться от глупых предупреждающих тегов
- "Char-массивы"
- Использование логических операторов для маленьких IF-условий
- Эффективное управление памятью со stock const
- Битовые флаги в enum
Тернарный оператор
Тернарный оператор является оператором, который принимает 3 аргумента; если первый аргумент верный, то аргумент стоящий за ним будет использоваться, если нет, то будет использоваться последний аргумент.
Структура оператора заключается в следующем:
состояние ? правда : ложь
Вот несколько примеров:
PHP:
if ( a == b )
c = d;
else
c = e;
PHP:
c = ( a == b ) ? d : e;
// если-^ тогда-^ ^-иначе
PHP:
SetPlayerColor( playerid, ( Team[ playerid ] == TEAM_ONE ) ? COLOR_RED : COLOR_BLUE );
// Установить цвет на красный, если игрок в TEAM_ONE, в противном случае цвет синий.
GivePlayerWeapon( playerid, ( IsMadnessEnabled() ) ? WEAPON_MINIGUN : WEAPON_FLOWER, 5000 );
// Если IsMadnessEnabled верно, дать игроку миниган
file = fopen( ( useSpecialFile ) ? ("special_file.txt") : ("normal_file.txt") );
// Строки должны быть в круглых скобках или компилятор PAWN будет выдавать ошибку.
// Вы также можете использовать тернарные операторы внутри тернарных операторов!
file = fopen( ( useFile == 1 ) ? ("file1.txt") : ( ( useFile == 2 ) ? ("file2.txt") : ( ( useFile == 3 ) ? ("file3.txt") : ("file0.txt") ) ) );
Int -> преобразование в Boolean
Если вам необходимо будет преобразовать Int в Boolen, то это делается вот так:
PHP:
new myInt = 50;
new bool:myBool = !!myInt;
Самый быстрый перебор строки
По моему опыту, самый быстрый способ для перебора строки:
PHP:
for(new i, l = strlen( string ); i != l; i++)
{
// ..
}
Самый быстрый перебор игроков
Обратите внимание, что Foreach быстрее, чем это.
PHP:
for(new slots = GetMaxPlayers(), i; i < slots; i++)
{
if (!IsPlayerConnected(i))
continue;
// код для подключенных игроков
}
Короткие функции
Если функция имеет только один оператор - её можно объявить так:
PHP:
stock SomeFunction(someInput)
return someArray[someInput / 2];
Несколько действия в одном stock'e
В Pawn, как вы могли заметить, все действия отделены точкой с запятой ( ; ) Если вы хотите, чтобы ваш код был только на одной строке, то вот как это сделать:
PHP:
stock KickEx(playerid, reason[])
SendClientMessage(playerid, 0xC00000FF, "Вы были кикнуты! Причина:"), SendClientMessage(playerid, 0xC00000FF, reason), Kick(playerid);
stock DoStuff(playerid)
return DoFirstThing(playerid), DoSecondThing(playerid), DoThirdThing(playerid), DoLastThing(playerid);
public OnPlayerRequestSpawn(playerid)
{
if (!IsPlayerLoggedIn(playerid)) return SendClientMessage(playerid, 0xC00000FF, "Вы не авторизовались!"), 0;
// Отправит сообщение и возвратит 0
return 1;
}
Как избавиться от глупых предупреждающих тегов
Вставляя 3DText, и прочее внутри функций, таких как Printf, Format, SetTimerEx, CallLocalFunction, CallRemoteFunction вы могли заметить, что вы получаете предупреждающие теги.
Чтобы избавиться от них вам нужно сделать очистку тега, поставив знак подчеркивания в качестве тега.
Пример:
PHP:
new Text3D:t3dTest = Create3DTextLabel( .. ), Text:txTest = TextDrawCreate( .. );
printf("DEBUG: %d, %d", _:t3dTest, _:txTest);
Char-массивы
PAWN имеет функцию для доступа одиночных байтов в массивах, предназначенных для использования с упакованными строками. Большинство программистов SA-MP не используют упакованные строки.
Однако, вы можете использовать эти массивы для оптимизации памяти. Нормальный массив может хранить значения между -2147483648 и 2147483647. Вам не всегда это нужно, не так ли?
В упакованных строках можно хранить значения между 0-255. (Нет отрицательных значений) Когда вы знаете, что вам не нужны отрицательные значения и никогда не будете превышать 255, почему бы не сэкономить немного памяти?
PHP:
new bool:g_IsPlayerSomething[MAX_PLAYERS]; // 500 клеток * 4 байта на 1 клетку = 2000 байтов!
new bool:g_IsPlayerSomething[MAX_PLAYERS char]; // 500 клеток = .. 500 байтов!
При использовании этих массивов, вам нужно использовать фигурные скобки, в отличие от нормальных квадратных скобках.
Пример:
PHP:
public OnPlayerConnect( playerid )
{
g_IsPlayerSomething{playerid} = false;
}
public OnPlayerSpawn( playerid )
{
if (g_IsPlayerSomething{playerid})
{
// ..
}
}
Использование логических операторов для маленьких IF-условий
Вы можете использовать логические операторы, как будто if-условие, но делать все это внутри одного условия!
Например:
PHP:
stock FIXES_valstr(dest[], value, bool:pack = false)
{
static const cellmin_value[] = !"-2147483648";
if (value == cellmin)
pack && strpack(dest, cellmin_value, 12) || strunpack(dest, cellmin_value, 12);
else
format(dest, 12, "%d", value), pack && strpack(dest, dest, 12);
}
Код выше, без этой маленькой уловки, будет выглядеть примерно так:
PHP:
stock FIXES_valstr(dest[], value, bool:pack = false)
{
static const cellmin_value[] = !"-2147483648";
if (value == cellmin) {
if (pack)
strpack(dest, cellmin_value, 12)
else
strunpack(dest, cellmin_value, 12);
} else {
format(dest, 12, "%d", value);
if (pack)
strpack(dest, dest, 12);
}
}
PHP:
a && b(); // если a, запускаем b.
a && b() || c(); // если a, запускаем b. в противном запускаем c.
a || b(); // если неверно a, запускаем b.
a && b() || c && d(); // если a, запускаем b. в противном случае, если c, запускаем d.
a && b() && c(); // если a, запускаем b. если b неверно, запускаем c.
Эффективное управление памятью со stock const
Автор Y_Less.
"stock const".
Это то, что я обнаружил некоторое время назад. Все пишут:
PHP:
#include <a_samp>
main()
{
print("hi");
print("hi");
}
PHP:
CODE 0 ; 0
;program exit point
halt 0
proc ; main
; line 4
; line 5
push.c 0 // тут
;$par
push.c 4
sysreq.c 0 ; print
stack 8
;$exp
; line 6
push.c c // тут
;$par
push.c 4
sysreq.c 0 ; print
stack 8
;$exp
zero.pri
retn
DATA 0 ; 0
dump 68 69 0 68 69 0
STKSIZE 1000
PHP:
dump 68 69 0 68 69 0
PHP:
dump 'h' 'i' '\0' 'h' 'i' '\0'
PHP:
#include <a_samp>
stock const
C_HI[3] = "hi";
main()
{
print(C_HI);
print(C_HI);
}
PHP:
CODE 0 ; 0
;program exit point
halt 0
DATA 0 ; 0
dump 68 69 0
proc ; main
; line 7
; line 8
push.c 0
;$par
push.c 4
sysreq.c 0 ; print
stack 8
;$exp
; line 9
push.c 0
;$par
push.c 4
sysreq.c 0 ; print
stack 8
;$exp
zero.pri
retn
STKSIZE 1000
Несмотря на то, что мы используем переменную, это еще ой какой эффективный и мудрый код, потому что мы все еще используем постоянные строки. Тем не менее, требования к памяти для хранения двух строк сократилось вдвое.
Вы можете также использовать "new const" или "statick stock const", но "stock const", вероятно, лучше для этого кода, чтобы избежать предупреждения.
Битовые флаги в enum
Вы знаете, что можно хранить 32 true/false значений в одной переменной? Вы не только сэкономите память, но также получаете меньше беспорядка в коде.
Вам не обязательно знать, как работает двоичная система счисления. Однако, я рекомендую вам узнать. Вы можете прочитать в этой теме, если вы заинтересованы.
Если у вас есть, скажем, 100 true/false (BOOL) переменных для игроков, вы используете 195 КБ память. Однако, если бы вы использовали 4 массива с битовыми флагами, только 8 КБ памяти будут использоваться. Из этого получаем, что мы сэкономили 187 KБ памяти!
Вот примеры, содержащие макросы для упрощения использования:
PHP:
// Использование для всех макросов: BitFlag_X(variable, flag)
#define BitFlag_Get(%0,%1) ((%0) & (%1)) // Возвращает ноль (false), если флаг не установлен.
#define BitFlag_On(%0,%1) ((%0) |= (%1)) // Включить флаг
#define BitFlag_Off(%0,%1) ((%0) &= ~(%1)) // Выключить флаг
#define BitFlag_Toggle(%0,%1) ((%0) ^= (%1)) // Переключить флаг (поменять true/false)
enum PlayerFlags:(<<= 1) {
// Важно, чтобы вы не забыли поставить "= 1" на первом флаге. Если этого не сделать, все флаги будут 0.
PLAYER_IS_LOGGED_IN = 1, // 0b00000000000000000000000000000001
PLAYER_HAS_GANG, // 0b00000000000000000000000000000010
PLAYER_CAN_BUY_PROPERTIES, // 0b00000000000000000000000000000100
PLAYER_BLABLA_1, // 0b00000000000000000000000000001000
PLAYER_BLABLA_2, // 0b00000000000000000000000000010000
PLAYER_BLABLA_3, // 0b00000000000000000000000000100000
PLAYER_BLABLA_4, // 0b00000000000000000000000001000000
PLAYER_BLABLA_5, // 0b00000000000000000000000010000000
PLAYER_BLABLA_6, // 0b00000000000000000000000100000000
PLAYER_BLABLA_7, // 0b00000000000000000000001000000000
PLAYER_BLABLA_8, // 0b00000000000000000000010000000000
PLAYER_BLABLA_9, // 0b00000000000000000000100000000000
PLAYER_BLABLA_10, // 0b00000000000000000001000000000000
PLAYER_BLABLA_11, // 0b00000000000000000010000000000000
PLAYER_BLABLA_12, // 0b00000000000000000100000000000000
PLAYER_BLABLA_13, // 0b00000000000000001000000000000000
PLAYER_BLABLA_14, // 0b00000000000000010000000000000000
PLAYER_BLABLA_15, // 0b00000000000000100000000000000000
PLAYER_BLABLA_16, // 0b00000000000001000000000000000000
PLAYER_BLABLA_17, // 0b00000000000010000000000000000000
PLAYER_BLABLA_18, // 0b00000000000100000000000000000000
PLAYER_BLABLA_19, // 0b00000000001000000000000000000000
PLAYER_BLABLA_20, // 0b00000000010000000000000000000000
PLAYER_BLABLA_21, // 0b00000000100000000000000000000000
PLAYER_BLABLA_22 // 0b00000001000000000000000000000000
};
new
Создание массива с тем же тегом как enum
PlayerFlags:g_PlayerFlags[MAX_PLAYERS]
;
public OnPlayerConnect(playerid) {
// 0 - Все флаги отключены (false)
g_PlayerFlags[playerid] = PlayerFlags:0;
}
public OnPlayerLogIn(playerid) {
BitFlag_On(g_PlayerFlags[playerid], PLAYER_IS_LOGGED_IN);
// Без макроса:
// g_PlayerFlags[playerid] |= PLAYER_IS_LOGGED_IN;
}
public OnPlayerJoinGang(playerid) {
BitFlag_On(g_PlayerFlags[playerid], PLAYER_HAS_GANG);
// Без макроса:
// g_PlayerFlags[playerid] |= PLAYER_HAS_GANG;
}
public OnPlayerLeaveGang(playerid) {
BitFlag_Off(g_PlayerFlags[playerid], PLAYER_HAS_GANG);
// Без макроса:
// g_PlayerFlags[playerid] &= ~PLAYER_HAS_GANG;
}
public OnPlayerUpdate(playerid) {
BitFlag_Toggle(g_PlayerFlags[playerid], PLAYER_BLABLA_19);
if (BitFlag_Get(g_PlayerFlags[playerid], PLAYER_BLABLA_19)) {
DoSomething();
}
// Без макроса:
// g_PlayerFlags[playerid] ^= PLAYER_BLABLA_19;
//
// if (g_PlayerFlags[playerid] & PLAYER_BLABLA_19) {
// DoSomething();
// }
}
Спасибо за внимание, с вами был pahan73rus, удачного скриптинга
Автор оригинального урока: Slice
Перевод на понятный русский язык: pahan73rus
Последнее редактирование:
