所以我一直在测试一些在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;
}
}
}
因此,与其说是一个新计时器,不如说是一种变通方法。我的具体问题的答案不是算法。这实际上是我做过的最流畅、最小的自制游戏引擎。问题是,我试图移动一个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