Re: спрайты

Ну вот например:
в start:

        sprite.compose(w_f_r, instpic, 0, 0);  -- наложили на instpic w_f_r
        sprite.compose(dark, instpic, 0, 0); -- наложили dark

-- теперь в instpic комбинация

pic = ...
  p(instpic)
Upd:
То что ты хочешь делается, но спрайтами.

Спрайтами можно делать что угодно, инстед не расчитан на комбинацию двух подходов. Поэтому или все спрайтами, или все через ';'

В доке по спрайтам есть пример, поизучай его.

27 (edited by malcolm 2013-02-06 13:25:03)

Re: спрайты

данное сообщение я написал до того, как прочитал твой ответ выше:


я правильно понимаю, что copy/draw/combine можно использовать между спрайтами? т.е. я имею некий спрайт "a" и спрайт "b". Я создаю временный буферный спрайт "с" и копирую в него спрайт "а", потом на него делаю combine спрайт "b". В результате получаю спрайт "c", представляющий собой совмещенные спрайты "a" и "b".
Далее. Опыт выше показал, что приравнивание pic к ОДНОМУ спрайту - работает. Значит я присваиваю pic спрайт "с" и вуаля, получаю то, что хочу...

вот только вуаля у меня не выходит sad

Re: спрайты

Во втором примере спрайтами это есть. Почитай.

Когда ты рисуешь a в b - меняется b. Если ты не хочешь менять b, создавай c с помощь dup или new, а потом draw/copy/compose a->c. При этом pic всегда возвращает c. Ты рисуешь прямо на рисунке c, когда ты что то меняешь, картинка поменяется прямо на экране. c нужно создать ОДИН раз и присвоить pic. А потом рисовать рисовать рисовать в c.

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

29 (edited by malcolm 2013-02-06 14:00:06)

Re: спрайты

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

Второе. Но очень хочется разобраться. На составных pic я уже сделал то что хотел и очень доволен собой. Теперь хочу улучшить результат, переведя всё на спрайты.

Понял свою ошибку!
Я вместо

sprite.compose(a, c, 0, 0);

делал

c = sprite.compose(a, c, 0, 0);

я почему то решил, что sprite.compose присваивает спрайту значение двух смешенных спрайтов. Одним из которых может быть и сам спрайт. Не подумал, что эту функцию надо вызывать саму по себе, без присваивания.
т.е. я рассуждал как с переменными. Чтобы увеличить a на b нужно написать:
a = a + b

кстати, в GML была удобная укороченная форма. Вместо a = a + b можно было написать a += b. В lua подобного нет?


На спрайты я хочу перейти, потому что меня не устраивает время, затрачиваемое на обновление картинки. Моими эталонами считаю уже многократно названные в соседних темах wizardry7 и Lands Of Lore. И там была возможность очень быстро перемещаться по клеткам. В моей же реализации лабиринта от момента, как я вошел в новую клетку, до того, как смогу перейти в следующую, проходит слишком много времени. На рабочем компе - еще более менее терпимо, но все равно не сразу, а на домашнем - вообще тормоза sad

Когда ты рисуешь a в b - меняется b. Если ты не хочешь менять b, создавай c с помощь dup или new, а потом draw/copy/compose a->c. При этом pic всегда возвращает c. Ты рисуешь прямо на рисунке c, когда ты что то меняешь, картинка поменяется прямо на экране. c нужно создать ОДИН раз и присвоить pic. А потом рисовать рисовать рисовать в c.

Да, это я понял сразу. Так пытался сделать, но не получилось, а почему - см. выше.

30 (edited by malcolm 2013-02-06 16:54:40)

Re: спрайты

Неожиданная проблема.

Поменял отображение стен в своем лабиринте. Раньше код выглядел так:

