Форум программистов, компьютерный форум, киберфорум
Наши страницы
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
Рейтинг 5.00/6: Рейтинг темы: голосов - 6, средняя оценка - 5.00
zusicks438
38 / 2 / 0
Регистрация: 29.04.2011
Сообщений: 51
1

Как работать с WriteConsoleOutput?

13.03.2015, 13:48. Просмотров 1138. Ответов 6
Метки нет (Все метки)

Добрый день!

Столкнулся с проблемой мерцания экрана в консольной игрушке при выводе символов через cout. Google выдал WriteConsoleOutput в качестве решения проблемы.

Но, как я ни пытался разобраться во работе этой функции, так толком и не понял, что и куда прописывать. Игра использует массив char grid[24][80] для формирования картинки. Более-менее внятные примеры нашёл здесь, но они какие-то полурабочие (допустим, выводятся кракозябры вместо символов). В примере из MSDN ничего не понял, несмотря на все комментарии

Забудем ненадолго про мою игру и допустим, что мне нужно, начиная с левого верхнего угла, выводить простенький массив grid[3][3] "стандартным" белым цветом на "стандартном" чёрном фоне. Кто-нибудь может хотя бы примерно подсказать, как это реализовать?
0
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
13.03.2015, 13:48
Ответы с готовыми решениями:

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

Как узнать и прочитать файл до того как с ним начнет работать другая программа
Здрувствуйте! Подскажите пожалуйста, как я могу узнать и прочитать файл до...

Как работать с окнами?
Гуглил, гуглил.. так ничо путёвого и не нашел.. у меня если чо Dev-C++ Вот...

Как работать с try - catch в С++?
Доброго времени суток. Подскажите плиз как именно работает try catch? Я...

Как работать с <ctime>?
Добрый день! почему получаю аварийное завершение ? #include &lt;ctime&gt;...

6
DrOffset
9014 / 4861 / 1196
Регистрация: 30.01.2014
Сообщений: 7,942
13.03.2015, 14:08 2
Цитата Сообщение от zusicks438 Посмотреть сообщение
Кто-нибудь может хотя бы примерно подсказать, как это реализовать?
Примерно можно здесь посмотреть. Просто рисуешь в буфер, потом его сбрасываешь в консоль. Код там, правда, не использует WriteConsoleOutput, потому что раздел не тот. Но у меня где-то валяется рабочая модификация последнего примера именно с учетом виндовых особенностей. Вечером, если все еще будет что-то не понятно, могу найти
Кстати, в винде, можно реализовать настоящий консольный double buffering, т.е. консольные буферы (с новой нарисованной картинкой и текущий) можно просто менять местами.
1
Ilot
Эксперт С++
1832 / 1190 / 342
Регистрация: 16.05.2013
Сообщений: 3,139
Записей в блоге: 5
Завершенные тесты: 1
13.03.2015, 14:28 3
zusicks438, очень подробно работа с консолью расписанна у Побегайло Системное программирование в Windows.
1
zusicks438
38 / 2 / 0
Регистрация: 29.04.2011
Сообщений: 51
13.03.2015, 16:44  [ТС] 4
Урррааа! Зарабоотало! Прочитал книгу Побегайло и действительно, нашёл нужный пример (листинг 13.10), в котором удалось понять, что к чему.

Спасибо!
0
DrOffset
9014 / 4861 / 1196
Регистрация: 30.01.2014
Сообщений: 7,942
13.03.2015, 23:41 5
zusicks438,
Вот тебе обещанный пример
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cassert>
#include <windows.h>
 
struct Point
{
    int x;
    int y;
};
 
template <size_t Lines, size_t Chars>
class screen_buffer
{
    void reset_position()
    {
        static COORD crd = {};
        SetConsoleCursorPosition(hStdout_, crd);
    }
 
public:
    enum
    {
        Size = Lines * Chars
    };
 
    screen_buffer()
        : hStdout_(GetStdHandle(STD_OUTPUT_HANDLE))
    {
        clear();
    }
 
    void flush()
    {
        SMALL_RECT srctWriteRect = { 0, 0, Chars - 1, Lines - 1 };
        COORD crd   = { 0, 0 };
        COORD bsize = { Chars, Lines };
 
        CHAR_INFO chInfo[Size];
        for(size_t i = 0; i < Size; ++i)
        {
            chInfo[i].Char.AsciiChar = screen_[i] ? screen_[i] : ' ';
            chInfo[i].Attributes     = 7;
        }
        WriteConsoleOutput(hStdout_, chInfo, bsize, crd, &srctWriteRect);
    }
 
    int printf(char const * format, ...)
    {
        va_list args;
        va_start(args, format);
        const size_t remainLen = Size - screenOff_;
        const int r = std::vsnprintf(&screen_[screenOff_], remainLen, format, args);
        screenOff_ += r;
        va_end(args);
        return r;
    }
    int printf(size_t x, size_t y, char const * format, ...)
    {
        va_list args;
        va_start(args, format);
        char * off = &screen_[x + y * Chars];
        char * beg = &screen_[0];
        const size_t remainLen = Size - std::distance(beg, off);
        const int r = std::vsnprintf(off, remainLen, format, args);
        va_end(args);
        return r;
    }
    int write(char const * data, size_t len)
    {
        const size_t remainLen = Size - screenOff_;
        const size_t count = len > remainLen ? remainLen : len;
        std::memcpy(&screen_[screenOff_], data, count);
        screenOff_ += count;
        return count;
    }
    int write(size_t x, size_t y, char const * data, size_t len)
    {
        char * off = &screen_[x + y * Chars];
        char * beg = &screen_[0];
        const size_t remainLen = Size - std::distance(beg, off);
        const size_t count = len > remainLen ? remainLen : len;
        std::memcpy(off, data, count);
        return count;
    }
    //Bresenham's line algorithm
    void line(Point p0, Point p1)
    {
        const int deltaX = std::abs(p1.x - p0.x);
        const int deltaY = std::abs(p1.y - p0.y);
        const int signX = p0.x < p1.x ? 1 : -1;
        const int signY = p0.y < p1.y ? 1 : -1;
        //
        int error = deltaX - deltaY;
        //
        size_t index = p1.x + p1.y * Chars;
        if(index >= 0 && index < Size)
        {
            screen_[index] = '*';
        }
        while(p0.x != p1.x || p0.y != p1.y)
        {
            index = p0.x + p0.y * Chars;
            if(index >= 0 && index < Size)
            {
                screen_[index] = '*';
            }
            const int error2 = error * 2;
            //
            if(error2 > -deltaY)
            {
                error -= deltaY;
                p0.x += signX;
            }
            if(error2 < deltaX)
            {
                error += deltaX;
                p0.y += signY;
            }
        }
    }
 
    void clear()
    {
        screenOff_ = 0;
        std::memset(screen_, ' ', Size);
    }
 
private:
    HANDLE hStdout_;
    size_t screenOff_;
    char   screen_[Size];
};
 
int main()
{
    screen_buffer<25, 80> conBuf;
 
    const int side = 5;
    const double pi = 3.14;
    // углы
    const double alpha  = 120 * pi / 180;
    const double beta   = 30  * pi / 180;
    const double radius = side * std::sin(alpha) / std::sin(beta);
 
    const size_t numPoints = 6;
    const double angle = 2 * pi / numPoints;
 
    int x = 5;
    int y = 10;
    int phi = 0;
 
    Point points[numPoints];
    do
    {
        for(size_t i = 0; i < numPoints; ++i)
        {
            points[i].x = int(x + radius * std::sin(phi + i * angle));
            points[i].y = int(y + radius * std::cos(phi + i * angle));
        }
        conBuf.clear();
        conBuf.printf(x, y, "^");
        for(size_t i = 0; i < numPoints; ++i)
        {
            conBuf.line(points[i], points[(i + 2) % numPoints]);
        }
        conBuf.flush();
 
        x = (x + 2) % 79; // катимся
 
        Sleep(70);
    }
    while((phi += 4) < 14400);
}
3
DrOffset
9014 / 4861 / 1196
Регистрация: 30.01.2014
Сообщений: 7,942
13.03.2015, 23:45 6
Демка во вложении
0
Вложения
Тип файла: zip console_demo.zip (21.0 Кб, 40 просмотров)
zusicks438
38 / 2 / 0
Регистрация: 29.04.2011
Сообщений: 51
14.03.2015, 10:10  [ТС] 7
красивый пример, спасибо. Иногда по книгам и примерам проще понять смысл работы кода, в MSDN всегда куча необязательных вещей в исходниках. С одной стороны это правильно, но не всегда сразу сообразишь, что к чему.
0
14.03.2015, 10:10
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
14.03.2015, 10:10

Как работать с битами?
Подскажите, пожалуйста... please... У меня дано число типа WORD. Как мне...

Как работать с va_list?
Есть функция: std::wstring APP::Execute (std::wstring scrName, wchar_t...

Как работать со строками?
Не мог бы кто-нибудь объяснить азы работы со стороками или дать ссылки, где это...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
7
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru