Category Archives: Prototype

Current Projects

I have been really busy with work recently but I’m making some time to discuss my current hobby projects. One of these project is more of a solo gig and the other, I’m hoping, will start with me doing most of the work at first but eventually I’d like other developers to join in and help.

This first project is similar in style to Arthur’s Grove (AG). AG was a little game I released not too long ago but this time I’m stepping up my game a little more now that I’m more comfortable with a lot of the game mechanics I used when developing AG. The worlds are completely different and the stories have nothing to do with each other (not that AG had much of a story anyways) but the game itself will be similar in style because I find myself gravitating towards this style of game a lot.

The tech is also a bit different. Here I’m relying more on the Tiled Map Editor to set collision boundaries and add entity objects into the level. The Tiled Map Editor exports to JSON which I then parse using Duktape. I have been using Duktape for a while and anytime I need to do a bit of scripting on parse Javascript/JSON it is my go-to library!

The second project has recently grown in importance to me since, apparently, Snoxd has been down for whatever reason (most likely due to the lack of contributing community members). As much as I would like to see Snoxd succeed, my feeling is that the private KO server community needs strong developers and not a bunch of “binary hackers.” A community that doesn’t share will never grow and a community that doesn’t support and praise good contributions will never provide the positive reinforcement necessary to keep people contributing. Sometime in the future I’ll write up a more complete article on my feeling towards the KO development community and a direction for where I would like to see the community head towards in the future. But nevertheless, I have been working on a completely new implementation of the KO AIServer architecture using SDL2 and MySQL server. Currently I’m able to spawn in a group of NPCs with this custom code and have the AIServer communicate with the stock 1298 Game server which allows the player to login and see the NPCs. Most of the work here comes from re-implementing the multi-threaded nature of the AIserver using SDL2, along with all the network calls using SDL2 Net. This code is completely cross-platform and will compile on Windows/Mac/Linux.

One very important reason for using MySQL server instead of Microsoft’s SQL server (which the official USKO, as well as all private servers, use) is because if you were to compile the KO servers on Linux you would will need access to a Microsoft SQL server on another remote windows machine. Therefore, no matter what, a machine running Windows is necessary. However, if the database is a MySQL database this isn’t an issue as MySQL can be installed on any prominent operating system. Hell, even a custom coded server running Sqlite would provide more versatility than SQL server (but I digress).

So that’s the sort of stuff I’ve been working with recently. If you have any questions, or would like to help contribute to the OpenKO project, let me know. The long-term idea is to replace each of the KO game servers for the stock 1298 release one at a time. Once this is complete and the binaries are virtually interchangeable with the originally released 1298 private server binaries we will start writing a custom 1298 client using SDL2 and OpenGL. This is the tentative plan, and likely won’t recent full attention until I have finished my PhD and have find a job. But the progress made so far is still quite an accomplishment relative to the stagnation which unfortunately permeates the KO development scene. This will eventually change though because I know there are passionate developer out there and I would love to help be apart of that change.

New Project – “June”

So for whatever reason I recently went on a Youtube binge watching a ton of videos on game design and artistic design. Based on the videos I saw I feel motivated to mix things up a little and try something more creative. There are a ton of point and click adventure games out there but what I have planned is a bit more personal. I am prototyping the idea of turning my own day-to-day experiences into a point and click.

For this game I am also adding music which a lot of my previous projects have been missing, and all the images for the game were taken with my android phone. Music plays a much bigger role in this game because there aren’t really any “game mechanics”. The game mechanic is the experience and how well it draws the play in. Everything I have now has been thrown together quickly just to get a feel for the gameplay, and I’d have to say I like what the prototype has had to offer so far. The images are a bit blurry but linking image to image through an option list of activities is a lot of fun and has opened more of my creative side than any other project so far.

So I will keep with this for a while and see where it takes me!

Obj Mesh Importer

Today I am sharing a bit of code I use to read very basic vertex and texture coordinate information from an obj file. The .obj format is explained in detail here. It is pretty well supported across most 3D-modeling software and is currently my go-to format for 3D mesh information.

