2013-02-23 1 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 здесь