カメラを実装したら当たり判定がずれた。

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
keito940
記事: 105
登録日時: 7年前

カメラを実装したら当たり判定がずれた。

#1

投稿記事 by keito940 » 7年前

前回、当たり判定を苦心して実装しました。今度は、http://dixq.net/forum/viewtopic.php?f=3&t=7765を参考にして、縦スクロールを作って、なんとかカメラをキャラに向かせることに成功したのですが、今度は当たり判定全体がずれてしまいます。どうすればいいのでしょうか?
コードは以下のとおりです。

コード:

//衝突のテストプログラム
//アクションゲームのテストシステムを作る前に、
//めり込み防止のアルゴリズムを初心者なりに作らざるをえない。
//Create 2017/02/10
#include "DxLib.h"

#define SCREEN_WIDTH (320)		//画面の横幅
#define SCREEN_HEIGHT (240)		//画面の縦幅
#define STAGE_WIDTH  (336)
#define STAGE_HEIGHT (480)
#define CHIP_SIZE (16)			//チップのサイズ
#define MAP_WIDTH (STAGE_WIDTH/CHIP_SIZE)
#define MAP_HEIGHT (STAGE_HEIGHT/CHIP_SIZE)
HANDLE Stdout;

char MapData[MAP_HEIGHT][MAP_WIDTH]
{
	1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1, 
	1,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 1, 
	1,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 1, 
	1,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 1,
	1,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 1,

	1,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 1,
	1,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 1,
	1,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 1,
	1,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 1,
	1,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 1,

	1,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 1,
	1,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 1,
	1,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 1,
	1,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 1,
	1,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 1,

	1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,
};

float PlayerX, PlayerY;
float SaveX, SaveY;
float MoveX, MoveY;
float DropPower, Grav;
char JumpFlag, Dir;

int Input, EdgeInput;
int FreamStartTime;
int CameraX = 0;
int CameraY = 0;
int CharX, CharY, View_CharX, View_CharY;
int MapHitCheck(float X, float Y, float *MoveX, float *MoveY, int Size);
int CharMove(float *X, float *Y, float MoveX, float MoveY, float *Drop, float *G, char *Jump, float Size);
int MapChipParam(float X, float Y);

int MapChipParam(float X, float Y) {
	int x, y;

	x = (int)X / CHIP_SIZE;
	y = (int)Y / CHIP_SIZE;

	if (x >= MAP_WIDTH || y >= MAP_HEIGHT || x < 0 || y < 0) return 0;

	return MapData[y][x];
}
//衝突判定
int MapHitCheck(float X, float Y, float *MoveX, float *MoveY, int Size) {
	float afX, afY;
	afX = X + *MoveX;
	afY = Y + *MoveY;
	float blx, brx, bby, bty;
	blx = (float)((int)afX / Size)*Size;
	brx = (float)((int)afX / Size + 1)*Size;
	bty = (float)((int)afY / Size)*Size;
	bby = (float)((int)afY / Size + 1)*Size;
	if (MapChipParam(afX, afY) == 1) {
		if (*MoveY > 0.0F) {
			printf("\n下に当たりました。");
			//移動量を補正する
			*MoveY = bty - Y - 1.0F;
			//上の壁に当たったと判定する
			return 3;
		}
		if (*MoveY < 0.0F) {
			printf("\n上に当たりました。");
			//移動量を補正する
			*MoveY = bby - Y + 1.0F;
			//下の壁に当たったと判定する
			return 4;
		}
		//右の当たり判定
		if (*MoveX > 0.0F) {
			printf("\n右に当たりました。");
			//移動量を補正する
			*MoveX = blx - X - 1.0F;
			//右の壁に当たったと判定する
			return 1;
		}
		//左の当たり判定
		if (*MoveX < 0.0F) {
			printf("\n左に当たりました。");
			//移動量を補正する
			*MoveX = brx - X + 1.0F;
			//左の壁に当たったと判定する
			return 2;
		}
		//ここに来たら適当な値を返す
		return 4;
	}
	return 0;
}
//当たり判定チェック
int CharMove(float *X, float *Y, float MoveX, float MoveY, float *Drop,float *G,char *Jump,float Size){
	float Dummy = 0.0F;
	float hsize;
	//直前フレーム
	float PrevX = *X + MoveX;
	float PrevY = *Y + MoveY;
	//ベクトルのバックアップ
	float SaveMoveX = MoveX;
	float SaveMoveY = MoveY;

	hsize = Size * 0.5F; 
	//上下の当たり判定チェック、上に衝突したら落下させ、下に衝突したら着地させる。
	{
		//左下
		if (MapHitCheck(*X - hsize, *Y + hsize - 1.0F, &Dummy, &MoveY,(int)Size) == 3) *Drop = 0.0F,MoveY -= 1.0F,printf("\n上下::左下");
		//右下
		if (MapHitCheck(*X + hsize, *Y + hsize - 1.0F, &Dummy, &MoveY,(int)Size) == 3) *Drop = 0.0F,MoveY -= 1.0F,printf("\n上下::右下");
		//左上
		if (MapHitCheck(*X - hsize, *Y - hsize + 1.0F, &Dummy, &MoveY,(int)Size) == 4) *Drop *= -0.5F,MoveY = 0.0F,printf("\n上下::左上");
		//右上
		if (MapHitCheck(*X + hsize, *Y - hsize + 1.0F, &Dummy, &MoveY,(int)Size) == 4) *Drop *= -0.5F,MoveY = 0.0F,printf("\n上下::右上");
		//問題ないのなら移動させる
		PrevY = *Y + MoveY;
		*Y = PrevY;
	}
	//左右の当たり判定チェック
	{
		//左下
		if (MapHitCheck(*X - hsize + 1.0F, *Y + hsize, &MoveX, &Dummy, (int)Size))MoveX += 1.0F, printf("\n左右::左下");
		//右上
		if (MapHitCheck(*X + hsize - 1.0F, *Y + hsize, &MoveX, &Dummy, (int)Size))MoveX -= 1.0F, printf("\n左右::右下");
		//左上
		if (MapHitCheck(*X - hsize + 1.0F, *Y - hsize, &MoveX, &Dummy, (int)Size))MoveX += 1.0F, printf("\n左右::左上");
		//右上
		if (MapHitCheck(*X + hsize - 1.0F, *Y - hsize, &MoveX, &Dummy, (int)Size))MoveX -= 1.0F, printf("\n左右::右上");
		//問題ないのなら移動させる
		PrevX = *X + MoveX;
		*X = PrevX;
	}
	//着地判定
	{
		if (MapChipParam(*X - hsize, *Y + hsize + 1.0F) == 0 && MapChipParam(*X + hsize, *Y + hsize + 1.0F) == 0) {
			*Jump = TRUE;
			*G = 0.5F;
		}
		else {
			*Drop = 0.0F;
			*G = 0.0F;
			*Jump = FALSE;
		}
	}
	return 0;
}
int init(void) {
	ChangeWindowMode(TRUE),SetGraphMode(320,240,32),printf("初期化しています…"); 
	if (DxLib_Init() == -1) { return -1; }
	PlayerX = 160.0F, PlayerY = 120.0F, MoveX = 0.0F, MoveY = 0.0F;
	JumpFlag = FALSE, DropPower = 0.0F, Grav = 0.5F, Dir = TRUE;
	Input = 0, EdgeInput = 0, FreamStartTime = GetNowCount();
	return 0;
}
int main(void) {
	FreamStartTime = GetNowCount();
	while (GetNowCount() - FreamStartTime < 1000 / 60) { Sleep(1); }
	system("cls");
	printf("メインループ開始\n");
	printf("\nPlayerX=%d,PlayerY=%d,Grav=%8.1f,DropPower=%8.1f", (int)PlayerX, (int)PlayerY, Grav,DropPower);
	printf("\nMoveX=%8.1f,MoveY=%8.1f,Jump=%d", MoveX, MoveY,JumpFlag);
	printf("\nCharX=%d,CharY=%dCameraX=%d,CameraY=%d,ViewX=%d,ViewY=%d", CharX, CharY, CameraX, CameraY, View_CharX, View_CharY);
	{
		int i;
		i = GetJoypadInputState(DX_INPUT_KEY_PAD1);
		EdgeInput = i & ~Input;
		Input = i;
	}
	//移動処理
	{
		MoveX = 0.0F;
		MoveY = 0.0F;
		if ((Input&PAD_INPUT_RIGHT) != 0) {
			Dir = TRUE;
			MoveX += 5.0F;
		}
		if ((Input&PAD_INPUT_LEFT) != 0) {
			Dir = FALSE;
			MoveX -= 5.0F;
		}
		if (JumpFlag == FALSE && (EdgeInput&PAD_INPUT_1) != 0) {
			Grav = 0.5F;
			DropPower = -9.5F;
			JumpFlag = TRUE;
		}
		//落下処理
		DropPower += Grav;
		MoveY = DropPower;
		//移動量に基づいて移動する。
		CharMove(&PlayerX, &PlayerY, MoveX, MoveY, &DropPower, &Grav, &JumpFlag, CHIP_SIZE);
	}
	//カメラのチェック
	CharX = PlayerX;
	CharY = PlayerY;
	//カメラの位置を計算する
	CameraX = CharX - SCREEN_WIDTH / 2;
	CameraY = CharY - SCREEN_HEIGHT / 2;
	//カメラの補正
	if (CameraX < 0)CameraX = 0;
	if (CameraX > (STAGE_WIDTH - SCREEN_WIDTH))CameraX = (STAGE_WIDTH - SCREEN_WIDTH);
	if (CameraY < 0)CameraY = 0;
	if (CameraY > (STAGE_HEIGHT - SCREEN_HEIGHT))CameraY = (STAGE_HEIGHT - SCREEN_HEIGHT);
	//画面上の位置
	View_CharX = CharX - CameraX;
	View_CharY = CharY - CameraY;
	//マップの描画
	{
		int i, j;
		for (i = 0; i < MAP_HEIGHT; i++) {
			for (j = 0; j < MAP_WIDTH; j++) {
				if (MapData[i][j] == 1) {
					DrawBox(j*CHIP_SIZE - CameraX, i*CHIP_SIZE - CameraY, j*CHIP_SIZE + CHIP_SIZE - CameraX, i*CHIP_SIZE + CHIP_SIZE - CameraY, GetColor(255, 255, 255), TRUE);
				}
			}
		}
	}
	//キャラの描画
	DrawBox((int)(View_CharX), (int)(View_CharY), (int)(View_CharX-CHIP_SIZE) + 1, (int)(View_CharY-CHIP_SIZE) + 1, GetColor(255, 0, 0), TRUE);
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
	AllocConsole(); FILE* out = 0; freopen_s(&out, "CON", "w", stdout); Stdout = GetStdHandle(STD_OUTPUT_HANDLE);
	init();
	while (ScreenFlip() == 0 && ProcessMessage() == 0 && ClearDrawScreen() == 0) {
		main();
	}
	DxLib_End(); fclose(out); FreeConsole();
	return 0;
}
最後に編集したユーザー keito940 on 2017年3月01日(水) 15:20 [ 編集 6 回目 ]

Math

Re: カメラを実装したら当たり判定がずれた。

#2

投稿記事 by Math » 7年前

http://dixq.net/forum/viewtopic.php?f=3&t=7765は横スクロールの話であって縦スクロールの参考にはならないと思いますよ。横より縦の方が面倒かも?

コード:

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    AllocConsole(); FILE* out = 0; freopen_s(&out, "CON", "w", stdout); Stdout = GetStdHandle(STD_OUTPUT_HANDLE);
    init();SetConsoleTextAttribute(Stdout, 10 + (0 << 4));//<<<=====色を変えた
    while (ScreenFlip() == 0 && ProcessMessage() == 0 && ClearDrawScreen() == 0) {
        main();WaitKey();//<<<=====スペースキーなどを押してステップ実行させる
    }
    DxLib_End(); fclose(out); FreeConsole();
    return 0;
}
「スペースキーなどを押してステップ実行させると

コード:

メインループ開始

PlayerX=160,PlayerY=225,Grav=     0.5,DropPower=    10.0
MoveX=     0.0,MoveY=    10.0,Jump=1
CharX=160,CharY=225CameraX=0,CameraY=105,ViewX=160,ViewY=120
下に当たりました。
上下::左下
--------------------
のあとMoveY= 0となりおかしくなります。

keito940
記事: 105
登録日時: 7年前

Re: カメラを実装したら当たり判定がずれた。

#3

投稿記事 by keito940 » 7年前

Math さんが書きました:http://dixq.net/forum/viewtopic.php?f=3&t=7765は横スクロールの話であって縦スクロールの参考にはならないと思いますよ。横より縦の方が面倒かも?
えーっと、つまり、横スクロールは非常に簡単というわけですね。実はもう一つ解決したいのがありまして、キャラが画面の端まで来たらカメラを止まらず、カメラも動いてしまいます。結構めんどくさいらしいので頑張ります!

コード:

メインループ開始

PlayerX=160,PlayerY=225,Grav=     0.5,DropPower=    10.0
MoveX=     0.0,MoveY=    10.0,Jump=1
CharX=160,CharY=225,CameraX=0,CameraY=105,ViewX=160,ViewY=120
下に当たりました。
上下::左下
--------------------
のあとMoveY= 0となりおかしくなります。
つまり、地面の位置がずれているわけなんですね。具体的にどうすればいいのでしょうか?
変更したコードは以下のとおりです:

コード:

	//カメラのチェック
	CharX = PlayerX;
	CharY = PlayerY;
	//カメラの位置を計算する
	CameraX = CharX - SCREEN_WIDTH / 2;
	CameraY = CharY - SCREEN_HEIGHT / 2;
	//カメラの補正
	if (CameraX < 0)CameraX = 0;
	if (CameraX > (STAGE_WIDTH - SCREEN_WIDTH))CameraX = (STAGE_WIDTH - SCREEN_WIDTH);
	if (CameraY < 0)CameraY = 0;
	if (CameraY > (STAGE_HEIGHT - SCREEN_HEIGHT))CameraY = (STAGE_HEIGHT - SCREEN_HEIGHT);
	if (CameraY == (STAGE_HEIGHT + SCREEN_HEIGHT))CameraY = (STAGE_HEIGHT + SCREEN_HEIGHT);
	//画面上の位置
	View_CharX = CharX - CameraX;
	View_CharY = CharY - CameraY;
	//マップの描画
	{
		int i, j;
		for (i = 0; i < MAP_HEIGHT; i++) {
			for (j = 0; j < MAP_WIDTH; j++) {
				if (MapData[i][j] == 1) {
					DrawBox(j*CHIP_SIZE - CameraX, i*CHIP_SIZE - CameraY, j*CHIP_SIZE + CHIP_SIZE - CameraX, i*CHIP_SIZE - CHIP_SIZE - CameraY, GetColor(255, 255, 255), TRUE);
				}
			}
		}
	}
まだ当たり判定がおかしいままのようです。

