2013-07-03 64 views
6

我建立一个简单的单机游戏,还有谁移动当按键按下播放器,并有敌人自动移动,每种类型的敌人在X毫秒移动一次。使用定时器和游戏循环

据我了解我应该使用timer,但我真的不知道如何在游戏循环中做到这一点(尚未建成,因为我不知道如何处理计时器,但它应该我想是while loop)。游戏结束时,敌人“触摸”玩家(相同的x和y)。

一件重要的事情:我不能在Thread这个练习中,但如果您有其他建议而不是使用Timer,欢迎您。

谢谢。

+0

使用控制台游戏,你的意思是运行在视频游戏控制台或实际控制台应用程序上的应用程序? (命令提示符等) – 2013-07-03 05:52:49

+0

控制台应用程序。 – Luis

回答

16

您通常不会在游戏中使用传统的计时器。游戏有处理他们的逻辑非常不同的机制和经过的时间,他们一般不与定时器工作与否的方式,你会期望:

游戏通常有一些所谓游戏循环。一般来说它是被称为一个接一个的循环后三个主要功能:

while(running) 
{ 
    HandleUserInput(); 
    ChangeWorld(); 
    Render(); 
} 

您获取用户输入,你相应地改变游戏世界,你把它画到屏幕上。现在,你的电脑速度越快,这个循环运行得越快。这对图形来说很好(认为是FPS),但对游戏不利。想象一下俄罗斯方块,每块图块都会移动。现在我不想购买更快的电脑,这样游戏会变得更加困难。

所以要保持计算机的电源的游戏速度无关的常数,循环认为过去的时间:

while(running) 
{ 
    var timePassedSinceLastLoop = CalculateTimeDelta(); 

    HandleUserInput(); 
    ChangeWorld(timePassedSinceLastLoop); 
    Render(); 
} 

现在想象一下,冷却时间在游戏中的东西。玩家按下“a”,发生了一些很酷的动作,虽然他可能再次按下“a”,但在接下来的5秒内不会发生任何事情。但游戏仍然在运行,并且可能会在游戏中发生所有其他事情。这不是一个传统的计时器。这是一个变量,我们称它为ActionColdown,一旦玩家触发该动作,它将被设置为5秒。每当世界发生变化时,从该数字中减去timePassed直到它为零。一直以来,游戏都在运行并处理输入和渲染。但是只有ActionColdown达到零时,再次按下“a”才会再次触发该动作。

ChangeWorld方法包括对世界的所有自动更改。敌人,导弹,无需玩家互动的任何动作。它会根据时间而移动。如果敌人每秒移动一个正方形,则每次循环运行时,都需要使其坐标浮动并添加一部分正方形。

可以说你有30fps,所以你的循环每秒运行30次。你的敌人现在需要移动每个环的1/30平方。那么它最终会每秒移动一个完整的正方形。

+0

谢谢,但我该如何计算时间?我怎么知道敌人什么时候需要移动?我试着用'timer',但它看起来不好,因为它不准确。 – Luis

+1

要开始非常简单,您可以在每个循环中使用'DateTime.Now'并查找它们之间的时间间隔。每个敌人都有一个速度,你需要将速度加到每一帧的位置上。如果速度是以每秒块为单位测量的,则需要确保只将速度的一小部分添加到当前位置,因为只经过了几分之一秒。你的敌人的速度是什么,是你的设计决定。 – nvoigt

+1

我知道这真的很旧,但我强烈建议使用'DateTime.UtcNow'作为'DateTime.Now'很贵。既然你只需要计算已经过去的时间,你可以使用'UtcNow',它不做任何时区偏移数学来确定返回的'DateTime'需要在哪个时区。对于沿着这些行的东西,位更有效率。 –

0

定时器背后的一般前提是重复一些代码每n。

为了创建这个计时器使用:

System.Timers.Timer aTimer = new System.Timers.Timer(); 
     aTimer.Elapsed+=new ElapsedEventHandler(OnTimedEvent); 
     // Set the Interval to 1 millisecond. Note: Time is set in Milliseconds 
     aTimer.Interval=1; 
     aTimer.Enabled=true; 

然后你实现这个方法:

private static void OnTimedEvent(object source, ElapsedEventArgs e) 
    { 
     //Whatever you need repeated 
    } 

完整的例子可以在这里找到: http://msdn.microsoft.com/en-us/library/system.timers.timer(v=vs.71).aspx