MonoGame笔记(九)其他几个时间相关程序设计

这里介绍其他几个和时间相关的程序设计: 1. 调整单个动画的速度 2.显示帧率(FPS) 3.定时器

调整单个动画的速度

调整游戏本身的帧率可以影响动画的速度, 但这样的影响是全局的. 不同动画之间的速度是不一样的, 所以需要单个调节. 以下是Learn XNA 4.0中的相关代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int timeSinceLastFrame = 0; //自上一帧之后经过了多少时间。
int millisecondsPerFrame = 50 //动画播放的帧率
timeSinceLastFrame += gameTime.ElapsedGameTime.Milliseconds;
if (timeSinceLastFrame > millisecondsPerFrame)
{
timeSinceLastFrame-= millisecondsPerFrame;
++currentFrame.X;
if (currentFrame.X >= sheetSize.X) //spritesheet
{
currentFrame.X = 0;
++currentFrame.Y;
if (currentFrame.Y >= sheetSize.Y)
currentFrame.Y = 0;
}
}

显示帧率FPS

来自上一篇笔记中提到作者的文章Displaying the framerate https://blogs.msdn.microsoft.com/shawnhar/2007/06/08/displaying-the-framerate/
技巧和调整单个动画的速度一样, 这里作者使用1秒钟Draw调用的次数来作为帧率

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
public class FrameRateCounter : DrawableGameComponent
{
ContentManager content;
SpriteBatch spriteBatch;
SpriteFont spriteFont;

int frameRate = 0;
int frameCounter = 0;
TimeSpan elapsedTime = TimeSpan.Zero;


public FrameRateCounter(Game game): base(game)
{
content = new ContentManager(game.Services);
}

protected override void LoadGraphicsContent(bool loadAllContent)
{
if (loadAllContent)
{
spriteBatch = new SpriteBatch(GraphicsDevice);
spriteFont = content.Load<SpriteFont>("Font");
}
}

protected override void UnloadGraphicsContent(bool unloadAllContent)
{
if (unloadAllContent)
content.Unload();
}


public override void Update(GameTime gameTime)
{
elapsedTime += gameTime.ElapsedGameTime;

if (elapsedTime > TimeSpan.FromSeconds(1))//elapsedTime大于1秒
{
elapsedTime -= TimeSpan.FromSeconds(1);
frameRate = frameCounter;
frameCounter = 0;
}
}

public override void Draw(GameTime gameTime)
{
frameCounter++;

string fps = string.Format("fps: {0}", frameRate);

spriteBatch.Begin();

spriteBatch.DrawString(spriteFont, fps, new Vector2(33, 33), Color.Black);
spriteBatch.DrawString(spriteFont, fps, new Vector2(32, 32), Color.White);

spriteBatch.End();
}
}

使用方式:在Game的构造方法中加入下面一行, 关于Component和SpriteFont见以后的笔记
Components.Add(new FrameRateCounter(this));

作者还使用了SpriteFont来显示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?xml version="1.0" encoding="utf-8"?>
<XnaContent xmlns:Graphics="Microsoft.Xna.Framework.Content.Pipeline.Graphics">
<Asset Type="Graphics:FontDescription">
<FontName>Arial</FontName>
<Size>14</Size>
<Spacing>2</Spacing>
<Style>Regular</Style>
<CharacterRegions>
<CharacterRegion><Start>f</Start><End>f</End></CharacterRegion>
<CharacterRegion><Start>p</Start><End>p</End></CharacterRegion>
<CharacterRegion><Start>s</Start><End>s</End></CharacterRegion>
<CharacterRegion><Start>:</Start><End>:</End></CharacterRegion>
<CharacterRegion><Start> </Start><End> </End></CharacterRegion>
<CharacterRegion><Start>0</Start><End>9</End></CharacterRegion>
</CharacterRegions>
</Asset>
</XnaContent>

定时器

https://www.gamedev.net/forums/topic/473544-how-to-make-a-timer-using-xna/

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public class TimerComponent : GameComponent
{
TimeSpan interval = new TimeSpan(0, 0, 1);
TimeSpan lastTick = new TimeSpan();

public event EventHandler Tick;

public TimeSpan Interval
{
get { return interval; }
set { interval = value; }
}

public TimerComponent(Game game)
: base(game)
{
}

public override void Update(GameTime gameTime)
{
if (gameTime.TotalGameTime - lastTick >= interval)
{
if (Tick != null)
Tick(this, null);

lastTick = gameTime.TotalGameTime;
}
}
}

或者可以试下.NET自带的Timer