r5_5 = room {
    pic = function()
        if (faceto == 'N') then
            p (sky, w3_r, w2_c, w2_l);
        elseif (faceto == 'W') then
            p (sky, w3_l, w2_c, w2_r);
        elseif (faceto == 'S') then
            p (sky, w6_l, w6_r, w5_l, w5_r, w4_l, w4_r, w3_l, w3_r, w2_r);
        else
            p (sky, w6_l, w6_r_r, w5_r, w4_c, w4_l, w3_l, w3_r, w2_l);
        end;
    end;

теперь он выглядит так:

r5_5 = room {
    pic = function()
            view = sprite.dup(sky);
        if (faceto == 'N') then
            sprite.compose(w3_r, view, 0, 0);
            sprite.compose(w2_c, view, 0, 0);
            sprite.compose(w2_l, view, 0, 0);
        elseif (faceto == 'W') then
            sprite.compose(w3_l, view, 0, 0);
            sprite.compose(w2_c, view, 0, 0);
            sprite.compose(w2_r, view, 0, 0);
        elseif (faceto == 'S') then
            sprite.compose(w6_l, view, 0, 0);
            sprite.compose(w6_r, view, 0, 0);
            sprite.compose(w5_l, view, 0, 0);
            sprite.compose(w5_r, view, 0, 0);
            sprite.compose(w4_l, view, 0, 0);
            sprite.compose(w4_r, view, 0, 0);
            sprite.compose(w3_l, view, 0, 0);
            sprite.compose(w3_r, view, 0, 0);
            sprite.compose(w2_r, view, 0, 0);
        else
            sprite.compose(w6_l, view, 0, 0);
            sprite.compose(w6_r_r, view, 0, 0);
            sprite.compose(w5_r, view, 0, 0);
            sprite.compose(w4_c, view, 0, 0);
            sprite.compose(w4_l, view, 0, 0);
            sprite.compose(w3_l, view, 0, 0);
            sprite.compose(w3_r, view, 0, 0);
            sprite.compose(w2_l, view, 0, 0);
        end;
        p(view);
    end;

Прилагаю две картинки, как выглядело раньше и как выглядит сейчас.

Кажется это из-за того, что спрайты больше, чем поле вывода изображения. Т.е. картинка перестала масштабироваться! Это, конечно, решаемо подгонкой размеров спрайтов до нужного, но это значит, что игра становится жестко привязана к моей теме! И будут проблемы при попытке играть, например, на андроиде.

Как заставить спрайты автоматически масштабироваться под тему?

Post's attachments

Attachment icon after.JPG 71.47 kb, 108 downloads since 2013-02-06 

Attachment icon before.JPG 78.52 kb, 146 downloads since 2013-02-06 

Re: спрайты

1) в твоем коде утечка памяти, так как ты каждый раз создаешь новый спрайт и не освобождаешь его. Тебе нужно создать view ОДИН раз и всегда в него рисовать. Вообще - идеально делать это в одной комнате. Или работать с game.pic. Можно конечно освобождать спрайт, но вообще создание на каждый кадр спрайта это не тот путь - тк ты теряешь в скорости.

2) масштабирование спрайтов и pic разное - об этом написано в базовой доке (там где pic). Использование спрайтов - почти всегда привязка к теме. Масштабирование темы будет масштабировать спрайты, но автоматич подстройки спрайта под любую тему не будет.

Суть спрайтов - в скорости и полном контроле, за это приходится платить привязкой к теме (не к размеру темы ). Но в принципе - рисование лабиринтов как основной иллюстрации - это уже путь к спрайтам.

Если бы инстед автоматически масштабил спрайты как и pic, выигрыш в скорости будет минимальным. Кстати, тормоза с pic возможно объяснялись тем, что твой pic каждый раз масштабировался к выгодному размеру. Потому как даже базового pic для отрисовки нескольких кадров в сек должно быть вполне достаточно.

32 (edited by malcolm 2013-02-06 18:09:59)

Re: спрайты

1) в твоем коде утечка памяти, так как ты каждый раз создаешь новый спрайт и не освобождаешь его. Тебе нужно создать view ОДИН раз и всегда в него рисовать. Вообще - идеально делать это в одной комнате. Или работать с game.pic. Можно конечно освобождать спрайт, но вообще создание на каждый кадр спрайта это не тот путь - тк ты теряешь в скорости.

Спасибо, поправлю. Т.е. вместо dup лучше  copy? Тогда такой вопрос, если я сначала сделал в глобал:
    var_w2_c = ('gfx/w2_c.png');
потом в старт:
    w2_c = sprite.load(var_w2_c );

а потом, при некоторых обстоятельсвах, меняю путь в var_w2_c и снова прогружаю w2_c = sprite.load(var_w2_c ); - это тоже утечка? Лучше тогда рисовать с замещением? (sprite.copy) а sprite.load вызывать только в start?

А когда я закрываю игру - память надеюсь освобождается сама? Или надо еще прописать где-нибудь, чтобы перед выходом из инстед спрайты удалялись?

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

2) масштабирование спрайтов и pic разное - об этом написано в базовой доке (там где pic). Использование спрайтов - почти всегда привязка к теме. Масштабирование темы будет масштабировать спрайты, но автоматич подстройки спрайта под любую тему не будет.

ок, понял.

рисование лабиринтов как основной иллюстрации - это уже путь к спрайтам.

я пришел к такому же выводу, когда узнал, что наборный pik каждый раз грузит с диска.

Если бы инстед автоматически масштабил спрайты как и pic, выигрыш в скорости будет минимальным. Кстати, тормоза с pic возможно объяснялись тем, что твой pic каждый раз масштабировался к выгодному размеру. Потому как даже базового pic для отрисовки нескольких кадров в сек должно быть вполне достаточно.

Хм... об этом я не подумал. Надо будет поэкспериментировать с нормальными размерами. В любом случае нынешняя графика в лабирине - временная. Я буду рисовать свою, чтоб не зависить от копирайтов.
Но как ты сказал выше - "рисование лабиринтов как основной иллюстрации - это уже путь к спрайтам."


Да, и еще! Правильно ли я понимаю, что sprite.draw для моих целей подходит лучше чем sprite.compose? В спрайте sky у меня нет прозрачности, так что мне достаточно рисовать каждый следующий слой с прозрачностью, так? И это будет быстрее, чем sprite.compose?

Re: спрайты

Утечка это load/dup/new без последующего  free. В конце игры все освободиться само. Надо лишь следить за тем, чтоб в алгоритме не было бесконечного накопления load/dup/new.. В твоем варианте это было по каждому показу pic.

Re: спрайты

Так, стоп... Композ тоже утечку вызывает? Тогда я не понимаю фразы "создать view и в него рисовать". Разве композом я не рисую в спрайт? Как тогда? Через draw? Или каждый раз free? Но как тогда понимать твои слова, что это приводит к доп. тормозам?
Вообще не понимаю, почему они накапливаются, если я рисую в один и тот же спрайт >_<

Re: спрайты

Про compose описка. smile

36 (edited by z-Hunter 2013-02-06 20:02:42)

Re: спрайты

Да там нет ничего сложного на самом деле smile

Сначала автоматически считываем все спрайты, имена которых указаны в массиве  local names{} , в глобальный массив spr.


global {
    spr={}
};


function spriteload(pat)
    local ret = sprite.load(pat);
    if not ret then error ("spriteload(): Cannot load "..pat);  end;
    return ret;
end;

function sprites_init()
        
        local path = "./pic/"; local ext = ".png";
        local names = {
            
            "name1",
            "name2",
            "etc",        
        };

        for _, v in pairs(names) do
            spr[v] = spriteload(path..v..ext);
        end;    
end;


start = function ()
    sprites_init()
end;

Теперь мы имеем массив спрайтов. В частности, spr.name1 ; spr.name2 и тд.

копируем первый спрайт во временную переменную:

local SP = sprite.dup(spr.name1);

Совмещаем второй спрайт с содержимым переменной:

sprite.copy(spr.name2, SP);

Совмещаем третий спрайт в первымя двумя в переменной:

sprite.copy(spr.etc, SP);

А теперь можно делать pic = SP;
Вот и всё.

37 (edited by z-Hunter 2013-02-06 20:11:47)

Re: спрайты

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

Лучше сделать ОДНУ комнату-плеер, чем генерировать скриптом кучу комнат. Ибо геморой будет накапливаться с каждым шагом, поверь.
В этом нет ничего особо сложного. Если что-то непонятно - просто спрашивай.
Или подожди моей реализации smile.

Re: спрайты

z-Hunter: local SP = sprite.dup(spr.name1);
Только надо помнить, что потом надо будет сделать free, если конечно это не однажды делается. Те в твоем примере, если мы постоянно делаем dup и присваиваем pic, мы постепенно выжираем память.

Более прямой путь, pic всегда один и тот же спрайт, в который мы рисуем. Вместо dup тогда делаем copy.

Re: спрайты

А у меня разве не в один спрайт всё рисуется? Всегда в SP.

40 (edited by malcolm 2013-02-06 21:18:40)

Re: спрайты

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

Ну пока не копится smile наоборот, пока что все просто. С выводом графики я бы и с единой комнатой мучался.
Твою реализацию обязательно посмотрю, потому что работа близкая к тому, что я делаю.
Кстати еще интересно как ты карту рисуешь.  Я тоже хотел карту делать в своей игре.
Суть в чем - я хочу в клетках хранить много чего. Информацию о мобах убитых, о вещах, которые игрок выбросил, о НПС. Плюс специальные комнаты, в которых может что-то происходить. Ну правда, я даже на уровне алгоритма не могу придумать как сделать это в виде одной комнаты-плеера.

Пока в моей реализации только два потенциальных минуса:
1. Размер. Одна карта уже сейчас занимает 400-700 килобайт. На игру будет не менее 5 карт, а скорее всего около 10-15. Для текстовой игры 15 мегабайт - это много. А плюс же еще графика и звук!
2. Не уверен, что инстед сможет достаточно быстро обрабатывать такое количество комнат. На одну даже не большую карту приходится не менее 20-30 комнат. Значит вся игра будет состоять из нескольких сотен комнтат. Справится ли инстед с этим? С одной стороны не используемые комнаты в коде должны игнорироваться, пока не будут вызваны... Но все равно при каждом такте прогоняется вся программа и это не есть хорошо, когда в программе тысячи строк.
Возникает вопрос - можно ли динамически подключать и отключать файлы в инстеде? Я пока понял как пользоваться dofile - подключать файл, который прогоняется каждый такт. По сути программа увеличивается на содержимое этого файла.
Как пользоваться gamefile я пока не понял. Вроде как можно заменить главный исполняймый файл... а можно ли подменить один файл другим?
т.е. у меня есть main.lua и map.lua. Я хочу ВЫГРУЗИТЬ файл map.lua и вместо него подключить map2.lua, не трогая main.lua, а так же другие задействованные файлы - можно ли это сделать? Если да, то вторая проблема решается. Остается только проблема с размером.

А у меня разве не в один спрайт всё рисуется? Всегда в SP.

Во! Я тоже в недоумении! Я же так же сделал выше! Но раз Пётр говорит, что это жрет память, у меня нет оснований этому не верить.

Re: спрайты

z-Hunter wrote:

А у меня разве не в один спрайт всё рисуется? Всегда в SP.

local SP = sprite.dup(spr.name1);

Если это выполняется только 1 раз, то да.

42 (edited by z-Hunter 2013-02-06 21:25:15)

Re: спрайты

Peter wrote:
z-Hunter wrote:

А у меня разве не в один спрайт всё рисуется? Всегда в SP.

local SP = sprite.dup(spr.name1);

Если это выполняется только 1 раз, то да.

