singlepost

Help me please {JavaSсript} << На главную или назад  

Уважаемые, помогите решить задачу.
Необходимо создать нечто вроде карты, поля как в игре морской бой. На "карте" присутствуют перемещаемые объекты, нужно сделать так, чтобы эти объекты при перемещении никогда не вставали друг на друга. Ломал моск весь день, но никак не смог увязать между собой координаты Х и Y объектов. Максимум до чего в истериках дополз сам:

mZY = new Array(); mZX = new Array();
function umap(id) {
mH = document.body.clientHeight;
mW = document.body.clientWidth;
for(i=0;i<=mW;i=i+1) { if(mZX[i]==id) { mZX[i] = '';}}
for(i=0;i<=mH;i=i+1) { if(mZY[i]==id) { mZY[i] = '';}}
}

function map(mY,mX,id) {
mH = document.body.clientHeight;
mW = document.body.clientWidth;
for(i=mX;i<=mX+22;i=i+1) {
if(mZX[i]&&mZX[i]!=id) {
mZX[i+22]=id;
document.getElementById(id).style.left=i;
} else { mZX[i]=id;}
}
for(i=mY;i<=mY+22;i=i+1) {
if(mZY[i]&&mZY[i]!=id) {
mZY[i+22]=id;
document.getElementById(id).style.top=i;
} else { mZY[i]=id;}
}
}

При перемещении объекта вызывается функция map, где mY,mX – новые кооринаты объекта, id – его ид. Одновременно вызывается функция umap. Ф-я map присваивает ячейке массивов, соответствующей координате по оси Х или Y, ИД перемещаемого элемента, при этом проверяется не занята ли ячейка; Ф-я umap удаляет старые значения.

i<=mY+22 – сдесь 22 – ширина и высота объектов.

mZX[i+22]=id;
document.getElementById(id).style.left=i; – попытался сделать запрет на перемещение, если ячейка занята другим объектом. По идее объект должен отталкиваться от занятых ячеек. Работает ужасно криво.

Вроде что-то получилось, но тут косяк в том, что объект с координатами 10х20 на "карте" занимает пространство не 22х22 пикселей, а все иксы с игриком=20 и все Y с Х=10.

Скажите, я вообще в правильном направлении изобретаю велосипед?
Еси я не разберусь с этим, то вскоре моя клавиатура получит сотресение кнопок, а на голове не останеться волос :-)

