c++11 refactor
This commit is contained in:
@@ -4,82 +4,70 @@
|
||||
#else
|
||||
# include <SDL2_image/SDL_image.h>
|
||||
#endif
|
||||
#include <cstdio>
|
||||
#include <cmath>
|
||||
#include <memory.h>
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include <cstdio>
|
||||
#include <array>
|
||||
#include <utility>
|
||||
|
||||
#define CHARWIDTH 8
|
||||
#define CHARHEIGHT 16
|
||||
|
||||
constexpr int cellWidth = 8, cellHeight = 16;
|
||||
|
||||
enum class EColour : unsigned char
|
||||
{
|
||||
BLACK,
|
||||
BLUE,
|
||||
GREEN,
|
||||
CYAN,
|
||||
RED,
|
||||
MEGENTA,
|
||||
BROWN,
|
||||
LTGREY,
|
||||
DKGREY,
|
||||
LTBLUE,
|
||||
LTGREEN,
|
||||
LTCYAN,
|
||||
LTRED,
|
||||
LTMEGENTA,
|
||||
YELLOW,
|
||||
WHITE
|
||||
BLACK, BLUE, GREEN, CYAN, RED, MEGENTA, BROWN, LTGREY,
|
||||
DKGREY, LTBLUE, LTGREEN, LTCYAN, LTRED, LTMEGENTA, YELLOW, WHITE
|
||||
};
|
||||
|
||||
SDL_Colour g_aColourTable[] =
|
||||
static constexpr std::array<SDL_Colour, 16> colourTable =
|
||||
{
|
||||
{ 0x00, 0x00, 0x00, 0xFF }, // BLACK
|
||||
{ 0x00, 0x00, 0xAA, 0xFF }, // BLUE
|
||||
{ 0x00, 0xAA, 0x00, 0xFF }, // GREEN
|
||||
{ 0x00, 0xAA, 0xAA, 0xFF }, // CYAN
|
||||
{ 0xAA, 0x00, 0x00, 0xFF }, // RED
|
||||
{ 0xAA, 0x00, 0xAA, 0xFF }, // MEGENTA
|
||||
{ 0xAA, 0x55, 0x00, 0xFF }, // BROWN
|
||||
{ 0xAA, 0xAA, 0xAA, 0xFF }, // LTGREY
|
||||
{ 0x55, 0x55, 0x55, 0xFF }, // DKGREY
|
||||
{ 0x55, 0x55, 0xFF, 0xFF }, // BLUE
|
||||
{ 0x55, 0xFF, 0x55, 0xFF }, // GREEN
|
||||
{ 0x55, 0xFF, 0xFF, 0xFF }, // CYAN
|
||||
{ 0xFF, 0x55, 0x55, 0xFF }, // RED
|
||||
{ 0xFF, 0x55, 0xFF, 0xFF }, // MEGENTA
|
||||
{ 0xFF, 0xFF, 0x55, 0xFF }, // YELLOW
|
||||
{ 0xFF, 0xFF, 0xFF, 0xFF } // WHITE
|
||||
/* EColour::BLACK */ SDL_Colour{ 0x00, 0x00, 0x00, 0xFF },
|
||||
/* EColour::BLUE */ SDL_Colour{ 0x00, 0x00, 0xAA, 0xFF },
|
||||
/* EColour::GREEN */ SDL_Colour{ 0x00, 0xAA, 0x00, 0xFF },
|
||||
/* EColour::CYAN */ SDL_Colour{ 0x00, 0xAA, 0xAA, 0xFF },
|
||||
/* EColour::RED */ SDL_Colour{ 0xAA, 0x00, 0x00, 0xFF },
|
||||
/* EColour::MEGENTA */ SDL_Colour{ 0xAA, 0x00, 0xAA, 0xFF },
|
||||
/* EColour::BROWN */ SDL_Colour{ 0xAA, 0x55, 0x00, 0xFF },
|
||||
/* EColour::LTGREY */ SDL_Colour{ 0xAA, 0xAA, 0xAA, 0xFF },
|
||||
/* EColour::DKGREY */ SDL_Colour{ 0x55, 0x55, 0x55, 0xFF },
|
||||
/* EColour::LTBLUE */ SDL_Colour{ 0x55, 0x55, 0xFF, 0xFF },
|
||||
/* EColour::LTGREEN */ SDL_Colour{ 0x55, 0xFF, 0x55, 0xFF },
|
||||
/* EColour::LTCYAN */ SDL_Colour{ 0x55, 0xFF, 0xFF, 0xFF },
|
||||
/* EColour::LTRED */ SDL_Colour{ 0xFF, 0x55, 0x55, 0xFF },
|
||||
/* EColour::LTMEGENTA */ SDL_Colour{ 0xFF, 0x55, 0xFF, 0xFF },
|
||||
/* EColour::YELLOW */ SDL_Colour{ 0xFF, 0xFF, 0x55, 0xFF },
|
||||
/* EColour::WHITE */ SDL_Colour{ 0xFF, 0xFF, 0xFF, 0xFF }
|
||||
};
|
||||
|
||||
struct SChar
|
||||
struct Cell
|
||||
{
|
||||
unsigned char character;
|
||||
EColour bgColour;
|
||||
EColour fgColour;
|
||||
EColour bgColour, fgColour;
|
||||
bool blinking;
|
||||
};
|
||||
|
||||
inline int clampi(int a_iVal, int a_iMin, int a_iMax)
|
||||
template <typename T> constexpr T clamp(T x, T min, T max)
|
||||
{
|
||||
return (a_iVal < a_iMin) ? a_iMin : (a_iVal > a_iMax) ? a_iMax : a_iVal;
|
||||
return x < min ? min : (x > max ? max : x);
|
||||
}
|
||||
|
||||
static Uint32 TimerCallback(Uint32 a_uiInterval, void* a_pParam)
|
||||
static Uint32 timerCallback(Uint32 interval, void* param)
|
||||
{
|
||||
SDL_Event event;
|
||||
SDL_UserEvent userEvent;
|
||||
|
||||
userEvent.type = SDL_USEREVENT;
|
||||
userEvent.code = 0;
|
||||
userEvent.data1 = nullptr;
|
||||
userEvent.data2 = nullptr;
|
||||
|
||||
event.type = SDL_USEREVENT;
|
||||
event.user = userEvent;
|
||||
|
||||
SDL_Event event =
|
||||
{
|
||||
.type = SDL_USEREVENT,
|
||||
.user =
|
||||
{
|
||||
.type = SDL_USEREVENT,
|
||||
.timestamp = SDL_GetTicks(),
|
||||
.code = 0,
|
||||
.data1 = nullptr,
|
||||
.data2 = nullptr
|
||||
}
|
||||
};
|
||||
SDL_PushEvent(&event);
|
||||
|
||||
return a_uiInterval;
|
||||
return interval;
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
@@ -95,83 +83,86 @@ int main(int argc, char** argv)
|
||||
return -1;
|
||||
}
|
||||
|
||||
SDL_Window* pWindow = nullptr;
|
||||
SDL_Renderer* pRenderer = nullptr;
|
||||
if (SDL_CreateWindowAndRenderer(640, 400, 0, &pWindow, &pRenderer) < 0)
|
||||
SDL_Window* window = nullptr;
|
||||
SDL_Renderer* renderer = nullptr;
|
||||
if (SDL_CreateWindowAndRenderer(640, 400, 0, &window, &renderer) < 0)
|
||||
{
|
||||
IMG_Quit();
|
||||
SDL_Quit();
|
||||
return -1;
|
||||
}
|
||||
|
||||
SDL_SetWindowTitle(pWindow, "EnDOOMed");
|
||||
SDL_SetWindowTitle(window, "EnDOOMed");
|
||||
|
||||
SDL_Texture* pCodepage = IMG_LoadTexture(pRenderer, "codepage.png");
|
||||
if (pCodepage == nullptr)
|
||||
SDL_Texture* codepage = IMG_LoadTexture(renderer, "codepage.png");
|
||||
if (codepage == nullptr)
|
||||
{
|
||||
SDL_DestroyRenderer(pRenderer);
|
||||
SDL_DestroyWindow(pWindow);
|
||||
SDL_DestroyRenderer(renderer);
|
||||
SDL_DestroyWindow(window);
|
||||
IMG_Quit();
|
||||
SDL_Quit();
|
||||
return -1;
|
||||
}
|
||||
|
||||
SChar aDisplay[2000];
|
||||
memset(aDisplay, 0, sizeof(aDisplay));
|
||||
std::array<Cell, 2000> display;
|
||||
std::memset(display.data(), 0, sizeof(Cell) * display.size());
|
||||
|
||||
FILE* pFile = fopen("ENDOOM.bin", "rb");
|
||||
if (pFile == nullptr)
|
||||
FILE* file = fopen("ENDOOM.bin", "rb");
|
||||
if (file == nullptr)
|
||||
{
|
||||
SDL_DestroyTexture(pCodepage);
|
||||
SDL_DestroyRenderer(pRenderer);
|
||||
SDL_DestroyWindow(pWindow);
|
||||
SDL_DestroyTexture(codepage);
|
||||
SDL_DestroyRenderer(renderer);
|
||||
SDL_DestroyWindow(window);
|
||||
IMG_Quit();
|
||||
SDL_Quit();
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 2000; ++i)
|
||||
for (Cell& currentCharacter : display)
|
||||
{
|
||||
SChar& currentCharacter = aDisplay[i];
|
||||
unsigned char character[2];
|
||||
fread(character, sizeof(unsigned char), 2, file);
|
||||
|
||||
unsigned char ucSpecial;
|
||||
fread(¤tCharacter.character, sizeof(unsigned char), 1, pFile);
|
||||
fread(&ucSpecial, sizeof(unsigned char), 1, pFile);
|
||||
|
||||
currentCharacter.bgColour = EColour((ucSpecial & 112) >> 4);
|
||||
currentCharacter.fgColour = EColour(ucSpecial & 15);
|
||||
currentCharacter.blinking = (ucSpecial & 128 > 0) ? true : false;
|
||||
currentCharacter =
|
||||
{
|
||||
.character = character[0],
|
||||
.bgColour = EColour((character[1] & 0x70) >> 4),
|
||||
.fgColour = EColour( character[1] & 0x0F),
|
||||
.blinking = (character[1] & (0x80 > 1)) ? true : false
|
||||
};
|
||||
}
|
||||
|
||||
SDL_AddTimer(400, TimerCallback, nullptr);
|
||||
SDL_AddTimer(400, timerCallback, nullptr);
|
||||
|
||||
SChar leftBrush;
|
||||
leftBrush.character = 219;
|
||||
leftBrush.bgColour = EColour::BLACK;
|
||||
leftBrush.fgColour = EColour::LTGREY;
|
||||
leftBrush.blinking = false;
|
||||
|
||||
SChar rightBrush;
|
||||
rightBrush.character = ' ';
|
||||
rightBrush.bgColour = EColour::BLACK;
|
||||
rightBrush.fgColour = EColour::LTGREY;
|
||||
rightBrush.blinking = false;
|
||||
|
||||
bool bMouseLeft = false, bMouseRight = false;
|
||||
int iMousePrevX = 0, iMousePrevY = 0;
|
||||
int iMouseX = 0, iMouseY = 0;
|
||||
bool bMouseInWindow = false;
|
||||
|
||||
bool bValidRender = false;
|
||||
bool bBlinkState = true;
|
||||
bool bRunning = true;
|
||||
SDL_Event event;
|
||||
while (bRunning)
|
||||
Cell leftBrush =
|
||||
{
|
||||
iMousePrevX = iMouseX;
|
||||
iMousePrevY = iMouseY;
|
||||
.character = 219,
|
||||
.bgColour = EColour::BLACK,
|
||||
.fgColour = EColour::LTGREY,
|
||||
.blinking = false
|
||||
};
|
||||
Cell rightBrush =
|
||||
{
|
||||
.character = ' ',
|
||||
.bgColour = EColour::BLACK,
|
||||
.fgColour = EColour::LTGREY,
|
||||
.blinking = false
|
||||
};
|
||||
|
||||
SDL_PumpEvents();
|
||||
bool mouseLeft = false, mouseRight = false;
|
||||
int mousePrevX = 0, mousePrevY = 0;
|
||||
int mouseX = 0, mouseY = 0;
|
||||
bool mouseInWindow = false;
|
||||
|
||||
bool running = true, damage = true;
|
||||
bool blinkState = true;
|
||||
|
||||
do
|
||||
{
|
||||
mousePrevX = mouseX;
|
||||
mousePrevY = mouseY;
|
||||
|
||||
SDL_Event event;
|
||||
if (SDL_WaitEvent(&event))
|
||||
{
|
||||
do
|
||||
@@ -179,44 +170,46 @@ int main(int argc, char** argv)
|
||||
switch (event.type)
|
||||
{
|
||||
case SDL_QUIT:
|
||||
bRunning = false;
|
||||
running = false;
|
||||
break;
|
||||
case SDL_USEREVENT:
|
||||
bBlinkState = !bBlinkState;
|
||||
bValidRender = false;
|
||||
blinkState = !blinkState;
|
||||
damage = true;
|
||||
break;
|
||||
case SDL_MOUSEBUTTONDOWN:
|
||||
if (event.button.button == SDL_BUTTON_LEFT)
|
||||
switch (event.button.button)
|
||||
{
|
||||
bMouseLeft = true;
|
||||
}
|
||||
else if (event.button.button == SDL_BUTTON_RIGHT)
|
||||
{
|
||||
bMouseRight = true;
|
||||
case SDL_BUTTON_LEFT:
|
||||
mouseLeft = true;
|
||||
break;
|
||||
case SDL_BUTTON_RIGHT:
|
||||
mouseRight = true;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case SDL_MOUSEBUTTONUP:
|
||||
if (event.button.button == SDL_BUTTON_LEFT)
|
||||
switch (event.button.button)
|
||||
{
|
||||
bMouseLeft = false;
|
||||
}
|
||||
else if (event.button.button == SDL_BUTTON_RIGHT)
|
||||
{
|
||||
bMouseRight = false;
|
||||
case SDL_BUTTON_LEFT:
|
||||
mouseLeft = false;
|
||||
break;
|
||||
case SDL_BUTTON_RIGHT:
|
||||
mouseRight = false;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case SDL_MOUSEMOTION:
|
||||
iMouseX = event.motion.x;
|
||||
iMouseY = event.motion.y;
|
||||
mouseX = event.motion.x;
|
||||
mouseY = event.motion.y;
|
||||
break;
|
||||
case SDL_WINDOWEVENT:
|
||||
switch (event.window.event)
|
||||
{
|
||||
case SDL_WINDOWEVENT_LEAVE:
|
||||
bMouseInWindow = false;
|
||||
mouseInWindow = false;
|
||||
break;
|
||||
case SDL_WINDOWEVENT_ENTER:
|
||||
bMouseInWindow = true;
|
||||
mouseInWindow = true;
|
||||
break;
|
||||
};
|
||||
break;
|
||||
@@ -225,142 +218,105 @@ int main(int argc, char** argv)
|
||||
while (SDL_PollEvent(&event) > 0);
|
||||
}
|
||||
|
||||
if (bMouseInWindow && (bMouseLeft || bMouseRight))
|
||||
if (mouseInWindow && (mouseLeft || mouseRight))
|
||||
{
|
||||
int iFromX = clampi(iMouseX / CHARWIDTH, 0, 79);
|
||||
int iFromY = clampi(iMouseY / CHARHEIGHT, 0, 24);
|
||||
int iToX = clampi(iMousePrevX / CHARWIDTH, 0, 79);
|
||||
int iToY = clampi(iMousePrevY / CHARHEIGHT, 0, 24);
|
||||
int fromX = clamp(mouseX / cellWidth, 0, 79);
|
||||
int fromY = clamp(mouseY / cellHeight, 0, 24);
|
||||
int toX = clamp(mousePrevX / cellWidth, 0, 79);
|
||||
int toY = clamp(mousePrevY / cellHeight, 0, 24);
|
||||
|
||||
SChar* srcChar = nullptr;
|
||||
if (bMouseLeft)
|
||||
auto srcChar = mouseLeft ? leftBrush : rightBrush;
|
||||
if (toX == fromX && toY == fromY)
|
||||
{
|
||||
srcChar = &leftBrush;
|
||||
}
|
||||
else if (bMouseRight)
|
||||
{
|
||||
srcChar = &rightBrush;
|
||||
}
|
||||
|
||||
if (iToX == iFromX && iToY == iFromY)
|
||||
{
|
||||
SChar& dstChar = aDisplay[iToX + iToY * 80];
|
||||
dstChar.blinking = srcChar->blinking;
|
||||
dstChar.bgColour = srcChar->bgColour;
|
||||
dstChar.fgColour = srcChar->fgColour;
|
||||
dstChar.character = srcChar->character;
|
||||
display[toX + toY * 80] = srcChar;
|
||||
}
|
||||
else
|
||||
{
|
||||
int iTemp;
|
||||
bool bSteep = labs(iToY - iFromY) > labs(iToX - iFromX);
|
||||
if (bSteep)
|
||||
bool steep = std::abs(toY - fromY) > std::abs(toX - fromX);
|
||||
if (steep)
|
||||
{
|
||||
iTemp = iFromY;
|
||||
iFromY = iFromX;
|
||||
iFromX = iTemp;
|
||||
|
||||
iTemp = iToY;
|
||||
iToY = iToX;
|
||||
iToX = iTemp;
|
||||
std::swap(fromY, fromX);
|
||||
std::swap(toY, toX);
|
||||
}
|
||||
if (iFromX > iToX)
|
||||
if (fromX > toX)
|
||||
{
|
||||
iTemp = iToX;
|
||||
iToX = iFromX;
|
||||
iFromX = iTemp;
|
||||
|
||||
iTemp = iToY;
|
||||
iToY = iFromY;
|
||||
iFromY = iTemp;
|
||||
std::swap(toX, fromX);
|
||||
std::swap(toY, fromY);
|
||||
}
|
||||
|
||||
int iDeltaX = iToX - iFromX;
|
||||
int iDeltaY = labs(iToY - iFromY);
|
||||
int iError = iDeltaX / 2;
|
||||
int iY = iFromY;
|
||||
int iYStep = (iFromY < iToY) ? 1 : -1;
|
||||
for (int iX = iFromX; iX <= iToX; ++iX)
|
||||
int deltaX = toX - fromX;
|
||||
int deltaY = std::abs(toY - fromY);
|
||||
int error = deltaX / 2;
|
||||
int y = fromY;
|
||||
int yStep = (fromY < toY) ? 1 : -1;
|
||||
for (int x = fromX; x <= toX; ++x)
|
||||
{
|
||||
if (bSteep)
|
||||
{
|
||||
SChar& dstChar = aDisplay[iY + iX * 80];
|
||||
dstChar.blinking = srcChar->blinking;
|
||||
dstChar.bgColour = srcChar->bgColour;
|
||||
dstChar.fgColour = srcChar->fgColour;
|
||||
dstChar.character = srcChar->character;
|
||||
}
|
||||
else
|
||||
{
|
||||
SChar& dstChar = aDisplay[iX + iY * 80];
|
||||
dstChar.blinking = srcChar->blinking;
|
||||
dstChar.bgColour = srcChar->bgColour;
|
||||
dstChar.fgColour = srcChar->fgColour;
|
||||
dstChar.character = srcChar->character;
|
||||
}
|
||||
int idx = steep
|
||||
? y + x * 80
|
||||
: x + y * 80;
|
||||
display[idx] = srcChar;
|
||||
|
||||
iError -= iDeltaY;
|
||||
if (iError < 0)
|
||||
error -= deltaY;
|
||||
if (error < 0)
|
||||
{
|
||||
iY += iYStep;
|
||||
iError += iDeltaX;
|
||||
y += yStep;
|
||||
error += deltaX;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bValidRender = false;
|
||||
damage = true;
|
||||
}
|
||||
|
||||
if (!bValidRender)
|
||||
if (damage)
|
||||
{
|
||||
SDL_SetRenderDrawColor(pRenderer, 48, 48, 48, 255);
|
||||
SDL_RenderClear(pRenderer);
|
||||
SDL_SetRenderDrawColor(renderer, 48, 48, 48, 255);
|
||||
SDL_RenderClear(renderer);
|
||||
|
||||
SDL_Rect src, dst;
|
||||
src.w = cellWidth;
|
||||
src.h = cellHeight;
|
||||
dst.w = cellWidth;
|
||||
dst.h = cellHeight;
|
||||
|
||||
src.w = CHARWIDTH;
|
||||
src.h = CHARHEIGHT;
|
||||
dst.w = CHARWIDTH;
|
||||
dst.h = CHARHEIGHT;
|
||||
|
||||
int iX = 0, iY = 0;
|
||||
for (int i = 0; i < 2000; ++i)
|
||||
int x = 0, y = 0;
|
||||
for (const auto& currentCharacter : display)
|
||||
{
|
||||
SChar& currentCharacter = aDisplay[i];
|
||||
SDL_Colour& currentBgColour = g_aColourTable[(unsigned char)aDisplay[i].bgColour];
|
||||
SDL_Colour& currentFgColour = g_aColourTable[(unsigned char)aDisplay[i].fgColour];
|
||||
auto currentBgColour = colourTable[static_cast<unsigned char>(currentCharacter.bgColour)];
|
||||
auto currentFgColour = colourTable[static_cast<unsigned char>(currentCharacter.fgColour)];
|
||||
|
||||
src.x = (currentCharacter.character % 32) * CHARWIDTH;
|
||||
src.y = (currentCharacter.character / 32) * CHARHEIGHT;
|
||||
dst.x = iX * CHARWIDTH;
|
||||
dst.y = iY * CHARHEIGHT;
|
||||
src.x = (currentCharacter.character % 32) * cellWidth;
|
||||
src.y = (currentCharacter.character / 32) * cellHeight;
|
||||
dst.x = x * cellWidth;
|
||||
dst.y = y * cellHeight;
|
||||
|
||||
SDL_SetRenderDrawColor(pRenderer, currentBgColour.r, currentBgColour.g, currentBgColour.b, currentBgColour.a);
|
||||
SDL_RenderFillRect(pRenderer, &dst);
|
||||
SDL_SetRenderDrawColor(pRenderer, 0, 0, 0, currentFgColour.a);
|
||||
SDL_SetRenderDrawColor(renderer, currentBgColour.r, currentBgColour.g, currentBgColour.b, currentBgColour.a);
|
||||
SDL_RenderFillRect(renderer, &dst);
|
||||
SDL_SetRenderDrawColor(renderer, 0, 0, 0, currentFgColour.a);
|
||||
|
||||
if (bBlinkState || !currentCharacter.blinking)
|
||||
if (blinkState || !currentCharacter.blinking)
|
||||
{
|
||||
SDL_SetTextureColorMod(pCodepage, currentFgColour.r, currentFgColour.g, currentFgColour.b);
|
||||
SDL_RenderCopy(pRenderer, pCodepage, &src, &dst);
|
||||
SDL_SetTextureColorMod(codepage, currentFgColour.r, currentFgColour.g, currentFgColour.b);
|
||||
SDL_RenderCopy(renderer, codepage, &src, &dst);
|
||||
}
|
||||
|
||||
if (++iX >= 80)
|
||||
if (++x >= 80)
|
||||
{
|
||||
iX = 0;
|
||||
++iY;
|
||||
x = 0;
|
||||
++y;
|
||||
}
|
||||
}
|
||||
|
||||
SDL_RenderPresent(pRenderer);
|
||||
bValidRender = true;
|
||||
SDL_RenderPresent(renderer);
|
||||
damage = false;
|
||||
}
|
||||
}
|
||||
while (running);
|
||||
|
||||
fclose(pFile);
|
||||
SDL_DestroyTexture(pCodepage);
|
||||
SDL_DestroyRenderer(pRenderer);
|
||||
SDL_DestroyWindow(pWindow);
|
||||
fclose(file);
|
||||
SDL_DestroyTexture(codepage);
|
||||
SDL_DestroyRenderer(renderer);
|
||||
SDL_DestroyWindow(window);
|
||||
IMG_Quit();
|
||||
SDL_Quit();
|
||||
return 0;
|
||||
|
||||
Reference in New Issue
Block a user