Add animation as blocks are broken

This commit is contained in:
Drew DeVault 2015-09-29 20:39:11 -04:00
parent 53987d2d52
commit 069e80469c
5 changed files with 102 additions and 29 deletions

View File

@ -66,7 +66,7 @@ namespace TrueCraft.Client.Modules
void UnloadChunk(ReadOnlyChunk chunk)
{
Game.PendingMainThreadActions.Add(() =>
Game.Invoke(() =>
{
ActiveMeshes.Remove(chunk.Coordinates);
ChunkMeshes.RemoveAll(m => m.Chunk.Coordinates == chunk.Coordinates);
@ -80,7 +80,7 @@ namespace TrueCraft.Client.Modules
case "Position":
var sorter = new ChunkRenderer.ChunkSorter(new Coordinates3D(
(int)Game.Client.Position.X, 0, (int)Game.Client.Position.Z));
Game.PendingMainThreadActions.Add(() => ChunkMeshes.Sort(sorter));
Game.Invoke(() => ChunkMeshes.Sort(sorter));
break;
}
}

View File

@ -6,6 +6,7 @@ using Microsoft.Xna.Framework;
using XVector3 = Microsoft.Xna.Framework.Vector3;
using TVector3 = TrueCraft.API.Vector3;
using TRay = TrueCraft.API.Ray;
using TrueCraft.Core.Logic.Blocks;
namespace TrueCraft.Client.Modules
{
@ -14,8 +15,13 @@ namespace TrueCraft.Client.Modules
public TrueCraftGame Game { get; set; }
private BasicEffect HighlightEffect { get; set; }
private AlphaTestEffect DestructionEffect { get; set; }
private Mesh ProgressMesh { get; set; }
private int Progress { get; set; }
private static readonly RasterizerState RasterizerState;
private static readonly VertexPositionColor[] CubeVerticies;
private static readonly short[] CubeIndicies;
private static readonly BlendState DestructionBlendState;
static HighlightModule()
{
@ -37,6 +43,18 @@ namespace TrueCraft.Client.Modules
0, 4, 4, 7, 7, 6, 6, 2,
1, 5, 5, 4, 3, 7, 6, 5
};
DestructionBlendState = new BlendState
{
ColorSourceBlend = Blend.DestinationColor,
ColorDestinationBlend = Blend.SourceColor,
AlphaSourceBlend = Blend.DestinationAlpha,
AlphaDestinationBlend = Blend.SourceAlpha
};
RasterizerState = new RasterizerState
{
DepthBias = -3,
SlopeScaleDepthBias = -3
};
}
public HighlightModule(TrueCraftGame game)
@ -44,6 +62,29 @@ namespace TrueCraft.Client.Modules
Game = game;
HighlightEffect = new BasicEffect(Game.GraphicsDevice);
HighlightEffect.VertexColorEnabled = true;
DestructionEffect = new AlphaTestEffect(Game.GraphicsDevice);
DestructionEffect.Texture = game.TextureMapper.GetTexture("terrain.png");
DestructionEffect.ReferenceAlpha = 1;
GenerateProgressMesh();
}
private void GenerateProgressMesh()
{
int[] indicies;
var texCoords = new Vector2(Progress, 15);
var texture = new[]
{
texCoords + Vector2.UnitX + Vector2.UnitY,
texCoords + Vector2.UnitY,
texCoords,
texCoords + Vector2.UnitX
};
for (int i = 0; i < texture.Length; i++)
texture[i] *= new Vector2(16f / 256f);
var verticies = BlockRenderer.CreateUniformCube(XVector3.Zero,
texture, VisibleFaces.All, 0, out indicies, Color.White);
ProgressMesh = new Mesh(Game, verticies, indicies);
}
public void Update(GameTime gameTime)
@ -62,10 +103,7 @@ namespace TrueCraft.Client.Modules
{
Game.HighlightedBlock = cast.Item1;
Game.HighlightedBlockFace = cast.Item2;
HighlightEffect.World =
Matrix.CreateTranslation(new XVector3(-0.5f)) *
Matrix.CreateScale(1.01f) *
Matrix.CreateTranslation(new XVector3(0.5f)) *
HighlightEffect.World = DestructionEffect.World =
Matrix.CreateTranslation(new XVector3(cast.Item1.X, cast.Item1.Y, cast.Item1.Z));
}
}
@ -73,9 +111,11 @@ namespace TrueCraft.Client.Modules
public void Draw(GameTime gameTime)
{
Game.Camera.ApplyTo(HighlightEffect);
Game.Camera.ApplyTo(DestructionEffect);
if (Game.HighlightedBlock != -Coordinates3D.One)
{
Game.GraphicsDevice.RasterizerState = RasterizerState;
foreach (var pass in HighlightEffect.CurrentTechnique.Passes)
{
pass.Apply();
@ -84,6 +124,26 @@ namespace TrueCraft.Client.Modules
CubeVerticies.Length, CubeIndicies, 0, CubeIndicies.Length / 2);
}
}
if (Game.EndDigging != DateTime.MaxValue)
{
var diff = Game.EndDigging - DateTime.UtcNow;
var total = Game.EndDigging - Game.StartDigging;
var progress = (int)(diff.TotalMilliseconds / total.TotalMilliseconds * 10);
progress = -(progress - 5) + 5;
if (progress > 9)
progress = 9;
if (progress != Progress)
{
Progress = progress;
GenerateProgressMesh();
}
Game.GraphicsDevice.BlendState = DestructionBlendState;
ProgressMesh.Draw(DestructionEffect);
Game.GraphicsDevice.BlendState = BlendState.AlphaBlend;
Game.GraphicsDevice.RasterizerState = RasterizerState.CullCounterClockwise;
}
}
}
}

