How to make a indie game?

Started by
7 comments, last by 0r0d 10 years, 11 months ago

Hi everyone,

I'm a developer for OS X and iOS apps and I develop little utilities, so no games or something like that. My dream is to make games and so I want to start making indie games. What programming language should I use for making indie games? I've learned Objective C, C, Ruby on Rails and PHP/HTML/CSS.

It would be nice to use a programming language which is not bound to a specific operating system, but it's not obligatory.

Have you any regards for me? Thanks!

And sorry for my english, its not my native language. ;)

Advertisement

Read me.

Given that you are on OS/X, replace all occurrences of XNA with MonoGame and you are good to go. Beyond the languages and libraries mentioned in that guide, I would also heavily consider one of the Lua based game engines. You could also of course consider Unity or UDK.

However, you need to pick your platform first and work backward from there, if you only care about supporting iOS and OSX, Objective-C is fine, if you want to support any other platform, it's a non-starter.

Thanks for the fast answer and the good link.

My platform for the future is not OS X or iOS. I would prefer (for gaming) windows and maybe linux (if the steam box will be a success). The problem at iOS is that there are to many limits because of the touch screen control. These kinds of games are not my target at the moment.

The game could be a nice 2D or 3D game for Windows. I think it's a long way to go but I don't want to start walking on the false way.

While C is perfectly fine for making games with, consider learning C++. It will open up many resources for you to use in terms of libraries and tutorials for game development. Also, look into an API such as SFML or SDL - both are cross-platform and work on many operating systems. Given that you've worked with C before, I would recommend SDL as it's written in C, so it may be of more interest to you if you wish to look through the source code.

Some resources for learning C++:

http://www.learncpp.com/

http://www.cplusplus.com/

Tutorials for SDL:

http://www.sdltutorials.com/

http://www.lazyfoo.net/SDL_tutorials/

If you already is used to write iOs OsX apps, just continue to use the language you're proficient with AND that allow to display images (full or bloc) and play sound.

Then, a game is just another utility. Start simple and small, to get used to the images manipulation and animation, playing sound and writing the game loop. For instance, avoiding asteroids coming at you... wink.png

A simple game is also easier to complete quickly.

Then, when you have a good fondations, you can start a more ambitious project.

Space Zig-Zag, a casual game of skill for Android by Sporniket-Studio.com

I also use Mac OSX as my primary development platform along side of iOS. You said that you'd rather not develop for MacOSX? I personally think it's a good idea to develop for every and any platform possible to broaden your audience.

For languages, you can use C for almost any platform, but there are a few indie platforms that limit you to use C# (which I personally hate). Most people will recommend using C++ as your primary programming language. I personally prefer C over C++, but don't avoid learning it because it can be very useful.

I see that SDL has already been recommended, but if you plan on creating something of great complexity, I recommend you learn OpenGL 3+ as well as OpenAL. They are also cross platform and compatible with SDL. OpenGL is the cross platform 3D graphics API, while OpenAL is a cross platform 3D sound API.

OpenGL 3.2 tutorials: http://nopper.tv/opengl.html

OpenAL video tutorial:

OpenAL w/ SDL: http://pastebin.com/rYp59nYg

A few notes I also wanted to share:

1. For MacOSX, the latest version of OpenGL supported is 3.2. It sounds unfortunate, but IMO, I don't see how much better 4.0 is for most applications.

