Понедельник, 04 Марта 2024, 21:59

Приветствую Вас Гость

[ Новые сообщения · Игроделы · Правила · Поиск ]
  • Страница 1 из 1
  • 1
Форум игроделов » Движки для разработки игр и сложные системы разработки » 2D-движки для создания игр » XNA 2D Occlusion Culling (Не получается сделать Occlusion Culling для 2D камеры в XNA)
XNA 2D Occlusion Culling
dima13230Дата: Четверг, 24 Марта 2016, 00:33 | Сообщение # 1
частый гость
Сейчас нет на сайте
Не получается сделать так, чтобы если камера не видит тайл, он не отображался. Всё это происходит в 2D среде.
Вот скрипт камеры:
Код

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Terraria.Input;
using Microsoft.Xna.Framework.Input;

namespace 2DBlocks
{
    public class Camera
    {
        protected float _zoom; // Camera Zoom
        public Matrix _transform; // Matrix Transform
        public Vector2 _pos; // Camera Position
        protected float _rotation; // Camera Rotation
        public Game1 game;

        public Camera(Game1 Game)
        {
            _zoom = 1.0f;
            _rotation = 0.0f;
            _pos = Vector2.Zero;
            game = Game;
        }

        // Sets and gets zoom
        public float Zoom
        {
            get { return _zoom; }
            set { _zoom = value; if (_zoom < 0.1f) _zoom = 0.1f; } // Negative zoom will flip image
        }

        public float Rotation
        {
            get { return _rotation; }
            set { _rotation = value; }
        }

        // Auxiliary function to move the camera
        public void Move(Vector2 amount)
        {
            _pos += amount;
        }
        // Get set position
        public Vector2 Pos
        {
            get { return _pos; }
            set { _pos = value; }
        }

        public Matrix get_transformation(GraphicsDevice graphicsDevice)
        {
            _transform =       // Thanks to o KB o for this solution
              Matrix.CreateTranslation(new Vector3(-_pos.X, -_pos.Y, 0)) *
                    Matrix.CreateRotationZ(Rotation) *
                    Matrix.CreateScale(new Vector3(Zoom, Zoom, 1)) *
                    Matrix.CreateTranslation(new Vector3(game.GraphicsDevice.Viewport.Width * 0.5f, game.GraphicsDevice.Viewport.Height * 0.5f, 0));
            return _transform;
        }

    }
}


А набор тайлов представляет из себя двумерный массив с координатами x и y. Я думаю, что можно вычислить площадь видимой зоны окна и сравнивать с координатами. Но что точно нужно сделать?


Сообщение отредактировал dima13230 - Четверг, 24 Марта 2016, 00:36
FlyOfFlyДата: Четверг, 24 Марта 2016, 00:40 | Сообщение # 2
заслуженный участник
Сейчас нет на сайте
Цитата dima13230 ()


А набор тайлов представляет из себя двумерный массив с координатами x и y. Я думаю, что можно вычислить площадь видимой зоны окна и сравнивать с координатами. Но что точно нужно сделать?

В таком случае, надо просто не выводить весь массив стразу, а выводить только в радиусе определенном
вот допустим типа такого
Код


for(int i = (camera._pos.x/TileSize)-5;i<(camera._pos.x/TileSize)+5;i++){
for(int j = (camera._pos.y/TileSize)-5;j<(camera._pos.y/TileSize)+5;j++){
if(i<0 && i>=MapWidth) continue;
if(j<0 && j>=MapHeight) continue;
//вывод тайла
}
}....


Сообщение отредактировал FlyOfFly - Четверг, 24 Марта 2016, 00:41
dima13230Дата: Четверг, 24 Марта 2016, 00:56 | Сообщение # 3
частый гость
Сейчас нет на сайте
Цитата FlyOfFly ()

Цитата dima13230 ()

А набор тайлов представляет из себя двумерный массив с координатами x и y. Я думаю, что можно вычислить площадь видимой зоны окна и сравнивать с координатами. Но что точно нужно сделать?

В таком случае, надо просто не выводить весь массив стразу, а выводить только в радиусе определенном
вот допустим типа такого
Код

