構造体テンプレートで座標データを使って画面スクロール

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

構造体テンプレートで座標データを使って画面スクロール

#1

投稿記事 by chalaza » 9年前

まず目的はといいますと、SRPGなどで、ターンが変わるときに違うキャラの座標視点に綺麗にスクロールしていく画面の処理がしたいのですが、
いきなり構造体のテンプレートでつまづいてしまい、まずそこをお願いしたいのですが、
キャラクター2人分の全データについて構造体テンプレートを作りました。

コード:

// キャラ全員分構造体
typedef struct {
	int X;
	int Y;
	int DrawX;
	int DrawY;
	int MoveBeforeX;
	int MoveBeforeY;
	int img;
	int gazou;
	int muki;
	int MoveBeforeMuki;
	int walk;
	int scope;
}PlayerAllData_t;

PlayerAllData_t PlayerAllDataSelect[2] = {
	{ Player.X, Player.Y, Player.DrawX, Player.DrawY, Player.MoveBeforeX, Player.MoveBeforeY, Player.img, Made[32],
	Player.muki, Player.MoveBeforeMuki, Player.walk, Player.scope },    //プレイヤー1
	{ Player2.X, Player2.Y, Player2.DrawX, Player2.DrawY, Player2.MoveBeforeX, Player2.MoveBeforeY, Player2.img, Otogi[32],
	Player2.muki, Player2.MoveBeforeMuki, Player2.walk, Player2.scope },  //プレイヤー2
};

PlayerAllData_t PlayerAllData = PlayerAllDataSelect[0];

最初にこう書いておいて、テンプレートの数値を変えるだけで違うキャラのデータにチェンジできるシステムにしたつもりなのですが、
このデータを使おうと思い、テンプレートを0にしてからスクロールの関数で

コード:

void MapScroll()//マップスクロール
{
	//X座標スクロール
	CameraX =180+ PlayerAllData.DrawX - SCREEN_WIDTH/2 + 24;

	if(CameraX < 0)CameraX = 0;
	if(CameraX > (MAP_WIDTH*48)-SCREEN_WIDTH-24) CameraX = (MAP_WIDTH*48)-SCREEN_WIDTH-24;
            //背景表示座標をスクロール
	PlayerViewX = PlayerAllData.DrawX - CameraX;

		//Y座標スクロール
	CameraY =90+ PlayerAllData.DrawY - SCREEN_HEIGHT/2 + 24;

	if(CameraY < 0)CameraY = 0;
	if(CameraY > (MAP_HEIGHT*12)-SCREEN_HEIGHT-12) CameraY = (MAP_HEIGHT*12)-SCREEN_HEIGHT-12;
            //背景表示座標をスクロール
	PlayerViewY = PlayerAllData.DrawY - CameraY;
}
と、PlayerAllData.DrawX を使ったのですが、どうやら認識されていないみたいで、画面が左上に固まってしまいました…
値を表示させてみたところ、常時0になっているところから、定義の仕方がおかしいのかもしれませんが
どこがおかしいでしょうか。

アバター
あたっしゅ
記事: 334
登録日時: 10年前
住所: 東京23区
連絡を取る:

Re: 構造体テンプレートで座標データを使って画面スクロール

#2

投稿記事 by あたっしゅ » 9年前

「テンプレート」という言葉をどういう意味で使ってる ?
この書き込みでは、日常で使う「雛形(ひながた)」という意味かな ?

C++ には、日常で使うのとは違った
http://ja.wikipedia.org/wiki/%E3%83%86% ... %E3%82%B0)
「テンプレート」があります。
手提鞄あたっしゅ、[MrAtassyu] http://ameblo.jp/mratassyu/
手提鞄屋魚有店(てさげかばんやうおありてん)
レスがついていないものを優先して、レスしています。時々、見当外れなレスをします。

chalaza

Re: 構造体テンプレートで座標データを使って画面スクロール

#3

投稿記事 by chalaza » 9年前

間違えてました。テンプレートではなくテーブルの事でした。
構造体テーブルです。すいません

chalaza

Re: 構造体テンプレートで座標データを使って画面スクロール

#4

投稿記事 by chalaza » 9年前

正確には構造体配列というのでしょうか…
全然違いましたね。すいません

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 10年前
住所: 東海地方
連絡を取る:

Re: 構造体テンプレートで座標データを使って画面スクロール

#5

投稿記事 by softya(ソフト屋) » 9年前

