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

View File

@ -6,6 +6,7 @@ using Microsoft.Xna.Framework;
using XVector3 = Microsoft.Xna.Framework.Vector3; using XVector3 = Microsoft.Xna.Framework.Vector3;
using TVector3 = TrueCraft.API.Vector3; using TVector3 = TrueCraft.API.Vector3;
using TRay = TrueCraft.API.Ray; using TRay = TrueCraft.API.Ray;
using TrueCraft.Core.Logic.Blocks;
namespace TrueCraft.Client.Modules namespace TrueCraft.Client.Modules
{ {
@ -14,8 +15,13 @@ namespace TrueCraft.Client.Modules
public TrueCraftGame Game { get; set; } public TrueCraftGame Game { get; set; }
private BasicEffect HighlightEffect { 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 VertexPositionColor[] CubeVerticies;
private static readonly short[] CubeIndicies; private static readonly short[] CubeIndicies;
private static readonly BlendState DestructionBlendState;
static HighlightModule() static HighlightModule()
{ {
@ -37,6 +43,18 @@ namespace TrueCraft.Client.Modules
0, 4, 4, 7, 7, 6, 6, 2, 0, 4, 4, 7, 7, 6, 6, 2,
1, 5, 5, 4, 3, 7, 6, 5 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) public HighlightModule(TrueCraftGame game)
@ -44,6 +62,29 @@ namespace TrueCraft.Client.Modules
Game = game; Game = game;
HighlightEffect = new BasicEffect(Game.GraphicsDevice); HighlightEffect = new BasicEffect(Game.GraphicsDevice);
HighlightEffect.VertexColorEnabled = true; 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) public void Update(GameTime gameTime)
@ -62,10 +103,7 @@ namespace TrueCraft.Client.Modules
{ {
Game.HighlightedBlock = cast.Item1; Game.HighlightedBlock = cast.Item1;
Game.HighlightedBlockFace = cast.Item2; Game.HighlightedBlockFace = cast.Item2;
HighlightEffect.World = HighlightEffect.World = DestructionEffect.World =
Matrix.CreateTranslation(new XVector3(-0.5f)) *
Matrix.CreateScale(1.01f) *
Matrix.CreateTranslation(new XVector3(0.5f)) *
Matrix.CreateTranslation(new XVector3(cast.Item1.X, cast.Item1.Y, cast.Item1.Z)); 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) public void Draw(GameTime gameTime)
{ {
Game.Camera.ApplyTo(HighlightEffect); Game.Camera.ApplyTo(HighlightEffect);
Game.Camera.ApplyTo(DestructionEffect);
if (Game.HighlightedBlock != -Coordinates3D.One) if (Game.HighlightedBlock != -Coordinates3D.One)
{ {
Game.GraphicsDevice.RasterizerState = RasterizerState;
foreach (var pass in HighlightEffect.CurrentTechnique.Passes) foreach (var pass in HighlightEffect.CurrentTechnique.Passes)
{ {
pass.Apply(); pass.Apply();
@ -84,6 +124,26 @@ namespace TrueCraft.Client.Modules
CubeVerticies.Length, CubeIndicies, 0, CubeIndicies.Length / 2); 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 public class PlayerControlModule : IInputModule
{ {
private TrueCraftGame Game { get; set; } private TrueCraftGame Game { get; set; }
private DateTime StartDigging { get; set; }
private DateTime NextAnimation { get; set; } private DateTime NextAnimation { get; set; }
private DateTime EndDigging { get; set; }
private Coordinates3D TargetBlock { get; set; }
private XVector3 Delta { get; set; } private XVector3 Delta { get; set; }
private bool Capture { get; set; } private bool Capture { get; set; }
@ -25,9 +22,9 @@ namespace TrueCraft.Client.Modules
{ {
Game = game; Game = game;
Capture = true; Capture = true;
StartDigging = DateTime.MinValue; Game.StartDigging = DateTime.MinValue;
EndDigging = DateTime.MaxValue; Game.EndDigging = DateTime.MaxValue;
TargetBlock = -Coordinates3D.One; Game.TargetBlock = -Coordinates3D.One;
NextAnimation = DateTime.MaxValue; NextAnimation = DateTime.MaxValue;
} }
@ -138,7 +135,7 @@ namespace TrueCraft.Client.Modules
switch (e.Button) switch (e.Button)
{ {
case MouseButton.Left: 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; var target = Game.HighlightedBlock;
if (target != -Coordinates3D.One) if (target != -Coordinates3D.One)
@ -149,11 +146,11 @@ namespace TrueCraft.Client.Modules
var target = Game.HighlightedBlock; var target = Game.HighlightedBlock;
if (target == -Coordinates3D.One) // Cancel if (target == -Coordinates3D.One) // Cancel
{ {
StartDigging = DateTime.MinValue; Game.StartDigging = DateTime.MinValue;
EndDigging = DateTime.MaxValue; Game.EndDigging = DateTime.MaxValue;
TargetBlock = -Coordinates3D.One; Game.TargetBlock = -Coordinates3D.One;
} }
else if (target != TargetBlock) // Change target else if (target != Game.TargetBlock) // Change target
BeginDigging(target); BeginDigging(target);
} }
return true; return true;
@ -163,15 +160,16 @@ namespace TrueCraft.Client.Modules
private void BeginDigging(Coordinates3D target) private void BeginDigging(Coordinates3D target)
{ {
// TODO: Adjust digging time to compensate for latency
var block = Game.Client.World.GetBlockID(target); var block = Game.Client.World.GetBlockID(target);
TargetBlock = target; Game.TargetBlock = target;
StartDigging = DateTime.UtcNow; Game.StartDigging = DateTime.UtcNow;
short damage; short damage;
EndDigging = StartDigging.AddMilliseconds( Game.EndDigging = Game.StartDigging.AddMilliseconds(
BlockProvider.GetHarvestTime(block, 0, out damage)); BlockProvider.GetHarvestTime(block, 0, out damage));
Game.Client.QueuePacket(new PlayerDiggingPacket( Game.Client.QueuePacket(new PlayerDiggingPacket(
PlayerDiggingPacket.Action.StartDigging, PlayerDiggingPacket.Action.StartDigging,
TargetBlock.X, (sbyte)TargetBlock.Y, TargetBlock.Z, Game.TargetBlock.X, (sbyte)Game.TargetBlock.Y, Game.TargetBlock.Z,
Game.HighlightedBlockFace)); Game.HighlightedBlockFace));
NextAnimation = DateTime.UtcNow.AddSeconds(0.25); NextAnimation = DateTime.UtcNow.AddSeconds(0.25);
} }
@ -181,9 +179,9 @@ namespace TrueCraft.Client.Modules
switch (e.Button) switch (e.Button)
{ {
case MouseButton.Left: case MouseButton.Left:
StartDigging = DateTime.MinValue; Game.StartDigging = DateTime.MinValue;
EndDigging = DateTime.MaxValue; Game.EndDigging = DateTime.MaxValue;
TargetBlock = -Coordinates3D.One; Game.TargetBlock = -Coordinates3D.One;
return true; return true;
} }
return false; return false;
@ -205,7 +203,7 @@ namespace TrueCraft.Client.Modules
} }
else else
Game.Client.Velocity *= new TVector3(0, 1, 0); Game.Client.Velocity *= new TVector3(0, 1, 0);
if (EndDigging != DateTime.MaxValue) if (Game.EndDigging != DateTime.MaxValue)
{ {
if (NextAnimation < DateTime.UtcNow) if (NextAnimation < DateTime.UtcNow)
{ {
@ -213,12 +211,13 @@ namespace TrueCraft.Client.Modules
Game.Client.QueuePacket(new AnimationPacket(Game.Client.EntityID, Game.Client.QueuePacket(new AnimationPacket(Game.Client.EntityID,
AnimationPacket.PlayerAnimation.SwingArm)); AnimationPacket.PlayerAnimation.SwingArm));
} }
if (DateTime.UtcNow > EndDigging && Game.HighlightedBlock == TargetBlock) if (DateTime.UtcNow > Game.EndDigging && Game.HighlightedBlock == Game.TargetBlock)
{ {
Game.Client.QueuePacket(new PlayerDiggingPacket( Game.Client.QueuePacket(new PlayerDiggingPacket(
PlayerDiggingPacket.Action.StopDigging, PlayerDiggingPacket.Action.StopDigging,
TargetBlock.X, (sbyte)TargetBlock.Y, TargetBlock.Z, Game.TargetBlock.X, (sbyte)Game.TargetBlock.Y, Game.TargetBlock.Z,
Game.HighlightedBlockFace)); Game.HighlightedBlockFace));
Game.EndDigging = DateTime.MaxValue;
} }
} }
} }

View File

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

View File

@ -19,6 +19,7 @@ using TrueCraft.Client.Rendering;
using TVector3 = TrueCraft.API.Vector3; using TVector3 = TrueCraft.API.Vector3;
using XVector3 = Microsoft.Xna.Framework.Vector3; using XVector3 = Microsoft.Xna.Framework.Vector3;
using TrueCraft.Core.Logic; using TrueCraft.Core.Logic;
using System.Threading;
namespace TrueCraft.Client namespace TrueCraft.Client
{ {
@ -34,12 +35,16 @@ namespace TrueCraft.Client
public float ScaleFactor { get; set; } public float ScaleFactor { get; set; }
public Coordinates3D HighlightedBlock { get; set; } public Coordinates3D HighlightedBlock { get; set; }
public BlockFace HighlightedBlockFace { 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 List<IGameplayModule> Modules { get; set; }
private SpriteBatch SpriteBatch { get; set; } private SpriteBatch SpriteBatch { get; set; }
private KeyboardHandler KeyboardComponent { get; set; } private KeyboardHandler KeyboardComponent { get; set; }
private MouseHandler MouseComponent { get; set; } private MouseHandler MouseComponent { get; set; }
private RenderTarget2D RenderTarget { get; set; } private RenderTarget2D RenderTarget { get; set; }
private int ThreadID { get; set; }
private FontRenderer Pixel { get; set; } private FontRenderer Pixel { get; set; }
private IPEndPoint EndPoint { get; set; } private IPEndPoint EndPoint { get; set; }
@ -139,6 +144,15 @@ namespace TrueCraft.Client
SpriteBatch = new SpriteBatch(GraphicsDevice); SpriteBatch = new SpriteBatch(GraphicsDevice);
Window_ClientSizeChanged(null, null); 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() private void CreateRenderTarget()