for(int i = (camera._pos.x/TileSize)-5;i<(camera._pos.x/TileSize)+5;i++){
for(int j = (camera._pos.y/TileSize)-5;j<(camera._pos.y/TileSize)+5;j++){
if(i<0 && i>=MapWidth) continue;
if(j<0 && j>=MapHeight) continue;
//вывод тайла
}
}....


Не, не работает, выдаёт исключение OutOfMemory ( наверное вечный цикл... )
FlyOfFlyДата: Четверг, 24 Марта 2016, 00:57 | Сообщение # 4
заслуженный участник
Сейчас нет на сайте
Цитата dima13230 ()

Не, не работает, выдаёт исключение OutOfMemory ( наверное вечный цикл... )

Код

for(int i = (camera._pos.x/TileSize)-5;i<(camera._pos.x/TileSize)+5;i++){
for(int j = (camera._pos.y/TileSize)-5;j<(camera._pos.y/TileSize)+5;j++){
if(i<0 || i>=MapWidth) continue;
if(j<0 || j>=MapHeight) continue;
//вывод тайла, который на i,j
}
}
Попробуй так


Сообщение отредактировал FlyOfFly - Четверг, 24 Марта 2016, 00:58
LertmindДата: Четверг, 24 Марта 2016, 01:04 | Сообщение # 5
заслуженный участник
Сейчас нет на сайте
Ты не объяснил как именно у тебя выглядит камера, я нарисовал пример:

Синяя - камера, и тебе надо узнать какие клетки отобразить (с галочкой) и не отображать (с крестиком)?
UPD: Понял, у тебя нет направления.


Сообщение отредактировал Lertmind - Четверг, 24 Марта 2016, 01:07
dima13230Дата: Четверг, 24 Марта 2016, 01:07 | Сообщение # 6
частый гость
Сейчас нет на сайте
Спасибо! Только радиус увеличу, а то отображается лишь малая часть тайлов :-)

Добавлено (24 марта 2016, 01:07)
---------------------------------------------

Цитата Lertmind ()
Ты не объяснил как именно у тебя выглядит камера, я нарисовал пример:

Синяя - камера, и тебе надо узнать какие клетки отобразить (с галочкой) и не отображать (с крестиком)?


Камера квадратная. Отображает вид сбоку.
FlyOfFlyДата: Четверг, 24 Марта 2016, 01:08 | Сообщение # 7
заслуженный участник
Сейчас нет на сайте
Цитата Lertmind ()

Синяя - камера, и тебе надо узнать какие клетки отобразить (с галочкой) и не отображать (с крестиком)?

Читай, внимательно, он написал что камера 2д, этого хватит, что бы понять что он про это
LertmindДата: Четверг, 24 Марта 2016, 01:10 | Сообщение # 8
заслуженный участник
Сейчас нет на сайте
Цитата dima13230 ()
Камера квадратная. Отображает вид сбоку.

Тогда да, всё просто. Твоё Occlusion Culling ввело в заблуждение, я думал тебе надо отсекать невидимые клетки.
FlyOfFlyДата: Четверг, 24 Марта 2016, 01:12 | Сообщение # 9
заслуженный участник
Сейчас нет на сайте
Цитата dima13230 ()
Спасибо! Только радиус увеличу, а то отображается лишь малая часть тайлов :-)

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

for(int i = (camera._pos.x/TileSize)-Camera_Width/TileSize/2;i<(camera._pos.x/TileSize)+Camera_Width/TileSize/2;i++){
for(int j = (camera._pos.y/TileSize)-Camera_Height/TileSize/2;j<(camera._pos.y/TileSize)+Camera_Height/TileSize/2;j++){
if(i<0 || i>=MapWidth) continue;
if(j<0 || j>=MapHeight) continue;
//вывод тайла, который на i,j
}
}

или экрана
Код

for(int i = (camera._pos.x/TileSize)-Screen_Width/TileSize/2;i<(camera._pos.x/TileSize)+Screen_Width/TileSize/2;i++){
for(int j = (camera._pos.y/TileSize)-Screen_Height/TileSize/2;j<(camera._pos.y/TileSize)+Screen_Height/TileSize/2;j++){
if(i<0 || i>=MapWidth) continue;
if(j<0 || j>=MapHeight) continue;
//вывод тайла, который на i,j
}
}


