Commit 27a275bc authored by Jesse Freeman's avatar Jesse Freeman

Created a new service layer allowing classes to register themselves with the...

Created a new service layer allowing classes to register themselves with the ChipManager and expose functionality to the chips without being tightly coupled to their APIs. Fixed bugs and missing code in SoundChip and MusicChip. Corrected ColorData Hex color conversion to be more accurate and added RoundToInt to the MathUtil. General code cleanup and other updated to bring SDK codebase in line with above changes.
parent 524f6e4e
/[Ll]ibrary/ /[Ll]ibrary/
/[Tt]emp/ /[Tt]emp/
/[Oo]bj/ /[Oo]bj/
/[Bb]uild/ /[Bb]uild/
/[Bb]uilds/ /[Bb]uilds/
/[Pp]roperties/ /[Pp]roperties/
/[Bb]in/ /[Bb]in/
# Autogenerated VS/MD solution and project files # Autogenerated VS/MD solution and project files
*.csproj *.csproj
*.unityproj *.unityproj
*.sln *.sln
*.suo *.suo
*.tmp *.tmp
*.user *.user
*.userprefs *.userprefs
*.pidb *.pidb
*.booproj *.booproj
*.meta *.meta
# Unity3D generated meta files # Unity3D generated meta files
*.pidb.meta *.pidb.meta
# Unity3D Generated File On Crash Reports # Unity3D Generated File On Crash Reports
sysinfo.txt sysinfo.txt
*.DS_Store *.DS_Store
\ No newline at end of file
// //
// Copyright (c) Jesse Freeman. All rights reserved. // Copyright (c) Jesse Freeman. All rights reserved.
// //
// Licensed under the Microsoft Public License (MS-PL) License. // Licensed under the Microsoft Public License (MS-PL) License.
// See LICENSE file in the project root for full license information. // See LICENSE file in the project root for full license information.
// //
// Contributors // Contributors
// -------------------------------------------------------- // --------------------------------------------------------
// This is the official list of Pixel Vision 8 contributors: // This is the official list of Pixel Vision 8 contributors:
// //
// Jesse Freeman - @JesseFreeman // Jesse Freeman - @JesseFreeman
// Christer Kaitila - @McFunkypants // Christer Kaitila - @McFunkypants
// Pedro Medeiros - @saint11 // Pedro Medeiros - @saint11
// Shawn Rakowski - @shwany // Shawn Rakowski - @shwany
// //
using System; using System;
using PixelVisionSDK.Chips; using PixelVisionSDK.Chips;
using PixelVisionSDK.Utils; using PixelVisionSDK.Utils;
namespace PixelVisionSDK namespace PixelVisionSDK
{ {
/// <summary> /// <summary>
/// The <see cref="APIBridge" /> is the communication layer between the games /// The <see cref="APIBridge" /> is the communication layer between the games
/// and the engine's chips. It's designed to provide a clean and safe API /// and the engine's chips. It's designed to provide a clean and safe API
/// for games to use without exposing the rest of the underpinnings of the /// for games to use without exposing the rest of the underpinnings of the
/// engine.<br /> /// engine.<br />
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// This is the class diagram<br /> /// This is the class diagram<br />
/// <img src="Content/images/apibridge.png" /> /// <img src="Content/images/apibridge.png" />
/// </remarks> /// </remarks>
public class APIBridge : IAPIBridge public class APIBridge : IAPIBridge
{ {
//TODO need to make sure this is correctly sized when sprite sizes change //TODO need to make sure this is correctly sized when sprite sizes change
private static readonly int[] tmpPixelData = new int[8 * 8]; private static readonly int[] tmpPixelData = new int[8 * 8];
protected bool _paused; protected bool _paused;
/// <summary> /// <summary>
/// </summary> /// </summary>
/// <param name="enginechips"></param> /// <param name="enginechips"></param>
public APIBridge(IEngineChips enginechips) public APIBridge(IEngineChips enginechips)
{ {
chips = enginechips; chips = enginechips;
} }
/// <summary> /// <summary>
/// </summary> /// </summary>
/// <param name="enginechips"></param> /// <param name="enginechips"></param>
public IEngineChips chips { get; set; } public IEngineChips chips { get; set; }
/// <summary> /// <summary>
/// </summary> /// </summary>
public float timeDelta public float timeDelta
{ {
get { return chips.chipManager.timeDelta; } get { return chips.chipManager.timeDelta; }
} }
public int spriteWidth public int spriteWidth
{ {
get { return chips.spriteChip.width; } get { return chips.spriteChip.width; }
} }
public int spriteHeight public int spriteHeight
{ {
get { return chips.spriteChip.height; } get { return chips.spriteChip.height; }
} }
public int displayWidth public int displayWidth
{ {
get { return chips.displayChip.width; } get { return chips.displayChip.width; }
} }
public bool displayWrap public bool displayWrap
{ {
get { return chips.displayChip.wrapMode; } get { return chips.displayChip.wrapMode; }
} }
public void ToggleDisplayWrap(bool value) public void ToggleDisplayWrap(bool value)
{ {
chips.displayChip.wrapMode = value; chips.displayChip.wrapMode = value;
} }
public int displayHeight public int displayHeight
{ {
get { return chips.displayChip.height; } get { return chips.displayChip.height; }
} }
public int scrollX public int scrollX
{ {
get { return chips.screenBufferChip.scrollX; } get { return chips.screenBufferChip.scrollX; }
} }
public int scrollY public int scrollY
{ {
get { return chips.screenBufferChip.scrollY; } get { return chips.screenBufferChip.scrollY; }
} }
public void ScrollTo(int x, int y) public void ScrollTo(int x, int y)
{ {
if (chips.screenBufferChip == null) if (chips.screenBufferChip == null)
return; return;
chips.screenBufferChip.scrollX = x; chips.screenBufferChip.scrollX = x;
chips.screenBufferChip.scrollY = y; chips.screenBufferChip.scrollY = y;
} }
public bool paused public bool paused
{ {
get { return _paused; } get { return _paused; }
} }
public void TogglePause(bool value) public void TogglePause(bool value)
{ {
if (_paused != value) if (_paused != value)
{ {
if (chips.displayChip != null) if (chips.displayChip != null)
chips.displayChip.paused = value; chips.displayChip.paused = value;
} }
} }
public int mouseX public int mouseX
{ {
get { return chips.controllerChip.mousePosition.x; } get { return chips.controllerChip.mousePosition.x; }
} }
public int mouseY public int mouseY
{ {
get { return chips.controllerChip.mousePosition.y; } get { return chips.controllerChip.mousePosition.y; }
} }
public string inputString public string inputString
{ {
get { return chips.controllerChip.inputString; } get { return chips.controllerChip.inputString; }
} }
public Vector mousePosition public Vector mousePosition
{ {
get { return chips.controllerChip.mousePosition; } get { return chips.controllerChip.mousePosition; }
} }
public void DrawSprite(int id, int x, int y, bool flipH = false, bool flipV = false, bool aboveBG = true, public void DrawSprite(int id, int x, int y, bool flipH = false, bool flipV = false, bool aboveBG = true,
int colorOffset = 0) int colorOffset = 0)
{ {
if (!chips.displayChip.CanDraw()) if (!chips.displayChip.CanDraw())
{ {
//Debug.Log("Out of draw calls"); //Debug.Log("Out of draw calls");
return; return;
} }
chips.spriteChip.ReadSpriteAt(id, tmpPixelData); chips.spriteChip.ReadSpriteAt(id, tmpPixelData);
var layerOrder = aboveBG ? 1 : -1; var layerOrder = aboveBG ? 1 : -1;
DrawPixelData(tmpPixelData, x, y, spriteWidth, spriteHeight, flipH, flipV, true, layerOrder); DrawPixelData(tmpPixelData, x, y, spriteWidth, spriteHeight, flipH, flipV, true, layerOrder);
} }
public void DrawSprites(int[] ids, int x, int y, int width, bool flipH = false, bool flipV = false, public void DrawSprites(int[] ids, int x, int y, int width, bool flipH = false, bool flipV = false,
bool aboveBG = true, int colorOffset = 0) bool aboveBG = true, int colorOffset = 0)
{ {
//TODO need to allow flipping and match the draw sprite API //TODO need to allow flipping and match the draw sprite API
//Debug.Log("Draw "+ids.Length + " sprites."); //Debug.Log("Draw "+ids.Length + " sprites.");
var total = ids.Length; var total = ids.Length;
for (var i = 0; i < total; i++) for (var i = 0; i < total; i++)
{ {
var id = Convert.ToInt32(ids[i]); var id = Convert.ToInt32(ids[i]);
if (id > -1) if (id > -1)
{ {
var newX = MathUtil.FloorToInt(i % width) * spriteWidth + x; var newX = MathUtil.FloorToInt(i % width) * spriteWidth + x;
var newY = MathUtil.FloorToInt(i / width) * spriteWidth + y; var newY = MathUtil.FloorToInt(i / width) * spriteWidth + y;
DrawSprite(id, newX, newY, flipH, flipV, aboveBG, colorOffset); DrawSprite(id, newX, newY, flipH, flipV, aboveBG, colorOffset);
} }
} }
} }
public void UpdateTile(int spriteID, int column, int row, int flag = -1, int colorOffset = 0) public void UpdateTile(int spriteID, int column, int row, int flag = -1, int colorOffset = 0)
{ {
chips.tileMapChip.UpdateTileAt(spriteID, column, row); chips.tileMapChip.UpdateTileAt(spriteID, column, row);
} }
public void Clear() public void Clear()
{ {
chips.displayChip.Clear(); chips.displayChip.Clear();
} }
public void ChangeBackgroundColor(int id) public void ChangeBackgroundColor(int id)
{ {
id = id.Clamp(0, chips.colorChip.total - 1); id = id.Clamp(0, chips.colorChip.total - 1);
chips.screenBufferChip.backgroundColor = id; chips.screenBufferChip.backgroundColor = id;
} }
public void PlaySound(int id, int channel = 0) public void PlaySound(int id, int channel = 0)
{ {
chips.soundChip.PlaySound(id, channel); chips.soundChip.PlaySound(id, channel);
} }
public void RebuildScreenBuffer() public void RebuildScreenBuffer()
{ {
chips.screenBufferChip.RefreshScreenBlock(); chips.screenBufferChip.RefreshScreenBlock();
} }
public bool ButtonDown(int button, int player = 0) public bool ButtonDown(int button, int player = 0)
{ {
var totalButtons = Enum.GetNames(typeof(Buttons)).Length; var totalButtons = Enum.GetNames(typeof(Buttons)).Length;
if (button >= totalButtons) if (button >= totalButtons)
return false; return false;
return chips.controllerChip.ButtonDown(button, player); return chips.controllerChip.ButtonDown(button, player);
} }
public bool ButtonReleased(int button, int player = 0) public bool ButtonReleased(int button, int player = 0)
{ {
var totalButtons = Enum.GetNames(typeof(Buttons)).Length; var totalButtons = Enum.GetNames(typeof(Buttons)).Length;
if (button >= totalButtons) if (button >= totalButtons)
return false; return false;
return chips.controllerChip.ButtonReleased(button, player); return chips.controllerChip.ButtonReleased(button, player);
} }
public bool GetMouseButtonDown(int id = 0) public bool GetMouseButtonDown(int id = 0)
{ {
return chips.controllerChip.GetMouseButtonDown(id); return chips.controllerChip.GetMouseButtonDown(id);
} }
public bool GetMouseButtonUp(int id = 0) public bool GetMouseButtonUp(int id = 0)
{ {
return chips.controllerChip.GetMouseButtonUp(id); return chips.controllerChip.GetMouseButtonUp(id);
} }
public bool GetMouseButton(int id = 0) public bool GetMouseButton(int id = 0)
{ {
return chips.controllerChip.GetMouseButton(id); return chips.controllerChip.GetMouseButton(id);
} }
public virtual void DrawScreenBuffer() public virtual void DrawScreenBuffer()
{ {
chips.displayChip.CopyScreenBlockBuffer(); chips.displayChip.CopyScreenBlockBuffer();
} }
public void DrawTileToBuffer(int spriteID, int column, int row, int colorOffset = 0) public void DrawTileToBuffer(int spriteID, int column, int row, int colorOffset = 0)
{ {
chips.spriteChip.ReadSpriteAt(spriteID, tmpPixelData); chips.spriteChip.ReadSpriteAt(spriteID, tmpPixelData);
DrawBufferData(tmpPixelData, column * spriteWidth, row * spriteHeight, spriteWidth, spriteHeight); DrawBufferData(tmpPixelData, column * spriteWidth, row * spriteHeight, spriteWidth, spriteHeight);
} }
public void DrawTilesToBuffer(int[] ids, int column, int row, int columns, int colorOffset = 0) public void DrawTilesToBuffer(int[] ids, int column, int row, int columns, int colorOffset = 0)
{ {
//TODO need to allow flipping and match the draw sprite API //TODO need to allow flipping and match the draw sprite API
//Debug.Log("Draw "+ids.Length + " sprites."); //Debug.Log("Draw "+ids.Length + " sprites.");
var total = ids.Length; var total = ids.Length;
for (var i = 0; i < total; i++) for (var i = 0; i < total; i++)
{ {
var id = Convert.ToInt32(ids[i]); var id = Convert.ToInt32(ids[i]);
if (id > -1) if (id > -1)
{ {
var newX = MathUtil.FloorToInt(i % columns) + column; var newX = MathUtil.FloorToInt(i % columns) + column;
var newY = MathUtil.FloorToInt(i / columns) + row; var newY = MathUtil.FloorToInt(i / columns) + row;
DrawTileToBuffer(id, newX, newY, 0); DrawTileToBuffer(id, newX, newY, 0);
} }
} }
} }
public void DrawFont(string text, int x, int y, string fontName = "Default", int letterSpacing = 0) public void DrawFont(string text, int x, int y, string fontName = "Default", int letterSpacing = 0)
{ {
if (chips.fontChip != null) if (chips.fontChip != null)
{ {
int[] pixels; int[] pixels;
int width; int width;
int height; int height;
chips.fontChip.ConvertTextToPixelData(text, out pixels, out width, out height, fontName, letterSpacing); chips.fontChip.ConvertTextToPixelData(text, out pixels, out width, out height, fontName, letterSpacing);
DrawPixelData(pixels, x, y, width, height, false, false, true); DrawPixelData(pixels, x, y, width, height, false, false, true);
} }
} }
public void DrawFontToBuffer(string text, int column, int row, string fontName = "Default", public void DrawFontToBuffer(string text, int column, int row, string fontName = "Default",
int letterSpacing = 0) int letterSpacing = 0)
{ {
int[] pixels; int[] pixels;
int width; int width;
int height; int height;
chips.fontChip.ConvertTextToPixelData(text, out pixels, out width, out height chips.fontChip.ConvertTextToPixelData(text, out pixels, out width, out height
, fontName, letterSpacing); , fontName, letterSpacing);
var x = column; var x = column;
var y = row; var y = row;
chips.screenBufferChip.MergePixelDataAt(x, y, width, height, pixels); chips.screenBufferChip.MergePixelDataAt(x, y, width, height, pixels);
} }
public void DrawTextBox(string text, int witdh, int x, int y, string fontName = "Default", int letterSpacing = 0, public void DrawTextBox(string text, int witdh, int x, int y, string fontName = "Default", int letterSpacing = 0,
bool wholeWords = false) bool wholeWords = false)
{ {
text = wholeWords ? FontChip.WordWrap(text, witdh) : FontChip.Split(text, witdh); text = wholeWords ? FontChip.WordWrap(text, witdh) : FontChip.Split(text, witdh);
DrawFont(text, x, y, fontName, letterSpacing); DrawFont(text, x, y, fontName, letterSpacing);
} }
public void DrawTextBoxToBuffer(string text, int witdh, int column, int row, string fontName = "Default", public void DrawTextBoxToBuffer(string text, int witdh, int column, int row, string fontName = "Default",
int letterSpacing = 0, bool wholeWords = false) int letterSpacing = 0, bool wholeWords = false)
{ {
text = wholeWords ? FontChip.WordWrap(text, witdh) : FontChip.Split(text, witdh); text = wholeWords ? FontChip.WordWrap(text, witdh) : FontChip.Split(text, witdh);
DrawFontToBuffer(text, column, row, fontName, letterSpacing); DrawFontToBuffer(text, column, row, fontName, letterSpacing);
} }
public void DrawBufferData(int[] pixelData, int x, int y, int width, int height) public void DrawBufferData(int[] pixelData, int x, int y, int width, int height)
{ {
chips.screenBufferChip.UpdatePixelDataAt(x, y, width, height, pixelData); chips.screenBufferChip.UpdatePixelDataAt(x, y, width, height, pixelData);
} }
public void DrawPixelData(int[] pixelData, int x, int y, int width, int height, bool flipH, bool flipV, public void DrawPixelData(int[] pixelData, int x, int y, int width, int height, bool flipH, bool flipV,
bool flipY, int layerOrder = 0, bool masked = false) bool flipY, int layerOrder = 0, bool masked = false)
{ {
chips.displayChip.NewDrawCall(pixelData, x, y, width, height, flipH, flipV, flipY, layerOrder, masked); chips.displayChip.NewDrawCall(pixelData, x, y, width, height, flipH, flipV, flipY, layerOrder, masked);
} }
public int ReadFlagAt(int column, int row) public int ReadFlagAt(int column, int row)
{ {
return chips.tileMapChip.ReadFlagAt(column, row); return chips.tileMapChip.ReadFlagAt(column, row);
} }
public bool GetKey(int key) public bool GetKey(int key)
{ {
return chips.controllerChip.GetKey(key); return chips.controllerChip.GetKey(key);
} }
public bool GetKeyDown(int key) public bool GetKeyDown(int key)
{ {
return chips.controllerChip.GetKeyDown(key); return chips.controllerChip.GetKeyDown(key);
} }
public bool GetKeyUp(int key) public bool GetKeyUp(int key)
{ {
return chips.controllerChip.GetKeyUp(key); return chips.controllerChip.GetKeyUp(key);
} }
public int[] SpritesToRawData(int[] ids, int width) public int[] SpritesToRawData(int[] ids, int width)
{ {
var spriteChip = chips.spriteChip; var spriteChip = chips.spriteChip;
var spriteWidth = spriteChip.width; var spriteWidth = spriteChip.width;
var spriteHeight = spriteChip.height; var spriteHeight = spriteChip.height;
var realHeight = spriteHeight * MathUtil.CeilToInt(ids.Length / width); var realHeight = spriteHeight * MathUtil.CeilToInt(ids.Length / width);
var realWidth = spriteWidth * width; var realWidth = spriteWidth * width;
var pixelData = new int[realWidth * realHeight]; var pixelData = new int[realWidth * realHeight];
SpriteChipUtil.CovertSpritesToRawData(ref pixelData, ids, width, SpriteChipUtil.CovertSpritesToRawData(ref pixelData, ids, width,
chips); chips);