Math

Re: カメラを実装したら当たり判定がずれた。

#4

投稿記事 by Math » 7年前


>えーっと、つまり、横スクロールは非常に簡単というわけですね。
違います。直観でいいました。いま”C言語わくわくゲームプログラミング教室”の5.横スクロールアクションゲームを作ろう を読み始めたところです。縦も横も難しそうです。失礼いたしました。(”龍神録プログラミングの館”は縦のスクロールしてたはずだから質問してみれ......。)

このプログラムはよく把握出来ていません。スクロールする為の要件を一度基本から見てみます..。
>まだ当たり判定がおかしいままのようです
そうですか。全体的に把握しにくいので全方位がいいのか一点集中がいいのか..。

Math

Re: カメラを実装したら当たり判定がずれた。

#5

投稿記事 by Math » 7年前

簡単な設計図を作ってみませんか。フローチャートのようなもの。
たしか プログラムから生成出来るはず。(少なくともC#,VisualBasicではそういう資料を自動生成してたのです)
風呂チャート?とか...何かみたような?..

Math

Re: カメラを実装したら当たり判定がずれた。

#6

投稿記事 by Math » 7年前

http://csi.nisinippon.com/flow2.png
http://csi.nisinippon.com/flow1.png
一応フロチャートは自動生成出来ました。思ったより大きな図になりました。
これで解析して見ます。

Math

Re: カメラを実装したら当たり判定がずれた。

#7

投稿記事 by Math » 7年前

フローチャート自動生成に使用したソフトは”Visustin – フローチャートジェネレイター”で
http://www.aivosto.com/visustin-ja.htmlからダウンロードしました。
30日無料使用版です。言語がたくさんあります。C/C++はを選んでC++のファイルを開くだけでOKですよ。

math

Re: カメラを実装したら当たり判定がずれた。

#8

投稿記事 by math » 7年前

左下にDrawボタンがあります。押すとフローチャートを描きます。

アバター
もるも
記事: 54
登録日時: 8年前
連絡を取る:

Re: カメラを実装したら当たり判定がずれた。

#9

投稿記事 by もるも » 7年前

>当たり判定がずれた

当たり判定のチップの座標にもマップチップ描画と時のようにカメラ移動した分計算してみてください。

アバター
usao
記事: 1887
登録日時: 11年前

Re: カメラを実装したら当たり判定がずれた。

#10

投稿記事 by usao » 7年前

オフトピック
・「カメラ」は単にゲームの状態を表示する方法のみに関わる話
・「当たり判定」はゲームのロジック(ゲームの状態をあれこれ演算する部分)の話
ですよね.
つまり「カメラ」というのは,「当たり判定」側には一切影響が無い要素.
(当たり判定等を計算している部分は,カメラなんてものが存在することすら知らないし知らなくていいし)

「カメラでスクロールがどうの…」な話が無い状態では「当たり判定」ができていた という話なのであれば
「当たり判定」部分(というかゲームのロジック部分の実装)はそのときの状態のものをそのまま用いていれば良いのではないかと思いますが…

アバター
もるも
記事: 54
登録日時: 8年前
連絡を取る:

Re: カメラを実装したら当たり判定がずれた。

#11

投稿記事 by もるも » 7年前

この方法はプレイヤーが移動したら条件別に計算して、
大きいマップをゲームスクリーンの320×240内に描画できるよう、マップの座標をずらしていくことによってスクロールを表現しています。
なので、
スクロールさせる場合はキャラクター、マップ、当たり判定すべてにCamera分(どれだけマップを動かしたか)を計算しないとずれてしまいます。

keito940
記事: 105
登録日時: 7年前

Re: カメラを実装したら当たり判定がずれた。

#12

投稿記事 by keito940 » 7年前

もるもさんの言うとおりにカメラ分を計算させてみたのですが、キャラがマップの中央に行って衝突したっきり動きません。
WaitKeyによると、一度落下してから、以下のコンソールのような当たり判定に衝突しましたと出るのです。

コード:

int main(void) {
	FreamStartTime = GetNowCount();
	while (GetNowCount() - FreamStartTime < 1000 / 60) {}
	system("cls");
	printf("メインループ開始\n");
	printf("\nPlayerX=%d,PlayerY=%d,Grav=%8.1f,DropPower=%8.1f", (int)PlayerX, (int)PlayerY, Grav,DropPower);
	printf("\nMoveX=%8.1f,MoveY=%8.1f,Jump=%d", MoveX, MoveY,JumpFlag);
	printf("\nCharX=%d,CharY=%d,CameraX=%d,CameraY=%d,ViewX=%d,ViewY=%d", CharX, CharY, CameraX, CameraY, ViewCharX, ViewCharY);
	{
		int i;
		i = GetJoypadInputState(DX_INPUT_KEY_PAD1);
		EdgeInput = i & ~Input;
		Input = i;
	}
	//カメラのチェック
	CharX = PlayerX;
	CharY = PlayerY;
	//カメラの位置を計算する
	CameraX = CharX - SCREEN_WIDTH / 2;
	CameraY = CharY - SCREEN_HEIGHT / 2;
	//カメラの補正
	if (CameraX < 0)CameraX = 0;
	if (CameraX >(STAGE_WIDTH - SCREEN_WIDTH))CameraX = (STAGE_WIDTH - SCREEN_WIDTH);
	if (CameraY < 0)CameraY = 0;
	if (CameraY >(STAGE_HEIGHT - SCREEN_HEIGHT))CameraY = (STAGE_HEIGHT - SCREEN_HEIGHT);
	if (CameraY == (STAGE_HEIGHT + SCREEN_HEIGHT))CameraY = (STAGE_HEIGHT + SCREEN_HEIGHT);
	//画面上の位置
	ViewCharX = CharX - CameraX;
	ViewCharY = CharY - CameraY;
	//カメラ分の計算
	CameraMoveX = CharX-ViewCharX;
	CameraMoveY = CharY - ViewCharY;

	//移動処理
	{
		MoveX = 0.0F;
		MoveY = 0.0F;
		if ((Input&PAD_INPUT_RIGHT) != 0) {
			Dir = TRUE;
			MoveX += 5.0F;
		}
		if ((Input&PAD_INPUT_LEFT) != 0) {
			Dir = FALSE;
			MoveX -= 5.0F;
		}
		if (JumpFlag == FALSE && (EdgeInput&PAD_INPUT_1) != 0) {
			Grav = 0.5F;
			DropPower = -9.5F;
			JumpFlag = TRUE;
		}
		//落下処理
		DropPower += Grav;
		MoveY = DropPower;
		//移動量に基づいて移動する。
		CharMove(&PlayerX+CameraMoveX, &PlayerY+CameraMoveY, MoveX, MoveY, &DropPower, &Grav, &JumpFlag, CHIP_SIZE);
	}
	//マップの描画
	{
		int i, j;
		for (i = 0; i < MAP_HEIGHT; i++) {
			for (j = 0; j < MAP_WIDTH; j++) {
				if (MapData[i][j] == 1) {
					DrawBox(j*CHIP_SIZE - CameraMoveX, i*CHIP_SIZE - CameraMoveY, j*CHIP_SIZE + CHIP_SIZE - CameraMoveX, i*CHIP_SIZE - CHIP_SIZE - CameraMoveY, GetColor(255, 255, 255), TRUE);
				}
			}
		}
	}
	//キャラの描画
	DrawBox((int)(ViewCharX), (int)(ViewCharY), (int)(ViewCharX-CHIP_SIZE) + 1, (int)(ViewCharY-CHIP_SIZE) + 1, GetColor(255, 0, 0), TRUE);
}
コンソールは以下のとおりです。

コード:

メインループ開始

PlayerX=167,PlayerY=121,Grav=     0.0,DropPower=     0.0
MoveX=     0.0,MoveY=     0.0,Jump=0
CharX=167,CharY=121,CameraX=7,CameraY=1,ViewX=160,ViewY=120
上下::左上
上下::右上
左右::左下
右に当たりました。
左右::右下
左に当たりました。
左右::右上

アバター
みけCAT
記事: 6734
登録日時: 13年前
住所: 千葉県
連絡を取る:

Re: カメラを実装したら当たり判定がずれた。

#13

投稿記事 by みけCAT » 7年前

keito940 さんが書きました:

コード:

		//移動量に基づいて移動する。
		CharMove(&PlayerX+CameraMoveX, &PlayerY+CameraMoveY, MoveX, MoveY, &DropPower, &Grav, &JumpFlag, CHIP_SIZE);
このコードは、PlayerXやPlayerYは1要素の配列とみなせるので、CameraMoveXやCameraMoveYが0でない場合は範囲外のポインタがCharMoveに渡され、
CharMoveでは渡されたポインタをデリファレンスするため未定義動作になる、非常によくないコードです。
keito940 さんが書きました:もるもさんの言うとおりにカメラ分を計算させてみたのですが
usaoさんが言うやり方でやってみてください。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

アバター
usao
記事: 1887
登録日時: 11年前

Re: カメラを実装したら当たり判定がずれた。

#14

投稿記事 by usao » 7年前

オフトピック
>usaoさんが言うやり方でやってみてください。

参考にしたというトピックの話をそのまま書いただけですけどね.

#参考先トピックの末尾(No15)でも書かれていますが,
 複数の座標系の間の座標変換処理を関数として書く
 (そしてもちろん,座標変換を行う場所では常にそれを使う)
 ことは重要だと個人的に思います.
 それをやれば(やれるなら)多分何の問題も無く終わる話.

keito940
記事: 105
登録日時: 7年前

Re: カメラを実装したら当たり判定がずれた。

#15

投稿記事 by keito940 » 7年前

usaoさんの言うとおりに、カメラの関数を作って、横のスクロールはうまく行ったのですが、縦のスクロールがうまくできません。
でも、内部処理上では落下しているようです。
ちなみに、コードは以下のとおりです。

コード:

//カメラの位置計算
int CameraCheck(float X, float Y) {
	//カメラのチェック
	CharX = X;
	CharY = Y;
	//カメラの位置を計算する
	CameraX = CharX - SCREEN_WIDTH / 2;
	CameraY = CharY - SCREEN_HEIGHT / 2;
	//カメラの補正
	if (CameraX < 0)CameraX = 0;
	if (CameraX >(STAGE_WIDTH - SCREEN_WIDTH))CameraX = (STAGE_WIDTH - SCREEN_WIDTH);
	if (CameraY < 0)CameraY = 0;
	if (CameraY >(STAGE_HEIGHT - SCREEN_HEIGHT))CameraY = (STAGE_HEIGHT - SCREEN_HEIGHT);
	if (CameraY == (STAGE_HEIGHT + SCREEN_HEIGHT))CameraY = (STAGE_HEIGHT + SCREEN_HEIGHT);
	ViewCharX = CharX - CameraX;
	ViewCharY = CharY - CameraY;
	return 0;
}
int init(void) {
	ChangeWindowMode(TRUE),SetGraphMode(320,240,32),printf("初期化しています…"); 
	if (DxLib_Init() == -1) { return -1; }
	PlayerX = 160.0F, PlayerY = 120.0F, MoveX = 0.0F, MoveY = 0.0F;
	JumpFlag = FALSE, DropPower = 0.0F, Grav = 0.5F, Dir = TRUE;
	Input = 0, EdgeInput = 0, FreamStartTime = GetNowCount();
	return 0;
}
int main(void) {
	FreamStartTime = GetNowCount();
	while (GetNowCount() - FreamStartTime < 1000 / 60) {}
	system("cls");
	printf("メインループ開始\n");
	printf("\nPlayerX=%d,PlayerY=%d,Grav=%8.1f,DropPower=%8.1f", (int)PlayerX, (int)PlayerY, Grav,DropPower);
	printf("\nMoveX=%8.1f,MoveY=%8.1f,Jump=%d", MoveX, MoveY,JumpFlag);
	printf("\nCharX=%d,CharY=%d,CameraX=%d,CameraY=%d,ViewX=%d,ViewY=%d", CharX, CharY, CameraX, CameraY, ViewCharX, ViewCharY);
	{
		int i;
		i = GetJoypadInputState(DX_INPUT_KEY_PAD1);
		EdgeInput = i & ~Input;
		Input = i;
	}
	//カメラの処理を行う
	CameraCheck(PlayerX, PlayerY);
	//移動処理
	{
		MoveX = 0.0F;
		MoveY = 0.0F;
		if ((Input&PAD_INPUT_RIGHT) != 0) {
			Dir = TRUE;
			MoveX += 5.0F;
		}
		if ((Input&PAD_INPUT_LEFT) != 0) {
			Dir = FALSE;
			MoveX -= 5.0F;
		}
		if (JumpFlag == FALSE && (EdgeInput&PAD_INPUT_1) != 0) {
			Grav = 0.5F;
			DropPower = -9.5F;
			JumpFlag = TRUE;
		}
		//落下処理
		DropPower += Grav;
		MoveY = DropPower;
		//移動量に基づいて移動する。
		CharMove(&PlayerX, &PlayerY, MoveX, MoveY, &DropPower, &Grav, &JumpFlag, CHIP_SIZE);
	}
	//マップの描画
	{
		int i, j;
		for (i = 0; i < MAP_HEIGHT; i++) {
			for (j = 0; j < MAP_WIDTH; j++) {
				if (MapData[i][j] == 1) {
					DrawBox(j*CHIP_SIZE - ViewCharX, i*CHIP_SIZE - ViewCharY, j*CHIP_SIZE + CHIP_SIZE - ViewCharX, i*CHIP_SIZE - CHIP_SIZE - ViewCharY, GetColor(255, 255, 255), TRUE);
				}
			}
		}
	}
	//キャラの描画
	DrawBox((int)(ViewCharX), (int)(ViewCharY), (int)(ViewCharX-CHIP_SIZE) + 1, (int)(ViewCharY-CHIP_SIZE) + 1, GetColor(255, 0, 0), TRUE);
}

添付ファイル
質問用.PNG
質問用.PNG (1.79 KiB) 閲覧数: 8763 回

アバター
みけCAT
記事: 6734
登録日時: 13年前
住所: 千葉県
連絡を取る:

Re: カメラを実装したら当たり判定がずれた。

#16

投稿記事 by みけCAT » 7年前

keito940 さんが書きました:

コード:

	if (CameraY == (STAGE_HEIGHT + SCREEN_HEIGHT))CameraY = (STAGE_HEIGHT + SCREEN_HEIGHT);
この行は意味が無さそう(いい影響も悪い影響も無さそう)だと思うのですが、何のためにあるのですか?
すなわち、どうしてこの行があると良さそうだと思ったのですか?
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

アバター
みけCAT
記事: 6734
登録日時: 13年前
住所: 千葉県
連絡を取る:

Re: カメラを実装したら当たり判定がずれた。

#17

投稿記事 by みけCAT » 7年前

うーむ、このコードは意図の理解が難しいですね。
keito940 さんが書きました:

コード:

	//マップの描画
	{
		int i, j;
		for (i = 0; i < MAP_HEIGHT; i++) {
			for (j = 0; j < MAP_WIDTH; j++) {
				if (MapData[i][j] == 1) {
					DrawBox(j*CHIP_SIZE - ViewCharX, i*CHIP_SIZE - ViewCharY, j*CHIP_SIZE + CHIP_SIZE - ViewCharX, i*CHIP_SIZE - CHIP_SIZE - ViewCharY, GetColor(255, 255, 255), TRUE);
				}
			}
		}
	}
どうしてCameraXやCameraYではなく、ViewCharXやViewCharYを引いているのですか?
オフトピック
完全におかしいように見えて、横のスクロールはうまく行ったと主張しているし…

やはりコードを目視するだけでなく、自分でコンパイルして動かしてみるべきかな…
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

keito940
記事: 105
登録日時: 7年前

Re: カメラを実装したら当たり判定がずれた。

#18

投稿記事 by keito940 » 7年前

みけCATさん、ご指摘ありがとうございます。コードを以下の通りにしたら治りました。

コード:

	{
		int i, j;
		for (i = 0; i < MAP_HEIGHT; i++) {
			for (j = 0; j < MAP_WIDTH; j++) {
				if (MapData[i][j] == 1) {
					DrawBox(j*CHIP_SIZE - CameraX, i*CHIP_SIZE - CameraY, j*CHIP_SIZE + CHIP_SIZE - CameraX, i*CHIP_SIZE - CHIP_SIZE - CameraY, GetColor(255, 255, 255), TRUE);
				}
			}
		}
	}
	//キャラの描画
	DrawBox((int)(ViewCharX), (int)(ViewCharY), (int)(ViewCharX-CHIP_SIZE) + 1, (int)(ViewCharY-CHIP_SIZE) + 1, GetColor(255, 0, 0), TRUE);
}
で、本題に入りたいと思います。当たり判定とキャラのカメラの位置がずれているのはどうれば直せますか?