Сообщение отредактировал FlyOfFly - Четверг, 24 Марта 2016, 01:13
LertmindДата: Четверг, 24 Марта 2016, 01:12 | Сообщение # 10
заслуженный участник
Сейчас нет на сайте
Цитата Lertmind ()
Читай, внимательно, он написал что камера 2д, этого хватит, что бы понять что он про это

Нет, это не очевидно, я думал он хочет использовать что-то типа фонарика в темноте.
dima13230Дата: Четверг, 24 Марта 2016, 01:19 | Сообщение # 11
частый гость
Сейчас нет на сайте
Цитата Lertmind ()
что-то типа фонарика в темноте


Возможно и это спрошу потом :-)

Добавлено (24 марта 2016, 01:18)
---------------------------------------------
Цитата FlyOfFly ()
Спасибо! Только радиус увеличу, а то отображается лишь малая часть тайлов :-)

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

for(int i = (camera._pos.x/TileSize)-Camera_Width/TileSize/2;i<(camera._pos.x/TileSize)+Camera_Width/TileSize/2;i++){
for(int j = (camera._pos.y/TileSize)-Camera_Height/TileSize/2;j<(camera._pos.y/TileSize)+Camera_Height/TileSize/2;j++){
if(i<0 || i>=MapWidth) continue;
if(j<0 || j>=MapHeight) continue;
//вывод тайла, который на i,j
}
}

или экрана
Код

for(int i = (camera._pos.x/TileSize)-Screen_Width/TileSize/2;i<(camera._pos.x/TileSize)+Screen_Width/TileSize/2;i++){
for(int j = (camera._pos.y/TileSize)-Screen_Height/TileSize/2;j<(camera._pos.y/TileSize)+Screen_Height/TileSize/2;j++){
if(i<0 || i>=MapWidth) continue;
if(j<0 || j>=MapHeight) continue;
//вывод тайла, который на i,j
}
}


Пишет что индекс выходит за пределы массива

Добавлено (24 марта 2016, 01:19)
---------------------------------------------
FlyOfFly, может я дам код отображения? Он чуть отличается от того, что ты давал. ( правда суть та же )


Сообщение отредактировал dima13230 - Четверг, 24 Марта 2016, 01:20
FlyOfFlyДата: Четверг, 24 Марта 2016, 01:20 | Сообщение # 12
заслуженный участник
Сейчас нет на сайте
Цитата dima13230 ()

FlyOfFly, может я дам код отображения? Он чуть отличается от того, что ты давал. ( правда суть та же )

Давай
dima13230Дата: Четверг, 24 Марта 2016, 01:22 | Сообщение # 13
частый гость
Сейчас нет на сайте
Код

for (int x = ((int)cam.Pos.X / 15) - graphics.GraphicsDevice.Viewport.Width / 15 / 2; x < (cam.Pos.X / 15) + graphics.GraphicsDevice.Viewport.Width / 15 / 2; x++)
            {
                for (int y = ((int)cam.Pos.Y / 15) - graphics.GraphicsDevice.Viewport.Height / 15 / 2; y < (cam.Pos.Y / 15) + graphics.GraphicsDevice.Viewport.Height / 15 / 2; y++)
                {
                    if (tiles[x, y] != null)
                    {
                        if (x < 0 || x >= ViewTilesWidth) continue;
                        if (y < 0 || x >= ViewTilesHeight) continue;
                        int id = (int)tiles[x, y].type;

                        DrawFrameTile(id, x, y, 0, 0);

                    }
                }
            }
FlyOfFlyДата: Четверг, 24 Марта 2016, 01:23 | Сообщение # 14
заслуженный участник
Сейчас нет на сайте
Цитата dima13230 ()

