行けない場所をつくる

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

行けない場所をつくる

#1

投稿記事 by 時雨 » 13年前

プログラミングの館を見ながら行けない場所を作っているのですが、実行してみると素通りしてしまい止まってくれません。なにかアドバイスお願いします。
分割で行っているのですが慣れないとむずかしいでしょうか?

コード:


#include "DxLib.h"
#include "Player.h"
#include "Keyboard.h"
#include "Field.h"

// このファイル内でしか使えないグローバル変数
static int m_Image[IMAGE_MAX]; //画像ハンドル
static int m_y;     //y座標
static int m_x;
static int SPD,i,j;
static int muki_flag,walk_flag;



// 初期化をする
void Player_Initialize(){
        LoadDivGraph("画像/キャラクタ10.png", 16, 4, 4, 32, 32, m_Image);
        m_y = 320;
		m_x = 160;
		SPD=1;
		FIELD_MAX_X;//600
		FIELD_MAX_Y;//448
		muki_flag=2;
		walk_flag=0;
}

// 動きを計算する

int IsAbleToGo(int i,int j,int muki_flag){//進めるかを判定
	if(muki_flag==0)//上
		if(hantei[i/32-1][j/32]==1)//進めるか判定
			return 1;//エラー
	if(muki_flag==1)//下
		if(hantei[i/32+1][j/32]==1)
			return 1;
	if(muki_flag==2)//左
		if(hantei[i/32][j/32-1]==1)
			return 1;
	if(muki_flag==3)//右
		if(hantei[i/32][j/32+1]==1)
			return 1;
	return 0;//正常

}
void Player_Calc(){


if(Keyboard_Get(KEY_INPUT_UP)>0){
	walk_flag=1;
	muki_flag=0;
	m_y-=SPD;
	if(Keyboard_Get(KEY_INPUT_LSHIFT)>=1)
	m_y-=SPD*2;
}
	
if(Keyboard_Get(KEY_INPUT_DOWN)>0){
	walk_flag=1;
	muki_flag=1;
	m_y+=SPD;
	if(Keyboard_Get(KEY_INPUT_LSHIFT)>=1)
	m_y+=SPD*2;
}

if(Keyboard_Get(KEY_INPUT_LEFT)>0){
	walk_flag=1;
	muki_flag=2;
	m_x-=SPD;
	if(Keyboard_Get(KEY_INPUT_LSHIFT)>=1)
	m_x-=SPD*2;
}	

if(Keyboard_Get(KEY_INPUT_RIGHT)>0){
	walk_flag=1;
	muki_flag=3;
	m_x+=SPD;
	if(Keyboard_Get(KEY_INPUT_LSHIFT)>=1)
	m_x+=SPD*2;

if(walk_flag==1){
	if(IsAbleToGo(m_x,m_y,muki_flag)==1)
		walk_flag=0;
}
	
}




//画面内移動補正	
if(m_x > FIELD_MAX_X) m_x = FIELD_MAX_X;//592
if(m_x < 0          ) m_x = 0;
if(m_y > FIELD_MAX_Y) m_y = FIELD_MAX_Y;//448
if(m_y < 0         )  m_y = 0;



//ワープ


}



// 描画する
void Player_Graph(){
	
	m_Image[12]=m_Image[(m_x%32)/8+12];
	m_Image[8]=m_Image[(m_y%32)/8+8];
	m_Image[0]=m_Image[(m_y%32)/8+0];
	m_Image[4]=m_Image[(m_x%32)/8+4];
if(muki_flag==0)
   DrawGraph(m_x, m_y, m_Image[0], TRUE);
else if(muki_flag==1)
	DrawGraph(m_x, m_y, m_Image[8], TRUE);
else if(muki_flag==2)
	DrawGraph(m_x, m_y, m_Image[4], TRUE);
else if(muki_flag==3)
	DrawGraph(m_x, m_y, m_Image[12], TRUE);
}

// 終了処理をする
void Player_Finalize(){
	
    DeleteGraph(m_Image[0]);
	DeleteGraph(m_Image[4]);
	DeleteGraph(m_Image[8]);
	DeleteGraph(m_Image[12]);
	}

コード:

#ifndef DEF_FIELD_H //二重include防止

#define DEF_FILD_H

#define FIELD_MAX_X 618
#define FIELD_MAX_Y 448

#define FIELD_X 32
#define FIELD_Y 16


