ページ 11

C#のジャンプ処理について

Posted: 2016年5月03日(火) 22:39
by Snake
昔のエアバルーンみたいなゲームをC# で作っていたんですが、初心者なもので自分にもよくわからないコードになってしまいました。

なぜかどこからジャンプしてもy座標が0になるまで飛んでしまうのです。
とても見づらく無駄な処理が多いコードだと思いますが、原因がわかる方アドバイスよろしくお願いします。

コード:

using System;
using System.Diagnostics;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        Label MePoint = new Label();
        Timer timer2 = new Timer();
        Timer timer3 = new Timer();
        Stopwatch sw_ff = new Stopwatch();
        Stopwatch sw_jp = new Stopwatch();
        PictureBox Me = new PictureBox();
        PictureBox ENEMY1 = new PictureBox();
        PictureBox ENEMY2 = new PictureBox();
        Random cRandom = new Random();
        Decimal Round;
        int x, y,i,j,enemy_y,enemy_x,enemy2_x,enemy2_y,enemy_level,enemy_speed,level;
        double time,t,y_jump,jump_sec;
        bool ff_flug,jp_flug;

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            SetTimer2();
            SetTimer3();
            MeSet();
            //CreateGate();
            i = j = 0;
        }

        private void Form1_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Space) Parabola();
        }

        private void Parabola()
        {
            sw_ff.Stop();
            ff_flug = false;

            j = y;
            time = t = 0;
            Round = 0;
            if (jp_flug == true)
            {
                sw_jp.Start();
            }
            else
            {
                sw_jp.Restart();
            }
            jp_flug = true;
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            if(ff_flug == true)FreeFall();

            if(jp_flug == true)Jump();   
        }

        private void Jump()
        {
            time = (double)sw_jp.ElapsedTicks
                           / (double)Stopwatch.Frequency;                               
            //Console.WriteLine(time);

            Round = (Decimal)Math.Round(time, 2, MidpointRounding.AwayFromZero);        

            t = jump_sec  - (double)Round;                                                       
            //Console.WriteLine(t);
            
            y_jump = 980 * (t * t);
            //Console.WriteLine(jump_sec);

            xMove(1);        

            y = (int)y_jump; 

            Me.Location = new Point(x,y);
            Controls.Add(Me);

            if (y == 0)
            {
                ff_flug = true;
                sw_ff.Restart();
                jp_flug = false;
            }
            
        }

        private void FreeFall()
        {
            time = (double)sw_ff.ElapsedTicks
                           / (double)Stopwatch.Frequency;                               
            //Console.WriteLine(time);

            Round = (Decimal)Math.Round(time, 2, MidpointRounding.AwayFromZero);        

            t = (double)Round;                                                             
            Console.WriteLine(t);

            y_jump = 980 * (t * t); 
            //Console.WriteLine(y_jump);

            xMove(1);

            jump_sec = t;  
            y = (int)y_jump;

            Me.Location = new Point(x,y);
            Controls.Add(Me);
        }
            
        private void MeSet()
        {                                                
            sw_ff.Start();
            ff_flug = true;
            jp_flug = false;

            this.Width = 1000;
            this.Height = 700;

            x = 100;
            enemy_x = 920;
            enemy_y = cRandom.Next(636);

            enemy2_x = 460;
            enemy2_y = cRandom.Next(636);

            Me.BackColor = Color.Blue;

            Me.Width = 64;
            Me.Height = 64 ;

            MePoint.Width = 100;
            MePoint.Height = 100;
            MePoint.Font = new Font("", 15);

            enemy_level = 0;
            enemy_speed = 5;
            level = 1;

            this.Text = "JumpGame";

            Me.Location = new Point(x, y);
            //Console.WriteLine("MeSet Execution");
            CreateEnemy();

            Controls.Add(Me);
        }

        private void CreateEnemy()
        {
            ENEMY1.BackColor = Color.Black;
            ENEMY2.BackColor = Color.Black;

            ENEMY1.Width = 128;
            ENEMY1.Height = 64;

            ENEMY2.Width = 128;
            ENEMY2.Height = 64;

            ENEMY1.Location = new Point(enemy_x, enemy_y);
            ENEMY2.Location = new Point(enemy2_x, enemy2_y);

            Controls.Add(ENEMY2);
            Controls.Add(ENEMY1);
        }

        private void xMove(int i)
        {
            for (int j = 0; j < i; j++)
            {
                x++;
            }  
        }

        private void SetTimer3()
        {
            timer3.Enabled = true;
            timer3.Interval = 1;
            timer3.Tick += new EventHandler(Enemy_Move);
        }

        private void SetTimer2()
        {
            timer2.Enabled = true;
            timer2.Interval = 1;
            timer2.Tick += new EventHandler(PointRenewal);
        }

        private void Enemy_Move (object sender,EventArgs e)
        {
            for (int i = 0; i < enemy_speed; i++)
            {
                enemy_x--;
                ENEMY1.Location = new Point(enemy_x, enemy_y);
                Controls.Add(ENEMY1);
            }
            if (enemy_x < -128)
            {
                enemy_x = 984;
                enemy_y = cRandom.Next(604);
            }

            for (int i = 0; i < enemy_speed; i++)
            {
                enemy2_x--;
                ENEMY2.Location = new Point(enemy2_x, enemy2_y);
                Controls.Add(ENEMY2);
            }
            if (enemy2_x < -128)
            {
                enemy_level++;

                enemy2_x = 984;
                enemy2_y = cRandom.Next(604);
            }

            if (enemy_level == enemy_speed * 2)
            {
                level++;
                enemy_speed += 3;
            }

            if (y > 1000)
            {
                GameOver();
            }
        }

        private void GameOver()
        {
            timer3.Enabled = false;
            timer2.Enabled = false;
            timer1.Enabled = false;
            MessageBox.Show("Game Over");
            Application.Exit();
        }

        private void PointRenewal(object sender,EventArgs e)
        {
            Console.WriteLine("x = "+ x + " , y = " + y);
            MePoint.Text = "x  =  " + Convert.ToString(x) + "  y  =  " + Convert.ToString(y) + "   Lv = " + level;
            Controls.Add(MePoint);
        }
    }
}

