相変わらず超適当ですが Windows(x86, x64, MBCS, 2バイトUnicode), Android(x86) でビルドできるようにしました。
なお、DrawStringで改行したときに何ドット下がるかがAndroid版とWindows版で違う(?)ようなので、手動で数値設定するようにしました。
#include "DxLib.h"
#include <vector>
using namespace std;
#define ALIGNMENT_LEFT 0
#define ALIGNMENT_CENTER 1
#define ALIGNMENT_RIGHT 2
// 文字ごとの色変更版DrawString
//
// bApplyCRColor=TRUEなら、改行文字('\n')にもダミー色を割り当ててあるとして処理
// 位置寄せ指定は『改行後の文字』が対象なので、一行目は左寄せ固定。
// Unicodeは『1文字=2バイトのUnicode』のみが対象。1文字=4バイトのUnicodeでは動作しない。
// nLineInterval=改行の際のドット数 (DrawStringの改行ドット数はWindowsとAndroidで挙動が違うが法則がわからなかったので手動にした)
int DrawStringWithColorArray(int x, int y, const TCHAR* pStr, unsigned int* pColorCodeArray, int bApplyCRColor, int nLineInterval, int nPosAlignment = ALIGNMENT_LEFT)
{
if (pStr == NULL) return -1;
if (pColorCodeArray == NULL) return -1;
#ifdef _WINDOWS
#ifdef UNICODE
const TCHAR *lpStr = pStr;
#else
LPSTR lpStr = (LPSTR)pStr;
#endif
#else
LPSTR lpStr = (LPSTR)pStr;
#endif
vector<vector<TCHAR>> vct;
vector<TCHAR> vct0;
int SizeX, SizeY = 0, ColorBitDepth = 0;
RECT rc;
DxLib::GetDrawArea(&rc);
SizeX = rc.right;
// スクリーンサイズで寄せ位置を設定したい場合は↓
// DxLib::GetScreenState(&SizeX, &SizeY, &ColorBitDepth);
int nFSize = DxLib::GetFontSize(), xs = x;
size_t uiSize = DxLib::strlen2Dx(pStr); // 文字数取得(UTF-8でもここは文字数が返る)
unsigned int uiCL = 0, ui2 = 0;
int tt = 0;
int CharBytes = 0;
TCHAR c;
TCHAR cc[10];
for (unsigned int ui = 0; ui < uiSize; ui++)
{
// まず、現在の文字が何バイトかを取得
#ifdef _WINDOWS
#ifdef UNICODE
CharBytes = 1; // 2バイトなのだが処理の都合上『1単位』とする。なお4バイトUnicodeは対象外
#else
CharBytes = DxLib::GetCharBytes(DX_CHARCODEFORMAT_SHIFTJIS, lpStr + ui2);
#endif
#endif
#ifdef __ANDROID__
CharBytes = DxLib::GetCharBytes(DX_CHARCODEFORMAT_UTF8, lpStr + ui2);
#endif
// 1バイトの場合
if (CharBytes == 1)
{
c = *(lpStr + ui2++);
if (c == '\n')
{
vct.push_back(vct0);
vct0.clear();
}
else {
vct0.push_back(c);
}
}
else {
// 多バイトの場合(改行は無く、文字のみ)
for (int i = 0; i < CharBytes; i++)
{
c = *(lpStr + ui2++);
vct0.push_back(c);
}
}
}
// 最後に \n が無い限り尻切れトンボになるのでそのまま足す
if (vct0.size() > 0)
{
vct.push_back(vct0);
vct0.clear();
}
// ここまでで、行ごとに分割できている
for (unsigned int i = 0; i < vct.size(); i++)
{
vct0 = vct[i]; // i行目
int xss = 0;
if (nPosAlignment == ALIGNMENT_CENTER && i > 0)
{
for (unsigned int k = 0; k < vct0.size(); k++)
{
cc[0] = vct0[k];
#ifdef _WINDOWS
#ifdef UNICODE
CharBytes = 1;
#else
CharBytes = DxLib::GetCharBytes(DX_CHARCODEFORMAT_SHIFTJIS, &cc[0]);
#endif
#endif
#ifdef __ANDROID__
CharBytes = DxLib::GetCharBytes(DX_CHARCODEFORMAT_UTF8, &cc[0]);
#endif
for (int m = 1; m < CharBytes; m++)
{
cc[m] = vct0[++k];
}
cc[CharBytes] = '\0';
xss += DxLib::GetDrawStringWidth(cc, CharBytes);
}
x = (SizeX - xss) / 2;
}
else if (nPosAlignment == ALIGNMENT_RIGHT && i > 0)
{
for (unsigned int k = 0; k < vct0.size(); k++)
{
cc[0] = vct0[k];
#ifdef _WINDOWS
#ifdef UNICODE
CharBytes = 1;
#else
CharBytes = DxLib::GetCharBytes(DX_CHARCODEFORMAT_SHIFTJIS, &cc[0]);
#endif
#endif
#ifdef __ANDROID__
CharBytes = DxLib::GetCharBytes(DX_CHARCODEFORMAT_UTF8, &cc[0]);
#endif
for (int m = 1; m < CharBytes; m++)
{
cc[m] = vct0[++k];
}
cc[CharBytes] = '\0';
xss += DxLib::GetDrawStringWidth(cc, CharBytes);
}
x = SizeX - xss;
}
else
{
x = xs;
}
for (unsigned int j = 0; j < vct0.size(); j++)
{
cc[0] = vct0[j];
#ifdef _WINDOWS
#ifdef UNICODE
CharBytes = 1;
#else
CharBytes = DxLib::GetCharBytes(DX_CHARCODEFORMAT_SHIFTJIS, &cc[0]);
#endif
#endif
#ifdef __ANDROID__
CharBytes = DxLib::GetCharBytes(DX_CHARCODEFORMAT_UTF8, &cc[0]);
#endif
for (int m = 1; m < CharBytes; m++)
{
cc[m] = vct0[++j];
}
cc[CharBytes] = '\0';
DxLib::DrawString(x, y, cc, pColorCodeArray[uiCL++]);
x += DxLib::GetDrawStringWidth(cc, CharBytes);
}
if (bApplyCRColor) uiCL++;
y += nLineInterval;
}
return 0;
}
#ifdef _WINDOWS
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
#endif
#ifdef __ANDROID__
int android_main(void)
#endif
{
#ifdef _WINDOWS
DxLib::ChangeWindowMode(TRUE);
#endif
if (DxLib::DxLib_Init() == -1) return -1;
DxLib::SetBackgroundColor(128, 128, 128);
DxLib::ClearDrawScreen();
DxLib::SetFontSize(20);
DxLib::SetDrawScreen(DX_SCREEN_BACK);
int SizeX, SizeY = 0, ColorBitDepth = 0;
DxLib::GetScreenState(&SizeX, &SizeY, &ColorBitDepth);
TCHAR *pStr = TEXT("Hello_\nC++_DXライブラリProgramming\nカナカナKANA");
size_t uiSize = DxLib::strlen2Dx(pStr);
unsigned int *puiCArray = new unsigned int[uiSize], uiCounter = 0, uiCounter2 = 0;
while (DxLib::ProcessMessage() == 0)
{
DxLib::ClearDrawScreen();
if (uiCounter++ % 30 == 0)
{
for (unsigned int ui = 0; ui < uiSize; ui++)
{
puiCArray[ui] = DxLib::GetColor((uiCounter2 + ui & 2) ? 255 : 0, (uiCounter2 + ui & 4) ? 255 : 0, (uiCounter2 + ui & 1) ? 255 : 0);
}
uiCounter2++;
}
// 通常描画
DxLib::DrawString(50, 50, pStr, DxLib::GetColor(255, 255, 255));
// 文字単位で色変更する
int nLIntv = DxLib::GetFontSize() + 2; // 行間はお好みで設定してください。
DrawStringWithColorArray(50, 150, pStr, puiCArray, TRUE, nLIntv); // 改行でも色カウンターを進める場合・左寄せ
DrawStringWithColorArray(50, 250, pStr, puiCArray, FALSE, nLIntv, ALIGNMENT_CENTER); // 改行では色カウンターを進めない場合・中央寄せ
DxLib::SetDrawArea(0, 330, SizeX / 2, 450); // 描画範囲を狭く設定する
DxLib::DrawBox(0, 0, SizeX, SizeY, DxLib::GetColor(132, 193, 255), TRUE);
DrawStringWithColorArray(50, 350, pStr, puiCArray, TRUE, nLIntv, ALIGNMENT_RIGHT); // 改行でも色カウンターを進める場合・右寄せ・描画範囲指定
DxLib::SetDrawArea(0, 0, SizeX, SizeY); // 描画範囲を画面いっぱいに戻す
DxLib::ScreenFlip();
}
delete[]puiCArray;
return DxLib::DxLib_End();
}