#13
by ISLe » 6年前
1920x1080を前提に作っていても、それを任意のサイズで表示することはほとんど手間をかけることなくできるのに、その手間を惜しむというのは選ばれたひとにしかプレイして欲しくないという意思表示になってしまうと思いますけどね。
1920x1080固定だと4Kディスプレイでは小さい画面でプレイするのを強制することになりますよ。
ファミコン時代の256x240とかのゲームがPCに移植されるのを豆粒のような画面でプレイしたくはないですよね。
1920x1080を800x600で表示したいのなら、SetGraphMode(1920,1080)のままで、SetWindowSizeExtendRate(0.416)とする。
ただし、この方法はアスペクト比が異なると誤差が大きかったり、環境によってドットが欠けるのを防げなかったりします。
► スポイラーを表示
コード:
#include "DxLib.h"
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
// ↓↓↓↓
SetGraphMode(1920,1080,32);
SetWindowSizeExtendRate(0.416);
// ↑↑↑↑
ChangeWindowMode(TRUE);
if (DxLib_Init() != 0) return 0;
SetDrawScreen(DX_SCREEN_BACK);
while (ProcessMessage() == 0 && ScreenFlip() == 0 && ClearDrawScreen() == 0) {
// 1920x1080を前提とした描画
DrawBox(0,0,1920,1080,GetColor(255,0,0),FALSE);
DrawLine(0,0,1920,1080,GetColor(255,0,0));
DrawLine(0,1080,1920,0,GetColor(255,0,0));
}
DxLib_End();
return 0;
}
ユーザーに、より快適にプレイして欲しいと思うのであれば、オフスクリーンに描画してから、それを表示用画面に描画する方法をお勧めします。
► スポイラーを表示
コード:
#include "DxLib.h"
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
// ↓↓↓↓
// 描画位置とサイズを計算(拡大縮小アスペクト比汎用)
int w = 800; // 画面サイズ
int h = 600; // 〃
int renderW = 1920; // 前提サイズ
int renderH = 1080; // 〃
double rw = (double)w / renderW;
double rh = (double)h / renderH;
if (rw > rh) {
renderW *= rh;
renderH = h;
}
else {
renderW = w;
renderH *= rw;
}
int renderX = (w - renderW) / 2;
int renderY = (h - renderH) / 2;
// 画面サイズを設定
// ウィンドウモードなら上で計算したサイズを使ってアスペクト比による余白を無くすことが可能
SetGraphMode(800,600,32);
// ↑↑↑↑
ChangeWindowMode(TRUE);
if (DxLib_Init() != 0) return 0;
// ↓↓↓↓
// 前提サイズでオフスクリーンを作成
int hOffScrn = MakeScreen(1920,1080);
// ↑↑↑↑
while (ProcessMessage() == 0 && ScreenFlip() == 0 && ClearDrawScreen() == 0) {
// ↓↓↓↓
// オフスクリーンに対して描画するように指定
SetDrawScreen(hOffScrn);
// 表示用画面に転送する際にフィルタを掛けるのでここでは画面全体に対してのフィルターを掛けない
// コンテンツとしてのフィルターは別、掛け過ぎると表示が滲む
SetDrawMode(DX_DRAWMODE_NEAREST);
// ↑↑↑↑
// 1920x1080を前提とした描画
DrawBox(0,0,1920,1080,GetColor(255,0,0),FALSE);
DrawLine(0,0,1920,1080,GetColor(255,0,0));
DrawLine(0,1080,1920,0,GetColor(255,0,0));
// ↓↓↓↓
// バックバッファ(裏画面)に対して描画するように指定
SetDrawScreen(DX_SCREEN_BACK);
// 画面全体に対して掛けるフィルターを指定
SetDrawMode(DX_DRAWMODE_BILINEAR);
// オフスクリーンをバックバッファに描画
DrawExtendGraph(renderX,renderY,renderW,renderH,hOffScrn,FALSE);
// ↑↑↑↑
}
DxLib_End();
return 0;
}
もとの前提サイズに対する描画処理はそのまま、それ以外の部分も定型で使い回せるので、手間は大きくありません。
オフスクリーンをバックバッファに描画する際、もっと(等倍で)大きなサイズのオフスクリーンに(フィルタなしで)描画して、それを表示用画面に描画するようにすると、細い線など細かい部分が欠けたりしない、さらに綺麗な描画を得られます。
#nVIDIAの最新のグラフィックドライバには、ドライバ側でそれをやってくれるようにする設定があります。
(追記)
前者の方法はマウス入力の座標変換をDXライブラリがやってくれますが、後者の方法は自前でやる必要があります。
マウスを使うゲームの場合は、綺麗な描画を得る代わりに、さらにひと手間増えるということになりますね。
1920x1080を前提に作っていても、それを任意のサイズで表示することはほとんど手間をかけることなくできるのに、その手間を惜しむというのは選ばれたひとにしかプレイして欲しくないという意思表示になってしまうと思いますけどね。
1920x1080固定だと4Kディスプレイでは小さい画面でプレイするのを強制することになりますよ。
ファミコン時代の256x240とかのゲームがPCに移植されるのを豆粒のような画面でプレイしたくはないですよね。
1920x1080を800x600で表示したいのなら、SetGraphMode(1920,1080)のままで、SetWindowSizeExtendRate(0.416)とする。
ただし、この方法はアスペクト比が異なると誤差が大きかったり、環境によってドットが欠けるのを防げなかったりします。
[spoil][code=cpp]#include "DxLib.h"
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
// ↓↓↓↓
SetGraphMode(1920,1080,32);
SetWindowSizeExtendRate(0.416);
// ↑↑↑↑
ChangeWindowMode(TRUE);
if (DxLib_Init() != 0) return 0;
SetDrawScreen(DX_SCREEN_BACK);
while (ProcessMessage() == 0 && ScreenFlip() == 0 && ClearDrawScreen() == 0) {
// 1920x1080を前提とした描画
DrawBox(0,0,1920,1080,GetColor(255,0,0),FALSE);
DrawLine(0,0,1920,1080,GetColor(255,0,0));
DrawLine(0,1080,1920,0,GetColor(255,0,0));
}
DxLib_End();
return 0;
}
[/code][/spoil]
ユーザーに、より快適にプレイして欲しいと思うのであれば、オフスクリーンに描画してから、それを表示用画面に描画する方法をお勧めします。
[spoil][code=cpp]#include "DxLib.h"
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
// ↓↓↓↓
// 描画位置とサイズを計算(拡大縮小アスペクト比汎用)
int w = 800; // 画面サイズ
int h = 600; // 〃
int renderW = 1920; // 前提サイズ
int renderH = 1080; // 〃
double rw = (double)w / renderW;
double rh = (double)h / renderH;
if (rw > rh) {
renderW *= rh;
renderH = h;
}
else {
renderW = w;
renderH *= rw;
}
int renderX = (w - renderW) / 2;
int renderY = (h - renderH) / 2;
// 画面サイズを設定
// ウィンドウモードなら上で計算したサイズを使ってアスペクト比による余白を無くすことが可能
SetGraphMode(800,600,32);
// ↑↑↑↑
ChangeWindowMode(TRUE);
if (DxLib_Init() != 0) return 0;
// ↓↓↓↓
// 前提サイズでオフスクリーンを作成
int hOffScrn = MakeScreen(1920,1080);
// ↑↑↑↑
while (ProcessMessage() == 0 && ScreenFlip() == 0 && ClearDrawScreen() == 0) {
// ↓↓↓↓
// オフスクリーンに対して描画するように指定
SetDrawScreen(hOffScrn);
// 表示用画面に転送する際にフィルタを掛けるのでここでは画面全体に対してのフィルターを掛けない
// コンテンツとしてのフィルターは別、掛け過ぎると表示が滲む
SetDrawMode(DX_DRAWMODE_NEAREST);
// ↑↑↑↑
// 1920x1080を前提とした描画
DrawBox(0,0,1920,1080,GetColor(255,0,0),FALSE);
DrawLine(0,0,1920,1080,GetColor(255,0,0));
DrawLine(0,1080,1920,0,GetColor(255,0,0));
// ↓↓↓↓
// バックバッファ(裏画面)に対して描画するように指定
SetDrawScreen(DX_SCREEN_BACK);
// 画面全体に対して掛けるフィルターを指定
SetDrawMode(DX_DRAWMODE_BILINEAR);
// オフスクリーンをバックバッファに描画
DrawExtendGraph(renderX,renderY,renderW,renderH,hOffScrn,FALSE);
// ↑↑↑↑
}
DxLib_End();
return 0;
}
[/code][/spoil]
もとの前提サイズに対する描画処理はそのまま、それ以外の部分も定型で使い回せるので、手間は大きくありません。
オフスクリーンをバックバッファに描画する際、もっと(等倍で)大きなサイズのオフスクリーンに(フィルタなしで)描画して、それを表示用画面に描画するようにすると、細い線など細かい部分が欠けたりしない、さらに綺麗な描画を得られます。
#nVIDIAの最新のグラフィックドライバには、ドライバ側でそれをやってくれるようにする設定があります。
(追記)
前者の方法はマウス入力の座標変換をDXライブラリがやってくれますが、後者の方法は自前でやる必要があります。
マウスを使うゲームの場合は、綺麗な描画を得る代わりに、さらにひと手間増えるということになりますね。