マウスでクリックした位置にトコトコ歩くには?

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

マウスでクリックした位置にトコトコ歩くには?

#1

投稿記事 by メリッサ » 17年前

キャラクターをマウスでクリックした位置に トコトコ歩くようなプログラムを作りたいのですが、全く思いつきません。教えてください。

プレゼンハムアルゴリズムで、最短距離を算出して、最短経路をたどるようにしたいんですが、過去の履歴にマウスで移動というものが、検索で出なかったため、そういった質問はないのかと思い書きました。

メリッサ

Re:マウスでクリックした位置にトコトコ歩くには?

#2

投稿記事 by メリッサ » 17年前

ラグナロクオンラインなど、ネットゲームで良く使う手法の歩き方をしてみたいということです。

メリッサ

Re:マウスでクリックした位置にトコトコ歩くには?

#3

投稿記事 by メリッサ » 17年前

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

typedef struct{
int x,y,img,muki,walking_flag;
}ch_t;



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

int image[16];
char Key[256];
ch_t ch;

char StrBuf[ 128 ] , StrBuf2[ 32 ];
int MouseX , MouseY ;
int StringCr , BoxCr ;

if( ChangeWindowMode(TRUE) != DX_CHANGESCREEN_OK || DxLib_Init() == -1 ) return -1; //ウィンドウ化と初期化処理

// マウスを表示状態にする
SetMouseDispFlag( TRUE ) ;

// 白色の値を取得
StringCr = GetColor( 255 , 255 , 255 ) ;

// 黒の値を取得
BoxCr = GetColor( 0 , 0 , 0 ) ;

ch.x =320;
ch.y =160;
ch.walking_flag=0;
ch.muki=3;

int MouseXX, MouseYY;
int startX;
int startY;
int deltaX;
int deltaY;
int stepX, stepY;
int fraction;


SetDrawScreen( DX_SCREEN_BACK ) ; //描画先を裏画面に設定
LoadDivGraph( "char.png" , 16 , 4 , 4 , 32 , 32 , image ) ;//画像を分割してimage配列に保存

while(!ProcessMessage() && !ClearDrawScreen() && !GetHitKeyStateAll( Key ) && !Key[KEY_INPUT_ESCAPE]){
//↑メッセージ処理 ↑画面をクリア ↑キーボード入力状態取得 ↑ESCが押されると終了


// マウスの位置を取得
GetMousePoint( &MouseX , &MouseY ) ;

// 表示する文字列を作成
{
lstrcpy( StrBuf , "座標 X" ) ; // 文字列"座標 X"をStrBufにコピー
itoa( MouseX , StrBuf2 , 10 ) ; // MouseXの値を文字列にしてStrBuf2に格納
lstrcat( StrBuf , StrBuf2 ) ; // StrBufの内容にStrBuf2の内容を付け足す
lstrcat( StrBuf , " Y " ) ; // StrBufの内容に文字列" Y "を付け足す
itoa( MouseY , StrBuf2 , 10 ) ; // MouseYの値を文字列にしてStrBuf2に格納
lstrcat( StrBuf , StrBuf2 ) ; // StrBufの内容にStrBuf2の内容を付け足す
}

// 画面左上の領域に黒い四角を描き前に描いてあった
// 文字列を消す
DrawBox( 0 , 0 , 200 , 32 , BoxCr , TRUE ) ;

// 座標文字列を描く
DrawString( 0 , 0 , StrBuf , StringCr ) ;


if( ProcessMessage() == -1 )
{
break ; // エラーが起きたらループを抜ける
}

if( ( GetMouseInput() & MOUSE_INPUT_LEFT ) != 0 )
{

MouseXX = MouseX;
MouseYY = MouseY;
startX = ch.x;
startY = ch.y;
deltaX = MouseXX - ch.x;
deltaY = MouseYY - ch.y;


if (deltaX < 0)
stepX = -1;
else
stepX = 1;
if (deltaY < 0)
stepY = -1;
else
stepY = 1;

deltaX = abs(deltaX * 2);
deltaY = abs(deltaY * 2);


if (deltaX > deltaY) {
fraction = deltaY - deltaX / 2;
while (ch.x != MouseXX) {
if (fraction >= 0) {
ch.y += stepY;
ch.img=image[12];
fraction -= deltaX;
DrawGraph( ch.x , ch.y , ch.img , TRUE ) ;//画像を描画
}
ch.x += stepX;
fraction += deltaY;
ch.img=image[12];
DrawGraph( ch.x , ch.y , ch.img , TRUE ) ;//画像を描画
}

}else {
fraction = deltaX - deltaY / 2;
while (ch.y != MouseYY) {
if (fraction >= 0) {
ch.x += stepX;
ch.img=image[12];
fraction -= deltaY;
DrawGraph( ch.x , ch.y , ch.img , TRUE ) ;//画像を描画
}
ch.y += stepY;
fraction += deltaX;
DrawGraph( ch.x , ch.y , ch.img , TRUE ) ;//画像を描画
}
}



// 押されている

}
else
{
// 押されていない
ch.img=image[12];


}

DrawGraph( ch.x , ch.y , ch.img , TRUE ) ;//画像を描画
ScreenFlip();
}

