2013-02-23 50 views
0

所以我一直在测试了在Silverlight创建一个垂直滚动游戏的一些新的算法,一个流畅的游戏帧计时器。我想出了一个非常简单的解决方案。但是,当你在手机上运行它时,帧速率会有很多不一致。我不知道这是否是由于算法不好,一次吸引很多东西(目前只有png背景和股票图片)或其他东西。创建为WP7 Silverlight的游戏

基本上我想要的是执行,我可以执行从所有更新方法,有一个一致的外观和感觉,无论游戏的你在哪一部分的方法的游戏循环计时器。这是后端代码。

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; 

      } 
     } 
    } 

回答

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