Jump to content

  • Log In with Google      Sign In   
  • Create Account

We're offering banner ads on our site from just $5!

1. Details HERE. 2. GDNet+ Subscriptions HERE. 3. Ad upload HERE.


Vincent_M

Member Since 16 Jan 2007
Offline Last Active Dec 15 2014 12:31 PM

#5194213 Textured Quads Appear White

Posted by Vincent_M on 22 November 2014 - 08:33 PM

I solved it. Turns out, the code above was fine, and the issue was within my vertex buffer:

glGenBuffers(2, vbo);
	glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo[1]);
	glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex) * numVertices, vertices, GL_STATIC_DRAW);
	glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(uint16_t) * numIndices, indices, GL_STATIC_DRAW);
	glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)0);
	glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)sizeof(Vector2));
	glEnableVertexAttribArray(0);
	glEnableVertexAttribArray(1);
	delete vertices;
	delete indices;

My second vertex attribute was set to 4 for the size, GL_UNSIGNED_BYTE for the type and GL_TRUE for the normalized arguments. This was a simple copy and paste mistake as the vertex format from another test state uses position and color. This one uses position and texture coordinates. False alarm!




#5191550 Resource management

Posted by Vincent_M on 06 November 2014 - 12:22 PM

I've thought against having a resource manager due to problems that could occur myself, but then my controller class ends up having a bunch of pointers to allocated resources for things like textures, models, scenes, etc. Then, having to explicitly release all of that data in my State's LoadContent() and UnloadContent() override methods gets kind of large for switching states and scenes. Then, I found myself writing the same resource loading code for most things, and that a subclass could handle a lot of the base functionality.

 

Since I'm using C++, I thought that OOP principles could help cut down on the redundant code. I think maybe my AssetManager system is taking on too much, honestly. I plan on having a File I/O namespace that'll include I/O classes for reading and writing data in binary blobs with speed and integrity checks as well as handling text/schema-based syntax formats such as XML and JSON for intermediate file data.

 

I really would like to learn more about software engineering, and systems development. I have quite a bit of experience doing things on my own. When it comes to developing a software system, such as an engine, or even a complete game, everything I'm currently capable of is a result of almost purely figuring things out on my own and experimentation. Are there any good software design books that cover OOP or important software engineering concepts in general, such as SRP? I've been reading papers online, but I'd like to find a course book that walks me through design patterns.




#5191384 Resource management

Posted by Vincent_M on 05 November 2014 - 01:12 PM

I've seen many arguments against a resource manager on these forums in the past in favor for writing a separate factory system per type of asset, but I think have a unified foundation with a factory system built on top for the specific needs of the asset is a better way to work on it. Here's the source to the beginning of my asset system:

#include <iostream>
#include <vector>
#include <map>


using namespace std;


class Asset
{
	template<class T> friend class AssetRef;
	
protected:
	bool persistent;
	vector<void**> references;
	
	virtual void Load() {}
	
public:
	Asset()
	{
		persistent = false;
	}
	
	~Asset()
	{
		for(int i=0;i<(int)references.size();++i)
			*references[i] = NULL;
		references.clear();
	}
	
	void MakePersistent(bool persistent) { this->persistent = persistent; }
	
	bool IsPersistent() { return persistent; }
	int GetReferenceCount() { return (int)references.size(); }
};


enum class AssetError
{
	Null=0,
	Exists,
	NotFound,
	DuplicateName,
	DuplicateAsset
};


template<class T>
class AssetRef
{
private:
	T *ref;
	
	void RemoveRef()
	{
		if(ref)
		{
			for(vector<void**>::iterator iter = ref->references.begin();iter != ref->references.end();++iter)
			{
				if(**iter == ref)
				{
					Asset *ptr = ref;
					ptr->references.erase(iter);
					break;
				}
			}
			ref = NULL;
		}
	}
	
public:
	AssetRef()
	{
		ref = NULL;
	}
	
	~AssetRef()
	{
		RemoveRef();
	}
	
