画像の移動

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
きつね

画像の移動

#1

投稿記事 by きつね » 15年前

はじめまして、学校の課題で行き詰ったので投稿させていただきます。
課題の内容は「出発座標から目的座標まで画像を移動させる」というものです。
そこで以下のようなプログラムを作りました。

#include "DxLib.h"
#include <math.h>

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow )
{

SetGraphMode(1366,768,32) ;
if(DxLib_Init()==-1) return -1 ;
SetDrawScreen(DX_SCREEN_BACK) ; //裏画面に描画

float sb,sbx,sby,bx,by,sx,sy; //初期座標と目的地の座標
float Ex,Ey,Esx,Esy; //移動時の座標
int agent; //人のグラフィック
int Cr; //線の色
double sokudo; //速度
double SB; //移動距離
float rad; //ラジアン

bx=600; //出発点x座標
by=300; //出発点y座標
sx=800; //目的地x座標
sy=600; //目的地y座標

sokudo=10; //人の移動速度
sbx=sx-bx; //それぞれのx座標の差
sby=by-sy; //それぞれのy座標の差
sb=sqrt(sbx*sbx+sby*sby); //出発点と目的地の距離
Esx=sbx/sb*sokudo; //x方向の移動速度
Esy=sby/sb*sokudo; //y方向の移動速度
agent=LoadGraph("char1.png"); //画像をメモリに読み込み
Cr=GetColor(255,255,255); //白の取得
SB=0; //初期値
Ex=0; //初期値
Ey=0; //初期値
rad=atan2(sbx,sby); //ラジアン

while(sb>SB) //SBがsbになるまで繰り返す
{

ClearDrawScreen(); //画面の初期化
Ex+=Esx; //EsxをExに代入
Ey+=Esy; //EsyをEyに代入
SB=sqrt(Ex*Ex+(Ey)*(Ey)); //移動距離の計算
DrawRotaGraph(bx+Ex,by-Ey,0.3f,rad,agent,TRUE); //画像の描画
DrawLine(bx,by,sx,sy,Cr); //線の描画
ScreenFlip(); //表画面へ描画

}

WaitKey() ; // キー入力待ち
DxLib_End() ; // DXライブラリ使用の終了処理
return 0 ; // ソフトの終了
}


一応移動はするのですが、目的座標にぴったりと到着しません。while(sb>SB)のあたりの計算式に問題があるはずなのですがどうしたらよいのかわかりません。
それと、目的座標に着いたら違う目的座標に再度移動するというプログラムも入れたいのですがどういう方法があるのでしょうか?自分は上記のプログラムを使ってif文等を使えば動くと思うのですが、どのようなプログラムの書き方をすればよいのかわかりません。

以上が質問になります。助言を頂けると嬉しいです、よろしくおねがいします。

[1] わからないこと
 (1)目的座標にぴったりと到着するにはどうしたらよいか
 (2)目的座標に着いたら再度違う目的座標に移動する
[2] 環境  
 [2.1] OS : WindowsXP
 [2.2] コンパイラ名 : VC++

[3] その他
 ・C言語を初めてまだ2週間程度です
 ・DXライブラリを使用

さかまき

Re:画像の移動

#2

投稿記事 by さかまき » 15年前

ループの中での sb,SB の値を調べるとわかりますが
sb = 360.555115 に対して、SB=10,20,30.... であり
ループを抜ける時には
sb=360.555115 SB=359.999860 (sb>SB)
sb=360.555115 SB=369.999851 (sb<SB)
となっており、一回ループが多いですね
歩幅が大きいから通り越しちゃってます。

さかまき

Re:画像の移動

#3

投稿記事 by さかまき » 15年前

ループの中のSBの計算のあとで通り越したかを判断して(if (sb<SB))
最後の一歩の調整を行う必要があります。ループは無限ループ(while(1))
にして、通り越したらループを抜ける様にしたほうがよいかも

きつね

Re:画像の移動

#4

投稿記事 by きつね » 15年前

ご回答ありがとうございます。
ループを無限ループにし、最後の一歩の処理を(sb<SB)になった時に目的座標に画像を描画するようにしてみました。

