Conceitos de C/C++
- Se não vamos modificar uma struct ou se ela não for muito grande podemos passar por valor ao invés de referência.
- Se há variáveis globais que fazem parte do mesmo contexto, podem ser usadas em uma struct. Isso também ajuda a flexibilizar o programa podendo passar outras structs.
- Funções pequenas e que processam poucas coisas podem ser funções inline.
- A stack começa com um número maior e vai diminuindo conforma alocamos mais dados nela. Isso significa que o primeiro pointeiro após a função main irá te mostrar o tamanho disponível na stack naquela momento.
const
não é útil porque const não é constante de verdade devido a casos de aliasing e ponteiros. Outro ponto é que não há otimização por parte do compilador quando se usa const. Logo, só é uma digitação a mais para o programador.
1
2
3
4
5
| // item 4.
void main() {
// aqui tem o endereço do maior valor da stack (e o disponivel)
My_Struct struct = {};
}
|
O parâmetro -F<num>
do compilador permite definir o tamanho da stack. Podemos testar o tamanho dela criando um array e inicializando ele com zero.
Criando uma struct que represente o BackBuffer
1
2
3
4
5
6
7
8
9
| struct Back_Buffer {
BITMAPINFO info;
void *memory;
int width;
int height;
int pitch;
}
static Back_Buffer g_back_buffer;
|
Refatorando o Gradiente
Vamos refatorar o gradiente usado no artigo anterior.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| internal void
render_gradient(Back_Buffer buffer, int x_offset, int y_offset)
{
uint8 *row = (uint8 *) buffer.memory;
for(int y = 0; y < buffer.height; y++) {
uint32 *pixel = (uint32 *) row;
for (int x = 0; x < buffer.width; x++) {
uint8 b = (x + x_offset);
uint8 g = (y + y_offset);
*pixel = ((g << 8) | b);
*pixel++;
}
row += buffer.pitch;
}
}
|
Refatorando o Redimensionamento da Janela
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
| internal void
resize_window(Back_Buffer *buffer, int width, int height)
{
if (buffer->memory) {
VirtualFree(&buffer->memory, 0, MEM_RELEASE);
}
buffer->width = width;
buffer->height = height;
int bytes_per_pixel = 4;
buffer->info.bmiHeader.biSize = sizeof(buffer->info.bmiHeader);
buffer->info.bmiHeader.biWidth = buffer->width;
buffer->info.bmiHeader.biHeight = -buffer->height;
buffer->info.bmiHeader.biPlanes = 1;
buffer->info.bmiHeader.biBitCount = 32;
buffer->info.bmiHeader.biCompression = BI_RGB;
int bitmap_memory_size = buffer->width * buffer->height * bytes_per_pixel;
buffer->memory = VirtualAlloc(0,
bitmap_memory_size,
MEM_COMMIT,
PAGE_READWRITE);
buffer->pitch = buffer->width * bytes_per_pixel;
}
|
Refatorando a Atualização da Janela
1
2
3
4
5
6
7
8
9
10
11
| internal void
update_window(HDC context, Back_Buffer buffer, int x, int y, int window_width, int window_height)
{
StretchDIBits(context,
0, 0, window_width, window_height,
0, 0, buffer.width, buffer.height,
buffer.memory,
&buffer.info,
DIB_RGB_COLORS,
SRCCOPY);
}
|
Reduzindo DRY (Don’t Repeat Yourself)
Há vários trechos de código onde usamos GetClientRect
. Vamos reduzir com uma função que retorna o tamanho da janela.
Essa função é uma boa candidata a ser inline
.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| struct Window_Size {
int width;
int height;
}
internal inline
Window_Size get_window_size(HWND window) {
Window_Size window_size;
RECT client_rect;
GetClientRect(window, &client_rect);
window_size.width = client_rect.right - client_rect.left;
window_size.height = client_rect.bottom - client_rect.top;
return window_size;
}
|
Agora, trocamos as chamadas de GetClientRect
para nossa nova função.
Adicionando Stretch para redimensionamento
Sempre que mudamos o tamanho da janela, o WM_SIZE
cria um novo backbuffer com uma nova proporção. Isso faz com que na hora do update, a janela não se redimensiona. Vamos comentar a linha do resize dentro do WM_SIZE
usar uma única vez na função main.
Para redimensionar, vamos definir uma única vez a chamada do resize_window
com uma tamanho pré-definido para que quando houver um resize, a função de update faça o stretch do nosso backbuffer de acordo com a janela desejada.
1
2
3
4
5
| // create window
resize_window(Back_Buffer *buffer, int width, int height)
// ... main loop
|