	void operator=(T *opt2)
	{
		// reduce old reference's count, and set the new one if not NULL
		RemoveRef();
		if(opt2)
		{
			ref = opt2;
			ref->references.push_back((void**)&ref);
		}
	}
	
	T *Get() { return ref; }
};


class AssetManager
{
private:
	static map<string, Asset*> assets;
	
public:
	static bool Add(string name, Asset *asset)
	{
		// make sure the asset isn't NULL and the name is unique
		if(!asset || assets.find(name) != assets.end())
			return false;
		
		// make sure asset doesn't already exist
		map<string, Asset*>::iterator iter = assets.begin();
		while(iter != assets.end())
		{
			if(iter->second == asset)
			{
				cout << "asset already exists" << endl;
				return false;
			}
			++iter;
		}
		
		assets[name] = asset;
		return true;
	}
	
	static bool Remove(string name)
	{
		if(assets.find(name) == assets.end())
		{
			cout << "could not find asset: " << name << endl;
			return false;
		}
		
		//Base::Release(&assets[name]); // TODO: implement this
		assets.erase(name);
		return true;
	}
	
	template<class T>
	static void Purge()
	{
		map<string, Asset*> *purgeAssets = GetAssets<T*>();
		if(purgeAssets)
		{
			map<string, Asset*>::iterator iter = purgeAssets->begin();
			while(iter != purgeAssets->end())
			{
				Remove(iter->first);
				++iter;
			}
			delete purgeAssets;
		}
	}
	
	static void Flush()
	{
		// only flushes assets deemed non-persistent
	}
	
	static void Clear()
	{
		map<string, Asset*>::iterator iter = assets.begin();
		while(iter != assets.begin())
		{
			//Base::Release(&iter->second); // TODO: implement this
			iter->second = NULL;
			++iter;
		}
		assets.clear();
	}
	
	template<class T>
	static T *Get(string name)
	{
		// make sure an asset with that name exists
		if(assets.find(name) == assets.end())
		{
			cout << "could not find asset: " << name << endl;
			return NULL;
		}
		return dynamic_cast<T*>(assets[name]);
	}
	
	template<class T>
	static map<string, T*> GetAssets()
	{
		// allocate a new map and setup an iterator
		map<string, T*> *set = new map<string, T*>;
		map<string, Asset*>::iterator iter = assets.begin();
		
		// populate with the correct type of assets
		while(iter != assets.end())
		{
			T *ptr = dynamic_cast<T*>(iter->second);
			if(ptr)
				*set[iter->first] = iter->second;
			++iter;
		}
		
		// delete the allocate map if there are no assets of that type
		if(!set->size())
		{
			delete set;
			set = NULL;
		}
		return set;
	}
	
	template<class T>
	static int GetNumAssets()
	{
		int count = 0;
		map<string, Asset*>::iterator iter = assets.begin();
		while(iter != assets.end())
		{
			if(dynamic_cast<T*>(iter->second))
				++count;
			++iter;
		}
		return count;
	}
	
	static int GetNumAssets() { return (int)assets.size(); }
};


map<string, Asset*> AssetManager::assets;


class Texture2D : public Asset
{
};


class Font : public Asset
{
};


typedef AssetRef<Texture2D> Texture2DRef;
typedef AssetRef<Font> FontRef;


int main(int argc, const char **argv)
{
	bool result = false;
	Texture2D *texture1 = new Texture2D();
	Texture2D *texture2 = new Texture2D();
	
	result = AssetManager::Add("test_asset1", texture1);
	cout << "add result: " << (int)result << "  num assets: " << AssetManager::GetNumAssets() << endl;
	result = AssetManager::Add("test_asset2", texture2);
	cout << "add result: " << (int)result << "  num assets: " << AssetManager::GetNumAssets() << endl;
	result = AssetManager::Remove("test_asset1");
	cout << "remove result: " << (int)result << "  num assets: " << AssetManager::GetNumAssets() << endl;
	
	Font *ptr = AssetManager::Get<Font>("test_asset2");
	if(ptr)
		cout << "ptr is VALID" << endl;
	else
		cout << "ptr is NULL" << endl;
	
	Texture2DRef texRef;
	texRef = AssetManager::Get<Texture2D>("test_asset2");
	Texture2D *tex = AssetManager::Get<Texture2D>("test_asset2");
	if(tex)
		cout << "test_asset2 count: " << tex->GetReferenceCount() << endl;
	
	AssetManager::Flush();
	cout << "finished..." << "  num assets: " << AssetManager::GetNumAssets() << endl;
    return 0;
}

Using C++-11's new smart pointer system probably would have been a better way to go instead of supporting my own reference counting system, but I haven't figured them out yet. The ideas is that every different type of asset you'd have in your game (textures, models, definition files, etc.) would derive from Asset. Then, you'd create an AssetRef typedef variant for shorthand. An AssetRef is simply a pointer to the asset that's (hopefully) already loaded into the AssetManager.

 

Even though I don't assume all assets are loaded from files (for example, textures generated from rendering to a texture), I may add a filename field to Asset. I'm also thinking about adding an MD5 hash generated from the data stored in the asset, which the subclass is responsible for providing the data to hash. This is so if I wanted to create a visual editor like UE4 and Unity have, I can create an asset database that acts like a database in the sense that it keeps track of where everything is, or when files are moved in and out of the file project's root folder. Anyway, there's some funky scope to the editor side of things, and I haven't drawn up that namespace yet...

 

EDIT: The main() function at the bottom demonstrates how this currently works. I don't want any assets to be created without the AssetManager owning them though, but I also want it to be transparent to the end-programmer. I'm thinking about replacing AssetManager::Add() with a method like AssetManager::Load<T>(const char *filename, const char *filename) which can be specialized with its own loader code for every new Asset subclass that's created. I want AssetManager to own all assets allocated into memory, and do it transparently so its reference counting system works correctly. For generated assets, I'd like to override the new operator that'll allocate the asset, but automatically add the asset to the AssetManager like AssetManager::Add() does right now.

 

This is how I'd handle my game-ready content pipeline. AssetManager is intended to use models, textures, config files, etc that are serialized into some engine-ready binary blob setup, possibly combined into a file atlas (similar to how texture atlases), zip archive, or both. My engine will handle common image formats for things like textures and icons as well as a text-based, intermediate file format for models, but those are handled through the ContentProcessor pipeline, which is a separate namespace.




#5191060 Datatype Size and Struct Compiler Padding

Posted by Vincent_M on 03 November 2014 - 11:40 PM

When it comes to storing my data in a game-ready format that's quick to load, I like to store my data using C's stdio library, so fread() and fwrite().There are a few problems with that, however:

-Changing the data structure will inevitably cause a crash when loading an older version of the file. Versioning can help here, or serializing the data in XML/JSON could help if it still wasn't so slow for large volumes of data on embedded devices.

-Compiler padding

 

I've noticed that some of my data types are odd numbers of bytes might pad the structure at different points in the struct's data. I think I've ran into issues where having a bool stored in a struct could cause issues too, but I usually store those in bit-fields if I have a group of them anyway. Are there any good guidelines I should follow when storing my data as binary blob files? I tend to write binary blob files for certain resources I serialize on my desktop computer in Visual Studio (Windows), or from Xcode (Mac), then load those files on any desktop OS or even mobile OS's like iOS and Android.

 

Also, is int the only datatype that changes its size based on processor? For example, int is usually 32-bit on 32-bit machines, and 64-bit on 64-bit machines. I tend to stay away from storing my integers as ints for this reason, and store my data as a long datatype as I'm pretty sure that it's always 32-bit whereas int is hardware-dependent. Is this correct so far?

 

If so, do any of C++'s other basic datatypes change their size? Also, is it wise to keep track of whether the CPU is little-endian or big-endian when writing files? I never really wrapped my head around that...




#5189557 General Programmer Salary

Posted by Vincent_M on 27 October 2014 - 06:43 PM

What's the average video game programmer's salary in the USA? Wikipedia (reliable source, right?!) says that some 2010 survey make anywhere between $72,000 (< 3 years experience) - $124,000 (6+ experience) at an average of $93,500. These numbers sound extremely high for me.