while(1)
{

ClearDrawScreen(); //画面の初期化
Ex+=Esx; //EsxをExに代入
Ey+=Esy; //EsyをEyに代入
SB=sqrt(Ex*Ex+(Ey)*(Ey)); //移動距離の計算

if(sb<SB)
{
DrawRotaGraph(sx,sy,0.3f,rad,agent,TRUE); //最後の一歩分の処理
ScreenFlip();
break;
}

DrawRotaGraph(bx+Ex,by-Ey,0.3f,rad,agent,TRUE); //画像の描画
DrawRotaGraph(sx,sy,0.3f,rad,agent,TRUE);
ScreenFlip(); //表画面へ描画


こんな感じでいいでしょうか?なにか改良点などがあればお願いします。

さかまき

Re:画像の移動

#5

投稿記事 by さかまき » 15年前

DrawLineがなくなったりしたのは関知しない事にして
>(1)目的座標にぴったりと到着するにはどうしたらよいか
は解決したのですよね?あとは
>(2)目的座標に着いたら再度違う目的座標に移動する
ですが、いまの動かす部分を引数(bx,by,sx,sy,sokudo)のサブルーチンUgokeにしてしまえば
Ugoke(600.0 , 300.0 , 800.0 , 600.0 ,10.0);
Ugoke(800.0 , 600.0 ~);
でずんずん進めます。

ところで、sqrtやatan2 の引数および返り値の型はfloatでOKですか?

きつね

Re:画像の移動

#6

投稿記事 by きつね » 15年前

ご回答ありがとうございます。DrawLineは特に意味がないので消してしまいました。
自分はC言語初心者なのでサブルーチンについて調べていました。
サブルーチンがどのようなものかは理解できましたが、どうやってプログラムを記述してよいのかいまいちわかりません。

*************************************************************************************

[1]
(bx,by,sx,sy,sokudo)の形で引数のリストを作る

[2]
sbx=sx-bx; //それぞれのx座標の差
sby=by-sy; //それぞれのy座標の差
sb=sqrt(sbx*sbx+sby*sby); //出発点と目的地の距離
Esx=sbx/sb*sokudo; //x方向の移動速度
Esy=sby/sb*sokudo; //y方向の移動速度
  rad=atan2(sbx,sby); //ラジアン

引数によって変化する値の部分の計算をする

[3]

while(1)
{

ClearDrawScreen(); //画面の初期化
Ex+=Esx; //EsxをExに代入
Ey+=Esy; //EsyをEyに代入
SB=sqrt(Ex*Ex+(Ey)*(Ey)); //移動距離の計算

if(sb<SB)
{
DrawRotaGraph(sx,sy,0.3f,rad,agent,TRUE); //最後の一歩分の処理
ScreenFlip();
break;
}

DrawRotaGraph(bx+Ex,by-Ey,0.3f,rad,agent,TRUE); //画像の描画
ScreenFlip(); //表画面へ描画

画像を移動させる計算をする。

************************************************************************************************

「目的座標に着いたら再度違う目的座標に移動する」
の手順はこのような感じでループさせればよいと思うのですが、どのようにプログラムを記述していけばよいのかわかりません・・・。

>ところで、sqrtやatan2 の引数および返り値の型はfloatでOKですか?
型の方もfloat、doubleは「小数点が付く値で使う」程度にしか理解しておらずの、どちらが適しているのかもわかりません・・・。

さかまき

Re:画像の移動

#7

投稿記事 by さかまき » 15年前

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance。。。。
の上に

void Ugoke(float bx,float by,float sx,float sy,double sokudo)
{
// この中に始点から終点まで動く処理を記述
// bx,by,sx,sy,sokudo の型宣言は引数のなかで行っているので不要
}
を記述しておけば、メインのなかで
Ugoke(600.0 , 300.0 , 800.0 , 600.0 ,10.0);
Ugoke(800.0 , 600.0 ,違う目的座標X,違う目的座標Y,速度);
を記述していけばよいです。

きつね

Re:画像の移動

#8

投稿記事 by きつね » 15年前

ご回答ありがとうございます。完成しました!
こんな感じになりました

#include "DxLib.h"
#include <math.h>

void Ugoke(float bx,float by,float sx,float sy,double sokudo)
{

float sb,sbx,sby; //初期座標と目的地の座標
float Ex,Ey,Esx,Esy; //移動時の座標
int agent; //人のグラフィック
double SB; //移動距離
float rad; //ラジアン

sbx=sx-bx; //それぞれのx座標の差
sby=by-sy; //それぞれのy座標の差
sb=sqrt(sbx*sbx+sby*sby); //出発点と目的地の距離
Esx=sbx/sb*sokudo; //x方向の移動速度
Esy=sby/sb*sokudo; //y方向の移動速度
agent=LoadGraph("char1.png"); //画像をメモリに読み込み
SB=0; //初期値
Ex=0; //初期値
Ey=0; //初期値
rad=atan2(sbx,sby); //ラジアン

while(1)
{

ClearDrawScreen(); //画面の初期化
Ex+=Esx; //EsxをExに代入
Ey+=Esy; //EsyをEyに代入
SB=sqrt(Ex*Ex+(Ey)*(Ey)); //移動距離の計算

if(sb<SB)
{
DrawRotaGraph(sx,sy,0.3f,rad,agent,TRUE); //最後の一歩分の処理
ScreenFlip();
break;
}

DrawRotaGraph(bx+Ex,by-Ey,0.3f,rad,agent,TRUE); //画像の描画
ScreenFlip(); //表画面へ描画
}

}


int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow )
{

SetGraphMode(1366,768,32) ; //画面の大きさ
if(DxLib_Init()==-1) return -1 ;
SetDrawScreen(DX_SCREEN_BACK) ; //裏画面に描画


Ugoke(600.0 , 300.0 , 800.0 , 600.0 ,3.0); //座標速度設定
Ugoke(800.0 , 600.0 , 300.0 , 200.0 ,3.0);
Ugoke(300.0 , 200.0 , 500.0 , 600.0 ,3.0);
Ugoke(500.0 , 600.0 , 300.0 , 200.0 ,3.0);
Ugoke(300.0 , 200.0 , 100.0 , 100.0 ,3.0);

WaitKey() ; // キー入力待ち
DxLib_End() ; // DXライブラリ使用の終了処理
return 0 ; // ソフトの終了
}


まだまだ沢山わからないこともあるのでさらに勉強したいと思います。
本当にお世話になりました。ありがとうございました。

閉鎖

“C言語何でも質問掲示板” へ戻る