画面スクロールについて

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

画面スクロールについて

#1

投稿記事 by 駄文使い » 14年前

画面スクロールについて質問します。
①使用ソフト visual stusio2010 C+ アクションプログラム
②質問 表示画面から一定以上横に離れると、画面をスクロールしたい。
③完成期限2月10日。1月25日からは毎日作業ができる環境になります。

ロジックを教えていただけないでしょうか。よろしくお願いします。
必要な情報がありましたら、追記いたします。

コード:

#define SCREEN_WIDTH     (640)                          // 画面の横幅
#define SCREEN_HEIGHT    (480)                          // 画面の縦幅
#define CHIP_SIZE        (32)                           // 一つのチップのサイズ
#define MAP_WIDTH        (SCREEN_WIDTH / CHIP_SIZE)     // マップの横幅
#define MAP_HEIGHT       (SCREEN_HEIGHT / CHIP_SIZE)    // マップの縦幅
// マップデータ
char MapData[MAP_HEIGHT][MAP_WIDTH] =
{
    0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0,
    1,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1,
    1,0,0,1,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1,
    1,0,0,1,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,1,0,1,
    1,0,0,1,1, 1,1,0,0,0, 0,0,0,0,0, 0,0,1,0,1,

    1,0,0,0,0, 0,0,0,2,2, 0,0,0,0,0, 0,0,2,0,1,
    1,0,0,0,0, 0,0,0,0,0, 0,0,2,2,0, 0,0,2,0,0,
    1,0,0,0,0, 0,0,0,0,2, 2,0,0,0,0, 0,0,2,0,0,
    1,0,0,0,0, 0,0,0,0,2, 3,0,0,0,0, 0,0,0,0,1,
    1,0,0,0,0, 0,0,0,0,2, 0,0,0,0,0, 2,0,0,0,1,

    1,0,0,0,0, 0,0,0,0,2, 0,0,0,0,2, 0,0,0,0,1,
    1,0,0,0,0, 1,0,0,0,2, 0,0,0,0,2, 0,0,0,2,1,
    3,0,0,0,0, 0,0,0,0,0, 0,0,0,0,2, 1,0,0,0,1,
    3,0,0,0,0, 0,0,0,0,0, 0,0,0,0,2, 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,
} ;

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

Re: 画面スクロールについて

#2

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

DXライブラリを使って良いのでしょうか?
そもそも、前に作っていたのはどうなりました?

あとマップデータが横画面よりある程度大きくないとスクロール出来ませんよ。

ロジックとしては、色々有りますが案の一つとして聞いてください。
キャラクタの座標とマップ表示座標の差分で画面内の相対位置を求めて、右寄りか左寄りならマップの表示位置をづらします。
コードを作るのは、もちろん駄文使いさんです。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

駄文使い
記事: 7
登録日時: 14年前
住所: 福岡

Re: 画面スクロールについて

#3

投稿記事 by 駄文使い » 14年前

回答ありがとうございます。
以前作っていたものをスクロールさせるものになります。
追記にてDXライブラリ使用について書かせていただきます。

コードに関してはもちろんです。

アバター
ookami
記事: 214
登録日時: 15年前
住所: 東京都

Re: 画面スクロールについて

#4

投稿記事 by ookami » 14年前

横からすいません。

> ①使用ソフト visual stusio2010 C+ アクションプログラム
> ②質問 表示画面から一定以上横に離れると、画面をスクロールしたい。
> ③完成期限2月10日。1月25日からは毎日作業ができる環境になります。

とのことですが、
①「visual stusio2010 C+」 は 「visual studio2010 C++」のタイプミスとして、「アクションプログラム」とはどんなものですか?
②現状ではどこまでできていますか?
③完成期限というのは、ゲーム全体の期限ですか?それとも、このスクロール機能の期限ですか?

駄文使い
記事: 7
登録日時: 14年前
住所: 福岡

Re: 画面スクロールについて

#5

投稿記事 by 駄文使い » 14年前

インフルエンザにかかってしまい、連絡が遅れてしまいました。
申し訳ございません。
ookamiさん、返信ありがとうございます。
②現状ではどこまでできているのか。
 現在は敵をチップ表示ではなく、ファイルから座標位置を読み込み画面描写するという事。
 キャラクタから上記敵に攻撃を指定回数当てることにより、敵を消滅つまり倒す処理完了。
 キャラクタのテクスチャの問題等若干の不具合を残し、ステージを描く為の画面スクロールだけとなっております。
③全体の完成期限として2月15日を提示されております。

①タイプミスの意味がわかりかねますが、打ちミスということでしょうか。
質問されて気づきましたが、+が一つ足りてませんでした。ありがとうございます。

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

Re: 画面スクロールについて

#6

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

普通アクションと言うと
・複数のステージ
・タイトル画面・エンディング画面
・オプション設定
・スコアの表示
・敵の移動や敵の攻撃アクションとかを含めた簡単なAI。
・ステージの仕掛け
・ボスの存在
などが考えられますが、全てなしですか?
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

駄文使い
記事: 7
登録日時: 14年前
住所: 福岡

Re: 画面スクロールについて

#7

投稿記事 by 駄文使い » 14年前

・複数のステージ→1ステージのみとなっております。
・タイトル画面・エンディング画面→タイトル画面とゲームオーバ画面のみ完成しております。エンディング画面については恥ずかしながら、質問されて、作ることを忘れていたことに気づかされました。私個人がですが。
・ボスの存在に関しては、まだ作っておりません。

以下の項目については現時点で検討しておりません。敵の移動に関して完成しております。
・オプション設定
・スコアの表示
・敵の攻撃アクションとかを含めた簡単なAI。
・ステージの仕掛け

アバター
ookami
記事: 214
登録日時: 15年前
住所: 東京都

Re: 画面スクロールについて

#8

投稿記事 by ookami » 14年前

インフルエンザお大事にm(_ _)m

> ②現状ではどこまでできているのか。
>  現在は敵をチップ表示ではなく、ファイルから座標位置を読み込み画面描写するという事。
>  キャラクタから上記敵に攻撃を指定回数当てることにより、敵を消滅つまり倒す処理完了。
>  キャラクタのテクスチャの問題等若干の不具合を残し、ステージを描く為の画面スクロールだけとなっております。

すいません、良く分からない表現があるので、詳しく説明していただけませんか。
どこまでできているのか分からないと、アドバイスのしようがありません。
・「チップ表示」
・「ファイルから座標位置を読み込み画面描写」 ← 敵は動かない...?
・「ステージを描く為の画面スクロール」 ← ステージを描くために、画面スクロール...?よく分かりません。

それとも、「カメラ座標で全ての座標を減算すればよい」で伝わりますか?

> ③全体の完成期限として2月15日を提示されております。
2/10が2/15に変わってますが、どっちでしょうか。

ラプター

Re: 画面スクロールについて

#9

投稿記事 by ラプター » 14年前

横から失礼します。駄文使いと一緒にゲーム制作をしているメンバーのラプターと申しますよろしく願いします。
私の担当はマップ画面のスクロールの部分を担当しています。
質問に答えさせていただきます。

>アクションプログラムについて
メタルスラッグのような横スクロールシューティングゲームを制作しています。
キャラ移動や弾丸の発射などは出来ています。

>・「チップ表示」
これはマップチップのことだと思います。ステージを32×32のサイズの画像を使って壁の部分などを表示しているので
そのことを言いたかったのではないかと思います。

>・「ファイルから座標位置を読み込み画面描写」 ← 敵は動かない...?
敵は動くのですがプレイヤーキャラとはまた別に動きを作っているため敵を増やすためには
毎回その部分を追加しなければいけないというふうになっております

>・「ステージを描く為の画面スクロール」
過去のスレッドのほうを参考にカメラ座標を使っての画面のスクロールの作っていますがうまくいっていない状態です。
キャラクターが画面中央付近まできたらキャラクターは中央付近で固定し
右にスクロールするようにしてマップの端まで来たら右端に行くようにしたいと考えています。
後左に行った場合はマップはスクロールせずに画面外にも行けないようにしたいと思っています。
マップ画像のスクロールは出来るのですが当たり判定が移動しないのでその部分を教えていただけますでしょうか?
後ソース全体かなり長くなってしまっているので短くしたいと思っているのですが省ける部分はありますでしょうか?
ソースを全文貼りますので見ていただけると幸いです

>2/10が2/15に変わってますが、どっちでしょうか。
どちらも間違いで正確には「2月11日」となっております。混乱させて申し訳ないです。

よろしくお願い致しますm(_ _)m

コード:


#include "DxLib.h"

#define SCREEN_WIDTH     (640)                          // 画面の横幅
#define SCREEN_HEIGHT    (480)                          // 画面の縦幅
#define CHIP_SIZE        (32)                           // 一つのチップのサイズ
#define MAP_WIDTH        (1920 / CHIP_SIZE)     // マップの横幅
#define MAP_HEIGHT       (SCREEN_HEIGHT / CHIP_SIZE)    // マップの縦幅

#define G                (0.3F)                         // キャラに掛かる重力加速度
#define JUMP_POWER       (9.0F)                         // キャラのジャンプ力
#define SPEED            (2.0F)                         // キャラの移動スピード
#define CHAR_SIZE        (60)                           // プレイヤーのサイズ

typedef struct{
        int img,muki;
}ch_t;

struct shot{
    int x2,y2;  //座標
    int flag;
};

// マップデータ
char MapData[MAP_HEIGHT][MAP_WIDTH] =
{
    0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0,
    1,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1,
    1,0,0,1,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,1,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,1,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,1,
    1,0,0,1,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,1,0,0, 0,0,0,1,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,1,0,0, 0,0,0,1,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,1,0,1,
    1,0,0,1,1, 1,1,0,0,0, 0,0,0,0,0, 0,0,1,0,0, 0,0,0,1,1, 1,1,0,0,0, 0,0,0,0,0, 0,0,1,0,0, 0,0,0,1,1, 1,1,0,0,0, 0,0,0,0,0, 0,0,1,0,1,

    1,0,0,0,0, 0,0,0,1,1, 0,0,0,0,0, 0,0,1,0,0, 0,0,0,0,0, 0,0,0,1,1, 0,0,0,0,0, 0,0,1,0,0, 1,0,0,0,0, 0,0,0,1,1, 0,0,0,0,0, 0,0,1,0,1,
    1,0,0,0,0, 0,0,0,0,0, 0,0,1,1,0, 0,0,1,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,1,1,0, 0,0,1,0,0, 1,0,0,0,0, 0,0,0,0,0, 0,0,1,1,0, 0,0,1,0,1,
    1,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,1,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,1,0,0, 1,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,1,0,1,
    1,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 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,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,1,

    1,0,0,0,0, 1,1,1,1,1, 0,0,0,0,1, 1,0,0,0,0, 0,0,0,0,0, 1,1,1,1,1, 0,0,0,0,1, 1,0,0,0,0, 0,0,0,0,0, 1,1,1,1,1, 0,0,0,0,1, 1,0,0,0,1,
    1,1,1,0,0, 1,1,1,1,1, 0,0,0,1,1, 1,0,0,0,0, 0,1,1,0,0, 1,1,1,1,1, 0,0,0,1,1, 1,0,0,0,0, 0,1,1,0,0, 1,1,1,1,1, 0,0,0,1,1, 1,0,0,0,1, 
    1,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,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, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,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,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1,
} ;

float PlX, PlY ;            // プレイヤーの座標(中心座標)
float ElX, ElY ;
float PlDownSp ;            // プレイヤーの落下速度
float ElDownSp ;
char PlJumpFlag ;           // プレイヤーがジャンプ中か、のフラグ
char walking_flag ;

int Input, EdgeInput ;      // 入力状態
int FrameStartTime ;        // 60FPS固定用、時間保存用変数
int camerax=0,cameray=0;    //カメラ

// マップチップの値を取得する関数
int GetChipParam( float X, float Y ) ;

// キャラクタをマップとの当たり判定を考慮しながら移動する関数
int CharMove( float *X, float *Y, float *DownSP,
                    float MoveX, float MoveY, float Size, char *JumpFlag ) ;

// アクションサンプルプログラムメイン関数
int ActMain( void ) ;

// マップとの当たり判定( 戻り値 0:当たらなかった  1:左辺に当たった  2:右辺に当たった
//                                                3:上辺に当たった  4:下辺に当たった
int MapHitCheck( float X, float Y, float *MoveX, float *MoveY ) ;

// WinMain関数
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    LPSTR lpCmdLine, int nCmdShow )
{
    //ChangeWindowMode( TRUE ) ;

	if( DxLib_Init() == -1 )	// DXライブラリ初期化処理
	{
		 return -1;				// エラーが起きたら直ちに終了
	}

    // アクションゲームのメイン関数を呼ぶ
    ActMain() ;

    // DXライブラリの後始末
    DxLib_End() ;

    // 終了
    return 0 ;
}

// アクションプログラムメイン
int ActMain( void )
{
	ch_t ch;
	int Color;
	Color=GetColor(255,255,255);
	int image[16],image2[16],image1[1],image3[1],image4[1];
	char Key[256];
	int i=0,counter=0,tmuki=2;
	struct shot tama[10];

	int HP=5,emo=1;

	if( DX_CHANGESCREEN_OK || DxLib_Init() == -1 ) return -1;

		for(i=0;i<10;i++){                  //初期化処理
                tama[i].x2=(int)PlX; tama[i].y2=(int)PlY; //座標代入
                tama[i].flag=0;                 //飛んでいない事を示すフラグ=0
		}


    // 描画先を裏画面にセット
    SetDrawScreen( DX_SCREEN_BACK ) ;

	walking_flag=FALSE;
	ch.muki=2;
	LoadDivGraph( "chara.png" , 16 , 4 , 4 , 60 , 60 , image );
	LoadDivGraph( "Mesh.bmp" , 1 , 1 , 1 , 32, 32 , image1);
	LoadDivGraph( "hg.png" , 16 , 4 , 4 , 32, 32 , image2);
	LoadDivGraph( "blo.png" , 1 , 1 , 1 , 32, 32 , image3);
	LoadDivGraph( "sima.png" , 1 , 1 , 1 , 32, 32 , image4);

    // 垂直同期信号を待たない
    SetWaitVSyncFlag( FALSE ) ;

    // プレイヤーの座標を初期化
    PlX = 320.0F ;        PlY = 240.0F ;
	ElX = 300.0F ;        ElY = 410.0F ;

    // プレイヤーの落下速度を初期化
    PlDownSp = 0.0F ;
	ElDownSp = 0.0F ;

    // ジャンプ中フラグを倒す
    PlJumpFlag = FALSE ;

    // 入力状態の初期化
    Input = 0 ;
    EdgeInput = 0 ;

    // 60FPS固定用、時間保存用変数を現在のカウント値にセット
    FrameStartTime = GetNowCount() ;

    // メインループ開始、ESCキーで外に出る
    while( ProcessMessage() == 0 && !ClearDrawScreen() && CheckHitKey( KEY_INPUT_ESCAPE ) == 0 && !GetHitKeyStateAll( Key ))
    {
			DrawFormatString(0,0,Color,"ch.muki=%d",ch.muki);
			DrawFormatString(100,0,Color,"tama.muki=%d",tmuki);

        // 1/60秒立つまで待つ
        while( GetNowCount() - FrameStartTime < 1000 / 60 ){}

        // 現在のカウント値を保存
        FrameStartTime = GetNowCount() ;

		if( (int)PlX%1==0 &&  (int)PlY%1==0){         //座標が1で割り切れたら入力可能
			walking_flag=FALSE;
            if     ( CheckHitKey( KEY_INPUT_UP   )  == 1 )  //上ボタンが押されたら
                    ch.muki=0;         //上向きフラグを立てる
            else if( CheckHitKey( KEY_INPUT_LEFT  )  == 1 )  //左ボタンが押されたら
                    ch.muki=1;         //左向きフラグを立てる
            else if( CheckHitKey( KEY_INPUT_RIGHT  )  == 1 )  //右ボタンが押されたら
                    ch.muki=2;         //右向きフラグを立てる
			else walking_flag=TRUE;
        }

        // プレイヤーの移動処理
        {
            float MoveX, MoveY ;

            // 移動量の初期化
            MoveX = 0.0F ;
            MoveY = 0.0F ;

            // 左右の移動を見る
			if(walking_flag==FALSE){
            if( Key[ KEY_INPUT_LEFT   ] == 1 ) MoveX -= SPEED ; 
			if( Key[ KEY_INPUT_RIGHT  ] == 1 ){
				if(camerax>350)
					MoveX;
				else
					MoveX += SPEED ; 
				}
			}

            // 地に足が着いている場合のみジャンプボタン(ボタン1 or Zキー)を見る
            if( PlJumpFlag == FALSE && Key[ KEY_INPUT_SPACE ] == 1 )
            {
                PlDownSp = -JUMP_POWER ;
                PlJumpFlag = TRUE ;
            }

            // 落下処理
            PlDownSp += G ;

            // 落下速度を移動量に加える
            MoveY = PlDownSp ;

            // 移動量に基づいてキャラクタの座標を移動
            CharMove( &PlX, &PlY, &PlDownSp, MoveX, MoveY, CHAR_SIZE, &PlJumpFlag ) ;
        }
		{
                if(counter<5)                        //前にzを押してから5カウント未満なら
                        counter++;                       //カウントアップ
                else if( Key[ KEY_INPUT_Z ]  == 1 ){//5カウント以上たってい
                        counter=0;                       //カウンターを戻す
						tmuki=ch.muki;
                        for(i=0;i<10;i++){             
                                if(tama[i].flag==0){     //発射していない玉を探し、
                                        tama[i].flag=1;  //発射フラグを立てる
										tama[i].x2=(int)PlX;
										tama[i].y2=(int)PlY;
                                        break;
                                }
                        }
                }
				
				if(tmuki==2){
                for(i=0;i<10;i++){
                        if(tama[i].flag==1){              //発射している玉なら
                                tama[i].x2+=8;
								DrawGraph( tama[i].x2 , tama[i].y2 , image2[15] , TRUE );//玉を描画
                                if(tama[i].x2 > 640){      //もし画面外まで来たら
                                        tama[i].x2=(int)PlX;    //初期値に戻し、
										tama[i].y2=(int)PlY;
                                        tama[i].flag=0;   //発射フラグを戻す
                                }
								if(tama[i].x2 < ElX+12 && tama[i].x2 > ElX-12 && 
									tama[i].y2 < ElY+12 && tama[i].y2 > ElY-12 && HP>0){
									tama[i].x2=(int)PlX;
									tama[i].y2=(int)PlY;
									tama[i].flag=0;
									HP--;
								}
						}
                }
				}
				if(tmuki==1){
                for(i=0;i<10;i++){
                        if(tama[i].flag==1){              //発射している玉なら
                                tama[i].x2-=8;
								DrawGraph( tama[i].x2-30 , tama[i].y2 , image2[6] , TRUE );//玉を描画
                                if(tama[i].x2 < 0){      //もし画面外まで来たら
                                        tama[i].x2=(int)PlX;    //初期値に戻し、
										tama[i].y2=(int)PlY;
                                        tama[i].flag=0;   //発射フラグを戻す
                                }
								if(tama[i].x2-30 < ElX+12 && tama[i].x2-30 > ElX-12 && 
									tama[i].y2 < ElY+12 && tama[i].y2 > ElY-12 && HP>0){
									tama[i].x2=(int)PlX;
									tama[i].y2=(int)PlY;
									tama[i].flag=0;
									HP--;
								}
                        }
                }
				}
				if(tmuki==0){
                for(i=0;i<10;i++){
                        if(tama[i].flag==1){              //発射している玉なら
                                tama[i].y2-=8;
								DrawGraph( tama[i].x2 , tama[i].y2 , image2[2] , TRUE );//玉を描画
                                if(tama[i].y2 > 480){      //もし画面外まで来たら
                                        tama[i].x2=(int)PlX;    //初期値に戻し、
										tama[i].y2=(int)PlY;
                                        tama[i].flag=0;   //発射フラグを戻す
                                }
								if(tama[i].x2 < ElX+12 && tama[i].x2 > ElX-12 && 
									tama[i].y2 < ElY+12 && tama[i].y2 > ElY-12 && HP>0){
									tama[i].x2=(int)PlX;
									tama[i].y2=(int)PlY;
									tama[i].flag=0;
									HP--;
								}
                        }
                }
				}
		}

		camerax=(int)PlX;
		if(camerax<0) camerax=0;
		if(camerax>1920) camerax=1920;

        // マップの描画
        {
            int i, j ;

            for( i = 0 ; i < MAP_HEIGHT ; i ++ )
            {
                for( j = 0 ; j < MAP_WIDTH ; j ++ )
                {
                    // 1は当たり判定チップを表しているので1のところだけ描画
                    if( MapData[i][j] == 1 )
                    {
						if(camerax>350){
							DrawGraph( (int)(j * CHIP_SIZE )-camerax  , (int) (i * CHIP_SIZE ) , image1[0]  , TRUE ) ;
						}
						else
							DrawGraph( (int)(j * CHIP_SIZE )  , (int) (i * CHIP_SIZE ) , image1[0]  , TRUE ) ;
                    }
                }
            }
        }
		if(ch.muki==2)
		ch.img=image[( (int)PlX%32)/8];
		if(ch.muki==1)
		ch.img=image[( (int)PlX%32)/8+4];

        // キャラクタの描画
		DrawGraph( (int) (PlX - CHAR_SIZE * 0.5F)  , (int) (PlY - CHAR_SIZE * 0.5F) , ch.img  , TRUE ) ; 

		{
			if(emo==1)
				ElX--;
			if(emo==0)
				ElX++;
			if(ElX==400)
				emo=1;
			if(ElX==50)
				emo=0;
		}

		if(HP>0)
		DrawGraph( (int) ElX , (int) ElY , image4[0]  , TRUE ) ;

		if(PlX>ElX-10 && PlX<ElX+10 && PlY>ElY-10 && PlY<ElY+10 && HP>0)
			DxLib_End() ;

        // 画面の更新
        ScreenFlip() ;
    }

    // 終了
    return 0 ;
}

