0

そこで、Silverlight で垂直スクロール ゲームを作成するための新しいアルゴリズムをいくつかテストしてきました。私は非常に簡単な解決策を思いつきました。ただし、電話で実行すると、フレームレートに多くの矛盾があります. これが貧弱なアルゴリズムによるものなのか、一度に多くのものを描画するのか (現時点では png 背景とストック プレーヤー画像のみ) が原因なのかはわかりません。

基本的に私が欲しいのは、すべての更新メソッドを実行できるメソッドを実行し、ゲームのどの部分にいても一貫したルック アンド フィールを持つゲーム ループ タイマーです。これがバックエンドのコードです。

   public partial class MainPage : PhoneApplicationPage
    {
        // Constructor
        int counter = 0;
        DispatcherTimer playerTimer;

        string _START   = "START";
        string _FALLING = "FALLING";
        string _LEFT    = "LEFT";
        string _RIGHT   = "RIGHT";
        string _CENTER  = "CENTER";

        string playerState = "";
        int playerMoveTimeout = 20;
        public MainPage()
        {
            InitializeComponent();
            playerState = _START;

            playerTimer = new DispatcherTimer();
            playerTimer.Interval = TimeSpan.FromSeconds(.00999);
            playerTimer.Tick += playerTimer_Tick;
            playerTimer.Start();
        }

        void playerTimer_Tick(object sender, EventArgs e)
        {
            updatePlayer();

            if (counter > 0)
            {
                counter = updateBG(counter);
            }
        }
        public void updatePlayer()
        {
            if (Canvas.GetLeft(Player) + Player.Width >= 480)
            {
                playerState = _LEFT;

            }
            else if (Canvas.GetLeft(Player) <= 0)
            {
                playerState = _RIGHT;
            }
            if(playerMoveTimeout <= 0)
            {
                playerState = _FALLING;
            }
            if (playerState.Equals(_START))
            { }
            else if (playerState.Equals(_FALLING))
            {
                Canvas.SetTop(Player, Canvas.GetTop(Player) + 30);
            }
            else if (playerState.Equals(_LEFT))
            {
                Canvas.SetTop(Player, Canvas.GetTop(Player) - 60);
                Canvas.SetLeft(Player, Canvas.GetLeft(Player) - 20);
                playerMoveTimeout--;
            }
            else if (playerState.Equals(_RIGHT))
            {
                Canvas.SetTop(Player, Canvas.GetTop(Player) - 60);
                Canvas.SetLeft(Player, Canvas.GetLeft(Player) + 20);
                playerMoveTimeout--;
            }
            else //CENTER
            {
                Canvas.SetTop(Player, Canvas.GetTop(Player) - 60);
                playerMoveTimeout--;
            }
        }

        public int updateBG(int time)
        {
            if (Canvas.GetTop(background) > 800)
                Canvas.SetTop(background, -2400);
            int x = time;
            Canvas.SetTop(background, Canvas.GetTop(background) + 60);
            x -= 40;
            return x;
        }


        private void Player_Tap(object sender, GestureEventArgs e)
        {

            Point point = e.GetPosition(Player);
            double Y = point.Y;
            double X = point.X;
            if (X < 80)
            {
                counter = 400;
                playerMoveTimeout = 20;
                playerState = _RIGHT;

            }
            else if (X > 120)
            {
                counter = 400;
                playerMoveTimeout = 20;
                playerState = _LEFT;

            }
            else
            {
                counter = 400;
                playerMoveTimeout = 20;
                playerState = _CENTER;

            }
        }
    }
4

1 に答える 1

0

したがって、答えは新しいタイマーよりも回避策です。私の特定の問題に対する答えは、アルゴリズムではありませんでした。これは実際、私がこれまでに作成した自作ゲーム エンジンの中で最も滑らかで最小です。問題は、480X2400 の背景画像を動かそうとしたところ、動きが鈍くなったことです。だから私がやったことは、メインのキャンバス内に新しいキャンバスを入れ子にして、背景に名前を付けることでした。次に、背景に移動したいすべての要素をそこに配置します

このような

<Canvas Name="background">
    <Image Name="cloud" Source="cloud.png" Width="247" Height="158"/>
    <Image x:Name="cloud_Copy" Source="/cloud.png" Width="247" Height="158" Canvas.Left="192" Canvas.Top="268"/>
    <Image x:Name="cloud_Copy1" Source="/cloud.png" Width="247" Height="158" Canvas.Left="-11" Canvas.Top="592"/>
    <Image x:Name="cloud_Copy2" Source="/cloud.png" Width="247" Height="158" Canvas.Left="192" Canvas.Top="-474"/>
    <Image x:Name="cloud_Copy3" Source="/cloud.png" Width="247" Height="158" Canvas.Top="-900"/>
    <Image x:Name="cloud_Copy4" Source="/cloud.png" Width="247" Height="158" Canvas.Left="192" Canvas.Top="-1566"/>
    <Image x:Name="cloud_Copy5" Source="/cloud.png" Width="247" Height="158" Canvas.Left="-78" Canvas.Top="-2280"/>
    <Image x:Name="cloud_Copy6" Source="/cloud.png" Width="247" Height="158" Canvas.Left="192" Canvas.Top="-2766"/>
    <Image x:Name="cloud_Copy7" Source="/cloud.png" Width="247" Height="158" Canvas.Left="-102" Canvas.Top="-3390"/>
    <Image x:Name="cloud_Copy8" Source="/cloud.png" Width="247" Height="158" Canvas.Left="90" Canvas.Top="-3122"/>
    <Image x:Name="cloud_Copy9" Source="/cloud.png" Width="247" Height="158" Canvas.Left="-113" Canvas.Top="-2798"/>
    <Image x:Name="cloud_Copy10" Source="/cloud.png" Width="247" Height="158" Canvas.Left="90" Canvas.Top="-3864"/>
    <Image x:Name="cloud_Copy11" Source="/cloud.png" Width="247" Height="158" Canvas.Top="-4290" Canvas.Left="-102"/>
    <Image x:Name="cloud_Copy12" Source="/cloud.png" Width="247" Height="158" Canvas.Left="90" Canvas.Top="-4956"/>
    <Image x:Name="cloud_Copy13" Source="/cloud.png" Width="247" Height="158" Canvas.Left="-180" Canvas.Top="-5670"/>
    <Image x:Name="cloud_Copy14" Source="/cloud.png" Width="247" Height="158" Canvas.Left="90" Canvas.Top="-6156"/>
    <Image x:Name="cloud_Copy15" Source="/cloud.png" Width="247" Height="158" Canvas.Left="-192" Canvas.Top="-7278"/>
    <Image x:Name="cloud_Copy16" Source="/cloud.png" Width="247" Height="158" Canvas.Top="-7010"/>
    <Image x:Name="cloud_Copy17" Source="/cloud.png" Width="247" Height="158" Canvas.Left="-203" Canvas.Top="-6686"/>
    <Image x:Name="cloud_Copy18" Source="/cloud.png" Width="247" Height="158" Canvas.Top="-7752"/>
    <Image x:Name="cloud_Copy19" Source="/cloud.png" Width="247" Height="158" Canvas.Top="-8178" Canvas.Left="-192"/>
    <Image x:Name="cloud_Copy20" Source="/cloud.png" Width="247" Height="158" Canvas.Top="-8844"/>
    <Image x:Name="cloud_Copy21" Source="/cloud.png" Width="247" Height="158" Canvas.Left="-270" Canvas.Top="-9558"/>
    <Image x:Name="cloud_Copy22" Source="/cloud.png" Width="247" Height="158" Canvas.Top="-10044"/>
</Canvas>


<Image Name="Star"  Visibility="Collapsed" Source="star.png" Height="50" Width="50" />
<Image x:Name="Player" Source="star.png" Width="200" Height="200" Canvas.Left="117" Canvas.Top="403"/>
<Rectangle Name="TapBox" Fill="#FFF4F4F5" Height="248" Stroke="Black" Width="301" Canvas.Left="68" Canvas.Top="403" Opacity="0" Tap="Rectangle_Tap_1"/>
    <TextBlock x:Name="alt"/> 
</Canvas>

私が見る限り、パフォーマンスを低下させることなく、このキャンバスに大量のものをロードできます。

次に、ここで更新するのは私の新しいゲームループです

public partial class MainPage : PhoneApplicationPage
    {
        DispatcherTimer gameTimer;

        string _START           = "START";
        string _FALLING         = "FALLING";
        string _LEFT            = "LEFT";
        string _RIGHT           = "RIGHT";
        string _CENTER          = "CENTER";
        string playerState      = "";

        int counter             = 0;
        int playerMoveTimeout   = 40;
        public int altitude { get; set; }

        // Constructor
        public MainPage()
        {
            InitializeComponent();
            buildGameArea();
            alt.Text = altitude.ToString();
            playerState = _START;
            gameTimer = new DispatcherTimer();
            gameTimer.Interval = new TimeSpan(3333);
            gameTimer.Start();
            gameTimer.Tick+=gameTimer_Tick;

        }

        void gameTimer_Tick(object sender, EventArgs e)
        {

            updatePlayer();
            updateGameElements();
        }

        public void buildGameArea()
        {
            Canvas.SetTop(cloud, -300);
        }
        public void reloadPlayer()
        {
            playerState = _START;
            playerMoveTimeout = 40;
            Canvas.SetTop(Player, 300);
            Canvas.SetLeft(Player, 200);
        }
        public void updatePlayer()
        {
            if (Canvas.GetTop(Player) > 800)
            {
                reloadPlayer();
            }


            if (Canvas.GetLeft(Player) + Player.Width >= 480)
            {
                playerState = _LEFT;

            }
            else if (Canvas.GetLeft(Player) <= 0)
            {
                playerState = _RIGHT;
            }

            if (playerMoveTimeout <= 0)
            {
                playerState = _FALLING;
            }


            if (playerState.Equals(_START))
            { }
            else if (playerState.Equals(_FALLING))
            {
                Canvas.SetTop(Player, Canvas.GetTop(Player) + 30);

            }
            else if (playerState.Equals(_LEFT))
            {
                Canvas.SetTop(Player, Canvas.GetTop(Player) - 40);
                Canvas.SetLeft(Player, Canvas.GetLeft(Player) - 20);
                playerMoveTimeout--;
            }
            else if (playerState.Equals(_RIGHT))
            {
                Canvas.SetTop(Player, Canvas.GetTop(Player) - 40);
                Canvas.SetLeft(Player, Canvas.GetLeft(Player) + 20);
                playerMoveTimeout--;

            }
            else //CENTER
            {
                Canvas.SetTop(Player, Canvas.GetTop(Player) - 40);
                playerMoveTimeout--;
            }
            TapBox.Margin = Player.Margin;
        }
        public void updateGameElements()
        {
            alt.Text = altitude.ToString();


            //This single conditional moves every single thing on the background canvas
            if (counter > 0)
            {
                Canvas.SetTop(background, Canvas.GetTop(background) + 20);
                counter -= 20;
            }
        }

        private void Rectangle_Tap_1(object sender, GestureEventArgs e)
        {
            System.Windows.Point point = e.GetPosition(Player);
            double Y = point.Y;
            double X = point.X;
            altitude += 100;
            if (X < 80)
            {
                counter = 400;
                playerMoveTimeout = 40;
                playerState = _RIGHT;

            }
            else if (X > 120)
            {
                counter = 400;
                playerMoveTimeout = 40;
                playerState = _LEFT;

            }
            else
            {
                counter = 400;
                playerMoveTimeout = 40;
                playerState = _CENTER;

            }
        }
    }

これをデバイスに配置すると、進行状況に関係なく、最初から最後まで一貫したフレーム レートがあることがわかります。

うまくいけば、これを理解するのに無駄な一日が将来誰かを助けるでしょう.

繰り返しますが、これは Silverlight ゲーム プログラミング用です。ここに XNA はありません

于 2013-02-23T23:25:56.030 に答える