View File

@ -14,10 +14,7 @@ namespace TrueCraft.Client.Modules
public class PlayerControlModule : IInputModule
{
private TrueCraftGame Game { get; set; }
private DateTime StartDigging { get; set; }
private DateTime NextAnimation { get; set; }
private DateTime EndDigging { get; set; }
private Coordinates3D TargetBlock { get; set; }
private XVector3 Delta { get; set; }
private bool Capture { get; set; }
@ -25,9 +22,9 @@ namespace TrueCraft.Client.Modules
{
Game = game;
Capture = true;
StartDigging = DateTime.MinValue;
EndDigging = DateTime.MaxValue;
TargetBlock = -Coordinates3D.One;
Game.StartDigging = DateTime.MinValue;
Game.EndDigging = DateTime.MaxValue;
Game.TargetBlock = -Coordinates3D.One;
NextAnimation = DateTime.MaxValue;
}
@ -138,7 +135,7 @@ namespace TrueCraft.Client.Modules
switch (e.Button)
{
case MouseButton.Left:
if (StartDigging == DateTime.MinValue) // Would like to start digging a block
if (Game.StartDigging == DateTime.MinValue) // Would like to start digging a block
{
var target = Game.HighlightedBlock;
if (target != -Coordinates3D.One)
@ -149,11 +146,11 @@ namespace TrueCraft.Client.Modules
var target = Game.HighlightedBlock;
if (target == -Coordinates3D.One) // Cancel
{
StartDigging = DateTime.MinValue;
EndDigging = DateTime.MaxValue;
TargetBlock = -Coordinates3D.One;
Game.StartDigging = DateTime.MinValue;
Game.EndDigging = DateTime.MaxValue;
Game.TargetBlock = -Coordinates3D.One;
}
else if (target != TargetBlock) // Change target
else if (target != Game.TargetBlock) // Change target
BeginDigging(target);
}
return true;
@ -163,15 +160,16 @@ namespace TrueCraft.Client.Modules
private void BeginDigging(Coordinates3D target)
{
// TODO: Adjust digging time to compensate for latency
var block = Game.Client.World.GetBlockID(target);
TargetBlock = target;
StartDigging = DateTime.UtcNow;
Game.TargetBlock = target;
Game.StartDigging = DateTime.UtcNow;
short damage;
EndDigging = StartDigging.AddMilliseconds(
Game.EndDigging = Game.StartDigging.AddMilliseconds(
BlockProvider.GetHarvestTime(block, 0, out damage));
Game.Client.QueuePacket(new PlayerDiggingPacket(
PlayerDiggingPacket.Action.StartDigging,
TargetBlock.X, (sbyte)TargetBlock.Y, TargetBlock.Z,
Game.TargetBlock.X, (sbyte)Game.TargetBlock.Y, Game.TargetBlock.Z,
Game.HighlightedBlockFace));
NextAnimation = DateTime.UtcNow.AddSeconds(0.25);
}
@ -181,9 +179,9 @@ namespace TrueCraft.Client.Modules
switch (e.Button)
{
case MouseButton.Left:
StartDigging = DateTime.MinValue;
EndDigging = DateTime.MaxValue;
TargetBlock = -Coordinates3D.One;
Game.StartDigging = DateTime.MinValue;
Game.EndDigging = DateTime.MaxValue;
Game.TargetBlock = -Coordinates3D.One;
return true;
}
return false;
@ -205,7 +203,7 @@ namespace TrueCraft.Client.Modules
}
else
Game.Client.Velocity *= new TVector3(0, 1, 0);
if (EndDigging != DateTime.MaxValue)
if (Game.EndDigging != DateTime.MaxValue)
{
if (NextAnimation < DateTime.UtcNow)
{
@ -213,12 +211,13 @@ namespace TrueCraft.Client.Modules
Game.Client.QueuePacket(new AnimationPacket(Game.Client.EntityID,
AnimationPacket.PlayerAnimation.SwingArm));
}
if (DateTime.UtcNow > EndDigging && Game.HighlightedBlock == TargetBlock)
if (DateTime.UtcNow > Game.EndDigging && Game.HighlightedBlock == Game.TargetBlock)
{
Game.Client.QueuePacket(new PlayerDiggingPacket(
PlayerDiggingPacket.Action.StopDigging,
TargetBlock.X, (sbyte)TargetBlock.Y, TargetBlock.Z,
Game.TargetBlock.X, (sbyte)Game.TargetBlock.Y, Game.TargetBlock.Z,
Game.HighlightedBlockFace));
Game.EndDigging = DateTime.MaxValue;
}
}
}

View File

@ -47,7 +47,7 @@ namespace TrueCraft.Client.Rendering
if (_vertices != null)
_vertices.Dispose();
_game.PendingMainThreadActions.Add(() =>
_game.Invoke(() =>
{
_vertices = new VertexBuffer(_graphicsDevice, VertexPositionNormalColorTexture.VertexDeclaration,
(value.Length + 1), BufferUsage.WriteOnly);
@ -132,7 +132,7 @@ namespace TrueCraft.Client.Rendering
if (_indices[index] != null)
_indices[index].Dispose();
_game.PendingMainThreadActions.Add(() =>
_game.Invoke(() =>
{
_indices[index] = new IndexBuffer(_graphicsDevice, typeof(int),
(indices.Length + 1), BufferUsage.WriteOnly);

View File

@ -19,6 +19,7 @@ using TrueCraft.Client.Rendering;
using TVector3 = TrueCraft.API.Vector3;
using XVector3 = Microsoft.Xna.Framework.Vector3;
using TrueCraft.Core.Logic;
using System.Threading;
namespace TrueCraft.Client
{
@ -34,12 +35,16 @@ namespace TrueCraft.Client
public float ScaleFactor { get; set; }
public Coordinates3D HighlightedBlock { get; set; }
public BlockFace HighlightedBlockFace { get; set; }
public DateTime StartDigging { get; set; }
public DateTime EndDigging { get; set; }
public Coordinates3D TargetBlock { get; set; }
private List<IGameplayModule> Modules { get; set; }
private SpriteBatch SpriteBatch { get; set; }
private KeyboardHandler KeyboardComponent { get; set; }
private MouseHandler MouseComponent { get; set; }
private RenderTarget2D RenderTarget { get; set; }
private int ThreadID { get; set; }
private FontRenderer Pixel { get; set; }
private IPEndPoint EndPoint { get; set; }
@ -139,6 +144,15 @@ namespace TrueCraft.Client
SpriteBatch = new SpriteBatch(GraphicsDevice);
Window_ClientSizeChanged(null, null);
ThreadID = Thread.CurrentThread.ManagedThreadId;
}
public void Invoke(Action action)
{
if (ThreadID == Thread.CurrentThread.ManagedThreadId)
action();
else
PendingMainThreadActions.Add(action);
}
private void CreateRenderTarget()