Refactor 2D text drawing to be simpler. Refactor IModel class - use the player argument directly, rather than copying them to fields for every different model. Move LocationUpdate structure into its own file.

This commit is contained in:
UnknownShadow200 2015-07-05 19:59:26 +10:00
parent 43a7e35d64
commit fa30faf812
29 changed files with 257 additions and 309 deletions

View File

@ -17,6 +17,10 @@ namespace ClassicalSharp {
this( graphics, text, col, useShadow, Color.Black ) {
}
public DrawTextArgs( IGraphicsApi graphics, string text, bool useShadow ) :
this( graphics, text, Color.White, useShadow, Color.Black ) {
}
public DrawTextArgs( IGraphicsApi graphics, string text, Color col, bool useShadow, Color shadowCol ) {
Graphics = graphics;
Text = text;

View File

@ -130,15 +130,15 @@ namespace ClassicalSharp {
Block block = blocksTable[selectedIndex].BlockId;
UpdateBlockInfoString( block );
List<DrawTextArgs> parts = Utils2D.SplitText( GraphicsApi, buffer.value, true );
Size size = Utils2D.MeasureSize( parts, font, true );
Size size = Utils2D.MeasureSize( buffer.value, font, true );
int x = startX + ( blockSize * blocksPerRow ) / 2 - size.Width / 2;
int y = startY - size.Height;
using( Bitmap bmp = Utils2D.CreatePow2Bitmap( size ) ) {
using( Graphics g = Graphics.FromImage( bmp ) ) {
Utils2D.DrawRect( g, backColour, 0, 0, bmp.Width, bmp.Height );
Utils2D.DrawText( g, parts, font, 0, 0 );
DrawTextArgs args = new DrawTextArgs( GraphicsApi, buffer.value, true );
Utils2D.DrawText( g, font, ref args, 0, 0 );
}
blockInfoTexture = Utils2D.Make2DTexture( GraphicsApi, bmp, size, x, y );
}

View File

@ -13,7 +13,7 @@ namespace ClassicalSharp {
public int ChatInputYOffset, ChatLogYOffset;
public bool HistoryMode;
const int chatLines = 12;
Texture announcementTexture;
Texture announcementTex;
TextInputWidget textInput;
TextGroupWidget status, bottomRight, normalChat;
bool suppressNextPress = true;
@ -28,15 +28,15 @@ namespace ClassicalSharp {
normalChat.Render( delta );
status.Render( delta );
bottomRight.Render( delta );
if( announcementTexture.IsValid ) {
announcementTexture.Render( GraphicsApi );
if( announcementTex.IsValid ) {
announcementTex.Render( GraphicsApi );
}
if( HandlesAllInput ) {
textInput.Render( delta );
}
if( Window.Announcement != null && ( DateTime.UtcNow - announcementDisplayTime ).TotalSeconds > 5 ) {
Window.Announcement = null;
GraphicsApi.DeleteTexture( ref announcementTexture );
GraphicsApi.DeleteTexture( ref announcementTex );
}
if( HistoryMode ) {
pageTexture.Render( GraphicsApi );
@ -109,13 +109,13 @@ namespace ClassicalSharp {
status.Dispose();
bottomRight.Dispose();
GraphicsApi.DeleteTexture( ref pageTexture );
GraphicsApi.DeleteTexture( ref announcementTexture );
GraphicsApi.DeleteTexture( ref announcementTex );
Window.ChatReceived -= ChatReceived;
}
public override void OnResize( int oldWidth, int oldHeight, int width, int height ) {
announcementTexture.X1 += ( width - oldWidth ) / 2;
announcementTexture.Y1 += ( height - oldHeight ) / 2;
announcementTex.X1 += ( width - oldWidth ) / 2;
announcementTex.Y1 += ( height - oldHeight ) / 2;
pageTexture.Y1 += height - oldHeight;
textInput.OnResize( oldWidth, oldHeight, width, height );
status.OnResize( oldWidth, oldHeight, width, height );
@ -141,15 +141,10 @@ namespace ClassicalSharp {
void UpdateAnnouncement( string text ) {
announcementDisplayTime = DateTime.UtcNow;
if( !String.IsNullOrEmpty( text ) ) {
List<DrawTextArgs> parts = Utils2D.SplitText( GraphicsApi, text, true );
Size size = Utils2D.MeasureSize( parts, announcementFont, true );
int x = Window.Width / 2 - size.Width / 2;
int y = Window.Height / 4 - size.Height / 2;
announcementTexture = Utils2D.MakeTextTexture( parts, announcementFont, size, x, y );
} else {
announcementTexture = new Texture( -1, 0, 0, 0, 0, 0, 0 );
}
DrawTextArgs args = new DrawTextArgs( GraphicsApi, text, true );
announcementTex = Utils2D.MakeTextTexture( announcementFont, 0, 0, ref args );
announcementTex.X1 = Window.Width / 2 - announcementTex.Width / 2;
announcementTex.Y1 = Window.Height / 4 - announcementTex.Height / 2;
}
void UpdateChat( string text ) {

View File

@ -37,9 +37,9 @@ namespace ClassicalSharp {
keyStatusFont = new Font( "Arial", 13, FontStyle.Italic );
textFont = new Font( "Arial", 14, FontStyle.Bold );
controlsWidget = TextWidget.Create( Window, 0, 30, "&eControls list", Docking.Centre, Docking.LeftOrTop, titleFont );
keyStatusWidget = TextWidget.Create( Window, 0, -80, "", Docking.Centre, Docking.BottomOrRight, keyStatusFont );
gameWidget = TextWidget.Create( Window, 0, -50, "&eBack to game", Docking.Centre, Docking.BottomOrRight, titleFont );
exitWidget = TextWidget.Create( Window, 0, -10, "&eExit", Docking.Centre, Docking.BottomOrRight, titleFont );
keyStatusWidget = TextWidget.Create( Window, 0, 80, "", Docking.Centre, Docking.BottomOrRight, keyStatusFont );
gameWidget = TextWidget.Create( Window, 0, 50, "&eBack to game", Docking.Centre, Docking.BottomOrRight, titleFont );
exitWidget = TextWidget.Create( Window, 0, 10, "&eExit", Docking.Centre, Docking.BottomOrRight, titleFont );
string[] descriptionsLeft = { "Forward", "Back", "Left", "Right", "Jump", "Respawn", "Set spawn",
"Open chat", "Send chat", "Pause", "Open inventory" };

View File

@ -45,22 +45,15 @@ namespace ClassicalSharp {
const float shadowOffset = 1.3f;
public static Size MeasureSize( string text, Font font, bool shadow ) {
SizeF size = measuringGraphics.MeasureString( text, font, Int32.MaxValue, format );
if( shadow ) {
size.Width += shadowOffset;
size.Height += shadowOffset;
}
return Size.Ceiling( size );
}
public static Size MeasureSize( List<DrawTextArgs> parts, Font font, bool shadow ) {
GetTextParts( text );
SizeF total = SizeF.Empty;
for( int i = 0; i < parts.Count; i++ ) {
SizeF size = measuringGraphics.MeasureString( parts[i].Text, font, Int32.MaxValue, format );
total.Height = Math.Max( total.Height, size.Height );
total.Width += size.Width;
}
if( shadow ) {
if( shadow && parts.Count > 0 ) {
total.Width += shadowOffset;
total.Height += shadowOffset;
}
@ -68,22 +61,23 @@ namespace ClassicalSharp {
}
public static void DrawText( Graphics g, Font font, ref DrawTextArgs args, float x, float y ) {
Brush textBrush = GetOrCreateBrush( args.TextColour );
Brush shadowBrush = GetOrCreateBrush( args.ShadowColour );
g.TextRenderingHint = TextRenderingHint.AntiAlias;
if( args.UseShadow ) {
g.DrawString( args.Text, font, shadowBrush, x + shadowOffset, y + shadowOffset, format );
}
g.DrawString( args.Text, font, textBrush, x, y, format );
GetTextParts( args.Text );
DrawTextNoCheck( g, font, ref args, x, y );
}
public static void DrawText( Graphics g, List<DrawTextArgs> parts, Font font, float x, float y ) {
private static void DrawTextNoCheck( Graphics g, Font font, ref DrawTextArgs args, float x, float y ) {
g.TextRenderingHint = TextRenderingHint.AntiAlias;
Brush shadowBrush = GetOrCreateBrush( args.ShadowColour );
for( int i = 0; i < parts.Count; i++ ) {
DrawTextArgs part = parts[i];
DrawText( g, font, ref part, x, y );
SizeF partSize = g.MeasureString( part.Text, font, Int32.MaxValue, format );
x += partSize.Width;
TextPart part = parts[i];
Brush textBrush = GetOrCreateBrush( part.TextColour );
if( args.UseShadow ) {
g.DrawString( part.Text, font, shadowBrush, x + shadowOffset, y + shadowOffset, format );
}
g.DrawString( part.Text, font, textBrush, x, y, format );
x += g.MeasureString( part.Text, font, Int32.MaxValue, format ).Width;
}
}
@ -100,27 +94,20 @@ namespace ClassicalSharp {
public static Texture MakeTextTexture( Font font, int x1, int y1, ref DrawTextArgs args ) {
Size size = MeasureSize( args.Text, font, args.UseShadow );
if( parts.Count == 0 )
return new Texture( -1, x1, y1, 0, 0, 1, 1 );
using( Bitmap bmp = CreatePow2Bitmap( size ) ) {
using( Graphics g = Graphics.FromImage( bmp ) ) {
DrawText( g, font, ref args, 0, 0 );
DrawTextNoCheck( g, font, ref args, 0, 0 );
}
return Make2DTexture( args.Graphics, bmp, size, x1, y1 );
}
}
public static Texture MakeTextTexture( List<DrawTextArgs> parts, Font font, Size size, int x1, int y1 ) {
if( parts.Count == 0 ) return new Texture( -1, x1, y1, 0, 0, 1, 1 );
using( Bitmap bmp = CreatePow2Bitmap( size ) ) {
using( Graphics g = Graphics.FromImage( bmp ) ) {
DrawText( g, parts, font, 0, 0 );
}
return Make2DTexture( parts[0].Graphics, bmp, size, x1, y1 );
}
}
public static Texture Make2DTexture( IGraphicsApi graphics, Bitmap bmp, Size used, int x1, int y1 ) {
int textureID = graphics.LoadTexture( bmp );
return new Texture( textureID, x1, y1, used.Width, used.Height,
int texId = graphics.LoadTexture( bmp );
return new Texture( texId, x1, y1, used.Width, used.Height,
(float)used.Width / bmp.Width, (float)used.Height / bmp.Height );
}
@ -132,36 +119,47 @@ namespace ClassicalSharp {
}
}
static Color[] colours = new Color[] {
Color.FromArgb( 0, 0, 0 ), // black
Color.FromArgb( 0, 0, 191 ), // dark blue
Color.FromArgb( 0, 191, 0 ), // dark green
Color.FromArgb( 0, 191, 191 ), // dark teal
Color.FromArgb( 191, 0, 0 ), // dark red
Color.FromArgb( 191, 0, 191 ), // purple
Color.FromArgb( 191, 191, 0 ), // gold
Color.FromArgb( 191, 191, 191 ), // gray
Color.FromArgb( 64, 64, 64 ), // dark gray
Color.FromArgb( 64, 64, 255 ), // blue
Color.FromArgb( 64, 255, 64 ), // lime
Color.FromArgb( 64, 255, 255 ), // teal
Color.FromArgb( 255, 64, 64 ), // red
Color.FromArgb( 255, 64, 255 ), // pink
Color.FromArgb( 255, 255, 64 ), // yellow
Color.FromArgb( 255, 255, 255 ), // white
};
static List<TextPart> parts = new List<TextPart>( 64 );
static Color white = Color.FromArgb( 255, 255, 255 );
struct TextPart {
public string Text;
public Color TextColour;
public TextPart( string text, Color col ) {
Text = text;
TextColour = col;
}
}
static void GetTextParts( string value ) {
if( String.Equals( value, lastSplitText ) ) {
return;
}
static List<DrawTextArgs> parts = new List<DrawTextArgs>( 64 );
public static List<DrawTextArgs> SplitText( IGraphicsApi graphics, string value, bool shadow ) {
int code = 0xF;
parts.Clear();
if( String.IsNullOrEmpty( value ) ) {
} else if( value.IndexOf( '&' ) == -1 ) {
parts.Add( new TextPart( value, white ) );
} else {
SplitText( value );
}
lastSplitText = value;
}
static string lastSplitText;
static void SplitText( string value ) {
int code = 0xF;
for( int i = 0; i < value.Length; i++ ) {
int nextAnd = value.IndexOf( '&', i );
int partLength = nextAnd == -1 ? value.Length - i : nextAnd - i;
if( partLength > 0 ) {
string part = value.Substring( i, partLength );
parts.Add( new DrawTextArgs( graphics, part, colours[code], shadow ) );
Color col = Color.FromArgb(
191 * ( ( code >> 2 ) & 0x1 ) + 64 * ( code >> 3 ),
191 * ( ( code >> 1 ) & 0x1 ) + 64 * ( code >> 3 ),
191 * ( ( code >> 0 ) & 0x1 ) + 64 * ( code >> 3 ) );
parts.Add( new TextPart( part, col ) );
}
i += partLength + 1;
@ -174,7 +172,6 @@ namespace ClassicalSharp {
}
}
}
return parts;
}
}
}

View File

@ -106,9 +106,8 @@ namespace ClassicalSharp {
}
void AddPlayerInfo( CpeListInfo player, int index ) {
List<DrawTextArgs> parts = Utils2D.SplitText( GraphicsApi, player.ListName, true );
Size size = Utils2D.MeasureSize( parts, font, true );
Texture tex = Utils2D.MakeTextTexture( parts, font, size, 0, 0 );
DrawTextArgs args = new DrawTextArgs( GraphicsApi, player.ListName, true );
Texture tex = Utils2D.MakeTextTexture( font, 0, 0, ref args );
if( index < 0 ) {
info[namesCount] = new PlayerInfo( player );
textures[namesCount] = tex;

View File

@ -50,9 +50,8 @@ namespace ClassicalSharp {
}
void AddPlayerInfo( Player player ) {
List<DrawTextArgs> parts = Utils2D.SplitText( GraphicsApi, player.DisplayName, true );
Size size = Utils2D.MeasureSize( parts, font, true );
Texture tex = Utils2D.MakeTextTexture( parts, font, size, 0, 0 );
DrawTextArgs args = new DrawTextArgs( GraphicsApi, player.DisplayName, true );
Texture tex = Utils2D.MakeTextTexture( font, 0, 0, ref args );
info[namesCount] = new PlayerInfo( player );
textures[namesCount] = tex;
namesCount++;

View File

@ -12,14 +12,12 @@ namespace ClassicalSharp {
}
Texture[] textures;
string[] textCache;
int ElementsCount, defaultHeight;
public int XOffset = 0, YOffset = 0;
readonly Font font;
public override void Init() {
textures = new Texture[ElementsCount];
textCache = new string[ElementsCount];
defaultHeight = Utils2D.MeasureSize( "I", font, true ).Height;
for( int i = 0; i < textures.Length; i++ ) {
textures[i].Height = defaultHeight;
@ -29,34 +27,19 @@ namespace ClassicalSharp {
public void SetText( int index, string text ) {
GraphicsApi.DeleteTexture( ref textures[index] );
List<DrawTextArgs> parts = null;
Size size = new Size( 0, defaultHeight );
if( !String.IsNullOrEmpty( text ) ) {
parts = Utils2D.SplitText( GraphicsApi, text, true );
size = Utils2D.MeasureSize( parts, font, true );
}
int x = HorizontalDocking == Docking.LeftOrTop ? XOffset : Window.Width - size.Width - XOffset;
int y = CalcY( index, size.Height );
if( !String.IsNullOrEmpty( text ) ) {
textures[index] = Utils2D.MakeTextTexture( parts, font, size, x, y );
DrawTextArgs args = new DrawTextArgs( GraphicsApi, text, true );
Texture tex = Utils2D.MakeTextTexture( font, 0, 0, ref args );
tex.X1 = CalcOffset( Window.Width, tex.Width, XOffset, HorizontalDocking );
tex.Y1 = CalcY( index, tex.Height );
textures[index] = tex;
} else {
textures[index] = new Texture( -1, 0, 0, 0, defaultHeight, 0, 0 );
}
textCache[index] = text;
UpdateDimensions();
}
public void SetText( int startIndex, params string[] texts ) {
for( int i = 0; i < texts.Length; i++ ) {
SetText( startIndex + i, texts[i] );
}
}
public string GetText( int index ) {
return textCache[index];
}
public int CalcUsedY() {
int y = Y;
for( int i = 0; i < textures.Length; i++ ) {
@ -72,7 +55,6 @@ namespace ClassicalSharp {
for( int i = 0; i < textures.Length - 1; i++ ) {
textures[i] = textures[i + 1];
textures[i].Y1 = y;
textCache[i] = textCache[i + 1];
y += textures[i].Height;
}
textures[textures.Length - 1].ID = 0; // Delete() is called by SetText otherwise.
@ -80,28 +62,28 @@ namespace ClassicalSharp {
}
int CalcY( int index, int newHeight ) {
int y = 0;
int deltaY = newHeight - textures[index].Height;
if( VerticalDocking == Docking.LeftOrTop ) {
int y = Y;
y = Y;
for( int i = 0; i < index; i++ ) {
y += textures[i].Height;
}
int deltaY = newHeight - textures[index].Height;
for( int i = index + 1; i < textures.Length; i++ ) {
textures[i].Y1 += deltaY;
}
return y;
} else {
int y = Window.Height - YOffset;
y = Window.Height - YOffset;
for( int i = index + 1; i < textures.Length; i++ ) {
y -= textures[i].Height;
}
y -= newHeight;
int deltaY = newHeight - textures[index].Height;
for( int i = 0; i < index; i++ ) {
textures[i].Y1 -= deltaY;
}
return y;
}
return y;
}
void UpdateDimensions() {
@ -109,7 +91,7 @@ namespace ClassicalSharp {
for( int i = 0; i < textures.Length; i++ ) {
Height += textures[i].Height;
}
Y = VerticalDocking == Docking.LeftOrTop ? YOffset : Window.Height - Height - YOffset;
Y = CalcOffset( Window.Height, Height, YOffset, VerticalDocking );
Width = 0;
for( int i = 0; i < textures.Length; i++ ) {
@ -118,7 +100,7 @@ namespace ClassicalSharp {
Width = width;
}
}
X = HorizontalDocking == Docking.LeftOrTop ? XOffset : Window.Width - Width - XOffset;
X = CalcOffset( Window.Width, Width, XOffset, HorizontalDocking );
}
public override void Render( double delta ) {

View File

@ -22,43 +22,27 @@ namespace ClassicalSharp {
}
Texture texture;
string textCache = null;
public int XOffset = 0, YOffset = 0;
int defaultHeight;
readonly Font font;
public override void Init() {
defaultHeight = Utils2D.MeasureSize( "I", font, true ).Height;
texture.Height = defaultHeight;
UpdateDimensions();
Height = defaultHeight;
}
public void SetText( string text ) {
GraphicsApi.DeleteTexture( ref texture );
textCache = text;
if( String.IsNullOrEmpty( text ) ) {
texture = new Texture( -1, 0, 0, 0, defaultHeight, 0, 0 );
UpdateDimensions();
return;
texture = new Texture();
Height = defaultHeight;
} else {
DrawTextArgs args = new DrawTextArgs( GraphicsApi, text, true );
texture = Utils2D.MakeTextTexture( font, 0, 0, ref args );
X = texture.X1 = CalcOffset( Window.Width, texture.Width, XOffset, HorizontalDocking );
Y = texture.Y1 = CalcOffset( Window.Height, texture.Height, YOffset, VerticalDocking );
Height = texture.Height;
}
List<DrawTextArgs> parts = null;
Size size = new Size( 0, defaultHeight );
parts = Utils2D.SplitText( GraphicsApi, text, true );
size = Utils2D.MeasureSize( parts, font, true );
X = CalcOffset( Window.Width, size.Width, XOffset, HorizontalDocking );
Y = CalcOffset( Window.Height, size.Height, YOffset, VerticalDocking );
texture = Utils2D.MakeTextTexture( parts, font, size, X, Y );
UpdateDimensions();
}
public string GetText() {
return textCache;
}
void UpdateDimensions() {
Height = texture.Height;
Width = texture.Width;
}

View File

@ -112,7 +112,7 @@ namespace ClassicalSharp {
protected static int CalcOffset( int axisSize, int elemSize, int offset, Docking mode ) {
if( mode == Docking.LeftOrTop ) return offset;
if( mode == Docking.BottomOrRight) return axisSize - elemSize + offset;
if( mode == Docking.BottomOrRight) return axisSize - elemSize - offset;
return ( axisSize - elemSize ) / 2 + offset;
}
}

View File

@ -39,7 +39,7 @@
<IntermediateOutputPath>obj\$(Configuration)\</IntermediateOutputPath>
</PropertyGroup>
<PropertyGroup Condition=" '$(Platform)' == 'AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<PlatformTarget>x86</PlatformTarget>
<RegisterForComInterop>False</RegisterForComInterop>
<GenerateSerializationAssemblies>Auto</GenerateSerializationAssemblies>
<BaseAddress>4194304</BaseAddress>
@ -65,7 +65,7 @@
<DefineConstants>TRACE</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug_DX32' ">
<PlatformTarget>x86</PlatformTarget>
<PlatformTarget>AnyCPU</PlatformTarget>
<OutputPath>output\debug\</OutputPath>
<DebugSymbols>true</DebugSymbols>
<DebugType>Full</DebugType>
@ -112,6 +112,7 @@
<Compile Include="Entities\Entity.cs" />
<Compile Include="Entities\EntityList.cs" />
<Compile Include="Entities\LocalPlayer.cs" />
<Compile Include="Entities\LocationUpdate.cs" />
<Compile Include="Entities\NetPlayer.cs" />
<Compile Include="Entities\Particles\Particle.cs" />
<Compile Include="Entities\Particles\ParticleManager.cs" />

View File

@ -6,27 +6,32 @@ namespace ClassicalSharp {
public abstract partial class Entity {
public Vector3 Position;
public Vector3 Velocity;
public float YawDegrees, PitchDegrees;
public IModel Model;
public float YawRadians {
get { return (float)Utils.DegreesToRadians( YawDegrees ); }
set { YawDegrees = (float)Utils.RadiansToDegrees( value ); }
}
public float PitchRadians {
get { return (float)Utils.DegreesToRadians( PitchDegrees ); }
set { PitchDegrees = (float)Utils.RadiansToDegrees( value ); }
}
public Entity( Game window ) {
map = window.Map;
info = window.BlockInfo;
}
public abstract float StepSize { get; }
public IModel Model;
public string ModelName;
public byte ID;
public Vector3 Position;
public Vector3 Velocity;
public float YawDegrees, PitchDegrees;
protected float StepSize;
const float deg2Rad = (float)( Math.PI / 180 );
const float rad2Deg = (float)( 180 / Math.PI );
public float YawRadians {
get { return YawDegrees * deg2Rad; }
set { YawDegrees = value * rad2Deg; }
}
public float PitchRadians {
get { return PitchDegrees * deg2Rad; }
set { PitchDegrees = value * rad2Deg; }
}
public virtual Vector3 CollisionSize {
get { return new Vector3( 8 / 16f, 30 / 16f, 8 / 16f );
//Model.CollisionSize; TODO: for non humanoid models, we also need to offset eye position.
@ -85,40 +90,4 @@ namespace ClassicalSharp {
return false;
}
}
public struct LocationUpdate {
public Vector3 Pos;
public float Yaw, Pitch;
public bool IncludesPosition;
public bool RelativePosition;
public bool IncludesOrientation;
public LocationUpdate( float x, float y, float z, float yaw, float pitch,
bool incPos, bool relPos, bool incOri ) {
Pos = new Vector3( x, y, z );
Yaw = yaw;
Pitch = pitch;
IncludesPosition = incPos;
RelativePosition = relPos;
IncludesOrientation = incOri;
}
public static LocationUpdate MakeOri( float yaw, float pitch ) {
return new LocationUpdate( 0, 0, 0, yaw, pitch, false, false, true );
}
public static LocationUpdate MakePos( float x, float y, float z, bool rel ) {
return new LocationUpdate( x, y, z, 0, 0, true, rel, false );
}
public static LocationUpdate MakePos( Vector3 pos, bool rel ) {
return new LocationUpdate( pos.X, pos.Y, pos.Z, 0, 0, true, rel, false );
}
public static LocationUpdate MakePosAndOri( float x, float y, float z, float yaw, float pitch, bool rel ) {
return new LocationUpdate( x, y, z, yaw, pitch, true, rel, true );
}
}
}

View File

@ -52,7 +52,10 @@ namespace ClassicalSharp {
public Player this[int id] {
get { return Players[id]; }
set { Players[id] = value; }
set {
Players[id] = value;
value.ID = (byte)id;
}
}
}
}

View File

@ -40,10 +40,9 @@ namespace ClassicalSharp {
get { return (float)GetMaxHeight( jumpVel ); }
}
public LocalPlayer( byte id, Game window ) : base( id, window ) {
public LocalPlayer( Game window ) : base( window ) {
DisplayName = window.Username;
SkinName = window.Username;
map = window.Map;
}
public override void SetLocation( LocationUpdate update, bool interpolate ) {

View File

@ -0,0 +1,42 @@
using System;
using ClassicalSharp.Model;
using OpenTK;
namespace ClassicalSharp {
public struct LocationUpdate {
public Vector3 Pos;
public float Yaw, Pitch;
public bool IncludesPosition;
public bool RelativePosition;
public bool IncludesOrientation;
public LocationUpdate( float x, float y, float z, float yaw, float pitch,
bool incPos, bool relPos, bool incOri ) {
Pos = new Vector3( x, y, z );
Yaw = yaw;
Pitch = pitch;
IncludesPosition = incPos;
RelativePosition = relPos;
IncludesOrientation = incOri;
}
public static LocationUpdate MakeOri( float yaw, float pitch ) {
return new LocationUpdate( 0, 0, 0, yaw, pitch, false, false, true );
}
public static LocationUpdate MakePos( float x, float y, float z, bool rel ) {
return new LocationUpdate( x, y, z, 0, 0, true, rel, false );
}
public static LocationUpdate MakePos( Vector3 pos, bool rel ) {
return new LocationUpdate( pos.X, pos.Y, pos.Z, 0, 0, true, rel, false );
}
public static LocationUpdate MakePosAndOri( float x, float y, float z, float yaw, float pitch, bool rel ) {
return new LocationUpdate( x, y, z, yaw, pitch, true, rel, true );
}
}
}

View File

@ -8,7 +8,7 @@ namespace ClassicalSharp {
int tickCount = 0;
public NetPlayer( byte id, string displayName, string skinName, Game window ) : base( id, window ) {
public NetPlayer( string displayName, string skinName, Game window ) : base( window ) {
DisplayName = displayName;
SkinName = Utils.StripColours( skinName );
renderer = new PlayerRenderer( this, window );

View File

@ -16,20 +16,14 @@ namespace ClassicalSharp {
get { return new Vector3( Position.X, Position.Y + EyeHeight, Position.Z ); }
}
public override float StepSize {
get { return 0.5f; }
}
public Game Window;
public byte ID;
public string DisplayName, SkinName;
public string ModelName;
protected PlayerRenderer renderer;
public SkinType SkinType;
protected PlayerRenderer renderer;
public Player( byte id, Game window ) : base( window ) {
ID = id;
public Player( Game window ) : base( window ) {
Window = window;
StepSize = 0.5f;
SkinType = Window.DefaultPlayerSkinType;
SetModel( "humanoid" );
}
@ -45,7 +39,6 @@ namespace ClassicalSharp {
}
Block GetBlock( Vector3 coords ) {
if( map == null || map.IsNotLoaded ) return Block.Air;
Vector3I blockCoords = Vector3I.Floor( coords );
return map.IsValidPos( blockCoords ) ?
(Block)map.GetBlock( blockCoords ) : Block.Air;
@ -65,16 +58,14 @@ namespace ClassicalSharp {
float dx = newPos.X - oldPos.X;
float dz = newPos.Z - oldPos.Z;
double distance = Math.Sqrt( dx * dx + dz * dz );
bool moves = distance > 0.05;
if( moves ) {
if( distance > 0.05 ) {
walkTimeN += (float)distance * 2 * (float)( 20 * delta );
swingN += (float)delta * 3;
if( swingN > 1 ) swingN = 1;
} else {
swingN -= (float)delta * 3;
if( swingN < 0 ) swingN = 0;
}
Utils.Clamp( ref swingN, 0, 1 );
}
const float armMax = (float)( 90 * Math.PI / 180.0 );

View File

@ -130,7 +130,7 @@ namespace ClassicalSharp {
BlockInfo.Init();
BlockInfo.SetDefaultBlockPermissions( CanPlace, CanDelete );
Map = new Map( this );
LocalPlayer = new LocalPlayer( 255, this );
LocalPlayer = new LocalPlayer( this );
Players[255] = LocalPlayer;
width = Width;
height = Height;

View File

@ -66,20 +66,20 @@ namespace ClassicalSharp.Model {
get { return new BoundingBox( -4 / 16f, 0, -8 / 16f, 4 / 16f, 15 / 16f, 4 / 16f ); }
}
protected override void DrawPlayerModel( Player player, PlayerRenderer renderer ) {
protected override void DrawPlayerModel( Player p, PlayerRenderer renderer ) {
graphics.Texturing = true;
int texId = renderer.MobTextureId <= 0 ? DefaultTexId : renderer.MobTextureId;
graphics.Bind2DTexture( texId );
graphics.AlphaTest = true;
DrawRotate( 0, 0.5625f, -0.1875f, -pitch, 0, 0, Set.Head );
DrawRotate( 0, 0.5625f, -0.1875f, -pitch, 0, 0, Set.Head2 );
DrawRotate( 0, 0.5625f, -0.1875f, -pitch, 0, 0, Set.Head3 );
DrawRotate( 0, 0.5625f, -0.1875f, -p.PitchRadians, 0, 0, Set.Head );
DrawRotate( 0, 0.5625f, -0.1875f, -p.PitchRadians, 0, 0, Set.Head2 );
DrawRotate( 0, 0.5625f, -0.1875f, -p.PitchRadians, 0, 0, Set.Head3 );
Set.Torso.Render();
DrawRotate( 0, 0.3125f, 0.0625f, leftLegXRot, 0, 0, Set.LeftLeg );
DrawRotate( 0, 0.3125f, 0.0625f, rightLegXRot, 0, 0, Set.RightLeg );
DrawRotate( -0.1875f, 0.6875f, 0, 0, 0, -Math.Abs( leftArmXRot ), Set.LeftWing );
DrawRotate( 0.1875f, 0.6875f, 0, 0, 0, Math.Abs( rightArmXRot ), Set.RightWing );
DrawRotate( 0, 0.3125f, 0.0625f, p.leftLegXRot, 0, 0, Set.LeftLeg );
DrawRotate( 0, 0.3125f, 0.0625f, p.rightLegXRot, 0, 0, Set.RightLeg );
DrawRotate( -0.1875f, 0.6875f, 0, 0, 0, -Math.Abs( p.leftArmXRot ), Set.LeftWing );
DrawRotate( 0.1875f, 0.6875f, 0, 0, 0, Math.Abs( p.rightArmXRot ), Set.RightWing );
}
public override void Dispose() {

View File

@ -48,17 +48,17 @@ namespace ClassicalSharp.Model {
get { return new BoundingBox( -4 / 16f, 0, -6 / 16f, 4 / 16f, 26 / 16f, 6 / 16f ); }
}
protected override void DrawPlayerModel( Player player, PlayerRenderer renderer ) {
protected override void DrawPlayerModel( Player p, PlayerRenderer renderer ) {
graphics.Texturing = true;
int texId = renderer.MobTextureId <= 0 ? DefaultTexId : renderer.MobTextureId;
graphics.Bind2DTexture( texId );
DrawRotate( 0, 1.125f, 0, -pitch, 0, 0, Set.Head );
DrawRotate( 0, 1.125f, 0, -p.PitchRadians, 0, 0, Set.Head );
Set.Torso.Render();
DrawRotate( 0, 0.375f, -0.125f, leftLegXRot, 0, 0, Set.LeftLegFront );
DrawRotate( 0, 0.375f, -0.125f, rightLegXRot, 0, 0, Set.RightLegFront );
DrawRotate( 0, 0.375f, 0.125f, rightLegXRot, 0, 0, Set.LeftLegBack );
DrawRotate( 0, 0.375f, 0.125f, leftLegXRot, 0, 0, Set.RightLegBack );
DrawRotate( 0, 0.375f, -0.125f, p.leftLegXRot, 0, 0, Set.LeftLegFront );
DrawRotate( 0, 0.375f, -0.125f, p.rightLegXRot, 0, 0, Set.RightLegFront );
DrawRotate( 0, 0.375f, 0.125f, p.rightLegXRot, 0, 0, Set.LeftLegBack );
DrawRotate( 0, 0.375f, 0.125f, p.leftLegXRot, 0, 0, Set.RightLegBack );
graphics.AlphaTest = true;
}

View File

@ -23,30 +23,15 @@ namespace ClassicalSharp.Model {
public abstract BoundingBox PickingBounds { get; }
protected Vector3 pos;
protected float yaw, pitch;
protected float rightLegXRot, rightArmXRot, rightArmZRot;
protected float leftLegXRot, leftArmXRot, leftArmZRot;
public void RenderModel( Player player, PlayerRenderer renderer ) {
pos = player.Position;
yaw = player.YawRadians;
pitch = player.PitchRadians;
leftLegXRot = player.leftLegXRot;
leftArmXRot = player.leftArmXRot;
leftArmZRot = player.leftArmZRot;
rightLegXRot = player.rightLegXRot;
rightArmXRot = player.rightArmXRot;
rightArmZRot = player.rightArmZRot;
public void RenderModel( Player p, PlayerRenderer renderer ) {
graphics.PushMatrix();
Matrix4 mat = Matrix4.RotateY( -yaw ) * Matrix4.Translate( pos );
Matrix4 mat = Matrix4.RotateY( -p.YawRadians ) * Matrix4.Translate( p.Position );
graphics.MultiplyMatrix( ref mat );
DrawPlayerModel( player, renderer );
DrawPlayerModel( p, renderer );
graphics.PopMatrix();
}
protected abstract void DrawPlayerModel( Player player, PlayerRenderer renderer );
protected abstract void DrawPlayerModel( Player p, PlayerRenderer renderer );
public abstract void Dispose();

View File

@ -49,17 +49,17 @@ namespace ClassicalSharp.Model {
get { return new BoundingBox( -5 / 16f, 0, -14 / 16f, 5 / 16f, 16 / 16f, 9 / 16f ); }
}
protected override void DrawPlayerModel( Player player, PlayerRenderer renderer ) {
protected override void DrawPlayerModel( Player p, PlayerRenderer renderer ) {
graphics.Texturing = true;
int texId = renderer.MobTextureId <= 0 ? DefaultTexId : renderer.MobTextureId;
graphics.Bind2DTexture( texId );
DrawRotate( 0, 0.75f, -0.375f, -pitch, 0, 0, Set.Head );
DrawRotate( 0, 0.75f, -0.375f, -p.PitchRadians, 0, 0, Set.Head );
Set.Torso.Render();
DrawRotate( 0, 0.375f, -0.3125f, leftLegXRot, 0, 0, Set.LeftLegFront );
DrawRotate( 0, 0.375f, -0.3125f, rightLegXRot, 0, 0, Set.RightLegFront );
DrawRotate( 0, 0.375f, 0.4375f, rightLegXRot, 0, 0, Set.LeftLegBack );
DrawRotate( 0, 0.375f, 0.4375f, leftLegXRot, 0, 0, Set.RightLegBack );
DrawRotate( 0, 0.375f, -0.3125f, p.leftLegXRot, 0, 0, Set.LeftLegFront );
DrawRotate( 0, 0.375f, -0.3125f, p.rightLegXRot, 0, 0, Set.RightLegFront );
DrawRotate( 0, 0.375f, 0.4375f, p.rightLegXRot, 0, 0, Set.LeftLegBack );
DrawRotate( 0, 0.375f, 0.4375f, p.leftLegXRot, 0, 0, Set.RightLegBack );
graphics.AlphaTest = true;
}

View File

@ -91,23 +91,23 @@ namespace ClassicalSharp.Model {
}
ModelSet model;
protected override void DrawPlayerModel( Player player, PlayerRenderer renderer ) {
protected override void DrawPlayerModel( Player p, PlayerRenderer renderer ) {
graphics.Texturing = true;
int texId = renderer.PlayerTextureId <= 0 ? DefaultTexId : renderer.PlayerTextureId;
graphics.Bind2DTexture( texId );
SkinType skinType = p.SkinType;
model = Set64x32;
SkinType skinType = player.SkinType;
if( skinType == SkinType.Type64x64 ) model = Set64x64;
else if( skinType == SkinType.Type64x64Slim ) model = Set64x64Slim;
DrawRotate( 0, 1.5f, 0, -pitch, 0, 0, model.Head );
DrawRotate( 0, 1.5f, 0, -p.PitchRadians, 0, 0, model.Head );
model.Torso.Render();
DrawRotate( 0, 0.75f, 0, leftLegXRot, 0, 0, model.LeftLeg );
DrawRotate( 0, 0.75f, 0, rightLegXRot, 0, 0, model.RightLeg );
DrawRotate( 0, 1.5f, 0, leftArmXRot, 0, leftArmZRot, model.LeftArm );
DrawRotate( 0, 1.5f, 0, rightArmXRot, 0, rightArmZRot, model.RightArm );
DrawRotate( 0, 0.75f, 0, p.leftLegXRot, 0, 0, model.LeftLeg );
DrawRotate( 0, 0.75f, 0, p.rightLegXRot, 0, 0, model.RightLeg );
DrawRotate( 0, 1.5f, 0, p.leftArmXRot, 0, p.leftArmZRot, model.LeftArm );
DrawRotate( 0, 1.5f, 0, p.rightArmXRot, 0, p.rightArmZRot, model.RightArm );
graphics.AlphaTest = true;
DrawRotate( 0, 1.4375f, 0, -pitch, 0, 0, model.Hat );
DrawRotate( 0, 1.4375f, 0, -p.PitchRadians, 0, 0, model.Hat );
}
public override void Dispose() {

View File

@ -73,26 +73,26 @@ namespace ClassicalSharp.Model {
get { return new BoundingBox( -6 / 16f, 0, -13 / 16f, 6 / 16f, 23 / 16f, 10 / 16f ); }
}
protected override void DrawPlayerModel( Player player, PlayerRenderer renderer ) {
protected override void DrawPlayerModel( Player p, PlayerRenderer renderer ) {
graphics.Texturing = true;
int texId = renderer.MobTextureId <= 0 ? DefaultTexId : renderer.MobTextureId;
graphics.Bind2DTexture( texId );
DrawRotate( 0, 1.125f, -0.5f, -pitch, 0, 0, Set.Head );
DrawRotate( 0, 1.125f, -0.5f, -p.PitchRadians, 0, 0, Set.Head );
Set.Torso.Render();
DrawRotate( 0, 0.75f, -0.3125f, leftLegXRot, 0, 0, Set.LeftLegFront );
DrawRotate( 0, 0.75f, -0.3125f, rightLegXRot, 0, 0, Set.RightLegFront );
DrawRotate( 0, 0.75f, 0.4375f, rightLegXRot, 0, 0, Set.LeftLegBack );
DrawRotate( 0, 0.75f, 0.4375f, leftLegXRot, 0, 0, Set.RightLegBack );
DrawRotate( 0, 0.75f, -0.3125f, p.leftLegXRot, 0, 0, Set.LeftLegFront );
DrawRotate( 0, 0.75f, -0.3125f, p.rightLegXRot, 0, 0, Set.RightLegFront );
DrawRotate( 0, 0.75f, 0.4375f, p.rightLegXRot, 0, 0, Set.LeftLegBack );
DrawRotate( 0, 0.75f, 0.4375f, p.leftLegXRot, 0, 0, Set.RightLegBack );
graphics.AlphaTest = true;
if( Fur ) {
graphics.Bind2DTexture( furTextureId );
Set.FurTorso.Render();
DrawRotate( 0, 1.125f, -0.5f, -pitch, 0, 0, Set.FurHead );
DrawRotate( 0, 0.75f, -0.3125f, leftLegXRot, 0, 0, Set.FurLeftLegFront );
DrawRotate( 0, 0.75f, -0.3125f, rightLegXRot, 0, 0, Set.FurRightLegFront );
DrawRotate( 0, 0.75f, 0.4375f, rightLegXRot, 0, 0, Set.FurLeftLegBack );
DrawRotate( 0, 0.75f, 0.4375f, leftLegXRot, 0, 0, Set.FurRightLegBack );
DrawRotate( 0, 1.125f, -0.5f, -p.PitchRadians, 0, 0, Set.FurHead );
DrawRotate( 0, 0.75f, -0.3125f, p.leftLegXRot, 0, 0, Set.FurLeftLegFront );
DrawRotate( 0, 0.75f, -0.3125f, p.rightLegXRot, 0, 0, Set.FurRightLegFront );
DrawRotate( 0, 0.75f, 0.4375f, p.rightLegXRot, 0, 0, Set.FurLeftLegBack );
DrawRotate( 0, 0.75f, 0.4375f, p.leftLegXRot, 0, 0, Set.FurRightLegBack );
}
}

View File

@ -61,18 +61,18 @@ namespace ClassicalSharp.Model {
get { return new BoundingBox( -4 / 16f, 0, -4 / 16f, 4 / 16f, 32 / 16f, 4 / 16f ); }
}
protected override void DrawPlayerModel( Player player, PlayerRenderer renderer ) {
protected override void DrawPlayerModel( Player p, PlayerRenderer renderer ) {
graphics.Texturing = true;
graphics.AlphaTest = true;
int texId = renderer.MobTextureId <= 0 ? DefaultTexId : renderer.MobTextureId;
graphics.Bind2DTexture( texId );
DrawRotate( 0, 1.5f, 0, -pitch, 0, 0, Set.Head );
DrawRotate( 0, 1.5f, 0, -p.PitchRadians, 0, 0, Set.Head );
Set.Torso.Render();
DrawRotate( 0, 0.75f, 0, leftLegXRot, 0, 0, Set.LeftLeg );
DrawRotate( 0, 0.75f, 0, rightLegXRot, 0, 0, Set.RightLeg );
DrawRotate( 0, 1.375f, 0, (float)Math.PI / 2, 0, leftArmZRot, Set.LeftArm );
DrawRotate( 0, 1.375f, 0, (float)Math.PI / 2, 0, rightArmZRot, Set.RightArm );
DrawRotate( 0, 0.75f, 0, p.leftLegXRot, 0, 0, Set.LeftLeg );
DrawRotate( 0, 0.75f, 0, p.rightLegXRot, 0, 0, Set.RightLeg );
DrawRotate( 0, 1.375f, 0, (float)Math.PI / 2, 0, p.leftArmZRot, Set.LeftArm );
DrawRotate( 0, 1.375f, 0, (float)Math.PI / 2, 0, p.rightArmZRot, Set.RightArm );
}
public override void Dispose() {

View File

@ -54,13 +54,13 @@ namespace ClassicalSharp.Model {
const float quarterPi = (float)( Math.PI / 4 );
const float eighthPi = (float)( Math.PI / 8 );
protected override void DrawPlayerModel( Player player, PlayerRenderer renderer ) {
protected override void DrawPlayerModel( Player p, PlayerRenderer renderer ) {
graphics.Texturing = true;
int texId = renderer.MobTextureId <= 0 ? DefaultTexId : renderer.MobTextureId;
graphics.Bind2DTexture( texId );
graphics.AlphaTest = true;
DrawRotate( 0, 0.5f, -0.1875f, -pitch, 0, 0, Set.Head );
DrawRotate( 0, 0.5f, -0.1875f, -p.PitchRadians, 0, 0, Set.Head );
Set.Link.Render();
Set.End.Render();
// TODO: leg animations

View File

@ -61,17 +61,17 @@ namespace ClassicalSharp.Model {
get { return new BoundingBox( -4 / 16f, 0, -4 / 16f, 4 / 16f, 32 / 16f, 4 / 16f ); }
}
protected override void DrawPlayerModel( Player player, PlayerRenderer renderer ) {
protected override void DrawPlayerModel( Player p, PlayerRenderer renderer ) {
graphics.Texturing = true;
int texId = renderer.MobTextureId <= 0 ? DefaultTexId : renderer.MobTextureId;
graphics.Bind2DTexture( texId );
DrawRotate( 0, 1.5f, 0, -pitch, 0, 0, Set.Head );
DrawRotate( 0, 1.5f, 0, -p.PitchRadians, 0, 0, Set.Head );
Set.Torso.Render();
DrawRotate( 0, 0.75f, 0, leftLegXRot, 0, 0, Set.LeftLeg );
DrawRotate( 0, 0.75f, 0, rightLegXRot, 0, 0, Set.RightLeg );
DrawRotate( 0, 1.375f, 0, (float)Math.PI / 2, 0, leftArmZRot, Set.LeftArm );
DrawRotate( 0, 1.375f, 0, (float)Math.PI / 2, 0, rightArmZRot, Set.RightArm );
DrawRotate( 0, 0.75f, 0, p.leftLegXRot, 0, 0, Set.LeftLeg );
DrawRotate( 0, 0.75f, 0, p.rightLegXRot, 0, 0, Set.RightLeg );
DrawRotate( 0, 1.375f, 0, (float)Math.PI / 2, 0, p.leftArmZRot, Set.LeftArm );
DrawRotate( 0, 1.375f, 0, (float)Math.PI / 2, 0, p.rightArmZRot, Set.RightArm );
graphics.AlphaTest = true;
}

View File

@ -652,7 +652,7 @@ namespace ClassicalSharp {
Window.RaiseEntityRemoved( entityId );
oldPlayer.Despawn();
}
Window.Players[entityId] = new NetPlayer( entityId, displayName, skinName, Window );
Window.Players[entityId] = new NetPlayer( displayName, skinName, Window );
Window.RaiseEntityAdded( entityId );
Window.AsyncDownloader.DownloadSkin( skinName );
}

View File

@ -8,7 +8,6 @@ namespace ClassicalSharp.Renderers {
public class PlayerRenderer {
Vector3 pos;
public Game Window;
public IGraphicsApi Graphics;
public Player Player;
@ -23,11 +22,10 @@ namespace ClassicalSharp.Renderers {
Graphics = window.Graphics;
using( Font font = new Font( "Arial", 14 ) ) {
List<DrawTextArgs> parts = Utils2D.SplitText( Graphics, player.DisplayName, true );
Size size = Utils2D.MeasureSize( parts, font, true );
nameTexture = Utils2D.MakeTextTexture( parts, font, size, 0, 0 );
nameWidth = size.Width;
nameHeight = size.Height;
DrawTextArgs args = new DrawTextArgs( Graphics, player.DisplayName, true );
nameTexture = Utils2D.MakeTextTexture( font, 0, 0, ref args );
nameWidth = nameTexture.Width;
nameHeight = nameTexture.Height;
nameTextureId = nameTexture.ID;
}
}
@ -38,13 +36,13 @@ namespace ClassicalSharp.Renderers {
}
public void Render( double deltaTime ) {
pos = Player.Position;
Player.Model.RenderModel( Player, this );
DrawName();
}
const float nameScale = 1 / 50f;
private void DrawName() {
Vector3 pos = Player.Position;
Graphics.PushMatrix();
Matrix4 mat = Matrix4.Translate( pos.X, pos.Y + Player.Model.NameYOffset, pos.Z );
// Do this to always have names facing the player