Add proper sounds, fix block models, remove vertical water on map edges.

This commit is contained in:
UnknownShadow200 2015-12-03 20:35:40 +11:00
parent f06a0dda88
commit 2e317c4b99
22 changed files with 164 additions and 183 deletions

View File

@ -23,7 +23,7 @@ namespace ClassicalSharp {
Make( -140, -150, "Use sound (WIP)", Anchor.Centre, OnWidgetClick,
g => g.UseSound ? "yes" : "no",
(g, v) => { g.UseSound = v == "yes";
g.AudioManager.SetSound( g.UseSound ); } ),
g.AudioPlayer.SetSound( g.UseSound ); } ),
Make( -140, -100, "Show hover names", Anchor.Centre, OnWidgetClick,
g => g.Players.ShowHoveredNames ? "yes" : "no",
@ -57,7 +57,7 @@ namespace ClassicalSharp {
Make( 140, -150, "Use music", Anchor.Centre, OnWidgetClick,
g => g.UseMusic ? "yes" : "no",
(g, v) => { g.UseMusic = v == "yes";
g.AudioManager.SetMusic( g.UseMusic );
g.AudioPlayer.SetMusic( g.UseMusic );
Options.Set( OptionsKey.UseMusic, v == "yes" ); }),
Make( 140, -100, "View bobbing", Anchor.Centre, OnWidgetClick,

View File

@ -1,97 +0,0 @@
using System;
using System.IO;
using System.Threading;
using OpenTK;
using SharpWave;
using SharpWave.Codecs;
using SharpWave.Codecs.Vorbis;
namespace ClassicalSharp.Audio {
public sealed partial class AudioManager {
Soundboard digBoard, stepBoard;
public void SetSound( bool enabled ) {
if( enabled )
InitSound();
else
DisposeSound();
}
void InitSound() {
disposingSound = false;
if( digBoard == null )
InitSoundboards();
digChunk.Data = digBoard.Data;
stepChunk.Data = stepBoard.Data;
soundThread = MakeThread( DoSoundThread, ref soundOut,
"ClassicalSharp.DoSound" );
}
object soundLock = new object();
Sound digSound = null, stepSound = null;
AudioChunk digChunk = new AudioChunk(),
stepChunk = new AudioChunk();
void DoSoundThread() {
while( !disposingSound ) {
bool playDig = false, playStep = false;
lock( soundLock ) {
MakeSound( ref digSound, ref playDig, digChunk );
MakeSound( ref stepSound, ref playStep, stepChunk );
}
if( playDig )
soundOut.PlayRaw( digChunk );
if( playStep )
soundOut.PlayRaw( stepChunk );
if( !(playDig || playStep) )
Thread.Sleep( 1 );
}
}
public void PlayDigSound( SoundType type ) {
PlaySound( type, digBoard, ref digSound );
}
public void PlayStepSound( SoundType type ) {
PlaySound( type, stepBoard, ref stepSound );
}
void PlaySound( SoundType type, Soundboard board, ref Sound target ) {
if( type == SoundType.None || soundOut == null )
return;
lock( soundLock )
target = board.PlayRandomSound( type );
}
void MakeSound( ref Sound src, ref bool play, AudioChunk target ) {
if( src == null ) return;
play = true;
target.Frequency = src.SampleRate;
target.BitsPerSample = src.BitsPerSample;
target.Channels = src.Channels;
target.BytesOffset = src.Offset;
target.BytesUsed = src.Length;
src = null;
}
void DisposeSound() {
disposingSound = true;
DisposeOf( ref soundOut, ref soundThread );
digChunk.Data = null;
stepChunk.Data = null;
}
void InitSoundboards() {
digBoard = new Soundboard();
digBoard.Init( "dig" );
stepBoard = new Soundboard();
stepBoard.Init( "step" );
}
}
}

View File

@ -0,0 +1,110 @@
using System;
using System.IO;
using System.Threading;
using OpenTK;
using SharpWave;
using SharpWave.Codecs;
using SharpWave.Codecs.Vorbis;
namespace ClassicalSharp.Audio {
public sealed partial class AudioPlayer {
Soundboard digBoard, stepBoard;
const int maxSounds = 10;
Sound[] pending;
int pendingCount;
public void SetSound( bool enabled ) {
if( enabled )
InitSound();
else
DisposeSound();
}
void InitSound() {
disposingSound = false;
if( digBoard == null )
InitSoundboards();
soundContainer = new BinContainer( 44100, maxSounds );
pending = new Sound[maxSounds];
soundCodec = (BinCodec)soundContainer.GetAudioCodec();
soundThread = MakeThread( DoSoundThread, ref soundOut,
"ClassicalSharp.DoSound" );
}
EventWaitHandle soundHandle = new EventWaitHandle( false, EventResetMode.AutoReset );
BinContainer soundContainer;
BinCodec soundCodec;
void DoSoundThread() {
while( !disposingSound ) {
soundHandle.WaitOne();
if( disposingSound ) break;
soundOut.PlayStreaming( soundContainer );
}
}
public void Tick( double delta ) {
if( pendingCount > 0 ) {
Sound snd = pending[0];
byte[] data = snd.Metadata == 1 ? digBoard.Data : stepBoard.Data;
soundCodec.AddSound( data, snd.Offset, snd.Length, snd.Channels );
RemoveFirstPendingSound();
soundHandle.Set();
}
}
public void PlayDigSound( SoundType type ) { PlaySound( type, digBoard ); }
public void PlayStepSound( SoundType type ) { PlaySound( type, stepBoard ); }
void PlaySound( SoundType type, Soundboard board ) {
if( type == SoundType.None || soundOut == null )
return;
Sound target = board.PlayRandomSound( type );
target.Metadata = board == digBoard ? (byte)1 : (byte)2;
Console.WriteLine( "ADD " + target.Offset + " : " + target.Length + " : " + target.Channels );
if( pendingCount == maxSounds )
RemoveFirstPendingSound();
pending[pendingCount++] = target;
}
void MakeSound( ref Sound src, ref bool play, AudioChunk target ) {
if( src == null ) return;
play = true;
target.Frequency = src.SampleRate;
target.BitsPerSample = src.BitsPerSample;
target.Channels = src.Channels;
target.BytesOffset = src.Offset;
target.BytesUsed = src.Length;
src = null;
}
void RemoveFirstPendingSound() {
for( int i = 1; i < maxSounds - 1; i++ )
pending[i] = pending[i + 1];
pending[maxSounds - 1] = null;
pendingCount--;
}
void DisposeSound() {
disposingSound = true;
soundHandle.Set();
DisposeOf( ref soundOut, ref soundThread );
}
void InitSoundboards() {
digBoard = new Soundboard();
digBoard.Init( "dig" );
stepBoard = new Soundboard();
stepBoard.Init( "step" );
}
}
}

View File

@ -6,16 +6,12 @@ using SharpWave.Codecs.Vorbis;
namespace ClassicalSharp.Audio {
public sealed partial class AudioManager {
public sealed partial class AudioPlayer {
IAudioOutput musicOut, soundOut;
string[] musicFiles;
Thread musicThread, soundThread;
public AudioManager() {
musicFiles = Directory.GetFiles( "audio", "*.ogg" );
}
public void SetMusic( bool enabled ) {
if( enabled )
InitMusic();
@ -24,12 +20,13 @@ namespace ClassicalSharp.Audio {
}
void InitMusic() {
musicFiles = Directory.GetFiles( "audio", "*.ogg" );
disposingMusic = false;
musicThread = MakeThread( DoMusicThread, ref musicOut,
"ClassicalSharp.DoMusic" );
}
EventWaitHandle waitHandle = new EventWaitHandle( false, EventResetMode.AutoReset );
EventWaitHandle musicHandle = new EventWaitHandle( false, EventResetMode.AutoReset );
void DoMusicThread() {
Random rnd = new Random();
while( !disposingMusic ) {
@ -42,7 +39,7 @@ namespace ClassicalSharp.Audio {
if( disposingMusic ) break;
int delay = 2000 * 60 + rnd.Next( 0, 5000 * 60 );
waitHandle.WaitOne( delay );
musicHandle.WaitOne( delay );
}
}
@ -50,12 +47,12 @@ namespace ClassicalSharp.Audio {
public void Dispose() {
DisposeMusic();
DisposeSound();
waitHandle.Close();
musicHandle.Close();
}
void DisposeMusic() {
disposingMusic = true;
waitHandle.Set();
musicHandle.Set();
DisposeOf( ref musicOut, ref musicThread );
}

View File

@ -89,5 +89,6 @@ namespace ClassicalSharp.Audio {
public string Name;
public int SampleRate, BitsPerSample, Channels;
public int Offset, Length;
public byte Metadata;
}
}

View File

@ -126,8 +126,8 @@
<Compile Include="2D\Widgets\PlayerListWidget.cs" />
<Compile Include="2D\Widgets\TextWidget.cs" />
<Compile Include="2D\Widgets\Widget.cs" />
<Compile Include="Audio\AudioManager.cs" />
<Compile Include="Audio\AudioManager.Sounds.cs" />
<Compile Include="Audio\AudioPlayer.cs" />
<Compile Include="Audio\AudioPlayer.Sounds.cs" />
<Compile Include="Audio\Soundboard.cs" />
<Compile Include="Blocks\Block.cs" />
<Compile Include="Blocks\BlockInfo.BoundingBox.cs" />

View File

@ -7,7 +7,8 @@ namespace ClassicalSharp.Commands {
public class CommandManager {
public static bool IsCommandPrefix( string input ) {
return Utils.CaselessStarts( input, "/client" );
return Utils.CaselessStarts( input, "/client " ) ||
Utils.CaselessEquals( input, "/client" );
}
protected Game game;

View File

@ -90,7 +90,7 @@ namespace ClassicalSharp {
float distSq = (lastSoundPos - soundPos).LengthSquared;
if( onGround && distSq > 2 * 2 ) {
SoundType type = game.BlockInfo.StepSounds[(int)BlockUnderFeet];
game.AudioManager.PlayStepSound( type );
game.AudioPlayer.PlayStepSound( type );
lastSoundPos = soundPos;
}
}

View File

@ -76,7 +76,7 @@ namespace ClassicalSharp {
public InputHandler InputHandler;
public ChatLog Chat;
public BlockHandRenderer BlockHandRenderer;
public AudioManager AudioManager;
public AudioPlayer AudioPlayer;
/// <summary> Account username of the player. </summary>
public string Username;

View File

@ -121,9 +121,9 @@ namespace ClassicalSharp {
EnvRenderer.Init();
MapBordersRenderer.Init();
Picking = new PickingRenderer( this );
AudioManager = new AudioManager();
AudioPlayer = new AudioPlayer();
UseMusic = Options.GetBool( OptionsKey.UseMusic, false );
AudioManager.SetMusic( UseMusic );
AudioPlayer.SetMusic( UseMusic );
LiquidsBreakable = Options.GetBool( OptionsKey.LiquidsBreakable, false );
string connectString = "Connecting to " + IPAddress + ":" + Port + "..";
@ -150,12 +150,6 @@ namespace ClassicalSharp {
get { return activeScreen == null ? hudScreen : activeScreen; }
}
const int ticksFrequency = 20;
const double ticksPeriod = 1.0 / ticksFrequency;
const double imageCheckPeriod = 30.0;
const double cameraPeriod = 1.0 / 120.0;
double ticksAccumulator, imageCheckAccumulator, cameraAccumulator;
protected override void OnRenderFrame( FrameEventArgs e ) {
PerformFpsElapsed( e.Time * 1000 );
Graphics.BeginFrame( this );
@ -214,10 +208,18 @@ namespace ClassicalSharp {
Graphics.EndFrame( this );
}
const int ticksFrequency = 20;
const double ticksPeriod = 1.0 / ticksFrequency;
const double imageCheckPeriod = 30.0;
const double cameraPeriod = 1.0 / 120, audioPeriod = 1.0 / 40;
double ticksAccumulator, imageCheckAccumulator,
cameraAccumulator, audioAccumulator;
void CheckScheduledTasks( double time ) {
imageCheckAccumulator += time;
ticksAccumulator += time;
cameraAccumulator += time;
audioAccumulator += time;
if( imageCheckAccumulator > imageCheckPeriod ) {
imageCheckAccumulator -= imageCheckPeriod;
@ -230,14 +232,19 @@ namespace ClassicalSharp {
Players.Tick( ticksPeriod );
ParticleManager.Tick( ticksPeriod );
Animations.Tick( ticksPeriod );
AudioPlayer.Tick( ticksPeriod );
ticksThisFrame++;
ticksAccumulator -= ticksPeriod;
}
while( cameraAccumulator >= cameraPeriod ) {
Camera.Tick( ticksPeriod );
Camera.Tick( cameraPeriod );
cameraAccumulator -= cameraPeriod;
}
while( audioAccumulator >= audioPeriod ) {
AudioPlayer.Tick( audioPeriod );
audioAccumulator -= audioPeriod;
}
if( ticksThisFrame > ticksFrequency / 3 )
Utils.LogDebug( "Falling behind (did {0} ticks this frame)", ticksThisFrame );
@ -398,7 +405,7 @@ namespace ClassicalSharp {
ParticleManager.Dispose();
Players.Dispose();
AsyncDownloader.Dispose();
AudioManager.Dispose();
AudioPlayer.Dispose();
Chat.Dispose();
if( activeScreen != null )

View File

@ -94,7 +94,7 @@ namespace ClassicalSharp {
if( game.Map.IsValidPos( pos ) && (block = game.Map.GetBlock( pos )) != 0
&& inv.CanDelete[block] ) {
game.ParticleManager.BreakBlockEffect( pos, block );
game.AudioManager.PlayDigSound( game.BlockInfo.DigSounds[block] );
game.AudioPlayer.PlayDigSound( game.BlockInfo.DigSounds[block] );
game.UpdateBlock( pos.X, pos.Y, pos.Z, 0 );
game.Network.SendSetBlock( pos.X, pos.Y, pos.Z, false, (byte)inv.HeldBlock );
}

View File

@ -185,7 +185,7 @@ namespace ClassicalSharp.Model {
void TransformVertices() {
for( int i = 0; i < index; i++ ) {
VertexPos3fTex2fCol4b vertex = cache.vertices[i];
Vector3 newPos = new Vector3( vertex.X, vertex.Y, vertex.Z ) + pos;//Utils.RotateY( vertex.X, vertex.Y, vertex.Z, cosA, sinA ) + pos;
Vector3 newPos = Utils.RotateY( vertex.X, vertex.Y, vertex.Z, cosA, sinA ) + pos;
vertex.X = newPos.X; vertex.Y = newPos.Y; vertex.Z = newPos.Z;
cache.vertices[i] = vertex;
}

View File

@ -7,7 +7,7 @@ namespace ClassicalSharp {
internal static class Program {
public const string AppName = "ClassicalSharp 0.98";
public const string AppName = "ClassicalSharp 0.98.1";
[STAThread]
static void Main( string[] args ) {

View File

@ -10,4 +10,4 @@ using System.Runtime.InteropServices;
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
[assembly: AssemblyVersion("0.95")]
[assembly: AssemblyVersion("0.98.1")]

View File

@ -20,8 +20,7 @@ namespace ClassicalSharp {
int sidesVb = -1, edgesVb = -1;
int edgeTexId, sideTexId;
int sidesVertices, edgesVertices,
edgesBaseVertices, edgesVerVertices;
int sidesVertices, edgesVertices;
bool legacy, fullColSides, fullColEdge;
public void SetUseLegacyMode( bool legacy ) {
@ -60,12 +59,8 @@ namespace ClassicalSharp {
// Fixes some 'depth bleeding through' issues with 16 bit depth buffers on large maps.
Vector3 eyePos = game.LocalPlayer.EyePosition;
float yVisible = Math.Min( 0, map.SidesHeight );
if( game.Map.EdgeBlock != Block.Air ) {
if( game.Camera.GetCameraPos( eyePos ).Y >= yVisible ) {
graphics.DrawIndexedVb_TrisT2fC4b( edgesVertices * 6 / 4, 0 );
} else {
graphics.DrawIndexedVb_TrisT2fC4b( edgesVerVertices * 6 / 4, edgesBaseVertices * 6 / 4 );
}
if( game.Map.EdgeBlock != Block.Air && game.Camera.GetCameraPos( eyePos ).Y >= yVisible ) {
graphics.DrawIndexedVb_TrisT2fC4b( edgesVertices * 6 / 4, 0 );
}
graphics.AlphaBlending = false;
graphics.Texturing = false;
@ -168,12 +163,6 @@ namespace ClassicalSharp {
foreach( Rectangle rec in rects ) {
edgesVertices += Utils.CountVertices( rec.Width, rec.Height, axisSize ); // YPlanes outside
}
edgesBaseVertices = edgesVertices;
if( waterLevel >= 0 ) {
edgesVertices += 2 * Utils.CountVertices( map.Width, 2, axisSize ); // ZPlanes
edgesVertices += 2 * Utils.CountVertices( map.Length, 2, axisSize ); // XPlanes
}
edgesVerVertices = edgesVertices - edgesBaseVertices;
VertexPos3fTex2fCol4b* vertices = stackalloc VertexPos3fTex2fCol4b[edgesVertices];
IntPtr ptr = (IntPtr)vertices;
@ -182,14 +171,6 @@ namespace ClassicalSharp {
foreach( Rectangle rec in rects ) {
DrawY( rec.X, rec.Y, rec.X + rec.Width, rec.Y + rec.Height, waterLevel, axisSize, col, ref vertices );
}
col = fullColEdge ? FastColour.White : map.SunlightYBottom;
if( waterLevel >= 0 ) {
DrawZ( 0, 0, map.Width, waterLevel - 2, waterLevel, axisSize, col, ref vertices );
DrawZ( map.Length, 0, map.Width, waterLevel - 2, waterLevel, axisSize, col, ref vertices );
DrawX( 0, 0, map.Length, waterLevel - 2, waterLevel, axisSize, col, ref vertices );
DrawX( map.Width, 0, map.Length, waterLevel - 2, waterLevel, axisSize, col, ref vertices );
}
edgesVb = graphics.CreateVb( ptr, VertexFormat.Pos3fTex2fCol4b, edgesVertices );
}

Binary file not shown.

View File

@ -122,7 +122,7 @@ namespace Launcher2 {
LauncherInputWidget widget = new LauncherInputWidget( game );
widget.OnClick = InputClick;
widget.Password = password;
widget.MaximumTextLength = maxChars;
widget.MaxTextLength = maxChars;
widget.DrawAt( drawer, text, inputFont, Anchor.Centre, verAnchor, width, 30, x, y );
widgets[widgetIndex++] = widget;

View File

@ -179,7 +179,7 @@ namespace Launcher2 {
abstract class TableEntryComparer : IComparer<TableEntry> {
public bool Invert = false;
public bool Invert = true;
public abstract int Compare( TableEntry a, TableEntry b );
}
@ -203,7 +203,7 @@ namespace Launcher2 {
}
}
sealed class UptimeComparer : TableEntryComparer {
sealed class UptimeComparer : TableEntryComparer {
public override int Compare( TableEntry a, TableEntry b ) {
TimeSpan valX = ParseUptimeString( a.Uptime );

View File

@ -17,7 +17,7 @@ namespace Launcher2 {
public bool Password;
/// <summary> Maximum number of characters that the 'Text' field can contain. </summary>
public int MaximumTextLength = 32;
public int MaxTextLength = 32;
/// <summary> Filter applied to text received from the clipboard. Can be null. </summary>
public Func<string, string> ClipboardFilter;
@ -53,7 +53,7 @@ namespace Launcher2 {
/// <summary> Appends a character to the end of the currently entered text. </summary>
/// <returns> true if a redraw is necessary, false otherwise. </returns>
public bool AppendChar( char c ) {
if( c >= ' ' && c <= '~' && Text.Length < MaximumTextLength ) {
if( c >= ' ' && c <= '~' && Text.Length < MaxTextLength ) {
Text += c;
return true;
}
@ -88,13 +88,12 @@ namespace Launcher2 {
/// <returns> true if a redraw is necessary, false otherwise. </returns>
public bool CopyFromClipboard() {
string text = Clipboard.GetText();
if( String.IsNullOrEmpty( text )
|| Text.Length >= MaximumTextLength ) return false;
if( String.IsNullOrEmpty( text ) || Text.Length >= MaxTextLength ) return false;
if( ClipboardFilter != null )
text = ClipboardFilter( text );
if( Text.Length + text.Length > MaximumTextLength ) {
text = text.Substring( 0, MaximumTextLength - Text.Length );
if( Text.Length + text.Length > MaxTextLength ) {
text = text.Substring( 0, MaxTextLength - Text.Length );
}
Text += text;
return true;

View File

@ -5,7 +5,7 @@ namespace Launcher2 {
internal sealed class Program {
public const string AppName = "ClassicalSharp Launcher 0.98";
public const string AppName = "ClassicalSharp Launcher 0.98.1";
[STAThread]
static void Main( string[] args ) {

View File

@ -1,31 +1,13 @@
#region Using directives
using System;
using System.Reflection;
using System.Reflection;
using System.Runtime.InteropServices;
#endregion
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Launcher2")]
[assembly: AssemblyTitle("ClassicalSharp Launcher")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Launcher2")]
[assembly: AssemblyCopyright("Copyright 2015")]
[assembly: AssemblyProduct("ClassicalSharp Launcher")]
[assembly: AssemblyCopyright("Copyright 2014 - 2015")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// This sets the default COM visibility of types in the assembly to invisible.
// If you need to expose a type to COM, use [ComVisible(true)] on that type.
[assembly: ComVisible(false)]
// The assembly version has following format :
//
// Major.Minor.Build.Revision
//
// You can specify all the values or you can use the default the Revision and
// Build Numbers by using the '*' as shown below:
[assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("0.98.1")]

View File

@ -9,4 +9,4 @@ using System.Runtime.InteropServices;
[assembly: AssemblyTrademark("OpenTK")]
[assembly: System.Security.AllowPartiallyTrustedCallers]
[assembly: ComVisible(false)]
[assembly: AssemblyVersion("0.95")]
[assembly: AssemblyVersion("0.98.1")]