2D-видимость с java-графикой (Fog of War)

Я делаю 2D-игру, и я хочу сделать 2D-видимость. Итак, моя идея состоит в том, чтобы сделать карту, а затем замаскировать ее другим черным (например) полигоном, чтобы игрок мог видеть карту через черный полигон. Итак, моя идея состоит в том, чтобы нарисовать какое-то отверстие (многоугольник) через черный многоугольник, чтобы увидеть карту, которая находится под черным многоугольником. Я уже сделал видимость, но понятия не имею, как сделать маску.

Так программа выглядит на данный момент http://prntscr.com/7y36ev

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

Редактировать - для тех, кто хочет сделать то же самое, я сделал это с помощью Path2D. Сначала я создаю внешний многоугольник с помощью Path2D, затем делаю внутренний многоугольник (отверстие) и добавляю отверстие к внешнему многоугольнику. Это пример кода:

public void paintComponent(Graphics g){
        Graphics2D g2d = (Graphics2D) g;
        g2d.setColor(Color.red);

        Path2D.Double poly = new Path2D.Double();
        Path2D.Double hole = new Path2D.Double();

        hole.moveTo(40,40);
        hole.lineTo(40,60);
        hole.lineTo(60,60);
        hole.lineTo(60,40);
        hole.lineTo(40,40);

        poly.moveTo(80,2);
        poly.lineTo(80,80);
        poly.lineTo(2,80);
        poly.lineTo(2,2);
        poly.lineTo(80,2);

        poly.append(hole, true);
        g2d.fill(poly);  
    }

person Nikolai Nikolov    schedule 28.07.2015    source источник


Ответы (1)


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

Получите BufferedImage карты и BufferedImage маски и, используя два цикла for, проверьте, есть ли у маски черный пиксель в позиции (X, Y), если да, то добавьте пиксель карты в новое BufferedImage в позицию (X, Y) в противном случае добавьте черный пиксель к полученному BufferedImage в позиции (X, Y).

Изменить: немного Псевдокод

BufferedImage mapBI = .... // the map as BufferedImage
BufferedImage maskBI = .... // the mask as BufferedImage
BufferedImage resultBI = ... // new BufferedImage with same size as mask 

for (i=0; i< maskBI.width; i++){
    for(j=0; j< maskBI.height; j++){
        if (maskBI.pixelAt(i,j) == blackPixel){
            resultBI.setPixel(i,j,mapBI.pixelAt(i,j));
        }else{
            resultBI.setPixel(i,j,blackPixel);
        }
    }
}

Надеюсь, вы понимаете, что я имею в виду.

person Kami    schedule 28.07.2015
comment
Что ж, это хорошая идея, но я рисую с помощью Graphics2D и не знаю, как редактировать пиксели только с помощью Graphics. Я использую тот же алгоритм, что и этот ncase.me/sight-and-light. У вас есть идея, как сделать это без редактирования каждого пикселя? - person Nikolai Nikolov; 28.07.2015
comment
Вы можете преобразовать Graphics2D в BuffredImage для доступа к каждому пикселю: прочитайте здесь - person Kami; 28.07.2015
comment
Да, но это не будет медленным, потому что если бы у меня было большое разрешение, оно бы сильно замедлилось. Если я сделаю в маске целое, то сначала нарисую карту, а затем маску, мне не нужно будет проходить через каждый пиксель, если это возможно. - person Nikolai Nikolov; 28.07.2015
comment
Это возможно, но вы должны знать, где нарисовать отверстие, и эта информация хранится только в маске. Другим вариантом является определение объекта маски, содержащего информацию о круге или прямоугольнике, который не должен быть отрисован, а затем нарисовать многоугольник по краям этого объекта маски. Круг будет немного сложным, но прямоугольник будет легко решить. - person Kami; 28.07.2015
comment
Но я думаю, что мой ответ с псевдокодом - лучший подход. Я много использовал BufferedImage для рисования или управления изображениями. Это должно решить вашу проблему. Вы должны попробовать и проверить производительность. - person Kami; 28.07.2015
comment
Да, я мог бы попробовать оба подхода. Спасибо за помощь и быстрый ответ! - person Nikolai Nikolov; 29.07.2015
comment
Добро пожаловать :), если этот ответ поможет вам, не могли бы вы принять мой ответ? :) Благодарность :) - person Kami; 29.07.2015