#5177683 COLLADA vs FBX... Are They Worthwhile for Generic Model Formats?

Posted by Vincent_M on 02 September 2014 - 10:57 AM

I'm excited to try it out. In the meantime, I setup the FBX SDK, and began exporting models from Blender (FBX 7.4). Surprisingly, the SDK with its constant API changes, still work. Btw, if I were to write a community-driven, open source, engine utilizing the FBX SDK, would I be able to distribute my engine? I understand that I wouldn't be able to distribute Autodesk's own SDK along with it, but if I were to distribute the built binaries on my end, would I have any issues there?

 

Btw Eric, I checked out your C4 Engine back in 2011, and it's impressive! It inspires me to become better at what I do.




#5177233 COLLADA vs FBX... Are They Worthwhile for Generic Model Formats?

Posted by Vincent_M on 31 August 2014 - 11:27 AM

I have seriously almost gone the COLLADA here and there since late 2012, but then I kept remembering how "well" I did with my .x parser, and how incompetent I was in grabbing data properly. That said, it's XML-based, and that's pretty easy to parse with an XML-parsing library, such tinyXML in C++. C# does have some good XML and JSON parsing abilities. I just wish we used XML more with our Unity projects at work lol. I've been hoping for some sort of person or group to push a new, tighter-spec'd format to replace COLLADA, and it looks like OpenGEX may be on the right track for that.

 

EDIT: Eric Lengyel, on 30 Aug 2014 - 9:34 PM, said:

snapback.png

These are just some of the reasons we created the Open Game Engine Exchange format (OpenGEX):

 

http://opengex.org/

When do you think you'll have an exporter ready for Blender? That's currently what I use since it's free, stable, highly-functional, and there are communities of artists out there with Blender models you can download for free. It'd be pretty easy to get a few models of Sintel with various animations to try different tests.




#5154494 2D Scrolling in openGL ES 2.0 outside of ViewController

Posted by Vincent_M on 18 May 2014 - 03:11 PM

After looking through your code, there are a few basic things related to OpenGL and 3D math that you should learn. They can be really helpful in the future :)

 

If you look through your project's files, you'll notice two files: Shader.vsh and Shader.fsh. If you view them, they're just text files containing C-like code. The thing is, it is not C. The code that's written in there is called GLSL, or the GL Shader Language. The .vsh file is your vertex shader's source, and the .fsh file is your fragment shader's source. Your "loadShaders" method in your code above opens those two files, reads their contents into your program as if it's a giant text string, and uses OpenGL to send it to the GPU for compilation. Once both shaders have been compiled, they are attached to a "program" object, which is a mini-program run by the GPU. Whenever you want to render something with glDrawArrays or glDrawElements, you must first use that program using glUseProgram, and pass in the program ID you got back upon successful compilation and linkage (assuming your vertex and fragment shaders had no compiler errors). Then, the vertex shader runs once per vertex you pass in to transform your vertices from local (aka, "object space") to eye-space. Those vertices are eventually linked up into triangles, and rasterized to the screen in the rendering pipeline for that frame, and the fragment shader of that program runs once for each pixel of the frame buffer that the triangles take up on the screen.

 

Anyway, now that your have a basic understanding of that, how do we transform the vertices' positions from object space to pixel coordinates onto the viewport on your device's screen? You'll need a few matrices to do this: projection matrix, view matrix and a model matrix. Older versions of OpenGL used to handle all of this for you back in the day, but now that we live in the world of shaders where developers have so much control over how to process their graphical data, these methods have been stripped away. OpenGL ES 2.0 doesn't provide you with matrix modes, etc.

 

First off, you'll need a projection matrix. If you were rendering in 3D, then you'd be using a perspective projection matrix so that objects that are further away from the screen appear smaller, just like as perceive far-away objects in real-life. Since we are using 2D, however, we're going to use another matrix called an orthographic matrix. This allows your objects to as far away from the camera you want (provided it's not outside of your viewing bounds), and it'll appear as the same size as your close-up objects. You'll uses setup your projection matrix once, then rarely have to change it.

 

