diff --git a/osu.Game.Modes.Taiko/Objects/Drawable/DrawableHit.cs b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableHit.cs
new file mode 100644
index 0000000000..caf4fee335
--- /dev/null
+++ b/osu.Game.Modes.Taiko/Objects/Drawable/DrawableHit.cs
@@ -0,0 +1,82 @@
+using OpenTK.Input;
+using osu.Framework.Input;
+using osu.Game.Modes.Objects.Drawables;
+using osu.Game.Modes.Taiko.Judgements;
+using System;
+using System.Collections.Generic;
+
+namespace osu.Game.Modes.Taiko.Objects.Drawable
+{
+ public abstract class DrawableHit : DrawableTaikoHitObject
+ {
+ ///
+ /// A list of keys which can result in hits for this HitObject.
+ ///
+ protected abstract List HitKeys { get; }
+
+ ///
+ /// A list of keys which this hit object will accept. These are the standard Taiko keys for now.
+ /// These should be moved to bindings later.
+ ///
+ private List validKeys = new List(new[] { Key.D, Key.F, Key.J, Key.K });
+
+ ///
+ /// Whether the last key pressed is a valid hit key.
+ ///
+ private bool validKeyPressed;
+
+ protected DrawableHit(TaikoHitObject hitObject)
+ : base(hitObject)
+ {
+ }
+
+ protected override void CheckJudgement(bool userTriggered)
+ {
+ if (!userTriggered)
+ {
+ if (Judgement.TimeOffset > HitObject.HitWindowGood)
+ Judgement.Result = HitResult.Miss;
+ return;
+ }
+
+ double hitOffset = Math.Abs(Judgement.TimeOffset);
+
+ if (hitOffset > HitObject.HitWindowMiss)
+ return;
+
+ if (!validKeyPressed)
+ Judgement.Result = HitResult.Miss;
+ else if (hitOffset < HitObject.HitWindowGood)
+ {
+ Judgement.Result = HitResult.Hit;
+ Judgement.Score = hitOffset < HitObject.HitWindowGreat ? TaikoScoreResult.Great : TaikoScoreResult.Good;
+ }
+ else
+ Judgement.Result = HitResult.Miss;
+ }
+
+ protected virtual bool HandleKeyPress(Key key)
+ {
+ if (Judgement.Result.HasValue)
+ return false;
+
+ validKeyPressed = HitKeys.Contains(key);
+
+ return UpdateJudgement(true);
+ }
+
+ protected sealed override bool OnKeyDown(InputState state, KeyDownEventArgs args)
+ {
+ // Make sure we don't handle held-down keys
+ if (args.Repeat)
+ return false;
+
+ // Check if we've pressed a valid taiko key
+ if (!validKeys.Contains(args.Key))
+ return false;
+
+ // Handle it!
+ return HandleKeyPress(args.Key);
+ }
+ }
+}
diff --git a/osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj b/osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj
index aab9a17276..dbd58d4666 100644
--- a/osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj
+++ b/osu.Game.Modes.Taiko/osu.Game.Modes.Taiko.csproj
@@ -50,6 +50,7 @@
+