In order to keep the vertex information file format agnostic (in case you decide to add other file formats later), I designed an intermediate layer of abstraction between the .obj file and OpenGL.

typedef struct {
	GLfloat* pos;   // (x,y,z)
	GLfloat* tex;   // (u,v)
	GLfloat* norm;  // (x,y,z)
	GLsizeiptr num; // total num of verts
} VertInfo;

typedef struct {
	GLuint* pos;    // 3 pos inds per
	GLuint* tex;    // 3 tex inds per
	GLuint* norm;   // 3 norm inds per
	GLsizeiptr num; // num of triangles
} IndInfo;

This works well for my current needs but there are a few simplifications I have made about the obj. An obj file may contain an optional coordinate (x, y, z [,w]) but I am ignoring that it might exist. Another simplification is that the texture coordinates have two variables, not three. These are reasonable assumptions to make since they basically ignore optional arguments that I won’t use anyways. The bigger assumption is that all the face definitions are triangles. This isn’t the case, even with the files I’ll be using, but OpenGL is really fast with triangles to I’m converting the quadrilaterals to triangles. This current iteration only accepts quadrilaterals but triangle faces would be trivial to add.

Here is the actually importer.

void loadObjFile(VertInfo** verts, IndInfo** inds, const char* filename) {
	if(*verts) {
		free((*verts)->pos);
		(*verts)->pos = NULL;
		free((*verts)->tex);
		(*verts)->tex = NULL;
		free((*verts)->norm);
		(*verts)->norm = NULL;

		(*verts)->num = 0;
	} else *verts = (VertInfo*) calloc(0x01, sizeof(VertInfo));

	if(*inds) {
		free((*inds)->pos);
		(*inds)->pos = NULL;
		free((*inds)->tex);
		(*inds)->tex = NULL;
		free((*inds)->norm);
		(*inds)->norm = NULL;
		
		(*inds)->num = 0;
	} else *inds = (IndInfo*) calloc(0x01, sizeof(IndInfo));

	size_t n = 0;
	char** lines = NULL;

	if(filename==NULL) return;
	FILE* fp = fopen(filename, "r");

	do {
		char c;
		int colInd = 0;

		lines = (char**) realloc(lines, ++n*sizeof(char*));
		lines[n-1] = NULL;

		do {
			fread(&c, sizeof(char), 1, fp);

			// NOTE: strip newlines
			if(c!='n') {
				if(colInd>0) {
					// NOTE: strip extra spaces
					if(!(lines[n-1][colInd-1]==' ' && c==' ')) {
						lines[n-1] = (char*) realloc(lines[n-1], ++colInd*sizeof(char));
						lines[n-1][colInd-1] = c;
					}
				} else {
					lines[n-1] = (char*) realloc(lines[n-1], ++colInd*sizeof(char));
					lines[n-1][colInd-1] = c;
				}
			}
		} while(c!='n');

		// NOTE: end with a null terminator
		lines[n-1] = (char*) realloc(lines[n-1], ++colInd*sizeof(char));
		lines[n-1][colInd-1] = '';

		if(lines[n-1][0]=='#') {
			// NOTE: ignore comments

			free(lines[n-1]);
			lines[n-1] = NULL;

			lines = (char**) realloc(lines, --n*sizeof(char*));
		} else if(lines[n-1][0]=='') {
			// NOTE: ignore blank lines

			free(lines[n-1]);
			lines[n-1] = NULL;

			lines = (char**) realloc(lines, --n*sizeof(char*));
		}
	} while(!feof(fp));

	fclose(fp);
	fp = NULL;

	size_t numPos = 0;
	size_t numTex = 0;

	int i;
	for(i=0; i<n; i++) {
		// NOTE: parse the file

		printf("%sn", lines[i]);

		if(lines[i][0]=='v' && lines[i][1]==' ') {
			// NOTE: parse the vertex and add it to the array

			(*verts)->num++;

			numPos += 3;
			(*verts)->pos = (GLfloat*) realloc((*verts)->pos, numPos*sizeof(GLfloat));

			GLfloat x = 0, y = 0, z = 0;
			sscanf(lines[i], "v %f %f %f", &x, &y, &z);
			printf("[%f, %f, %f]n", x, y, z);

			(*verts)->pos[numPos-3] = x;
			(*verts)->pos[numPos-2] = y;
			(*verts)->pos[numPos-1] = z;

		} else if(lines[i][0]=='v' && lines[i][1]=='t' && lines[i][2]==' ') {
			// NOTE: parse the texture coordinates

			numTex += 2;
			(*verts)->tex = (GLfloat*) realloc((*verts)->tex, numTex*sizeof(GLfloat));

			GLfloat u = 0, v = 0;
			sscanf(lines[i], "vt %f %f", &u, &v);
			printf("[%f, %f]n", u, v);

			(*verts)->tex[numTex-2] = u;
			(*verts)->tex[numTex-1] = v;
			
		} else if(lines[i][0] == 'f' && lines[i][1] == ' ') {
			// NOTE: parse the face elements

			int c, num = 0;
			GLuint* indices = NULL;

			for(c=1; c<strlen(lines[i]); c++) {

				// TODO: will have to handle the case when normals are left out
				// or when texture indices are left out

				// TODO: currently I am assuming 4 indices per face which makes
				// two triangles (i.e. 6 elements)

				if(lines[i][c]==' ') {
					num += 3;
					indices = (GLuint*) realloc(indices, num*sizeof(GLuint));

					GLuint vi = 0, vti = 0, vni = 0;
					sscanf(&lines[i][c], " %d/%d/%d", &vi, &vti, &vni);
					printf("[%d, %d, %d]n", vi, vti, vni);

					indices[num-3] = vi;
					indices[num-2] = vti;
					indices[num-1] = vni;
				}
			}

			if(num==4*3) {

				// TODO: currently only setting the position index but I need
				// to set them all eventually

				(*inds)->num += 6;

				(*inds)->pos = (GLuint*) realloc((*inds)->pos, (*inds)->num*sizeof(GLuint));
				(*inds)->tex = (GLuint*) realloc((*inds)->tex, (*inds)->num*sizeof(GLuint));
				(*inds)->norm = (GLuint*) realloc((*inds)->norm, (*inds)->num*sizeof(GLuint));

				int pos0 = indices[0];
				int pos1 = indices[3];
				int pos2 = indices[6];
				int pos3 = indices[9];

				(*inds)->pos[(*inds)->num-6] = pos0-1;
				(*inds)->pos[(*inds)->num-5] = pos1-1;
				(*inds)->pos[(*inds)->num-4] = pos2-1;
				(*inds)->pos[(*inds)->num-3] = pos2-1;
				(*inds)->pos[(*inds)->num-2] = pos3-1;
				(*inds)->pos[(*inds)->num-1] = pos0-1;
			}

			free(indices);
			indices = NULL;
		}

		printf("n");
	}

	for(i=0; i<n; i++) {
		free(lines[i]);
		lines[i] = NULL;
	}

	free(lines);
	lines = NULL;
}