Next off, you'll need a view matrix which is just an inverse of a model matrix. More on how to inverse a matrix is here. Due to this, I'll cover the model matrix first: it's a matrix describing how to translate (or move), rotate and/or scale your objects. The model matrix is actually a combination of matrices: translation matrix, scale matrix, and various rotation matrices. There's 3 Euler rotation matrices for each axis: X, Y and Z. If you ever get into full-3D-like games, you'll want to learn about quaternions, and how to convert that into a rotation matrix.

 

So, let's say you wanted to move your camera around your scene, in this case, left or right. You'd keep track of the current position, and even the rotation of your camera if you'd like. Since you're not using some sort of transformation hierarchy, you could make a view matrix simply by creating a translation matrix using the negative x, y and z components for your camera's position in the world. Additionally, if you wanted to rotate your camera in your 2D game, you could use make a z-rotation matrix from your camera's negative z-rotation angle. Then, you'd multiply the two matrices together like so: translation * rotation to get your final view matrix.

 

Now, why are we plugging in negative values? Well, it's because your view matrix is a model matrix, except the scale. We developers like to think of the camera as some separate object you can move through the 3D world to capture certain parts of its at different spots, different angles, etc, but that's actually not how it works. If we want to draw an object in our world, we just pass its vertex data to the GPU, and transform the vertices in the vertex shader. Makes sense, right? Well, if we want to view our world at a specific position and orientation in the world, we'd have to offset everything we see by that camera. That's where the view matrix comes in. How do we apply the view matrix? Simple: matrix multiplication. Multiply the view matrix by the model matrix, and you're all set. We are missing one piece of that puzzle, however. We need to take perspective into account, so we need to apply our camera's projection matrix into everything we render with that camera as well. You'd typically want to create a camera class that holds a perspective matrix (in your case, it's an orthogonal projection matrix), and a view matrix. Again, you'd only setup the perspective once, and rarely, if ever, change it. The view matrix, on the other hand, will need to be re-computed whenever your camera's position or rotation changes.

 

The way you multiply these matrices together are also very important. Multiplying the projection * view * model matrices together is different than multiplying model * view * projection together, unless you transpose the matrices first as shown here. I've suggested a book on OpenGL ES 2.0 below that can give you some really good information on this.

 

So, we've briefly gone over the concepts on how transformations work in vertex shader above, how do we apply these concepts in code? Well, Apple's GLKit provides you with a matrix class, among other things, to make writing OpenGL apps easier. I'd recommend against it, unless you like Objective-C, and don't plan on working on other platforms, such as Linux, UNIX, Mac, Windows, Android, etc, other mobile devices. There are some good math libraries out there, such as the GLM (GL Math) library. I've got my own math library that'll set you up pretty well, but it's integrated into my engine right now, and it's broken. I'm also not near my computer, so I will have to post when everything works again.

 

Until then, let's assume you have your projection and view matrices setup for your camera, and a model matrix setup for each of your objects. Before you call glDrawArrays(), or glDrawElements() to draw your object, make sure you're using the shader you want by calling glUseProgram() passing in the program handle you want. Then, we want to send those matrices to your shaders. To do this, let's look at a snippet from your own code :)

// Get uniform locations. TODO what is this?
uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX] = glGetUniformLocation(_program, "modelViewProjectionMatrix");
uniforms[UNIFORM_NORMAL_MATRIX] = glGetUniformLocation(_program, "normalMatrix");

When you loaded the shader in your loadShaders method, your code grabs handles to your shader's uniforms. A uniform is an input variable to can inject into your shader before you draw something with it, and your shader will use that variable in its calculations. You could think of it as a parameter in a function. You can have uniforms in both your vertex and fragment shaders, and it looks like the shaders you use has two of them: one called modelViewProjectionMatrix and another called normalMatrix. If you look in your Shader.vsh file, you'll probably see two lines of code with declaring a mat4 for modelViewProjectionMatrix and normalMatrix. The name is also model-view-projection, suggesting that this is the order it's multiplied by. This means Apple stores its matrix data in a row-major fashion (common), but the old way OpenGL did it was column-major.

 