// キャラクタをマップとの当たり判定を考慮しながら移動する
int CharMove( float *X, float *Y, float *DownSP,
                    float MoveX, float MoveY, float Size, char *JumpFlag )
{
    float Dummy = 0.0F ;
    float hsize ;

    // キャラクタの左上、右上、左下、右下部分が当たり判定のある
    // マップに衝突しているか調べ、衝突していたら補正する

    // 半分のサイズを算出
    hsize = Size * 0.5F ;

    // 先ず上下移動成分だけでチェック
    {
        // 左下のチェック、もしブロックの上辺に着いていたら落下を止める
        if( MapHitCheck( *X - hsize, *Y + hsize, &Dummy, &MoveY ) == 3 ) *DownSP = 0.0F ;

        // 右下のチェック、もしブロックの上辺に着いていたら落下を止める
        if( MapHitCheck( *X + hsize, *Y + hsize, &Dummy, &MoveY ) == 3 ) *DownSP = 0.0F ;

        // 左上のチェック、もしブロックの下辺に当たっていたら落下させる
        if( MapHitCheck( *X - hsize, *Y - hsize, &Dummy, &MoveY ) == 4 ) *DownSP *= -1.0F ;

        // 右上のチェック、もしブロックの下辺に当たっていたら落下させる
        if( MapHitCheck( *X + hsize, *Y - hsize, &Dummy, &MoveY ) == 4 ) *DownSP *= -1.0F ;

		if( MapHitCheck( *X , *Y + hsize, &Dummy, &MoveY ) == 3 ) *DownSP = 0.0F ;

        // 上下移動成分を加算
        *Y += MoveY ;
    }

    // 後に左右移動成分だけでチェック
    {
        // 左下のチェック
        MapHitCheck( *X - hsize, *Y + hsize, &MoveX, &Dummy ) ;

        // 右下のチェック
        MapHitCheck( *X + hsize, *Y + hsize, &MoveX, &Dummy ) ;

        // 左上のチェック
        MapHitCheck( *X - hsize, *Y - hsize, &MoveX, &Dummy ) ;

        // 右上のチェック
        MapHitCheck( *X + hsize, *Y - hsize, &MoveX, &Dummy ) ;

        // 左右移動成分を加算
        *X += MoveX ;
    }

    // 接地判定
    {
        // キャラクタの左下と右下の下に地面があるか調べる
        if( GetChipParam( *X - Size * 0.5F, *Y + Size * 0.5F + 1.0F ) == 0 && 
            GetChipParam( *X + Size * 0.5F, *Y + Size * 0.5F + 1.0F ) == 0 )
        {
            // 足場が無かったらジャンプ中にする
            *JumpFlag = TRUE ;
        }
        else
        {
            // 足場が在ったら接地中にする
            *JumpFlag = FALSE ;
        }
    }

    // 終了
    return 0 ;
}

// マップとの当たり判定( 戻り値 0:当たらなかった  1:左辺に当たった  2:右辺に当たった
//                                                3:上辺に当たった  4:下辺に当たった
// 注意:MoveX と MoveY 、どっちか片方が0じゃないとまともに動作しません(爆)
int MapHitCheck( float X, float Y,
                    float *MoveX, float *MoveY )
{
    float afX, afY ;

    // 移動量を足す
    afX = X + *MoveX ;
    afY = Y + *MoveY ;

    // 当たり判定のあるブロックに当たっているかチェック
    if( GetChipParam( afX, afY ) != 0 )
    {
        float blx, bty, brx, bby ;

        // 当たっていたら壁から離す処理を行う

        // ブロックの上下左右の座標を算出
        blx = (float)( (int)afX / CHIP_SIZE ) * CHIP_SIZE ;        // 左辺の X 座標
        brx = (float)( (int)afX / CHIP_SIZE + 1 ) * CHIP_SIZE ;    // 右辺の X 座標

        bty = (float)( (int)afY / CHIP_SIZE ) * CHIP_SIZE ;        // 上辺の Y 座標
        bby = (float)( (int)afY / CHIP_SIZE + 1 ) * CHIP_SIZE ;    // 下辺の Y 座標

        // 上辺に当たっていた場合
        if( *MoveY > 0.0F )
        {
            // 移動量を補正する
            *MoveY = bty - Y - 1.0F  ;

            // 上辺に当たったと返す
            return 3 ;
        }

        // 下辺に当たっていた場合
        if( *MoveY < 0.0F )
        {
            // 移動量を補正する
            *MoveY = bby - Y + 1.0F ;

            // 下辺に当たったと返す
            return 4 ;
        }

        // 左辺に当たっていた場合
        if( *MoveX > 0.0F )
        {
            // 移動量を補正する
            *MoveX = blx - X - 1.0F ;

            // 左辺に当たったと返す
            return 1 ;
        }

        // 右辺に当たっていた場合
        if( *MoveX < 0.0F )
        {
            // 移動量を補正する
            *MoveX = brx - X + 1.0F ;

            // 右辺に当たったと返す
            return 2 ;
        }

        // ここに来たら適当な値を返す
        return 4 ;
    }

    // どこにも当たらなかったと返す
    return 0 ;
}

// マップチップの値を取得する関数
int GetChipParam( float X, float Y )
{
    int x, y ;

    // 整数値へ変換
    x = (int)X / CHIP_SIZE ;
    y = (int)Y / CHIP_SIZE ;

    // マップからはみ出ていたら 0 を返す
    if( x >= MAP_WIDTH || y >= MAP_HEIGHT || x < 0 || y < 0 ) return 0 ;

    // 指定の座標に該当するマップの情報を返す
    return MapData[ y ][ x ] ;
}


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

Re: 画面スクロールについて

#10

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

ざっと概念だけを説明するとキャラクタ(自分や敵)のマップ上の座標と表示する画面内の座標は別にもちます。
まず自分のキャラクタの位置が画面中心になる様にマップの表示位置を決めます。
この時に決めた座標でマップ表示マップからはみ出すようなら表示位置を補正します。
マップの表示座標が決まったら、それとの相対位置を計算して画面内の自分・敵キャラの表示位置を計算して表示ます。
って感じですが分かりますか?
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

ラプター

Re: 画面スクロールについて

#11

投稿記事 by ラプター » 14年前

ご返信ありがとうございます。

>まず自分のキャラクタの位置が画面中心になる様にマップの表示位置を決めます。
>この時に決めた座標でマップ表示マップからはみ出すようなら表示位置を補正します。
>マップの表示座標が決まったら、それとの相対位置を計算して画面内の自分・敵キャラの表示位置を計算して表示ます。
>って感じですが分かりますか?

はい、なんとなくですがわかりました。
ということは今の自分のコードの状態だとマップ上の座標で表示するのではなく
画面内の座標のみで表示しているからうまくスクロールが出来てないということでいいのでしょうか?

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

Re: 画面スクロールについて

#12

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

ラプター さんが書きました:ご返信ありがとうございます。

>まず自分のキャラクタの位置が画面中心になる様にマップの表示位置を決めます。
>この時に決めた座標でマップ表示マップからはみ出すようなら表示位置を補正します。
>マップの表示座標が決まったら、それとの相対位置を計算して画面内の自分・敵キャラの表示位置を計算して表示ます。
>って感じですが分かりますか?

はい、なんとなくですがわかりました。
ということは今の自分のコードの状態だとマップ上の座標で表示するのではなく
画面内の座標のみで表示しているからうまくスクロールが出来てないということでいいのでしょうか?
どっちでも出来るのですが、作る側としてどちらが簡単かで決めてください。
画面内位置で管理するなら、自分のキャラクタがスクロールのポイントを超えたら順方向へマップ、逆方向へ自分、敵座標を移動します。
この時マップ座標がマップデータを超えるようならマップ、自分、敵の移動をキャンセルします。
あと画面座標とマップデータの座標が食い違うのでマップの地形判定をするときには、実際のマップデータの座標に変換してから行って下さい。
その代わり画面外に出たことを判定するのは、この方が楽です。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

ラプター

Re: 画面スクロールについて

