Нужен совет по псевдо 3D игрушке
Привет сижу дома, от нефиг делать мучу игрушку. Ссылка(спрайты весят 15 Mb, нужно подождать пока откроет). Проблема с которой столкнулся- карявое отображение движущихся объектов. На фоне "плиток переднего плана".
Попробую объяснить человеческим языком. Картанка состоит из 3-х канвасов наложенных друг на друга, каждый канвас составлен из "плиток". На заднем плане трава, камни и т.д. На переднем плане - дом и деревья. Между ними- коровы паладины и хз что ещё. Когда корова движется и заходит за дом с верху- она как и задумано теряется из вида, но когда она подходит с низу- то она сцуко залазит под дом. Редактор состоит из 5 глобалльных объектов var imgObj = {};//картинки var canObj = {};//канвасы var unitObj = {};//движущиеся спрайты отображённые на экране(направление, текуший номер картинки в спрайте, позиция и т.д.) var spriteObj = {};//инструкция по нарезке unitObj с imgObj (размеры фреймов, исходный img fail и т.д.) var levelObj = {};//сама карта или левел, состоит из масива отдельных плиток, одно из свойств плитки- z-index канваса на котором она будет печататся. Второй массив- walkareas -collision detection lines. Все объекты кроме канвасов загружаются с XML файлов Верхний и нижний канвасы нарезаются при запуске игры и не меняются(если не тыркатся с плитками через редактор). Для загрузки используется функци: function loadLevel() { canObj.canvas0.ctx.clearRect(0, 0, canObj.canvas0.canvas.width, canObj.canvas0.canvas.height); canObj.canvas5.ctx.clearRect(0, 0, canObj.canvas5.canvas.width, canObj.canvas5.canvas.height); canObj.canvas0.canvas.height = levelObj.level.size.x; canObj.canvas0.canvas.width = levelObj.level.size.y; canObj.canvas5.canvas.height = levelObj.level.size.x; canObj.canvas5.canvas.width = levelObj.level.size.y; for (var i in levelObj.level.map.tile) { var zisTile = levelObj.level.map.tile[i]; if (zisTile.z_index === 0) { var ctx = canObj.canvas0.ctx; }else if (zisTile.z_index === 5) { var ctx = canObj.canvas5.ctx; } drowTile(zisTile, ctx, levelObj.level.map.tile[i].tilex, levelObj.level.map.tile[i].tiley); } } function drowTile(tile, ctx, ix, iy) { //console.log(ctx); ctx.drawImage(imgObj[tile.tileimg.obj], spriteObj[tile.tileimg.obj][tile.tileimg.sprtype].sx + spriteObj[tile.tileimg.obj].width * tile.tileimg.x, spriteObj[tile.tileimg.obj][tile.tileimg.sprtype].sy + spriteObj[tile.tileimg.obj].height * tile.tileimg.y, 160, spriteObj[tile.tileimg.obj][tile.tileimg.sprtype].sheight, ix, iy, 160, spriteObj[tile.tileimg.obj][tile.tileimg.sprtype].sheight); } Рендеринг производится с помощью requestAnimationFrame() которая дёргат функцию update() и через неё stopMoving() function update(dt, now){ canObj.canvas1.ctx.clearRect(0, 0, canObj.canvas1.canvas.width, canObj.canvas1.canvas.height); for(var i in unitObj){ if (unitObj[i].vy === 0 && unitObj[i].vx === 0) { unitObj[i].action = "neutral"; } if ((now - unitObj[i].framestart)>unitObj[i].spr[unitObj[i].action].framerate){ unitObj[i].framestart = now; if (unitObj[i].framenumber < unitObj[i].spr[unitObj[i].action].numberofframes) { unitObj[i].framenumber++; var context = canObj.canvas2.canvas.getContext('2d'); var position = $(canObj.canvas2.canvas).position(); var x = unitObj[i].x + unitObj[i].vx; var y = unitObj[i].y + unitObj[i].vy; //проверяем столкновение с colision lines for (var j in levelObj.level.walkareas) { levelObj.level.walkareas[j].mouseover = false; var initx = levelObj.level.walkareas[j].initx; var inity = levelObj.level.walkareas[j].inity; var lastx = levelObj.level.walkareas[j].lastx; var lasty = levelObj.level.walkareas[j].lasty; var ang = Math.atan2((inity - lasty), (initx - lastx)); context.beginPath(); context.arc(initx, inity, 5, ang - Math.PI/2, ang +Math.PI/2); context.arc(lastx, lasty, 5, ang + Math.PI/2, ang -Math.PI/2, false); context.closePath(); if (context.isPointInPath(x, y)) { unitObj[i].vx = 0; unitObj[i].vy = 0; return; } } ////////////////////////// unitObj[i].x+=unitObj[i].vx; unitObj[i].y+=unitObj[i].vy; }else { unitObj[i].framenumber=0;} } //console.log(unitObj[i].framenumber); canObj.canvas1.ctx.drawImage(imgObj[unitObj[i].type], (unitObj[i].spr[unitObj[i].action][unitObj[i].direction].sx)+unitObj[i].framenumber*(unitObj[i].spr[unitObj[i].action].swidth), (unitObj[i].spr[unitObj[i].action][unitObj[i].direction].sy), (unitObj[i].spr[unitObj[i].action].swidth), (unitObj[i].spr[unitObj[i].action].sheight), unitObj[i].x - (unitObj[i].spr[unitObj[i].action].width)/2, unitObj[i].y - (unitObj[i].spr[unitObj[i].action].height)/2, (unitObj[i].spr[unitObj[i].action].width), (unitObj[i].spr[unitObj[i].action].height)); stopMoving(i); } } function backgroundRendering(i) { //code } function stopMoving(i){ if (unitObj[i].vx!==0 || unitObj[i].vy!==0) {//if moving //moving up left if ((unitObj[i].vx<=0 && unitObj[i].vy<=0) && ((unitObj[i].x <= unitObj[i].destX) || (unitObj[i].y <= unitObj[i].destY))) { unitObj[i].vx = 0; unitObj[i].vy = 0; } //moving up right if ((unitObj[i].vx>=0 && unitObj[i].vy<=0) && ((unitObj[i].x >= unitObj[i].destX) || (unitObj[i].y <= unitObj[i].destY))) { unitObj[i].vx = 0; unitObj[i].vy = 0; } //moving down right if ((unitObj[i].vx>=0 && unitObj[i].vy>=0) && ((unitObj[i].x >= unitObj[i].destX) || (unitObj[i].y >= unitObj[i].destY))) { unitObj[i].vx = 0; unitObj[i].vy = 0; } //moving down left if ((unitObj[i].vx<=0 && unitObj[i].vy>=0) && ((unitObj[i].x <= unitObj[i].destX) || (unitObj[i].y >= unitObj[i].destY))) { unitObj[i].vx = 0; unitObj[i].vy = 0; } } } } С такой структурой игрушки решить проблему с коровой прячушейся под дом не решить, нужно что-то менять :-/ . Рассматривал следующие варианты: перемещять плитки дама на задний план если вектор движения коровы(как звучит :lol: ) под определённым углом и её позиция... это бред потому что двигатся должна не только корова, и если несколько коров будут подходить к дому с разных сторон получится месево. второй вариант(вроде должен работать)- добавить ещё 1-н канвас поверх уже существующих и рендерить коров в зависимости от их положения относительно дома на 2-м или 4-м канвасеНо вот что до меня не доходит так это к которой точке на спрайте коровы нужно будет привязать Collision detection, либо если эта точка должна меняться- то по какому принципу? |
diablo ))
|
Если кто поможет то возможно диабло и будет, кстати если у каго не открывается или зависае браусер- напишите плз с чего сидите(ОС и броуер)
|
Необходимо хранить карту в виде матрицы, где указывать проходимые и непроходимые пути: 0 - свободно, 1 - занято(к примеру) . Для поиска пути и обхода препятствий использовать какой-нибудь матричный алгоритм(А* к примеру). Дом обозначить как непроходимую зону, чтобы можно было обойти.
Далее, необходимо сортировать по-вложенности объекты динамического холста, чтобы если герой находится между 2-х деревьев, где первое - впереди героя, второе - позади. Первое дерево перекрывает героя, а второе-перекрывается уже им самим. Советую выкинуть эти наброски и начать заново с нуля. |
1- матрица хранится в levelObj.level.map, там 775 плиток сложено грузится с level.xml.
Плитки по вложенности отсортированны и отображаются правильно- на нулевой или пятый канвас, всё это редактируется с редактора(открывается с кропки Settings->Tile property editor->Activate Selector. Кликаем на сам канвас и видим плитки которые привязаны к этому участку матрицы, удаляем, добавляем, меняем z-index). Проходные пути можно подсветить с Settings->Walking Areas->Highlight Stop Lines: ON. причина по которой не привязывал пути к самим плиткам- плитка прямоугольная а картинка на ней в виде ромба или же в 10 раз выше самого прямоугольнака на катором она сидит(Settings->Background tiles->a1outdoorwals). 2- "Далее, необходимо сортировать по-вложенности объекты динамического холста, чтобы если герой находится между 2-х деревьев, где первое - впереди героя, второе - позади. Первое дерево перекрывает героя, а второе-перекрывается уже им самим." Вопрос если к герою бегут мобы то дерево которое на переднем плане долно быть подрисованно(z-index) под которого из этих мобов или под героя или перерисовывать его по (60 fps*5units = 300) раз в секунду вместе с обоими канвасами, потому что зачистить только 1 квадрат не получится? 3- Попробую ещё раз пояснить проблему, дерево на переднем плане сейчас намертво привязано к 5-му канвасу, и отображается поверх коровы(героя) когда тот движется вывше основания дерева всё ок, когда ниже- голова будет зазить под дерево. Перерисовывать дерево не вариант по причинам изложеннвм в пункте 2, нужно добавлять ещё 1-н канвас и переносить рендеринг героя(или других спрайтов) поверх всего что есть, но только на время пока его позиция "ниже" дерева или стены или дома... И собственно вопрос- от которых точкек на спрайте героя и плики отсчитывать этоп перенос и как их вычислять? |
Проблема в том, что привязка должна быть к матрице и только к ней. Какое ей дело в каком виде она представлена пользователю? Хоть в чистом 3д. Переводи ромб в прямоугольник выровненный по осям. Так ты сможешь получить необходимый индекс для прямоугольной матрицы. Ты не сдвинешься с места пока не организуешь нормальную логику.
Модели должно быть до лампочки каким образом её отображает представление. |
Часовой пояс GMT +3, время: 00:58. |