mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-14 18:15:28 -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\LocationUpdate.cs" />
|
||||
<Compile Include="Entities\NetPlayer.cs" />
|
||||
<Compile Include="Entities\Particles\CollidableParticle.cs" />
|
||||
<Compile Include="Entities\Particles\Particle.cs" />
|
||||
<Compile Include="Entities\Particles\ParticleManager.cs" />
|
||||
<Compile Include="Entities\Particles\RainParticle.cs" />
|
||||
<Compile Include="Entities\Particles\TerrainParticle.cs" />
|
||||
<Compile Include="Entities\PhysicsEntity.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 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 ) {
|
||||
|
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 {
|
||||
|
||||
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() {
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 ) {
|
||||
|
@ -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<string, string> OptionsSet = new Dictionary<string, string>();
|
||||
@ -64,15 +72,15 @@ namespace ClassicalSharp {
|
||||
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() );
|
||||
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;
|
||||
}
|
||||
|
@ -128,16 +128,15 @@ namespace ClassicalSharp {
|
||||
|
||||
/// <summary> Attempts to caselessly parse the given string as a Key enum member,
|
||||
/// returning defValue if there was an error parsing. </summary>
|
||||
public static bool TryParseKey( string value, Key defValue, out Key key ) {
|
||||
Key mapping;
|
||||
public static bool TryParseEnum<T>( 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;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user