#13

投稿記事 by ラプター » 14年前

softya(ソフト屋) さんが書きました: どっちでも出来るのですが、作る側としてどちらが簡単かで決めてください。
画面内位置で管理するなら、自分のキャラクタがスクロールのポイントを超えたら順方向へマップ、逆方向へ自分、敵座標を移動します。
この時マップ座標がマップデータを超えるようならマップ、自分、敵の移動をキャンセルします。
あと画面座標とマップデータの座標が食い違うのでマップの地形判定をするときには、実際のマップデータの座標に変換してから行って下さい。
その代わり画面外に出たことを判定するのは、この方が楽です。
丁寧なご説明ありがとうございます。

画面内位置で管理したいと思います。
ですがそういった処理をどこを変更したり追加したらいいのかわかりません。

何かヒントをいただけるといいのですがダメでしょうか?

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

Re: 画面スクロールについて

#14

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

ラプター さんが書きました:
softya(ソフト屋) さんが書きました: どっちでも出来るのですが、作る側としてどちらが簡単かで決めてください。
画面内位置で管理するなら、自分のキャラクタがスクロールのポイントを超えたら順方向へマップ、逆方向へ自分、敵座標を移動します。
この時マップ座標がマップデータを超えるようならマップ、自分、敵の移動をキャンセルします。
あと画面座標とマップデータの座標が食い違うのでマップの地形判定をするときには、実際のマップデータの座標に変換してから行って下さい。
その代わり画面外に出たことを判定するのは、この方が楽です。
丁寧なご説明ありがとうございます。

画面内位置で管理したいと思います。
ですがそういった処理をどこを変更したり追加したらいいのかわかりません。

何かヒントをいただけるといいのですがダメでしょうか?
このスクロール処理を入れるなら、自キャラの移動後で弾や敵キャラの移動前、自キャラの描画前の条件を満たせるコードの部分が良いと思います。
※ 細かいところはコメントが少ないので把握しきれたないことをお断りしておきます。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

ラプター

Re: 画面スクロールについて

#15

投稿記事 by ラプター » 14年前

softya(ソフト屋) さんが書きました: このスクロール処理を入れるなら、自キャラの移動後で弾や敵キャラの移動前、自キャラの描画前の条件を満たせるコードの部分が良いと思います。
※ 細かいところはコメントが少ないので把握しきれたないことをお断りしておきます。
言葉足らずで申し訳ないです・・・。
教えてもらったとおり大体スクロールの文を入れようと思う位置は決めたのですが
マップ自体のスクロールのやり方がわかりません・・・MAP_WIDTHを使えばいいのかと思ってやってみようとしましたがエラーでダメでした。
順方向へのマップの移動の仕方を教えてもらえないでしょうか?
後移動のキャンセルというのはIF文を使って分岐させればいいのでしょうか?

よろしくお願いします。m(_ _)m

コード:

    while( ProcessMessage() == 0 && !ClearDrawScreen() && CheckHitKey( KEY_INPUT_ESCAPE ) == 0 && !GetHitKeyStateAll( Key ))
    {
			DrawFormatString(0,0,Color,"ch.muki=%d",ch.muki);
			DrawFormatString(100,0,Color,"tama.muki=%d",tmuki);

        // 1/60秒立つまで待つ
        while( GetNowCount() - FrameStartTime < 1000 / 60 ){}

        // 現在のカウント値を保存
        FrameStartTime = GetNowCount() ;

		if( (int)PlX%1==0 &&  (int)PlY%1==0){         //座標が1で割り切れたら入力可能
			walking_flag=FALSE;
            if     ( CheckHitKey( KEY_INPUT_UP   )  == 1 )  //上ボタンが押されたら
                    ch.muki=0;         //上向きフラグを立てる
            else if( CheckHitKey( KEY_INPUT_LEFT  )  == 1 )  //左ボタンが押されたら
                    ch.muki=1;         //左向きフラグを立てる
            else if( CheckHitKey( KEY_INPUT_RIGHT  )  == 1 )  //右ボタンが押されたら
                    ch.muki=2;         //右向きフラグを立てる
			else walking_flag=TRUE;
        }
		
        // プレイヤーの移動処理
        {
            float MoveX, MoveY ;

            // 移動量の初期化
            MoveX = 0.0F ;
            MoveY = 0.0F ;

            // 左右の移動を見る
			if(walking_flag==FALSE){
            if( Key[ KEY_INPUT_LEFT   ] == 1 ) MoveX -= SPEED ; 
			if( Key[ KEY_INPUT_RIGHT  ] == 1 ) MoveX += SPEED ; 
			}

            // 地に足が着いている場合のみジャンプボタン(ボタン1 or Zキー)を見る
            if( PlJumpFlag == FALSE && Key[ KEY_INPUT_SPACE ] == 1 )
            {
                PlDownSp = -JUMP_POWER ;
                PlJumpFlag = TRUE ;
            }

            // 落下処理
            PlDownSp += G ;

            // 落下速度を移動量に加える
            MoveY = PlDownSp ;

            // 移動量に基づいてキャラクタの座標を移動
            CharMove( &PlX, &PlY, &PlDownSp, MoveX, MoveY, CHAR_SIZE, &PlJumpFlag ) ;
        }

		//画面スクロール
		→ここに書く予定
			


		// キャラクタの描画
		if(ch.muki==2)
		ch.img=image[( (int)PlX%32)/8];
		if(ch.muki==1)
		ch.img=image[( (int)PlX%32)/8+4];

        DrawGraph( (int) (PlX - CHAR_SIZE * 0.5F)  , (int) (PlY - CHAR_SIZE * 0.5F) , ch.img  , TRUE ) ; 

		{
                if(counter<5)                        //前にzを押してから5カウント未満なら
                        counter++;                       //カウントアップ
                else if( Key[ KEY_INPUT_Z ]  == 1 ){//5カウント以上たってい
                        counter=0;                       //カウンターを戻す
						tmuki=ch.muki;
                        for(i=0;i<10;i++){             
                                if(tama[i].flag==0){     //発射していない玉を探し、
                                        tama[i].flag=1;  //発射フラグを立てる
										tama[i].x2=(int)PlX;
										tama[i].y2=(int)PlY;
                                        break;
                                }
                        }
                }
				
			if(tmuki==2){
                for(i=0;i<10;i++){
                        if(tama[i].flag==1){              //発射している玉なら
                                tama[i].x2+=8;
								DrawGraph( tama[i].x2 , tama[i].y2 , image2[15] , TRUE );//玉を描画
                                if(tama[i].x2 > 640){      //もし画面外まで来たら
                                        tama[i].x2=(int)PlX;    //初期値に戻し、
										tama[i].y2=(int)PlY;
                                        tama[i].flag=0;   //発射フラグを戻す
                                }
								if(tama[i].x2 < ElX+12 && tama[i].x2 > ElX-12 && 
									tama[i].y2 < ElY+12 && tama[i].y2 > ElY-12 && HP>0){
									tama[i].x2=(int)PlX;
									tama[i].y2=(int)PlY;
									tama[i].flag=0;
									HP--;
								}
						}
                }
			}
			if(tmuki==1){
                for(i=0;i<10;i++){
                        if(tama[i].flag==1){              //発射している玉なら
                                tama[i].x2-=8;
								DrawGraph( tama[i].x2-30 , tama[i].y2 , image2[6] , TRUE );//玉を描画
                                if(tama[i].x2 < 0){      //もし画面外まで来たら
                                        tama[i].x2=(int)PlX;    //初期値に戻し、
										tama[i].y2=(int)PlY;
                                        tama[i].flag=0;   //発射フラグを戻す
                                }
								if(tama[i].x2-30 < ElX+12 && tama[i].x2-30 > ElX-12 && 
									tama[i].y2 < ElY+12 && tama[i].y2 > ElY-12 && HP>0){
									tama[i].x2=(int)PlX;
									tama[i].y2=(int)PlY;
									tama[i].flag=0;
									HP--;
								}
                        }
                }
			}
				if(tmuki==0){
					for(i=0;i<10;i++){
                        if(tama[i].flag==1){              //発射している玉なら
                                tama[i].y2-=8;
								DrawGraph( tama[i].x2 , tama[i].y2 , image2[2] , TRUE );//玉を描画
                                if(tama[i].y2 > 480){      //もし画面外まで来たら
                                        tama[i].x2=(int)PlX;    //初期値に戻し、
										tama[i].y2=(int)PlY;
                                        tama[i].flag=0;   //発射フラグを戻す
                                }
								if(tama[i].x2 < ElX+12 && tama[i].x2 > ElX-12 && 
									tama[i].y2 < ElY+12 && tama[i].y2 > ElY-12 && HP>0){
									tama[i].x2=(int)PlX;
									tama[i].y2=(int)PlY;
									tama[i].flag=0;
									HP--;
								}
                        }
					}
				}
		}
		
        // マップの描画
        {
            int i, j ;

            for( i = 0 ; i < MAP_HEIGHT ; i ++ )
            {
                for( j = 0 ; j < MAP_WIDTH ; j ++ )
                {
                    // 1は当たり判定チップを表しているので1のところだけ描画
                    if( MapData[i][j] == 1 )
						DrawGraph( (int)(j * CHIP_SIZE )  , (int) (i * CHIP_SIZE ) , image1[0]  , TRUE ) ;
                }
            }
        }

		//敵キャラ
		{
			if(emo==1)
				ElX--;
			if(emo==0)
				ElX++;
			if(ElX==400)
				emo=1;
			if(ElX==50)
				emo=0;
			if(HP>0)
				DrawGraph( (int) ElX , (int) ElY , image4[0]  , TRUE ) ;
			if(PlX>ElX-10 && PlX<ElX+10 && PlY>ElY-10 && PlY<ElY+10 && HP>0)
				DxLib_End() ;
		}

        // 画面の更新
        ScreenFlip() ;
    }

    // 終了
    return 0 ;
}


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

Re: 画面スクロールについて

#16

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

