Commit b40fd253 authored by Jesse Freeman's avatar Jesse Freeman

Cleaned up Pixel Vision 8 SDK v1.0.0 for release.

parent a8cd5cb6
This diff is collapsed.
//
// Copyright (c) Jesse Freeman. All rights reserved.
//
// Licensed under the Microsoft Public License (MS-PL) License.
// See LICENSE file in the project root for full license information.
//
// Contributors
// --------------------------------------------------------
// This is the official list of Pixel Vision 8 contributors:
//
// Jesse Freeman
//
using PixelVisionSDK.Engine;
using PixelVisionSDK.Engine.Chips;
namespace PixelVisionSDK
{
/// <summary>
/// This internal defines the APIs for the
/// <see cref="IAPIBridge" /> which allows games to talk to the engine's
/// chips.
/// </summary>
public interface IAPIBridge : IPixelVisionAPI
{
/// <summary>
/// A reference to the core <see cref="chips" /> in the engine.
/// </summary>
IEngineChips chips { get; set; }
}
}
\ No newline at end of file
//
// Copyright (c) Jesse Freeman. All rights reserved.
//
// Licensed under the Microsoft Public License (MS-PL) License.
// See LICENSE file in the project root for full license information.
//
// Contributors
// --------------------------------------------------------
// This is the official list of Pixel Vision 8 contributors:
//
// Jesse Freeman
//
using System;
using System.Collections.Generic;
using System.Text;
namespace PixelVisionSDK.Engine.Chips
{
/// <summary>
/// The AbstractChip represents plug-in that adds new functionality to the
/// PixelVisionEngine. Simply extend this abstract class and override the
/// Config() method. Each Chip is responsible for registering itself with
/// the engine and managing its own state. Chips can also communicate to
/// each other via the reference of the ChipManager which is part of the
/// PixelVisionEngine instance supplied to the Config() method.
/// </summary>
/// <example>
/// // Create a new class that extends the abstract chip
/// public class CustomChip : AbstractChip
/// {
/// // You need to override the Config method with your own custom setup code
/// public override Config()
/// {
/// // Add custom logic here
/// }
/// }
/// // Create a new instance of your chip
/// var chip = new CustomChip();
/// // When ready, activate the chip by passing in a reference to an engine instance
/// chip.Activate(engine);
/// </example>
public class AbstractChip : IChip
{
protected PixelVisionEngine engine;
/// <summary>
/// A flag for the ChipManager to determine if the chip
/// should be part of the serialization process.
/// </summary>
/// <value>bool</value>
public bool export = true;
/// <summary>
/// Determines if the chip is enabled or active by the
/// ChipManager. If marked as active it may be deleted
/// when the ChipManager performs its cleanup.
/// </summary>
/// <value name>bool</value>
public bool active { get; private set; }
/// <summary>
/// Activate is the beginning of the chip's life cycle.
/// This allows the chip to gain a reference to the engine
/// itself. This allows chips to talk back to the engine
/// as well as to each other through the engine's exposed APIs.
/// </summary>
/// <param name="parent">A reference to the engine.</param>
public virtual void Activate(PixelVisionEngine parent)
{
engine = parent;
active = true;
Configure();
}
/// <summary>
/// Configure is the second part of the chip's life-cycle.
/// It is called after Activate() and is designed to be overridden by
/// children classes so perform specific configuration tasks. This
/// method must be implemented in order for a chip to activate
/// correctly.
/// </summary>
public virtual void Configure()
{
throw new NotImplementedException();
}
/// <summary>
/// When called, this method sets the active field to
/// false. It's part of the chip's life-cycle and is called when
/// shutting down the ChipManager.
/// </summary>
public virtual void Deactivate()
{
active = false;
}
/// <summary>
/// This methods sets up the foundation for serializing a component as
/// JSON. It automatically creates a json wrapper before calling
/// CustomSerializedData().
/// </summary>
/// <returns>string</returns>
public virtual string SerializeData()
{
var sb = new StringBuilder();
sb.Append("{");
CustomSerializedData(sb);
sb.Append("}");
return sb.ToString();
}
/// <summary>
/// Override this to add custom json data to the serialized string
/// passed in by the StringBuilder reference.
/// </summary>
/// <param name="sb">
/// A StringBuilder reference to add additional json string properties
/// to.
/// </param>
public virtual void CustomSerializedData(StringBuilder sb)
{
// Override to add custom data
}
/// <summary>
/// Override this to method to handle your own custom de-serialized
/// logic. It expects a Dictionary with a string as the key and a
/// generic object as the value.
/// </summary>
/// <param name="data">
/// A Dictionary with a string as the key and a generic object as the
/// value.
/// </param>
public virtual void DeserializeData(Dictionary<string, object> data)
{
throw new NotImplementedException();
}
public virtual void Init()
{
}
public virtual void Reset()
{
}
}
}
\ No newline at end of file
This diff is collapsed.
//
// Copyright (c) Jesse Freeman. All rights reserved.
//
// Licensed under the Microsoft Public License (MS-PL) License.
// See LICENSE file in the project root for full license information.
//
// Contributors
// --------------------------------------------------------
// This is the official list of Pixel Vision 8 contributors:
//
// Jesse Freeman
//
using System;
using PixelVisionSDK.Engine.Chips.Data;
using PixelVisionSDK.Engine.Utils;
namespace PixelVisionSDK.Engine.Chips.Audio
{
/// <summary>
/// The <see cref="SoundChip" /> is responsible for playing back sound
/// effects in the engine. It's powered by SFxr.
/// </summary>
public class SoundChip : AbstractChip
{
protected int _totalSounds;
protected ISoundData[] channels = new ISoundData[0];
protected ISoundData[] sounds;
/// <summary>
/// The total number of <see cref="channels" /> available for playing
/// back sounds.
/// </summary>
public int totalChannels
{
get { return channels.Length; }
set { Array.Resize(ref channels, value); }
}
/// <summary>
/// The total number of <see cref="sounds" /> in the collection.
/// </summary>
public int totalSounds
{
get { return sounds.Length; }
set
{
// TODO need to copy over existing sounds
value = value.Clamp(1, 96);
Array.Resize(ref sounds, value);
for (var i = 0; i < value; i++)
{
if (sounds[i] == null)
sounds[i] = CreateEmptySoundData();
}
}
}
/// <summary>
/// Updates a sound in the collection.
/// </summary>
/// <param name="index">The index to update the sound at.</param>
/// <param name="param">
/// A string representing the synth properties.
/// </param>
public void UpdateSound(int index, string param)
{
var synth = sounds[index];
synth.CacheSound();
}
/// <summary>
/// Clear all the <see cref="sounds" /> in the collection.
/// </summary>
/// <param name="index"></param>
public void ClearSound(int index)
{
// TODO need to see if there is a better way to revert a sound
sounds[index] = CreateEmptySoundData();
}
/// <summary>
/// This stub methods is designed to be overriden with a Factory to
/// create new sound instances that implement the ISoundData interface.
/// </summary>
/// <returns></returns>
public virtual ISoundData CreateEmptySoundData()
{
throw new NotImplementedException(
"Need to create a new ISoundData type and override SoundCollection CreateEmptySoundData method.");
}
/// <summary>
/// Configures the <see cref="SoundChip" /> by registering itself with
/// the engine and setting up the deafult values for total
/// <see cref="sounds" /> and total channels.
/// </summary>
public override void Configure()
{
engine.soundChip = this;
totalSounds = 16;
totalChannels = 4;
}
/// <summary>
/// This method plays back a sound on a specific channel. The
/// <see cref="SoundChip" /> has a limit of active <see cref="channels" />
/// so playing a sound effect while another was is playing on the same
/// <paramref name="channel" /> will cancel it out and replace with the
/// new sound.
/// </summary>
/// <param name="index">
/// The ID of the sound in the SoundCollection.
/// </param>
/// <param name="channel">
/// The channel the sound should play back on.
/// </param>
public void PlaySound(int index, int channel = 0)
{
if (index > sounds.Length)
return;
LoadSound(index, channel, true);
}
/// <summary>
/// Loads a sound into a channel so it can be played.
/// </summary>
/// <param name="index"></param>
/// <param name="channel"></param>
/// <param name="autoPlay"></param>
public void LoadSound(int index, int channel = 0, bool autoPlay = false)
{
channel = channel.Clamp(0, totalChannels - 1);
if (channels[channel] != null)
{
channels[channel].Stop();
channels[channel] = null;
}
if (channels[channel] == null)
{
channels[channel] = ReadSound(index);
if (autoPlay)
channels[channel].Play();
}
}
/// <summary>
/// Returns a Sfxr Synth to be played back at run time by the SoundChip.
/// </summary>
/// <param name="index">
/// The index where the sound is stored in the <see cref="sounds" />
/// array.
/// </param>
/// <returns>
/// A reference to a SfxrSynth which contains the sound data.
/// </returns>
public ISoundData ReadSound(int id)
{
return sounds[id];
}
/// <summary>
/// Returns a reference to the current channel to control it's assigned
/// sound value.
/// </summary>
/// <param name="index"></param>
/// <returns></returns>
public ISoundData ReadChannel(int index)
{
if (index < 0 || index >= totalChannels)
return null;
return channels[index];
}
}
}
\ No newline at end of file
This diff is collapsed.
//
// Copyright (c) Jesse Freeman. All rights reserved.
//
// Licensed under the Microsoft Public License (MS-PL) License.
// See LICENSE file in the project root for full license information.
//
// Contributors
// --------------------------------------------------------
// This is the official list of Pixel Vision 8 contributors:
//
// Jesse Freeman
//
using System.Collections.Generic;
using System.Text;
using PixelVisionSDK.Engine.Chips.IO.File;
namespace PixelVisionSDK.Engine.Chips.Data
{
/// <summary>
/// The AbstractData class represents a standard foundation for all
/// data objects in the engine. It implements the ISave, ILoad and
/// IInvalidate interfaces and provides as standard API for serializing
/// the data it contains via the CustomSerializeData() method.
/// </summary>
public class AbstractData : ISave, ILoad, IInvalidate
{
protected bool _invalid;
/// <summary>
/// The invalid flag allows you to quickly see if data has been changed
/// on the data instance. This is used in conjunction with the
/// Invalidate() and ResetValidation() methods. Use this flag in classes
/// that have the potential to be expensive to update and need to be delayed
/// before refreshing their data.
/// </summary>
/// <value>Boolean</value>
public virtual bool invalid
{
get { return _invalid; }
}
/// <summary>
/// This method allows a clean way to set the invalid property to true
/// signaling a change in the underlying data. This method could be overridden
/// to provide additional logic when the AbstractData is invalidated.
/// </summary>
public virtual void Invalidate()
{
_invalid = true;
}
/// <summary>
/// This method allows a clean way to reset the invalid property to false
/// signaling underlying data had finished updating. This method could be
/// overridden to provide additional logic when the AbstractData is
/// done changing.
/// </summary>
public virtual void ResetValidation()
{
_invalid = false;
}
/// <summary>
/// The DeserializeData method allows you to pass in a
/// Dictionary with a string as the key and a generic object for the
/// value. This can be manually parsed to convert each key/value pair
/// into data used to configure the class that
/// implements this interface.
/// </summary>
/// <param name="data">
/// A Dictionary with a string as the key and a generic object as the
/// value.
/// </param>
public virtual void DeserializeData(Dictionary<string, object> data)
{
// override with custom parsing logic
}
/// <summary>
/// Use this method to create a new StringBuilder instance and wrap any
/// custom serialized data by leveraging the CustomSerializedData()
/// method.
/// </summary>
/// <returns name="String">
/// A string JSON object.
/// </returns>
public virtual string SerializeData()
{
var sb = new StringBuilder();
sb.Append("{");
CustomSerializedData(sb);
sb.Append("}");
return sb.ToString();
}
/// <summary>
/// Use this method to add additional serialized string data to the
/// supplied StringBuilder instance.
/// </summary>
/// <param name="sb">
/// A reference to a StringBuilder which is supplied by the
/// SerializedData() method.
/// </param>
public virtual void CustomSerializedData(StringBuilder sb)
{
// override with custom serialized data
}
}
}
\ No newline at end of file
//
// Copyright (c) Jesse Freeman. All rights reserved.
//
// Licensed under the Microsoft Public License (MS-PL) License.
// See LICENSE file in the project root for full license information.
//
// Contributors
// --------------------------------------------------------
// This is the official list of Pixel Vision 8 contributors:
//
// Jesse Freeman
//
using System;
using System.Globalization;
using System.Text.RegularExpressions;
namespace PixelVisionSDK.Engine.Chips.Data
{
/// <summary>
/// The ColorData class is a wraper for color data in the engine.
/// It provides a simple interface for storing RBG color data as
/// well as converting that data in Hex or vise versa.
/// </summary>
public class ColorData : AbstractData
{
protected float _b;
protected float _g;
protected float _r;
/// <summary>
/// Use this constructor for setting the ColorData instance up
/// with RBG values.
/// </summary>
/// <param name="r"></param>
/// <param name="g"></param>
/// <param name="b"></param>
public ColorData(float r = 0f, float g = 0f, float b = 0f)
{
this.r = r;
this.g = g;
this.b = b;
}
/// <summary>
/// Use this constructor for setting the ColorData instance up
/// with a HEX color value.
/// </summary>
/// <param name="hexColor"></param>
public ColorData(string hexColor)
{
float tmpR, tmpG, tmpB;
HexToColor(hexColor, out tmpR, out tmpG, out tmpB);
r = tmpR;
g = tmpG;
b = tmpB;
}
/// <summary>
/// The red value of a color. This ranges from 0 to 255.
/// </summary>
public float r
{
get { return _r; }
set { _r = value; }
}
/// <summary>
/// The green value of a color. This ranges from 0 to 255.
/// </summary>
public float g
{
get { return _g; }
set { _g = value; }
}
/// <summary>
/// The blue value of a color. This ranges from 0 to 255.
/// </summary>
public float b
{
get { return _b; }
set { _b = value; }
}
/// <summary>
/// Returns the HEX value of the color data.
/// </summary>
/// <returns name="String"></returns>
public string ToHex()
{
return ColorToHex(r, g, b);
}
/// <summary>
/// Static method for converting RGB colors into HEX values
/// </summary>
/// <param name="r">Red value</param>
/// <param name="g">Green value</param>
/// <param name="b">Blue value</param>
/// <returns></returns>
public static string ColorToHex(float r, float g, float b)
{
var hex = "#" + ((int) (r*255)).ToString("X2") + ((int) (g*255)).ToString("X2") +
((int) (b*255)).ToString("X2");
return hex;
}
/// <summary>
/// Static method for converting a HEX color into an RGB value.
/// </summary>
/// <param name="hex"></param>
/// <param name="r"></param>
/// <param name="g"></param>
/// <param name="b"></param>
public static void HexToColor(string hex, out float r, out float g, out float b)
{
if (hex == null)
{
hex = "FF00FF";
}
if (hex[0] == '#')
hex = hex.Substring(1);
r = byte.Parse(hex.Substring(0, 2), NumberStyles.HexNumber)/(float) byte.MaxValue;
g = byte.Parse(hex.Substring(2, 2), NumberStyles.HexNumber)/(float) byte.MaxValue;
b = byte.Parse(hex.Substring(4, 2), NumberStyles.HexNumber)/(float) byte.MaxValue;
}
/// <summary>
/// Static method to calculate the brightness of a ColorData instance
/// </summary>
/// <param name="r"></param>
/// <param name="g"></param>
/// <param name="b"></param>
/// <returns></returns>
public static float Brightness(float r, float g, float b)
{
return (float) Math.Sqrt(
r*r*.241 +
g*g*.691 +
b*b*.068);
}
/// <summary>
/// Static method to valide that a HEX color can be parsed. HEX colors need
/// to be in the correct format #FFFFFF or #FFF
/// </summary>
/// <param name="color"></param>
/// <returns></returns>
public static bool ValidateColor(string color)
{
var regex = new Regex(@"^#(?:[0-9a-fA-F]{3}){1,2}$");
var match = regex.Match(color);
return match.Success;
}
}
}
\ No newline at end of file
//
// Copyright (c) Jesse Freeman. All rights reserved.
//
// Licensed under the Microsoft Public License (MS-PL) License.
// See LICENSE file in the project root for full license information.
//
// Contributors
// --------------------------------------------------------
// This is the official list of Pixel Vision 8 contributors:
//
// Jesse Freeman
//
namespace PixelVisionSDK.Engine.Chips.Data
{
public interface IInvalidate
{
/// <summary>
/// The invalid flag allows you to quickly see if data has been changed
/// on the AbstractData instance. This is used in conjunction with the
/// Invalidate() and ResetValidation() methods. Use this flag in classes
/// that have the potential to be expensive to update and need to be delayed
/// before refreshing their data.<br />When set to true, this value means that the data is dirty and needs be
/// updated. Set and Reset this value via the Invalidate() and ResetValidation()
/// methods.
/// </summary>
/// <value>Boolean</value>
bool invalid { get; }
/// <summary>
/// This method allows a clean way to set the invalid property to true
/// signaling a change in the underlying data. This method could be overridden
/// to provide additional logic when the AbstractData is invalidated.
/// </summary>
void Invalidate();
/// <summary>
/// This method allows a clean way to reset the invalid property to false
/// signaling underlying data had finished updating. This method could be
/// overridden to provide additional logic when the AbstractData is
/// done changing.
/// </summary>
void ResetValidation();
}
}
\ No newline at end of file
//
// Copyright (c) Jesse Freeman. All rights reserved.
//
// Licensed under the Microsoft Public License (MS-PL) License.
// See LICENSE file in the project root for full license information.
//
// Contributors
// --------------------------------------------------------
// This is the official list of Pixel Vision 8 contributors:
//
// Jesse Freeman
//
using PixelVisionSDK.Engine.Chips.IO.File;
namespace PixelVisionSDK.Engine.Chips.Data
{
/// <summary>
/// The ISoundData interface reprents a basic API for working
/// with sound objects in the PixelVisionSDK. Implement this
/// Interface with access to sound data to use it inside of
/// games and the MusicChip.
/// </summary>
public interface ISoundData : ISave, ILoad
{
/// <summary>
/// Plays the sound at a specific frequency.
/// </summary>
/// <param name="frequency"></param>
void Play(float frequency = 0f);