if (tiles[x, y] != null)
{

после
Код

                        if (x < 0 || x >= ViewTilesWidth) continue;
                        if (y < 0 || x >= ViewTilesHeight) continue;
dima13230Дата: Четверг, 24 Марта 2016, 01:23 | Сообщение # 15
частый гость
Сейчас нет на сайте
Заодно и сам вызов отображения тайла кинул на всякий случай smile
FlyOfFlyДата: Четверг, 24 Марта 2016, 01:25 | Сообщение # 16
заслуженный участник
Сейчас нет на сайте
Цитата dima13230 ()
Заодно и сам вызов отображения тайла кинул на всякий случай smile

Код
for (int x = ((int)cam.Pos.X / 15) - graphics.GraphicsDevice.Viewport.Width / 15 / 2; x < (cam.Pos.X / 15) + graphics.GraphicsDevice.Viewport.Width / 15 / 2; x++)
            {
                for (int y = ((int)cam.Pos.Y / 15) - graphics.GraphicsDevice.Viewport.Height / 15 / 2; y < (cam.Pos.Y / 15) + graphics.GraphicsDevice.Viewport.Height / 15 / 2; y++)
                {
                    if (x < 0 || x >= ViewTilesWidth) continue;
                    if (y < 0 || x >= ViewTilesHeight) continue;
                    if (tiles[x, y] != null)
                    {
                        int id = (int)tiles[x, y].type;

                        DrawFrameTile(id, x, y, 0, 0);

                    }
                }
            }

вот такой у тебя щас код должен быть
dima13230Дата: Четверг, 24 Марта 2016, 01:26 | Сообщение # 17
частый гость
Сейчас нет на сайте
Спасибо, поставил, включил, там половина экрана отображается, убрал деление на два - стало показывать на полный экран, теперь всё работает так, как нужно :).
FlyOfFlyДата: Четверг, 24 Марта 2016, 01:27 | Сообщение # 18
заслуженный участник
Сейчас нет на сайте
Цитата dima13230 ()
Спасибо, поставил, включил, там половина экрана отображается, убрал деление на два - стало показывать на полный экран, теперь всё работает так, как нужно :).

Тогда попробуй так
Код

for (int x = ((int)cam.Pos.X / 15); x < (cam.Pos.X / 15) + graphics.GraphicsDevice.Viewport.Width / 15; x++)
            {
                for (int y = ((int)cam.Pos.Y / 15); y < (cam.Pos.Y / 15) + graphics.GraphicsDevice.Viewport.Height / 15; y++)
                {
                    if (x < 0 || x >= ViewTilesWidth) continue;
                    if (y < 0 || x >= ViewTilesHeight) continue;
                    if (tiles[x, y] != null)
                    {
                        int id = (int)tiles[x, y].type;

                        DrawFrameTile(id, x, y, 0, 0);

                    }
                }
            }
dima13230Дата: Четверг, 24 Марта 2016, 01:28 | Сообщение # 19
частый гость
Сейчас нет на сайте
Если хотите, могу скрин кинуть :)))

Добавлено (24 марта 2016, 01:28)
---------------------------------------------

Цитата FlyOfFly ()
Спасибо, поставил, включил, там половина экрана отображается, убрал деление на два - стало показывать на полный экран, теперь всё работает так, как нужно :).

Тогда попробуй так
Код

for (int x = ((int)cam.Pos.X / 15); x < (cam.Pos.X / 15) + graphics.GraphicsDevice.Viewport.Width / 15; x++)
            {
                for (int y = ((int)cam.Pos.Y / 15); y < (cam.Pos.Y / 15) + graphics.GraphicsDevice.Viewport.Height / 15; y++)
                {
                    if (x < 0 || x >= ViewTilesWidth) continue;
                    if (y < 0 || x >= ViewTilesHeight) continue;
                    if (tiles[x, y] != null)
                    {
                        int id = (int)tiles[x, y].type;

                        DrawFrameTile(id, x, y, 0, 0);

                    }
                }
            }


я это уже и так исправил
Форум игроделов » Движки для разработки игр и сложные системы разработки » 2D-движки для создания игр » XNA 2D Occlusion Culling (Не получается сделать Occlusion Culling для 2D камеры в XNA)
  • Страница 1 из 1
  • 1
Поиск:

Все права сохранены. GcUp.ru © 2008-2024 Рейтинг