Jump to content
  • Advertisement
Sign in to follow this  
  • entries
  • comments
  • views

About this blog

Me actually trying to finish a game

Entries in this blog


Small break, but back to work

I took a break due to work being hectic and everyone seeming to get sick. I added alpha blending and I have working armatures and working on the keyframes to create animations.




It looks like something

I got rid of most of the slider bars now that I have working color picking and constant buffers. So I decided to try and draw something. I was going for the mysterious woman on the water in a row boat.
All the shapes now have visible, clickable, control points. I need to work a little bit more on correct mouse movement translations (you move left but the control moves right). But I was able to accomplish this. Next is armatures for actual animation.





Color Picking, Constant Buffers, and Shaders

FINALLY!!! Constant buffer worked without errors. I guess I kept running into bad examples. Many were missing information. I simply wanted to do color picking and set a constant buffer for the color. So both the color picking and the constant buffer (to set the object/shape to a solid color to be referenced) were a pain.
R - What kinds of pick (gui, object/shape, control point)
G - index1 (example - object index)
B - index2 (example - shape index)

So I finally wrote directx functions that are similar to my opengl counterparts.

For now this is my constant buffer (the name is from the msdn example). Vector4f is my own (x, y, z, w).
The other is my PixelShader, to which is stored in a vector for multiple shaders.struct VS_CONSTANT_BUFFER{Vector4f modifier;};struct PixelShader{ID3D11PixelShader* shader; ID3D11Buffer* g_pConstantBuffer11;Vector4f modifier;};
This is my AddShader routine. I currently have both my pixel shader and vertex shader in the same file, but left it like this in case I change my mind. I just give the same file name for both pix and vert.Vector2i Shaders::AddShader(ID3D11Device *dev, ID3D11DeviceContext *devcon, char* pix, char* vert){cShade = -1;//The Shaders. cShade holds the index of current shader loaded. -1 means none.pVS.resize(pVS.size() + 1);pPS.resize(pPS.size() + 1);pLayout.resize(pLayout.size() + 1);ID3D10Blob *VS, *PS;HRESULT HRV = D3DX11CompileFromFile(vert, 0, 0, "VShader", "vs_4_0", 0, 0, 0, &VS, 0, 0);HRESULT HRP = D3DX11CompileFromFile(pix, 0, 0, "PShader", "ps_4_0", 0, 0, 0, &PS, 0, 0);//Create the shaders and give the pointers. Vertex currently does not have extra parameters is just a std::vectordev->CreateVertexShader(VS->GetBufferPointer(), VS->GetBufferSize(), NULL, &pVS[pVS.size() - 1]);dev->CreatePixelShader(PS->GetBufferPointer(), PS->GetBufferSize(), NULL, &pPS[pPS.size() - 1].shader);//Each time the shaders are set, the modifier will be set to this initial valuepPS[pPS.size() - 1].modifier.x = 1.0f;pPS[pPS.size() - 1].modifier.y = 1.0f;pPS[pPS.size() - 1].modifier.z = 1.0f;pPS[pPS.size() - 1].modifier.w = 1.0f;//modify is what will be sent to the constant buffermodify.modifier = pPS[pPS.size() - 1].modifier;//constant buffer setup section STARTD3D11_BUFFER_DESC bd;ZeroMemory(&bd, sizeof(bd));bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER;bd.ByteWidth = sizeof(modify);bd.Usage = D3D11_USAGE_DEFAULT;HRESULT hr = dev->CreateBuffer(&bd, 0, &pPS[pPS.size() - 1].g_pConstantBuffer11);if( !FAILED( hr ) )devcon->VSSetConstantBuffers( 0, 1, &pPS[pPS.size() - 1].g_pConstantBuffer11 );//constant buffer setup section ENDD3D11_INPUT_ELEMENT_DESC ied[] ={{"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},{"COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0},{"UV", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 28, D3D11_INPUT_PER_VERTEX_DATA, 0},}; dev->CreateInputLayout(ied, 3, VS->GetBufferPointer(), VS->GetBufferSize(), &pLayout[pLayout.size() - 1]);return Vector2i(pPS.size() -1, pVS.size() - 1);}
This part of the code I saw so many different variations on. This one worked for me (finally).D3D11_BUFFER_DESC bd;ZeroMemory(&bd, sizeof(bd));bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER;bd.ByteWidth = sizeof(modify);bd.Usage = D3D11_USAGE_DEFAULT;HRESULT hr = dev->CreateBuffer(&bd, 0, &pPS[pPS.size() - 1].g_pConstantBuffer11);if( !FAILED( hr ) )devcon->VSSetConstantBuffers( 0, 1, &pPS[pPS.size() - 1].g_pConstantBuffer11 );
I selected my shader for drawing here.void Shaders::SetShader(ID3D11DeviceContext *devcon, int index){if (cShade == index) return;cShade = index;devcon->VSSetShader(pVS[index], 0, 0);devcon->PSSetShader(pPS[index].shader, 0, 0);devcon->IASetInputLayout(pLayout[index]);SetConstantBuffer(devcon, pPS[cShade].modifier);}
This code is used after I select the shader for the current draw (or when the shader is first selected). This will update the constant buffer to a new value. I can use it for color picking and other fun stuff.void Shaders::SetConstantBuffer(ID3D11DeviceContext *devcon, Vector4f aMod){modify.modifier = aMod;devcon->UpdateSubresource(pPS[cShade].g_pConstantBuffer11, 0, 0, &modify, 0, 0);devcon->PSSetConstantBuffers(0, 1, &pPS[cShade].g_pConstantBuffer11);}
And this is the shader for my ellipsestruct VOut{ float4 position : SV_POSITION; float4 color : COLOR; float2 uv : UV;};cbuffer VS_CONSTANT_BUFFER : register(b0){ float4 modifier;};VOut VShader(float4 position : POSITION, float4 color : COLOR, float2 uv : UV){ VOut output; output.position = position; output.color = color; output.uv = uv; return output;}float4 PShader(float4 position : SV_POSITION, float4 color : COLOR, float2 uv : UV) : SV_TARGET{ float result = (uv.x * uv.x + uv.y * uv.y); if (color.a 1) discard; if (modifier.w == 0.0) { color.r = modifier.x; color.g = modifier.y; color.b = modifier.z; color.a = 1.0; } return color;}

[Edit] Forgot Color Picking.
The Color format of the 1x1 texture must be the same as your backbuffer, or this is SO fail (took a while on that). The mouse must be in bounds or the srcbox will be said to be invalid.Vector4f PickColor(int the2d, int x, int y, ID3D11Device *dev, ID3D11DeviceContext *devcon){ID3D11Texture2D *BackBuffer;HRESULT hr = swapchain->GetBuffer( 0, __uuidof( ID3D11Texture2D ), reinterpret_cast( &BackBuffer ));Vector4f a = Vector4f(0, 0, 0 ,0);ID3D11Texture2D *Surface;D3D11_TEXTURE2D_DESC StagedDesc = {1,//Width;1,//Height;1,//MipLevels;1,//ArraySize;DXGI_FORMAT_R8G8B8A8_UNORM,//DXGI_FORMAT Format;1, 0,//DXGI_SAMPLE_DESC SampleDesc;D3D11_USAGE_STAGING,//D3D11_USAGE Usage;0,//UINT BindFlags;D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE,//UINT CPUAccessFlags;0//UINT MiscFlags;};dev->CreateTexture2D( &StagedDesc, NULL, &Surface);D3D11_BOX srcBox;srcBox.left = x;srcBox.right = srcBox.left + 1;srcBox.top = y;srcBox.bottom = srcBox.top + 1;srcBox.front = 0;srcBox.back = 1;devcon->CopySubresourceRegion(Surface, 0, 0, 0, 0, BackBuffer, 0, &srcBox);D3D11_MAPPED_SUBRESOURCE msr;if (devcon->Map(Surface, 0, D3D11_MAP_READ_WRITE, 0, &msr) != S_OK) return Vector4f(-1, -1, -1, -1);void *pixelA = msr.pData;std::vector pixel;pixel.resize(4);memcpy(&pixel[0], pixelA, 4);a.x = (float)pixel[0];a.y = (float)pixel[1];a.z = (float)pixel[2];a.w = (float)pixel[3];pixel.resize(0);devcon->Unmap(Surface, 0);Surface->Release();BackBuffer->Release();return a;}




Bezier, it's french

So I got bezier curves kickin', along with variable width of the start, middle, and end. If you have not used bezier ([be.zje]) is actually not a hard concept, but very effective. They use control points to modify a line interpolation from straight line into a curve.
Coding Math 19 was very helpful.

I used cubic bezier, so I have a start point, end point, and two control points.

This is the code, to which I got directly from the video, but it is apparently just the code for quadratic bezier (1 control point) and Cubic bezier (2 control point). t is what percent along the line you are at (between 0.0f and 1.0f). You input the start, 1 or 2 control points depending, and the end point. You give the t and it will change pFinal to the correct point along the curve. The smaller the increments you give for t, the smoother the curve will look. All the curves in the picture are 20 segments.
void QuadraticBezier(Vector2f p0, Vector2f p1, Vector2f p2, float t, Vector2f& pFinal){pFinal.x = powf(1.0f - t, 2.0f) * p0.x + (1 - t) * 2.0f * t * p1.x + t * t * p2.x;pFinal.y = powf(1.0f - t, 2.0f) * p0.y + (1 - t) * 2.0f * t * p1.y + t * t * p2.y; }void CubicBezier(Vector2f p0, Vector2f p1, Vector2f p2, Vector2f p3, float t, Vector2f& pFinal){pFinal.x = powf(1.0f - t, 3.0f) * p0.x +powf(1 - t, 2) * 3.0f * t * p1.x +(1 - t) * 3 * t * t * p2.x + t * t * t * p3.x;pFinal.y = powf(1.0f - t, 3.0f) * p0.y +powf(1 - t, 2) * 3.0f * t * p1.y +(1 - t) * 3 * t * t * p2.y + t * t * t * p3.y;}
I also used a function I wrote called Wide. It uses the start, middle, and ending widths are parameters. t is the same as the curve. It calculates how wide the line will be. Before halfway through, it ignores the ending width. After halfway through, it ignores the beginning width. It was cleaner than having all this in the loop creating the curve.Vector2f Wide(Vector2f a, Vector2f b, Vector2f c, float t){float x, y;if (t == 0.0f){x = a.x;y = a.y;}else if (t





Directx, What a pain in the butt! I learned opengl with no problems when it came to using uniform data and sending it to the shaders. Constant Buffers are not nearly as user friendly. I am sure they have wonderful attributes to them, but geez. But I did get my ellipses working along with my curved lines. I am using control points to define the length and width of both and then creating triangles that have u,v points to define the curves.

The Ellipse uvsuv[0] = Vector2f(0.0f, 2.0f);uv[1] = Vector2f(2.0f, 0.0f);uv[2] = Vector2f(0.0f, 2.0f);
The uvs are 2.0 so a curve of 1 radius will touch the hypotenuse (longest side of a right triangle).
The vertices are added along with indices to form a diamond of triangles. The ellipse will be within the triangle.objects[a].shapes.AddVertex(p[0], col[2], uv[0]);objects[a].shapes.AddVertex(p[1], col[2], uv[1]);objects[a].shapes.AddVertex(p[2], col[2], uv[1]);objects[a].shapes.AddVertex(p[3], col[0], uv[2]);objects[a].shapes.AddVertex(p[4], col[2], uv[0]);objects[a].shapes.AddTriangle(0, 3, 1);objects[a].shapes.AddTriangle(0, 2, 3);objects[a].shapes.AddTriangle(4, 1, 3);objects[a].shapes.AddTriangle(4, 3, 2);
The pixel shader for ellipse

I am discarding any pixel that is greater than a length of 1. I am using the uvs to determine length.float4 PShader(float4 position : SV_POSITION, float4 color : COLOR, float2 uv : UV) : SV_TARGET{float result = sqrt(uv.x * uv.x + uv.y * uv.y);if (color.a 1) discard; return color;}





Well I had super fun learning win32 without using a wrapper. I ended up with a system similar to what I used with my self made gui system, with the hWnd of each control being stored in an array. Now I have a drawing window, a working property page and a pop up (ish) window. Now I use sliders for adjust the properties so they can change on the fly.




Vector Graphics

So after figuring up the amount of work to make the bitmaps look fine on pc and android (all the different resolutions), I decided to go vector. So now I am making a vector graphics editor (aka like flash). This way it will scale to any resolution without loss.





Did not give up

I kept flip flopping on what I wanted to do. It is hard for me to give up on trying to make a 3d game. And I also want to add a lot of material to a game, I love customization. So I decided to try and limit myself forcibly by doing this on Android. Most people are not going to have a gamepad with it, and on screen ones are hit and miss. So I am making sure I keep it simple enough to be effective with only a touchscreen.
In the last two weeks (in between work), I have make a tile-map editor and character animation editor.

Right now I don't have a screenshot of it actually working on android simply because I am re-writing the loading of the character right now. I switched from text based to binary, also added more information per frame of animation. The character is moving and collision detection is working (albeit with a couple of bugs). So far so good..




Raw Input API

A lot of research went into using Raw Input API on a gamepad.
I am using a Logitech Dual Action usb gamepad.
This is where I got the best example. But he obviously changed part of the code cause it didn't work.

So after more research and tweeking, got it to work. Right now it is 4 buttons, two analog sticks, and the directional pad. The others wont be hard, just haven't done them yet.

you have to include HidClass.h
This may require installing the WDK (windows driver kit)
It may not as I believe Mingw already had it.
I tried a bunch of stuff so I installed WDK along the way.

This is in the windows WndProc
rid[0].usUsagePage = 0x01;
rid[0].usUsage = 0x05;
rid[0].dwFlags = RIDEV_INPUTSINK;
rid[0].hwndTarget = hWnd;

rid[1].usUsagePage = 0x01;
rid[1].usUsage = 0x04;
rid[1].dwFlags = RIDEV_INPUTSINK;
rid[1].hwndTarget = hWnd;

if (!RegisterRawInputDevices(rid, 2, sizeof(rid[0])))
return 0;
case WM_INPUT:
UINT cbSize;
LPBYTE lpbBuffer = new BYTE[cbSize];
RAWINPUT* raw = (RAWINPUT*)lpbBuffer;
if (lpbBuffer == NULL)
return 0;
if (raw->header.dwType == RIM_TYPEHID)
BYTE* test = new BYTE[raw->data.hid.dwCount * raw->data.hid.dwSizeHid];
test = &raw->data.hid.bRawData;

componentManager.gamepad.StateChange(0, test, raw->data.hid.dwCount * raw->data.hid.dwSizeHid);
return 0;

This is my gamepad class:
Each byte of data held multiple values. I am sure there is a better way of getting the values, but this worked.
I subtracted 127 from the analog so I could have a +/- value versus a 0 to 255.
I also made 16 the deadzone radius for the analog.
They stored 4 button values and the directional pad in one byte.
The value was 8 when nothing was pressed.
The directional pad was a value 0-7 when pressed.
Button 1: 16
Button 2: 32
Button 3: 64
Button 4: 128
I divided by 16 and made that Byte b.
BYTE c = data[5] - b * 16.

This made c the remainder due to rounding.
If no direction button is held, c would be negative because 8 would round up when divided by 16 due to the variable being a BYTE. So when multiplied by 16, it would be a number greater than data[5].
Otherwise, c would be 0-7.

void Gamepad::StateChange(int aPlayer, BYTE* data, int aSize)
if (player[aPlayer].type == 0)
player[aPlayer].analog[0].x = data[1] - 127;
player[aPlayer].analog[0].y = data[2] - 127;
player[aPlayer].analog[1].x = data[3] - 127;
player[aPlayer].analog[1].y = data[4] - 127;
if (player[aPlayer].analog[0].x -17) player[aPlayer].analog[0].x = 0;
if (player[aPlayer].analog[0].y -17) player[aPlayer].analog[0].y = 0;
if (player[aPlayer].analog[1].x -17) player[aPlayer].analog[1].x = 0;
if (player[aPlayer].analog[1].y -17) player[aPlayer].analog[1].y = 0;
bool a[4];
BYTE b = data[5] / 16;
BYTE c = data[5] - b * 16;
a[3] = (b >= 8);
if (a[3]) b -= 8;
a[2] = (b >= 4);
if (a[2]) b -= 4;
a[1] = (b >= 2);
if (a[1]) b -= 2;
a[0] = (b >= 1);
if (a[0]) b -= 1;
player[aPlayer].button[0] = a[0];
player[aPlayer].button[1] = a[1];
player[aPlayer].button[2] = a[2];
player[aPlayer].button[3] = a[3];
switch (c)
player[aPlayer].POV.x = 0;
player[aPlayer].POV.y = 1;
player[aPlayer].POV.x = 1;
player[aPlayer].POV.y = 1;
player[aPlayer].POV.x = 1;
player[aPlayer].POV.y = 0;
player[aPlayer].POV.x = 1;
player[aPlayer].POV.y = -1;
player[aPlayer].POV.x = 0;
player[aPlayer].POV.y = -1;
player[aPlayer].POV.x = -1;
player[aPlayer].POV.y = -1;
player[aPlayer].POV.x = -1;
player[aPlayer].POV.y = 0;
player[aPlayer].POV.x = -1;
player[aPlayer].POV.y = 1;
player[aPlayer].POV.x = 0;
player[aPlayer].POV.y = 0;
void Gamepad::UpdateGamepad()
for (unsigned aPlayer = 0; aPlayer {

for (unsigned count = 0; count {
if (player[aPlayer].button[count] == true && player[aPlayer].prevButton[count] == false) player[aPlayer].buttonState[count] = 1; //just hit
else if (player[aPlayer].button[count] == true && player[aPlayer].prevButton[count] == true) player[aPlayer].buttonState[count] = 2; //held
else if (player[aPlayer].button[count] == false && player[aPlayer].prevButton[count] == true) player[aPlayer].buttonState[count] = 3; //just let go
else player[aPlayer].buttonState[count] = 0; //up
player[aPlayer].prevButton[count] = player[aPlayer].button[count];


After all the windows messaging is completed, UpdateGamepad() is called. This updates the button state by comparing it to the previous button state. Then all the previous button states are made equal to the current. This is done for all 4 potential players.




Small Break and now trying Gamepad support

I worked some crazy hours the last few weeks and had a vacation. I spent the vacation catching up on shows and got the ps4, so was also playing that.
I'm working on getting the basics of the game going to I can sync both the animator and game together. I may implement something in the animator, and absolutely realize it was a terrible idea in the game. And vice versa.
Right now, I am trying to implement a gamepad.
MICROSOFT, what is your problem?
I found multiple links to XInput/DirectInput. It was like they found the worst programmer to write the example. There was poor structuring and goto.....I haven't seen a goto in years.
I said screw it, and am either going to use Raw Input API or maybe SDL.
I hear good things about SDL...just not sure if it is for me.





So I cloned my main hard drive over to a bigger one and then extended the partition. Everything seemed fine the first day. I even programmed more. I have been working a lot at my sad non-computer based job so not much programming. I have been working on a multi-branching menu GUIObject. It was working....then the new(er) hard drive had a meltdown and windows went nuts. So we had to put the old hard drive in. I lost only a little bit of programming...and am somehow now not programming the menu right. For some reason glReadPixels reads the menu object as a whole entity. Then inside the menu object, I redraw the menu only, with each button and item inside having its own color. Now it is only reading the background color. Quite frustrating. It was SO much simplier when I did everything has a bounding box and checked if the mouse position was in or out of the box. But I want the possibility of interesting shapes for the GUIObjects so I am determined.

Still frustrated...

Decided to do a screw it. I figured it down the me trying to redo the frame/screen in which the menu object is located. Basically clear the area and redo the viewport. For some reason, this was messing up thing, because when I removed the code it started working just fine. So for now I am moving on, and will come back to it if I need to.




GUIObject: Button

Now please correct me if I say something wrong. I am not trying to create a tutorial, but rather explain my process.

Now all my GUI (Graphical User Interface) objects inherit from GUIObject.hpp

#include #include "OpenGLContext.hpp"#include "Command.hpp"#include "AValue.hpp"#include "Vector2i.hpp"#include "Texture.hpp"#include "FontBMP.hpp"#include #include #include #include "Buffer.hpp"#include "Mouse.hpp"#ifndef GUIOBJECT_H#define GUIOBJECT_Hclass GUIObject{public: GUIObject() { }; std::vector command; //outgoing command std::vector commands; //command to copy to outgoing std::string name; std::string type; int width; int height; Vector2i position; Vector2i prevPos; bool enabled; //Is this button clickable; bool visible; Vector2i mousePosition; int debug; std::string debugS; bool created; bool grabbed; virtual void Standard() { return; }; virtual void CreateVAO() { return; } virtual void Destroy() { return; } virtual void Draw(std::vector &textures, FontBMP &aFont, bool textured, OpenGLContext *openglContext) { Draw(0, 0, textures, aFont, textured, openglContext); return; }; virtual void Draw(int sx, int sy, std::vector &textures, FontBMP &aFont, bool textured, OpenGLContext *openglContext) { return; }; virtual void DrawPick(int sx, int sy, Color4f thePick, OpenGLContext *openglContext) { return; } virtual void SetPosition(int x, int y, int Awidth, int Aheight) { position.x = x; position.y = y; width = Awidth; height = Aheight; } virtual void SetPosition(int x, int y) { SetPosition(x, y, width, height); return; } virtual bool InBounds(Vector2i pos) { return InBounds(pos.x, pos.y); } virtual bool InBounds(int x, int y) { if (x > position.x && x position.y && y upperLeft.x && pos.x upperLeft.y && pos.y keys, std::vector buffer) { return -2; }; virtual AValue PropertyGet(std::string theProp) { AValue newValue; newValue.theString = (char*)"none"; return newValue; }; virtual std::vector PropertyGetVector(std::string theProp) { std::vector newValue; newValue.clear(); return newValue; }; virtual void PropertySet(std::string theProp, std::string theFormat, ...) { return; }; virtual void PropertySet(std::string theProp, AValue &theValue) { return; } virtual void Commands(Command &aCommand) { return; } virtual AValue CommandR(Command &aCommand) { return AValue(); } virtual void LoseFocus() { return; }};#endifNow my Button class will Inherit the GUIObject class. This allows Button to immediately have all the variables and functions that the GUIObject has. Plus, it can override any virtual class to make one with the same name and parameters, but different code inside it.
Now if I wanted to, I could make a function abstract versus virtual. This would make any class that inherits this class forced to override the function and make its own.

#ifndef Button_h#define Button_h#include "GUIObject.hpp"#include "Quad.hpp"#include class Button: public GUIObject{ public: Quad back; std::string text; Button() { } Button(const Button& other) { if (this != &other) { Destroy(); back = other.back; } } void Standard(); void CreateVAO(); void Destroy(); void Draw(std::vector &textures, FontBMP &aFont, bool textured, OpenGLContext *openglContext); void Draw(int sx, int sy, std::vector &textures, FontBMP &aFont, bool textured, OpenGLContext *openglContext); void DrawPick(int sx, int sy, Color4f thePick, OpenGLContext *openglContext); void SetPosition(int x, int y, int Awidth, int Aheight); void SetPosition(int x, int y); bool InBounds(int x, int y); bool ClickUp(Mouse& mouse); bool ClickHeld(Mouse& mouse); bool ClickDown(Mouse& mouse); int KeyboardInput(std::vectorkeys, std::vector buffer); AValue PropertyGet(std::string theProp); std::vector PropertyGetVector(std::string theProp); void PropertySet(std::string theProp, std::string theFormat, ...); void PropertySet(std::string theProp, AValue &theValue); void Commands(Command &aCommand); AValue CommandR(Command &aCommand); void LoseFocus();};#endifNotice some of the functions are the same as GUIObject, just without the virtual part. These functions can be called even when stored in a GUIObject pointer, and will call the overridden function versus the GUIObject original function.

ComponentGUI has a vector 'std::vector guiObject' that stores a pointer to all the GUIObject created.
It has a function to Add a GUIObject:

int ComponentGui::AddControl(char *theName, char *theType, GUIObject *theObject){ int count = AddControlVar(); guiObject[count] = theObject; guiObject[count]->type = theType; guiObject[count]->name = theName; controlOrder.push_back(ControlOrder(count, theName)); theObject = NULL; return count;}Now I want to add a button so I could call this function like this:
componentGui.AddControl("Button1", "Button", new Button());Even though the parameter asked for two char* and a GUIObject pointer, I gave it two char* and a pointer to a Button. Since Button inherited GUIObject, the Button pointer can be used in place of a GUIObject pointer. This can work vice versa, but you have the type cast the GUIObject back to Button.
Button* button = (Button*)guiObject[0];Now since guiObject[0] now contains a GUIObject, I can call one of its functions.
componentGui.guiObject[0]->Standard();componentGui.guiObject[0]->Draw(0, 0, textures, aFont, textured, &openglContext);This code calls Standard(), basically sets all the parameters of the object to starting/standard.
Then the next code draws it.
Now since button has overridden Standard and Draw, the buttons version of the functions will be called.

I do want to point out, you cannot call any function or use any parameter from Button that is not contained in GUIObject while it is thought of as a GUIobject.
'Button *button = new Button()' could call any of the functions from GUIObject or Button.
'GUIObject *guiObject = new Button()' could only call the functions from GUIObject. Now any overridden functions would be called instead, but they must have same name and parameters.




Component Manager and GUI

So my custom GUI uses an inherited 'GUIObject.hpp'. They are then kept in a std::Vector of pointers. I have a ComponentManager that handles different screens/frames (however you want to look at it), the ComponentGui (cGui), and Component2d (c2d). Both cGui and c2d are 2d components, but the latter is going to handle the 2d objects and animations.
This time around, I am making sure every object has a constructor, a copy constructor, and an =operator override. Now obviously when translating from c++ to java for android, there will be changes. But a lot of use of the GUI is for the model/scene creation, and not the game itself.
The GUI before used to use mouse coordinates, a combination of left, middle, and right buttons as function parameters that is sent to the first GUI that the mouse coordinates were inside. The order of checking was determined by controlOrder, a vector variable that held a string and integer. It kept the position of guiObject[], and the type of object it was. I used a variable to order my controls and screens versus reordering the original vector because that seemed like the more efficient code. Changing the order of a complex variable would theoretically take more time than to change a variable that held an integer and string.
This time around, I am still using controlOrder to keep track of the drawing order. But, I am making sure that each guiObject[] has a Draw and a DrawPick function. The pick function takes one of its parameters as a pick color value. That value is then drawn in place of its normal color/texture value. I then use the glReadPixels to read a pixel value off the screen at the mouse coordinates.

R = Type. Is this a GUI_TYPE, a C2D_TYPE, SCREEN_TYPE (0 left as nothing for R)
G = Index1. Which GUI, C2D, SCREEN
B = Sub-Index. Which GUI Component, C2D Component, SCREEN part (control box, frame);

So far, this will limit me to 255 types, 256 indices, and 256 sub-indices. I am pretty sure I won't cry over limiting myself to 256 2d Objects on screen.

I have read so many articles, I couldn't tell you where I read how to do some of these things.





I have started and abandons/restarted so many games/engines. Every since third grade, multitude of languages (QBasic, Visual Basic, C++, Java). I think in 20 years, I have completed 3 games (Tic Tac Toe, Dodger (a simple space craft moving right faster, astroids), and a simple 2d fighter). For the last 9 years I have restarted the same 3d engine with custom 2d GUI in opengl. Dont get me wrong, every time I restarted, I got farther and caught back up to my previous point with better code. It is really sad to realize how much time has gone by without finishing anything though.

So I am going to create a 2d game, but use skeletal animations. I want it a version on Android and PC.

So good luck to me.



Sign in to follow this  
  • 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!