Нужен совет по псевдо 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, время: 15:39. |