DxLib_End();
return 0;
}

2Dキャラクターを2Dマップ上で動かすつもりです。
現在このようなプログラムです。
一瞬で移動するのをトコトコあるくようにしたいのですが。
どなかた教えていただけないでしょうか?

メリッサ

Re:マウスでクリックした位置にトコトコ歩くには?

#4

投稿記事 by メリッサ » 17年前

コードが見にくい状態で投稿してしまいました。
すいません。

Re:マウスでクリックした位置にトコトコ歩くには?

#5

投稿記事 by » 17年前

座標指定かな~とか勝手に思っていますが、順路を考えるような思考アルゴリズムがいるかと

座標処理なら、通る道の座標を順残にを格納その通りに歩かせる


斜めに進めるなら
同時に減らす

無理なら片方づつ減らす

でどうでしょうか?

バグ

Re:マウスでクリックした位置にトコトコ歩くには?

#6

投稿記事 by バグ » 17年前

1:マウスカーソルの座標を取得する
2:現在のキャラクターの座標を取得する
3:1と2で取得した2つの点を結ぶ直線の傾きを求める
4:3で求めた角度へキャラクターを一定量移動させる
5:1へ戻る

これでいいんじゃないでしょうか?
三角関数を使えばそんなに難しくはないと思いますよ。

ibis

Re:マウスでクリックした位置にトコトコ歩くには?

#7

投稿記事 by ibis » 17年前

ループ中にWaitTimer関数を入れたらゆっくり移動するようになりそうですね、多分。

メリッサ

Re:マウスでクリックした位置にトコトコ歩くには?

#8

投稿記事 by メリッサ » 17年前

まだ解決していません。

>座標指定かな~とか勝手に思っていますが、順路を考えるような思考アルゴリズムがいるかと
>座標処理なら、通る道の座標を順残にを格納その通りに歩かせる

>斜めに進めるなら
>同時に減らす
>無理なら片方づつ減らす
>でどうでしょうか?

経路の配列を格納しているので、その通りに歩かせることは出来ています。
それが、速すぎて、一瞬で移動します。


>1:マウスカーソルの座標を取得する
>2:現在のキャラクターの座標を取得する
>3:1と2で取得した2つの点を結ぶ直線の傾きを求める
>4:3で求めた角度へキャラクターを一定量移動させる
>5:1へ戻る

>これでいいんじゃないでしょうか?
>三角関数を使えばそんなに難しくはないと思いますよ。

直線の傾きを求めて、求めた角度へキャラクターを一定量移動させるにも、たどる経路の位置を格納するべきだと思うんですが、その経路をたどるときにやっぱし瞬間移動するんじゃないですかね?



>ループ中にWaitTimer関数を入れたらゆっくり移動するようになりそうですね、多分。

その方法はやってみたんですが、できません。
クリックした後にキャラクターはすぐに移動せず、その場でキャラクターが止まり、数秒たったら、瞬間移動するっていうものになりました。

