質問をすることでしか得られない、回答やアドバイスがある。

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

新規登録して質問してみよう
ただいま回答率
85.35%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

DXライブラリ

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

Q&A

解決済

2回答

1818閲覧

dxlib線同士が重ならないようにしたい

papu12

総合スコア2

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

DXライブラリ

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

0グッド

0クリップ

投稿2021/04/17 11:23

編集2021/04/17 11:57

前提・実現したいこと

dxlibでマウスを使って線を引けるようなプログラム(点と点を線で結ぶようなプログラム)を組んでいるのですが黒線を白線で消した後また白線の上から黒線を引こうとすると黒の上に白が重なってしまって黒線の方が見えない状況です。理由としては黒線の処理の下に白線の処理を書いてしまっているからだと思うんですがどうすれば重ならないようになるのかが良くわかりません。プログラム始めたばかりの初心者でコードが汚かったり読み辛かったりするかもしれませんがどうかよろしくお願いいたします

発生している問題・エラーメッセージ

線がかぶってしまって見えない

該当のソースコード

c言語

1#include "DxLib.h" 2#include<math.h> 3const char TITLE[] = ""; 4 5const int WIN_WIDTH = 600; //ウィンドウ横幅 6const int WIN_HEIGHT = 400;//ウィンドウ縦幅 7 8#define BC 20000//黒線の制限 9#define EC 20000//消しゴムの制限 10int WINAPI WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPSTR lpCmdLine, _In_ int nCmdShow) 11{ 12 ChangeWindowMode(TRUE); //ウィンドウモードに設定 13 //ウィンドウサイズを手動では変更できず、かつウィンドウサイズに合わせて拡大できないようにする 14 SetWindowSizeChangeEnableFlag(FALSE, FALSE); 15 SetMainWindowText(TITLE); // タイトルを変更 16 SetGraphMode(WIN_WIDTH, WIN_HEIGHT, 32); //画面サイズの最大サイズ、カラービット数を設定(モニターの解像度に合わせる) 17 SetWindowSizeExtendRate(1.0); //画面サイズを設定(解像度との比率で設定) 18 SetBackgroundColor(255, 255, 255); // 画面の背景色を設定する 19 20 //Dxライブラリの初期化 21 if (DxLib_Init() == -1) { return -1; } 22 23 //(ダブルバッファ)描画先グラフィック領域は裏面を指定 24 SetDrawScreen(DX_SCREEN_BACK); 25 26 //画像などのリソースデータの変数宣言と読み込み 27 int BlackPenX = 0, BlackPenY = 0, Blackradiuss = 1;//書き始めのところ 28 int eraserPenX = 0, eraserPenY = 0, eraserradiuss = 10;//書き始めのところ 29 30 //黒線のx、y 31 int BlackLineX[BC];//点と点結ぶ線のx 32 int BlackLineY[BC];//点と点結ぶ線のy 33 int radius[BC]; 34 int flag[BC]; 35 36 //消しゴム 37 int eraserX[EC];//点と点結ぶ線のx 38 int eraserY[EC];//点と点結ぶ線のy 39 int eraserradius[EC]; 40 int eraserflag[EC]; 41 42 int mousex = 0, mousey = 0;//mouse座標の取得 43 //int BlackPenX, BlackPenY, Blackradiuss; 44 // 45 //黒線の初期化位置をBlackPenX,yに 46 for (int i = 0; i < BC; i++) { 47 BlackLineX[i] = BlackPenX, BlackLineY[i] = BlackPenY, radius[i] = Blackradiuss, flag[i] = 0; 48 } 49 50 for (int i = 0; i < EC; i++) { 51 eraserX[i] = eraserPenX, eraserY[i] = eraserPenY, eraserradius[i] = eraserradiuss, eraserflag[i] = 0; 52 } 53 54 int clickX, clickY; 55 int counttimer = 0; 56 int Ecounttimer = 0; 57 int hanareflag = 0; 58 int type = 0; 59 int kaeflag = 0; 60 int mousetouch = 0; 61 //ゲームループで使う変数の宣言 62 char keys[256] = { 0 }; //最新のキーボード情報用 63 char oldkeys[256] = { 0 };//1ループ(フレーム)前のキーボード情報 64 65 66 67 68 // ゲームループ 69 while (1) 70 { 71 //最新のキーボード情報だったものは1フレーム前のキーボード情報として保存 72 73 //最新のキーボード情報を取得 74 GetHitKeyStateAll(keys); 75 76 //画面クリア 77 ClearDrawScreen(); 78 //--------- ここからプログラムを記述 ----------// 79 80 //更新処理 81 //mouseがタッチ去れた時に建てる 82 if ((GetMouseInput() & MOUSE_INPUT_LEFT) == 1) 83 { 84 mousetouch = 1; 85 } 86 if ((GetMouseInput() & MOUSE_INPUT_LEFT) == 0) 87 { 88 mousetouch = 0; 89 } 90 91 //消しゴムとペンの切り替えフラグ 92 if (keys[KEY_INPUT_1] == 1) { 93 type = 1; 94 } 95 if (type == 1) { 96 if (keys[KEY_INPUT_2] == 1) { 97 kaeflag = 1; 98 type = 0; 99 } 100 } 101 102 //全部消すやつ 103 if (keys[KEY_INPUT_0] == 1) { 104 counttimer = 0; 105 Ecounttimer = 0; 106 } 107 108 //黒線の方の処理 109 GetMousePoint(&mousex, &mousey); 110 GetMouseInput(); 111 112 //mouseが押されたらフラグを1に 113 if ((GetMouseInput() & MOUSE_INPUT_LEFT) == 1){ 114 GetMousePoint(&clickX, &clickY); 115 for (int i = 0; i < BC; i++) { 116 flag[i] = 1; 117 } 118 } 119 120 //カーソル座標をクリック位置に 121 for (int i = 0; i < BC; i++) { 122 if (flag[i] == 1) { 123 BlackPenX = clickX; 124 BlackPenY = clickY; 125 } 126 } 127 128 if (BlackPenX != 0 && BlackPenY != 0) { 129 BlackLineX[counttimer] = BlackPenX; 130 BlackLineY[counttimer] = BlackPenY; 131 132 //制限時間内であれば残像の描画を1ずつ増やす 133 if (counttimer < BC&&type!=1&&mousetouch!=0) { counttimer++; } 134 DrawFormatString(80, 5, GetColor(0, 0, 0), "%d", counttimer); 135 } 136 137 //黒線描画処理 点 138 for (int i = 2; i < counttimer; i++) { 139 DrawCircle(BlackLineX[i], BlackLineY[i], radius[i], GetColor(0, 0, 0), TRUE); 140 141 //線と線の距離を求める 142 double length = sqrt(((BlackLineX[i] - BlackLineX[i - 1]) * (BlackLineX[i] - BlackLineX[i - 1])) + ((BlackLineY[i] - BlackLineY[i - 1]) * (BlackLineY[i] - BlackLineY[i - 1]))); 143 144 if(length < 60) {//ある程度の距離が離れるようだったら線引けないようにする 145 DrawLine(BlackLineX[i - 1], BlackLineY[i - 1], BlackLineX[i], BlackLineY[i], GetColor(0, 0, 0)); 146 } 147 } 148 //黒線処理おわり// 149 150 //////////////// 151 152 //消しゴムの方の処理 153 if ((GetMouseInput() & MOUSE_INPUT_LEFT) == 1){ 154 GetMousePoint(&clickX, &clickY); 155 for (int i = 0; i < EC; i++) { 156 eraserflag[i] = 1; 157 } 158 } 159 160 //カーソル座標をクリック位置に 161 for (int i = 0; i < EC; i++) { 162 if (eraserflag[i] == 1) { 163 eraserPenX = clickX; 164 eraserPenY = clickY; 165 } 166 } 167 168 if (eraserPenX != 0 && eraserPenY != 0) { 169 eraserX[Ecounttimer] = eraserPenX; 170 eraserY[Ecounttimer] = eraserPenY; 171 172 if (Ecounttimer < BC&&type==1&&mousetouch==1) { 173 Ecounttimer++; 174 }//制限時間内であれば点の描画を1ずつ増やす 175 DrawFormatString(80, 5, GetColor(0, 0, 0), "%d", Ecounttimer); 176 } 177 178 //消しゴムのやつ描画 点 179 for (int i = 2; i < Ecounttimer; i++) { 180 DrawCircle(eraserX[i], eraserY[i], eraserradius[i], GetColor(255, 255, 255), TRUE); 181 182 //線分の点と点の距離が一定数離れたら線を描画しないようにする 183 double Elength = sqrt(((eraserX[i] - eraserX[i - 1]) * (eraserX[i] - eraserX[i - 1])) + ((eraserY[i] - eraserY[i - 1]) * (eraserY[i] - eraserY[i - 1]))); 184 if (Elength < 40) { 185 if (type == 1) { 186 DrawLine(eraserX[i - 1], eraserY[i - 1], eraserX[i], eraserY[i], GetColor(255, 255, 255)); 187 } 188 } 189 DrawFormatString(0, 12, GetColor(0, 0, 0), "%d,%d", Ecounttimer, counttimer); 190 } 191 192 193 //新みたいなやう 194 if (type == 0) { 195 DrawLine(BlackPenX, BlackPenY, BlackPenX + Blackradiuss, BlackPenY + Blackradiuss, GetColor(0, 0, 0)); 196 } 197 else { 198 DrawLine(eraserPenX, eraserPenY, eraserPenX + eraserradiuss, eraserPenY + eraserradiuss, GetColor(255, 255, 255)); 199 } 200 //説明書きのところ 201 DrawFormatString(0, 0, GetColor(0, 0, 0), "全削除:0"); 202 if (type == 0) { 203 DrawFormatString(0, 50, GetColor(0, 0, 0), "消しゴム:1 OFF"); 204 } 205 else { 206 DrawFormatString(0, 50, GetColor(0, 0, 0), "消しゴム:1 ON"); 207 } 208 //--------- ここまでにプログラムを記述 ---------// 209 ScreenFlip();//(ダブルバッファ)裏面 210 // 20ミリ秒待機(疑似60FPS) 211 WaitTimer(20); 212 // Windows システムからくる情報を処理する 213 if (ProcessMessage() == -1) 214 { 215 break; 216 } 217 // ESCキーが押されたらループから抜ける 218 if (CheckHitKey(KEY_INPUT_ESCAPE) == 1) 219 { 220 break; 221 } 222 } 223 //Dxライブラリ終了処理 224 DxLib_End(); 225 226 return 0; 227}

試したこと

フラグを変えたりしてあげればできるかなと思いましたがそうすると線自体が消えてしまいました

補足情報(FW/ツールのバージョンなど)

ここにより詳細な情報を記載してください。

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

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

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

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

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

y_waiwai

2021/04/17 11:28

このままではコードが読めないので、質問を編集し、<code>ボタンを押し、出てくる’’’の枠の中にコードを貼り付けてください
papu12

2021/04/17 12:00

申し訳ありません、、修正の方しました ご指摘していただきありがとうございます
guest

回答2

0

(どのような形のものを本当に望まれているのかはわかりませんが)
とりあえず現状の話の延長気味に考えるならば,

黒線を白線で消した後また白線の上から黒線を引こう

という話を表現すればよい,
すなわち,

  1. 最初に黒線を描画する
  2. 次に,白を描画する
  3. その次に,黒線を描画する
  4. ...

という,描画処理の順序を表現できる形でデータを保有し,その順序で描画すればよい.

例えば,黒と白を別々のデータとして保有するのではなくて,白も黒も表せるデータとして,

  • 始点と終点の座標
  • その他必要な情報(線の太さとか)

といった形のデータを考え,
操作によって新しい線等を描画することが決まるごとに,この形のデータを(配列なりに)蓄えていくならば,
蓄えたデータの先頭側のデータから順に用いて描画を行っていけば,描画順序が操作順と一致する.


