// -std=c++14 -lgdi32 -lOpengl32 -ld3d11 -ldxgi
#define NOMINMAX
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <wrl/client.h>
#include <d3d11_4.h>
#include <dxgi1_6.h>
#include <d3dcompiler.h>
#include <DirectXMath.h>
#include <gl/gl.h>
#include <cmath>
#include <vector>
#include <ctime>
#include <string>
#include <iostream>
using namespace std;
namespace D3D11 {
using namespace std;
using namespace Microsoft::WRL;
using namespace DirectX;
#ifdef assert
#undef assert
#endif
#define assert(expr) (!(bool) (expr) ? __my_assert_report(#expr, __FILE__, __LINE__) : (void) 0)
#define CHK(expr) check_error((expr))
struct Size2D {
int w, h;
};
namespace
{
void break_or_exit() {
if (IsDebuggerPresent()) __debugbreak();
else exit(-1);
}
void __my_assert_report(const char* expr, const char* file, int line) {
cerr << "Assertion failed: " << expr << " in file " << file << ", line " << line << "." << endl;
break_or_exit();
}
wstring get_error_message(DWORD error_code) {
wchar_t* buf = nullptr;
FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr,
error_code, 0, (LPWSTR) &buf, 0, nullptr);
if (!buf) return L"Error "+to_wstring(error_code);
auto msg=L"Error "+to_wstring(error_code)+L": "+buf;
LocalFree(buf);
return msg;
}
void report_win32_error() {
if (GetLastError() != ERROR_SUCCESS) {
auto msg = get_error_message(GetLastError());
wcerr << msg << endl;
break_or_exit();
}
}
void report_hresult(HRESULT hr) {
if (FAILED(hr)) {
auto msg = get_error_message(HRESULT_CODE(hr));
wcerr << msg << endl;
break_or_exit();
}
}
template<typename T> void check_error(T) { static_assert(0, "Unknown result type"); }
template<> void check_error(HRESULT hr) { report_hresult(hr); }
template<> void check_error(BOOL ok) {
if (!ok) report_win32_error();
}
template<> void check_error(HANDLE handle) {
if (handle == INVALID_HANDLE_VALUE) report_win32_error();
}
vector<uint8_t> read_file_bin(const wchar_t* filename) {
auto file
= CreateFileW(filename, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
CHK(file);
LARGE_INTEGER size;
CHK(GetFileSizeEx(file, &size));
vector<uint8_t> buffer(size.QuadPart, '\0');
DWORD size_read;
CHK((BOOL) (ReadFile(file, buffer.data(), size.QuadPart, &size_read, nullptr) && size_read == size.QuadPart));
return buffer;
}
template<typename T, size_t N> constexpr size_t array_size(T (&)[N]) { return N; }
struct DrawCmd {
int x,y,w,h;
float col[3];
};
vector<DrawCmd> draw_cmds;
HWND hwnd;
ComPtr<IDXGIFactory4> dxgi_factory;
ComPtr<IDXGIAdapter4> dxgi_adapter;
ComPtr<IDXGISwapChain4> swap_chain;
ComPtr<ID3D11Device5> device;
ComPtr<ID3D11DeviceContext4> device_context;
Size2D d3d11_buffer_size;
vector<uint8_t> vertex_shader_bin, pixel_shader_bin;
ComPtr<ID3D11VertexShader> vertex_shader;
ComPtr<ID3D11PixelShader> pixel_shader;
ComPtr<ID3D11InputLayout> input_layout;
ComPtr<ID3D11Buffer> vertex_buffer;
ComPtr<ID3D11Buffer> constant_buffer1;
struct VertexData {
XMINT2 position;
XMFLOAT3 color;
};
struct ConstantBuffer1 {
XMINT2 size;
};
void load_shader() {
vertex_shader_bin = read_file_bin(L".\\build\\1.vs.cso");
CHK(device->CreateVertexShader(vertex_shader_bin.data(), vertex_shader_bin.size(), nullptr, &vertex_shader));
pixel_shader_bin = read_file_bin(L".\\build\\1.ps.cso");
CHK(device->CreatePixelShader(pixel_shader_bin.data(), pixel_shader_bin.size(), nullptr, &pixel_shader));
}
Size2D get_screen_size() { return {GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN)}; }
Size2D get_window_size() {
RECT r;
GetClientRect(hwnd, &r);
return {r.right - r.left, r.bottom - r.top};
}
void init_D3D11() {
d3d11_buffer_size = get_screen_size();
CHK(CreateDXGIFactory2(DXGI_CREATE_FACTORY_DEBUG, IID_PPV_ARGS(&dxgi_factory)));
{
ComPtr<IDXGIAdapter1> dxgi_adapter_tmp;
CHK(dxgi_factory->EnumAdapters1(0, &dxgi_adapter_tmp));
CHK(dxgi_adapter_tmp.As(&dxgi_adapter));
DXGI_ADAPTER_DESC desc;
CHK(dxgi_adapter->GetDesc(&desc));
wcerr << L"Using adapter: " << desc.Description << endl;
}
{
ComPtr<ID3D11Device> device_tmp;
CHK(D3D11CreateDevice(dxgi_adapter.Get(), D3D_DRIVER_TYPE_UNKNOWN, nullptr, D3D11_CREATE_DEVICE_DEBUG, nullptr,
0, D3D11_SDK_VERSION, &device_tmp, nullptr, nullptr));
CHK(device_tmp.As(&device));
ComPtr<ID3D11DeviceContext3> device_context_tmp;
device->GetImmediateContext3(&device_context_tmp);
CHK(device_context_tmp.As(&device_context));
}
{
DXGI_SWAP_CHAIN_DESC1 desc;
memset(&desc, 0, sizeof(desc));
auto w=d3d11_buffer_size.w, h=d3d11_buffer_size.h;
desc.Width = w, desc.Height = h;
desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
desc.SampleDesc = {1,0};
desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
desc.BufferCount = 2;
desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
desc.Scaling = DXGI_SCALING_NONE;
desc.Flags = 0;
ComPtr<IDXGISwapChain1> swap_chain_tmp;
CHK(dxgi_factory->CreateSwapChainForHwnd(device.Get(), hwnd, &desc, nullptr, nullptr, &swap_chain_tmp));
CHK(swap_chain_tmp.As(&swap_chain));
}
load_shader();
{
D3D11_INPUT_ELEMENT_DESC layout[] {
{"POSITION", 0, DXGI_FORMAT_R32G32_SINT, 0, offsetof(VertexData, position), D3D11_INPUT_PER_VERTEX_DATA, 0},
{"COLOR", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, offsetof(VertexData, color), D3D11_INPUT_PER_VERTEX_DATA, 0}
};
CHK(device->CreateInputLayout(
layout, array_size(layout), vertex_shader_bin.data(), vertex_shader_bin.size(), &input_layout));
}
{
D3D11_BUFFER_DESC desc;
memset(&desc, 0, sizeof(desc));
desc.ByteWidth = 1048576;
desc.Usage = D3D11_USAGE_DYNAMIC;
desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
CHK(device->CreateBuffer(&desc, nullptr, &vertex_buffer));
}
{
D3D11_BUFFER_DESC desc;
memset(&desc, 0, sizeof(desc));
desc.ByteWidth = 64;
desc.Usage = D3D11_USAGE_DYNAMIC;
desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
CHK(device->CreateBuffer(&desc, nullptr, &constant_buffer1));
}
}
void render() {
ComPtr<ID3D11Texture2D> back_buffer;
swap_chain->GetBuffer(0, IID_PPV_ARGS(&back_buffer));
ComPtr<ID3D11RenderTargetView> back_buffer_rtv;
CHK(device->CreateRenderTargetView(back_buffer.Get(), nullptr, &back_buffer_rtv));
device_context->OMSetRenderTargets(1, back_buffer_rtv.GetAddressOf(), nullptr);
D3D11_VIEWPORT viewport;
viewport.TopLeftX = 0, viewport.TopLeftY = 0;
viewport.Width = d3d11_buffer_size.w, viewport.Height = d3d11_buffer_size.h;
viewport.MinDepth = 0.0f, viewport.MaxDepth = 1.0f;
device_context->RSSetViewports(1, &viewport);
float bgr_color[] {0.92f,0.92f,0.92f, 1.0f};
device_context->ClearRenderTargetView(back_buffer_rtv.Get(), bgr_color);
device_context->VSSetShader(vertex_shader.Get(), nullptr, 0);
device_context->PSSetShader(pixel_shader.Get(), nullptr, 0);
device_context->IASetInputLayout(input_layout.Get());
device_context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
{
D3D11_MAPPED_SUBRESOURCE map_info;
CHK(device_context->Map(constant_buffer1.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &map_info));
// int h = get_window_size().h, w = get_window_size().w;
int h = d3d11_buffer_size.h, w = d3d11_buffer_size.w;
ConstantBuffer1 cb1 {};
cb1.size = {w, h};
memcpy(map_info.pData, &cb1, sizeof(cb1));
device_context->Unmap(constant_buffer1.Get(), 0);
device_context->VSSetConstantBuffers(0, 1, constant_buffer1.GetAddressOf());
}
{
vector<VertexData> vertices;
for (auto& cmd : draw_cmds) {
VertexData v1, v2, v3, v4;
v1.position = {cmd.x, cmd.y};
v2.position = {cmd.x+cmd.w, cmd.y};
v3.position = {cmd.x+cmd.w, cmd.y+cmd.h};
v4.position = {cmd.x, cmd.y+cmd.h};
v1.color={cmd.col[0], cmd.col[1], cmd.col[2]};
v2.color={cmd.col[0], cmd.col[1], cmd.col[2]};
v3.color={cmd.col[0], cmd.col[1], cmd.col[2]};
v4.color={cmd.col[0], cmd.col[1], cmd.col[2]};
vertices.push_back(v1);
vertices.push_back(v2);
vertices.push_back(v3);
vertices.push_back(v4);
vertices.push_back(v1);
vertices.push_back(v3);
}
if(vertices.size()){
D3D11_MAPPED_SUBRESOURCE map_info;
CHK(device_context->Map(vertex_buffer.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &map_info));
memcpy(map_info.pData, vertices.data(), sizeof(vertices[0])*vertices.size());
device_context->Unmap(vertex_buffer.Get(), 0);
UINT stride = sizeof(VertexData), offset = 0;
device_context->IASetVertexBuffers(0, 1, vertex_buffer.GetAddressOf(), &stride, &offset);
device_context->Draw(vertices.size(), 0);
}
}
CHK(swap_chain->Present(0, 0));
}
} // namespace
}
void EnableOpenGL(HWND hWnd, HDC *hDC, HGLRC *hRC) {
PIXELFORMATDESCRIPTOR pfd; int iFormat;
*hDC = GetDC(hWnd);
ZeroMemory(&pfd, sizeof(pfd));
pfd.nSize = sizeof(pfd);
pfd.nVersion = 1;
pfd.dwFlags = PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL|PFD_DOUBLEBUFFER;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.cColorBits = 24;
pfd.cDepthBits = 16;
pfd.iLayerType = PFD_MAIN_PLANE;
iFormat = ChoosePixelFormat(*hDC, &pfd);
SetPixelFormat(*hDC, iFormat, &pfd);
*hRC = wglCreateContext(*hDC);
wglMakeCurrent(*hDC, *hRC);
}
void DisableOpenGL(HWND hWnd, HDC hDC, HGLRC hRC) {
wglMakeCurrent(NULL, NULL);
wglDeleteContext(hRC);
ReleaseDC(hWnd, hDC);
}
int Mix(int ca, int cb, double rt) {
int Ar = (ca>>16);
int Ag = ((ca>>8)&((1<<8)-1));
int Ab = (ca&((1<<8)-1));
int Br = (cb>>16);
int Bg = ((cb>>8)&((1<<8)-1));
int Bb = (cb&((1<<8)-1));
int R = int(floor(rt*double(Ar)+(1.0-rt)*double(Br)));
int G = int(floor(rt*double(Ag)+(1.0-rt)*double(Bg)));
int B = int(floor(rt*double(Ab)+(1.0-rt)*double(Bb)));
return (max(0,min(255,R))<<16)+(max(0,min(255,G))<<8)+max(0,min(255,B));
}
int PS = 800;
struct ClassPiece {
int B[10][10], LX, LY, clr, SDel, FstX, FstY;
ClassPiece() {
LX=LY=clr=SDel=0; FstX=FstY=-1;
for (int i=0; i<=9; ++i) {
for (int j=0; j<=9; ++j) B[i][j]=0;
}
}
ClassPiece(int _LX, int _LY, int _clr, int _SDel, vector<vector<int> > _B) {
LX=_LX; LY=_LY; clr=_clr; SDel=_SDel; FstX=FstY=-1;
for (int i=0; i<=9; ++i) {
for (int j=0; j<=9; ++j) B[i][j]=0;
}
for (int i=0; i<_LX; ++i) {
for (int j=0; j<_LY; ++j) {
B[i][j] = _B[_LX-i-1][j];
if ((B[i][j])&&(FstX<0)) {
FstX=i; FstY=j;
}
}
}
}
} Piece[55][4];
vector<pair<int,int> > Kick[55][4][4];
bool CheckKey(char ch) {
return bool(GetAsyncKeyState(ch)&0x8000);
}
struct Board {
int B[111][111], C[111][111], LX, LY, DX;
double KX, KY; int Pid, Dir;
constexpr static char KEY_LEFT = VK_LEFT;
constexpr static char KEY_RIGHT = VK_RIGHT;
constexpr static char KEY_DOWN = VK_DOWN;
constexpr static char KEY_CW = 'x';
constexpr static char KEY_CCW = 'z';
constexpr static char KEY_180 = 'a';
constexpr static char KEY_HARD = ' ';
vector<char> KeyList = {KEY_LEFT,KEY_RIGHT,KEY_DOWN,KEY_CW,KEY_CCW,KEY_180,KEY_HARD};
int KeySta[256];
vector<int> pressed_keys;
uint64_t key_down[256];
Board(int _LX, int _LY, int _DX, double _KX, double _KY) {
LX=_LX; LY=_LY; DX=_DX;
KX=_KX; KY=_KY;
for (int i=0; i<111; ++i) {
for (int j=0; j<111; ++j) B[i][j]=C[i][j]=0;
}
for (int i=0; i<256; ++i) KeySta[i]=0;
}
void Plot(double x, double y, int clr) {
x+=KX; y+=KY;
int B=clr&255; clr>>=8;
int G=clr&255; clr>>=8;
int R = clr&255;
double px = 1.0-x/double(PS);
double py = y/double(PS);
px = px*1.8-0.9;
py = py*1.8-0.9;
glColor3f(min(1.0,max(0.0,double(R)/255.0)), min(1.0,max(0.0,double(G)/255.0)), min(1.0,max(0.0,double(B)/255.0)));
glVertex2f(py, px);
}
void Poly(double x, double y, double r, int n, int clr, double th=0.0) {
glBegin(GL_POLYGON);
for (int i=0; i<n; ++i) {
Plot(x-r*cos(th), y+r*sin(th), clr);
th += 2.0*acos(-1.0)/double(n);
}
glEnd();
}
void Square(double x, double y, double d, int clr) {
glBegin(GL_POLYGON);
Plot(x, y, clr);
Plot(x+d, y, clr);
Plot(x+d, y+d, clr);
Plot(x, y+d, clr);
glEnd();
}
bool CheckActive() {
for (int i=1; i<=LX; ++i) {
for (int j=1; j<=LY; ++j) {
if (C[i][j]) return true;
}
}
return false;
}
bool CheckPlace(int x, int y) {
if ((min(x,y)<1)||((x>LX)||(y>LY))) return true;
return ((B[x][y])&&(!C[x][y]));
}
bool Spawn(int _Pid, int _Dir) {
ClassPiece P = Piece[_Pid][_Dir];
if (LY<P.LY) return false;
int SX=DX-1+P.SDel, SY=(LY-P.LY)/2+1;
SY = max(1,min(LY-P.LY+1,SY));
SX = max(1,min(LX,SX));
for (int i=0; i<P.LX; ++i) {
for (int j=0; j<P.LY; ++j) {
if ((CheckPlace(SX+i,SY+j))&&(P.B[i][j])) return false;
}
}
for (int i=0; i<P.LX; ++i) {
for (int j=0; j<P.LY; ++j) {
if (P.B[i][j]) {
C[SX+i][SY+j]=1; B[SX+i][SY+j]=_Pid;
}
}
}
Pid=_Pid; Dir=_Dir;
return true;
}
bool CheckDown() {
for (int i=1; i<=LX; ++i) {
for (int j=1; j<=LY; ++j) {
if ((C[i][j])&&(CheckPlace(i-1,j))) return false;
}
}
return true;
}
void MoveDown() {
if (!CheckDown()) return;
for (int i=1; i<LX; ++i) {
for (int j=1; j<=LY; ++j) {
if (C[i+1][j]) {
B[i][j]=B[i+1][j]; C[i][j]=1;
B[i+1][j]=C[i+1][j]=0;
}
}
}
}
bool CheckLeft() {
for (int i=1; i<=LX; ++i) {
for (int j=1; j<=LY; ++j) {
if ((C[i][j])&&(CheckPlace(i,j-1))) return false;
}
}
return true;
}
bool MoveLeft() {
if (!CheckLeft()) return false;
for (int i=1; i<=LX; ++i) {
for (int j=1; j<=LY; ++j) {
if (C[i][j+1]) {
B[i][j]=B[i][j+1]; C[i][j]=1;
B[i][j+1]=C[i][j+1]=0;
}
}
}
return true;
}
bool CheckRight() {
for (int i=1; i<=LX; ++i) {
for (int j=1; j<=LY; ++j) {
if ((C[i][j])&&(CheckPlace(i,j+1))) return false;
}
}
return true;
}
bool MoveRight() {
if (!CheckRight()) return false;
for (int i=1; i<=LX; ++i) {
for (int j=LY; j; --j) {
if (C[i][j-1]) {
B[i][j]=B[i][j-1]; C[i][j]=1;
B[i][j-1]=C[i][j-1]=0;
}
}
}
return true;
}
bool Rotate(int NewDir) {
if ((NewDir<0)||(NewDir>3)||(NewDir==Dir)||(!Pid)) return false;
int FstX=0, FstY=0;
for (int i=1; i<=LX; ++i) {
for (int j=1; j<=LY; ++j) {
if (C[i][j]) {
FstX=i; FstY=j; break;
}
}
if (FstX) break;
}
if (!FstX) return false;
int SX=FstX-Piece[Pid][Dir].FstX, SY=FstY-Piece[Pid][Dir].FstY;
ClassPiece P = Piece[Pid][NewDir];
bool flag = false;
for (pair<int,int> KT : Kick[Pid][Dir][NewDir]) {
SX+=KT.second; SY+=KT.first;
bool ok = true;
for (int i=0; i<P.LX; ++i) {
for (int j=0; j<P.LY; ++j) {
if ((P.B[i][j])&&(CheckPlace(SX+i,SY+j))) {
ok=false; break;
}
}
if (!ok) break;
}
if (ok) {
flag=true; break;
}
else {
SX-=KT.second; SY-=KT.first;
}
}
if (!flag) return false;
for (int i=1; i<=LX; ++i) {
for (int j=1; j<=LY; ++j) {
if (C[i][j]) B[i][j]=C[i][j]=0;
}
}
for (int i=0; i<P.LX; ++i) {
for (int j=0; j<P.LY; ++j) {
if (P.B[i][j]) {
B[SX+i][SY+j]=Pid; C[SX+i][SY+j]=1;
}
}
}
Dir = NewDir;
return true;
}
bool SpawnPiece() {
return Spawn(2,0);
}
void Lock() {
for (int i=1; i<=LX; ++i) {
for (int j=1; j<=LY; ++j) C[i][j]=0;
}
}
void HardDrop() {
while (CheckDown()) MoveDown();
Lock();
}
void Square1(int x,int y,int d,int clr){
float b=(clr&255)/256.; clr>>=8;
float g=(clr&255)/256.; clr>>=8;
float r=(clr&255)/256.;
D3D11::draw_cmds.push_back({x,y,d,d, {r,g,b}});
}
void Paint() {
D3D11::draw_cmds.clear();
double sz = min(400.0/double(LY),800.0/double(DX))*0.8;
for (int i=1; i<=DX; ++i) {
for (int j=1; j<=LY; ++j) {
int clr = (B[i][j])?Piece[B[i][j]][0].clr:0xFFFFFF;
if ((!C[i][j])&&(B[i][j])) clr=Mix(0x000000,clr,0.1);
// Square(sz*double(DX-i),sz*double(j-1),sz,clr);
Square1(j*50,(DX-i)*50,50,clr);
}
}
}
vector<char> GetKey() {
vector<char> res;
for (char ch : KeyList) {
bool nw = CheckKey(ch);
if ((nw)&&(!KeySta[ch])) res.push_back(ch);
KeySta[ch] = nw;
}
return res;
}
void Frame() {
if (!CheckActive()) {
SpawnPiece();
}
if (CheckActive()) {
for (char ch : pressed_keys) {
if (ch==KEY_LEFT) MoveLeft();
if (ch==KEY_RIGHT) MoveRight();
if (ch==KEY_CCW) Rotate((Dir+1)&3);
if (ch==KEY_CW) Rotate((Dir+3)&3);
if (ch==KEY_180) Rotate((Dir+2)&3);
if (ch==KEY_DOWN) MoveDown();
if (ch==KEY_HARD) HardDrop();
}
}
pressed_keys.clear();
Paint();
}
} P1(40,10,22,0.0,0.0);
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
auto board=(Board*)GetWindowLongPtr(hWnd,GWLP_USERDATA);
switch (message) {
case WM_CREATE:
return 0;
case WM_CLOSE:
PostQuitMessage (0);
return 0;
case WM_DESTROY:
return 0;
case WM_KEYDOWN:
if (board){
auto key=wParam;
if(!board->key_down[key]||clock()-board->key_down[key]>CLOCKS_PER_SEC*0.03){
board->key_down[key]=clock();
if (key==VK_LEFT || key==VK_RIGHT || key==VK_DOWN || key==VK_UP) PostMessage(hWnd,WM_CHAR,key,0);
}
}
return 0;
case WM_KEYUP:
if(board){ auto key=wParam; board->key_down[key]=0; }
return 0;
case WM_CHAR:
if (board) board->pressed_keys.push_back(wParam);
return 0;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
}
void prepare_data(){
// clang-format off
Piece[1][0] = ClassPiece(4,4,0x66CCFF,-1,{{0,0,0,0},{1,1,1,1},{0,0,0,0},{0,0,0,0}});
Piece[1][1] = ClassPiece(4,4,0x66CCFF,-1,{{0,0,1,0},{0,0,1,0},{0,0,1,0},{0,0,1,0}});
Piece[1][2] = ClassPiece(4,4,0x66CCFF,-1,{{0,0,0,0},{0,0,0,0},{1,1,1,1},{0,0,0,0}});
Piece[1][3] = ClassPiece(4,4,0x66CCFF,-1,{{0,1,0,0},{0,1,0,0},{0,1,0,0},{0,1,0,0}});
Piece[2][0] = ClassPiece(3,3,0x0080FF,-1,{{1,0,0},{1,1,1},{0,0,0}});
Piece[2][1] = ClassPiece(3,3,0x0080FF,-1,{{0,1,1},{0,1,0},{0,1,0}});
Piece[2][2] = ClassPiece(3,3,0x0080FF,-1,{{0,0,0},{1,1,1},{0,0,1}});
Piece[2][3] = ClassPiece(3,3,0x0080FF,-1,{{0,1,0},{0,1,0},{1,1,0}});
for (int i=0; i<4; ++i) {
for (int j=0; j<4; ++j) {
Kick[1][0][3]={{0,0},{-2,0},{+1,0},{-2,-1},{+1,+2}};
Kick[1][3][0]={{0,0},{+2,0},{-1,0},{+2,+1},{-1,-2}};
Kick[1][3][2]={{0,0},{-1,0},{+2,0},{-1,+2},{+2,-1}};
Kick[1][2][3]={{0,0},{+1,0},{-2,0},{+1,-2},{-2,+1}};
Kick[1][2][1]={{0,0},{+2,0},{-1,0},{+2,+1},{-1,-2}};
Kick[1][1][2]={{0,0},{-2,0},{+1,0},{-2,-1},{+1,+2}};
Kick[1][1][0]={{0,0},{+1,0},{-2,0},{+1,-2},{-2,+1}};
Kick[1][0][1]={{0,0},{-1,0},{+2,0},{-1,+2},{+2,-1}};
Kick[1][0][2]={{0,0},{0,+1},{+1,+1},{-1,+1},{+1,0},{-1,0}};
Kick[1][2][0]={{0,0},{0,-1},{-1,-1},{+1,-1},{-1,0},{+1,0}};
Kick[1][1][3]={{0,0},{-1,0},{-1,+2},{-1,+1},{0,+2},{0,+1}};
Kick[1][3][1]={{0,0},{+1,0},{+1,+2},{+1,+1},{0,+2},{0,+1}};
for (int o=2; o<55; ++o) {
Kick[o][0][3]={{0,0},{-1,0},{-1,+1},{0,-2},{-1,-2}};
Kick[o][3][0]={{0,0},{+1,0},{+1,-1},{0,+2},{+1,+2}};
Kick[o][3][2]={{0,0},{+1,0},{+1,-1},{0,+2},{+1,+2}};
Kick[o][2][3]={{0,0},{-1,0},{-1,+1},{0,-2},{-1,-2}};
Kick[o][2][1]={{0,0},{+1,0},{+1,+1},{0,-2},{+1,-2}};
Kick[o][1][2]={{0,0},{-1,0},{-1,-1},{0,+2},{-1,+2}};
Kick[o][1][0]={{0,0},{-1,0},{-1,-1},{0,+2},{-1,+2}};
Kick[o][0][1]={{0,0},{+1,0},{+1,+1},{0,-2},{+1,-2}};
Kick[o][0][2]={{0,0},{0,+1},{+1,+1},{-1,+1},{+1,0},{-1,0}};
Kick[o][2][0]={{0,0},{0,-1},{-1,-1},{+1,-1},{-1,0},{+1,0}};
Kick[o][1][3]={{0,0},{-1,0},{-1,+2},{-1,+1},{0,+2},{0,+1}};
Kick[o][3][1]={{0,0},{+1,0},{+1,+2},{+1,+1},{0,+2},{0,+1}};
}
}
}
// clang-format on
}
int main() {
SetProcessDPIAware();
WNDCLASS wc;
HWND hWnd;
HDC hDC;
HGLRC hRC;
MSG msg;
BOOL bQuit = FALSE;
wc.style = CS_OWNDC;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = GetModuleHandle(nullptr);
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = HBRUSH(GetStockObject (BLACK_BRUSH));
wc.lpszMenuName = NULL;
wc.lpszClassName = "GLSample";
RegisterClass(&wc);
//hWnd = GetConsoleWindow();
hWnd = CreateWindow("GLSample", "Tetris", WS_OVERLAPPEDWINDOW, 0, 0, 1000, 1000, NULL, NULL, GetModuleHandle(nullptr), NULL);
ShowWindow(hWnd, 1);
SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR)&P1);
// EnableOpenGL(hWnd, &hDC, &hRC);
D3D11::hwnd=hWnd;
D3D11::init_D3D11();
prepare_data();
while (!bQuit) {
while (PeekMessage(&msg,NULL,0,0,PM_REMOVE)) {
if (msg.message == WM_QUIT) bQuit=true;
else {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
{
// glClearColor(0.92, 0.92, 0.92, 0);
// glClear(GL_COLOR_BUFFER_BIT);
// glPushMatrix();
P1.Frame();
D3D11::render();
// glPopMatrix();
// SwapBuffers(hDC);
Sleep(16);
}
}
// DisableOpenGL(hWnd, hDC, hRC);
return 0;
}