
// WindowsProject1.cpp : Defines the entry point for the application.
#define WIN32_LEAD_AND_MEAN////включение всех макросов
#define INITGUID//включение графическо
// интерфейса пользователя
// windows libraries
#include <windowsx.h>
#include <Windows.h>
#include <mmsystem.h>
// c++
#include <iostream>
#include <conio.h>
#include <math.h>
#include <io.h>
#include <string>
#include <ddraw.h>
#include <memory>
#include <malloc.h>
#include <stdarg.h>
#include <fcntl.h>
#include <stdlib.h>
#include "Blackbox.h"
#define WINDOW_CLASS_NAME L"WIND3DCLASS"// NAME OF THE CLASS
#define WINDOW_WIDTH 640
#define WINDOW_HEIGHT 480
//Состояние цикла игры
#define GAME_STATE_INIT 0
#define GAME_STATE_START_LEVEL 1
#define GAME_STATE_RUN 2
#define GAME_STATE_SHUTDOWN 3
#define GAME_STATE_EXIT 4
//Определение блоков
#define NUM_BLOCK_ROWS 6
#define NUM_BLOCK_COLUMNS 8
#define BLOCK_WIDTH 64
#define BLOCK_HEIGHT 16
#define BLOCK_ORIGIN_X 8
#define BLOCK_ORIGIN_Y 8
#define BLOCK_X_GAP 80
#define BLOCK_Y_GAP 32
//Определение ракетки
#define PADDLE_START_X (SCREEN_WIDTH/2-16)
#define PADDLE_START_Y (SCREEN_HEIGHT/2)
#define PADDLE_WIDTH 32
#define PADDLE_HEIGHT 8
#define PADDLE_COLOT 191
//ОПРЕДЕЛЕНИЕ МЯЧА
#define BALL_START_Y (SCREEN_HEIGHT/2)
#define BALL_SIZE 4
// Прототипы//////////
//Game Console
int Game_Init(void* parms = NULL);
int Game_Shutdown(void* parms = NULL);
int Game_Main(void* parms = NULL);
// Global variables
HWND main_window_handle = NULL; // дескриптор окна
HINSTANCE main_instance = NULL; //экземпляр
int game_state = GAME_STATE_INIT;// НАЧАЛЬНОЕ СОСТОЯНИЕ ПРИ ЗАПУСКЕ ПРОГРАММЫ
int paddle_x = 0, paddle_y = 0;
int ball_x = 0, ball_y = 0;
int ball_dx = 0, ball_dy = 0; // ball's velocity
int score = 0;
int level = 1;
int blocks_hit = 0;
//map
UCHAR blocks[NUM_BLOCK_ROWS][NUM_BLOCK_COLUMNS];
//FUNCTIONS ///
LRESULT CALLBACK WindowProc(HWND hwnd,
UINT msg,
WPARAM wparam,
LPARAM lparam) {
//Главный обработчик сообщений в системе
PAINTSTRUCT ps; //используется в WM_PAINT
HDC hdc; //Дескриптор окна
// Какой сообщение получено
switch (msg) {
case WM_CREATE:
{
//инициализация
return(0);
}break;
case WM_PAINT:
{
//Рисование
hdc = BeginPaint(hwnd, &ps);
//Теперь окно действительно
// Конец рисования
EndPaint(hwnd, &ps);
return(0);
}break;
case WM_DESTROY:
{
//конец рисования
PostQuitMessage(0);
return(0);
}break;
default:break;
}
//обработка по умолчани остальных сообщений
return(DefWindowProc(hwnd, msg, wparam, lparam));
}
int WINAPI WinMain(
HINSTANCE hinstance, HINSTANCE hprevinstance,
LPSTR lpcmdline, int ncmdshow
)
{
WNDCLASS winclass;//Класс создаваемый нами
HWND hwnd; // ДЕСКРИИПТОР ОКНА
MSG msg; // Сообщение
HDC hdc; // Контекст устройства
PAINTSTRUCT ps;
// Cозданиие структуры класса окна
winclass.style = CS_DBLCLKS | CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
winclass.lpfnWndProc = WindowProc;
winclass.cbClsExtra = 0;
winclass.cbWndExtra = 0;
winclass.hInstance = hinstance;
winclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
winclass.hCursor = LoadCursor(NULL, IDC_ARROW);
winclass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
winclass.lpszMenuName = NULL;
winclass.lpszClassName = WINDOW_CLASS_NAME;
//РЕГИСТРАЦИЯ класса окна
if (!RegisterClass(&winclass))
return 0;
//создания окна
if (!(hwnd = CreateWindow(WINDOW_CLASS_NAME, L"WIND3DCLASS", // Class , title of the class
WS_POPUP | WS_VISIBLE,
0, 0, // coordinates
GetSystemMetrics(SM_CXSCREEN), //width
GetSystemMetrics(SM_CYSCREEN), //height
NULL, // дескриптор родителя
NULL, // дескриптор меню
hinstance, // экземпляр
NULL)))// параметры создания
return (0);
ShowCursor(false);
// сохранение дескриптора окна и экземпляра
main_window_handle = hwnd;
main_instance = hinstance;
Game_Init();
// main game cycle
while (1) {
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
if (msg.message == WM_QUIT)
break;
//трансляция клавиш
TranslateMessage(&msg);
// пересылка сообщений процедуре окна
DispatchMessage(&msg);
}
Game_Main();
}
Game_Shutdown();
ShowCursor(true);
return(msg.wParam);
}
int Game_Init(void* parms)
{
// game inizialization
//successful ending
return(1);
}
int Game_Shutdown(void* parms) {
//завершение игры и освобождение ресурсов
//успешное завершение
return(1);
}
void Init_Blocks(void) {
for (int r = 0; r < NUM_BLOCK_ROWS; r++)
for (int c = 0; c < NUM_BLOCK_COLUMNS; c++)
blocks[r][c] = r * 16 + c * 3 + 16;
}
void Draw_Blocks(void) {
int x1 = BLOCK_ORIGIN_X;
int y1 = BLOCK_ORIGIN_Y;
for (int row = 0; row < NUM_BLOCK_ROWS; row++) {
x1 = BLOCK_ORIGIN_X;
for (int col = 0; col < NUM_BLOCK_COLUMNS; col++) {
if (blocks[row][col] != 0) {
Draw_Rectangle(x1 - 4, y1 + 4,
x1 + BLOCK_WIDTH - 4, y1 + BLOCK_HEIGHT+4, 255);
Draw_Rectangle(x1 , y1 ,
x1 + BLOCK_WIDTH , y1 + BLOCK_HEIGHT,blocks[row][col] );
}
x1 += BLOCK_X_GAP;
}
y1 += BLOCK_Y_GAP;
}
}
void Process_Ball(void) {
//обработка движения мяча соударения с ракеткой или блоком отражения мяча и удаления блока с
экрана проверка соударения с блоком
//Проверяем все блоки (неэффективно, но просто;
int x1 = BLOCK_ORIGIN_X;
int y1 = BLOCK_ORIGIN_Y;
int ball_cx = ball_x + (BALL_SIZE / 2);
int ball_cy = ball_y + (BALL_SIZE / 2);
//ПРОВЕРЯЕМ СТОЛКНОВЕНИЕ С Ракеткой
if (ball_y > (SCREEN_HEIGHT / 2) && ball_dy > 0) {
int x = ball_x + (BALL_SIZE / 2);
int y = ball_y + (BALL_SIZE / 2);
if (x >= paddle_x && x <= paddle_x + PADDLE_WIDTH && y >= paddle_y && y <= paddle_y +
PADDLE_HEIGHT) {
//отражение мяча
ball_dy = -ball_dy;
ball_y += ball_dy;
//изменения траектории из-за движения ракетки
if (KEY_DOWN(VK_LEFT))
ball_dx -= (rand() % 3);
else if (KEY_DOWN(VK_RIGHT))
ball_dx += (rand() % 3);
else
ball_dx += (-1 + rand() % 3);
// Проверка есть ли блоки в системе Если нет, то переход на новый уровень
if (blocks_hit >= (NUM_BLOCK_ROWS * NUM_BLOCK_ROWS)) {
game_state = GAME_STATE_START_LEVEL;
level++;
}
MessageBeep(MB_OK);
return;
}
}
// сканируем все блоки и колоны
for (int r = 0; r < NUM_BLOCK_ROWS; r++)
{
x1 = BLOCK_ORIGIN_X;
for (int c = 0; c < NUM_BLOCK_COLUMNS; c++)
{
if (blocks[r][c] != 0) {
if ((ball_cx > x1) && (ball_cx < x1 + BLOCK_WIDTH) && (ball_cy > y1) && (ball_cy <
y1 + BLOCK_HEIGHT)) {
blocks[r][c] = 0;
blocks_hit++;
ball_dy = -ball_dy;
ball_dx = (-1 + rand() % 3);
MessageBeep(MB_OK);
score += 5 * (level + (abs(ball_dx)));
return;
}
}
x1 += BLOCK_X_GAP;
}
y1 += BLOCK_Y_GAP;
}
}
int GameMain(void* parms) {
char buffer[80];// используется для вывода текста
if (game_state == GAME_STATE_INIT) {
//инициализация графики
DD_Init(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP);
//инициализация генератора случайных чисел
srand(Start_Clock());
// позионирование ракетки
paddle_x = PADDLE_START_X;
paddle_y = PADDLE_START_Y;
//позиционирование мяча
ball_x = 8 + rand() % (SCREEN_WIDTH - 16);
ball_y = BALL_START_Y;
ball_dx = -4 + rand() % (8 + 1);
ball_dy = 6 + rand() % 2;
// Переход в стартовое состояние
game_state = GAME_STATE_START_LEVEL;
}
else if (game_state == GAME_STATE_START_LEVEL) {
blocks_hit = 0;
game_state = GAME_STATE_RUN;
}
else if (game_state == GAME_STATE_RUN) {
Start_Clock();
Draw_Rectangle(0, 0, SCREEN_WIDTH - 1, SCREEN_HEIGHT - 1, 200);
if (KEY_DOWN(VK_RIGHT)) {
paddle_x += 8;
if (paddle_x > SCREEN_WIDTH - PADDLE_WIDTH) {
paddle_x = SCREEN_WIDTH - PADDLE_WIDTH;
}
}
if (KEY_DOWN(VK_LEFT)) {
paddle_x -= 8;
if (paddle_x < 0)
paddle_x = 0;
}
Draw_Blocks();
//ball locomotion
ball_x += ball_dx;
ball_y += ball_dy;
//мяч не должен выходить за рамки экрана
if (ball_x > (SCREEN_WIDTH - BALL_SIZE) || ball_x < 0) {
ball_dx = -ball_dx;
ball_x += ball_dx;
}
if (ball_y < 0) {
ball_dy = -ball_dy;
ball_y += ball_dy;
}
if (ball_y > (SCREEN_HEIGHT - BALL_SIZE))
{
ball_dy = -ball_dy;
ball_y += ball_dy;
}
if (ball_dx > 8)ball_dx = 8;
if (ball_dx < -8)ball_dx = -8;
Process_Ball();
//рисуем ракетку
Draw_Rectangle(ball_x - 8, ball_y + 8, ball_x + BALL_SIZE - 8, ball_y + BALL_SIZE + 8, 0);
Draw_Rectangle(ball_x, ball_y, ball_x + BALL_SIZE, ball_y + BALL_SIZE, PADDLE_COLOT);
// РИСУЕМ МЯЧ
Draw_Rectangle(ball_x, ball_y, ball_x + BALL_SIZE, ball_y + BALL_SIZE, 255);
Draw_Rectangle(ball_x - 4, ball_y + 4, ball_x + BALL_SIZE - 4, ball_y + BALL_SIZE + 4, 255);
//Выводим Информацию
sprintf_s(buffer, "TIMUR+EVA Score" "%d level %d", score, level);
Draw_Text_Gdi(buffer, 8, SCREEN_HEIGHT - 16, 127);
//вывод на экран
DD_Flip();
// синхронизация до 33fps
Wait_Clock(30);
// проверяем есть ли запрос на выход
if (KEY_DOWN(VK_ESCAPE))
{
PostMessage(main_window_handle, WM_DESTROY, 0, 0);
game_state = GAME_STATE_SHUTDOWN;
}
}
else {
if (game_state == GAME_STATE_SHUTDOWN) {
DD_Shutdown();
game_state = GAME_STATE_EXIT;
}
}
return 1;
}
blackbox.h
#pragma once
#ifndef BLACKBOX
#define BLACKBOX
//Определения
// размер экрана по умолчанию
#define SCREEN_WIDTH 640
#define SCREEN_HEIGHT 480
#define SCREEN_BPP 8 //БИТ на пиксель
#define MAX_COLORS 256 // Максимальное количество цветов
// macros ///
// ЧТение Клавиатуры
#define KEY_DOWN(vk_code)\
((GetAsyncKeyState(vk_code)& 0x8000)? 1:0)
#define KEY_UP(vk_code) \
((GetAsyncKeyState(vk_code) & 0x8000)?0 : 1)
//Инициализация Структур DirectDraw
#define DD_INIT_STRUCT(ddstruct)\
{memset(&ddstruct,0,sizeof(ddstruct))};\
ddstruct.dwSize = sizeof(ddstruct);}
/////Типы/////////
/////Основные безнаковые типы
typedef unsigned short USHORT;
typedef unsigned short WORD;
typedef unsigned char UCHAR;
typedef unsigned char BYTE;
//////////////Внешние объекты
extern LPDIRECTDRAW7 lpdd;
extern LPDIRECTDRAWSURFACE7 lpddsprimary;
extern LPDIRECTDRAWSURFACE7 lpddsback;
extern LPDIRECTDRAWPALETTE lpddpal;
extern LPDIRECTDRAWCLIPPER lpddclipper;
extern PALETTEENTRY palette[256];
extern PALETTEENTRY save_palette[256];
extern DDSURFACEDESC2 ddsd;
extern DDBLTFX ddblftx;
extern DDSCAPS2 ddscaps;
extern HRESULT ddrval;
extern DWORD start_clock_count;
extern int min_clip_x,
max_clip_x,
min_clip_y,
max_clip_y;
// изменяются при вызове DD_Init()
extern int screen_width,
screen_height,
screen_bpp;
//прототипы
// direct draw function
int DD_Init(int width, int height, int bpp);
int DD_Shutdown(void);
LPDIRECTDRAWCLIPPER DD_Attach_Clipper(
LPDIRECTDRAWSURFACE7 lpdds,
int num_rects, LPRECT clip_list);
int DD_Flip(void);
int DD_Fill_Surface(LPDIRECTDRAWSURFACE7 lpdds, int color);
//time function
DWORD Start_Clock(void);
DWORD Get_Clock(void);
DWORD Wait_Clock(DWORD count);
int Draw_Rectangle(int x1, int y1, int x2, int y2, int color, LPDIRECTDRAWSURFACE7 lpdds =
lpddsback);
// function Gdi
int Draw_Text_Gdi(char* text, int x, int y, COLORREF color,
LPDIRECTDRAWSURFACE7 lpdds = lpddsback);
int Draw_Text_Gdi(char* text, int x, int y, int color,
LPDIRECTDRAWSURFACE7 lpdds = lpddsback);
#endif // !