mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-01-24 18:13:15 -05:00
135 lines
No EOL
4 KiB
C#
135 lines
No EOL
4 KiB
C#
// Copyright 2014-2017 ClassicalSharp | Licensed under BSD-3
|
|
using System;
|
|
using ClassicalSharp.Events;
|
|
using ClassicalSharp.Model;
|
|
using OpenTK;
|
|
|
|
#if USE16_BIT
|
|
using BlockID = System.UInt16;
|
|
#else
|
|
using BlockID = System.Byte;
|
|
#endif
|
|
|
|
namespace ClassicalSharp.Renderers {
|
|
|
|
internal class HeldBlockAnimation {
|
|
|
|
internal bool doAnim, digAnim, swingAnim;
|
|
internal float angleY = 0;
|
|
internal Vector3 pos;
|
|
|
|
double time, period = 0.25, speed = Math.PI / 0.25;
|
|
BlockID lastType;
|
|
Game game;
|
|
HeldBlockRenderer held;
|
|
|
|
internal void Init(Game game, HeldBlockRenderer held) {
|
|
this.game = game;
|
|
this.held = held;
|
|
lastType = game.Inventory.Selected;
|
|
|
|
game.Events.HeldBlockChanged += DoSwitchBlockAnim;
|
|
game.UserEvents.BlockChanged += BlockChanged;
|
|
}
|
|
|
|
internal void Dispose() {
|
|
game.Events.HeldBlockChanged -= DoSwitchBlockAnim;
|
|
game.UserEvents.BlockChanged -= BlockChanged;
|
|
}
|
|
|
|
/// <summary> Sets the current animation state of the held block.<br/>
|
|
/// true = left mouse pressed, false = right mouse pressed. </summary>
|
|
internal void SetClickAnim(bool dig) {
|
|
// TODO: timing still not quite right, rotate2 still not quite right
|
|
ResetAnimationState(true, dig ? 0.35 : 0.25);
|
|
swingAnim = false;
|
|
digAnim = dig;
|
|
doAnim = true;
|
|
// Start place animation at bottom of cycle
|
|
if (!dig) time = period / 2;
|
|
}
|
|
|
|
void DoSwitchBlockAnim(object sender, EventArgs e) {
|
|
if (swingAnim) {
|
|
// Like graph -sin(x) : x=0.5 and x=2.5 have same y values
|
|
// but increasing x causes y to change in opposite directions
|
|
if (time > period * 0.5)
|
|
time = period - time;
|
|
} else {
|
|
ResetAnimationState(false, 0.25);
|
|
doAnim = true;
|
|
swingAnim = true;
|
|
}
|
|
}
|
|
|
|
void BlockChanged(object sender, BlockChangedEventArgs e) {
|
|
if (e.Block == 0) return;
|
|
SetClickAnim(false);
|
|
}
|
|
|
|
internal void Update(double delta, Vector3 last) {
|
|
if (swingAnim || !digAnim) {
|
|
pos.Y = -0.4f * (float)Math.Sin(time * speed);
|
|
if (swingAnim) {
|
|
// i.e. the block has gone to bottom of screen and is now returning back up
|
|
// at this point we switch over to the new held block.
|
|
if (pos.Y > last.Y)
|
|
lastType = held.type;
|
|
held.type = lastType;
|
|
}
|
|
} else {
|
|
if (time >= period * 0.25) DigSecondCycle();
|
|
else DigFirstCycle();
|
|
}
|
|
time += delta;
|
|
if (time > period)
|
|
ResetAnimationState(true, 0.25);
|
|
}
|
|
|
|
// Based off incredible gifs from (Thanks goodlyay!)
|
|
// https://dl.dropboxusercontent.com/s/iuazpmpnr89zdgb/slowBreakTranslate.gif
|
|
// https://dl.dropboxusercontent.com/s/z7z8bset914s0ij/slowBreakRotate1.gif
|
|
// https://dl.dropboxusercontent.com/s/pdq79gkzntquld1/slowBreakRotate2.gif
|
|
// https://dl.dropboxusercontent.com/s/w1ego7cy7e5nrk1/slowBreakFull.gif
|
|
void DigFirstCycle() {
|
|
double angle = time * speed;
|
|
pos.X = -0.325f * (float)Math.Sin(angle * 2);
|
|
pos.Y = 0.20f * (float)Math.Sin(angle * 2 * 2);
|
|
pos.Z = -0.325f * (float)Math.Sin(angle * 2);
|
|
|
|
angleY = -90 * (float)Math.Sin(angle * 2);
|
|
}
|
|
|
|
void DigSecondCycle() {
|
|
// Need to adjust angle so it starts at same point and of first cycle
|
|
// And finishes cycle at original position
|
|
double endFirst = period * 0.25;
|
|
double angle = (endFirst * 2 + (time - endFirst) * 0.66667) * speed;
|
|
|
|
pos.X = -0.325f * (float)Math.Sin(angle);
|
|
pos.Y = 0.25f * (float)Math.Sin(angle * 2);
|
|
pos.Z = -0.325f * (float)Math.Sin(angle);
|
|
|
|
// For second cycle, rotate the block from 0-->15 then back to 15-->0.
|
|
float rotX = Math.Max(0, (float)angle - 90 * Utils.Deg2Rad);
|
|
if (rotX >= 45 * Utils.Deg2Rad) rotX = 90 * Utils.Deg2Rad - rotX;
|
|
|
|
held.held.RotX = (rotX * 0.33333f) * Utils.Rad2Deg;
|
|
angleY = -90 * (float)Math.Sin(angle);
|
|
}
|
|
|
|
void ResetAnimationState(bool updateLastType, double period) {
|
|
time = 0;
|
|
doAnim = false;
|
|
swingAnim = false;
|
|
pos = Vector3.Zero;
|
|
angleY = 0;
|
|
this.period = period;
|
|
speed = Math.PI / period;
|
|
|
|
if (updateLastType)
|
|
lastType = game.Inventory.Selected;
|
|
pos = Vector3.Zero;
|
|
}
|
|
}
|
|
} |