diff --git a/ClassicalSharp/ClassicalSharp.csproj b/ClassicalSharp/ClassicalSharp.csproj
index 5e8713b8c..c31dd718e 100644
--- a/ClassicalSharp/ClassicalSharp.csproj
+++ b/ClassicalSharp/ClassicalSharp.csproj
@@ -130,8 +130,10 @@
+
+
diff --git a/ClassicalSharp/Entities/Particles/CollidableParticle.cs b/ClassicalSharp/Entities/Particles/CollidableParticle.cs
new file mode 100644
index 000000000..cd785d2b9
--- /dev/null
+++ b/ClassicalSharp/Entities/Particles/CollidableParticle.cs
@@ -0,0 +1,64 @@
+using System;
+using OpenTK;
+
+namespace ClassicalSharp.Particles {
+
+ public abstract class CollidableParticle : Particle {
+
+ const float gravity = 3.4f;
+
+ public CollidableParticle( Game game, Vector3 pos, Vector3 velocity, double lifetime )
+ : base( game, pos, velocity, lifetime ) {
+ }
+
+ public override bool Tick( double delta ) {
+ lastPos = Position = nextPos;
+ byte curBlock = game.Map.SafeGetBlock( (int)Position.X, (int)Position.Y, (int)Position.Z );
+ if( !CanPassThrough( curBlock ) ) return true;
+
+ Velocity.Y -= gravity * (float)delta;
+ int startY = (int)Math.Floor( Position.Y );
+ Position += Velocity * (float)delta * 3;
+ int endY = (int)Math.Floor( Position.Y );
+ Utils.Clamp( ref Position.X, 0, game.Map.Width - 0.01f );
+ Utils.Clamp( ref Position.Z, 0, game.Map.Length - 0.01f );
+
+ if( Velocity.Y > 0 ) {
+ for( int y = startY; y <= endY && TestY( y, false ); y++ );
+ } else {
+ for( int y = startY; y >= endY && TestY( y, true ); y-- );
+ }
+ nextPos = Position;
+ Position = lastPos;
+ return base.Tick( delta );
+ }
+
+ bool TestY( int y, bool topFace ) {
+ if( y < 0 ) {
+ Position.Y = nextPos.Y = lastPos.Y = 0 + Entity.Adjustment;
+ Velocity = Vector3.Zero;
+ return false;
+ }
+
+ byte block = game.Map.SafeGetBlock( (int)Position.X, y, (int)Position.Z );
+ if( CanPassThrough( block ) ) return true;
+
+ float collideY = y;
+ if( topFace )
+ collideY += game.BlockInfo.Height[block];
+
+ bool collide = topFace ? (Position.Y < collideY) : (Position.Y > collideY );
+ if( collide ) {
+ float adjust = topFace ? Entity.Adjustment : -Entity.Adjustment;
+ Position.Y = nextPos.Y = lastPos.Y = collideY + adjust;
+ Velocity = Vector3.Zero;
+ return false;
+ }
+ return true;
+ }
+
+ bool CanPassThrough( byte block ) {
+ return block == 0 || game.BlockInfo.IsSprite[block] || game.BlockInfo.IsLiquid[block];
+ }
+ }
+}
diff --git a/ClassicalSharp/Entities/Particles/Particle.cs b/ClassicalSharp/Entities/Particles/Particle.cs
index 99167dcb5..1a1cc23fe 100644
--- a/ClassicalSharp/Entities/Particles/Particle.cs
+++ b/ClassicalSharp/Entities/Particles/Particle.cs
@@ -7,7 +7,6 @@ namespace ClassicalSharp.Particles {
public Vector3 Position;
public Vector3 Velocity;
- public TextureRec Rectangle;
public float Lifetime;
protected Game game;
protected Vector3 lastPos, nextPos;
@@ -16,12 +15,11 @@ namespace ClassicalSharp.Particles {
public abstract void Dispose();
- public Particle( Game game, Vector3 pos, Vector3 velocity, double lifetime, TextureRec rec ) {
+ public Particle( Game game, Vector3 pos, Vector3 velocity, double lifetime ) {
this.game = game;
Position = lastPos = nextPos = pos;
Velocity = velocity;
Lifetime = (float)lifetime;
- Rectangle = rec;
}
public virtual bool Tick( double delta ) {
diff --git a/ClassicalSharp/Entities/Particles/RainParticle.cs b/ClassicalSharp/Entities/Particles/RainParticle.cs
new file mode 100644
index 000000000..f7ea67790
--- /dev/null
+++ b/ClassicalSharp/Entities/Particles/RainParticle.cs
@@ -0,0 +1,31 @@
+using System;
+using OpenTK;
+
+namespace ClassicalSharp.Particles {
+
+ public sealed class RainParticle : CollidableParticle {
+
+ static Vector2 rainSize = new Vector2( 1/8f, 1/8f );
+ static TextureRec rec = new TextureRec( 2/128f, 14/128f, 3/128f, 2/128f );
+ public RainParticle( Game game, Vector3 pos, Vector3 velocity, double lifetime )
+ : base( game, pos, velocity, lifetime ) {
+ }
+
+ public override void Render( double delta, float t, VertexPos3fTex2fCol4b[] vertices, ref int index ) {
+ Position = Vector3.Lerp( lastPos, nextPos, t );
+ Vector3 p111, p121, p212, p222;
+ Utils.CalcBillboardPoints( rainSize, Position, ref game.View,
+ out p111, out p121, out p212, out p222 );
+ Map map = game.Map;
+ FastColour col = map.IsLit( Vector3I.Floor( Position ) ) ? map.Sunlight : map.Shadowlight;
+
+ vertices[index++] = new VertexPos3fTex2fCol4b( p111, rec.U1, rec.V2, col );
+ vertices[index++] = new VertexPos3fTex2fCol4b( p121, rec.U1, rec.V1, col );
+ vertices[index++] = new VertexPos3fTex2fCol4b( p222, rec.U2, rec.V1, col );
+ vertices[index++] = new VertexPos3fTex2fCol4b( p212, rec.U2, rec.V2, col );
+ }
+
+ public override void Dispose() {
+ }
+ }
+}
diff --git a/ClassicalSharp/Entities/Particles/TerrainParticle.cs b/ClassicalSharp/Entities/Particles/TerrainParticle.cs
index fd813bebe..b1e037359 100644
--- a/ClassicalSharp/Entities/Particles/TerrainParticle.cs
+++ b/ClassicalSharp/Entities/Particles/TerrainParticle.cs
@@ -3,13 +3,13 @@ using OpenTK;
namespace ClassicalSharp.Particles {
- public sealed class TerrainParticle : Particle {
+ public sealed class TerrainParticle : CollidableParticle {
- const float gravity = 3.4f;
static Vector2 terrainSize = new Vector2( 1/8f, 1/8f );
-
+ TextureRec rec;
public TerrainParticle( Game game, Vector3 pos, Vector3 velocity, double lifetime, TextureRec rec )
- : base( game, pos, velocity, lifetime, rec ) {
+ : base( game, pos, velocity, lifetime ) {
+ this.rec = rec;
}
public override void Render( double delta, float t, VertexPos3fTex2fCol4b[] vertices, ref int index ) {
@@ -20,60 +20,10 @@ namespace ClassicalSharp.Particles {
Map map = game.Map;
FastColour col = map.IsLit( Vector3I.Floor( Position ) ) ? map.Sunlight : map.Shadowlight;
- vertices[index++] = new VertexPos3fTex2fCol4b( p111, Rectangle.U1, Rectangle.V2, col );
- vertices[index++] = new VertexPos3fTex2fCol4b( p121, Rectangle.U1, Rectangle.V1, col );
- vertices[index++] = new VertexPos3fTex2fCol4b( p222, Rectangle.U2, Rectangle.V1, col );
- vertices[index++] = new VertexPos3fTex2fCol4b( p212, Rectangle.U2, Rectangle.V2, col );
- }
-
- public override bool Tick( double delta ) {
- lastPos = Position = nextPos;
- byte curBlock = game.Map.SafeGetBlock( (int)Position.X, (int)Position.Y, (int)Position.Z );
- if( !CanPassThrough( curBlock ) ) return true;
-
- Velocity.Y -= gravity * (float)delta;
- int startY = (int)Math.Floor( Position.Y );
- Position += Velocity * (float)delta * 3;
- int endY = (int)Math.Floor( Position.Y );
- Utils.Clamp( ref Position.X, 0, game.Map.Width - 0.01f );
- Utils.Clamp( ref Position.Z, 0, game.Map.Length - 0.01f );
-
- if( Velocity.Y > 0 ) {
- for( int y = startY; y <= endY && TestY( y, false ); y++ );
- } else {
- for( int y = startY; y >= endY && TestY( y, true ); y-- );
- }
- nextPos = Position;
- Position = lastPos;
- return base.Tick( delta );
- }
-
- bool TestY( int y, bool topFace ) {
- if( y < 0 ) {
- Position.Y = nextPos.Y = lastPos.Y = 0 + Entity.Adjustment;
- Velocity = Vector3.Zero;
- return false;
- }
-
- byte block = game.Map.SafeGetBlock( (int)Position.X, y, (int)Position.Z );
- if( CanPassThrough( block ) ) return true;
-
- float collideY = y;
- if( topFace )
- collideY += game.BlockInfo.Height[block];
-
- bool collide = topFace ? (Position.Y < collideY) : (Position.Y > collideY );
- if( collide ) {
- float adjust = topFace ? Entity.Adjustment : -Entity.Adjustment;
- Position.Y = nextPos.Y = lastPos.Y = collideY + adjust;
- Velocity = Vector3.Zero;
- return false;
- }
- return true;
- }
-
- bool CanPassThrough( byte block ) {
- return block == 0 || game.BlockInfo.IsSprite[block] || game.BlockInfo.IsLiquid[block];
+ vertices[index++] = new VertexPos3fTex2fCol4b( p111, rec.U1, rec.V2, col );
+ vertices[index++] = new VertexPos3fTex2fCol4b( p121, rec.U1, rec.V1, col );
+ vertices[index++] = new VertexPos3fTex2fCol4b( p222, rec.U2, rec.V1, col );
+ vertices[index++] = new VertexPos3fTex2fCol4b( p212, rec.U2, rec.V2, col );
}
public override void Dispose() {
diff --git a/ClassicalSharp/Game/InputHandler.cs b/ClassicalSharp/Game/InputHandler.cs
index 5ccc88cf5..fd80820da 100644
--- a/ClassicalSharp/Game/InputHandler.cs
+++ b/ClassicalSharp/Game/InputHandler.cs
@@ -30,9 +30,9 @@ namespace ClassicalSharp {
Key mapLeft, mapMiddle, mapRight;
void LoadMouseToKeyMappings() {
- mapLeft = Options.GetKey( OptionsKey.MouseLeft, Key.Unknown );
- mapMiddle = Options.GetKey( OptionsKey.MouseMiddle, Key.Unknown );
- mapRight = Options.GetKey( OptionsKey.MouseRight, Key.Unknown );
+ mapLeft = Options.GetEnum( OptionsKey.MouseLeft, Key.Unknown );
+ mapMiddle = Options.GetEnum( OptionsKey.MouseMiddle, Key.Unknown );
+ mapRight = Options.GetEnum( OptionsKey.MouseRight, Key.Unknown );
}
public KeyMap Keys;
diff --git a/ClassicalSharp/Game/KeyMap.cs b/ClassicalSharp/Game/KeyMap.cs
index bedbb104f..2844e123c 100644
--- a/ClassicalSharp/Game/KeyMap.cs
+++ b/ClassicalSharp/Game/KeyMap.cs
@@ -55,7 +55,7 @@ namespace ClassicalSharp {
string[] names = KeyBinding.GetNames( typeof( KeyBinding ) );
for( int i = 0; i < names.Length; i++ ) {
string key = "key-" + names[i];
- Key mapping = Options.GetKey( key, Keys[i] );
+ Key mapping = Options.GetEnum( key, Keys[i] );
if( !IsReservedKey( mapping ) )
Keys[i] = mapping;
}
diff --git a/ClassicalSharp/Hotkeys/HotkeyList.cs b/ClassicalSharp/Hotkeys/HotkeyList.cs
index 273f1bde7..78244faf0 100644
--- a/ClassicalSharp/Hotkeys/HotkeyList.cs
+++ b/ClassicalSharp/Hotkeys/HotkeyList.cs
@@ -99,7 +99,7 @@ namespace ClassicalSharp.Hotkeys {
// Then try to parse the key and value
Key key; byte flags; bool moreInput;
- if( !Utils.TryParseKey( strKey, Key.Unknown, out key ) ||
+ if( !Utils.TryParseEnum( strKey, Key.Unknown, out key ) ||
!Byte.TryParse( strFlags, out flags ) ||
!Boolean.TryParse( strMoreInput, out moreInput ) ||
strText.Length == 0 ) {
diff --git a/ClassicalSharp/Utils/Options.cs b/ClassicalSharp/Utils/Options.cs
index edc90d0ae..c679d4b0a 100644
--- a/ClassicalSharp/Utils/Options.cs
+++ b/ClassicalSharp/Utils/Options.cs
@@ -23,6 +23,14 @@ namespace ClassicalSharp {
public const string VSync = "vsync";
}
+ public enum FpsLimit {
+ LimitVSync,
+ Limit30FPS,
+ Limit60FPS,
+ Limit120FPS,
+ LimitNone,
+ }
+
public static class Options {
public static Dictionary OptionsSet = new Dictionary();
@@ -64,15 +72,15 @@ namespace ClassicalSharp {
return valueFloat;
}
- public static Key GetKey( string key, Key defValue ) {
+ public static T GetEnum( string key, T defValue ) {
string value = Options.Get( key.ToLower() );
if( value == null ) {
Set( key, defValue );
return defValue;
}
- Key mapping;
- if( !Utils.TryParseKey( value, defValue, out mapping ) )
+ T mapping;
+ if( !Utils.TryParseEnum( value, defValue, out mapping ) )
Options.Set( key, defValue );
return mapping;
}
diff --git a/ClassicalSharp/Utils/Utils.cs b/ClassicalSharp/Utils/Utils.cs
index b3cecf897..dc43f1d54 100644
--- a/ClassicalSharp/Utils/Utils.cs
+++ b/ClassicalSharp/Utils/Utils.cs
@@ -128,16 +128,15 @@ namespace ClassicalSharp {
/// Attempts to caselessly parse the given string as a Key enum member,
/// returning defValue if there was an error parsing.
- public static bool TryParseKey( string value, Key defValue, out Key key ) {
- Key mapping;
+ public static bool TryParseEnum( string value, T defValue, out T result ) {
+ T mapping;
try {
- mapping = (Key)Enum.Parse( typeof( Key ), value, true );
+ mapping = (T)Enum.Parse( typeof( T ), value, true );
} catch( ArgumentException ) {
- key = defValue;
+ result = defValue;
return false;
- }
-
- key = mapping;
+ }
+ result = mapping;
return true;
}