Judging from your uniform names, I'm guessing you're building from Apple's 3D cube demo that also does lighting calculations, if I remember correctly. You won't need 3D lighting for what you're doing. To be honest, this shader does some advanced things you don't really need, and it's much more processing-heavy than you'll need.

 

I read the book, "OpenGL ES 2.0 Programming Guide" back in early 2010 to get up to speed with how OES 2.0 differs from OES 1.1, and how shaders work. This book is great because it covers things like matrices, shaders, how to pass data (attributes and uniforms) from your Objective-C code to your shaders, etc. Here's a link to it:

http://www.barnesandnoble.com/w/open-gl-es-20-programming-guide-aaftab-munshi/1100835208?cm_mmc=googlepla-_-textbook_instock_26to75_pt104-_-q000000633-_-9780321502797&ean=9780321502797&isbn=9780321502797&r=1

 

Also, one huge performance issue I see you doing are making many unnecessary gl* calls. Any time you're calling a function beginning with "gl" in the name, it's related to OpenGL, and almost all of them can be very costly as they're usually used to talk back and forth with your device's GPU. All of your app's code is written for the CPU, except shaders. So, whenever you tell your code to talk to the GPU with one of those "gl" calls, you're halting the thread doing those GPU calls until it finishes talking to the other hardware. These devices are really fast nowadays, but you don't want to be calling "glDrawArrays" once per rectangle --push all rectangles into a giant vertex buffer, and call it once ;) We can go into detail about that in another time, though.

 

 

If I have time this week, I'd like to cook up a simple demo for you that does what I've discussed above.




#5149201 Library For Downloading Files

Posted by Vincent_M on 24 April 2014 - 01:14 PM

I agree with the trivial part, but I've had issues in the past where I wasn't saving the data out correctly. I mean, it's a matter of grabbing the file in segmented buffers of raw bytes, and passing it through fwrite() until there are no segments left (last segment will probably be less bytes). I'll try it out again. After posting, I found that libcurl's website even has an FTP upload demo, so it's almost copy and paste. *facepalm*




#5134024 C++ IDEs for Linux

Posted by Vincent_M on 24 February 2014 - 01:18 AM

I'm developing a set of arcade games to put into an arcade machine I'm designing. I'm using Eclipse to develop everything, and it's got quite a few projects in the workspace: Engine, Launcher, Game1, Game2, Game3, etc. My Engine and all of the game projects are built as shared objects, and all projects use Engine as a dependency project as it handles all of the OpenGL/AL stuff under the hood. The problem is, I keep running into headaches with Eclipse on my Debian development computer:
-Vague/obscure errors (I keep getting "Error 1" with no further information whenever something happens in the Engine library)
-Some classes in the Engine project are unrecognized, even when they're in the same header/source files as recognized classes when calling them from projects outside of the Engine project
-Engine appears to rebuild itself every single time I make a change in any project, but the changes aren't always reflected, so I have to manually Clean/Refresh/Build each project

I think it's better to try a different IDE at this point. I went through a tricky episode trying to get Eclipse to play nice with the NDK so I could get a simple Hello World app to compile using my engine as a shared library for the OUYA. Does anyone have any recommendations?


#5089427 How Useful is SVG?

Posted by Vincent_M on 27 August 2013 - 01:54 AM

By the looks of it, SVG seems like the 2D doppleganger of COLLADA:

-They both have XML-based DOMs

-They're both quite complex interim formats

-Both seem to be open formats aimed for wider support application support than other formats of their kind

 

How suitable is SVG for animation? I've read that it's mainly for static images, but then I've also seen information that could be for animation manipulation for SVG 1.1, but I'm not quite sure. I'm on a vendetta for finding an open, vector-based solution for generating computer graphics for 2D games since rasterized graphics, although have their advantages over vector graphics, are just too memory-instense for my purposes.




#5089424 Maximum Landsize in a console game

Posted by Vincent_M on 27 August 2013 - 01:48 AM