アバター
もるも
記事: 54
登録日時: 8年前
連絡を取る:

Re: カメラを実装したら当たり判定がずれた。

#19

投稿記事 by もるも » 7年前

適切じゃない方法で混乱させてしまって申し訳ないです(;´・ω・)

http://dxlib.o.oo7.jp/program/ActionSample.cpp
多分使ってるのは↑のサンプルですよね。
それにマップスクロールを追加してみました。
ソースコードはスポイラーで閉じています。良かったら参考にしてください。
► スポイラーを表示
今回使ったマップスクロールの計算解説サイト様
http://aidiary.hatenablog.com/entry/20050624/1255786339

アバター
usao
記事: 1887
登録日時: 11年前

Re: カメラを実装したら当たり判定がずれた。

#20

投稿記事 by usao » 7年前

キャラの描画のところ

>(int)(ViewCharX-CHIP_SIZE) + 1, (int)(ViewCharY-CHIP_SIZE) + 1

+CHIP_SIZE
ではなく?

アバター
みけCAT
記事: 6734
登録日時: 13年前
住所: 千葉県
連絡を取る:

Re: カメラを実装したら当たり判定がずれた。

#21

投稿記事 by みけCAT » 7年前

usao さんが書きました:キャラの描画のところ

>(int)(ViewCharX-CHIP_SIZE) + 1, (int)(ViewCharY-CHIP_SIZE) + 1

+CHIP_SIZE
ではなく?
マップ描画に使用しているDrawBoxの第3引数(x座標)のみCHIP_SIZEを足していますが、
その他(マップ描画のy座標、自機描画のx座標とy座標)は「CHIP_SIZEを引く」で統一されていますね。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

アバター
usao
記事: 1887
登録日時: 11年前

Re: カメラを実装したら当たり判定がずれた。

#22

投稿記事 by usao » 7年前

む?
ViewCharX,ViewCharYはそもそもキャラクタの「どこ」の座標なんだ?
当たり判定の箇所を見た感じだと,真ん中?
描画時は矩形の角の点として使われているようだが…?

keito940
記事: 105
登録日時: 7年前

Re: カメラを実装したら当たり判定がずれた。

#23

投稿記事 by keito940 » 7年前

usao さんが書きました: 当たり判定の箇所を見た感じだと,真ん中?
描画時は矩形の角の点として使われているようだが…?
そうです。

なんとかキャラを画面内に合わせることができました。
コードは以下のとおりです。

コード:

int main(void) {
	FreamStartTime = GetNowCount();
	while (GetNowCount() - FreamStartTime < 1000 / 60) {}
	system("cls");
	printf("メインループ開始\n");
	printf("\nPlayerX=%d,PlayerY=%d,Grav=%8.1f,DropPower=%8.1f", (int)PlayerX, (int)PlayerY, Grav,DropPower);
	printf("\nMoveX=%8.1f,MoveY=%8.1f,Jump=%d", MoveX, MoveY,JumpFlag);
	printf("\nCharX=%d,CharY=%d,CameraX=%d,CameraY=%d,ViewX=%d,ViewY=%d", CharX, CharY, CameraX, CameraY, ViewCharX, ViewCharY);
	{
		int i;
		i = GetJoypadInputState(DX_INPUT_KEY_PAD1);
		EdgeInput = i & ~Input;
		Input = i;
	}
	//カメラの処理を行う
	CameraCheck(PlayerX, PlayerY);
	//移動処理
	{
		MoveX = 0.0F;
		MoveY = 0.0F;
		if ((Input&PAD_INPUT_RIGHT) != 0) {
			Dir = TRUE;
			MoveX += 5.0F;
		}
		if ((Input&PAD_INPUT_LEFT) != 0) {
			Dir = FALSE;
			MoveX -= 5.0F;
		}
		if (JumpFlag == FALSE && (EdgeInput&PAD_INPUT_1) != 0) {
			Grav = 0.5F;
			DropPower = -9.5F;
			JumpFlag = TRUE;
		}
		//落下処理
		DropPower += Grav;
		MoveY = DropPower;
		//移動量に基づいて移動する。
		CharMove(&PlayerX, &PlayerY, MoveX, MoveY, &DropPower, &Grav, &JumpFlag, CHIP_SIZE);
	}
	//マップの描画
	{
		int i, j;
		for (i = 0; i < MAP_HEIGHT; i++) {
			for (j = 0; j < MAP_WIDTH; j++) {
				if (MapData[i][j] == 1) {
					DrawBox(j*CHIP_SIZE - CameraX, i*CHIP_SIZE - CameraY, j*CHIP_SIZE + CHIP_SIZE - CameraX, i*CHIP_SIZE + CHIP_SIZE - CameraY, GetColor(255, 255, 255), TRUE);
				}
			}
		}
	}
	//キャラの描画
	DrawBox((int)(ViewCharX), (int)(ViewCharY), (int)(ViewCharX+CHIP_SIZE) + 1, (int)(ViewCharY+CHIP_SIZE) + 1, GetColor(255, 0, 0), TRUE);
}


