mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-16 19:15:14 -04:00
Start work on rain particles.
This commit is contained in:
parent
42381461be
commit
dff4877fd6
@ -130,8 +130,10 @@
|
|||||||
<Compile Include="Entities\LocalPlayer.cs" />
|
<Compile Include="Entities\LocalPlayer.cs" />
|
||||||
<Compile Include="Entities\LocationUpdate.cs" />
|
<Compile Include="Entities\LocationUpdate.cs" />
|
||||||
<Compile Include="Entities\NetPlayer.cs" />
|
<Compile Include="Entities\NetPlayer.cs" />
|
||||||
|
<Compile Include="Entities\Particles\CollidableParticle.cs" />
|
||||||
<Compile Include="Entities\Particles\Particle.cs" />
|
<Compile Include="Entities\Particles\Particle.cs" />
|
||||||
<Compile Include="Entities\Particles\ParticleManager.cs" />
|
<Compile Include="Entities\Particles\ParticleManager.cs" />
|
||||||
|
<Compile Include="Entities\Particles\RainParticle.cs" />
|
||||||
<Compile Include="Entities\Particles\TerrainParticle.cs" />
|
<Compile Include="Entities\Particles\TerrainParticle.cs" />
|
||||||
<Compile Include="Entities\PhysicsEntity.cs" />
|
<Compile Include="Entities\PhysicsEntity.cs" />
|
||||||
<Compile Include="Entities\Player.cs" />
|
<Compile Include="Entities\Player.cs" />
|
||||||
|
64
ClassicalSharp/Entities/Particles/CollidableParticle.cs
Normal file
64
ClassicalSharp/Entities/Particles/CollidableParticle.cs
Normal file
@ -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];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -7,7 +7,6 @@ namespace ClassicalSharp.Particles {
|
|||||||
|
|
||||||
public Vector3 Position;
|
public Vector3 Position;
|
||||||
public Vector3 Velocity;
|
public Vector3 Velocity;
|
||||||
public TextureRec Rectangle;
|
|
||||||
public float Lifetime;
|
public float Lifetime;
|
||||||
protected Game game;
|
protected Game game;
|
||||||
protected Vector3 lastPos, nextPos;
|
protected Vector3 lastPos, nextPos;
|
||||||
@ -16,12 +15,11 @@ namespace ClassicalSharp.Particles {
|
|||||||
|
|
||||||
public abstract void Dispose();
|
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;
|
this.game = game;
|
||||||
Position = lastPos = nextPos = pos;
|
Position = lastPos = nextPos = pos;
|
||||||
Velocity = velocity;
|
Velocity = velocity;
|
||||||
Lifetime = (float)lifetime;
|
Lifetime = (float)lifetime;
|
||||||
Rectangle = rec;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual bool Tick( double delta ) {
|
public virtual bool Tick( double delta ) {
|
||||||
|
31
ClassicalSharp/Entities/Particles/RainParticle.cs
Normal file
31
ClassicalSharp/Entities/Particles/RainParticle.cs
Normal file
@ -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() {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -3,13 +3,13 @@ using OpenTK;
|
|||||||
|
|
||||||
namespace ClassicalSharp.Particles {
|
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 );
|
static Vector2 terrainSize = new Vector2( 1/8f, 1/8f );
|
||||||
|
TextureRec rec;
|
||||||
public TerrainParticle( Game game, Vector3 pos, Vector3 velocity, double lifetime, 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 ) {
|
public override void Render( double delta, float t, VertexPos3fTex2fCol4b[] vertices, ref int index ) {
|
||||||
@ -20,60 +20,10 @@ namespace ClassicalSharp.Particles {
|
|||||||
Map map = game.Map;
|
Map map = game.Map;
|
||||||
FastColour col = map.IsLit( Vector3I.Floor( Position ) ) ? map.Sunlight : map.Shadowlight;
|
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( p111, rec.U1, rec.V2, col );
|
||||||
vertices[index++] = new VertexPos3fTex2fCol4b( p121, Rectangle.U1, Rectangle.V1, col );
|
vertices[index++] = new VertexPos3fTex2fCol4b( p121, rec.U1, rec.V1, col );
|
||||||
vertices[index++] = new VertexPos3fTex2fCol4b( p222, Rectangle.U2, Rectangle.V1, col );
|
vertices[index++] = new VertexPos3fTex2fCol4b( p222, rec.U2, rec.V1, col );
|
||||||
vertices[index++] = new VertexPos3fTex2fCol4b( p212, Rectangle.U2, Rectangle.V2, col );
|
vertices[index++] = new VertexPos3fTex2fCol4b( p212, rec.U2, rec.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];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Dispose() {
|
public override void Dispose() {
|
||||||
|
@ -30,9 +30,9 @@ namespace ClassicalSharp {
|
|||||||
|
|
||||||
Key mapLeft, mapMiddle, mapRight;
|
Key mapLeft, mapMiddle, mapRight;
|
||||||
void LoadMouseToKeyMappings() {
|
void LoadMouseToKeyMappings() {
|
||||||
mapLeft = Options.GetKey( OptionsKey.MouseLeft, Key.Unknown );
|
mapLeft = Options.GetEnum( OptionsKey.MouseLeft, Key.Unknown );
|
||||||
mapMiddle = Options.GetKey( OptionsKey.MouseMiddle, Key.Unknown );
|
mapMiddle = Options.GetEnum( OptionsKey.MouseMiddle, Key.Unknown );
|
||||||
mapRight = Options.GetKey( OptionsKey.MouseRight, Key.Unknown );
|
mapRight = Options.GetEnum( OptionsKey.MouseRight, Key.Unknown );
|
||||||
}
|
}
|
||||||
|
|
||||||
public KeyMap Keys;
|
public KeyMap Keys;
|
||||||
|
@ -55,7 +55,7 @@ namespace ClassicalSharp {
|
|||||||
string[] names = KeyBinding.GetNames( typeof( KeyBinding ) );
|
string[] names = KeyBinding.GetNames( typeof( KeyBinding ) );
|
||||||
for( int i = 0; i < names.Length; i++ ) {
|
for( int i = 0; i < names.Length; i++ ) {
|
||||||
string key = "key-" + names[i];
|
string key = "key-" + names[i];
|
||||||
Key mapping = Options.GetKey( key, Keys[i] );
|
Key mapping = Options.GetEnum( key, Keys[i] );
|
||||||
if( !IsReservedKey( mapping ) )
|
if( !IsReservedKey( mapping ) )
|
||||||
Keys[i] = mapping;
|
Keys[i] = mapping;
|
||||||
}
|
}
|
||||||
|
@ -99,7 +99,7 @@ namespace ClassicalSharp.Hotkeys {
|
|||||||
|
|
||||||
// Then try to parse the key and value
|
// Then try to parse the key and value
|
||||||
Key key; byte flags; bool moreInput;
|
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 ) ||
|
!Byte.TryParse( strFlags, out flags ) ||
|
||||||
!Boolean.TryParse( strMoreInput, out moreInput ) ||
|
!Boolean.TryParse( strMoreInput, out moreInput ) ||
|
||||||
strText.Length == 0 ) {
|
strText.Length == 0 ) {
|
||||||
|
@ -23,6 +23,14 @@ namespace ClassicalSharp {
|
|||||||
public const string VSync = "vsync";
|
public const string VSync = "vsync";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public enum FpsLimit {
|
||||||
|
LimitVSync,
|
||||||
|
Limit30FPS,
|
||||||
|
Limit60FPS,
|
||||||
|
Limit120FPS,
|
||||||
|
LimitNone,
|
||||||
|
}
|
||||||
|
|
||||||
public static class Options {
|
public static class Options {
|
||||||
|
|
||||||
public static Dictionary<string, string> OptionsSet = new Dictionary<string, string>();
|
public static Dictionary<string, string> OptionsSet = new Dictionary<string, string>();
|
||||||
@ -64,15 +72,15 @@ namespace ClassicalSharp {
|
|||||||
return valueFloat;
|
return valueFloat;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Key GetKey( string key, Key defValue ) {
|
public static T GetEnum<T>( string key, T defValue ) {
|
||||||
string value = Options.Get( key.ToLower() );
|
string value = Options.Get( key.ToLower() );
|
||||||
if( value == null ) {
|
if( value == null ) {
|
||||||
Set( key, defValue );
|
Set( key, defValue );
|
||||||
return defValue;
|
return defValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
Key mapping;
|
T mapping;
|
||||||
if( !Utils.TryParseKey( value, defValue, out mapping ) )
|
if( !Utils.TryParseEnum( value, defValue, out mapping ) )
|
||||||
Options.Set( key, defValue );
|
Options.Set( key, defValue );
|
||||||
return mapping;
|
return mapping;
|
||||||
}
|
}
|
||||||
|
@ -128,16 +128,15 @@ namespace ClassicalSharp {
|
|||||||
|
|
||||||
/// <summary> Attempts to caselessly parse the given string as a Key enum member,
|
/// <summary> Attempts to caselessly parse the given string as a Key enum member,
|
||||||
/// returning defValue if there was an error parsing. </summary>
|
/// returning defValue if there was an error parsing. </summary>
|
||||||
public static bool TryParseKey( string value, Key defValue, out Key key ) {
|
public static bool TryParseEnum<T>( string value, T defValue, out T result ) {
|
||||||
Key mapping;
|
T mapping;
|
||||||
try {
|
try {
|
||||||
mapping = (Key)Enum.Parse( typeof( Key ), value, true );
|
mapping = (T)Enum.Parse( typeof( T ), value, true );
|
||||||
} catch( ArgumentException ) {
|
} catch( ArgumentException ) {
|
||||||
key = defValue;
|
result = defValue;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
result = mapping;
|
||||||
key = mapping;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user