There are some tech demos out there, and a game on Steam, that render entire planets to-scale using procedural generated terrain, a quad tree hierarchy and other elements for the environment. The beautiful part is that generic artwork is required because everything is generated and processed with algorithms and shaders. LOD is used with the hierarchy of a bunch of heightmaps generated, usually on-the-fly with random control variables, but then those maps can be saved to a disk if you like a particular configuration. The problem is, I've read that you're looking at ~8GBs of heightmaps lol.

 

Check out Infinity and the XNA Planet Rendering videos on YouTube. That Steam game is called StarForge, and it's quite impressive. It's got voxel-processing, but it's based on realism and more organic, contrary to Minecraft. It's an FPS with neat ragdoll physics and cool RPG elements built into it as well. I haven't bought it yet (all my time goes to makin' games!), but it looks like the entire planet IS your sandbox.




#5086831 Generic Datatypes --Are Templates the Way to Go?

Posted by Vincent_M on 17 August 2013 - 01:38 PM

I developed my own linked list for C++ that has a few features in it that I like over STL lists. The idea is that I have this abstract LinkedItem class, which holds pointers to the previous and next element in the linked list. Then, I have the LinkedList class that manages this class. LinkedList is able to add and remove elements, and more importantly, get an element from a specific index. LinkedItem also contains a virtual method, GetType(), that returns a literal string, and LinkedList contains a "key" field, which is also a string. When LinkedItem is subclassed, GetType() should be overridden to return some other unique string, such as "item_definition", "character_definition", "map_character", etc. and LinkedList instances with the matching key will allow only LinkedItem subclasses with the matching type to be added to the list. That way, it's guaranteed. I think templates might be an even smarter way to go, but I'm not sure how to use them yet...

 

Here is another example:

LinkedItem and LinkedList also also subclassed by DictionaryItem and Dictionary, respectively. DictionaryItem provides an additional "name" field, and when Dictionary attempts to add a DictionaryItem to the list, it'll check the name field against items currently in the list to make sure it's unique (checking duplicates can be turned off, though).

 

Then, I have the last subclassed pair: UniqueItem and UniqueList. When an item is successfully placed into the list, a unique number, called "primaryKey", is generated, and stored in that item.

 

I have all three classes working, but a lot of casting is required to make it work... I plan on using these three classes, mainly Dictionary, as an abstract class where I can override my ValidateAdd method to implement further code for the situation. But then, if I was to use GetItem() to retrieve anything, it'd return abstract datatypes depending on the base class that implemented them.

 

For example:

LinkedItem *GetItem(int index); // implemented by LinkedList
DictionaryItme *GetItem(string name); // implemented by Dictionary

If I were to make a Dictionary subclass called CharacterController, that managed a list subclassed DictionaryItem's called Character, then GetItem(int) and GetItem(string) would return LinkedItem and DictionaryItem pointers of the actual Character instance actually there. I could write wrapper methods, but that seems messy.

 

Would templates work for this situation?

 




#5064540 Keeping Track of a Dictionary

Posted by Vincent_M on 24 May 2013 - 11:06 AM

I've always been a fan of games like Scrabble, Words with Friends, and Bookworm. One thing they all seem to have in common that fascinates are their real-time spelling algorithms. One thing I'd like to know though: where did the dictionary of valid words come from? Was it an extern file that was shipped with the game, hardcoded, a feature built into the OS, etc?

 

Also, how did they manage to make the search algorithm so fast? You'd think having a giant dictionary of tens of thousands (possibly more in Words with Friends), they wouldn't be searching through 1 giant library-like list.

 

I'd assume it's just a large file that's alphabetized, but with smaller reference lists, similar to MySQL queries. There'd probably possibly in 26 separate lists (one for each letter) organizing all of the 'a' characters in one, 'b' in another, and so on... Then, maybe have 26 lists for each of the original 26 lists for the second one in the list to organize each list up alphabetically from the second word.

 

Here's a thread started over at StackOverflow on spell checking:

http://stackoverflow.com/questions/2294915/what-algorithm-gives-suggestions-in-a-spell-checker




#5063012 Dependencies

Posted by Vincent_M on 19 May 2013 - 09:43 AM

Supporting multiple libraries




PARTNERS