teratail header banner
teratail header banner
質問するログイン新規登録
Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

DXライブラリ

DXライブラリとは、DirectXを使ったWindowsソフトの開発に必ず付いて回るDirectXやWindows関連のプログラムを使い易くまとめた形で利用できるようにしたC++言語用のゲームライブラリです。

Q&A

解決済

1回答

409閲覧

背景画像上を動く画像に、背景との合成部分のようなものが見える

asdfghjkl_12345

総合スコア27

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

DXライブラリ

DXライブラリとは、DirectXを使ったWindowsソフトの開発に必ず付いて回るDirectXやWindows関連のプログラムを使い易くまとめた形で利用できるようにしたC++言語用のゲームライブラリです。

0グッド

0クリップ

投稿2025/07/10 05:08

編集2025/07/10 17:16

0

0

実現したいこと

Microsoft Visual Studio Community 2022 (64 ビット) - Current Version 17.14.8
C++20
DXライブラリ Ver 3.24f
を使用して、プログラミングをしています。

ディスプレイに背景画像と画像A(キャラクター)を描画するのですが、
画像Aが止まっているときは残像のようなものが見えないのですが、
画像Aを動かしているときには、画像Aの動く方向の画像端のほうに、
背景との合成のような残像のようなものが見えました。

画像Aはキャラクターを描画していると思ってもらえばわかりやすいと思いますが、
画像Aが単純な四角画像の場合は画像端のみ残像があるように見えるのですが、
実際のキャラクターの画像を描画した場合、
特にジャンプなどの斜め移動をする動きをするとき、キャラクターの全体に残像がかかって、かなり見づらいのです。

画像AがBMP画像でも現象が起きます。
テストではウィンドウモードにしていますが、フルスクリーンでも現象が起きます。
また、画面をキャプチャソフトで録画した場合の録画動画でも現象が確認できました。

とりあえずの背景、キャラクター画像はこの質問の最後のほうに張り付けてあります。

これが自分の環境に特有のものなのか、
どんな環境でも起きる現象なのか、
あるいは原因は何か、解決策があれば知りたいです。

該当のソースコード

C++

1//test.h 2#pragma once 3 4#include "DxLib.h" 5 6//変数、関数宣言 7extern int dGraphHandle1; 8extern int dGraphHandle2; 9extern bool dFlag; 10extern int dX; 11extern int dY; 12 13inline void dP_X(int i) { int n = dX; dX = n + i; } 14inline void dP_Y(int i) { int n = dY; dY = n + i; } 15 16void dGraphMove(); 17 18//test.cpp 19#include "test.h" 20 21//変数、関数定義 22int dGraphHandle1 = 0; 23int dGraphHandle2 = 0; 24bool dFlag = 0; 25 26int dX = 0; 27int dY = 0; 28 29void dGraphMove() 30{ 31 //画像を読み込む 32 if (dFlag == false) 33 { 34 dGraphHandle1 = DxLib::LoadGraph("キャラクター画像.png"); 35 dGraphHandle2 = DxLib::LoadGraph("背景画像.png"); 36 37 dFlag = true; 38 } 39 40//描画先を裏画面にする 41 DxLib::SetDrawScreen(DX_SCREEN_BACK); 42//画面をクリアする 43 DxLib::ClearDrawScreen(); 44 45//キャラクターの移動速度 46 int speed = 10; 47 48//上下左右移動 49 if (DxLib::CheckHitKey(KEY_INPUT_UP) != 0) 50 { 51 dP_Y(-speed); 52 } 53 else if (DxLib::CheckHitKey(KEY_INPUT_DOWN) != 0) 54 { 55 dP_Y(speed); 56 } 57 58 if (DxLib::CheckHitKey(KEY_INPUT_LEFT) != 0) 59 { 60 dP_X(-speed); 61 } 62 else if (DxLib::CheckHitKey(KEY_INPUT_RIGHT) != 0) 63 { 64 dP_X(speed); 65 } 66 67//描画の際のブレンドモード無し 68 DxLib::SetDrawBlendMode(DX_BLENDMODE_NOBLEND, 0); 69 70//背景、キャラクター描画 71 DxLib::DrawGraph 72 ( 73 0, 74 0, 75 dGraphHandle2, 76 TRUE 77 ); 78 79 DxLib::DrawGraph 80 ( 81 dX, 82 dY, 83 dGraphHandle1, 84 TRUE 85 ); 86 87//裏画面を表画面に描画 88 DxLib::ScreenFlip(); 89} 90 91//main.cpp 92#pragma once 93#include "test.h" 94 95//FPS制御のための変数 96unsigned long long dNow = 0; 97unsigned long long dStart = 0; 98bool dFlag_Time = 0; 99int dCount = 0; 100 101double dOneFrame = 1000000 / 60; 102 103//main関数 104int WINAPI _tWinMain( 105 [[maybe_unused]] _In_ HINSTANCE hInstance, 106 [[maybe_unused]] _In_opt_ HINSTANCE hPrevInstance, 107 [[maybe_unused]] _In_ LPSTR lpCmdLine, 108 [[maybe_unused]] _In_ int nCmdShow) 109{ 110 111 //ウィンドウモードに変更 112 DxLib::ChangeWindowMode(true); 113 DxLib::SetGraphMode(1900, 1080, 32); 114 115 if (DxLib_Init() == -1) // DXライブラリ初期化処理 116 { 117 return -1; // エラーが起きたら直ちに終了 118 } 119 120 //描画先を裏画面にする 121 DxLib::SetDrawScreen(DX_SCREEN_BACK); 122 123 //ループ処理 124 while ((DxLib::ProcessMessage() == 0) && (DxLib::CheckHitKey(KEY_INPUT_ESCAPE) == 0)) 125 { 126 //FPS処理の初期化 127 if (dFlag_Time == false) 128 { 129 dStart = DxLib::GetNowHiPerformanceCount(); 130 dFlag_Time = true; 131 } 132 133 //現在の時間 134 dNow = DxLib::GetNowHiPerformanceCount(); 135 136 unsigned long long dif = dNow - dStart; 137 138 //FPS制御 139 if (dif >= (dOneFrame * dCount)) 140 { 141 142 //裏画面セット、クリア、 143 //キャラクターの座標移動、 144 //ブレンドモード無し、背景、キャラクターの描画、 145 //ダブルバッファリング 146 dGraphMove(); 147 148 ++dCount; 149 150 //1秒ごと(1000000ミリ秒)に開始時間、カウントをリセット 151 if (dif >= 1000000) 152 { 153 dStart = DxLib::GetNowHiPerformanceCount(); 154 dCount = 0; 155 } 156 } 157 158 } 159 160 DxLib_End(); // DXライブラリ使用の終了処理 161 162 return 0; // ソフトの終了 163 164}

//テスト画像
イメージ説明
イメージ説明

//イメージ画像
画像左が静止中、右が動いている最中のイメージです
イメージ説明
イメージ説明

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

fana

2025/07/10 06:09 編集

念のための現象に関する確認ですが, 実際に各フレームの描画結果が「合成された形の描画結果になっている」ということではなくて, 各フレームの描画結果自体は想定通りであるがそれを見ている人間側には残像が見えてしまう …という話であるという認識で合っていますか? (例えばこのページをブラウザで上下に相応の速度でスクロールさせると残像が見えますが,それをどうにかして軽減したい,みたいな話ですか?)
asdfghjkl_12345

2025/07/10 07:04

「各フレームの描画結果自体は想定通りであるがそれを見ている人間側には残像が見えてしまう」 ということで合っていると思います。 このwebページに載せた、緑の四角画像を上下スクロールすると、私には画像の移動方向の辺のあたりに暗めの緑が見えたりします。 これは緑画像単体で見えますが、私のプログラムでは独自のキャラクター画像もありますが、背景画像と組み合わさって、キャラクター画像に明るい色と暗い色が加わって見え、それがかなりきつく感じられたため、質問を投稿しました。 伝わるかどうかわかりませんが、イメージ画像を追加します。
fana

2025/07/10 07:26

DXライブラリについてよく知らないのでコードから判断できないのですが,これって何FPSくらいで動いているんでしょう? 例えば,「現コードではモニタのリフレッシュレートか何かに依存した速度(:FPS)で動いていてそのためFPSがすごい高い」みたいなことになっていたりする場合,FPSを何らかの狙いの値に制御する実装を入れることである程度改善するのかもしれません. (30FPSとか60FPSになるようにした場合に残像具合がどうなるのか?的な)
asdfghjkl_12345

2025/07/10 08:47

簡易ですが、コードを修正してFPS制御らしきものを入れてみましたが、やはり残像のようなものが見えます。
asdfghjkl_12345

2025/07/10 09:10

ディスプレイのリフレッシュレートは60Hzです
tamoto

2025/07/10 10:05

残像というのが人間の目に残る残像なのか、それとも実際に画面に表示する前から残像的な描画になっているのか、動画を撮って一フレームずつチェックしてみると良いかもしれません。 動画のフレーム上でも「イメージ画像」のように残像的な描画になっているのであればコードの修正が可能ですが、人間の目に残像的に見えているとしたら、デザインの修正などで残像を感じないように直すしかありません。 要するに、目の錯覚画像に対してグニャグニャ動いて見えるのを止めたい、って言われたら、画像のデザインを変えないと無理ということです。
fana

2025/07/10 10:28

(他のモニタだと残像の具合がそうでもないとかそういうのもあり得るかも?)
katsuko

2025/07/10 13:50

「残像」なんですかね。 話を聞く限り、画像Aの描画時におかしなアルファブレンドが行われているようにも見えますが。
hiroki-o

2025/07/10 15:30 編集

Windows 11、Visual Studio 2022、DXライブラリ 3.24fで確認しました。 確かに残像が気になります。 このDXライブラリで作ると、普通にこうなる(要するにライブラリの処理が遅い)のですかね? DXライブラリに詳しくないので具体的なアドバイスはできませんが、再現は簡単です。 有識者の皆さんも試してみてください。 (DXライブラリの公式ページに書いてある通りに設定するだけ) (追記) 毎回、画面全体を書き直しているようなソースに見えます。 背景はバッファに取っておいて、キャラだけ動かすようなことは、できないのかな? ↑全然違っていたら、すみません。
asdfghjkl_12345

2025/07/10 17:01

tomatoさん 録画した動画を1フレームずつ確認してみました。 1フレームごとの画像は背景と画像が合成されたり、残像が発生したりはしていませんでしたので、 デザインの修正を考えてみます。 また、あとに述べますが、ディスプレイの問題もあるかもしれません。 fanaさん 別のディスプレイ(60Hz)を接続して確認してみました。 ディスプレイの大きさが違う(最初は27inchでテスト,別のディスプレイは23inch)ということを差し引いても、見え方が違うと思いました。(ウィンドウモードでウィンドウの大きさを変化させて確認もしました) 後者では、キャラクター自体の残像がなくなるわけではないのですが、例に挙げたイメージ画像における明るくなる色、暗くなる色が少なく感じられました。 katsukoさん はっきりとはわからないのですが、 DxLib::SetDrawBlendMode(DX_BLENDMODE_NOBLEND, 0); でおそらく背景と画像Aをブレンド無しで描画していると思われます。 hiroki-oさん dGraphMove()内、 if (dFlag == false) { dGraphHandle1 = DxLib::LoadGraph("キャラクター画像.png"); dGraphHandle2 = DxLib::LoadGraph("背景画像.png"); dFlag = true; } この部分で、キャラクター画像と背景画像を一回取り込んで、 while()で使いまわしていると思われます。 コード部分に動作に関するコメントを追記します。 今のところ、この現象はディスプレイによって見え方が違う可能性がある、と考えています。 ただ、最初にテストしたディスプレイでこの現象が抑えられるかどうかはわからないので、 この現象が抑えられない場合、キャラクター画像全体が毎フレームアニメーションをしている場合、残像が気にならないかも、という風にするしかないか?と考えています。
hiroki-o

2025/07/10 20:54

画像ファイルの読み込みが最初の1回だけなのは、理解しています。 描画が毎回、画面全体なのでは、と思っただけです。
asdfghjkl_12345

2025/07/10 22:50

hiroki-oさん DXライブラリや他のアプリケーションなどの内部処理として、一部のみ画面を更新することが原因かどうかはわかりませんでしたが、このwebページでも似たような残像現象が起こったため、DXライブラリでは無さそうかな、と思っていました。 結局原因らしきものが判明しましたので、自己解決を参照してみてください。
guest

回答1

0

自己解決

ディスプレイの設定が原因と思われます。

残像が出るディスプレイにはオーバードライブ(OverDrive)機能というものがあり、
この機能をOFFにすると残像現象が収まるように見えました。
オーバードライブを強くすると残像がさらに強くなったので、これが原因の一部であることは間違いないと思われます。
テストした2つのディスプレイで同じくらいの見た目のように見えるので、
これ以上の残像を無くすとしたら別の方法が必要でしょう。
自己解決とさせていただきます。

投稿2025/07/10 23:00

asdfghjkl_12345

総合スコア27

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.30%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問