I added printf() outputs for debugging purposes. This function will build the structs and set the pointers so that we can then work on this abstraction layer to build the information OpenGL needs to render the object.

To create the structs just place the following calls.

IndInfo* inds = NULL;
VertInfo* verts = NULL;

loadObjFile(&verts, &inds, "test.obj");

The neat thing about this current setup is that the index information can be passed directly to OpenGL as an element buffer.

// NOTE: allocate a GPU buffer for the element data
GLuint eleBuffer;
glGenBuffers(1, &eleBuffer);

// NOTE: bind to the element buffer so that we may send our data to the GPU
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, eleBuffer);

// NOTE: send our element data to the GPU and set as STAIC
glBufferData(GL_ELEMENT_ARRAY_BUFFER, inds->num*sizeof(GLuint), inds->pos, GL_STATIC_DRAW);

On the other hand, the OpenGL vertex information is highly specific to the type of effects you plan to render with your objects. Here I’m just using the position and texture information but if you plan to add lighting or some other type of rendering effect you’ll have to customize the OpenGL vertex information to fit your needs.

GLfloat glVerts[5*verts->num];
memset(glVerts, 0x00, 5*verts->num*sizeof(GLfloat));

int tempInd = 0;
for(; tempInd<verts->num; tempInd++) {
	glVerts[5*tempInd+0] = verts->pos[3*tempInd+0];
	glVerts[5*tempInd+1] = verts->pos[3*tempInd+1];
	glVerts[5*tempInd+2] = verts->pos[3*tempInd+2];

	glVerts[5*tempInd+3] = verts->tex[2*tempInd+0];
	glVerts[5*tempInd+4] = verts->tex[2*tempInd+1];
}

