mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-15 18:45:23 -04:00
Block break particles should account for block height, more work on rain particles.
This commit is contained in:
parent
e198ef367f
commit
0defe3b66c
@ -80,12 +80,14 @@ namespace ClassicalSharp {
|
|||||||
Font chatFont, chatInputFont, chatUnderlineFont, announcementFont;
|
Font chatFont, chatInputFont, chatUnderlineFont, announcementFont;
|
||||||
public override void Init() {
|
public override void Init() {
|
||||||
int fontSize = (int)(12 * game.GuiScale() * game.ChatScale);
|
int fontSize = (int)(12 * game.GuiScale() * game.ChatScale);
|
||||||
Utils.Clamp( ref fontSize, 8, 60 );
|
Utils.Clamp( ref fontSize, 8, 60 );
|
||||||
|
|
||||||
chatFont = new Font( "Arial", fontSize );
|
chatFont = new Font( "Arial", fontSize );
|
||||||
chatInputFont = new Font( "Arial", fontSize, FontStyle.Bold );
|
chatInputFont = new Font( "Arial", fontSize, FontStyle.Bold );
|
||||||
chatUnderlineFont = new Font( "Arial", fontSize, FontStyle.Underline );
|
chatUnderlineFont = new Font( "Arial", fontSize, FontStyle.Underline );
|
||||||
announcementFont = new Font( "Arial", 14 );
|
|
||||||
|
fontSize = (int)(14 * game.GuiScale());
|
||||||
|
Utils.Clamp( ref fontSize, 8, 60 );
|
||||||
|
announcementFont = new Font( "Arial", fontSize );
|
||||||
blockSize = (int)(40 * game.GuiScale());
|
blockSize = (int)(40 * game.GuiScale());
|
||||||
|
|
||||||
textInput = new TextInputWidget( game, chatFont, chatInputFont );
|
textInput = new TextInputWidget( game, chatFont, chatInputFont );
|
||||||
|
@ -3,7 +3,7 @@ using OpenTK;
|
|||||||
|
|
||||||
namespace ClassicalSharp.Particles {
|
namespace ClassicalSharp.Particles {
|
||||||
|
|
||||||
public abstract class Particle : IDisposable {
|
public abstract class Particle {
|
||||||
|
|
||||||
public Vector3 Position;
|
public Vector3 Position;
|
||||||
public Vector3 Velocity;
|
public Vector3 Velocity;
|
||||||
@ -13,8 +13,6 @@ namespace ClassicalSharp.Particles {
|
|||||||
|
|
||||||
public abstract void Render( double delta, float t, VertexPos3fTex2fCol4b[] vertices, ref int index );
|
public abstract void Render( double delta, float t, VertexPos3fTex2fCol4b[] vertices, ref int index );
|
||||||
|
|
||||||
public abstract void Dispose();
|
|
||||||
|
|
||||||
public Particle( Game game, Vector3 pos, Vector3 velocity, double lifetime ) {
|
public Particle( Game game, Vector3 pos, Vector3 velocity, double lifetime ) {
|
||||||
this.game = game;
|
this.game = game;
|
||||||
Position = lastPos = nextPos = pos;
|
Position = lastPos = nextPos = pos;
|
||||||
|
@ -7,54 +7,71 @@ namespace ClassicalSharp.Particles {
|
|||||||
|
|
||||||
public class ParticleManager : IDisposable {
|
public class ParticleManager : IDisposable {
|
||||||
|
|
||||||
List<Particle> particles = new List<Particle>();
|
public int ParticlesTexId;
|
||||||
|
List<Particle> terrainParticles = new List<Particle>();
|
||||||
|
List<Particle> rainParticles = new List<Particle>();
|
||||||
Game game;
|
Game game;
|
||||||
IGraphicsApi graphics;
|
Random rnd;
|
||||||
int vb;
|
int vb;
|
||||||
|
|
||||||
public ParticleManager( Game game ) {
|
public ParticleManager( Game game ) {
|
||||||
this.game = game;
|
this.game = game;
|
||||||
graphics = game.Graphics;
|
rnd = new Random();
|
||||||
vb = graphics.CreateDynamicVb( VertexFormat.Pos3fTex2fCol4b, 1000 );
|
vb = game.Graphics.CreateDynamicVb( VertexFormat.Pos3fTex2fCol4b, 1000 );
|
||||||
}
|
}
|
||||||
|
|
||||||
VertexPos3fTex2fCol4b[] vertices = new VertexPos3fTex2fCol4b[0];
|
VertexPos3fTex2fCol4b[] vertices = new VertexPos3fTex2fCol4b[0];
|
||||||
public void Render( double delta, float t ) {
|
public void Render( double delta, float t ) {
|
||||||
if( particles.Count == 0 ) return;
|
if( terrainParticles.Count == 0 && rainParticles.Count == 0 ) return;
|
||||||
|
IGraphicsApi graphics = game.Graphics;
|
||||||
int count = particles.Count * 4;
|
|
||||||
if( count > vertices.Length ) {
|
|
||||||
vertices = new VertexPos3fTex2fCol4b[count];
|
|
||||||
}
|
|
||||||
int index = 0;
|
|
||||||
for( int i = 0; i < particles.Count; i++ ) {
|
|
||||||
particles[i].Render( delta, t, vertices, ref index );
|
|
||||||
}
|
|
||||||
|
|
||||||
graphics.Texturing = true;
|
graphics.Texturing = true;
|
||||||
graphics.BindTexture( game.TerrainAtlas.TexId );
|
|
||||||
graphics.AlphaTest = true;
|
graphics.AlphaTest = true;
|
||||||
count = Math.Min( count, 1000 );
|
|
||||||
|
|
||||||
graphics.SetBatchFormat( VertexFormat.Pos3fTex2fCol4b );
|
graphics.SetBatchFormat( VertexFormat.Pos3fTex2fCol4b );
|
||||||
graphics.UpdateDynamicIndexedVb( DrawMode.Triangles, vb, vertices, count, count * 6 / 4 );
|
|
||||||
|
int count = RenderParticles( terrainParticles, delta, t );
|
||||||
|
if( count > 0 ) {
|
||||||
|
graphics.BindTexture( game.TerrainAtlas.TexId );
|
||||||
|
graphics.UpdateDynamicIndexedVb( DrawMode.Triangles, vb, vertices, count, count * 6 / 4 );
|
||||||
|
}
|
||||||
|
count = 0;//RenderParticles( rainParticles, delta, t );
|
||||||
|
if( count > 0 ) {
|
||||||
|
graphics.BindTexture( ParticlesTexId );
|
||||||
|
graphics.UpdateDynamicIndexedVb( DrawMode.Triangles, vb, vertices, count, count * 6 / 4 );
|
||||||
|
}
|
||||||
|
|
||||||
graphics.AlphaTest = false;
|
graphics.AlphaTest = false;
|
||||||
graphics.Texturing = false;
|
graphics.Texturing = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int RenderParticles( List<Particle> particles, double delta, float t ) {
|
||||||
|
int count = particles.Count * 4;
|
||||||
|
if( count > vertices.Length )
|
||||||
|
vertices = new VertexPos3fTex2fCol4b[count];
|
||||||
|
|
||||||
|
int index = 0;
|
||||||
|
for( int i = 0; i < particles.Count; i++ )
|
||||||
|
particles[i].Render( delta, t, vertices, ref index );
|
||||||
|
return Math.Min( count, 1000 );
|
||||||
|
}
|
||||||
|
|
||||||
public void Tick( double delta ) {
|
public void Tick( double delta ) {
|
||||||
|
TickParticles( terrainParticles, delta );
|
||||||
|
//TickParticles( rainParticles, delta );
|
||||||
|
}
|
||||||
|
|
||||||
|
void TickParticles( List<Particle> particles, double delta ) {
|
||||||
for( int i = 0; i < particles.Count; i++ ) {
|
for( int i = 0; i < particles.Count; i++ ) {
|
||||||
Particle particle = particles[i];
|
Particle particle = particles[i];
|
||||||
if( particle.Tick( delta ) ) {
|
if( particle.Tick( delta ) ) {
|
||||||
particles.RemoveAt( i );
|
particles.RemoveAt( i );
|
||||||
i--;
|
i--;
|
||||||
particle.Dispose();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose() {
|
public void Dispose() {
|
||||||
graphics.DeleteDynamicVb( vb );
|
game.Graphics.DeleteDynamicVb( vb );
|
||||||
|
game.Graphics.DeleteTexture( ref ParticlesTexId );
|
||||||
}
|
}
|
||||||
|
|
||||||
public void BreakBlockEffect( Vector3I position, byte block ) {
|
public void BreakBlockEffect( Vector3I position, byte block ) {
|
||||||
@ -62,30 +79,50 @@ namespace ClassicalSharp.Particles {
|
|||||||
int texLoc = game.BlockInfo.GetTextureLoc( block, TileSide.Left );
|
int texLoc = game.BlockInfo.GetTextureLoc( block, TileSide.Left );
|
||||||
TextureRec rec = game.TerrainAtlas.GetTexRec( texLoc );
|
TextureRec rec = game.TerrainAtlas.GetTexRec( texLoc );
|
||||||
|
|
||||||
float invSize = TerrainAtlas2D.invElementSize;
|
const float invSize = TerrainAtlas2D.invElementSize;
|
||||||
int cellsCountX = (int)( 0.25f / invSize );
|
const int cellsCount = (int)((1/4f) / invSize);
|
||||||
int cellsCountY = (int)( 0.25f / invSize );
|
const float elemSize = invSize / 4f;
|
||||||
float elementXSize = invSize * 0.25f;
|
float blockHeight = game.BlockInfo.Height[block];
|
||||||
float elementYSize = invSize * 0.25f;
|
|
||||||
|
|
||||||
Random rnd = new Random();
|
|
||||||
for( int i = 0; i < 25; i++ ) {
|
for( int i = 0; i < 25; i++ ) {
|
||||||
double velX = ( rnd.NextDouble() * 0.8/*5*/ ) - 0.4/*0.25*/;
|
double velX = rnd.NextDouble() * 0.8 - 0.4; // [-0.4, 0.4]
|
||||||
double velZ = ( rnd.NextDouble() * 0.8/*5*/ ) - 0.4/*0.25*/;
|
double velZ = rnd.NextDouble() * 0.8 - 0.4;
|
||||||
double velY = ( rnd.NextDouble() + 0.25 ) * game.BlockInfo.Height[block];
|
double velY = rnd.NextDouble() + 0.2;
|
||||||
Vector3 velocity = new Vector3( (float)velX, (float)velY, (float)velZ );
|
Vector3 velocity = new Vector3( (float)velX, (float)velY, (float)velZ );
|
||||||
double xOffset = rnd.NextDouble() - 0.125;
|
|
||||||
double yOffset = rnd.NextDouble() - 0.125;
|
double xOffset = rnd.NextDouble() - 0.5; // [-0.5, 0.5]
|
||||||
double zOffset = rnd.NextDouble() - 0.125;
|
double yOffset = (rnd.NextDouble() - 0.125) * blockHeight;
|
||||||
Vector3 pos = startPos + new Vector3( (float)xOffset, (float)yOffset, (float)zOffset );
|
double zOffset = rnd.NextDouble() - 0.5;
|
||||||
|
Vector3 pos = startPos + new Vector3( 0.5f + (float)xOffset,
|
||||||
|
(float)yOffset, 0.5f + (float)zOffset );
|
||||||
|
|
||||||
TextureRec particleRec = rec;
|
TextureRec particleRec = rec;
|
||||||
particleRec.U1 = (float)( rec.U1 + rnd.Next( 0, cellsCountX ) * elementXSize );
|
particleRec.U1 = rec.U1 + rnd.Next( 0, cellsCount ) * elemSize;
|
||||||
particleRec.V1 = (float)( rec.V1 + rnd.Next( 0, cellsCountY ) * elementYSize );
|
particleRec.V1 = rec.V1 + rnd.Next( 0, cellsCount ) * elemSize;
|
||||||
particleRec.U2 = particleRec.U1 + elementXSize;
|
particleRec.U2 = particleRec.U1 + elemSize;
|
||||||
particleRec.V2 = particleRec.V1 + elementYSize;
|
particleRec.V2 = particleRec.V1 + elemSize;
|
||||||
double life = 1.5 - rnd.NextDouble();
|
double life = 1.5 - rnd.NextDouble();
|
||||||
|
|
||||||
particles.Add( new TerrainParticle( game, pos, velocity, life, particleRec ) );
|
terrainParticles.Add( new TerrainParticle( game, pos, velocity, life, particleRec ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddRainParticle( Vector3 pos ) {
|
||||||
|
Vector3 startPos = pos;
|
||||||
|
|
||||||
|
for( int i = 0; i < 5; i++ ) {
|
||||||
|
double velX = rnd.NextDouble() * 0.8 - 0.4; // [-0.4, 0.4]
|
||||||
|
double velZ = rnd.NextDouble() * 0.8 - 0.4;
|
||||||
|
double velY = rnd.NextDouble() + 0.2;
|
||||||
|
Vector3 velocity = new Vector3( (float)velX, (float)velY, (float)velZ );
|
||||||
|
|
||||||
|
double xOffset = rnd.NextDouble() - 0.5; // [-0.5, 0.5]
|
||||||
|
double yOffset = rnd.NextDouble() - 0.125;
|
||||||
|
double zOffset = rnd.NextDouble() - 0.5;
|
||||||
|
pos = startPos + new Vector3( 0.5f + (float)xOffset,
|
||||||
|
(float)yOffset, 0.5f + (float)zOffset );
|
||||||
|
double life = 1.5 - rnd.NextDouble();
|
||||||
|
rainParticles.Add( new RainParticle( game, pos, velocity, life ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,8 +24,5 @@ namespace ClassicalSharp.Particles {
|
|||||||
vertices[index++] = new VertexPos3fTex2fCol4b( p222, rec.U2, rec.V1, col );
|
vertices[index++] = new VertexPos3fTex2fCol4b( p222, rec.U2, rec.V1, col );
|
||||||
vertices[index++] = new VertexPos3fTex2fCol4b( p212, rec.U2, rec.V2, col );
|
vertices[index++] = new VertexPos3fTex2fCol4b( p212, rec.U2, rec.V2, col );
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Dispose() {
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,8 +25,5 @@ namespace ClassicalSharp.Particles {
|
|||||||
vertices[index++] = new VertexPos3fTex2fCol4b( p222, rec.U2, rec.V1, col );
|
vertices[index++] = new VertexPos3fTex2fCol4b( p222, rec.U2, rec.V1, col );
|
||||||
vertices[index++] = new VertexPos3fTex2fCol4b( p212, rec.U2, rec.V2, col );
|
vertices[index++] = new VertexPos3fTex2fCol4b( p212, rec.U2, rec.V2, col );
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Dispose() {
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -82,7 +82,7 @@ namespace ClassicalSharp {
|
|||||||
|
|
||||||
last = now;
|
last = now;
|
||||||
if( writer != null ) {
|
if( writer != null ) {
|
||||||
string data = text;//Utils.StripColours( text );
|
string data = Utils.StripColours( text );
|
||||||
string entry = now.ToString( "[yyyy-MM-dd HH:mm:ss] " ) + data;
|
string entry = now.ToString( "[yyyy-MM-dd HH:mm:ss] " ) + data;
|
||||||
writer.WriteLine( entry );
|
writer.WriteLine( entry );
|
||||||
}
|
}
|
||||||
|
@ -126,6 +126,7 @@ namespace ClassicalSharp {
|
|||||||
ViewDistance = Options.GetInt( OptionsKey.ViewDist, 16, 4096, 512 );
|
ViewDistance = Options.GetInt( OptionsKey.ViewDist, 16, 4096, 512 );
|
||||||
InputHandler = new InputHandler( this );
|
InputHandler = new InputHandler( this );
|
||||||
Chat = new ChatLog( this );
|
Chat = new ChatLog( this );
|
||||||
|
ParticleManager = new ParticleManager( this );
|
||||||
HudScale = Options.GetFloat( OptionsKey.HudScale, 0.25f, 5f, 1f );
|
HudScale = Options.GetFloat( OptionsKey.HudScale, 0.25f, 5f, 1f );
|
||||||
ChatScale = Options.GetFloat( OptionsKey.ChatScale, 0.35f, 5f, 1f );
|
ChatScale = Options.GetFloat( OptionsKey.ChatScale, 0.35f, 5f, 1f );
|
||||||
defaultIb = Graphics.MakeDefaultIb();
|
defaultIb = Graphics.MakeDefaultIb();
|
||||||
@ -173,7 +174,6 @@ namespace ClassicalSharp {
|
|||||||
CommandManager = new CommandManager();
|
CommandManager = new CommandManager();
|
||||||
CommandManager.Init( this );
|
CommandManager.Init( this );
|
||||||
SelectionManager = new SelectionManager( this );
|
SelectionManager = new SelectionManager( this );
|
||||||
ParticleManager = new ParticleManager( this );
|
|
||||||
WeatherRenderer = new WeatherRenderer( this );
|
WeatherRenderer = new WeatherRenderer( this );
|
||||||
WeatherRenderer.Init();
|
WeatherRenderer.Init();
|
||||||
BlockHandRenderer = new BlockHandRenderer( this );
|
BlockHandRenderer = new BlockHandRenderer( this );
|
||||||
|
@ -23,6 +23,7 @@ namespace ClassicalSharp {
|
|||||||
float vOffset;
|
float vOffset;
|
||||||
const int extent = 4;
|
const int extent = 4;
|
||||||
VertexPos3fTex2fCol4b[] vertices = new VertexPos3fTex2fCol4b[8 * (extent * 2 + 1) * (extent * 2 + 1)];
|
VertexPos3fTex2fCol4b[] vertices = new VertexPos3fTex2fCol4b[8 * (extent * 2 + 1) * (extent * 2 + 1)];
|
||||||
|
double rainAcc;
|
||||||
|
|
||||||
public void Render( double deltaTime ) {
|
public void Render( double deltaTime ) {
|
||||||
Weather weather = map.Weather;
|
Weather weather = map.Weather;
|
||||||
@ -33,6 +34,7 @@ namespace ClassicalSharp {
|
|||||||
Vector3I pos = Vector3I.Floor( game.LocalPlayer.Position );
|
Vector3I pos = Vector3I.Floor( game.LocalPlayer.Position );
|
||||||
float speed = weather == Weather.Rainy ? 1f : 0.25f;
|
float speed = weather == Weather.Rainy ? 1f : 0.25f;
|
||||||
vOffset = -(float)game.accumulator * speed;
|
vOffset = -(float)game.accumulator * speed;
|
||||||
|
rainAcc += deltaTime;
|
||||||
|
|
||||||
int index = 0;
|
int index = 0;
|
||||||
graphics.AlphaBlending = true;
|
graphics.AlphaBlending = true;
|
||||||
@ -44,10 +46,14 @@ namespace ClassicalSharp {
|
|||||||
float height = Math.Max( game.Map.Height, pos.Y + 64 ) - rainY;
|
float height = Math.Max( game.Map.Height, pos.Y + 64 ) - rainY;
|
||||||
if( height <= 0 ) continue;
|
if( height <= 0 ) continue;
|
||||||
|
|
||||||
|
//if( rainAcc >= 3 )
|
||||||
|
// game.ParticleManager.AddRainParticle( new Vector3( pos.X + dx, rainY, pos.Z + dz ) );
|
||||||
col.A = (byte)Math.Max( 0, AlphaAt( dx * dx + dz * dz ) );
|
col.A = (byte)Math.Max( 0, AlphaAt( dx * dx + dz * dz ) );
|
||||||
MakeRainForSquare( pos.X + dx, rainY, height, pos.Z + dz, col, ref index );
|
MakeRainForSquare( pos.X + dx, rainY, height, pos.Z + dz, col, ref index );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if( rainAcc >= 3 )
|
||||||
|
rainAcc = 0;
|
||||||
|
|
||||||
// fixes crashing on nVidia cards in OpenGL builds.
|
// fixes crashing on nVidia cards in OpenGL builds.
|
||||||
if( index > 0 ) {
|
if( index > 0 ) {
|
||||||
|
@ -78,6 +78,9 @@ namespace ClassicalSharp.TexturePack {
|
|||||||
StreamReader reader = new StreamReader( stream );
|
StreamReader reader = new StreamReader( stream );
|
||||||
game.Animations.ReadAnimationsDescription( reader );
|
game.Animations.ReadAnimationsDescription( reader );
|
||||||
break;
|
break;
|
||||||
|
case "particles.png":
|
||||||
|
UpdateTexture( ref game.ParticleManager.ParticlesTexId,
|
||||||
|
stream, false ); break;
|
||||||
case "default.png":
|
case "default.png":
|
||||||
SetFontBitmap( game, stream );
|
SetFontBitmap( game, stream );
|
||||||
break;
|
break;
|
||||||
|
@ -40,6 +40,17 @@ namespace Launcher2 {
|
|||||||
|
|
||||||
protected override void OnRemovedChar() { FilterList(); }
|
protected override void OnRemovedChar() { FilterList(); }
|
||||||
|
|
||||||
|
protected override void KeyDown( object sender, KeyboardKeyEventArgs e ) {
|
||||||
|
if( e.Key == Key.Enter ) {
|
||||||
|
LauncherTableWidget table = (LauncherTableWidget)widgets[tableIndex];
|
||||||
|
if( table.Count == 1 )
|
||||||
|
widgets[3].Text = table.usedEntries[0].Hash;
|
||||||
|
ConnectToServer( 0, 0 );
|
||||||
|
} else {
|
||||||
|
base.KeyDown( sender, e );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void FilterList() {
|
void FilterList() {
|
||||||
if( lastInput == widgets[1] ) {
|
if( lastInput == widgets[1] ) {
|
||||||
LauncherTableWidget table = (LauncherTableWidget)widgets[tableIndex];
|
LauncherTableWidget table = (LauncherTableWidget)widgets[tableIndex];
|
||||||
|
@ -24,7 +24,7 @@ namespace Launcher2 {
|
|||||||
game.Window.Keyboard.KeyRepeat = true;
|
game.Window.Keyboard.KeyRepeat = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void KeyDown( object sender, KeyboardKeyEventArgs e ) {
|
protected virtual void KeyDown( object sender, KeyboardKeyEventArgs e ) {
|
||||||
if( lastInput != null && e.Key == Key.BackSpace ) {
|
if( lastInput != null && e.Key == Key.BackSpace ) {
|
||||||
if( lastInput.RemoveChar() ) {
|
if( lastInput.RemoveChar() ) {
|
||||||
RedrawLastInput();
|
RedrawLastInput();
|
||||||
|
@ -15,7 +15,7 @@ namespace Launcher2 {
|
|||||||
public Action<string> SelectedChanged;
|
public Action<string> SelectedChanged;
|
||||||
public string SelectedHash;
|
public string SelectedHash;
|
||||||
|
|
||||||
TableEntry[] entries, usedEntries;
|
internal TableEntry[] entries, usedEntries;
|
||||||
internal List<ServerListEntry> servers;
|
internal List<ServerListEntry> servers;
|
||||||
public void SetEntries( List<ServerListEntry> servers ) {
|
public void SetEntries( List<ServerListEntry> servers ) {
|
||||||
entries = new TableEntry[servers.Count];
|
entries = new TableEntry[servers.Count];
|
||||||
@ -56,7 +56,7 @@ namespace Launcher2 {
|
|||||||
public int[] ColumnWidths = { 280, 80, 80 };
|
public int[] ColumnWidths = { 280, 80, 80 };
|
||||||
public int[] DesiredColumnWidths = { 280, 80, 80 };
|
public int[] DesiredColumnWidths = { 280, 80, 80 };
|
||||||
|
|
||||||
struct TableEntry {
|
internal struct TableEntry {
|
||||||
public string Hash, Name, Players, Uptime;
|
public string Hash, Name, Players, Uptime;
|
||||||
public int Y, Height;
|
public int Y, Height;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user