コード:

PlayerAllData_t PlayerAllDataSelect[2] = {
    { Player.X, Player.Y, Player.DrawX, Player.DrawY, Player.MoveBeforeX, Player.MoveBeforeY, Player.img, Made[32],
    Player.muki, Player.MoveBeforeMuki, Player.walk, Player.scope },    //プレイヤー1
    { Player2.X, Player2.Y, Player2.DrawX, Player2.DrawY, Player2.MoveBeforeX, Player2.MoveBeforeY, Player2.img, Otogi[32],
    Player2.muki, Player2.MoveBeforeMuki, Player2.walk, Player2.scope },  //プレイヤー2
};
個別の定義と配列の定義の2つは必要ありませんし、初期化で値を入れたらそこで値が固定されます。
つまり、Playerの情報とPlayerAllDataSelect[0]の情報は最初の時点で同じでも、変化するのはPlayerの情報だけでPlayerAllDataSelect[0]の情報は更新されません。この2つは別の構造体で別のアドレスにあるんですから。
いろいろな都合を考えたら配列で定義するのが良いと思いますので、個別のPlayerとPlayer2と言う実体が不要で構造体配列だけを使ってください。

コード:

PlayerAllData_t PlayerAllData = PlayerAllDataSelect[0];
この代入こそ意味が無いです。構造体の内容をあちこちにコピーするのではなく関数にポインタを使った参照渡し(もどき)をしてください。
「C言語ポインタと構造体を理解する」
http://chaichan.lolipop.jp/src/c.htm
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

chalaza

Re: 構造体テンプレートで座標データを使って画面スクロール

#6

投稿記事 by chalaza » 9年前

構造体をキャラ全員分のもの1つだけにして、Playerの1.2の構造体を削除して
シンプルにこんなふうにしてみました。

コード:

// キャラ全員分構造体
typedef struct {
	int X[2];
	int Y[2];
	int DrawX[2];
	int DrawY[2];
	int MoveBeforeX[2];
	int MoveBeforeY[2];
	int img[2];
	int gazou[2];
	int muki[2];
	int MoveBeforeMuki[2];
	int walk[2];
	int scope[2];
}PlayerData;
この構造体の中身を使おうとしたのですが、
他のところでPlayerData.X[0] = 6 ,等と書こうとすると『静的でないメンバー参照は特定のオブジェクトを基準とする相対参照である必要がある』と
言われてしまうのですが、こういうところでポインタを使うとかなのでしょうか…

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 10年前
住所: 東海地方
連絡を取る:

Re: 構造体テンプレートで座標データを使って画面スクロール

#7

投稿記事 by softya(ソフト屋) » 9年前

それだと実体がないので
PlayerData.X[0] = 6
と代入できません。

つまり、

コード:

// キャラ構造体のtypedef
typedef struct {
    int X;
    int Y;
    int DrawX;
    int DrawY;
    int MoveBeforeX;
    int MoveBeforeY;
    int img;
    int gazou;
    int muki;
    int MoveBeforeMuki;
    int walk;
    int scope;
} PlayerData_t;

// キャラ構造体の実体
PlayerData_t PlayerData[2];
としておいて初期化関数で
PlayerData[0].X = 6;
と代入してください。
あとはこのPlayerDataの内容をコピーせずPlayerDataを引数にしてやれば良いでしょう。

●構造体全てを渡す場合
void xxxx_kansu( PlayerData_t PlayerData[],int PlayerDataNum ); //宣言
xxxx_kansu( PlayerData, 2 ); //呼び出し

●1つのプレーヤー構造体のポインタだけ渡す場合
void player_kansu( PlayerData_t *PlayerData ); //宣言
player_kansu( &PlayerData ); //呼び出し
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

chalaza

Re: 構造体テンプレートで座標データを使って画面スクロール

#8

投稿記事 by chalaza » 9年前

ありがとうございます。
構造体配列の設定はなんとかできました。現在のターンの変数を作っているので丁度良かったです。

これでターンによって座標を参照するプレイヤーを変えることができるようになったのですが…
本題のスクロールの話です。長くてすみません。
ターンが変わった時に、次のキャラの座標を中心にした位置へ綺麗にスクロールしていく画面の処理がしたいのです。
綺麗にというのは、ターンが変わる前のキャラの座標から次のターンのキャラの座標まで最短距離を通る軌道を求めて、
その通りに画面を動かすという感じです。
シューティングゲーム等の自機狙い弾と同じようなものかと思って少し調べてみたのですが、
アークタンジェント関数を使うと書いてあるところがあったのですが、画面のスクロールもそれと同じようにできるのでしょうか?

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 10年前
住所: 東海地方
連絡を取る:

Re: 構造体テンプレートで座標データを使って画面スクロール

#9

投稿記事 by softya(ソフト屋) » 9年前

chalaza さんが書きました:アークタンジェント関数を使うと書いてあるところがあったのですが、画面のスクロールもそれと同じようにできるのでしょうか?
考え方としては問題有りませんので、試してみてください。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

chalaza

Re: 構造体テンプレートで座標データを使って画面スクロール

#10

投稿記事 by chalaza » 9年前

#include <math.h>を追加してアークタンジェントを使えるようにして計算を組んだつもりなのですが…

atan2を使おうとしたときだけ、『オーバーロードされた関数"atan2"の複数のインスタンスが引数リストと一致します。』と言われて
エラーになってしまうのですが、これは座標指定の仕方がいけないのでしょうか…

コード:

void HomingScroll(){

	if(Turn==1){	//ターンが0から1になったら
		if(CameraX != PlayerData[1].DrawX && CameraY != PlayerData[1].DrawY){	//カメラ座標XYがプレイヤー2の位置に到達するまで
		double p1 = atan2((PlayerData[1].DrawY - PlayerData[0].DrawY), (PlayerData[1].DrawX - PlayerData[0].DrawX));
		double X1 = cos(p1) * 2;//速さを掛ける
		double Y1 = sin(p1) * 2;

		CameraX = X1 + CameraX;		//カメラ座標を動かす
		CameraY = Y1 + CameraY;

		CameraX =180+ CameraX - SCREEN_WIDTH/2 + 24;	//画面スクロールに反映
		CameraY =180+ CameraY - SCREEN_WIDTH/2 + 24;
		}

		if(CameraX==PlayerData[1].DrawX && CameraY==PlayerData[1].DrawY)//カメラ座標がプレイヤー2に到達したら
			CameraX =180+ PlayerData[1].DrawX - SCREEN_WIDTH/2 + 24;	//カメラをプレイヤー2に固定してもう動かさない
	}

}

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 10年前
住所: 東海地方
連絡を取る:

Re: 構造体テンプレートで座標データを使って画面スクロール

#11

投稿記事 by softya(ソフト屋) » 9年前

あっ、今さら気づきましたが等速で目的座標まで移動するだけならatan2不要ですね。
X,Yの距離の差分を移動フレーム数で割るだけで良いです。

ちなみに、atan2に関しては引数をdoubleにキャストしていないのが原因です。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

chalaza

Re: 構造体テンプレートで座標データを使って画面スクロール

#12

投稿記事 by chalaza » 9年前

フレーム数で割るという事は、距離が遠い場合は移動が速く、近い場合は移動が遅くなりますよね。
ならそっちの方が見栄え的に良いのでこの場合atan2は不要かもしれませんね…

考え方が同じようなら、もし60フレームでうごかしたい場合は
(移動先X-移動前X)/60 と計算してその分X座標を動かせばよいですかね?

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 10年前
住所: 東海地方
連絡を取る:

Re: 構造体テンプレートで座標データを使って画面スクロール

#13

投稿記事 by softya(ソフト屋) » 9年前

chalaza さんが書きました:フレーム数で割るという事は、距離が遠い場合は移動が速く、近い場合は移動が遅くなりますよね。
ならそっちの方が見栄え的に良いのでこの場合atan2は不要かもしれませんね…

考え方が同じようなら、もし60フレームでうごかしたい場合は
(移動先X-移動前X)/60 と計算してその分X座標を動かせばよいですかね?
そういう事ですね。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

chalaza

Re: 構造体テンプレートで座標データを使って画面スクロール

#14

投稿記事 by chalaza » 9年前

なんとかスクロールして動くようにはなったのですが、
プレイヤー1とプレイヤー2の位置によって すごく綺麗にスクロールしたり、ずれた角度で動いて最後に瞬間移動するようになったり、
どうも安定しません。やっぱりスクロールの計算がint型のせいなのでしょうか?

コード:

void HomingScroll(){

	if(TurnChange==1){		//ターンチェンジした瞬間だけ
		Homing2X = PlayerData[(Turn-1)%2].DrawX;	//画面基準(Homing2X,Y)を1ターン前のキャラに合わせる
		Homing2Y = PlayerData[(Turn-1)%2].DrawY;
		HomingStart=1;		//ここからスクロールスタート
		HomingEnd=0;
		Keisan=0;
		TurnChange=0;	//処理をこの瞬間までにする
	}
	if(HomingStart==1 && HomingEnd==0 && Keisan==0){		//スクロールが始まったら
		HomingX = (PlayerData[Turn%2].DrawX - PlayerData[(Turn-1)%2].DrawX)/60;	//60フレームの移動距離(Homing2X,Y)を求める
		HomingY = (PlayerData[Turn%2].DrawY - PlayerData[(Turn-1)%2].DrawY)/60;
		Keisan=1;	//処理をこの瞬間までにする
	}
	if(Keisan==1 && HomingCount<60){	//60フレーム経つまで
		HomingCount++;		//カウントしていく

		Homing2X += HomingX; //画面基準座標を動かす
		Homing2Y += HomingY;

		CameraX =180+ Homing2X - SCREEN_WIDTH/2 + 24;	//画面スクロールに反映
		CameraY =180+ Homing2Y - SCREEN_WIDTH/2 + 24;
	}
	if(HomingCount>=60)	//60フレーム経ったら
		HomingEnd=1;	//終了フラグ
	if(HomingEnd==1){		//終了したら
		HomingCount=0;	//カウンターを初期化
		CameraX =180+ PlayerData[Turn%2].DrawX - SCREEN_WIDTH/2 + 24;	//画面を現在のキャラ座標に固定
		CameraY =180+ PlayerData[Turn%2].DrawY - SCREEN_WIDTH/2 + 24;
		HomingStart=0;	//再スタート用
	}

}

void MapScroll()//マップスクロール
{


	if(Turn==0)		//最初のターンはX座標スクロールしない
		CameraX =180+ PlayerData[0].DrawX - SCREEN_WIDTH/2 + 24;

	if(Turn==0)		//最初のターンはY座標スクロールしない
		CameraY =90+ PlayerData[0].DrawY - SCREEN_HEIGHT/2 + 24;

	if(Turn>0)		//2ターン目からスクロール
		HomingScroll();

	//スクロール画面座標XYがスクリーン最小値、最大値を超えない
	if(CameraX < 0)CameraX = 0;
	if(CameraX > (MAP_WIDTH*48)-SCREEN_WIDTH-24) CameraX = (MAP_WIDTH*48)-SCREEN_WIDTH-24;

	if(CameraY < 0)CameraY = 0;
	if(CameraY > (MAP_HEIGHT*12)-SCREEN_HEIGHT-12) CameraY = (MAP_HEIGHT*12)-SCREEN_HEIGHT-12;

}

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 10年前
住所: 東海地方
連絡を取る:

Re: 構造体テンプレートで座標データを使って画面スクロール

#15

投稿記事 by softya(ソフト屋) » 9年前

スムーズスクロールするなら移動差分と表示位置をdoubleで計算した方が良さそうですね。
doubleの表示座標を表示時だけintにキャストしてください。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

ISLe
記事: 2648
登録日時: 10年前
連絡を取る:

Re: 構造体テンプレートで座標データを使って画面スクロール

#16

投稿記事 by ISLe » 9年前

↓のようにすると誤差が蓄積しません。

コード:

    if(Keisan==1 && HomingCount<60){    //60フレーム経つまで
        HomingCount++;      //カウントしていく

        //画面基準座標を動かす
        Homing2X = PlayerData[Turn%2].DrawX + (PlayerData[(Turn-1)%2].DrawX - PlayerData[Turn%2].DrawX) * (60 - HomingCount) / 60;
        Homing2Y = PlayerData[Turn%2].DrawY + (PlayerData[(Turn-1)%2].DrawY - PlayerData[Turn%2].DrawY) * (60 - HomingCount) / 60;
 
        CameraX =180+ Homing2X - SCREEN_WIDTH/2 + 24;   //画面スクロールに反映
        CameraY =180+ Homing2Y - SCREEN_WIDTH/2 + 24;
    }

chalaza

Re: 構造体テンプレートで座標データを使って画面スクロール

#17

投稿記事 by chalaza » 9年前

doubleで計算してみたら物凄い綺麗に動いてくれました。
キャストも上手くいったので文句無しです。
ありがとうございました 解決とさせて頂きますー。

閉鎖

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