例えば何かこんなデータ型があって…

C

1//描画すべき1本の線分の情報 2struct LineSeg 3{ 4 int x0,y0, x1,y1; //2端点(x0,y0),(x1,y1) 5 Color DrawColor; //描画色(具体的な型はわからんが) 6}; 7 8//線を描画する 9void DrawLine( const LineSeg *pLG ) 10{ 11 DrawLine( pLG->x0,pLG->y0, pLG->x1,pLG->y1, pLG->DrawColor ); 12}

こんな形で複数の線分の情報を保持しているとしたら…

C

1//データ. 2//(先頭から nLineSegs 個が現在有効なデータ) 3LineSeg LineSegs[100]; 4int nLineSegs = 0;

こうやって,配列 LineSegs[] の先頭側から順に用いて描画する.
先に描画された線分は,後から描画される線分によって一部を上書きされ得る(よね,っていうだけの話)

C

1for( i=0; i<nLineSegs; ++i ) 2{ 3 DrawLine( LineSegs+i ); 4}

投稿2021/04/19 02:00

編集2021/04/20 01:03
fana

総合スコア11996

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

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

papu12

2021/04/19 12:16

確認遅れてしまいすみません。自分の知識足らずで申し訳ないのですが蓄えたデータの先頭から順にというところがまだよく分かりません イメージとしては線の終点からまた線を引くようなものと考えてしまっているのですが、、下は今の自分の考え方のコードです for (int i = 2; i < BC; i++) { DrawCircle(BlackLineX[i], BlackLineY[i], radius[i], GetColor(0, 0, 0), TRUE); //線と線の距離を求める double length = sqrt(((BlackLineX[i] - BlackLineX[i - 1]) * (BlackLineX[i] - BlackLineX[i - 1])) + ((BlackLineY[i] - BlackLineY[i - 1]) * (BlackLineY[i] - BlackLineY[i - 1]))); //if(length < 60) {//ある程度の距離が離れるようだったら線引けないようにする //if(type==0){ DrawLine(BlackLineX[i - 1], BlackLineY[i - 1], BlackLineX[i], BlackLineY[i],cr[i]); //} if (type == 1) { for (int j = i; j < counttimer; j++) {//線の終点から引かれる線 cr[i] = GetColor(255, 255, 255);//色を白に DrawLine(BlackLineX[i-1], BlackLineY[i-1], BlackLineX[i], BlackLineY[i], cr[i]); } } }
fana

2021/04/20 01:05

> ある程度の距離が… みたいな詳細仕様についてはわかりませんが,話の内容を追記はしておきました.
papu12

2021/04/20 04:26

ご丁寧にコードまでありがとうございます、参考になります そして追記で申し訳ないのですが色の切り替えはどうやってするのが正解なんでしょうか?今はフラグでフラグが1の時は白線、0の時は黒線という感じで切り替えているんですが切り替えがうまく行かず、白線の上から黒線を引くことは出来たのですが黒線から白線に切り替えようとすると今まで引いていた黒線がすべて白線になってしまいます この場合どうすればいいのでしょうか?
fana

2021/04/20 04:59

問題点が何なのかわからない. 提示した簡素なコードで言えば, 各線を描画すべき色がデータとして存在しているのだから,それに従って各線を描画するだけの話. その色のデータ値自体をどう決めるのか? という話なら,それはもうアプリケーションの仕様(これからマウスか何かで入力しようとする線が白か黒かを決めるための操作方法というか)次第では.
papu12

2021/04/21 00:54

すみません後から見返してみると訳が分からないことを聞いてました、、もう一度貼ってくれたコードを参考に作ってみたら無事実装の方ができました 本当にありがとうございます
guest

0

ベストアンサー

残念ながら、現在のコードは、データ構造がベクタなのに、上書きで消去するというラスタでのみ有効な機能を実装するという、設計ミスの為、簡単な変更では修正できません。

まずは、ラスタとベクタに関して、学んでください。
ラスタとベクタ

追記
ベクタのまま修正する場合の修正方法です。

現状のデータは、黒線をペン、白線を消しゴムとして扱い、全ての黒線を描画した後、全ての白線を描画しています。
これを、黒線も白線もペンとして扱い、配列も分けずにまとめます。(ただし、別途、色を保持する配列も必要)
描画も、黒線、白線、黒線と書かれたのならば、そのまま、黒線、白線、黒線の順番に描画します。

この修正で、画面上は正しい絵になりますが、本来意図していた消去という概念からは遠ざかります。

その為、描画済みの線を選択できるようにし、選択した線を削除できるようにするのが、一般的な実装になります。

投稿2021/04/17 13:47

編集2021/04/19 22:54
YT0014

総合スコア1750

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

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

papu12

2021/04/19 12:19

全然知りませんでした。ラスタとベクタですか、、勉強してきます 教えてくださりありがとうございました
papu12

2021/04/20 04:04

ご親切に修正方法までありがとうございます。追加の質問で申し訳ないんですが、色を保持する配列についてなんですがどう使えばいいんでしょうか?今は色のオン、オフのフラグを立てて上げてオフの時はgetcolor(0.0.0)オンの時はgetcolor(255.255.255)といった感じに色を変えています。ですがこの方法だと白線の上から黒線を引くことは可能になったのですが黒線から白線に切り替えるとき、今まであった黒線が全部白線になってしまいます。どうするのが正解なんでしょうか?
YT0014

2021/04/20 11:15

現在のコードを最大限生かすのなら、色番号などの配列をX座標などと同じだけ用意することになります。 一般的な実装としては、XYの座標、半径、色などをまとめた構造体を用意し、その構造体の配列で管理します。
papu12

2021/04/21 00:58

なるほど構造体の配列使うんですね おかげさまで上書きの方ができました ありがとうございました これからラスタとベクタについて勉強しようと思います
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問