敵がランダムで流れてくるようにもなっていますがまだあたり判定はつけていません。よろしければあたり判定のロジックのようなものも教えていただけると幸いです。

よろしくお願いします。

Re: C#のジャンプ処理について

Posted: 2016年5月07日(土) 14:38
by いわん
質問の情報だけでソースを追いかけるのは大変なのでデバッグのヒントだけ。
y座標に関連する変数の内容を変更している箇所でブレークなり内容をログ出力するなりしたら、予備知識のない人が一から追っかけるより案外簡単に原因が判明するかもしれません。
デバッグ出力に Consoleクラスを使っているようですが、 Debugクラスを利用したほうがファイルに出力できたりとかいろいろ便利です。

Debugクラスでファイルに出力する例

コード:

public Form1()
{
	// テキストファイルに出力する TextWriterTraceListenerオブジェクトを作成して Debug Listeners コレクションに追加する
	System.Diagnostics.TextWriterTraceListener tl = 
		new System.Diagnostics.TextWriterTraceListener(System.IO.File.CreateText("debug.txt"));
	System.Diagnostics.Debug.Listeners.Add(tl);

	InitializeComponent();
}

・・・
	System.Diagnostics.Debug.WriteLine("y = " + y);	// デバッグログ出力
・・・

private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
	// 終了時にすべての出力をファイルに書き込む
	System.Diagnostics.Debug.Flush();
}

Re: C#のジャンプ処理について

Posted: 2016年5月07日(土) 16:36
by Tatu
求めている動作はこの動画のような感じですか?
[youtube][/youtube]

それなら自機のy方向の速度を扱う変数vyを追加し、
ジャンプ時にはvyをある値にする。
落下処理時にはvyを増やしてyの値をvyだけ増加する。
というようにしてみてはどうでしょうか?


あと、実行してみてもらいたいのでしたら
Form1.Designer.csファイルも載せるようにするとよいでしょう。