こちらではデータ等がないので、確認できないことはご了承下さい。
なのでイメージで書くのとプログラムを読み違えてるかも知れません。
使う定数。
SCROLL_POINT スクロール開始する画面内の位置 640-(32*4) ぐらい?
MAP_WIDTH マップチップの横サイズ
使う変数。
PIX 画面内の自キャラX座標

コード:

#define MAP_WIDTH_PIXEL        (1920)     // マップの横幅(ピクセル)

	// 画面内のスクロールポイントに達した?
	if( PIX > SCROLL_POINT ) {
		//	はみ出したサイズ
		int scroll_offset = PIX - SCROLL_POINT;
		
		//	新しいカメラ位置
		int new_camerax = camerax + scroll_offset;
		
		//	カメラ位置がマップサイズを超えていないか? (カメラの座標は左端なのでSCREEN_WIDTHの補正が必要)
		if( new_camerax > (MAP_WIDTH_PIXEL-SCREEN_WIDTH) ) {
			//	オフセットを残りサイズに補正。
			scroll_offset = (MAP_WIDTH_PIXEL-SCREEN_WIDTH) - camerax;
		}
		
		//	補正が必要?
		if( scroll_offset > 0 ) {
			//	カメラの位置を変更する。
			camerax += scroll_offset;
			
			//	キャラクタ、弾、敵の座標を-scroll_offsetで補正する。
			
			
		}
	}
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

ラプター

Re: 画面スクロールについて

#17

投稿記事 by ラプター » 14年前

ありがとうございます!
さっそく組み込んでみたのですが今度は画面が描画されずにたぶんスクロール位置と思われる位置まで移動すると
描画されてちょっとだけ画面がスクロールした後戻ってしまうようになりました。
組み込んでみたもののコードを張りますので何か見当違いなことをしていましたら教えてください。

後遅れましたが↓がデータになってます。画像は仮のもので現在製作中です。
http://firestorage.jp/download/d3c2378a ... 296ac43ffe

コード:

int ActMain( void )
{
	ch_t ch;
	int Color;
	Color=GetColor(255,255,255);
	int image[16],image2[16],image1[1],image3[1],image4[1];
	char Key[256];
	int i=0,counter=0,tmuki=2;
	struct shot tama[10];
	int scroll=0;

	int HP=5,emo=1;

	if( DX_CHANGESCREEN_OK || DxLib_Init() == -1 ) return -1;

		for(i=0;i<10;i++){                  //初期化処理
                tama[i].x2=(int)PlX; tama[i].y2=(int)PlY; //座標代入
                tama[i].flag=0;                 //飛んでいない事を示すフラグ=0
		}


    // 描画先を裏画面にセット
    SetDrawScreen( DX_SCREEN_BACK ) ;

	walking_flag=FALSE;
	ch.muki=2;
	LoadDivGraph( "chara.png" , 16 , 4 , 4 , 60 , 60 , image );
	LoadDivGraph( "Mesh.bmp" , 1 , 1 , 1 , 32, 32 , image1);
	LoadDivGraph( "hg.png" , 16 , 4 , 4 , 32, 32 , image2);
	LoadDivGraph( "blo.png" , 1 , 1 , 1 , 32, 32 , image3);
	LoadDivGraph( "sima.png" , 1 , 1 , 1 , 32, 32 , image4);

    // 垂直同期信号を待たない
    SetWaitVSyncFlag( FALSE ) ;

    // プレイヤーの座標を初期化
    PlX = 320.0F ;        PlY = 240.0F ;
	ElX = 300.0F ;        ElY = 410.0F ;

    // プレイヤーの落下速度を初期化
    PlDownSp = 0.0F ;
	ElDownSp = 0.0F ;

    // ジャンプ中フラグを倒す
    PlJumpFlag = FALSE ;

    // 入力状態の初期化
    Input = 0 ;
    EdgeInput = 0 ;

    // 60FPS固定用、時間保存用変数を現在のカウント値にセット
    FrameStartTime = GetNowCount() ;

    // メインループ開始、ESCキーで外に出る
    while( ProcessMessage() == 0 && !ClearDrawScreen() && CheckHitKey( KEY_INPUT_ESCAPE ) == 0 && !GetHitKeyStateAll( Key ))
    {
			DrawFormatString(0,0,Color,"ch.muki=%d",ch.muki);
			DrawFormatString(100,0,Color,"tama.muki=%d",tmuki);

        // 1/60秒立つまで待つ
        while( GetNowCount() - FrameStartTime < 1000 / 60 ){}

        // 現在のカウント値を保存
        FrameStartTime = GetNowCount() ;

		if( (int)PlX%1==0 &&  (int)PlY%1==0){         //座標が1で割り切れたら入力可能
			walking_flag=FALSE;
            if     ( CheckHitKey( KEY_INPUT_UP   )  == 1 )  //上ボタンが押されたら
                    ch.muki=0;         //上向きフラグを立てる
            else if( CheckHitKey( KEY_INPUT_LEFT  )  == 1 )  //左ボタンが押されたら
                    ch.muki=1;         //左向きフラグを立てる
            else if( CheckHitKey( KEY_INPUT_RIGHT  )  == 1 )  //右ボタンが押されたら
                    ch.muki=2;         //右向きフラグを立てる
			else walking_flag=TRUE;
        }
		
        // プレイヤーの移動処理
        {
            float MoveX, MoveY ;

            // 移動量の初期化
            MoveX = 0.0F ;
            MoveY = 0.0F ;

            // 左右の移動を見る
			if(walking_flag==FALSE){
            if( Key[ KEY_INPUT_LEFT   ] == 1 ) MoveX -= SPEED ; 
			if( Key[ KEY_INPUT_RIGHT  ] == 1 ) MoveX += SPEED ; 
			}

            // 地に足が着いている場合のみジャンプボタン(ボタン1 or Zキー)を見る
            if( PlJumpFlag == FALSE && Key[ KEY_INPUT_SPACE ] == 1 )
            {
                PlDownSp = -JUMP_POWER ;
                PlJumpFlag = TRUE ;
            }

            // 落下処理
            PlDownSp += G ;

            // 落下速度を移動量に加える
            MoveY = PlDownSp ;

            // 移動量に基づいてキャラクタの座標を移動
            CharMove( &PlX, &PlY, &PlDownSp, MoveX, MoveY, CHAR_SIZE, &PlJumpFlag ) ;
        }

		//画面スクロール
		if( PlX > SCROLL_POINT ) {
        //  はみ出したサイズ
        int scroll_offset = PlX - SCROLL_POINT;
        
        //  新しいカメラ位置
        int new_camerax = camerax + scroll_offset;
        
        //  カメラ位置がマップサイズを超えていないか? (カメラの座標は左端なのでSCREEN_WIDTHの補正が必要)
        if( new_camerax > (MAP_WIDTH_PIXEL-SCREEN_WIDTH) ) {
            //  オフセットを残りサイズに補正。
            scroll_offset = (MAP_WIDTH_PIXEL-SCREEN_WIDTH) - camerax;
        }
        
        //  補正が必要?
        if( scroll_offset > 0 ) {
            //  カメラの位置を変更する。
            camerax += scroll_offset;
            
        //  キャラクタ、弾、敵の座標を-scroll_offsetで補正する。    
			}
		

		// キャラクタの描画
		if(ch.muki==2)
		ch.img=image[( (int)PlX%32)/8];
		if(ch.muki==1)
		ch.img=image[( (int)PlX%32)/8+4];

        DrawGraph( (int) (PlX - CHAR_SIZE * 0.5F)-scroll_offset  , (int) (PlY - CHAR_SIZE * 0.5F) , ch.img  , TRUE ) ; 

		{
                if(counter<5)                        //前にzを押してから5カウント未満なら
                        counter++;                       //カウントアップ
                else if( Key[ KEY_INPUT_Z ]  == 1 ){//5カウント以上たってい
                        counter=0;                       //カウンターを戻す
						tmuki=ch.muki;
                        for(i=0;i<10;i++){             
                                if(tama[i].flag==0){     //発射していない玉を探し、
                                        tama[i].flag=1;  //発射フラグを立てる
										tama[i].x2=(int)PlX;
										tama[i].y2=(int)PlY;
                                        break;
                                }
                        }
                }
				
			if(tmuki==2){
                for(i=0;i<10;i++){
                        if(tama[i].flag==1){              //発射している玉なら
                                tama[i].x2+=8;
								DrawGraph( tama[i].x2-scroll_offset , tama[i].y2 , image2[15] , TRUE );//玉を描画
                                if(tama[i].x2 > 640){      //もし画面外まで来たら
                                        tama[i].x2=(int)PlX;    //初期値に戻し、
										tama[i].y2=(int)PlY;
                                        tama[i].flag=0;   //発射フラグを戻す
                                }
								if(tama[i].x2 < ElX+12 && tama[i].x2 > ElX-12 && 
									tama[i].y2 < ElY+12 && tama[i].y2 > ElY-12 && HP>0){
									tama[i].x2=(int)PlX;
									tama[i].y2=(int)PlY;
									tama[i].flag=0;
									HP--;
								}
						}
                }
			}
			if(tmuki==1){
                for(i=0;i<10;i++){
                        if(tama[i].flag==1){              //発射している玉なら
                                tama[i].x2-=8;
								DrawGraph( tama[i].x2-30-scroll_offset , tama[i].y2 , image2[6] , TRUE );//玉を描画
                                if(tama[i].x2 < 0){      //もし画面外まで来たら
                                        tama[i].x2=(int)PlX;    //初期値に戻し、
										tama[i].y2=(int)PlY;
                                        tama[i].flag=0;   //発射フラグを戻す
                                }
								if(tama[i].x2-30 < ElX+12 && tama[i].x2-30 > ElX-12 && 
									tama[i].y2 < ElY+12 && tama[i].y2 > ElY-12 && HP>0){
									tama[i].x2=(int)PlX;
									tama[i].y2=(int)PlY;
									tama[i].flag=0;
									HP--;
								}
                        }
                }
			}
				if(tmuki==0){
					for(i=0;i<10;i++){
                        if(tama[i].flag==1){              //発射している玉なら
                                tama[i].y2-=8;
								DrawGraph( tama[i].x2-scroll_offset , tama[i].y2 , image2[2] , TRUE );//玉を描画
                                if(tama[i].y2 > 480){      //もし画面外まで来たら
                                        tama[i].x2=(int)PlX;    //初期値に戻し、
										tama[i].y2=(int)PlY;
                                        tama[i].flag=0;   //発射フラグを戻す
                                }
								if(tama[i].x2 < ElX+12 && tama[i].x2 > ElX-12 && 
									tama[i].y2 < ElY+12 && tama[i].y2 > ElY-12 && HP>0){
									tama[i].x2=(int)PlX;
									tama[i].y2=(int)PlY;
									tama[i].flag=0;
									HP--;
								}
                        }
					}
				}
		}
		
        // マップの描画
        {
            int i, j ;

            for( i = 0 ; i < MAP_HEIGHT ; i ++ )
            {
                for( j = 0 ; j < MAP_WIDTH ; j ++ )
                {
                    // 1は当たり判定チップを表しているので1のところだけ描画
                    if( MapData[i][j] == 1 )
						DrawGraph( (int)(j * CHIP_SIZE )-scroll_offset  , (int) (i * CHIP_SIZE ) , image1[0]  , TRUE ) ;
                }
            }
        }

		//敵キャラ
			{
			if(emo==1)
				ElX--;
			if(emo==0)
				ElX++;
			if(ElX==400)
				emo=1;
			if(ElX==50)
				emo=0;
			if(HP>0)
				DrawGraph( (int) ElX -scroll_offset, (int) ElY , image4[0]  , TRUE ) ;
			if(PlX>ElX-10 && PlX<ElX+10 && PlY>ElY-10 && PlY<ElY+10 && HP>0)
				DxLib_End() ;
			}
	}

        // 画面の更新
        ScreenFlip() ;
    }

    // 終了
    return 0 ;
}

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