Вот оно что. sprite.dup, значит, просто откусывает порцию памяти, копирует туда спрайт и возвращает хендл. А при новом присваивании этот кусок памяти окажется потерян для общества...
Тут, как мне кажется, спрятаны опасные грабли, на которые наступит почти всякий начинающий работать со спрайтами. А нельзя на уровне движка как-то организовать автоматическое отслеживание и освобождение таких кусков? В Lua же есть сборка мусора.

Re: спрайты

Именно поэтому я никогда не рекомендовал использовать спрайты. И даже не хотел их документировать. Делал я их в основном для себя. Спрайты не для начинающих! Автоматическая сборка мусора спрайтов да еще и завязанная на lua -- это утопичная цель. Когда вы используете спрайты -- это значит что вы перешли в зону настоящего программирования. В инстеде есть некоторые недокументированные вещи, которые я не описываю из тех же соображений. Считайте спрайты внутренним механизмом, который будет использоваться для каких-то простых спрайтов, написанных уже на lua.... Пример такого "безопасного" модуля -- fonts. Те написать что то подобное можно, но на данный момент мне не интересно этим заниматься.

В общем, еще раз напоминаю. Я призываю писать простые игры.

Re: спрайты

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

Re: спрайты

А я и не запрещаю. Я литературно напоминаю, что спрайты уже требуют программистких навыков. smile Вообще, в докции все это есть, хоть и кратко.

Re: спрайты

Мы еще не настоящие программисты, мы еще только учимся!

Re: спрайты

Это действительно хорошо! Значит, INSTEAD также играет роль кружка программирования. smile

48 (edited by z-Hunter 2013-04-27 22:37:15)

Re: спрайты

S = sprite.load("mysprite.png");      -- тут у нас спрайт

local SP = sprite.dup(S);       -- копируем его и записываем хендл копии в SP
p( img(SP) );                      -- выводим копию спрайта на экран
sprite.free(SP);                  -- освобождаем мир от копии

Вместо спрайтов выводит на печать текстом что-то типа <g:spr:f00ac74f> (наверное хендл покойного спрайта). Если убрать последнюю строку, то печатается сам спрайт. Почему так происходит? Мы же его сначала печатаем, а потом уничтожаем, а не наоборот.

Re: спрайты

Движок INSTEAD событийный, а не процедурный. p() висит не в воздухе, а в обработчике, который вызывается движком в нужное время.

Например, представим, что в твоем примере  p() вызывается из act. Это значит, что движок возьмет весь вывод act и будет использовать его так, как нужно ему. Это будет время, точно после выполнения act, в это время спрайта уже нет.

Вообще p - это просто удобная форма сделать return "текст". p - накапливает текст в буфере и после завершения обработчика - этот буфер воспринимается как возвращаемое значение.

50 (edited by z-Hunter 2013-04-28 15:44:27)

Re: спрайты

Гм... Тогда непонятно, почему если вызвать вот это из dsc

S[1] = sprite.load("mysprite1.png");        
S[2] = sprite.load("mysprite2.png");        
S[3] = sprite.load("mysprite3.png");        

for i=1, 3 do
     local SP = S[i]; 
     p( img(SP)  );
end

то печатается три разных спрайта, а не один.


Хотя... кажется понял. Ты же про это и сказал. Потому, что все три спрайта на момент вывода dsc живы.
Тогда вопрос, что делать в предыдущем примере с копией спрайта которая в SP? Если не делать free то будет работать, но при этом будет утекать память при каждом sprite.dup().

Единственное, что приходит на ум, это перенести объявление SP = sprite.dup(S) в область глобальных переменных, а заодно и S тоже.

P.S. Нет, так не выходит делать p (img(SP)). На выводе dsc получаются пустые спрайты.

P.P.S. Когда разберусь с этой премудростью видимо сделаю к sprites обёрточный модуль "безопасных" спрайтов. А то тут таких дров можно нарубить...:)