Имя пользователя:
Пароль:  
Помощь | Регистрация | Забыли пароль?  | Правила  

Компьютерный форум OSzone.net » Программирование, базы данных и автоматизация действий » Программирование и базы данных » C/C++ - Игра Ксоникс

Ответить
Настройки темы
C/C++ - Игра Ксоникс

Аватара для Doom77

Пользователь


Сообщения: 69
Благодарности: 0

Профиль | Отправить PM | Цитировать


Пишу игру Ксоникс на C. Подскажите как вырезать картинку.

Есть масив
0000000000
0000000000
0000000000
0000000000

Пользователь произвольно ставит 1.

0000000000
0000000000
0000001111
0000001000


0000100000
0000100000
1111100000
0000000000

Как эти элементы поменять на 2?
1111
1000


00001
00001
11111

Отправлено: 11:16, 28-12-2008

 
pva pva вне форума

Аватара для pva

Ветеран


Сообщения: 1180
Благодарности: 279

Профиль | Отправить PM | Цитировать


Если не прибегать к библиотекам сторонних производителей, например gdi32.dll от микрософт, не пользоваться алгоритмами стандартной библиотеки c++, то код будет выглядеть примерно так:
Код: Выделить весь код
typedef int surf_bit_t;

struct rect_t
{
   int left, top, right, bottom;
}

struct surface_desc
{
  surf_bit_t *begin; // начало данных
  unsigned width, height, stride; // длина, ширина блока, длина строчки
};

void __blt(surface_desc* from, surface_desc* to)
{
    // копирование без проверки исходых данных.
    // чтобы случайно не попортить память при записи, руководствуемся размерами конечной области
    for(surf_bit_t *row_first1=to->begin,
       *row_last1=to->begin+from->stride*to->width,
       *row_first2=from->from->begin;
        row_first1<row_last1; row_first1+=to->stride, row_first2+=from->stride)
    {
// закомментирован пример кода для копирования,
// можешь поиграться с ним (переделать в закрашивание)
//        for(unsigned col=0; col<to->width; ++col)
//        {
//            row_first1[col] = row_first2[col];
//        }
           memcpy(row_first2, row_first1, to->width*sizeof(surf_bit_t));
    }
}

inline int __constraint(int x, int min, int max)
{
   return x < min ? min : (x < max ? x : max);
}

void blt(surface_desc* from, int x, int y, int width, int height, surface_desc* to, int to_x, int to_y)
{
  // более удобный для пользователя интерфейс
  // с проверкой исходных данных
  // вычисляем перекрывающийся прямоугольник для копирования.

  surface_desc from1, to1;

  {
	// пересечение прямоугольника {0, 0, width, height} с
	// исходным изображением, в координатах копируемого окошка
	rect_t rect_src = {
		__constraint(-x, 0, width),
		__constraint(-y, 0, height),
		__constraint(from->width - x, 0, width),
		__constraint(from->height - y, 0, height)},
	// пересечение  {0, 0, width, height} с
	// конечным изображением и сразу с пересечённым исходным rect_src
	  	rect_dest = {
		__constraint(__constraint(-x_to, 0, width), rect_src.left, rect_src.right),
		__constraint(__constraint(-y_to, 0, height), rect_src.top, rect_src.bottom),
		__constraint(__constraint(to->width - x_to, 0, width), rect_src.left, rect_src.right),
		__constraint(__constraint(to->height - y_to, 0, height), rect_src.top, rect_src.bottom)};
	
	// составляем полётное задание для __blt

	from1.begin  = from->begin + (rect_dest.top + y)*from->stride + rect_dest.left + x;
 	from1.stride = from->stride;
        from1.width  = rect_desc.right - rect_dest.left;
        from1.height = rect_desc.bottom - rect_dest.top;

	to1.begin  = to->begin + (rect_dest.top + to_y)*from->stride + rect_dest.left + to_x;
 	to1.stride = to->stride;
        to1.width  = rect_desc.right - rect_dest.left;
        to1.height = rect_desc.bottom - rect_dest.top;
   }  

   __blt(&from1, &to1);
}

...

// как пользоваться

surf_bit_t screen1_bits[320*200];
surface_desc screen1 = {&screen1_bits, 320, 200, 320};

surf_bit_t screen2_bits[50*100];
surface_desc screen2 = {&screen2_bits, 50, 100, 50};

...

blt(&screen1, 100, 100, 60, 60, &screen2, 10, 10);
если внутри __blt заменить memcpy на memset, то получится "закрашивание". Рекомендую почитать в сторону функции BitBlt от винды. Если surf_bit_t - 8 битный, то можно сделать 8-битные картинки в памяти и смело пользоваться функциями GDI
Это сообщение посчитали полезным следующие участники:

Отправлено: 23:21, 28-12-2008 | #2



Для отключения данного рекламного блока вам необходимо зарегистрироваться или войти с учетной записью социальной сети.

Если же вы забыли свой пароль на форуме, то воспользуйтесь данной ссылкой для восстановления пароля.


Аватара для Doom77

Пользователь


Сообщения: 69
Благодарности: 0

Профиль | Отправить PM | Цитировать


Не могу разобраться в коде не могли бы вы упростить код или объяснить доходчивей

Отправлено: 18:31, 30-12-2008 | #3

pva pva вне форума

Аватара для pva

Ветеран


Сообщения: 1180
Благодарности: 279

Профиль | Отправить PM | Цитировать


Цитата Doom77:
не могли бы вы упростить код »
только если подняться на высокий уровень (С++).
Добавил комментариев
Код: Выделить весь код
// это чтобы можно было легко подменить тип-носитель
// для "цвета" ячейки
typedef int surf_bit_t;

struct rect_t
{
    // прямоугольник - понадобится для пересечений
   int left, top, right, bottom;
}

// стркуктура, которая указывает, в каком виде хранится картинка.
// данные хранятся в виде линейного массива определённой ширины строчки
//                     на картинке нарисован массив, у которого stride = 6,
//     x x x x x x     width = 4, height = 3. Можно сказать, что мы работаем
//     x x 1 1 1 1                   с большим массивом 6x5, а можно что с
//     x x 1 0 0 0     1 1 1 1 ? ?   маленьким 4x3, строчки которого
//     x x 1 0 0 0     1 0 0 0 ? ?   расположены через 6 элементов.
//     x x x x x x     1 0 0 0 ? ?   begin в последнем случае указывает на
//                                   начало "маленького" массива.

struct surface_desc
{
  surf_bit_t *begin; // начало данных
  unsigned width, height, stride; // длина, ширина блока, длина строчки
};

void __blt(surface_desc* from, surface_desc* to)
{
    // функция НЕ ПОЗВОЛЯЕТ копировать в себя, то есть когда from и to могут пересекаться.
    // копирование без проверки исходых данных.
    // чтобы случайно не попортить память при записи, руководствуемся размерами конечной области

    // эта функция используется как внутренняя, исходные данные должны быть уже проверены.
    // в качестве аргументов получает поверхности экрана, описанные выше (surface_desc)

    // row_first1 пробегает строчки, куда копировать, от начала до конца, с шагом stride
    // row_last1 - это и есть конец (посчитали и запомнили)
    // row_first1 пробегает строчки, откуда копировать, с шагом stride

    for(surf_bit_t *row_first1=to->begin,
       *row_last1=to->begin+from->stride*to->width,
       *row_first2=from->from->begin;
        row_first1<row_last1; row_first1+=to->stride, row_first2+=from->stride)
    {
        // закомментирован пример кода для копирования,
        // можешь поиграться с ним (переделать в закрашивание)

        for(unsigned col=0; col<to->width; ++col)
        {
            // копирование
            row_first1[col] = row_first2[col];

            // а это могло бы быть закрашивание
            // row_first1[col] = 2;
        }

        // простейший случай - просто копирование памяти. Сэкономил код функцией
        //   memcpy(row_first2, row_first1, to->width*sizeof(surf_bit_t));
    }
}

inline int __constraint(int x, int min, int max)
{
    // ограничивает значение x - прибмвает к одному из порогов.
    // нужно для пересечения прямоугольников
   return x < min ? min : (x < max ? x : max);
}

//                                          функция, которая вычисляет аргументы для __blt
//     x x x x x x                          по заданным исходному прямоугольнику и конечной
//     x x 1 1 1 1        y 1 1 1 1 y y     точке, куда содержимое этого прямоугольника
//     x x 1 0 0 0  ->    y 1 0 0 0 y y     скопировать.
//     x x 1 0 0 0        y 1 0 0 0 y y     Надо учесть случаи, когда часть прямоугольника
//     x x x x x x                          будет выходить за пределы исходного или
//                                          конечного экранов. Для этого сделаем следующее:
// (1) пересчитаем координаты прямоугольников экранов в координатах исходного и конечного
// прямоугольника, (2) пересечём их с исходным и конечным прямоугольником. Затем (3)
// пересечём что получилось между собой. Получится прямоугольник (4), который и надо
// копировать. Пересчитаем его в координатах экранов (5), запишем в виде поверхностей (6) и
// отдадим функции __blt
//
//  (0,0)              (0,0)                  (0,0)
//    +---+ (w,0)        +---+ (w,0)            +---+ (w,0)
//    |   |              |   |                  |   |
//    |  x|x x x         |y y|y y y     ->      |  N|    область, которая_
//    |  x|x x x         |y y|y y y             |  N|    будет скопирована
//    +--x+x x x         +y-y+y y y             +--N+
// (0,h) x x x x      (0,h)                  (0,h)
//


void blt(surface_desc* from, /*поверхность-откуда*/
        int x, int y,  /*координаты, откуда копировать*/
        int width, int height,  /*размеры окошка*/
        surface_desc* to, /*поверхность-куда*/
        int to_x, int to_y) /*координаты куда*/
{
  // более удобный для пользователя интерфейс
  // с проверкой исходных данных
  // вычисляем перекрывающийся прямоугольник для копирования.

  surface_desc from1, to1;

  {
    // пересечение прямоугольника {0, 0, width, height} с
    // исходным изображением, в координатах копируемого окошка
    rect_t rect_src = {
        /*2*/__constraint(/*1*/-x, 0, width),
        /*2*/__constraint(/*1*/-y, 0, height),
        /*2*/__constraint(/*1*/from->width - x, 0, width),
        /*2*/__constraint(/*1*/from->height - y, 0, height)},
    // пересечение  {0, 0, width, height} с
    // конечным изображением и сразу с пересечённым исходным rect_src
        rect_dest = /*4*/{
        /*3*/__constraint(/*2*/__constraint(/*1*/-x_to, 0, width), rect_src.left, rect_src.right),
        /*3*/__constraint(/*2*/__constraint(/*1*/-y_to, 0, height), rect_src.top, rect_src.bottom),
        /*3*/__constraint(/*2*/__constraint(/*1*/to->width - x_to, 0, width), rect_src.left, rect_src.right),
        /*3*/__constraint(/*2*/__constraint(/*1*/to->height - y_to, 0, height), rect_src.top, rect_src.bottom)};

    // составляем полётное задание для __blt

    from1.begin  = /*6*/from->begin + (/*5*/rect_dest.top + y)*from->stride + /*5*/rect_dest.left + x;
    from1.stride = /*6*/from->stride; /*сохраняется для подобласти*/
    from1.width  = /*6*/rect_desc.right - rect_dest.left;
    from1.height = /*6*/rect_desc.bottom - rect_dest.top;

    to1.begin  = /*6*/to->begin + (/*5*/rect_dest.top + to_y)*from->stride + /*5*/rect_dest.left + to_x;
    to1.stride = /*6*/to->stride;     /*сохраняется для подобласти*/
    to1.width  = /*6*/rect_desc.right - rect_dest.left;
    to1.height = /*6*/rect_desc.bottom - rect_dest.top;
   }

   __blt(&from1, &to1);
}


// как пользоваться_
// где-то в программе выделена память под экран, сделано описание для этой памяти:

surf_bit_t screen1_bits[/*width*/320 * /*height*/200];
surface_desc screen1 = {/*begin*/ &screen1_bits, /*width*/320, /*height*/200, /*stride=width*/320};

surf_bit_t screen2_bits[/*width*/50 * /*height*/100];
surface_desc screen2 = {/*begin*/ &screen2_bits, /*width*/50, /*height*/100, /*stride=width*/50};

// в том месте, где надо скопировать делаем так:
// копируем прямоугольник 60x60 из точки (100,100) в (10,10) на другом экране
blt(&screen1, 100, 100, 60, 60, &screen2, 10, 10);

Отправлено: 12:03, 31-12-2008 | #4



Компьютерный форум OSzone.net » Программирование, базы данных и автоматизация действий » Программирование и базы данных » C/C++ - Игра Ксоникс

Участник сейчас на форуме Участник сейчас на форуме Участник вне форума Участник вне форума Автор темы Автор темы Шапка темы Сообщение прикреплено

Похожие темы
Название темы Автор Информация о форуме Ответов Последнее сообщение
Не устанавливается игра Monsterup Непонятные проблемы с Железом 1 09-06-2008 15:28
Не работает игра. Dosmod Microsoft Windows Vista 4 05-05-2007 13:53
незапускается игра pirat0 Microsoft Windows Vista 2 26-02-2007 11:42
игра по сети idon Сетевые технологии 1 04-01-2006 17:42
Игра по модему Dronvelikii Сетевые технологии 1 02-08-2004 17:17




 
Переход