Re: 画面スクロールについて

#18

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

まず、プログラムの流れを変えすぎです。
// キャラクタ、弾、敵の座標を-scroll_offsetで補正する。
とコメントを書いたのは、そのコメントのところで値を書き換えて欲しいからです。
後々のコードに-scroll_offsetをいれないでください。

コード:

		//画面スクロール
		if( PlX > SCROLL_POINT ) {
			//  はみ出したサイズ
			int scroll_offset = PlX - SCROLL_POINT;

			//  新しいカメラ位置
			int new_camerax = camerax + scroll_offset;

			//  カメラ位置がマップサイズを超えていないか? (カメラの座標は左端なのでSCREEN_WIDTHの補正が必要)
			if( new_camerax > (MAP_WIDTH_PIXEL-SCREEN_WIDTH) ) {
				//  オフセットを残りサイズに補正。
				scroll_offset = (MAP_WIDTH_PIXEL-SCREEN_WIDTH) - camerax;
			}

			//  補正が必要?
			if( scroll_offset > 0 ) {
				//  カメラの位置を変更する。
				camerax += scroll_offset;

				//  キャラクタ、弾、敵の座標を-scroll_offsetで補正する。
				PlX -= scroll_offset;
				
				他のも補正。
				
			}
		}
あとマップチップ表示で-cameraxが無くなっているので追加しておいてください。

まだまだ、問題がありそうですがとりあえずこれだけ直して、またそれからですね。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

ラプター

Re: 画面スクロールについて

#19

投稿記事 by ラプター » 14年前

スクロール出来ました!
もうホント見当違いなことして申し訳ないです・・・。
後は地形判定の処理なんですが
softya(ソフト屋) さんが書きました: 画面座標とマップデータの座標が食い違うのでマップの地形判定をするときには、実際のマップデータの座標に変換してから行って下さい。
-= scroll_offsetで補正した分を実際のマップデータのほうに変換、反映すれば
地形判定もスクロールするということでいいのでしょうか?

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

Re: 画面スクロールについて

#20

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

ラプター さんが書きました:スクロール出来ました!
もうホント見当違いなことして申し訳ないです・・・。
後は地形判定の処理なんですが
softya(ソフト屋) さんが書きました: 画面座標とマップデータの座標が食い違うのでマップの地形判定をするときには、実際のマップデータの座標に変換してから行って下さい。
-= scroll_offsetで補正した分を実際のマップデータのほうに変換、反映すれば
地形判定もスクロールするということでいいのでしょうか?
地形判定はcameraxで補正してください。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

ラプター

Re: 画面スクロールについて

#21

投稿記事 by ラプター » 14年前

softya(ソフト屋) さんが書きました: 地形判定はcameraxで補正してください。
すいませんもうホント最後の最後なのにまたわかりません。orz
cameraxの補正をマップチップ表示のように-cameraxをCharMove関数やMapHitCheck関数、GetChipParam関数の
X座標を変える部分に入れてみましたが全くうまくいきません。
また-scroll_offsetのような感じで補正しようともしましたがうまくいきませんでした。
どこに補正をかければいいでしょうか教えてくださいm(_ _)m

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

Re: 画面スクロールについて

#22

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

ラプター さんが書きました:
softya(ソフト屋) さんが書きました: 地形判定はcameraxで補正してください。
すいませんもうホント最後の最後なのにまたわかりません。orz
cameraxの補正をマップチップ表示のように-cameraxをCharMove関数やMapHitCheck関数、GetChipParam関数の
X座標を変える部分に入れてみましたが全くうまくいきません。
また-scroll_offsetのような感じで補正しようともしましたがうまくいきませんでした。
どこに補正をかければいいでしょうか教えてくださいm(_ _)m
-cameraxだと補正が逆です。
画面に合わせて判定するマップチップがcamerax分だけ横にずれた位置の物になりますので、プレーヤーならPlX+cameraxの位置のマップチップとの衝突判定が必要になります。
他のものの処理も同様です。

ここら辺は画面座標ではなく、マップ全体座標で管理すると楽なんですけどね。
まぁ、画面座標での処理を選んでしまったので頑張りましょう!
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

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

Re: 画面スクロールについて

#23

投稿記事 by ISLe » 14年前

いまさらですしソースを読んでないので勝手に命名してますが、
getPlayerScreenPosX() /* 画面X座標を取得 */
getPlayerScreenPosY() /* 画面Y座標を取得 */
getPlayerMapPosX() /* マップX座標を取得 */
getPlayerMapPosY() /* マップY座標を取得 */
という感じの関数を宣言して使うようにして、
プレイヤー座標がplayer_x,player_yでスクロール座標(オフセット)がscroll_x,scroll_yだとしたとき
プレイヤー座標が画面座標なら
getPlayerScreenPosX(){ return player_x; }
getPlayerScreenPosY(){ return player_y; }
getPlayerMapPosX(){ return player_x + scroll_x; }
getPlayerMapPosY(){ return player_y + scroll_y; }
プレイヤー座標がマップ座標なら
getPlayerScreenPosX(){ return player_x - scroll_x; }
getPlayerScreenPosY(){ return player_y - scroll_y; }
getPlayerMapPosX(){ return player_x; }
getPlayerMapPosY(){ return player_y; }
と関数本体を定義して使うようにすると
いちいち足すのか引くのかその必要があるのかどれだっけと悩まなくてもよくなる気がします。

ラプター

Re: 画面スクロールについて

#24

投稿記事 by ラプター » 14年前

softya(ソフト屋) さんが書きました: -cameraxだと補正が逆です。
画面に合わせて判定するマップチップがcamerax分だけ横にずれた位置の物になりますので、プレーヤーならPlX+cameraxの位置のマップチップとの衝突判定が必要になります。
他のものの処理も同様です。
cameraxでの補正の解説ありがとうございます。
色々試したのですがまだうまくいかないのでお聞きしたいのですがPlX+cameraxの位置の
マップチップとの衝突判定処理は既存のCharMove関数、MapHitCheck関数、GetChipParam関数を使ってするのでしょうか?
それとも他に処理を作らないとダメでしょうか?
すいません、頭の回らない馬鹿で・・・。

>>ISLeさん
アドバイスありがとうございます!
こういった関数の宣言でのやりかたもあるんですね。
今のが完成したらこのやり方のでも作ってみようと思います。

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

Re: 画面スクロールについて

#25

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

ラプター さんが書きました:
softya(ソフト屋) さんが書きました: -cameraxだと補正が逆です。
画面に合わせて判定するマップチップがcamerax分だけ横にずれた位置の物になりますので、プレーヤーならPlX+cameraxの位置のマップチップとの衝突判定が必要になります。
他のものの処理も同様です。
cameraxでの補正の解説ありがとうございます。
色々試したのですがまだうまくいかないのでお聞きしたいのですがPlX+cameraxの位置の
マップチップとの衝突判定処理は既存のCharMove関数、MapHitCheck関数、GetChipParam関数を使ってするのでしょうか?
それとも他に処理を作らないとダメでしょうか?
すいません、頭の回らない馬鹿で・・・。
それらの関数の中でやることになります。
PlX+cameraxはマップ全体における自キャラのピクセル座標を表します。
(PlX+camerax)/CHIP_SIZEがキャラクタの中心座標です。

printfデバッグ方法をお教えしますので、マップチップの実際にチェックしている位置をprintfで確認してみてください。
http://dixq.net/forum/blog.php?u=114&b=982


一度、図に書いてみるとか工夫が必要かもしれません。
ここら辺のややこしさが表示座標主体にするのをオススメしなかった理由です。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

ラプター

Re: 画面スクロールについて

#26

投稿記事 by ラプター » 14年前

softya(ソフト屋) さんが書きました:
それらの関数の中でやることになります。
PlX+cameraxはマップ全体における自キャラのピクセル座標を表します。
(PlX+camerax)/CHIP_SIZEがキャラクタの中心座標です。

printfデバッグ方法をお教えしますので、マップチップの実際にチェックしている位置をprintfで確認してみてください。
http://dixq.net/forum/blog.php?u=114&b=982
printfデバッグの方法を使って色々とチェックしたりしながらやってみましたところ

コード:

// マップチップの値を取得する関数
int GetChipParam( float X, float Y )
{
    int x, y ;

    // 整数値へ変換
	if( PlX > SCROLL_POINT )
		x = (int)X / CHIP_SIZE ;
	else
		x = ((int)X+camerax)/CHIP_SIZE;
    y = (int)Y / CHIP_SIZE ;

    // マップからはみ出ていたら 0 を返す
    if( x >= MAP_WIDTH || y >= MAP_HEIGHT || x < 0 || y < 0 ) return 0 ;

    // 指定の座標に該当するマップの情報を返す
    return MapData[ y ][ x ] ;
}
ここをいじってみたところ当たり判定が一緒にスクロールをしたことはしたのですが、
教えてもらったのとは何か違いますからここでいじるのは違うなというのはわかるのですが
上のほうを確認してもやはりややこしいと言われているだけあって考えるほどわからなくなってしまいました・・・・

画面座標管理よりもマップ全体管理のほうが楽と言われているので
現在の状態からマップ全体座標での管理へ変えることは出来ますか?
もし可能ならば変更や追加すべき箇所を教えてください。

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

Re: 画面スクロールについて

#27

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

今から変えてもかえって混乱すると思うので、このまま処理することをお勧めします。

コード:

    // 整数値へ変換
    if( PlX > SCROLL_POINT )
        x = (int)X / CHIP_SIZE ;
    else
        x = ((int)X+camerax)/CHIP_SIZE;
    y = (int)Y / CHIP_SIZE ;
ここでPIXとSCROLL_POINTは出てこなくて良いです。と言うより出てきてはいけません。
スクロールの補正値は全てcameraxに集約されているので、ここでPIXをチェックすると逆にずれが生じます。
どこでもcameraxは常に加算して使ってください。条件はいりません。

あとMapHitCheck()はマップチップ単位で処理するところがあるのでcameraxの補正が必要な部分があります。
CharMoveは見なおしてみましたが不要だと思います。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

ラプター

Re: 画面スクロールについて

#28

投稿記事 by ラプター » 14年前

softya(ソフト屋) さんが書きました:今から変えてもかえって混乱すると思うので、このまま処理することをお勧めします。

どこでもcameraxは常に加算して使ってください。条件はいりません。

あとMapHitCheck()はマップチップ単位で処理するところがあるのでcameraxの補正が必要な部分があります。
CharMoveは見なおしてみましたが不要だと思います。

解説ありがとうございます。後ちょっとなので頑張ってみます!
GetChipParam関数をいじってみたところ

コード:

    // 整数値へ変換
    x = ((int)X + camerax) / CHIP_SIZE ;
    y = (int)Y / CHIP_SIZE ;
こうしたところ当たり判定を一緒に動かすことは出来ました。
ですがスクロールすると当たり判定があいまいなのか変に跳ね返ったりしているので
教えていただいた通りMapHitCheck()のマップチップ単位で処理するところだと思っている部分を
いじってみているのですが

コード:

        // 当たっていたら壁から離す処理を行う

        // ブロックの上下左右の座標を算出
        blx = (float)( (int)afX / CHIP_SIZE ) * CHIP_SIZE ;        // 左辺の X 座標 ←
        brx = (float)( (int)afX / CHIP_SIZE + 1 ) * CHIP_SIZE ;    // 右辺の X 座標 ←

        bty = (float)( (int)afY / CHIP_SIZE ) * CHIP_SIZE ;        // 上辺の Y 座標
        bby = (float)( (int)afY / CHIP_SIZE + 1 ) * CHIP_SIZE ;    // 下辺の Y 座標
この部分の←を置いているところにcameraxを加算してみてるのですがうまくいきません。
もしかして私がマップチップ単位の処理のところを勘違いしているのでしょうか?
それともどちらか一方だけをいじればいいのでしょうか?

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

Re: 画面スクロールについて

#29

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

((int)afX+camerax)で良いはずですが。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

ラプター

Re: 画面スクロールについて

#30

投稿記事 by ラプター » 14年前

softya(ソフト屋) さんが書きました:((int)afX+camerax)で良いはずですが。
そうすると壁に触れたときに右のほうにすっ飛んで行ってしまうのですが・・・・
何か足りないとこがありますでしょうか?

コード:


// アクションプログラムメイン
int ActMain( void )
{
	ch_t ch;
	int Color;
	Color=GetColor(255,255,255);
	int image[36],image2[16],image1[1],image3[1],image4[1];
	char Key[256];
	int i=0,counter=0,tmuki=2;
	struct shot tama[10];

	int HP=5,emo=1;

	if( DX_CHANGESCREEN_OK || DxLib_Init() == -1 ) return -1;

		for(i=0;i<10;i++){									//初期化処理
                tama[i].x2=(int)PlX; tama[i].y2=(int)PlY;   //座標代入
                tama[i].flag=0;								//飛んでいない事を示すフラグ=0
		}


    // 描画先を裏画面にセット
    SetDrawScreen( DX_SCREEN_BACK ) ;

	walking_flag=FALSE;
	ch.muki=2;
	LoadDivGraph( "chara.png" , 16 , 4 , 4 , 60 , 60 , image );
	LoadDivGraph( "Mesh.bmp" , 1 , 1 , 1 , 32, 32 , image1);
	LoadDivGraph( "hg.png" , 16 , 4 , 4 , 32, 32 , image2);
	LoadDivGraph( "blo.png" , 1 , 1 , 1 , 32, 32 , image3);
	LoadDivGraph( "sima.png" , 1 , 1 , 1 , 32, 32 , image4);

    // 垂直同期信号を待たない
    SetWaitVSyncFlag( FALSE ) ;

    // プレイヤーの座標を初期化
    PlX = 320.0F ;        PlY = 240.0F ;
	ElX = 300.0F ;        ElY = 410.0F ;

    // プレイヤーの落下速度を初期化
    PlDownSp = 0.0F ;
	ElDownSp = 0.0F ;

    // ジャンプ中フラグを倒す
    PlJumpFlag = FALSE ;

    // 入力状態の初期化
    Input = 0 ;
    EdgeInput = 0 ;

    // 60FPS固定用、時間保存用変数を現在のカウント値にセット
    FrameStartTime = GetNowCount() ;

    // メインループ開始、ESCキーで外に出る
    while( ProcessMessage() == 0 && !ClearDrawScreen() && CheckHitKey( KEY_INPUT_ESCAPE ) == 0 && !GetHitKeyStateAll( Key ))
    {
			DrawFormatString(0,0,Color,"ch.muki=%d",ch.muki);
			DrawFormatString(100,0,Color,"tama.muki=%d",tmuki);

        // 1/60秒立つまで待つ
        while( GetNowCount() - FrameStartTime < 1000 / 60 ){}

        // 現在のカウント値を保存
        FrameStartTime = GetNowCount() ;

		if( (int)PlX%1==0 &&  (int)PlY%1==0){         //座標が1で割り切れたら入力可能
			walking_flag=FALSE;
            if     ( CheckHitKey( KEY_INPUT_UP   )  == 1 )  //上ボタンが押されたら
                    ch.muki=0;         //上向きフラグを立てる
            else if( CheckHitKey( KEY_INPUT_LEFT  )  == 1 )  //左ボタンが押されたら
                    ch.muki=1;         //左向きフラグを立てる
            else if( CheckHitKey( KEY_INPUT_RIGHT  )  == 1 )  //右ボタンが押されたら
                    ch.muki=2;         //右向きフラグを立てる
			else walking_flag=TRUE;
        }
		
        // プレイヤーの移動処理
        {
            float MoveX, MoveY ;

            // 移動量の初期化
            MoveX = 0.0F ;
            MoveY = 0.0F ;

            // 左右の移動を見る
			if(walking_flag==FALSE){
            if( Key[ KEY_INPUT_LEFT   ] == 1 ) MoveX -= SPEED ; 
			if( Key[ KEY_INPUT_RIGHT  ] == 1 ) MoveX += SPEED ; 
			}

            // 地に足が着いている場合のみジャンプボタン(ボタン1 or Zキー)を見る
            if( PlJumpFlag == FALSE && Key[ KEY_INPUT_SPACE ] == 1 )
            {
                PlDownSp = -JUMP_POWER ;
                PlJumpFlag = TRUE ;
            }

            // 落下処理
            PlDownSp += G ;

            // 落下速度を移動量に加える
            MoveY = PlDownSp ;

            // 移動量に基づいてキャラクタの座標を移動
            CharMove( &PlX, &PlY, &PlDownSp, MoveX, MoveY, CHAR_SIZE, &PlJumpFlag ) ;
        }

        //画面スクロール
        if( PlX > SCROLL_POINT ) {
            //  はみ出したサイズ
            int scroll_offset = PlX - SCROLL_POINT;
 
            //  新しいカメラ位置
            int new_camerax = camerax + scroll_offset;
 
            //  カメラ位置がマップサイズを超えていないか? (カメラの座標は左端なのでSCREEN_WIDTHの補正が必要)
            if( new_camerax > (MAP_WIDTH_PIXEL-SCREEN_WIDTH) ) {
                //  オフセットを残りサイズに補正。
                scroll_offset = (MAP_WIDTH_PIXEL-SCREEN_WIDTH) - camerax;
            }
 
            //  補正が必要?
            if( scroll_offset > 0 ) {
                //  カメラの位置を変更する。
                camerax += scroll_offset;
 
                //  キャラクタ、弾、敵の座標を-scroll_offsetで補正する。
                PlX -= scroll_offset;
                ElX -= scroll_offset;
                tama[i].x2 -= scroll_offset;
            }
        }
		// キャラクタの描画
		if(ch.muki==2)
		ch.img=image[( (int)PlX%32)/8];
		if(ch.muki==1)
		ch.img=image[( (int)PlX%32)/8+4];

        DrawGraph( (int) (PlX - CHAR_SIZE * 0.5F)  , (int) (PlY - CHAR_SIZE * 0.5F) , ch.img  , TRUE ) ; 

		{
                if(counter<5)                        //前にzを押してから5カウント未満なら
                        counter++;                       //カウントアップ
                else if( Key[ KEY_INPUT_Z ]  == 1 ){//5カウント以上たってい
                        counter=0;                       //カウンターを戻す
						tmuki=ch.muki;
                        for(i=0;i<10;i++){             
                                if(tama[i].flag==0){     //発射していない玉を探し、
                                        tama[i].flag=1;  //発射フラグを立てる
										tama[i].x2=(int)PlX;
										tama[i].y2=(int)PlY;
                                        break;
                                }
                        }
                }
				
			if(tmuki==2){
                for(i=0;i<10;i++){
                        if(tama[i].flag==1){              //発射している玉なら
                                tama[i].x2+=8;
								DrawGraph( tama[i].x2 , tama[i].y2 , image2[15] , TRUE );//玉を描画
                                if(tama[i].x2 > 640){      //もし画面外まで来たら
                                        tama[i].x2=(int)PlX;    //初期値に戻し、
										tama[i].y2=(int)PlY;
                                        tama[i].flag=0;   //発射フラグを戻す
                                }
								if(tama[i].x2 < ElX+12 && tama[i].x2 > ElX-12 && 
									tama[i].y2 < ElY+12 && tama[i].y2 > ElY-12 && HP>0){
									tama[i].x2=(int)PlX;
									tama[i].y2=(int)PlY;
									tama[i].flag=0;
									HP--;
								}
						}
                }
			}
			if(tmuki==1){
                for(i=0;i<10;i++){
                        if(tama[i].flag==1){              //発射している玉なら
                                tama[i].x2-=8;
								DrawGraph( tama[i].x2-30 , tama[i].y2 , image2[6] , TRUE );//玉を描画
                                if(tama[i].x2 < 0){      //もし画面外まで来たら
                                        tama[i].x2=(int)PlX;    //初期値に戻し、
										tama[i].y2=(int)PlY;
                                        tama[i].flag=0;   //発射フラグを戻す
                                }
								if(tama[i].x2-30 < ElX+12 && tama[i].x2-30 > ElX-12 && 
									tama[i].y2 < ElY+12 && tama[i].y2 > ElY-12 && HP>0){
									tama[i].x2=(int)PlX;
									tama[i].y2=(int)PlY;
									tama[i].flag=0;
									HP--;
								}
                        }
                }
			}
				if(tmuki==0){
					for(i=0;i<10;i++){
                        if(tama[i].flag==1){              //発射している玉なら
                                tama[i].y2-=8;
								DrawGraph( tama[i].x2 , tama[i].y2 , image2[2] , TRUE );//玉を描画
                                if(tama[i].y2 < 0){      //もし画面外まで来たら
                                        tama[i].x2=(int)PlX;    //初期値に戻し、
										tama[i].y2=(int)PlY;
                                        tama[i].flag=0;   //発射フラグを戻す
                                }
								if(tama[i].x2 < ElX+12 && tama[i].x2 > ElX-12 && 
									tama[i].y2 < ElY+12 && tama[i].y2 > ElY-12 && HP>0){
									tama[i].x2=(int)PlX;
									tama[i].y2=(int)PlY;
									tama[i].flag=0;
									HP--;
								}
                        }
					}
				}
		}
		
        // マップの描画
        {
            int i, j ;

            for( i = 0 ; i < MAP_HEIGHT ; i ++ )
            {
                for( j = 0 ; j < MAP_WIDTH ; j ++ )
                {
                    // 1は当たり判定チップを表しているので1のところだけ描画
                    if( MapData[i][j] == 1 )
						DrawGraph( (int)(j * CHIP_SIZE )-camerax  , (int) (i * CHIP_SIZE ) , image1[0]  , TRUE ) ;
                }
            }
        }

		//敵キャラ
			{
			if(emo==1)
				ElX--;
			if(emo==0)
				ElX++;
			if(ElX==400)
				emo=1;
			if(ElX==50)
				emo=0;
			if(HP>0)
				DrawGraph( (int) ElX , (int) ElY , image4[0]  , TRUE ) ;
			if(PlX>ElX-10 && PlX<ElX+10 && PlY>ElY-10 && PlY<ElY+10 && HP>0)
				DxLib_End() ;
			}

        // 画面の更新
        ScreenFlip() ;
    }

    // 終了
    return 0 ;
}