2. If you plan to use OpenGL 3+ with SDL, either make sure you are using the beta version of SDL 2.0 (the final release hasn't been made yet), or you can roll your own code to initialize and use an OpenGL 3.2 context. Finding code on how to do that is extremely hard to find, but after a VERY long time searching google, I finally found some example code.

main.m


// Based on the Cocoa variant of the "minimal animation" demo
// Working, reasonably simple 3.2 demo!!!
// Preliminary demo by Ingemar Ragnemalm 2012
// for the 3.2 update of my course book.
// Partially based on other GL3.2 demos, especially that demo with two triangles.
// (Should be referenced I guess but I can't do that right now.)
// Later versions appears in my book.

#import <Cocoa/Cocoa.h>
#include <OpenGL/gl3.h>

#include <stdlib.h>
#include <stdio.h>
#include <stddef.h>
#include <string.h>

// Globals
// Data would normally be read from files
GLfloat vertices[] = {	-1.0f,0.0f,0.0f,
    0.0f,1.0f,0.0f,
    0.0f,0.0f,0.0f };
GLfloat colours[] = {	1.0f, 0.0f, 0.0f,
    0.0f, 1.0f, 0.0f,
    0.0f, 0.0f, 1.0f };
GLfloat vertices2[] = {	0.0f,0.0f,0.0f,
    0.0f,-1.0f,0.0f,
    1.0f,0.0f,0.0f };

// two vertex array objects, one for each object drawn
unsigned int vertexArrayObjID[2];
// three vertex buffer objects in this example
unsigned int vertexBufferObjID[3];

void checkError(const char *functionName);

// Note: free data afterwards.
char* loadFile(char *filename, GLint *fSize)
{
	char * data;
	FILE *theFile;
	char c;
	long howMuch;
    
	// Get file length
	theFile = fopen(filename, "rb");
	if (theFile == NULL)
	{
		printf("%s not found\n", filename);
		return NULL;
	}
	howMuch = 0;
	c = 0;
	while (c != EOF)
	{
		c = getc(theFile);
		howMuch++;
	}
	fclose(theFile);
    
	printf("%ld bytes\n", howMuch);
    
	// Read it again
	data = (char *)malloc(howMuch);
	theFile = fopen(filename, "rb");
	fread(data, howMuch-1,1,theFile);
	fclose(theFile);
	data[howMuch-1] = 0;
    
	printf("\n--- Shader source %s ---\n%s\n-- end of %s --\n", filename, data, filename);
	printf("%s loaded from disk\n", filename);
	*fSize = howMuch;
    
	return data;
}

void dumpInfo(void)
{
    printf ("Vendor: %s\n", glGetString (GL_VENDOR));
    printf ("Renderer: %s\n", glGetString (GL_RENDERER));
    printf ("Version: %s\n", glGetString (GL_VERSION));
    printf ("GLSL: %s\n", glGetString (GL_SHADING_LANGUAGE_VERSION));
    checkError ("dumpInfo");
}

/* report GL errors, if any, to stderr */
void checkError(const char *functionName)
{
    GLenum error;
    while (( error = glGetError() ) != GL_NO_ERROR)
    {
        fprintf (stderr, "GL error 0x%X detected in %s\n", error, functionName);
    }
}

// printShaderInfoLog
// From OpenGL Shading Language 3rd Edition, p215-216
// Display (hopefully) useful error messages if shader fails to compile
void printShaderInfoLog(GLint shader)
{
	GLint infoLogLen = 0;
	GLsizei charsWritten = 0;
	GLchar *infoLog;
    
	glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogLen);
    
	// should additionally check for OpenGL errors here
    
	if (infoLogLen > 0)
	{
		infoLog = (GLchar *)malloc(infoLogLen); //new GLchar[infoLogLen];
		// error check for fail to allocate memory omitted
		glGetShaderInfoLog(shader,infoLogLen, &charsWritten, infoLog);
		printf("Infolog: %s\n", infoLog);
		free(infoLog);
	}
	else
		printf("No infolog\n");
    
	// should additionally check for OpenGL errors here
}


void init(void)
{
	// GL inits
	glClearColor(0.2,0.2,0.5,0);
	glEnable(GL_DEPTH_TEST);
	checkError("GL inits");
    
	// Would load objects from file here - but using globals in this example
    
	// Allocate Vertex Array Objects
	glGenVertexArrays(2, &vertexArrayObjID[0]);
	// Setup first Vertex Array Object
	glBindVertexArray(vertexArrayObjID[0]);
	glGenBuffers(2, vertexBufferObjID);
    
	// VBO for vertex data
	glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObjID[0]);
	glBufferData(GL_ARRAY_BUFFER, 9*sizeof(GLfloat), vertices, GL_STATIC_DRAW);
	glVertexAttribPointer((GLuint)0, 3, GL_FLOAT, GL_FALSE, 0, 0);
	glEnableVertexAttribArray(0);
    
	// VBO for colour data
	glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObjID[1]);
	glBufferData(GL_ARRAY_BUFFER, 9*sizeof(GLfloat), colours, GL_STATIC_DRAW);
	glVertexAttribPointer((GLuint)1, 3, GL_FLOAT, GL_FALSE, 0, 0);
	glEnableVertexAttribArray(1);
    
	// Setup second Vertex Array Object
	glBindVertexArray(vertexArrayObjID[1]);
	glGenBuffers(1, &vertexBufferObjID[2]);
    
	// VBO for vertex data
	glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObjID[2]);
	glBufferData(GL_ARRAY_BUFFER, 9*sizeof(GLfloat), vertices2, GL_STATIC_DRAW);
	glVertexAttribPointer((GLuint)0, 3, GL_FLOAT, GL_FALSE, 0, 0);
	glEnableVertexAttribArray(0);
    
	glBindVertexArray(0);
    
	checkError("init");
}