結局トコトコと経路をたどって歩くようにできませんね。

ファイヤーエンブレムなどのシュミレーションゲームみたくすればいいのかなと思ったんですが、シュミレーションゲームの経路をたどって歩かせるプログラムの話やプログラミングのサイトが見つからないですね。
ターン性を導入する物ではないので、常にモンスターも自キャラも動いてるって形にしたいんですが。

ラグナロクオンラインのようなタイプにしたいのですが。。

勉強不足です。
とりあえず解決してません。

経歴2ヶ月

Re:マウスでクリックした位置にトコトコ歩くには?

#9

投稿記事 by 経歴2ヶ月 » 17年前

とりあえず、自分が館と龍神録を参考に追尾ってどうすればできるのか
動くA点に追いかけるB点をどう追尾させるか考えたやつです。

参考にならないと思うけれどシューティングからそのままコピペしました。
for(int i=0;i<ENEMY_TOTAL_NUM;i++){
	if(PointShot.flag==1){
		for(int j=0;j<ENEMY_TOTAL_NUM;j++){
			if(PointShot.PointShots[j].flag==1){//出現中のポイントを抽出する
				PointShot.PointShots[j].angle = atan2(Player.y+PLAYER_SIZE-PointShot.PointShots[j].y,Player.x-PointShot.PointShots[j].x+PLAYER_SIZE);	//角度を決める
				PointShot.PointShots[j].disp_angle =atan2(Player.y+PLAYER_SIZE-PointShot.PointShots[j].y,Player.x-PointShot.PointShots[j].x+PLAYER_SIZE);	//向きを変える
				PointShot.PointShots[j].x+=1*PATTERN1SPEED*cos(PointShot.PointShots[j].angle);	//追尾させるX座標
				PointShot[i].PointShots[j].y+=1*PATTERN1SPEED*sin(PointShot[i].PointShots[j].angle);	//追尾させるY座標
			}
		}
	}
}


------------------
PATTERN1SPEEDが追いかける速度で、上記のプログラムはスキル発動時に画面上に表示されてるポイントが自分へ向かってくる感じです。

経歴2ヶ月

Re:マウスでクリックした位置にトコトコ歩くには?

#10

投稿記事 by 経歴2ヶ月 » 17年前

>1:マウスカーソルの座標を取得する
>2:現在のキャラクターの座標を取得する
>3:1と2で取得した2つの点を結ぶ直線の傾きを求める
>4:3で求めた角度へキャラクターを一定量移動させる
>5:1へ戻る

ようするに上記の考えで、プログラムのforは無視して1、2で座標取得して、atan2()を用いて角度をを求めて、キャラクターをxとy求めた角度ずらならが表示すればテクテク動くんじゃないかと思います。

バグ

Re:マウスでクリックした位置にトコトコ歩くには?

#11

投稿記事 by バグ » 17年前

私がイメージしているものと違っていたら申し訳ないんですが…
とりあえず私がイメージしたものをコーディングしてみました。
#include "DxLib.h"
#include <math.h>

#define PI 3.141592654		// 円周率
#define MOVE 1.0			// 移動量

struct LOCATE
{
	double X;
	double Y;
};

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
	LOCATE locate, mouse;

	// マークの初期位置
	locate.X = 320.0;
	locate.Y = 240.0;

	// Windowの初期化
	ChangeWindowMode(TRUE);
	SetDrawScreen(DX_SCREEN_BACK);

	// DxLibの初期化
	if (DxLib_Init() == -1)
	{
		 return -1;
	}

	while (ProcessMessage() == 0)
	{
		// マウスカーソルの取得
		int x = 0, y = 0;
		if (GetMousePoint(&x, &y) == -1)
		{
			// マウスカーソルの取得に失敗した場合は何もしない
			continue;
		}
		else
		{
			// マウスカーソルの取得
			mouse.X = (double)x;
			mouse.Y = (double)y;
		}

		// 傾きを算出
		double angle = atan2(mouse.Y - locate.Y, mouse.X - locate.X);

		// 算出した傾き方向へ、定数MOVEだけ移動させる
		locate.X += MOVE * cos(angle);
		locate.Y += MOVE * sin(angle);

		// 画面の消去
		ClearDrawScreen();

		// マークの描画
		DrawCircle((int)locate.X, (int)locate.Y, 10, GetColor(255, 255, 255), TRUE);

		ScreenFlip();
	}

	DxLib_End();
	return 0;
}