// キャラクタをマップとの当たり判定を考慮しながら移動する
int CharMove( float *X, float *Y, float *DownSP,
                    float MoveX, float MoveY, float Size, char *JumpFlag )
{
    float Dummy = 0.0F ;
    float hsize ;

    // キャラクタの左上、右上、左下、右下部分が当たり判定のある
    // マップに衝突しているか調べ、衝突していたら補正する

    // 半分のサイズを算出
    hsize = Size * 0.5F ;

    // 先ず上下移動成分だけでチェック
    {
        // 左下のチェック、もしブロックの上辺に着いていたら落下を止める
        if( MapHitCheck( *X - hsize, *Y + hsize, &Dummy, &MoveY ) == 3 ) *DownSP = 0.0F ;

        // 右下のチェック、もしブロックの上辺に着いていたら落下を止める
        if( MapHitCheck( *X + hsize, *Y + hsize, &Dummy, &MoveY ) == 3 ) *DownSP = 0.0F ;

        // 左上のチェック、もしブロックの下辺に当たっていたら落下させる
        if( MapHitCheck( *X - hsize, *Y - hsize, &Dummy, &MoveY ) == 4 ) *DownSP *= -1.0F ;

        // 右上のチェック、もしブロックの下辺に当たっていたら落下させる
        if( MapHitCheck( *X + hsize, *Y - hsize, &Dummy, &MoveY ) == 4 ) *DownSP *= -1.0F ;

		if( MapHitCheck( *X , *Y + hsize, &Dummy, &MoveY ) == 3 ) *DownSP = 0.0F ;

		
        // 上下移動成分を加算
        *Y += MoveY ;
    }

    // 後に左右移動成分だけでチェック
    {
        // 左下のチェック
        MapHitCheck( *X - hsize, *Y + hsize, &MoveX, &Dummy ) ;

        // 右下のチェック
        MapHitCheck( *X + hsize, *Y + hsize, &MoveX, &Dummy ) ;

        // 左上のチェック
        MapHitCheck( *X - hsize, *Y - hsize, &MoveX, &Dummy ) ;

        // 右上のチェック
        MapHitCheck( *X + hsize, *Y - hsize, &MoveX, &Dummy ) ;

        // 左右移動成分を加算
        *X += MoveX ;
    }

    // 接地判定
    {
        // キャラクタの左下と右下の下に地面があるか調べる
        if( GetChipParam( *X - Size * 0.5F, *Y + Size * 0.5F + 1.0F ) == 0 && 
            GetChipParam( *X + Size * 0.5F, *Y + Size * 0.5F + 1.0F ) == 0 )
        {
            // 足場が無かったらジャンプ中にする
            *JumpFlag = TRUE ;
        }
        else
        {
            // 足場が在ったら接地中にする
            *JumpFlag = FALSE ;
        }
    }

    // 終了
    return 0 ;
}

// マップとの当たり判定( 戻り値 0:当たらなかった  1:左辺に当たった  2:右辺に当たった
//                                                3:上辺に当たった  4:下辺に当たった
// 注意:MoveX と MoveY 、どっちか片方が0じゃないとまともに動作しません(爆)
int MapHitCheck( float X, float Y,
                    float *MoveX, float *MoveY )
{
    float afX, afY ;

    // 移動量を足す
    afX = X + *MoveX ;
    afY = Y + *MoveY ;

    // 当たり判定のあるブロックに当たっているかチェック
    if( GetChipParam( afX, afY ) != 0 )
    {
        float blx, bty, brx, bby ;

        // 当たっていたら壁から離す処理を行う

        // ブロックの上下左右の座標を算出
        blx = (float)( ((int)afX+camerax) / CHIP_SIZE ) * CHIP_SIZE ;        // 左辺の X 座標
        brx = (float)( ((int)afX+camerax) / CHIP_SIZE + 1 ) * CHIP_SIZE ;    // 右辺の X 座標

        bty = (float)( (int)afY / CHIP_SIZE ) * CHIP_SIZE ;        // 上辺の Y 座標
        bby = (float)( (int)afY / CHIP_SIZE + 1 ) * CHIP_SIZE ;    // 下辺の Y 座標

        // 上辺に当たっていた場合
        if( *MoveY > 0.0F )
        {
            // 移動量を補正する
            *MoveY = bty - Y - 1.0F  ;

            // 上辺に当たったと返す
            return 3 ;
        }

        // 下辺に当たっていた場合
        if( *MoveY < 0.0F )
        {
            // 移動量を補正する
            *MoveY = bby - Y + 1.0F ;

            // 下辺に当たったと返す
            return 4 ;
        }

        // 左辺に当たっていた場合
        if( *MoveX > 0.0F )
        {
            // 移動量を補正する
            *MoveX = blx - X - 1.0F ;

            // 左辺に当たったと返す
            return 1 ;
        }

        // 右辺に当たっていた場合
        if( *MoveX < 0.0F )
        {
            // 移動量を補正する
            *MoveX = brx - X + 1.0F ;

            // 右辺に当たったと返す
            return 2 ;
        }

        // ここに来たら適当な値を返す
        return 4 ;
    }

    // どこにも当たらなかったと返す
    return 0 ;
}

// マップチップの値を取得する関数
int GetChipParam( float X, float Y )
{
    int x, y ;

    // 整数値へ変換
    x = ((int)X + camerax) / CHIP_SIZE ;
    y = (int)Y / CHIP_SIZE ;

    // マップからはみ出ていたら 0 を返す
    if( x >= MAP_WIDTH || y >= MAP_HEIGHT || x < 0 || y < 0 ) return 0 ;

    // 指定の座標に該当するマップの情報を返す
    return MapData[ y ][ x ] ;
}



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

Re: 画面スクロールについて

#31

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

MoveX = brx - X + 1.0F ;
の式なんですが画面座標のものとマップ全体の座標が混在しています。
どちらかに変換してから計算してください。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

ラプター

Re: 画面スクロールについて

#32

投稿記事 by ラプター » 14年前

printfデバックを使用しながらそれぞれの座標を確認しつつ
全体座標のほうを画面座標に変換することで判定移動することが出来ました!
また直さなければいけない他の問題も見えてきたのでよかったです。

色々とご迷惑をおかけしましたが、本当にありがとうございました!

閉鎖

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