void initShaders(void)
{
	GLuint p, f, v;
    
	char *vs,*fs;
    
	v = glCreateShader(GL_VERTEX_SHADER);
	f = glCreateShader(GL_FRAGMENT_SHADER);
    
	// load shaders & get length of each
	GLint vlen;
	GLint flen;
	vs = loadFile("OpenGL3Test.app/Contents/Resources/minimal.vert", &vlen);
	fs = loadFile("OpenGL3Test.app/Contents/Resources/minimal.frag", &flen);
    
	const char * vv = vs;
	const char * ff = fs;
    
	glShaderSource(v, 1, &vv, NULL); // &vlen);
	glShaderSource(f, 1, &ff, NULL); // &flen);
    
	GLint compiled;
    
	glCompileShader(v);
	glGetShaderiv(v, GL_COMPILE_STATUS, &compiled);
	if (!compiled)
	{
		printf("Vertex shader not compiled.\n");
		printShaderInfoLog(v);
	}
    
	glCompileShader(f);
	glGetShaderiv(f, GL_COMPILE_STATUS, &compiled);
	if (!compiled)
	{
		printf("Fragment shader not compiled.\n");
		printShaderInfoLog(f);
		printf("-----\n");
	}
    
	p = glCreateProgram();
    
	glBindAttribLocation(p,0, "in_Position");
	glBindAttribLocation(p,1, "in_Color");
    
	glAttachShader(p,v);
	glAttachShader(p,f);
    
	glLinkProgram(p);
	glUseProgram(p);
    
	free(vs); // dont forget to free allocated memory
	free(fs); // we allocated this in the loadFile function...
    
	checkError("init shader");
}

void display(void)
{
	checkError("pre display");
    
	// clear the screen
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    
	glBindVertexArray(vertexArrayObjID[0]);	// First VAO
	glDrawArrays(GL_TRIANGLES, 0, 3);	// draw first object
    
	glBindVertexArray(vertexArrayObjID[1]);		// select second VAO
	glVertexAttrib3f((GLuint)1, 1.0, 0.0, 0.0); // set constant color attribute
	glDrawArrays(GL_TRIANGLES, 0, 3);	// draw second object
    
	glBindVertexArray(0);
    
	checkError("display");
}

void reshape(int w, int h)
{
	glViewport(0,0,(GLsizei)w,(GLsizei)h);
}



// -----------

// Globals (was in GLViewDataPtr)
NSOpenGLContext	*m_context;
float lastWidth, lastHeight;
NSView *theView;

void MakeContext(NSView *view)
{
    //	NSWindow *w;
	NSOpenGLPixelFormat *fmt;
    
	NSOpenGLPixelFormatAttribute attrs[] =
	{
		NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core,
		NSOpenGLPFADoubleBuffer,
		NSOpenGLPFADepthSize, 32,
		0
	};
    
	// Create custom data pointer
	theView = view;
    
	// Init GL context
	fmt = [[NSOpenGLPixelFormat alloc] initWithAttributes: attrs];
    
	m_context = [[NSOpenGLContext alloc] initWithFormat: fmt shareContext: nil];
	[fmt release];
	[m_context makeCurrentContext];
    
	checkError("makeCurrentContext");
}



// -------------------- View ------------------------

@interface TestView : NSView { }
-(void)drawRect:(NSRect)rect;
@end

float loop;

#define Pi 3.1415

@implementation TestView

-(void)drawRect:(NSRect)rect
{
	if (([theView frame].size.width != lastWidth) || ([theView frame].size.height != lastHeight))
	{
		lastWidth = [theView frame].size.width;
		lastHeight = [theView frame].size.height;
        
		// Only needed on resize:
		[m_context clearDrawable];
        
		reshape([theView frame].size.width, [theView frame].size.height);
	}
    
	[m_context setView: theView];
	[m_context makeCurrentContext];
    
	// Draw
	display();
    
	[m_context flushBuffer];
	[NSOpenGLContext clearCurrentContext];
    
	loop = loop + 0.1;
}

-(void)windowWillClose:(NSNotification *)note
{
    [[NSApplication sharedApplication] terminate:self];
}
@end


// -------------------- Timer ------------------------

// Mini-mini class for the timer
@interface TimerController : NSObject { }
-(void)timerFireMethod:(NSTimer *)t;
@end

NSTimer	*gTimer;
TimerController	*myTimerController;
NSView	*view;

// Timer!
@implementation TimerController
-(void)timerFireMethod:(NSTimer *)t;
{
	[view setNeedsDisplay: YES];
}
@end

// home()

#include <Carbon/Carbon.h>
#include <stdio.h>

void home()
{
	/*CFBundleRef mainBundle = CFBundleGetMainBundle();
	CFURLRef resourcesURL = CFBundleCopyResourcesDirectoryURL(mainBundle);
	char path[PATH_MAX];
	if (!CFURLGetFileSystemRepresentation(resourcesURL, TRUE, (UInt8 *)path, PATH_MAX))
	{
		// error!
		return;
	}
	CFRelease(resourcesURL);
    
	chdir(path);
	printf("Current Path: %s\n", path);*/
}

// ------------------ Main program ---------------------

NSApplication *myApp;
NSView *view;
NSAutoreleasePool *pool;
NSWindow *window;

int main(int argc, const char *argv[])
{
	pool = [NSAutoreleasePool new];
	myApp = [NSApplication sharedApplication];
	home();
    
	NSRect frame = NSMakeRect(10., 1000., 640., 480.);
    
	window = [NSWindow alloc];
	[window initWithContentRect:frame
                      styleMask:NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask
                        backing:NSBackingStoreBuffered
                          defer:false];
	[window setTitle:@"Minimal OpenGL animation (Cocoa)"];
    
	view = [TestView alloc];
	[view initWithFrame: frame];
    
	// OpenGL init!
	MakeContext(view);
    
    init ();
	initShaders();
    dumpInfo ();
    
	[window setContentView: view];
	[window setDelegate: view];
	[window makeKeyAndOrderFront: nil];
    
	// Timer
	myTimerController = [TimerController alloc];
	gTimer = [NSTimer
              scheduledTimerWithTimeInterval: 0.02
              target: myTimerController
              selector: @selector(timerFireMethod:)
              userInfo: nil
              repeats: YES];
    
	// Main loop
	[myApp run];
	[pool release]; // Free;
	return( EXIT_SUCCESS );
}

minimal.vert:


#version 150
 
in  vec3 in_Position;
in  vec3 in_Color;
out vec3 ex_Color;
 
void main(void)
{
	ex_Color = in_Color;
	gl_Position = vec4(in_Position, 1.0);
}

minimal.frag:


#version 150
 
in  vec3 ex_Color;
out vec4 out_Color;
 
void main(void)
{
	out_Color = vec4(ex_Color,1.0);
}

That should be enough to get you going on the most basic of basics with OpenGL 3.2

3. While OpenAL is an awesome audio API, it's support for Mac OSX is rather poor. A good example would be the fact that the native framework doesn't work in 64-bit mode. An alternative to this is to use OpenALSoft.framework which is a wrapper that uses CoreAudio to handle audio. Works very well and I have no complaints using it!

4. When reading and referencing OpenAL tutorials, please try to avoid using ALUT because it is very depreciated. The SDL example using OpenAL is strongly preferred since it loads sound effects without the need to use ALUT.

I really hope that this helps you in one way or another. Be sure to take your time and learn at a pace that works best for you! Feel free to ask me anything when it comes to developing games on OSX or iOS. OpenGL on OSX is becoming my new specialty.

Shogun.

If you want an active community , easy language to learn and power you should take a look at Love2d

Thanks for all your information. I were the last 3 weeks in holiday, no internet, nothing.

I think I will take a look at iOS game developing. I work in the next weeks with cocos2d to learn the first basics of game developing. Are there some good tutorials for cocos2d you have worked with?

I also recommend moving up to C++ since you already know C. C++ is by far the most widely used and supported language in game development, with lots of tutorials, tools, source code, books, groups, and knowledgeable devs on forums that can help you. It will also allow you to easily port your code to any platform you want.

You cant go wrong with C++, and you'll be learning stuff that you can directly use if you go work for a pro dev studio.

This topic is closed to new replies.

Advertisement