// NOTE: allocate an array buffer on the GPU
GLuint verBuffer;
glGenBuffers(1, &verBuffer);

// NOTE: bind to the array buffer so that we may send our data to the GPU
glBindBuffer(GL_ARRAY_BUFFER, verBuffer);

// NOTE: send our vertex data to the GPU and set as STAIC
glBufferData(GL_ARRAY_BUFFER, 5*verts->num*sizeof(GLfloat), glVerts, GL_STATIC_DRAW);

And that is pretty much it! Now you can create complicated meshes using something like Anim8or or Blender and render them with your own OpenGL implementation.

NPC Questing

Here lately I have had some time to work on Arthur’s Grove (I’m still note 100% sold on the name, but we’ll see!). I have started to add a few basic “quests.” These mostly involve item fetching – for example, before you acquire a weapon you must fetch an item for a NPC. Even from these very basic quests characteristics of an NPC start to emerge. With the fetch quests, the player learns a lot about what the NPC desires. Some game characters might strive for coins or treasure, while others ask for family trinkets which have been recently lost or misplaced. These characteristics are nice because they are simple and easy to identify but also help the player start to build expectations for how a particular NPC will act when placed in a certain situation.

From these very simple to build quests the player starts to associate with each of these characters. Aligning with those they favor and disliking those characters they find it hard to identify with. Next task for me will be to start using these characters and what the play learns about them to start building elements of lore which persist throughout the game!

Arthur’s Grove: Update

So lately I’ve been working a lot with C++ to beef up my skills for possible future employment. Part of this work has involved me going back over Arthur’s Grove (AG) and writing it in an object structure. I’ve also started using Git version control for similar reasons. So the results of the week are as follows:

 

I added a non-hostile bug entity to the world. It walks around randomly and is destroyed in one hit. They are mostly there for amusement and to add to the environment.

I added the ability to sail across the ocean while riding a whale!

I also added the ability to shoot tsunamis across the sea, for future sea combat.

I added a basic worm enemy which will turn up dust in the player’s face. The movement for the worm enemy is a simplistic straight line but more intelligent enemies will come soon.

Bacon Game Jam 08

I participated in the 5th bacon jam over a year ago and had a blast doing it, so I’m doing it again with the hopes of beating my old score. Last time I teamed up with an artist, this time I’ll be doing everything! I will be updating this post along the way with my progress! I’m using GCC and SDL2, the code base I’m starting with can be found here. Wish me luck! If you would like to participant be sure to sign up here.

Update #1

We are about two hours in, the theme is “Millions of them.” My current idea for a basic game mechanic is to have the player move up/down/left/right and shoot a lightning bolt which kills all enemies along that direction. These enemies would be small, move randomly, and there would be “millions of them”. I’m going to start coding it up and see what we get!

Update #2

6 hrs in, about to call it for the night and get some rest. Tomorrow I’m going to polish the simplistic gameplay I have already and hopefully add an extra layer of fun on top! I was going to post a Gif of what I’ve done so far but unfortunately I don’t have the software installed on this computer, and I’m too tired to install everything right now. If I can remember, I’ll post a Gif first thing in the morning.

Update #3

Just got up, I’m going to try and polish what I made yesterday and try to add more flash and fun! 1 day and 7 hrs left 😀

Update #4

Done! you can check it out here: https://bacongamejam.org/jams/bacongamejam-08/286/.