Jump to content
  • Advertisement

Gaius Baltar

  • Content Count

  • Joined

  • Last visited

Community Reputation

300 Neutral

About Gaius Baltar

  • Rank

Personal Information

  • Interests
  1. Thanks... I knew it was gonna be something simple...
  2. I'm trying to change the data in a Texture2D with Map/Unmap and am running into an issue where the texture seems to only appear in the top 5th of the screen and the rest is just random pixels. (screenshot for clarification) Here's some code: uint32_t* m_colorBuffer; //buffer to fill the texture with random colors D3D11_SUBRESOURCE_DATA m_textureData; ID3D11Texture2D* m_texture; D3D11_MAPPED_SUBRESOURCE mappedResource; m_deviceContext->Map(m_texture, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); uint32_t rowSize = 256 * 4; BYTE* mappedData = reinterpret_cast<BYTE*>(mappedResource.pData); for (int i = 0; i < 256; i++) { memcpy(mappedData, &(m_colorBuffer[i*rowSize]), rowSize); mappedData += mappedResource.RowPitch; } m_deviceContext->Unmap(m_texture, 0); Can Someone please tell me what I'm doing wrong here? I'd be happy to supply more code if needed.
  3. Gaius Baltar

    Issue with personal DirectX Framework

    Okay, I just realized that I forgot to add the InputLayout to the immediateContext. That basically solved the issue.   After some edits to the code I finally get the output I was hoping for:  
  4. First off I'd like to point out that I'm an absolute beginner regarding 3D graphics programming and DirectX in general. So if you have any code optimization tips for me I'll accept them with open arms.   I've been learning my way about the DirectX API using SlimDX and the help of some useful resources like Frank D. Luna's book on programming with DirectX 11 and this site . (The book and site go very well together, especially for someone learning to use DirectX with C#).   Anyhow, I've recently finished chapter 6 of Luna's book and decided to try and make a personal DirectX framework of sorts for learning purposes, but now that I've got a sort of skeleton of the thing going, it throws weird errors at me occasionally or it just doesn't do what I want it to (display a cube in this case).   So, here it is:   Window.cs [spoiler] using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using SlimDX; using SlimDX.Windows; using System.Drawing; using System.Windows.Forms; using SlimDX.Direct3D11; using Device = SlimDX.Direct3D11.Device; using Debug = System.Diagnostics.Debug; using SlimDX.DXGI;   namespace MyFramework {     public delegate void Renderer();     public delegate void Updater(float dt);     public delegate void Disposer();     public class Window : RenderForm     {         public Event windowsEvent;           public Renderer OnRender;         public Updater OnUpdate;         public Disposer OnDispose;         public Timer timer;         private Device device;         private SwapChain swapChain;         private DeviceContext immediateContext;         private RenderTargetView renderTargetView;         private DepthStencilView depthStencilView;         private Texture2D depthStencilBuffer;         private Viewport viewport;         private Rectangle scissorRect;         private Shader shader;         private EffectMatrixVariable fxWVP;         private Matrix proj;           private RasterizerStateDescription rsd;         private RasterizerState rs;           private int msaa4XQuality;         private bool enableMsaa4X;         private float viewportX;         private float viewportY;         private float viewportWidth;         private float viewportHeight;           public bool ToggleMsaa4XEnabled         {             get { return enableMsaa4X; }             set { enableMsaa4X = value; }         }           public bool ToggleWireframe         {             get             {                 if (rsd.FillMode == FillMode.Wireframe)                     return true;                 else                     return false;             }             set             {                 if (value)                     rsd.FillMode = FillMode.Wireframe;                 else                     rsd.FillMode = FillMode.Solid;             }         }           public bool ToggleScissorMode         {             get { return rsd.IsScissorEnabled; }             set { rsd.IsScissorEnabled = value; }         }           public Device Device         {             get { return device; }         }           public void SetScissorRect(int x, int y, int width, int height)         {             scissorRect = new Rectangle(x, y, width, height);         }         public Window(string title, Size size, float vX = 0, float vY = 0, float vWidth = -1, float vHeight = -1)             : base(title)         {             this.Size = size;             this.Icon = null;             viewportX = vX;             viewportY = vY;             viewportWidth = vWidth >= 0 ? vWidth : size.Width;             viewportHeight = vHeight >= 0 ? vHeight : size.Height;               Init();         }           private void Init()         {             device = null;             swapChain = null;             immediateContext = null;             renderTargetView = null;             depthStencilView = null;             depthStencilBuffer = null;             rs = null;             shader = null;             fxWVP = null;               msaa4XQuality = 0;             enableMsaa4X = true;               scissorRect = new Rectangle();             windowsEvent = new Event();             timer = new Timer();             rsd = new RasterizerStateDescription();             viewport = new Viewport();               OnRender += () => { };             OnUpdate += (dt) => { };             OnDispose += () => { };               this.ResizeBegin += (sender, args) =>             {                 timer.Stop();             };             this.ResizeEnd += (sender, args) =>             {                 timer.Start();                 OnResize();             };             this.FormClosing += (sender, args) =>             {                 DisposeWindow();                 OnDispose();                 Environment.Exit(0);               };             this.Show();             this.Update();               InitD3D();         }           private void InitD3D()         {             try             {                 device = new Device(DriverType.Hardware, DeviceCreationFlags.None);             }             catch (Exception ex)             {                 MessageBox.Show("D3D11Device creation failed\n" + ex.Message + "\n" + ex.StackTrace, "Error");             }               Debug.Assert((msaa4XQuality = device.CheckMultisampleQualityLevels(Format.R8G8B8A8_UNorm, 4)) > 0);             try             {                 var description = new SwapChainDescription()                 {                     BufferCount = 1,                     Usage = Usage.RenderTargetOutput,                     OutputHandle = this.Handle,                     IsWindowed = true,                     ModeDescription = new ModeDescription(0, 0, new Rational(60, 1), Format.R8G8B8A8_UNorm),                     SampleDescription = enableMsaa4X ? new SampleDescription(4, msaa4XQuality - 1) : new SampleDescription(1, 0),                     Flags = SwapChainFlags.AllowModeSwitch,                     SwapEffect = SwapEffect.Discard                 };                 Device.CreateWithSwapChain(DriverType.Hardware, DeviceCreationFlags.None, description, out device, out swapChain);                 immediateContext = device.ImmediateContext;                   rsd = new RasterizerStateDescription()                 {                     FillMode = FillMode.Solid,                     CullMode = CullMode.Back,                     IsAntialiasedLineEnabled = true,                     IsFrontCounterclockwise = false,                     IsDepthClipEnabled = true,                     IsScissorEnabled = false                 };                 rs = RasterizerState.FromDescription(device, rsd);                   using (var factory = swapChain.GetParent<SlimDX.DXGI.Factory>())                     factory.SetWindowAssociation(this.Handle, WindowAssociationFlags.IgnoreAltEnter);                   this.KeyDown += (o, e) =>                 {                     if (e.Alt && e.KeyCode == Keys.Enter)                     {                         swapChain.IsFullScreen = !swapChain.IsFullScreen;                     }                 };             }             catch (Exception ex)             {                 MessageBox.Show(ex.Message + "\n" + ex.StackTrace, "Error");             }             OnResize();         }           public void InitShader(string filePath)         {             shader = new Shader(ref device, filePath);             fxWVP = shader.fx.GetVariableByName("worldViewProj").AsMatrix();         }         public void InitCustomShader(string filePath, string[] inputElements, Format[] iEFormats, int[] iEStrides)         {             shader = new Shader(ref device, filePath, inputElements, iEFormats, iEStrides);         }           private void DisposeWindow()         {             Util.ReleaseCom(ref renderTargetView);             Util.ReleaseCom(ref depthStencilView);             Util.ReleaseCom(ref depthStencilBuffer);             if (shader != null) shader.Dispose();             if (immediateContext != null) immediateContext.ClearState();             if (swapChain.IsFullScreen) swapChain.SetFullScreenState(false, null);             Util.ReleaseCom(ref swapChain);             Util.ReleaseCom(ref immediateContext);             Util.ReleaseCom(ref device);         }           private void OnResize()         {             Util.ReleaseCom(ref renderTargetView);             Util.ReleaseCom(ref depthStencilView);             Util.ReleaseCom(ref depthStencilBuffer);             swapChain.ResizeBuffers(1, this.Width, this.Height, Format.R8G8B8A8_UNorm, SwapChainFlags.None);             using (var resource = SlimDX.Direct3D11.Resource.FromSwapChain<Texture2D>(swapChain, 0))             {                 renderTargetView = new RenderTargetView(device, resource);             }             var depthStencilDesc = new Texture2DDescription()             {                 Width = this.Width,                 Height = this.Height,                 MipLevels = 1,                 ArraySize = 1,                 Format = Format.D24_UNorm_S8_UInt,                 SampleDescription = enableMsaa4X ? new SampleDescription(4, msaa4XQuality - 1) : new SampleDescription(1, 0),                 Usage = ResourceUsage.Default,                 BindFlags = BindFlags.DepthStencil,                 CpuAccessFlags = CpuAccessFlags.None,                 OptionFlags = ResourceOptionFlags.None             };             depthStencilBuffer = new Texture2D(device, depthStencilDesc);             depthStencilView = new DepthStencilView(device, depthStencilBuffer);             immediateContext.OutputMerger.SetTargets(depthStencilView, renderTargetView);             viewport = new Viewport(viewportX, viewportY, viewportWidth, viewportHeight, 0.0f, 1.0f);             immediateContext.Rasterizer.SetViewports(viewport);               proj = Matrix.PerspectiveFovLH(0.25f * (float)Math.PI, this.Width / this.Height, 0.01f, 500.0f);         }           public Viewport Viewport         {             get { return viewport; }             set             {                 viewportX = value.X;                 viewportY = value.Y;                 viewportWidth = value.Width;                 viewportHeight = value.Height;                 OnResize();             }         }           public void Run()         {             MessagePump.Run(() =>             {                 timer.Tick();                 OnRender();                 OnUpdate(timer.DeltaTime);             });         }           public void ClearScreen(Color4 clearColor)         {             immediateContext.ClearRenderTargetView(renderTargetView, clearColor);             immediateContext.ClearDepthStencilView(depthStencilView, DepthStencilClearFlags.Depth | DepthStencilClearFlags.Stencil, 1.0f, 0);             immediateContext.Rasterizer.State = rs;         }           public void SetPrimitiveTobology(PrimitiveTopology topology)         {             immediateContext.InputAssembler.PrimitiveTopology = topology;         }           public void SwapBuffers()         {             swapChain.Present(0, PresentFlags.None);         }           public void Draw<T>(ref T entity) where T : Entity3D         {             immediateContext.InputAssembler.SetVertexBuffers(0, new VertexBufferBinding(entity.vb, Vertex.stride, 0));             immediateContext.InputAssembler.SetIndexBuffer(entity.ib, Format.R32_UInt, 0);               if (shader != null)             {                 Vector3 pos = new Vector3(3, 3, 3);                 Vector3 target = new Vector3(0);                 Vector3 up = new Vector3(0, 1, 0);                 Matrix view = Matrix.LookAtLH(pos, target, up);                 fxWVP.SetMatrix(entity.shapeWorld * view * proj);                 for (int p = 0; p < shader.tech.Description.PassCount; p++)                 {                     shader.tech.GetPassByIndex(p).Apply(immediateContext);                     immediateContext.DrawIndexed(entity.indexCount, 0, 0);                 }             }             else             {                 immediateContext.DrawIndexed(entity.indexCount, 0, 0);             }         }           protected override void WndProc(ref Message m)         {             windowsEvent.SetType(m);             base.WndProc(ref m);         }     } }  [/spoiler]   Sahder.cs [spoiler] using SlimDX.D3DCompiler; using SlimDX.Direct3D11; using SlimDX.DXGI; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using Device = SlimDX.Direct3D11.Device;   namespace MyFramework {     class Shader     {         public InputLayout inputLayout;         public Effect fx;         public EffectTechnique tech;           public Shader(ref Device device, string filePath, string[] inputElements, Format[] iEformats, int[] iEStrides)         {             CompileShaders(ref device, filePath);             CreateInputLayout(ref device, inputElements, iEformats, iEStrides);         }           public Shader(ref Device device, string filePath)         {             CompileShaders(ref device, filePath);             string[] inputElements = new string[] { "POSITION", "COLOR" };             Format[] iEformats = new Format[] { Format.R32G32B32_Float, Format.R32G32B32A32_Float };             int[] iEStrides = new int[] { 12 };               CreateInputLayout(ref device, inputElements, iEformats, iEStrides);         }           private void CompileShaders(ref Device device, string filePath)         {             string errors = null;             ShaderBytecode compiledShader = null;             try             {                 compiledShader = ShaderBytecode.CompileFromFile(                 filePath,                 null,                 "fx_5_0",                 ShaderFlags.None,                 EffectFlags.None,                 null,                 null,                 out errors);                 fx = new Effect(device, compiledShader);             }             catch (Exception ex)             {                 if (!string.IsNullOrEmpty(errors))                 {                     MessageBox.Show(errors);                 }                 MessageBox.Show(ex.Message);                 return;             }             finally             {                 Util.ReleaseCom(ref compiledShader);             }             tech = fx.GetTechniqueByName("Tech");         }           private void CreateInputLayout(ref Device device, string[] inputElements, Format[] iEformats, int[] iEStrides)         {             InputElement[] vertexDesc = new InputElement[inputElements.Length];             for (int i = 0; i < vertexDesc.Length; i++)             {                 vertexDesc[i] = new InputElement(inputElements[i], 0, iEformats[i], i > 0 ? iEStrides[i - 1] : 0, 0, InputClassification.PerVertexData, 0);             }               var passDesc = tech.GetPassByIndex(0).Description;             inputLayout = new InputLayout(device, passDesc.Signature, vertexDesc);         }           public void Dispose()         {             Util.ReleaseCom(ref inputLayout);             Util.ReleaseCom(ref fx);         }     } }  [/spoiler]   Entity3D.cs [spoiler] using SlimDX; using SlimDX.Direct3D11; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Buffer = SlimDX.Direct3D11.Buffer;   namespace MyFramework {     public class Entity3D     {         public int vertexCount;         public int indexCount;         public Vertex[] vertices;         public uint[] indices;         public Matrix shapeWorld;         public Buffer vb;         public Buffer ib;                    public Entity3D()         {             vertexCount = 0;             indexCount = 0;             vertices = null;             indices = null;             vb = null;             ib = null;             shapeWorld = Matrix.Identity;         }           public virtual void Dispose()         {             Util.ReleaseCom(ref vb);             Util.ReleaseCom(ref ib);         }     } }[/spoiler]   Cube.cs [spoiler] using SlimDX; using SlimDX.Direct3D11; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Buffer = SlimDX.Direct3D11.Buffer;   namespace MyFramework {     public class Cube : Entity3D     {         public Cube(Device device, float width, float height, float depth, Color4 color)             : base()         {             float x = 0.5f * width;             float y = 0.5f * height;             float z = 0.5f * depth;               vertexCount = 8;             indexCount = 36;             vertices = new Vertex[] {                  new Vertex(-x,-y,-z, color), // 0                 new Vertex( x,-y,-z, color), // 1                 new Vertex( x, y,-z, color), // 2                 new Vertex(-x, y,-z, color), // 3                 new Vertex(-x,-y, z, color), // 4                 new Vertex( x,-y, z, color), // 5                 new Vertex( x, y, z, color), // 6                 new Vertex(-x, y, z, color), // 7             };             indices = new uint[] {                  0,3,2,                 0,2,1,                 2,6,1,                 6,5,1,                 6,7,5,                 7,4,5,                 7,3,4,                 3,0,4,                 7,6,3,                 3,6,2,                 0,1,4,                 1,5,4             };               BufferDescription vbd = new BufferDescription(Vertex.stride * vertexCount, ResourceUsage.Immutable, BindFlags.VertexBuffer, CpuAccessFlags.None, ResourceOptionFlags.None, 0);             vb = new Buffer(device, new DataStream(vertices, false, false), vbd);             BufferDescription ibd = new BufferDescription(sizeof(uint) * indexCount, ResourceUsage.Immutable, BindFlags.IndexBuffer, CpuAccessFlags.None, ResourceOptionFlags.None, 0);             ib = new Buffer(device, new DataStream(indices, false, false), ibd);         }     } }  [/spoiler]   Vertex.cs [spoiler] using SlimDX; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks;   namespace MyFramework {     public struct Vertex     {         public Vector3 position;         public Color4 color;         public const int stride = 28;           public Vertex(Vector3 pos, Color4 col)         {             position = pos;             color = col;         }         public Vertex(float x, float y, float z, Color4 col)         {             position = new Vector3(x, y, z);             color = col;         }     } }  [/spoiler]   Program.cs //Main entry point   [spoiler] using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using MyFramework; using System.Drawing; using SlimDX;   namespace FrameworkTester {     class Program     {         static void Main(string[] args)         {             SlimDX.Configuration.EnableObjectTracking = true;             Window window = new Window("Test", new Size(1280, 720));               window.InitShader("FX/shader.fx");               window.OnUpdate += (dt) => {                               };               Cube cube = new Cube(window.Device, 0.5f, 0.5f, 0.5f, Color.White);               window.OnRender += () => {                 window.ClearScreen(Color.CornflowerBlue);                 window.SetPrimitiveTobology(SlimDX.Direct3D11.PrimitiveTopology.TriangleList);                 window.Draw(ref cube);                 window.SwapBuffers();             };               window.OnDispose += () => {                 cube.Dispose();             };               window.Run();         }     } }  [/spoiler]   And lastly, my shader, "shader.fx" [spoiler] cbuffer wvpm{ float4x4 worldViewProj; };   struct VertexIn { float3 PosL : POSITION; float4 Color : COLOR; }; struct VertexOut { float4 PosH : SV_POSITION; float4 Color: COLOR; }; RasterizerState rsWireframe{  FillMode = Wireframe; CullMode = Back; FrontCounterClockwise = false; }; VertexOut VS(VertexIn vin){ VertexOut vout; vout.PosH = mul(float4(vin.PosL, 1.0f), worldViewProj); vout.Color = vin.Color; return vout; } float4 PS(VertexOut pin) :SV_Target{ return pin.Color; } technique11 Tech { pass P0{ SetVertexShader(CompileShader(vs_4_0, VS())); SetGeometryShader(NULL); SetPixelShader(CompileShader(ps_4_0, PS())); } }[/spoiler]   I'd like to leave you with a screenshot of what I get when I run Program.cs:   Also, please don't bash the hard-coded stuff too much, everything so far is mostly just placeholder code for me to get my bearings.
  5. Gaius Baltar

    c# method question

      It appears, I was wrong, go with Nypyren's suggestion, in this case it would be the better solution overall.
  6. Gaius Baltar

    c# method question

    Disregard this post. 
  7. Gaius Baltar

    c# method question

    Disregard this post
  8. Gaius Baltar

    Line vs Triangle collision in 3D

    You're welcome! The thing is, I've never actually done anything in 3d so this is completely theoretical... would be logical though.   Also I would be interested to know how one would find the position where the line and triangle pass each other, I could probably figure it out for 2d but it seems more complex for 3d.If anyone knows, would be great to note into my reference book.
  9. Gaius Baltar

    Line vs Triangle collision in 3D

    I'm just guessing right now, so this might be wrong:   First check if the line ever passes the triangle, if yes, take the point where the line passes the triangle and make three more triangles with each of the points of the original triangle and the point like so:       If the area of the three triangles is equal to the area of the larger triangle, you have yourself an intersection. I actually had a quick glimpse at a youtube video talking about this kind of intersection, thought it might be worth sharing my two cents.   Edit: Here's the video: 
  10. Gaius Baltar

    Missile Command code review request

    I figured that, but I thought Visual Studio somehow did it differently. Suppose not.
  11. Gaius Baltar

    Missile Command code review request

    Oh, I missed the static part. Thanks for clarification.
  12. Gaius Baltar

    Missile Command code review request

    I'm using Visual Studio, as far as I can tell it only compiles the files that have been edited, and if I'm not mistaken, I believe that it doesn't compile files just because they were included by another. Or, I could be totally wrong about that... I never really considered the possibility of simply creating a data array to fill another array. Wouldn't it be expensive though to recreate the array every iteration of the loop?
  13. Gaius Baltar

    Missile Command code review request

      So, I should make multiple headers? includes.h and constants.h?   But I also don't really see how "init.h" isn't scalable, is it because of the merging of includes and constants in a single file, or is there another reason?   Even with the "classname.cpp #includes classname.h" thing, wouldn't it still be the same? Because the classname.h still might depend on stuff from init.h. Or am I getting this wrong somehow?     Yeah, I try to spend the least amount of time on naming my variables, if I don't think of a name fast, it might get a bad name .     I know. After a while it got really confusing to try and find code I was looking for in that file, In my next project I'm going to have my entire GUI in a separate class, that should save me a few lines.        I was thinking of doing that, but then I didn't... I suppose it was too much work for me , especially because it was only used for the high scores.       Yeah, KulSeran told me the same thing just about. And my question to him still stands:  "[background=#fafbfc]...I believe sfml takes care of deallocating it's own allocated memory, so the destructor wouldn't really be necessary(?)[/background]". Is it always necessary to implement all three? Because in the case of the button class, the destructor would be empty.      I remember someone posting on a previous thread of mine that I shouldn't keep the application running after an error has occured. Should I keep it running or not? I'm confused, but I suppose I could write the error to a error log file or something.     My attempt at trying to stay consistent with the sfml naming convention (mostly inspired by the sf::Vector<> class) , I suppose I failed.      That's a mistake, I think most of the time I just completely forget that I'm following any kind of naming convention and just name the damn thing whatever seems right at the time .       Huh, but how would I integrate the jump from 300 to 600? I can't think of a way.      Woops, I think the problem here is that I used to have a text class. When I got rid of that I tried to rewrite everything into the button class, I suppose I just missed a few things on the way.       I keep forgetting some of these built in methods to make life easier... I'll implement that.        I used a whole button class, because I thought there was a method to test if one class was equal to another, that failed, so I used the string value in the button, seems stupid now that I think about it.       That's what I did with the missiles, because I first had like five vectors just for the missiles in my Missile_Command class. But I didn't want to make a whole new class for the enemies, I suppose it slipped my mind that I could have easily used a structure to store both items...       Thanks for reading through my code, I appreciate the time that you took to do so. This review really gave me a further push in the right direction and I'll most likely use this as a reference for future projects.      vector.end() is 1) you could do (vector.end() - 1) as well.  The end iterator is one-past the end of the array, and does not point at a valid object. 2) It's all relative to the container.  Not all containers provide iterators that support (end() -1).  Vector happens to be a random-access iterator, so vector.begin() + x is just as fast as vector.end() - y.  So yes, you could base the second point off the end iterator.     Oh, I thought vector.end() was just the last item in the array.   You're right, in my case it wouldn't matter for the _trails particles, because they all have a one pixel area and are mostly white.  
  14. Gaius Baltar

    3D Graphics with C#

    You can use OpenTK for C#, it might even be what 3ddreamer meant with "There is an OpenGL library for 3D but I don't remember what it is called".
  15. Gaius Baltar

    Missile Command code review request

      Thanks for trying it out! Yeah, the console window is a little intrusive at times, but is required for score keeping in this case (also debugging). I suppose I just didn't want to write a class utilizing text objects to keep track of user input.     First of all, thanks for taking the time to read through my code! As to the underscore naming convention, could you suggest what I should use instead?   I'll make sure to do that. That's interesting, so far I've always written my classes: private > protected > public. I'll keep that in mind for my next project.   I never really got into reserving memory for vectors before... I'll have to look that up, but does it really make in impact on performance to reserve vector space?   Wow, that actually makes way more sense than my code, but wouldn't it be vector.end() and not vector.begin() + (vector.size() - 1)? Or is there some sort of difference?   You're right about the copy constructor, but I believe sfml takes care of deallocating it's own allocated memory, so the destructor wouldn't really be necessary(?) I could implement it anyway, just to stay consistent with the C++ law.   I thought you only had to do the const reference thing on parameters, but I suppose now that you mentioned it, it kind of does make sense to return a const reference as well.   Yeah, I keep telling myself that, because most of the time I end up expanding my if statements anyway, but I suppose in some cases it's just faster to not include the curly brackets. I think I'll eventually find an equilibrium between curly brackets and no curly brackets.   Woops.
  • Advertisement

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!