static int hantei[15][20]={//[i=y][j=x]
{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,1},
{1,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,1},
{1,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,1,0,0,0,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1},
{1,0,0,0,0,0,0,1,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,1},
{1,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,1},
{1,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,1},
{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
};



// 初期化をする
void Field_Initialize();

// 動きを計算する
void Field_Calc();

// 描画する
void Field_Graph();

// 終了処理をする
void Field_Finalize();

#endif 

box
記事: 2002
登録日時: 15年前

Re: 行けない場所をつくる

#2

投稿記事 by box » 13年前

とりあえず、いちばん気になったところだけ。
時雨 さんが書きました:

コード:

#define FIELD_X 32
#define FIELD_Y 16
ここで書いている32とか16とかいう値(盤面の縦と横のこと?)と
時雨 さんが書きました:

コード:

static int hantei[15][20]={//[i=y][j=x]
ここで書いている15と20との意味の違いを教えてください。
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。

時雨

Re: 行けない場所をつくる

#3

投稿記事 by 時雨 » 13年前

32と16はフィールドの始点と考えてもらえばいいです。15はyの20はxの判定のための区間の個数です。

box
記事: 2002
登録日時: 15年前

Re: 行けない場所をつくる

#4

投稿記事 by box » 13年前

時雨 さんが書きました:32と16はフィールドの始点と考えてもらえばいいです。15はyの20はxの判定のための区間の個数です。
フィールドの始点というのは、何を意味するのでしょうか。
判定というのは、何を判定するのでしょうか。

FIELD_XやFIELD_Yを#defineしていますが、提示されたソースでは
全く使っていないように見えます。
どこか別のソースコードで使っているのでしょうか。
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。

conio
記事: 9
登録日時: 13年前
連絡を取る:

Re: 行けない場所をつくる

#5

投稿記事 by conio » 13年前

コード:

void Player_Calc(){ 
if(Keyboard_Get(KEY_INPUT_UP)>0){
    walk_flag=1;
    muki_flag=0;
    m_y-=SPD;
    if(Keyboard_Get(KEY_INPUT_LSHIFT)>=1)
    m_y-=SPD*2;
}
    
if(Keyboard_Get(KEY_INPUT_DOWN)>0){
    walk_flag=1;
    muki_flag=1;
    m_y+=SPD;
    if(Keyboard_Get(KEY_INPUT_LSHIFT)>=1)
    m_y+=SPD*2;
}
 
if(Keyboard_Get(KEY_INPUT_LEFT)>0){
    walk_flag=1;
    muki_flag=2;
    m_x-=SPD;
    if(Keyboard_Get(KEY_INPUT_LSHIFT)>=1)
    m_x-=SPD*2;
}   
 
if(Keyboard_Get(KEY_INPUT_RIGHT)>0){
    walk_flag=1;
    muki_flag=3;
    m_x+=SPD;
    if(Keyboard_Get(KEY_INPUT_LSHIFT)>=1)
    m_x+=SPD*2;
 
if(walk_flag==1){
    if(IsAbleToGo(m_x,m_y,muki_flag)==1)
        walk_flag=0;
}
}
上記の部分ですが、
処理の流れが以下のようになっていると思います。
-------------------------------------------------------
【1】入力を受け付ける。
【2】矢印キーであれば、walk_flagを1にする。
【3】実際の座標を動かす。
【4】IsAbleToGo関数で、エラー(1)が返ってくる
【5】walk_flagを0にする。
-------------------------------------------------------
判定とか関係なく、先に座標だけ動かしてしまっているので、
衝突しないのだと思います。

以下の流れに変えてください。
-------------------------------------------------------
【1】入力を受け付ける。
【2】移動した場合の座標を、IsAbleToGo関数に渡す。
【3】エラー(1)が返ってこなければ、walk_flagを1にする。
【4】walk_flagが1であれば、座標を動かす。
-------------------------------------------------------
大まかに以下のような感じでどうでしょう。
※実行はしてないので、エラーが出る可能性あり。

コード:

int IsAbleToGo(int x, int y){
    int result = 0;
    if(hantei[(y>>5)][(x>>5)]==1){ //渡される値が範囲外か? のチェックは省略してます。
        result = 1;
    }
    return (result);
}

void Player_Calc(){
    if(Keyboard_Get(KEY_INPUT_RIGHT)>0){ 
        muki_flag=3;    //移動出来なかったとしても、向きだけは変更する
        if(IsAbleToGo( m_x + 31 + SPD, m_y, muki_flag ) != 1){    //衝突しなければ
            walk_flag=1;
        }
    }

    if(walk_flag == 1){
        switch(muki_flag){
            case 3: m_x += SPD; break;
            defult:break;
        }
    }
}
※上記の実装方法の場合、
  変数"SPD"は、32(画像の幅)で割り切れる数にして下さい。

あと、以下のFIELD_MAX_X; FIELD_MAX_Y;の部分は要らないと思います。

コード:

void Player_Initialize(){
        LoadDivGraph("画像/キャラクタ10.png", 16, 4, 4, 32, 32, m_Image);
        m_y = 320;
        m_x = 160;
        SPD=1;
        FIELD_MAX_X;//600
        FIELD_MAX_Y;//448
        muki_flag=2;
        walk_flag=0;
}
そもそも、 FIELD_MAX_Xは618で定義されているのですが
コメントで//600と記載されているのが良く分からないです。

時雨

Re: 行けない場所をつくる

#6

投稿記事 by 時雨 » 13年前

アドバイスを参考にちょっと変えてみたのですが壁に対して手前で止まったりするのですが、どこか訂正あったらお願いします。

コード:


#include "DxLib.h"
#include "Player.h"
#include "Keyboard.h"
#include "Field.h"

// このファイル内でしか使えないグローバル変数
static int m_Image[IMAGE_MAX]; //画像ハンドル
static int m_y;     //y座標
static int m_x;
static int SPD,i,j;
static int muki_flag,walk_flag;



// 初期化をする
void Player_Initialize(){
        LoadDivGraph("画像/キャラクタ10.png", 16, 4, 4, 32, 32, m_Image);
        m_y = 320;
		m_x = 160;
		SPD=2;
		muki_flag=2;
		walk_flag=0;
}

// 動きを計算する

int IsAbleToGo(int i,int j,int muki_flag){//進めるかを判定
	if(muki_flag==0)//上
		if(hantei[i/32-1][j/32]==1)//進めるか判定
			return 1;//エラー
	if(muki_flag==1)//下
		if(hantei[i/32+1][j/32]==1)
			return 1;
	if(muki_flag==2)//左
		if(hantei[i/32][j/32-1]==1)
			return 1;
	if(muki_flag==3)//右
		if(hantei[i/32][j/32+1]==1)
			return 1;
	return 0;//正常

}
void Player_Calc(){


if(Keyboard_Get(KEY_INPUT_UP)>0){
	muki_flag=0;
	if(IsAbleToGo(m_y,m_x,muki_flag)==0)
		walk_flag=1;
	if(walk_flag==1)
		m_y-=SPD;
	if(IsAbleToGo(m_y,m_x,muki_flag)==1)
		walk_flag=0;
}
	
if(Keyboard_Get(KEY_INPUT_DOWN)>0){
	muki_flag=1;
	if(IsAbleToGo(m_y,m_x,muki_flag)==0)
		walk_flag=1;
	if(walk_flag==1)
		m_y+=SPD;
	if(IsAbleToGo(m_y,m_x,muki_flag)==1)
		walk_flag=0;
}

if(Keyboard_Get(KEY_INPUT_LEFT)>0){
	muki_flag=2;
    if(IsAbleToGo(m_y,m_x,muki_flag)==0)
		walk_flag=1;
	if(walk_flag==1)
		m_x-=SPD;
	if(IsAbleToGo(m_y,m_x,muki_flag)==1)
		walk_flag=0;	
}	

if(Keyboard_Get(KEY_INPUT_RIGHT)>0){
	muki_flag=3;
	if(IsAbleToGo(m_y,m_x,muki_flag)==0)
		walk_flag=1;
	if(walk_flag==1)
		m_x+=SPD;
	if(IsAbleToGo(m_y,m_x,muki_flag)==1)
		walk_flag=0;

}






	





//画面内移動補正	
if(m_x > FIELD_MAX_X) m_x = FIELD_MAX_X;//592
if(m_x < 0          ) m_x = 0;
if(m_y > FIELD_MAX_Y) m_y = FIELD_MAX_Y;//448
if(m_y < 0         )  m_y = 0;


}



// 描画する
void Player_Graph(){
	
	m_Image[12]=m_Image[(m_x%32)/8+12];
	m_Image[8]=m_Image[(m_y%32)/8+8];
	m_Image[0]=m_Image[(m_y%32)/8+0];
	m_Image[4]=m_Image[(m_x%32)/8+4];
if(muki_flag==0)
   DrawGraph(m_x, m_y, m_Image[0], TRUE);
else if(muki_flag==1)
	DrawGraph(m_x, m_y, m_Image[8], TRUE);
else if(muki_flag==2)
	DrawGraph(m_x, m_y, m_Image[4], TRUE);
else if(muki_flag==3)
	DrawGraph(m_x, m_y, m_Image[12], TRUE);
}

// 終了処理をする
void Player_Finalize(){
	
    DeleteGraph(m_Image[0]);
	DeleteGraph(m_Image[4]);
	DeleteGraph(m_Image[8]);
	DeleteGraph(m_Image[12]);
	}

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

Re: 行けない場所をつくる

#7

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

こちらでアドバイスしている内容を参考に当たり判定を視覚化してみてください。
「上下左右の当たり判定 • C言語交流フォーラム ~ mixC++ ~」
http://dixq.net/forum/viewtopic.php?f=3&t=10463
問題がよく分かると思います。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

ISLe
記事: 2650
登録日時: 15年前
連絡を取る:

Re: 行けない場所をつくる

#8

投稿記事 by ISLe » 13年前

『キャラの移動 • C言語交流フォーラム ~ mixC++ ~』
http://dixq.net/forum/viewtopic.php?f=3&t=10575
上のスレと同じ原因ではないですかね。

いま現在いるマップ座標を求める
→マップ座標で上下左右のマスとの距離は1
というふうにするとコードが分かりやすくなると思いますけどね。

チップの大きさに影響されなくなるので使い回しやすいコードにもなります。

閉鎖

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