Кроссплатформенная "Змейка"

Появилось немного свободного времени, и я переписал «Змейку» с использованием кроссплатформенной библиотеки curses. Для Винды был использован порт PDcurses.

Исходники «Змейки» с curses.

К сожалению у меня нет возможности откомпилировать и оттестировать программу под Линуксом. Если кому не лениво, протестируйте пожалуйста.

Проект сделан под Code::Blocks. Винда определяется по символу _WIN32. Если символ не определён, то считается, что это Линукс. Библиотека curses (NCurses) в состав проекта не включена. Порт conio для *nix я не использовал. Для компиляции в проекте надо указать, что должна быть подключена эта библиотека, и надо убрать подключение pdcurses.a. В остальном, как я надеюсь, должно откомпилироваться и запуститься без проблем. А если таковые будут, напишите, что пошло не так.

PS. Общие впечатления от curses/NCurses/PDcurses — тяжёлые.
PS2. Ещё о портировании Змейки на Линукс была тема на форуме.

Здавствуйте.
Ваш код прекрасно компилируется и запускается, но работать не хочет:

картинка

А пока позвольте излить негодование по поводу вашей фразы :)

Общие впечатления от curses/NCurses/PDcurses — тяжёлые.

Ну они и должны быть тяжёлыми, поскольку это старая низкоуровневая библиотека, которая создавалась, видимо, когда С++ ещё даже не было.
Но всё же мне показалось, что её использование не такое уж и сложное, в какой-то степени даже удобное для новичка, не привыкшего к ООП (мне, например).

P.S.: Кстати, у меня была идейка сделать эту библиотеку объектно-ориентированной. То есть все сущности (такие как окна и панели) занести в классы (тогда можно будет избавиться от функций с приставками w). А затем занести все эти классы в какое-нибудь пространство имён, например, curses.

Вобщем, я тут покумекал, и нашёл, что программа прекрасно работает, просто результат её работы у меня не видно. Он отображается чёрным текстом на чёрном фоне :)
Я думаю, проблема в функции text_attr. Видимо, её вызов в main получился не совсем кроссплатформенным.
картинка

Да, догадка подтвердилась, если убрать вызов метода text_attr объекта screen в main, то получится самая настоящая змейка белыми символами на чёрном фоне:
картинка

Тут есть один баг — статистика игры вывожится на игровом поле :(

Спасибо, porshe, за тестирование.

Значит PDcurses не на 100% совместима с ncurses (( У меня всё работает нормально. Можно, конечно попробовать в main вместо screen.text_attr((short)0x0a) попробовать screen.text_attr((short)0x02) — должен быть темно-зелёный цвет вместо яркого. Или при портировании вообще изменили схему кодирования цветов. Если так, то печально.

Глюк с выводом статистики в игровом поле у меня тоже проявлялся, но исключительно при работе из-под отладчика. Я списал это на некий конфликт библиотеки с отладчиком. Как оказалось, я был не прав.

Очень не хочется лезть внутрь исходников библиотеки (( Тем более, что, скорее всего, исходники будут некроссплатформенные.

Или, вариант второй, я где-то что-то не дочитал в доке по curses (кстати, отвратительная дока).


А пока позвольте излить негодование по поводу вашей фразы :)

Общие впечатления от curses/NCurses/PDcurses — тяжёлые.

Я только высказал своё личное впечатление.

P.S.: Кстати, у меня была идейка сделать эту библиотеку объектно-ориентированной. То есть все сущности (такие как окна и панели) занести в классы (тогда можно будет избавиться от функций с приставками w). А затем занести все эти классы в какое-нибудь пространство имён, например, curses.

Идейка неплохая. Только будь готов к тому, что придётся полностью перелопатить весь код библиотеки. Причём под несколько платформ. Мне кажется, что, например, с тестированием под OS/2 у тебя будут проблемы ))

А просто делать ООП-обёртку — замучаешься с глюками бороться.

Баг с неправильным позиционированием статистики я вроде поборол.

Файл CScreen.h, определение класса:

class CScreen {
public:
    CScreen();
    ~CScreen();
    void cursor_show(bool visible);                 // показать/скрыть курсор
    void text_attr(short attr);                     // установить цвет текста/фона
    void pos(int x, int y, char ch = 0);            // позиционирование курсора и
                                                    // вывод символа, если ch != 0
    void pos_str(int x, int y, const char *str);    // позиционирование курсора
                                                    // и вывод строки
    void cls();                                     // очистка экрана

    int getch_delay();                              // получить символ с ожиданием
    void clearkeys();                               // очистка буфера клавиатуры
    int get_ch();                                   // wrapper
    int getnstring(char *buf, int len);
    int update() { return refresh(); }
    int maxx() { return getmaxx(stdscr); }
    int maxy() { return getmaxy(stdscr); }

private:
};

Файл main.cpp, строка 27:

        // вместо
        CGame game(screen, 80, 24, 120);

        // должно быть
        CGame game(screen, screen.maxx(), screen.maxy()-1, 120);

Видимо под Линуксом по умолчанию для окна консоли отводится 24 строки. А под Виндой — 25.
Теперь в main игра будет подстраиваться под текущие настройки консоли.


Ещё в коде библиотеки нашёл странную фичу (это Windows-specific):

    SP->lines = (str = getenv("LINES")) ? atoi(str) : PDC_get_rows();
    SP->cols = (str = getenv("COLS")) ? atoi(str) : PDC_get_columns();

Оно, с какого-то пня, определяет через getenv, что у меня в консоли 24 строки. Откуда оно берёт переменную окружения LINES — я так и не понял, похоже, что это происки Code::Blocks. Причём, если всё свернуть до прямого вызова PDC_get_rows(), который использует виндовую GetConsoleScreenBufferInfo(), то работает правильно. Шарада, мля (

попробовать screen.text_attr((short)0x02) — должен быть темно-зелёный цвет вместо яркого.

Да, так работает.

rfhnbyrf

И, собственно, у меня вопрос: почему вы не пользуетесь стандартными константами цветов? (COLOR_GREEN, к примеру). Ведь используя прямые значения (0x02, например) получается непереносимый (либо плохопереносимый) код.

porshe, ещё раз спасибо за тестирование.

почему вы не пользуетесь стандартными константами цветов?

Наверное это атавизм предыдущей (виндовой) версии )))
Конечно надо пользоваться именованными константами.
Как бы туда ещё повышенную яркость для цвета прикрутить...

Как бы туда ещё повышенную яркость для цвета прикрутить...

По-моему, attrset должна работать и с константами атрибутов. То есть можно установить атрибут A_STANDOUT, вроде.

Внимание! Это довольно старый топик, посты в него не попадут в новые, и их никто не увидит. Пишите пост, если хотите просто дополнить топик, а чтобы задать новый вопрос — начните новый.

Ответить

Вы можете использовать разметку markdown для оформления комментариев и постов. Используйте функцию предпросмотра для проверки корректности разметки.

Пожалуйста, оформляйте исходный код в соответствии с правилами разметки. Для того, чтобы вставить код в комментарий, скопируйте его в текстовое поле ниже, после чего выделите то, что скопировали и нажмите кнопку «код» в панели инструментов. Иначе ваш код может принять нечитаемый вид.

Либо производите оформление кода вручную, следующим образом:

``` #include <iostream> using namespace std; int main() { // ... } ```

Предпросмотр сообщения

Ваше сообщение пусто.