しりうす~

Re:マウスでクリックした位置にトコトコ歩くには?

#12

投稿記事 by しりうす~ » 17年前

ぱっと見た感じ、FPSとか考慮されて無いっポイんですけどその辺どうなってます?

単純に適当なウェイト処理入れるだけでやりたいことができそうですが。

やそ

Re:マウスでクリックした位置にトコトコ歩くには?

#13

投稿記事 by やそ » 17年前

しりうすさんの言うとおり、
提示されたプログラムを拝見する限り、
FPSなどの同期を取る処理を行っていないがために、
PCの性能限界そのままに表示を繰り返すため、一瞬で移動したように見えるのだと思います。
ある程度のウェイト毎に表示を繰り返していけばいいだけじゃないでしょうか?

シューティングの館のFPSなどを参考にしてみると良いんじゃないかな?

ibis

Re:マウスでクリックした位置にトコトコ歩くには?

#14

投稿記事 by ibis » 17年前

>>ループ中にWaitTimer関数を入れたらゆっくり移動するようになりそうですね、多分。
>
>その方法はやってみたんですが、できません。
>クリックした後にキャラクターはすぐに移動せず、その場でキャラクターが止まり、数秒たったら、瞬間移動するっていうものになりました。

「ループ中に」と書きましたが、ループは3つありますよね。
while(){
  while(){}
  while(){}
}
って感じでwhile文が3つ。
内側の2つのループでウェイトしてみたらできませんか?

Re:マウスでクリックした位置にトコトコ歩くには?

#15

投稿記事 by » 17年前

見づらいソースは見ないので、眺めただけですが(編集で直せると思いますがどうでしょうか?

現在の座標(x1,y1)
マウスで得た座標(x2,y2)

x=x2-x1
y=y2-y1

if y<x
x座標を減らす
else
y座標を減らす

カウントか何かを使って待機状態を作る

現在座標の更新
上から繰り返す…x1 == x2 && y1 == y2 のときbreak
でどうでしょうか?

ラグナロクとかは、移動中に目的地の変更ができるはずなんで、その辺も考慮できるようにした方が良いかと
それと、障害物はどう処理する予定ですか?
これは重要なことと思います。

もう少し、本場のをプレイして、この処理どうやってるんだろ?って深く考えてみると面白いかもwww
僕が言ってるのはなんとなくなんで、違ってたり、実装が面倒だったり、拡張性が無かったり、などなど起こりえるのでwww

** 座標へ移動 **

//座標は0以上で設定するとする。


カウンターが一定の値以上である。とき↓を行う
{
現在の座標(x1,y1)
マウスでクリックしたら更新する座標(x2,y2)
(それ以外は常にこのまま

if ( x1 == x2 && y1 == y2 ){
x=x2 - x1;
y=y2 - y1;
//斜め同時移動
if( x != 0 ){
if( x > 0 ){
x1 += 1;
}else{
x1 -= 1;
}
}
if( y != 0 ){
// x と同じ
}

//ここで、画像を表示
//画面の更新
//待機時間

}
}

でどうでしょ?

メリッサ

Re:マウスでクリックした位置にトコトコ歩くには?

#16

投稿記事 by メリッサ » 17年前

いろいろありがとうございます。
最初の段階で、考えが浅かったと思いますが、いろいろやった結果、処理時間を考慮に入れる方法と
キャラクターの動きの処理の仕方によっても変わる事がわかりましたので、
アドバイスもやりつつ、自分なりにも解決させました。

親切に教えていただき誠にありがとうございます。

閉鎖

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