Fix translucent blocks, fix clipboard crashing the client.

This commit is contained in:
UnknownShadow200 2015-09-30 13:49:37 +10:00
parent 9e9a739932
commit 0979c0597e
18 changed files with 223 additions and 44 deletions

View File

@ -3,10 +3,11 @@ using System.Collections.Generic;
using System.Drawing; using System.Drawing;
using System.Drawing.Drawing2D; using System.Drawing.Drawing2D;
using System.Drawing.Text; using System.Drawing.Text;
using ClassicalSharp.GraphicsAPI;
namespace ClassicalSharp { namespace ClassicalSharp {
public sealed class GdiDrawer2D : IDrawer2D { public sealed class GdiPlusDrawer2D : IDrawer2D {
StringFormat format; StringFormat format;
Bitmap measuringBmp; Bitmap measuringBmp;
@ -15,8 +16,8 @@ namespace ClassicalSharp {
Graphics g; Graphics g;
public GdiDrawer2D( Game game ) { public GdiPlusDrawer2D( IGraphicsApi graphics ) {
graphics = game.Graphics; this.graphics = graphics;
format = StringFormat.GenericTypographic; format = StringFormat.GenericTypographic;
format.FormatFlags |= StringFormatFlags.MeasureTrailingSpaces; format.FormatFlags |= StringFormatFlags.MeasureTrailingSpaces;
format.Trimming = StringTrimming.None; format.Trimming = StringTrimming.None;
@ -64,11 +65,11 @@ namespace ClassicalSharp {
g.DrawRectangle( pen, x, y, width, height ); g.DrawRectangle( pen, x, y, width, height );
} }
public override void DrawRoundedRect( Color colour, float x, float y, float width, float height ) { public override void DrawRoundedRect( Color colour, float radius, float x, float y, float width, float height ) {
GraphicsPath path = new GraphicsPath(); GraphicsPath path = new GraphicsPath();
float x1 = x, y1 = y, x2 = x + width, y2 = y + height; float x1 = x, y1 = y, x2 = x + width, y2 = y + height;
const float r = 3, dia = r * 2; float r = radius, dia = radius * 2;
path.AddArc( x1, y1, dia, dia, 180, 90 ); path.AddArc( x1, y1, dia, dia, 180, 90 );
path.AddLine( x1 + r, y1, x2 - r, y1 ); path.AddLine( x1 + r, y1, x2 - r, y1 );
path.AddArc( x2 - dia, y1, dia, dia, 270, 90 ); path.AddArc( x2 - dia, y1, dia, dia, 270, 90 );

View File

@ -19,7 +19,7 @@ namespace ClassicalSharp {
public abstract void DrawRectBounds( Color colour, float lineWidth, int x, int y, int width, int height ); public abstract void DrawRectBounds( Color colour, float lineWidth, int x, int y, int width, int height );
public abstract void DrawRoundedRect( Color colour, float x, float y, float width, float height ); public abstract void DrawRoundedRect( Color colour, float radius, float x, float y, float width, float height );
/// <summary> Disposes of any resources used by this class that are associated with the underlying bitmap. </summary> /// <summary> Disposes of any resources used by this class that are associated with the underlying bitmap. </summary>
public abstract void Dispose(); public abstract void Dispose();

View File

@ -230,7 +230,8 @@ namespace ClassicalSharp {
} }
public override bool HandlesKeyDown( Key key ) { public override bool HandlesKeyDown( Key key ) {
if( key == game.Keys[KeyMapping.PauseOrExit] ) { if( key == game.Keys[KeyMapping.PauseOrExit] ||
key == game.Keys[KeyMapping.OpenInventory] ) {
game.SetNewScreen( new NormalScreen( game ) ); game.SetNewScreen( new NormalScreen( game ) );
} }
return true; return true;

View File

@ -66,7 +66,6 @@ namespace ClassicalSharp {
public override void Init() { public override void Init() {
playerFont = new Font( "Arial", 12 ); playerFont = new Font( "Arial", 12 );
chat = new ChatScreen( game ); chat = new ChatScreen( game );
chat.game = game;
const int blockSize = 32; const int blockSize = 32;
chat.ChatLogYOffset = blockSize + blockSize; chat.ChatLogYOffset = blockSize + blockSize;
chat.ChatInputYOffset = blockSize + blockSize / 2; chat.ChatInputYOffset = blockSize + blockSize / 2;

View File

@ -6,7 +6,7 @@ namespace ClassicalSharp {
public abstract class Screen : IDisposable { public abstract class Screen : IDisposable {
protected internal Game game; protected Game game;
protected IGraphicsApi graphicsApi; protected IGraphicsApi graphicsApi;
public Screen( Game game ) { public Screen( Game game ) {

View File

@ -93,8 +93,8 @@ namespace ClassicalSharp {
using( Bitmap bmp = IDrawer2D.CreatePow2Bitmap( size ) ) { using( Bitmap bmp = IDrawer2D.CreatePow2Bitmap( size ) ) {
using( IDrawer2D drawer = game.Drawer2D ) { using( IDrawer2D drawer = game.Drawer2D ) {
drawer.SetBitmap( bmp ); drawer.SetBitmap( bmp );
drawer.DrawRoundedRect( shadowCol, 1.3f, 1.3f, baseSize.Width, baseSize.Height ); drawer.DrawRoundedRect( shadowCol, 3, 1.3f, 1.3f, baseSize.Width, baseSize.Height );
drawer.DrawRoundedRect( boxCol, 0, 0, baseSize.Width, baseSize.Height ); drawer.DrawRoundedRect( boxCol, 3, 0, 0, baseSize.Width, baseSize.Height );
DrawTextArgs args = new DrawTextArgs( text, true ); DrawTextArgs args = new DrawTextArgs( text, true );
args.SkipPartsCheck = true; args.SkipPartsCheck = true;

View File

@ -221,6 +221,7 @@ namespace ClassicalSharp {
} else { } else {
chatInputText.Append( caretPos, text ); chatInputText.Append( caretPos, text );
caretPos += text.Length; caretPos += text.Length;
if( caretPos >= chatInputText.Length ) caretPos = -1;
} }
Dispose(); Dispose();
Init(); Init();

View File

@ -66,7 +66,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="2D\Drawing\DrawTextArgs.cs" /> <Compile Include="2D\Drawing\DrawTextArgs.cs" />
<Compile Include="2D\Drawing\GdiDrawer2D.cs" /> <Compile Include="2D\Drawing\GdiPlusDrawer2D.cs" />
<Compile Include="2D\Drawing\IDrawer2D.cs" /> <Compile Include="2D\Drawing\IDrawer2D.cs" />
<Compile Include="2D\Screens\BlockSelectScreen.cs" /> <Compile Include="2D\Screens\BlockSelectScreen.cs" />
<Compile Include="2D\Screens\ChatScreen.cs" /> <Compile Include="2D\Screens\ChatScreen.cs" />

View File

@ -10,6 +10,7 @@ namespace ClassicalSharp {
protected IGraphicsApi api; protected IGraphicsApi api;
protected Texture nameTex; protected Texture nameTex;
protected internal int PlayerTextureId = -1, MobTextureId = -1; protected internal int PlayerTextureId = -1, MobTextureId = -1;
internal bool RenderHat = true;
public override void Despawn() { public override void Despawn() {
if( api == null ) return; if( api == null ) return;

View File

@ -99,7 +99,7 @@ namespace ClassicalSharp {
Utils.LogWarning( "Unable to load options.txt" ); Utils.LogWarning( "Unable to load options.txt" );
} }
Keys = new KeyMap(); Keys = new KeyMap();
Drawer2D = new GdiDrawer2D( this ); Drawer2D = new GdiPlusDrawer2D( Graphics );
ViewDistance = Options.GetInt( "viewdist", 16, 8192, 512 ); ViewDistance = Options.GetInt( "viewdist", 16, 8192, 512 );
defaultIb = Graphics.MakeDefaultIb(); defaultIb = Graphics.MakeDefaultIb();
ModelCache = new ModelCache( this ); ModelCache = new ModelCache( this );
@ -129,6 +129,8 @@ namespace ClassicalSharp {
} else { } else {
Network = new NetworkProcessor( this ); Network = new NetworkProcessor( this );
} }
Graphics.LostContextFunction = Network.Tick;
firstPersonCam = new FirstPersonCamera( this ); firstPersonCam = new FirstPersonCamera( this );
thirdPersonCam = new ThirdPersonCamera( this ); thirdPersonCam = new ThirdPersonCamera( this );
Camera = firstPersonCam; Camera = firstPersonCam;
@ -290,17 +292,14 @@ namespace ClassicalSharp {
Screen activeScreen; Screen activeScreen;
public void SetNewScreen( Screen screen ) { public void SetNewScreen( Screen screen ) {
if( activeScreen != null ) { if( activeScreen != null )
activeScreen.Dispose(); activeScreen.Dispose();
}
if( activeScreen != null && activeScreen.HandlesAllInput ) if( activeScreen != null && activeScreen.HandlesAllInput )
lastClick = DateTime.UtcNow; lastClick = DateTime.UtcNow;
activeScreen = screen; activeScreen = screen;
if( screen != null ) { if( screen != null )
screen.game = this;
screen.Init(); screen.Init();
}
if( Network.UsingPlayerClick ) { if( Network.UsingPlayerClick ) {
byte targetId = Players.GetClosetPlayer( this ); byte targetId = Players.GetClosetPlayer( this );
ButtonStateChanged( MouseButton.Left, false, targetId ); ButtonStateChanged( MouseButton.Left, false, targetId );

View File

@ -3,10 +3,10 @@ using System;
using System.Drawing; using System.Drawing;
using System.Drawing.Imaging; using System.Drawing.Imaging;
using System.Threading; using System.Threading;
using OpenTK;
using SharpDX; using SharpDX;
using SharpDX.Direct3D9; using SharpDX.Direct3D9;
using D3D = SharpDX.Direct3D9; using D3D = SharpDX.Direct3D9;
using Matrix4 = OpenTK.Matrix4;
using WinWindowInfo = OpenTK.Platform.Windows.WinWindowInfo; using WinWindowInfo = OpenTK.Platform.Windows.WinWindowInfo;
namespace ClassicalSharp.GraphicsAPI { namespace ClassicalSharp.GraphicsAPI {
@ -395,11 +395,11 @@ namespace ClassicalSharp.GraphicsAPI {
#endregion #endregion
public override void BeginFrame( Game game ) { public override void BeginFrame( GameWindow game ) {
device.BeginScene(); device.BeginScene();
} }
public override void EndFrame( Game game ) { public override void EndFrame( GameWindow game ) {
device.EndScene(); device.EndScene();
int code = device.Present(); int code = device.Present();
if( code >= 0 ) return; if( code >= 0 ) return;
@ -417,22 +417,22 @@ namespace ClassicalSharp.GraphicsAPI {
RecreateDevice( game ); RecreateDevice( game );
break; break;
} }
game.Network.Tick( 1 / 20.0 ); LostContextFunction( 1 / 20.0 );
} }
} }
bool vsync = false; bool vsync = false;
public override void SetVSync( Game game, bool value ) { public override void SetVSync( GameWindow game, bool value ) {
vsync = value; vsync = value;
game.VSync = value; game.VSync = value;
RecreateDevice( game ); RecreateDevice( game );
} }
public override void OnWindowResize( Game game ) { public override void OnWindowResize( GameWindow game ) {
RecreateDevice( game ); RecreateDevice( game );
} }
void RecreateDevice( Game game ) { void RecreateDevice( GameWindow game ) {
PresentParameters args = GetPresentArgs( game.Width, game.Height ); PresentParameters args = GetPresentArgs( game.Width, game.Height );
for( int i = 0; i < dynamicvBuffers.Length; i++ ) { for( int i = 0; i < dynamicvBuffers.Length; i++ ) {
DynamicDataBuffer buffer = dynamicvBuffers[i]; DynamicDataBuffer buffer = dynamicvBuffers[i];

View File

@ -172,13 +172,15 @@ namespace ClassicalSharp.GraphicsAPI {
Console.ResetColor(); Console.ResetColor();
} }
public abstract void BeginFrame( Game game ); public abstract void BeginFrame( GameWindow game );
public abstract void EndFrame( Game game ); public abstract void EndFrame( GameWindow game );
public abstract void SetVSync( Game game, bool value ); public abstract void SetVSync( GameWindow game, bool value );
public abstract void OnWindowResize( Game game ); public abstract void OnWindowResize( GameWindow game );
public Action<double> LostContextFunction;
protected void InitDynamicBuffers() { protected void InitDynamicBuffers() {
quadVb = CreateDynamicVb( VertexFormat.Pos3fCol4b, 4 ); quadVb = CreateDynamicVb( VertexFormat.Pos3fCol4b, 4 );

View File

@ -353,14 +353,14 @@ namespace ClassicalSharp.GraphicsAPI {
#endregion #endregion
public override void BeginFrame( Game game ) { public override void BeginFrame( GameWindow game ) {
} }
public override void EndFrame( Game game ) { public override void EndFrame( GameWindow game ) {
game.SwapBuffers(); game.SwapBuffers();
} }
public override void SetVSync( Game game, bool value ) { public override void SetVSync( GameWindow game, bool value ) {
game.VSync = value; game.VSync = value;
} }

View File

@ -89,12 +89,13 @@ namespace ClassicalSharp.Model {
DrawRotate( 0, 12/16f, 0, p.rightLegXRot, 0, 0, model.RightLeg ); DrawRotate( 0, 12/16f, 0, p.rightLegXRot, 0, 0, model.RightLeg );
DrawRotate( -6/16f, 22/16f, 0, p.leftArmXRot, 0, p.leftArmZRot, model.LeftArm ); DrawRotate( -6/16f, 22/16f, 0, p.leftArmXRot, 0, p.leftArmZRot, model.LeftArm );
DrawRotate( 6/16f, 22/16f, 0, p.rightArmXRot, 0, p.rightArmZRot, model.RightArm ); DrawRotate( 6/16f, 22/16f, 0, p.rightArmXRot, 0, p.rightArmZRot, model.RightArm );
graphics.AlphaTest = true; if( p.RenderHat ) {
DrawRotate( 0, 23.5f/16f, 0, -p.PitchRadians, 0, 0, model.Hat ); graphics.AlphaTest = true;
DrawRotate( 0, 23.5f/16f, 0, -p.PitchRadians, 0, 0, model.Hat );
}
} }
class ModelSet { class ModelSet {
public ModelPart Head, Torso, LeftLeg, RightLeg, LeftArm, RightArm, Hat; public ModelPart Head, Torso, LeftLeg, RightLeg, LeftArm, RightArm, Hat;
} }
} }

View File

@ -21,7 +21,7 @@ namespace ClassicalSharp {
if( part.IndicesCount > maxIndices ) { if( part.IndicesCount > maxIndices ) {
DrawBigPart( info, ref part ); DrawBigPart( info, ref part );
} else { } else {
DrawPart( info, ref part, true ); DrawPart( info, ref part );
} }
if( part.spriteCount > 0 ) if( part.spriteCount > 0 )
@ -37,7 +37,7 @@ namespace ClassicalSharp {
ChunkPartInfo part = info.TranslucentParts[batch]; ChunkPartInfo part = info.TranslucentParts[batch];
if( part.IndicesCount == 0 ) continue; if( part.IndicesCount == 0 ) continue;
DrawPart( info, ref part, false ); DrawTranslucentPart( info, ref part );
game.Vertices += part.IndicesCount; game.Vertices += part.IndicesCount;
} }
} }
@ -49,11 +49,11 @@ namespace ClassicalSharp {
ChunkPartInfo part = info.TranslucentParts[batch]; ChunkPartInfo part = info.TranslucentParts[batch];
if( part.IndicesCount == 0 ) continue; if( part.IndicesCount == 0 ) continue;
DrawPart( info, ref part, false ); DrawTranslucentPart( info, ref part );
} }
} }
void DrawPart( ChunkInfo info, ref ChunkPartInfo part, bool faceCulling ) { void DrawPart( ChunkInfo info, ref ChunkPartInfo part ) {
api.BindVb( part.VbId ); api.BindVb( part.VbId );
bool drawLeft = info.DrawLeft && part.leftCount > 0; bool drawLeft = info.DrawLeft && part.leftCount > 0;
bool drawRight = info.DrawRight && part.rightCount > 0; bool drawRight = info.DrawRight && part.rightCount > 0;
@ -63,7 +63,7 @@ namespace ClassicalSharp {
bool drawBack = info.DrawBack && part.backCount > 0; bool drawBack = info.DrawBack && part.backCount > 0;
if( drawLeft && drawRight ) { if( drawLeft && drawRight ) {
api.FaceCulling = faceCulling; api.FaceCulling = true;
api.DrawIndexedVb_TrisT2fC4b( part.leftCount + part.rightCount, part.leftIndex ); api.DrawIndexedVb_TrisT2fC4b( part.leftCount + part.rightCount, part.leftIndex );
api.FaceCulling = false; api.FaceCulling = false;
} else if( drawLeft ) { } else if( drawLeft ) {
@ -73,7 +73,7 @@ namespace ClassicalSharp {
} }
if( drawFront && drawBack ) { if( drawFront && drawBack ) {
api.FaceCulling = faceCulling; api.FaceCulling = true;
api.DrawIndexedVb_TrisT2fC4b( part.frontCount + part.backCount, part.frontIndex ); api.DrawIndexedVb_TrisT2fC4b( part.frontCount + part.backCount, part.frontIndex );
api.FaceCulling = false; api.FaceCulling = false;
} else if( drawFront ) { } else if( drawFront ) {
@ -83,7 +83,7 @@ namespace ClassicalSharp {
} }
if( drawBottom && drawTop ) { if( drawBottom && drawTop ) {
api.FaceCulling = faceCulling; api.FaceCulling = true;
api.DrawIndexedVb_TrisT2fC4b( part.bottomCount + part.topCount, part.bottomIndex ); api.DrawIndexedVb_TrisT2fC4b( part.bottomCount + part.topCount, part.bottomIndex );
api.FaceCulling = false; api.FaceCulling = false;
} else if( drawBottom ) { } else if( drawBottom ) {
@ -93,6 +93,41 @@ namespace ClassicalSharp {
} }
} }
bool drawAllFaces = false;
void DrawTranslucentPart( ChunkInfo info, ref ChunkPartInfo part ) {
api.BindVb( part.VbId );
bool drawLeft = (drawAllFaces || info.DrawLeft) && part.leftCount > 0;
bool drawRight = (drawAllFaces || info.DrawRight) && part.rightCount > 0;
bool drawBottom = (drawAllFaces || info.DrawBottom) && part.bottomCount > 0;
bool drawTop = (drawAllFaces || info.DrawTop) && part.topCount > 0;
bool drawFront = (drawAllFaces || info.DrawFront) && part.frontCount > 0;
bool drawBack = (drawAllFaces || info.DrawBack) && part.backCount > 0;
if( drawLeft && drawRight ) {
api.DrawIndexedVb_TrisT2fC4b( part.leftCount + part.rightCount, part.leftIndex );
} else if( drawLeft ) {
api.DrawIndexedVb_TrisT2fC4b( part.leftCount, part.leftIndex );
} else if( drawRight ) {
api.DrawIndexedVb_TrisT2fC4b( part.rightCount, part.rightIndex );
}
if( drawFront && drawBack ) {
api.DrawIndexedVb_TrisT2fC4b( part.frontCount + part.backCount, part.frontIndex );
} else if( drawFront ) {
api.DrawIndexedVb_TrisT2fC4b( part.frontCount, part.frontIndex );
} else if( drawBack ) {
api.DrawIndexedVb_TrisT2fC4b( part.backCount, part.backIndex );
}
if( drawBottom && drawTop ) {
api.DrawIndexedVb_TrisT2fC4b( part.bottomCount + part.topCount, part.bottomIndex );
} else if( drawBottom ) {
api.DrawIndexedVb_TrisT2fC4b( part.bottomCount, part.bottomIndex );
} else if( drawTop ) {
api.DrawIndexedVb_TrisT2fC4b( part.topCount, part.topIndex );
}
}
void DrawBigPart( ChunkInfo info, ref ChunkPartInfo part ) { void DrawBigPart( ChunkInfo info, ref ChunkPartInfo part ) {
api.BindVb( part.VbId ); api.BindVb( part.VbId );
bool drawLeft = info.DrawLeft && part.leftCount > 0; bool drawLeft = info.DrawLeft && part.leftCount > 0;

View File

@ -275,6 +275,8 @@ namespace ClassicalSharp {
// Render translucent(liquid) blocks. These 'blend' into other blocks. // Render translucent(liquid) blocks. These 'blend' into other blocks.
void RenderTranslucent() { void RenderTranslucent() {
Block block = game.LocalPlayer.BlockAtHead;
drawAllFaces = block == Block.Water || block == Block.StillWater;
// First fill depth buffer // First fill depth buffer
int[] texIds = game.TerrainAtlas1D.TexIds; int[] texIds = game.TerrainAtlas1D.TexIds;
api.BeginVbBatch( VertexFormat.Pos3fTex2fCol4b ); api.BeginVbBatch( VertexFormat.Pos3fTex2fCol4b );

View File

@ -3,7 +3,7 @@ using System.Reflection;
namespace ClassicalSharp { namespace ClassicalSharp {
internal sealed unsafe class StringBuffer { public sealed unsafe class StringBuffer {
internal string value; internal string value;
internal int capacity; internal int capacity;

137
Launcher2/Game.cs Normal file
View File

@ -0,0 +1,137 @@
using System;
using ClassicalSharp;
using ClassicalSharp.GraphicsAPI;
using OpenTK;
using System.Drawing;
namespace Launcher2 {
public partial class Game : GameWindow {
public IGraphicsApi Graphics;
FpsScreen fpsScreen;
public IDrawer2D Drawer2D;
protected override void OnLoad( EventArgs e ) {
#if !USE_DX
//Graphics = new OpenGLApi();
#else
Graphics = new Direct3D9Api( this );
#endif
Graphics.SetVSync( this, true );
Graphics.DepthTest = true;
Graphics.DepthTestFunc( CompareFunc.LessEqual );
Graphics.AlphaBlendFunc( BlendFunc.SourceAlpha, BlendFunc.InvSourceAlpha );
Graphics.AlphaTestFunc( CompareFunc.Greater, 0.5f );
Title = Utils.AppName;
Width = width;
Height = height;
fpsScreen = new FpsScreen( Graphics );
fpsScreen.Init();
}
int width, height;
protected override void OnRenderFrame( FrameEventArgs e ) {
Graphics.BeginFrame( this );
Graphics.Clear();
Graphics.Mode2D( Width, Height );
fpsScreen.Render( e.Time );
if( activeScreen != null ) {
activeScreen.Render( e.Time );
}
Graphics.Mode3D();
Graphics.EndFrame( this );
}
protected override void OnResize( EventArgs e ) {
base.OnResize( e );
Graphics.OnWindowResize( this );
if( activeScreen != null ) {
activeScreen.OnResize( width, height, Width, Height );
}
width = Width;
height = Height;
}
Screen activeScreen;
public void SetNewScreen( Screen screen ) {
if( activeScreen != null ) {
activeScreen.Dispose();
}
activeScreen = screen;
if( screen != null ) {
screen.Init();
}
}
public override void Dispose() {
if( activeScreen != null ) {
activeScreen.Dispose();
}
Graphics.Dispose();
Drawer2D.DisposeInstance();
base.Dispose();
}
}
public class FpsScreen : Screen {
readonly Font font;
StringBuffer text;
public FpsScreen( IGraphicsApi gfx ) : base( gfx ) {
font = new Font( "Arial", 13 );
text = new StringBuffer( 96 );
}
TextWidget fpsTextWidget;
public override void Render( double delta ) {
UpdateFPS( delta );
if( game.HideGui ) return;
graphicsApi.Texturing = true;
fpsTextWidget.Render( delta );
graphicsApi.Texturing = false;
}
double accumulator, maxDelta;
int fpsCount;
unsafe void UpdateFPS( double delta ) {
fpsCount++;
maxDelta = Math.Max( maxDelta, delta );
accumulator += delta;
if( accumulator >= 1 ) {
fixed( char* ptr = text.value ) {
char* ptr2 = ptr;
text.Clear( ptr2 )
.Append( ref ptr2, "FPS: " ).AppendNum( ref ptr2, (int)( fpsCount / accumulator ) )
.Append( ref ptr2, " (min " ).AppendNum( ref ptr2, (int)( 1f / maxDelta ) )
.Append( ref ptr2, "), chunks/s: " ).AppendNum( ref ptr2, game.ChunkUpdates )
.Append( ref ptr2, ", vertices: " ).AppendNum( ref ptr2, game.Vertices );
}
string textString = text.GetString();
fpsTextWidget.SetText( textString );
maxDelta = 0;
accumulator = 0;
fpsCount = 0;
game.ChunkUpdates = 0;
}
}
public override void Init() {
fpsTextWidget = new TextWidget( game, font );
fpsTextWidget.Init();
fpsTextWidget.SetText( "FPS: no data yet" );
}
public override void Dispose() {
font.Dispose();
fpsTextWidget.Dispose();
}
}
}