25 ответов в теме “Help me please {JavaSсript}”

  1. 25
    Александр Казанцев ответил:

    ну значит ничего необчного =)) решил отложить дела с координатами до лучших времен… буду писать дальше :-)

  2. 24
    Павел Потапов ответил:

    Именно эти объекты я и имею в виду :)

  3. 23
    Александр Казанцев ответил:

    я еще новичек в этом деле и с терминологией у меня не ахти, что понимается под HTML объектами? Выше я уже сказал что элементы обычные картинки. ЖАБАскрипт вставляет их на страницу по требованию и присваивает ID. Помойму это называется DOM, нет? :-)

  4. 22
    Александр Казанцев ответил:

    Да кстати скрипт который позволяет перемещать элементы писан не мной (стянул с нета) там как раз таки определяется какой элемент под мышкой расположен во время клика путем проверки его класса (className)

  5. 21
    Павел Потапов ответил:

    #21 Если речь о кликах мыши, то проще обрабатывать события от HTML элементов. Думаю, что браузер быстрее вычислит, что лежит под курсором, чем если делать это самостоятельно жабаскриптом. Если говорить о перемещении объектов, то тут придется перебирать объекты. А если объекты хранить в виде, приспособленном для этого, то сравнивать придется в большинстве случаев даже и не все, да и сравнения будут простые. Главный плюс – это то, что не надо будет постоянно синхронизировать объекты с полем. Что, кстати, тоже требует времени.

    ЗЫ На счет хранения объектов, сортированных по центру не уверен, возможно лучше сортировать их по одному из углов.

  6. 20
    Денис Лисов ответил:

    А определение объекта, лежащего в указанной точке, путем перебора? Да, если нет требований на быстроту поиска, это скорее всего эффективнее.

  7. 19
    Павел Потапов ответил:

    #16 Судя по описанию задачи, поле явно не надо :) Достаточно просто размещать объекты в окне так, чтобы они не пересекались :) И делать это проще, проверяя пересечения объектов. Особенно если они прямоугольные. Для ускорения перебора их даже можно хранить отсортированными по координатам центра… тогда проверка будет происходить очень быстро.

    Плюс, в таком варианте отпадает необходимость хранить координаты в матрице переменного размера…

    Оффтоп: Если не секрет, то как, не используя HTML объекты, ты выводишь свои элементы в окне?

  8. 18
    Денис Лисов ответил:

    А одномерный скушает вряд ли сильно меньше. Значений-то столько же, разве нет?

  9. 17
    Александр Казанцев ответил:

    ну мне сказали оно скушает много памяти – я испугался :)

  10. 16
    Денис Лисов ответил:

    А все-таки, почему не двумерный массив?

    var height=100, width=200;
    var i,arr;
    arr=new Array();
    for(i=0;i<height;i++) arr[i]=new Array();
    //Заполнить нулями?
    for(i=0;i<height;i++) for(i=0;i<width;i++) arr[i][j]=0;
    // Образец присвоения (строка i, столбец j, нумерация от нуля)
    arr[i][j] = 0
    // Образец считывания с выводом пользователю
    alert( arr[i][j] );

    А если элементы – обычные картинки, можно попробовать использовать средства самого браузера. Кажется, у него были функции, например, для определения верхнего элемента в заданной точке. Гарантий дать не могу, но по-моему что-то такое было.

  11. 15
    Александр Казанцев ответил:

    #14 да просто схема может не уместиться в одно окно, его нужно будет расширить… и помойму если правильно и грамотно составить формулу расчета, то изменение рабочего поля не должно создавать проблем.

    #15 Ну у меня как бы все элементы и так обычные картинки (IMG) =)

    Сейчас формула такая: Number([x]+y)+x – индексы ячеек массива никогда не повторятся (проверено), но относительно такой точки не возможно расчитать координаты следующей за ней (точнее я пока не сообразил как это сделать). Мне ведь нужно не объекту присвоить координату, а прилипить объект к координате, но только так, чтобы эту координату можно было расчитать.

  12. 14
    Павел Потапов ответил:

    Посмотрев на твой код, мне очень не понравилось, что размер поля ты определяешь на основе размера окна. Это не совсем корректно, т.к. размеры окно браузера могут изменится, а это не совсем то, чего хочется. Соответственно, лучше хранить данные в отдельном объекте, который будет за это отвечать – знать точные размеры и уметь изменять/выдавать данные.

    Если окно будет фиксированных размеров, то их тоже лучше фиксировать исходя из размеров матрицы, а не наоборот :)

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

  13. 13
    Павел Потапов ответил:

    А вариант представлять все элементы, в виде HTML элементов не рассматривался? Мне кажется, так с ними будет проще работать :) Да и рисовать их так проще, можно сделать картинки и масштабировать их до нужных размеров. Так их можно будет легко перемещать, обрабатывать клики на них… и прочее.

  14. 12
    Александр Казанцев ответил:

    ОМГ, я в шоке! уникальное имя для ячейки равно (X,Y+размер элемента) – можно обойтись одним массивом! Это же элементарно =)))

    Все контакты проводов должны будут записываться в таблицу (какой конец с каким соединен). Думаю с пересечениями проблем не возникнет.

    Всем огромное спасибо за ответы и советы!!!

  15. 11
    Денис Лисов ответил:

    Я бы предложил воспользоваться другим вариантом. Сделать сетку точек, между любыми двумя соседними из которых пользователь и включает элементы, провода и так далее. Чтобы можно было про тот же резистор задавать не координату по x, по y и угол поворота, а координаты левой/верхней вершины и флажок ориентации – вправо от нее или вниз. Сама сетка, скажем, 20×20 точек, с промежутками по 20 пикселей по горизонтали и вертикали.

    Кстати, в обоих вариантах есть проблема – пересекающиеся провода (без контакта), так как они должны проходить через одну и ту же точку.

  16. 10
    Александр Казанцев ответил:

    вот новый код, на порядок жирнее: //pastie.org/376694
    работает вроде лучше предыдущего, но сохраняется проблема с отсутствием "массива в массиве". Пока не доходит как это реализовать :[

    функция теперь вызывается не во время перемещения, а после него.
    Х,У - новые координаты
    mapX[],mapY[] – злополучные массивы с идами.
    в первом условии проверяется свободность, если занято – второе условие ищет первую свободную точку.

    А если браузер начнет тормозить, думаю брошу это дело :\
    ну или на крайний случай увязать все это дело с ПэХаПэ и временными файлами на хост-машине (я не извращенец! =))

  17. 9
    Александр Казанцев ответил:

    Простой вариант – сделать это все на cpp, ну или еще на чемнить не имеющем отношения к WEB. =)

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

    Для увязки элементов программе неоходимо знать что где располагается. Для того чтобы элементы не "терялись" друг за другом – нельзя допускать их наложения (впринципе можно и без этого обойтись)

  18. 8
    Денис Лисов ответил:

    Двумерный массив, обычное дело. Только вот памяти расходовать будет немало – JavaSсript ее не особо экономит. А для чего это нужно? Может быть, есть более простой вариант?

  19. 7
    Александр Казанцев ответил:

    мдя, переписал функцию заного и совсем ушел в сторону от основной проблемы… тут не просто нужно знать свободно пространство под объектом или нет, а нужно еще знать каким именно элементом оно занято (это уже другое условие), отсюда и вытекает > ячейка массива не может быть равна нулю или единице, она равна ИДу объекта. Но ведь по Х=10 может располагаться куча объектов с неравными игриками. Получается нужно использовать массив ИДов в массиве иксов и массиве игриков? о_0 такое возможно?

  20. 6
    Александр Казанцев ответил:

    #5 Денис, спасибо за код! Но тут еще одна фишка – объектов может быть сколько угодно, они появляются по требованию пользователя. Обязательно рассмотрю такой вариант.

    #6 Паша, не совсем вас понял, вы предлагаете сначала потренироваться на чем-нибудь маленьком? =)

  21. 5
    Павел Потапов ответил:

    Главная ошибка – это использование принципа "ветер дует от того, что деревья качаются". Вместо того, чтобы в качестве поля использовать экран произвольных размеров, лучше сделать "идеальное поле", модель поля, с которой будет удобно будет производить расчеты, какие бы они ни были. В случае с морским боем это будет просто квардратная матрица, в ячейках которой хранится информация о ее содержимом: неизвестно, корабль, "мимо". Далее, для отрисовки следует переводить "идеальное поле" в окно (либо как-то на лету, либо иметь промежуточный объект(ы)). А при обработке действий координаты сначала надо перевести в модель и уже в ней с ними работать. Несмотря на сложность конструкции, это позволит разделить задачу на несколько слабо связанных между собой: 1) модель взаимодействия, 2) представление, 3) обработка действий пользователя. 3 мелких задачи решаются проще, чем одна большая.

  22. 4
    Денис Лисов ответил:

    Не уверен, что подход с "попиксельным" сравнением оптимален. Мне кажется, что сравнение по списку объектов было бы более эффективно.

    //Точность синтаксиса не гарантирую, равно как и наименования свойств
    //objlist – список всех объектов, id – идентификатор сдвинутого
    //свойства объекта – координаты x,y; размеры width,height
    //возвращает true при правильном ходе, false при попытке "наезда"
    function validateMove(objlist, id) {
    cur=objlist[id];
    for(obj in objlist) {
    if(obj==cur) continue;
    if( (obj.x+obj.width>=cur.x&&cur.x+cur.width>=obj.x)
    &&(obj.y+obj.height>=cur.y&&cur.y+cur.height>=obj.y) )
    return false;
    }
    return true;
    }

  23. 3
    Алексей Тимофеев ответил:

    конечно если объекты различных размеров то тут сложнее, действительно нужно просто просчитывать движение объекта и совпадение координат

  24. 2
    Александр Казанцев ответил:

    морской бой я просто в качестве примера привел. Окно у пользователя может быть разных рамеров, а объекты размещаются где угодно. Про два массива вроде понятно все, а как сделать чтобы объект не залазил на другой? Тут по ходу математика нужна жесткая… у меня не получилось нормально это сделать

  25. 1
    Алексей Тимофеев ответил:

    >mH = document.body.clientHeight;
    >mW = document.body.clientWidth;

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

    Как мне кажеться для проверки на занятость ячеек нужно создать два массива забитого нулями. Первый используется как поле (с уже установленными объектами, которые буду отображаться как – 1). Второй используеться для утановки нового объекта (чистое поле с 1 – там где устанавливаеться новый объект). Далее процедура сводиться к сравнению двух массивов, где 1 совпадают, значит наезжаем на уже установленный объект.
    А далле по этим массивам и рисуем и играем.

Клуб программистов работает уже ой-ой-ой сколько, а если поточнее, то с 2007 года.