keito940
記事: 105
登録日時: 7年前

Re: カメラを実装したら当たり判定がずれた。

#24

投稿記事 by keito940 » 7年前

あ…ありのままおこったことを話すぜ!コードを以下の通りにしたら、「当たり判定がずれなくなった」

コード:

int main(void) {
	FreamStartTime = GetNowCount();
	while (GetNowCount() - FreamStartTime < 1000 / 60) {}
	system("cls");
	printf("メインループ開始\n");
	printf("\nPlayerX=%d,PlayerY=%d,Grav=%8.1f,DropPower=%8.1f", (int)PlayerX, (int)PlayerY, Grav,DropPower);
	printf("\nMoveX=%8.1f,MoveY=%8.1f,Jump=%d", MoveX, MoveY,JumpFlag);
	printf("\nCharX=%8.1f,CharY=%8.1f,CameraX=%d,CameraY=%d,ViewX=%8.1f,ViewY=%8.1f", CharX, CharY, CameraX, CameraY, ViewCharX, ViewCharY);
	{
		int i;
		i = GetJoypadInputState(DX_INPUT_KEY_PAD1);
		EdgeInput = i & ~Input;
		Input = i;
	}
	//カメラの処理を行う
	CameraCheck(PlayerX, PlayerY);
	//移動処理
	{
		MoveX = 0.0F;
		MoveY = 0.0F;
		if ((Input&PAD_INPUT_RIGHT) != 0) {
			Dir = TRUE;
			MoveX += 5.0F;
		}
		if ((Input&PAD_INPUT_LEFT) != 0) {
			Dir = FALSE;
			MoveX -= 5.0F;
		}
		if (JumpFlag == FALSE && (EdgeInput&PAD_INPUT_1) != 0) {
			Grav = 0.5F;
			DropPower = -9.5F;
			JumpFlag = TRUE;
		}
		//落下処理
		DropPower += Grav;
		MoveY = DropPower;
		//移動量に基づいて移動する。
		CharMove(&PlayerX, &PlayerY, MoveX, MoveY, &DropPower, &Grav, &JumpFlag, CHIP_SIZE);
	}
	//マップの描画
	{
		int i, j;
		for (i = 0; i < MAP_HEIGHT; i++) {
			for (j = 0; j < MAP_WIDTH; j++) {
				if (MapData[i][j] == 1) {
					DrawBox(j*CHIP_SIZE - CameraX, i*CHIP_SIZE - CameraY, j*CHIP_SIZE + CHIP_SIZE - CameraX, i*CHIP_SIZE + CHIP_SIZE - CameraY, GetColor(255, 255, 255), TRUE);
				}
			}
		}
	}
	//キャラの描画
	DrawBox((int)(ViewCharX)-(CHIP_SIZE / 2), (int)(ViewCharY)-(CHIP_SIZE / 2), (int)(ViewCharX + CHIP_SIZE) - (CHIP_SIZE / 2), (int)(ViewCharY + CHIP_SIZE) - (CHIP_SIZE / 2), GetColor(255, 0, 0), TRUE);
}
何を言っているのかわからねーと思うが(ry

…というわけで解決しました。

閉鎖

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