Sign in to follow this  
Followers 0
Sleash

"Найти ближайший дом"

4 posts in this topic

Всем снова доброго времени суток. на этот раз хотел бы опубликовать свою версию поиска ближайшего свободного дома в PAWN.

Для начала приступим к enum, НО предупрежу, что у вас может быть не такие переменные и прошу их заменить, если будите копи-пастить мой код.

enum hInfo
{
Float:hEntrancex,   // Координаты входа по оси X
Float:hEntrancey,   // Координаты входа по оси Y
Float:hEntrancez,   // Координаты входа по оси Z
    hOwned,         // Имеет ли дом кто-то (ДА - 1 || НЕТ - 0)
};
new HouseInfo[2000][hInfo];

Дальше уже сам код поиска, сделаю в стиле команды, хотя изначально у меня это был пункт в /gps

CMD:nearesthouse(playerid)
{
    for(new Float:radi = 0.0; radi < 8485.0; radi++)
    {
        new n; // переменная "Найдено"
        for(new bp = 0; bp < sizeof(HouseInfo); bp++)
        {
            new Float:px, Float:py, Float:pz;
            GetPlayerPos(playerid, px,py,pz);
            if(PosToPoint(radi, px, py, pz, HouseInfo[bp][hEntranceX], HouseInfo[bp][hEntranceY], HouseInfo[bp][hEntranceZ]) && HouseInfo[bp][hOwned] == 0)
            {
                SetPlayerCheckpoint(playerid, HouseInfo[bp][hEntranceX], HouseInfo[bp][hEntranceY], HouseInfo[bp][hEntranceZ], 3.0);
                SendClientMessage(playerid, COLOR_WHITE, "{9ACD32}[GPS] {FFFFFF}Место на карте помечено красной меткой");
                n = 1// устанавливаем "найдено"
                break;
            }
        }
        if(n == 1// Если найден дом
        {
            break// закрываем цикл
        }
    }
}

Давайте разберём одну неясную тут вещь: переменная n;

Дело в том, что тут 2 цикла:

1. Берёт определённый радиус в округе игрока.

    1.2. Ищет незанятый дом в данном радиусе.

И если при нахождении такого дома мы можем с помощью break; выпрыгнуть из этого цикла. то уже первый цикл снова его запустит, и поэтому нам нужна переменная, которая будет сообщать вне цикла 1.2 найден ли был дом.

Теперь перейдём к стоку, который используется в команде (просто киньте его в конец мода):

stock PosToPoint(Float:radi, Float:oldposx, Float:oldposy, Float:oldposz, Float:x, Float:y, Float:z)
{
    new Float:tempposx, Float:tempposy, Float:tempposz;
    tempposx = (oldposx -x);
    tempposy = (oldposy -y);
    tempposz = (oldposz -z);
    if (((tempposx < radi) && (tempposx > -radi)) && ((tempposy < radi) && (tempposy > -radi)) && ((tempposz < radi) && (tempposz > -radi))) return true;
    return false;
}

 

Share this post


Link to post
Share on other sites

@Sleash`en, задача поиска ближайшего объекта достаточно часто может пригождаться. То, что Вы привязались к домам, лишь вносит лишние зависимости. Наверное, стоило двигаться в более глобальном направлении: решение задачи поиска ближайшего объекта. И делать это непосредственно на примере системы домов.

 

Давайте посчитаем, сколько раз выполниться следующий участок кода:

new Float:px, Float:py, Float:pz;
GetPlayerPos(playerid, px,py,pz);
if(PosToPoint(radi, px, py, pz, HouseInfo[bp][hEntranceX], HouseInfo[bp][hEntranceY], HouseInfo[bp][hEntranceZ]) && HouseInfo[bp][hOwned] == 0)
{
    SetPlayerCheckpoint(playerid, HouseInfo[bp][hEntranceX], HouseInfo[bp][hEntranceY], HouseInfo[bp][hEntranceZ], 3.0);
    SendClientMessage(playerid, COLOR_WHITE, "{9ACD32}[GPS] {FFFFFF}Место на карте помечено красной меткой");
    n = 1// устанавливаем "найдено"
    break;
}

Если на сервере есть хотя бы 100 домов (то есть sizeof HouseInfo = 100), тогда указанный код будет исполняться (по крайней мере его часть) 8485*100=848500 раз. А зачем? Можно было бы обойтись 100 итерациями. Для этого было достаточно лишь получать расстояние между объектами, сохраняя минимальное, и потом установить точку на дом, расстояние до которого минимально. Что-то вроде такого:

Спойлер

stock getDistanceFromPointToPoint(Float:xA, Float:yA, Float:zA, Float:xB, Float:yB, Float:zB) {
    return (floatsqroot(floatpower(xB - xA, 2) + floatpower(yB - yA, 2) + floatpower(zB - zA, 2)));
}

stock setPosToNereastHouse(playerid) {
    new houseid = -1;
    new Float:minDistance = cellmax;

    new Float:x, Float:y, Float:z;
    GetPlayerPos(playerid, x, y, z);

    for (new i = 0, Float:distance; i < sizeof HouseInfo; i++) {
        distance = getDistanceFromPointToPoint(x, y, z, HouseInfo[i][hX], HouseInfo[i][hY], HouseInfo[i][hZ]);
        if (distance < minDistance) {
            houseid = i;
            minDistance = distance;
        }
    }

    if (houseid == -1) {
        return SendClientMessage(playerid, -1"К сожалению, ближайший дом не найден") & 0;
    }

    SetPlayerCheckpoint(playerid, HouseInfo[houseid][hX], HouseInfo[houseid][hY], HouseInfo[houseid][hZ]);
    SendClientMessage(playerid, -1"Точка до ближайшего дома установлена");
    return 1;
}

 

 

Share this post


Link to post
Share on other sites

@Cawfee Вы правы, но я был "ограничен", точнее брал то, что было под рукой, к тому же и не думал о стоке о поиске расстояния.

Share this post


Link to post
Share on other sites

При добавлении данной команды в свой мод результата никого не будет. Невозможно угадать как реализовано та или иная система у человека. Какой-то непонятный массив, непонятные координаты, производится цикл, когда можно обойтись и без него. Грубо говоря, очередная вырезка. Хочу посоветовать на будущее, никогда не создавайте переменные внутри цикла, к хорошему это уж точно не приведёт. Да и количество максимальных домов стоило вывести под константу, чтобы потом не мучатся и не искать каждую строку дабы изменить максимальное значение. ^_^

Edited by LoX_1337

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.

  • Similar Content

    • bogdan@gmail
      By bogdan@gmail
      Ошибки при компиляции
       

    • DAYREK
      By DAYREK
      Приветствую, подготовили для вас игровой сайт. Все сделано с нуля.
       
      В систему входит:
      - Главная страница.
      - Магазин.
      - Новости.
      - Личный кабинет.
      Все системы работают, в личном кабинете отображаются данные о игроке, имущество, статистика и прочее, добавите туда по своему желанию еще что-нибудь.

      Основные языки системы:
      - HTML, CSS, JS, PHP
      База данных MySQL
       
      Если я увижу потенциал в данном сайте, буду выпускать обновления. Добавлю систему ЛК для администратора, с отслеживанием логов админов и игроков.
      Изменением настроек сервера и сайта, изменение темы сайта и прочее.

      Связь со мной тык