Описание:
Функция отправляет сообщение ближайшим игрокам вычисляя цвет, интенсивность которого завит от расстояния.
Параметры:
playerid - игрок, от которого идёт сообщение
Float:max_range - максимальное расстояние, на котором будет отправлено сообщение
color - базовый цвет
string[] - сообщение
Float:max_ratio = 1.6 (необязательный) - коэффициент уменьшения интенсивности цвета
Возвращаемое значение:
Функция возвращает 0, если playerid не подключен, в остальных случаях возвращается 1.
Код:
stock ProxDetector(playerid, Float:max_range, color, const string[], Float:max_ratio = 1.6)
{
new
Float:pos_x,
Float:pos_y,
Float:pos_z,
Float:range,
Float:range_ratio,
Float:range_with_ratio,
clr_r, clr_g, clr_b,
Float:color_r, Float:color_g, Float:color_b;
if (!GetPlayerPos(playerid, pos_x, pos_y, pos_z)) {
return 0;
}
color_r = float(color >> 24 & 0xFF);
color_g = float(color >> 16 & 0xFF);
color_b = float(color >> 8 & 0xFF);
range_with_ratio = max_range * max_ratio;
#if defined foreach
foreach (new i : Player) {
#else
for (new i = GetPlayerPoolSize(); i != -1; i--) {
#endif
if (!IsPlayerStreamedIn(playerid, i)) {
continue;
}
range = GetPlayerDistanceFromPoint(i, pos_x, pos_y, pos_z);
if (range > max_range) {
continue;
}
range_ratio = (range_with_ratio - range) / range_with_ratio;
clr_r = floatround(range_ratio * color_r);
clr_g = floatround(range_ratio * color_g);
clr_b = floatround(range_ratio * color_b);
SendClientMessage(i, (color & 0xFF) | (clr_b << 8) | (clr_g << 16) | (clr_r << 24), string);
}
SendClientMessage(playerid, color, string);
return 1;
}
Примечания:
Функция поддерживает любые комбинации цветов, прозрачность переданного цвета остаётся не тронутой.
Пример использования:
CMD:say(playerid, params[])
{
ProxDetector(playerid, 20.0, 0xFFAA99FF, params);
return 1;
}
Автор: ziggi
Изменение яркости цвета полезно, спасибо.
Появилась тут мысль, как с её помощью реализовать 3d-тексты над пикапами с покупкой дома, как в сингле (когда при приближении к нему текст цены дома становился отчётливее)
В сингле ещё размер менялся, а этого, увы, в сампе не сделать.
Блестящая работа!
ziggi, если не сложно, напиши пожалуйста, что используется в коде, дабы разобрать код.
Побитовые сдвиги вижу (или как правильно назвать :)))
http://forum.sa-mp.com/showthread.php?t=177523 - тут расписана бинарная система и битовые операции
punkochel
29.05.2020, 23:41
Описание:
Функция отправляет сообщение ближайшим игрокам вычисляя цвет, интенсивность которого завит от расстояния.
Параметры:
playerid - игрок, от которого идёт сообщение
Float:max_range - максимальное расстояние, на котором будет отправлено сообщение
color - базовый цвет
string[] - сообщение
Float:max_ratio = 1.6 (не обязательный) - коэффициент уменьшения интенсивности цвета
Возвращаемое значение:
Функция возвращает 0, если playerid не подключен, в остальных случаях возвращается 1.
Код:
stock ProxDetector(playerid, Float:max_range, color, const string[], Float:max_ratio = 1.6)
{
new
Float:pos_x,
Float:pos_y,
Float:pos_z,
Float:range,
Float:range_ratio,
Float:range_with_ratio,
clr_r, clr_g, clr_b,
Float:color_r, Float:color_g, Float:color_b;
if (!GetPlayerPos(playerid, pos_x, pos_y, pos_z)) {
return 0;
}
color_r = float(color >> 24 & 0xFF);
color_g = float(color >> 16 & 0xFF);
color_b = float(color >> 8 & 0xFF);
range_with_ratio = max_range * max_ratio;
#if defined foreach
foreach (new i : Player) {
#else
for (new i = GetPlayerPoolSize(); i != -1; i--) {
#endif
if (!IsPlayerStreamedIn(playerid, i)) {
continue;
}
range = GetPlayerDistanceFromPoint(i, pos_x, pos_y, pos_z);
if (range > max_range) {
continue;
}
range_ratio = (range_with_ratio - range) / range_with_ratio;
clr_r = floatround(range_ratio * color_r);
clr_g = floatround(range_ratio * color_g);
clr_b = floatround(range_ratio * color_b);
SendClientMessage(i, (color & 0xFF) | (clr_b << 8) | (clr_g << 16) | (clr_r << 24), string);
}
SendClientMessage(playerid, color, string);
return 1;
}
Примечания:
Функция поддерживает любые комбинации цветов, прозрачность переданного цвета остаётся не тронутой.
Пример использования:
CMD:say(playerid, params[])
{
ProxDetector(playerid, 20.0, 0xFFAA99FF, params);
return 1;
}
Автор: ziggi
Решение отличное, но есть способ который на чуть чуть быстрее работает, но приходится вписывать цвета самому.
Код функции:
stock ProxDetector(Float:radi, playerid, const string[], color1, color2, color3, color4, color5)
{
if(IsPlayerConnected(playerid))
{
static Float:posx, Float:posy, Float:posz, Float:oldposx, Float:oldposy, Float:oldposz, Float:tempposx, Float:tempposy, Float:tempposz;
GetPlayerPos(playerid, oldposx, oldposy, oldposz);
foreach(new i: Player)
{
if(IsPlayerConnected(i))
{
if(GetPlayerVirtualWorld(playerid) == GetPlayerVirtualWorld(i))
{
GetPlayerPos(i, posx, posy, posz);
tempposx = (oldposx -posx);
tempposy = (oldposy -posy);
tempposz = (oldposz -posz);
if(((tempposx < radi/16) && (tempposx > -radi/16)) && ((tempposy < radi/16) && (tempposy > -radi/16)) && ((tempposz < radi/16) && (tempposz > -radi/16))) {
SendClientMessage(i, color1, string);
}
else if(((tempposx < radi/8) && (tempposx > -radi/8)) && ((tempposy < radi/8) && (tempposy > -radi/8)) && ((tempposz < radi/8) && (tempposz > -radi/8))) {
SendClientMessage(i, color2, string);
}
else if(((tempposx < radi/4) && (tempposx > -radi/4)) && ((tempposy < radi/4) && (tempposy > -radi/4)) && ((tempposz < radi/4) && (tempposz > -radi/4))) {
SendClientMessage(i, color3, string);
}
else if(((tempposx < radi/2) && (tempposx > -radi/2)) && ((tempposy < radi/2) && (tempposy > -radi/2)) && ((tempposz < radi/2) && (tempposz > -radi/2))) {
SendClientMessage(i, color4, string);
}
else if(((tempposx < radi) && (tempposx > -radi)) && ((tempposy < radi) && (tempposy > -radi)) && ((tempposz < radi) && (tempposz > -radi))) {
SendClientMessage(i, color5, string);
}
}
}
}
}
return 1;
}
Пример использования:
CMD:shout(playerid, params[])
{
if(sscanf(params, "s[137]", params[0])) return SCM(playerid, COLOR_WHITE, "Введите: /s(hout) [текст]");
new string[19+(-2+MAX_PLAYER_NAME)+(-2+3)+(-2+96)+1];
format(string, sizeof(string), "Крик: %s!", params[0]);
ProxDetector(60.0, playerid, string, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xE6E6E6E6, 0xC8C8C8C8);
return 1;
}
Тесты скорости.
Код сравнения:
// Кол-во итераций в циклах.
const PROFILER_ITERATIONS_MAJOR = 10_000;
const PROFILER_ITERATIONS_MINOR = 1_000;
// Названия отрывков кода.
new const code_snippets_names[2][] =
{
{"ProxDetector by ziggy"},
{"ProxDetector"}
};
// Здесь вы можете объявить переменные, используемые в профилируемых отрывках кода
// и выполнить некоторые действия непосредственно перед профилированием.
#define Prerequisites();\
/*
Собственно, сами отрывки кода, которые нужно тестировать.
Если код состоит из нескольких строк, переносите их обратным слэшем.
Пример:
#define CodeSnippet1();\
DoSomething();\
DoSomethingElse();
*/
#include <a_samp>
#include "../sources/include/foreach.inc"
#define COLOR_WHITE 0xFFFFFFFF
#define CodeSnippet0();\
ProxDetector(0, 20.0, COLOR_WHITE, "params");
#define CodeSnippet1();\
ProxDetector_2(60.0, 0, "string", COLOR_WHITE,COLOR_WHITE,COLOR_WHITE,COLOR_WHITE,COLOR_WHITE);
stock ProxDetector(playerid, Float:max_range, color, const string[], Float:max_ratio = 1.6)
{
new Float:pos_x, Float:pos_y, Float:pos_z, Float:range, Float:range_ratio, Float:range_with_ratio,
clr_r, clr_g, clr_b, Float:color_r, Float:color_g, Float:color_b;
if (!GetPlayerPos(playerid, pos_x, pos_y, pos_z)) {
return 0;
}
color_r = float(color >> 24 & 0xFF);
color_g = float(color >> 16 & 0xFF);
color_b = float(color >> 8 & 0xFF);
range_with_ratio = max_range * max_ratio;
foreach (new i:Player) {
if (!IsPlayerStreamedIn(playerid, i)) {
continue;
}
range = GetPlayerDistanceFromPoint(i, pos_x, pos_y, pos_z);
if (range > max_range) {
continue;
}
range_ratio = (range_with_ratio - range) / range_with_ratio;
clr_r = floatround(range_ratio * color_r);
clr_g = floatround(range_ratio * color_g);
clr_b = floatround(range_ratio * color_b);
SendClientMessage(i, (color & 0xFF) | (clr_b << 8) | (clr_g << 16) | (clr_r << 24), string);
}
SendClientMessage(playerid, color, string);
return 1;
}
stock ProxDetector_2(Float:radi, playerid, const string[], color1, color2, color3, color4, color5)
{
if(IsPlayerConnected(playerid))
{
static Float:posx, Float:posy, Float:posz, Float:oldposx, Float:oldposy, Float:oldposz, Float:tempposx, Float:tempposy, Float:tempposz;
GetPlayerPos(playerid, oldposx, oldposy, oldposz);
foreach(new i: Player)
{
if(IsPlayerConnected(i))
{
if(GetPlayerVirtualWorld(playerid) == GetPlayerVirtualWorld(i))
{
GetPlayerPos(i, posx, posy, posz);
tempposx = (oldposx -posx);
tempposy = (oldposy -posy);
tempposz = (oldposz -posz);
if(((tempposx < radi/16) && (tempposx > -radi/16)) && ((tempposy < radi/16) && (tempposy > -radi/16)) && ((tempposz < radi/16) && (tempposz > -radi/16))) SendClientMessage(i, color1, string);
else if(((tempposx < radi/8) && (tempposx > -radi/8)) && ((tempposy < radi/8) && (tempposy > -radi/8)) && ((tempposz < radi/8) && (tempposz > -radi/8))) SendClientMessage(i, color2, string);
else if(((tempposx < radi/4) && (tempposx > -radi/4)) && ((tempposy < radi/4) && (tempposy > -radi/4)) && ((tempposz < radi/4) && (tempposz > -radi/4))) SendClientMessage(i, color3, string);
else if(((tempposx < radi/2) && (tempposx > -radi/2)) && ((tempposy < radi/2) && (tempposy > -radi/2)) && ((tempposz < radi/2) && (tempposz > -radi/2))) SendClientMessage(i, color4, string);
else if(((tempposx < radi) && (tempposx > -radi)) && ((tempposy < radi) && (tempposy > -radi)) && ((tempposz < radi) && (tempposz > -radi))) SendClientMessage(i, color5, string);
}
}
}
}
return 1;
}
Результат теста:
Тестирование: <ProxDetector by ziggy> vs <ProxDetector>
Режим: интерпретируемый, 10000x1000 итераций.
ProxDetector by ziggy: 4755
ProxDetector: 3313
Автор функции: неизвестен
Daniel_Cortez
30.05.2020, 10:58
Решение отличное, но есть способ который на чуть чуть быстрее работает, но приходится вписывать цвета самому.
Зато читабельность кода хромает.
Исполнение тоже такое себе. Очень сомневаюсь, что такой код может быть производительнее варианта из 1-го поста. Каким образом проводилось тестирование? Сколько игроков/ботов было подключено? В каком радиусе они были от контрольного игрока, на котором тестировалась функция?
Powered by vBulletin® Version 4.2.0 Copyright © 2024 vBulletin Solutions, Inc. All rights reserved. Перевод: zCarot