マップスクロールがうまくできない

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

マップスクロールがうまくできない

#1

投稿記事 by ぴーまん » 14年前

現在のろのろと不定期にC#とDXライブラリでアクションゲームを制作しています。先日こちらの掲示板でマップとキャラの当たり判定の処理についてお尋ねしたところ大変満足する処理を実装できましたので,また質問させていただきます。

今度はマップスクロールで悩んでいます。マップは正方形型のブロックが配置された単純なものです。絶対に間違っているという予想の下,とりあえずキャラクタが動いたら動いた分だけ逆向きにブロックを動かしてやるというやり方をしてみたところ,案の定ブロックが吹っ飛んでしまい,しかも当たり判定はそのまま(ブロックのグラフィックはそこにないが,当たり判定はそのままあるという状態。文章だとわかりにくいですね)という風になってしまいました。
以下にコードを載せます。

コード:

using System;
using System.Windows.Forms;
using DxLibDLL;
namespace SampleGame
{
    public class Game
    {
        [STAThread]
        public static void Main()
        {
            Ziki ziki; //Zikiクラスのziki変数を用意
            Teki[] teki;
            Block block;//Blockクラスのblocks変数を用意
            Haikei haikei;
            int input;//自機の操作を割り当てる変数
            int zikigraph;//自機の画像を割り当てる変数
            int tekigraph;
            const int TEKI_NUM = 16;
            DX.ChangeWindowMode(1);
            if (DX.DxLib_Init() == -1) return;
            DX.SetDrawScreen(DX.DX_SCREEN_BACK);
            //画像ハンドルの読み込み
            zikigraph = DX.LoadGraph("data\\自機.png");
            tekigraph = DX.LoadGraph("data\\敵.jpg");
            //オブジェクトの生成
            ziki = new Ziki(zikigraph);
            teki = new Teki[TEKI_NUM];
            teki[0] = new Teki(tekigraph, 40*1, 40*1);
            teki[1] = new Teki(tekigraph, 40*4, 40*1);
            teki[2] = new Teki(tekigraph, 40*6, 40*1);
            teki[3] = new Teki(tekigraph, 40*8, 40*10);
            teki[4] = new Teki(tekigraph, 40*10, 40*10);
            teki[5] = new Teki(tekigraph, 40*14, 40*10);
            teki[6] = new Teki(tekigraph, 70, 310);
            teki[7] = new Teki(tekigraph, 100, 390);
            teki[8] = new Teki(tekigraph, 20, 400);
            teki[9] = new Teki(tekigraph, 80, 300);
            teki[10] = new Teki(tekigraph, 80, 300);
            teki[11] = new Teki(tekigraph, 80, 300);
            teki[12] = new Teki(tekigraph, 80, 300);
            teki[13] = new Teki(tekigraph, 80, 300);
            teki[14] = new Teki(tekigraph, 80, 300);
            teki[15] = new Teki(tekigraph, 80, 300);
            block = new Block();
            haikei = new Haikei();
            block.LoadGraph();
            haikei.LoadGraph();
            block.Init();

            while (DX.ProcessMessage() == 0)
            {
                input = DX.GetJoypadInputState(DX.DX_INPUT_KEY);//inputにこのキー操作を割り当てる
                ziki.Update(input);//Update関数(操作)にinputを渡す
                foreach (Teki te in teki)
                {
                    te.Move();
                    te.gravityflag = true;
                    te.Gravity();
                }
                ziki.gravityflag = true;
                ziki.Gravity();//重力を実際に与える関数
                ziki.Jump(input);
                ziki.Genkai();
                DX.ClearDrawScreen();
                haikei.Draw();
                block.Draw();
                block.BlockAtari(ziki.x, ziki.y);
                block.Scroll(ziki.x, ziki.y, input);
                foreach (Teki te in teki)
                {
                    te.Draw();
                }
                ziki.Draw();//自機の描画
                ziki.Kakunin();
                DX.ScreenFlip();
            }
            DX.DxLib_End();
        }
    }
    public class Character//後で敵キャラクターを作るためにひとまずキャラクター全体の基盤クラスをつくる
    {
        int graph;
        public int gravity = 3;//重力の大きさ
        public bool gravityflag;//重力がかかっているかないかのフラグ
        public int x, y;//キャラクターの座標
        public int movex, movey;//移動距離
        public int width, height;//キャラクターのタテヨコの長さ
        public int x_temp, y_temp,z_temp;//移動時の仮座標
        public int jump_power;//ジャンプ時の移動距離(初期)
        public bool jump_flag;//ジャンプ中かどうかのフラグ
        public bool run_flag;//走っているかどうかのフラグ
        public bool ontheground_flag; // 地面についているかどうかのフラグ
        public bool jump_key_previous;
        public bool muki;
        public Character(int gr)
        {
            graph = gr;
        }
        public void Draw()
        {
            DX.DrawGraph(x, y, graph, 1);//描画
        }
        public void Gravity()
        {
            while (gravityflag == true)
            {
                x_temp = x+6;
                y_temp = y+gravity+39;
                z_temp = x + 34;
                x_temp = x_temp / 40;
                y_temp = y_temp / 40;
                z_temp = z_temp / 40;
                if (Block.haiti[y_temp, x_temp] == 0 && Block.haiti[y_temp, z_temp] == 0)
                {
                    y += gravity;
                }
                if (Block.haiti[y_temp, x_temp] == 1 || Block.haiti[y_temp, z_temp] == 1)
                {
                    ontheground_flag = true;
                    jump_flag = false;
                    jump_power = 20;
                }
                break;
            }
        }
    }
    public class Ziki : Character
    {
        const int zeki_jump_power = 20;
        public Ziki(int gr)
            : base(gr)
        {
            x = 40;
            y = 40;
            width = 40;
            height = 40;
            jump_power = zeki_jump_power;
          jump_flag = false;
          run_flag = false;
            ontheground_flag = false;
            jump_key_previous = false;
            movex = 2;
            muki = true;
        }
        public void Update(int input)//自機の操作
        {
            if ((input & DX.PAD_INPUT_LEFT) != 0)
            {
                x_temp = x - movex;
                y_temp = y;
                z_temp = y + 39;
                x_temp = x_temp / 40;
                y_temp = y_temp / 40;
                z_temp = z_temp / 40;
                if (Block.haiti[y_temp, x_temp] == 0 && Block.haiti[z_temp, x_temp] == 0)
                {
                    x -= movex;
                    if (DX.CheckHitKey(DX.KEY_INPUT_LSHIFT) != 0)
                    {
                        run_flag = true;
                        x -= movex;
                    }
                    else
                    {
                        run_flag = false;
                    }
                }
            }
            if ((input & DX.PAD_INPUT_RIGHT) != 0)
            {
                x_temp = x + movex + 39;
                y_temp = y;
                z_temp = y + 39;
                x_temp = x_temp / 40;
                y_temp = y_temp / 40;
                z_temp = z_temp / 40;
                if (Block.haiti[y_temp, x_temp] == 0 && Block.haiti[z_temp, x_temp] == 0)
                {
                    x += movex;
                    if (DX.CheckHitKey(DX.KEY_INPUT_LSHIFT) != 0)
                    {
                        run_flag = true;
                        x += movex;
                    }
                    else
                    {
                        run_flag = false;
                    }
                }
            }
        }
        public void Genkai()
        {
            if (x < 0)
            {
                x = 0;
            }
        }
        public void Jump(int input)
        {
            if ((input & DX.PAD_INPUT_A) != 0 && jump_flag == false && ontheground_flag == true)
            {
                if (jump_key_previous == false)
                {
                    jump_flag = true;
                    ontheground_flag = false;
                    jump_key_previous = true;
                }
            }
            else
            {
                jump_key_previous = false;
            }
            if(jump_flag == true)
            {
                x_temp = x+6;
                y_temp = y - jump_power;
                z_temp = x + 34;
                x_temp = x_temp / 40;
                y_temp = y_temp / 40;
                z_temp = z_temp / 40;
                
                if (Block.haiti[y_temp, x_temp] == 0 && Block.haiti[y_temp, z_temp] == 0)
                {
                        y -= jump_power;
                        if (jump_power > 0)
                        {
                            jump_power--;
                        }
                        else
                        {
                            jump_power = 0;
                        }
                }
                if (Block.haiti[y_temp, x_temp] == 1 || Block.haiti[y_temp, z_temp] == 1)
                {
                    jump_power = 0;
                }
            }
        }
        public void Kakunin()
        {
            if (ontheground_flag == true)
            {
                DX.DrawString(0, 0, "着地", DX.GetColor(255, 255, 255));
            }
            else
            {
                DX.DrawString(0, 0, "着地していない", DX.GetColor(255, 255, 255));
            }
        }
    }
    public class Teki : Character
    {
        const int zeki_jump_power = 17;
        public Teki(int gr,int tx,int ty)
            : base(gr)
        {
            x = tx;
            y = ty;
            width = 40;
            height = 40;
            jump_power = zeki_jump_power;
            jump_flag = false;
            run_flag = false;
            ontheground_flag = false;
            jump_key_previous = false;
            movex = 1;
            muki = true;
        }
        public void Move()
        {
            if (muki == true)
            {
                x_temp = x + movex + 39;
                y_temp = y;
                z_temp = y + 39;
                x_temp = x_temp / 40;
                y_temp = y_temp / 40;
                z_temp = z_temp / 40;
                if (Block.haiti[y_temp, x_temp] == 0 && Block.haiti[z_temp, x_temp] == 0)
                {
                    x += movex;
                    if (run_flag == true)
                    {
                        x += movex;
                    }
                }
                if (Block.haiti[y_temp, x_temp] == 1 && Block.haiti[z_temp, x_temp] == 1)
                {
                    muki = false;
                }
            }
            if (muki == false)
            {
                x_temp = x - movex;
                y_temp = y;
                z_temp = y + 39;
                x_temp = x_temp / 40;
                y_temp = y_temp / 40;
                z_temp = z_temp / 40;
                if (Block.haiti[y_temp, x_temp] == 0 && Block.haiti[z_temp, x_temp] == 0)
                {
                    x -= movex;
                    if (run_flag == true)
                    {
                        x -= movex;
                    }
                }
                if (Block.haiti[y_temp, x_temp] == 1 && Block.haiti[z_temp, x_temp] == 1)
                {
                    muki = true;
                }
            }
        }
    }
    public class Block
    {
        int blockgraph1;
        public static int[,] haiti = 
            {
                {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
                {1,0,0,1,0,0,0,0,0,0,1,0,0,0,0,1},
                {1,0,0,1,1,1,1,1,0,1,1,0,0,0,0,1},
                {1,0,0,1,1,0,0,0,0,1,0,0,0,0,0,1},
                {1,0,0,1,1,0,1,0,0,1,0,0,0,0,0,1},
                {1,0,0,1,1,0,1,1,0,1,0,0,0,0,0,1},
                {1,0,0,1,1,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,1},
                {1,0,0,0,0,0,1,1,1,1,1,1,1,1,0,1},
                {1,0,0,0,0,1,1,1,1,1,1,1,1,1,0,1},
                {1,0,0,0,1,1,1,1,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なら配置,0なら配置しない
        const int CHIP_SIZE = 40;//ブロックひとつあたりの大きさ
        const int XKOSUU = 640 / CHIP_SIZE;//ブロックが画面横(X)に埋まる個数
        const int YKOSUU = 480 / CHIP_SIZE;//ブロックが画面縦(Y)に埋まる個数]
        int[] x = new int[XKOSUU];
        int[] y = new int[YKOSUU];
        public void LoadGraph()
        {
            blockgraph1 = DX.LoadGraph("data\\ブロック.png");//同上
        }
        public void Init()
        {
            for (int i = 0; i < YKOSUU; ++i)
            {
                for (int j = 0; j < XKOSUU; ++j)
                {
                    if (haiti[i, j] == 1)
                    {
                        x[j] = j * CHIP_SIZE;
                        y[i] = i * CHIP_SIZE;
                    }
                }
            }
        }
        public void Draw()
        {
            for (int i = 0; i < YKOSUU; ++i)
            {
                for (int j = 0; j < XKOSUU; ++j)
                {
                    if (haiti[i, j] == 1)
                    {
                        DX.DrawGraph(x[j], y[i], blockgraph1, 1);
                    }
                }
            }
        }
        public void BlockAtari(int x,int y)
        {
            int px, py;
            px = x / CHIP_SIZE;
            py = y / CHIP_SIZE;
            string pxstring = px.ToString();
            string pystring = py.ToString();
            string zahyou = "x座標のmap:" + pxstring + "     " + "y座標のmap:" + pystring;
            DX.DrawString(160,240,zahyou,DX.GetColor(255,255,255));
        }
        public void Scroll(int px, int py,int input)
        {
            if(px>320)
            {
                if ((input & DX.PAD_INPUT_RIGHT) != 0)
                {
                    for (int i = 0; i < YKOSUU; ++i)
                    {
                        for (int j = 0; j < XKOSUU; ++j)
                        {
                            if (haiti[i, j] == 1)
                            {
                                x[j] -= 2;
                            }
                        }
                    }
                }
            }
        }
    }
    public class Haikei
    {
        int graph;
        int x = 0;
        int y = 0;
        public void LoadGraph()
        {
            graph = DX.LoadGraph("data\\背景.jpg");
        }
        public void Draw()
        {
            DX.DrawGraph(x, y, graph, 1);
        }
    }
}
スクロールを行なっている関数は

コード:

public void Scroll(int px, int py,int input)
        {
            if(px>320)
            {
                if ((input & DX.PAD_INPUT_RIGHT) != 0)
                {
                    for (int i = 0; i < YKOSUU; ++i)
                    {
                        for (int j = 0; j < XKOSUU; ++j)
                        {
                            if (haiti[i, j] == 1)
                            {
                                x[j] -= 2;
                            }
                        }
                    }
                }
            }
}
ですが,どうみても間違っているように思えます。
正しいやり方をどなたか教えてください。

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

Re: マップスクロールがうまくできない

#2

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

簡単に説明すると、マップのおけるブロックやキャラの位置と表示位置は別に管理します。
(1)自キャラの位置を画面中心になるように、画面左上のマップ上の座標を求める。
(2)ただし自キャラが画面中心になれないマップ端の状況なら左上座標を補正する。
(3)画面左上の座標から相対で背景ブロックの一を計算して画面に入るブロックを表示する。
(4)画面左上の座標から相対で自キャラ、敵キャラの表示座標を求めて表示。

[補足]
最近にた投稿があったので参考にして下さい。
「マップスクロール時、敵の行動について • C言語交流フォーラム ~ mixC++ ~」
http://dixq.net/forum/viewtopic.php?f=3&t=10522
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

閉鎖

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