Last active
January 11, 2017 11:48
-
-
Save hakelimopu/ac636231098104cb5a6b5d9e132d7e50 to your computer and use it in GitHub Desktop.
Gotta get an asset loader and color cache going, but these are the bones of an SDL Runner.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using SDL2; | |
using PixelVisionSDK.Engine; | |
using PixelVisionSDK.Engine.Chips.Graphics.Sprites; | |
using PixelVisionSDK.Engine.Chips.Graphics.Colors; | |
using PixelVisionSDK.Engine.Chips.Graphics.Display; | |
using PixelVisionSDK.Engine.Chips.IO.Controller; | |
using PixelVisionSDK.Engine.Chips.Game; | |
using PixelVisionSDK.Engine.Utils; | |
using System.Runtime.InteropServices; | |
using System.Collections.Generic; | |
namespace SDLRunner | |
{ | |
class Program | |
{ | |
[STAThread] | |
static void Main(string[] args) | |
{ | |
SDL.SDL_Init(SDL.SDL_INIT_VIDEO); | |
SDL_image.IMG_Init(SDL_image.IMG_InitFlags.IMG_INIT_PNG); | |
IntPtr window = IntPtr.Zero; | |
IntPtr renderer = IntPtr.Zero; | |
SDL.SDL_CreateWindowAndRenderer(1280, 720, 0, out window, out renderer); | |
//TODO: put [ChipDependency] attribute on DrawSpriteDemo, and augment engine.LoadGame to automagically pull them in. | |
string[] chips = | |
{ | |
typeof(ColorChip).FullName, | |
typeof(SpriteChip).FullName, | |
typeof(ScreenBufferChip).FullName, | |
typeof(TileMapChip).FullName, | |
typeof(FontChip).FullName, | |
typeof(ControllerChip).FullName, | |
typeof(DisplayChip).FullName | |
}; | |
IEngine engine = new PixelVisionEngine(chips); | |
#region Load Colors From colors.png | |
IntPtr surface = SDL_image.IMG_Load("colors.png"); | |
SDL.SDL_Surface surfaceStruct = (SDL.SDL_Surface)Marshal.PtrToStructure(surface, typeof(SDL.SDL_Surface)); | |
const int bitsPerPixel = 32; | |
const int bytesPerPixel = 32 / 8; | |
const int redOffset = 0; | |
const int greenOffset = 1; | |
const int blueOffset = 2; | |
var pixels = new byte[surfaceStruct.w * surfaceStruct.h * bytesPerPixel]; | |
var handle = GCHandle.Alloc(pixels, GCHandleType.Pinned); | |
var tempSurface = SDL.SDL_CreateRGBSurfaceFrom(handle.AddrOfPinnedObject(), surfaceStruct.w, surfaceStruct.h, bitsPerPixel, surfaceStruct.w * bytesPerPixel, 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000); | |
SDL.SDL_BlitSurface(surface, IntPtr.Zero, tempSurface, IntPtr.Zero); | |
SDL.SDL_FreeSurface(tempSurface); | |
tempSurface = IntPtr.Zero; | |
handle.Free(); | |
SDL.SDL_FreeSurface(surface); | |
surface = IntPtr.Zero; | |
engine.colorChip.Clear(); | |
engine.colorChip.RebuildColorPages(pixels.Length / bytesPerPixel); | |
Dictionary<string, int> lookUp = new Dictionary<string, int>(); | |
Dictionary<int, byte> lookUpRed = new Dictionary<int, byte>(); | |
Dictionary<int, byte> lookUpGreen = new Dictionary<int, byte>(); | |
Dictionary<int, byte> lookUpBlue = new Dictionary<int, byte>(); | |
for (int index=0;index<pixels.Length;index+=bytesPerPixel) | |
{ | |
byte redValue = pixels[index + redOffset]; | |
byte greenValue = pixels[index + greenOffset]; | |
byte blueValue = pixels[index + blueOffset]; | |
int colorIndex = index / bytesPerPixel; | |
string colorValue = string.Format("#{0:X2}{1:X2}{2:X2}", redValue, greenValue, blueValue); | |
lookUp[colorValue] = colorIndex; | |
lookUpRed[colorIndex] = redValue; | |
lookUpGreen[colorIndex] = greenValue; | |
lookUpBlue[colorIndex] = blueValue; | |
engine.colorChip.UpdateColorAt(colorIndex, colorValue); | |
} | |
#endregion | |
#region Import Sprites from sprites.png | |
var spriteChip = engine.spriteChip; | |
surface = SDL_image.IMG_Load("sprites.png"); | |
surfaceStruct = (SDL.SDL_Surface)Marshal.PtrToStructure(surface, typeof(SDL.SDL_Surface)); | |
pixels = new byte[surfaceStruct.w * surfaceStruct.h * bytesPerPixel]; | |
handle = GCHandle.Alloc(pixels, GCHandleType.Pinned); | |
tempSurface = SDL.SDL_CreateRGBSurfaceFrom(handle.AddrOfPinnedObject(), surfaceStruct.w, surfaceStruct.h, bitsPerPixel, surfaceStruct.w * bytesPerPixel, 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000); | |
SDL.SDL_BlitSurface(surface, IntPtr.Zero, tempSurface, IntPtr.Zero); | |
SDL.SDL_FreeSurface(tempSurface); | |
tempSurface = IntPtr.Zero; | |
SDL.SDL_FreeSurface(surface); | |
surface = IntPtr.Zero; | |
handle.Free(); | |
var spritesPerRow = surfaceStruct.w / spriteChip.width; | |
var totalSprites = SpriteChipUtil.CalculateTotalSprites(surfaceStruct.w, surfaceStruct.h, spriteChip.width, spriteChip.height); | |
var maxSprites = SpriteChipUtil.CalculateTotalSprites(spriteChip.textureWidth, spriteChip.textureHeight, | |
spriteChip.width, spriteChip.height); | |
for(int index=0;index<totalSprites && index<maxSprites;++index) | |
{ | |
int spriteRow = (surfaceStruct.h / spriteChip.height) - 1 - index / spritesPerRow; | |
int spriteColumn = index % spritesPerRow; | |
var spriteData = new int[spriteChip.width * spriteChip.height]; | |
for(int spriteX = 0;spriteX<spriteChip.width;++spriteX) | |
{ | |
for(int spriteY=0;spriteY<spriteChip.height;++spriteY) | |
{ | |
int pixelIndex = ((spriteY + spriteRow * spriteChip.height) * surfaceStruct.w + (spriteX + spriteColumn * spriteChip.width)) * bytesPerPixel; | |
byte red = pixels[pixelIndex + redOffset]; | |
byte green = pixels[pixelIndex + greenOffset]; | |
byte blue = pixels[pixelIndex + blueOffset]; | |
string hex = string.Format("#{0:X2}{1:X2}{2:X2}", red, green, blue); | |
int paletteIndex = lookUp[hex]; | |
spriteData[spriteX + spriteY * spriteChip.width] = paletteIndex; | |
} | |
} | |
spriteChip.UpdateSpriteAt(index, spriteData); | |
} | |
#endregion | |
GameChip gameChip = new DrawSpriteDemo(); | |
SDL.SDL_RenderSetLogicalSize(renderer, 256, 240); | |
engine.LoadGame(gameChip); | |
engine.RunGame(); | |
SDL.SDL_Event evt; | |
bool done = false; | |
DateTimeOffset clock = DateTimeOffset.Now; | |
while(!done) | |
{ | |
while (SDL.SDL_PollEvent(out evt) > 0) | |
{ | |
if (evt.type == SDL.SDL_EventType.SDL_QUIT) | |
{ | |
done = true; | |
break; | |
} | |
} | |
DateTimeOffset oldClock = clock; | |
clock = DateTimeOffset.Now; | |
var elapsed = clock - oldClock; | |
engine.Update((float)elapsed.TotalSeconds); | |
engine.Draw(); | |
//more or less taken wholecloth from MonoGameRunner's Draw function. | |
var pixelData = engine.displayChip.displayPixelData; | |
var total = pixelData.Length; | |
SDL.SDL_Rect rect = new SDL.SDL_Rect() { x = 0, y = 0, w = 1, h = 1 }; | |
// Now it's time to loop through all of the DisplayChip's pixel data. | |
for (var i = 0; i < total; i++) | |
{ | |
int x, y; | |
PosUtil.CalculatePosition(i, 256, out x, out y); | |
int j; | |
PosUtil.CalculateIndex(x, 240 - y - 1, 256, out j); | |
// Here we get a reference to the color we are trying to look up from the pixelData array. Then we compare that ID to what we | |
// have in the cachedPixels. If the color is out of range, we use the cachedTransparentColor. If the color exists in the cache we use that. | |
var colorRef = pixelData[i]; | |
//TODO: get the actual color, and set it for the renderer | |
//cachedPixels[j] = colorRef < 0 || colorRef >= totalCachedColors ? cacheTransparentColor : cachedColors[colorRef]; | |
if (colorRef < 0) | |
{ | |
SDL.SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); | |
} | |
else | |
{ | |
SDL.SDL_SetRenderDrawColor(renderer, lookUpRed[colorRef], lookUpGreen[colorRef], lookUpBlue[colorRef], 255); | |
} | |
rect.x = x; | |
rect.y = y; | |
SDL.SDL_RenderFillRect(renderer, ref rect); | |
// As you can see, we are using a protected field called cachedPixels. When we call ResetResolution, we resize this array to make sure that | |
// it matches the length of the DisplayChip's pixel data. By keeping a reference to this Array and updating each color instead of rebuilding | |
// it, we can significantly increase the render performance of the Runner. | |
} | |
SDL.SDL_RenderPresent(renderer); | |
} | |
SDL.SDL_DestroyRenderer(renderer); | |
SDL.SDL_DestroyWindow(window); | |
SDL_image.IMG_Quit(); | |
SDL.SDL_Quit(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment