2d game and collision detection

Started by
16 comments, last by Hedos 20 years, 1 month ago
You do not *need* to use velocities in order to use the code. I merely suggested it because in Legoboy's situation it would be the logical thing. Legoboy had a ball struct with the properties "speed" and "direction" - combine this into a velocity and things will get simpler. Although in your situation it may not be best to use this, I'll give a brief example of velocities anyhow:

Objects position is 10,20
Objects velocity is 2,1
Each time the game updates, add the objects velocity (modified by whatever frame-independent movement method you are using) onto the objects position in order to move the Object:
Objects position += objects velocity
Objects position is now 12,21. In this way the velocity represents the speed and direction that a thing will travel. For instance, a velocity of 4,2 would indicated the same direction as 2,1, but the object would move twice as fast. A velocity of -2,-1 would cause the object to travel in the opposite direction (to a velocity of 2,1).

Hope that helps a little. I wouldn't worry about not having done any advanced maths classes - neither have I. In fact, I have learnt more maths through game programming that I think I ever have at secondary school.

All that said, whatever method you are using to handle movement is probably fine. If you are merely moving the player left, right and forward at a constant speed whenever he/she is pressing Left, Right and Up, then you may not need to use velocities (although I seriously suggest that you get a good feel of vectors as they are used in may ways), although you will still need to obviously represent the direction the player is facing. The CircleSegmentSweep function takes the original position of the circle and the update position of the circle. It will not matter how you determine where the updated position will be. The function also gives the reflection vector. This is important because you will need to add it to the objects position after a collision in order to move the object away from the segment (or you could just move the object in the opposite direction it is traveling).
One thing that this code does not do particularly well is handle sliding (ie an object slides alone a surface it has collided with). Perhaps I'll get around to adding that functionality some time .
Another thing - it may be necessary to go through all possible collisions and determine which one is closest, then actually responding to that one. This, I believe (although I have not tried) will help prevent glitches when several collisions are detected.

It is also worth noting that is may be easier to go with the code oliii provided because, although I have not had a good look, it may be easier to get a grip on. That and the fact that you can guarantee that oliii knows what he's talking about (more than I do).

Anyhow, hope all this helped.

[edited by - jack_1313 on March 23, 2004 7:06:36 PM]
Advertisement
Thanks for your replies

oliii: I tried your code for collision between a circle and lines, it works!
It isn't slicing correctly, it can only slices in one direction and it seems that the more the line is horizontal and the faster the slicing will be ( it becomes extremly fast when close to horizontal )...
Also, it's kinda bugged when touching the end of a line
And when there is a segment of two lines, the sphare will go trhought the segment..

Oh, but maybe this is just because I don't understand what is the use of the 'NumSegments' parameter in the collision function?

Well.. I guess I'm gonna try to learn some vector stuff and create a better collision detection based on your code

jack_1313: Thanks for your explanations

Edit: oliii, I just realised what's really happening, the sphere is not slicing on -any- lines when going in left or right direction, but it's slicing when going up or down.. ( and slicing at exagerated speeds)

[edited by - Hedos on March 23, 2004 7:34:04 PM]
ok, it''s the closest point calculations that''s buggy. I''ll have a look The best way to debug it is to draw the actual point, but I''ll check it out.

Everything is better with Metal.

I''ve had a look at it, and it works straight up. here are the files (ouch...).

//=========================================================//---------------------------------------------------------//// Gamecode.h////---------------------------------------------------------//=========================================================#ifndef OLI_GAMECODE_H#define OLI_GAMECODE_H/*#include "GameCode.h"*/#include <windows.h>#include <math.h>#include <stdio.h>#include <GL/glut.h>extern void  GameInit			();extern void  GameUpdate			(float dt);extern void  GameRender			(void);extern void  GameOnKeyCallback	(char keypressed);extern void  GameMouse			(float x, float y, int buttons);extern void  GameRenderStats	();extern void  Printf				(int x, int y, unsigned int rgba, const char* str, ...);static float dbg_world_size = 100.0f;#endif OLI_GAMECODE_H


//=========================================================//---------------------------------------------------------//// main.cpp////---------------------------------------------------------//=========================================================#include "GameCode.h"//--------------------------------------------------------------------------// mouse coords//--------------------------------------------------------------------------float mouse_x = 0.0f;float mouse_y = 0.0f;int   mouse_b = 0;//--------------------------------------------------------------------------// window size//--------------------------------------------------------------------------float width  = 640;float height = 480;void Printf(int x, int y, unsigned int rgba, const char* str, ...){	static char buffer[512];	va_list params;	va_start(params, str);	vsprintf(buffer, str, params);	va_end(params);	glPushMatrix();	glColor4ubv((unsigned char*) &rgba);		float fx = x * ( 8 * dbg_world_size / width);	float fy = y * (13 * dbg_world_size / height);	glRasterPos2f(fx, 102 - fy);	char* c = buffer;	while(*c)	{		glutBitmapCharacter(GLUT_BITMAP_8_BY_13, *c);		c++;	}	glPopMatrix();}//-----------------------------------------------------// resets the world with random data//-----------------------------------------------------void Init(){	GameInit();}//-----------------------------------------------------// Update the objects//-----------------------------------------------------void Update(float dt){	GameUpdate(dt);}//-----------------------------------------------------// displays the objects//-----------------------------------------------------void Display(){	//--------------------------------------------------------------------------	// render stuff	//--------------------------------------------------------------------------	glClearColor(0.2f, 0.2f, 0.2f, 0.2f);	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);	float aspect = 	width / (float) height;	glMatrixMode(GL_PROJECTION);	glLoadIdentity();	glOrtho(0, dbg_world_size, 0, dbg_world_size, -100, 100);		//-----------------------------------------------------------------	// Setup the model view matrix	//-----------------------------------------------------------------	glMatrixMode(GL_MODELVIEW);	glLoadIdentity();		float fx = (       (mouse_x / (float) width )) * dbg_world_size;	float fy = (1.0f - (mouse_y / (float) height)) * dbg_world_size;	GameMouse(fx, fy, mouse_b);	GameUpdate(1.0f / 60.0f);		GameRender();	glutSwapBuffers();}void Mouse(int buttons, int state, int x, int y){	mouse_x = x;	mouse_y = y;		if (buttons == GLUT_LEFT_BUTTON)	{		if (state == GLUT_DOWN)			mouse_b |= 1;		else			mouse_b &= ~1;	}	if (buttons == GLUT_RIGHT_BUTTON)	{		if (state == GLUT_DOWN)			mouse_b |= 2;		else			mouse_b &= ~2;	}}void PassiveMotion(int x, int y){	mouse_x = x;	mouse_y = y;}void Motion(int x, int y){	mouse_x = x;	mouse_y = y;}void Idle(){//	Update(1.0f / 60.0f);	Display();}void Timer(int t){	Idle();	glutTimerFunc(t, Timer, (int) 500.0f / 60.0f);}	void Reshape(int w, int h){	width  = w;	height = h;	glViewport(	0, 0, w, h);}void Keyboard(unsigned char k, int x, int y){	if (k == 27)		exit(0);	GameOnKeyCallback(k);}void main(int argc, char** argv){	//--------------------------------------------------------------------------	// OpenGL / GLUT init	//--------------------------------------------------------------------------    glutInit( &argc, argv );	glutInitDisplayMode		(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);		glutInitWindowSize		(width, height);	glutInitWindowPosition	(0, 0);	glutCreateWindow		("ping pong");		glPointSize(3.0f);	glEnable				(GL_BLEND);	glBlendFunc				(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);	glDisable				(GL_DEPTH_TEST);	glDisable				(GL_LIGHTING);		glutDisplayFunc			(Display);	glutReshapeFunc			(Reshape);//	glutIdleFunc			(Idle);	glutTimerFunc			(0, Timer, (int) 100.0f / 60.0f);	glutPassiveMotionFunc	(PassiveMotion);	glutMouseFunc			(Mouse);	glutMotionFunc			(Motion);	glutKeyboardFunc		(Keyboard);		printf("---------------------------------\n");	printf("- colliding spehre-segment demo -\n");	printf("---------------------------------\n");	printf("olivierrenault@hotmail.com\n");	printf("\n");	printf("- press esc to shutdown\n");		Init					();	glutMainLoop			();}


//=========================================================//---------------------------------------------------------//// Gamecode.cpp////---------------------------------------------------------//=========================================================#include "GameCode.h"static bool dbg_Pause		 = false;static int  ikeypressedtimer = 0;static int  itimer			 = 0;static float mousex			 = 0;static float mousey			 = 0;#define for if (0) {} else forfloat frand(float x) { return (rand() / (float) RAND_MAX) * x; }float TwoPi() { static float two_pi = atan(1) * 8.0f; return two_pi; }struct Vector{	float x, y;};enum { eNumSegments = 50 };Vector Seg[eNumSegments][2];int m_iNumSegments = eNumSegments;Vector Pointer;float  radius = dbg_world_size * 0.02f;Vector GetClosestPointOnSegment(Vector S0, Vector S1, Vector P){	Vector E; // edge direction	E.x = S1.x - S0.x; // E = S1 - S0	E.y = S1.y - S0.y; //	Vector D; // relative position of point to the edge	D.x = P.x - S0.x; // D = P - S0 	D.y = P.y - S0.y; //	float de; // project point on edge (dot product)	de = D.x*E.x + D.y*E.y; // de = D dot E	float e2; // length of the edge, squared	e2 = E.x*E.x + E.y*E.y; // e^2 = E dot E	if (de < 0.0f) // if projection is before the edge start point	return S0; // return edge start point	if (de > e2) // if projection after edge end point	return S1; // return edge end point	float t; // percentage on how far the point projects on the edge	t = de / e2; // t = projection / edge length^2	Vector Q; // vector projection of point on edge	Q.x = S0.x + E.x * t;	Q.y = S0.y + E.y * t;	return Q;}bool PointInCircle(Vector C, float r, Vector P){	Vector D; // relative position of point to circle centre	D.x = P.x - C.x; // D = P - C	D.y = P.y - C.y; //	float d2; // distance squared of the point to the circle centre	d2 = D.x*D.x + D.y*D.y; // d^2 = D dot D	float r2; // radius squared of the circle	r2 = r*r; // r^2 = r * r	if (d2 > r2) // distance squared greater than radius squared		return false; // point not inside the circle		return true; // yes, point is inside}// returns the new circle position so the point is right on the // surface of the circleVector ConstrainCircleToPoint(Vector C, float r, Vector P, float smoothness){	Vector D; // relative position of circle centre to point	D.x = C.x - P.x; // D = C - P	D.y = C.y - P.y;	float d2; // distance squared between points	d2 = D.x*D.x + D.y*D.y; // d^2 = D dot D	float d; // distance between points	d = (float) sqrt(d2); // d = dqrt(d^2)	float l = r - d; // how far is the point to the circle surface	D.x *= l / d * smoothness; // the movement vector required to push the circle	D.y *= l / d * smoothness; // centre away from the point	// D *= l / d	Vector NewC; // the new circle centre position,	NewC.x = C.x + D.x; // so that the point is on the circle surface	NewC.y = C.y + D.y; // NewC = C + D;	return NewC;}void GameInit(void){	for(int i = 0; i < m_iNumSegments; i ++)	{		Seg[i][0].x = frand(dbg_world_size);		Seg[i][0].y = frand(dbg_world_size);		Seg[i][1] = Seg[i][0];		Seg[i][1].x += frand(dbg_world_size * 0.3f) - dbg_world_size * 0.15f;		Seg[i][1].y += frand(dbg_world_size * 0.3f) - dbg_world_size * 0.15f;	}}	void GameUpdate(float dt){	if (dbg_Pause)		return;	Vector D;	D.x = mousex - Pointer.x;	D.y = mousey - Pointer.y;	float d = sqrt(D.x*D.x + D.y*D.y);	D.x /= d;	D.y /= d;		float speed = d;	if (speed > dbg_world_size * 0.1f) 		speed = dbg_world_size * 0.1f;	Pointer.x += D.x * speed * 0.1f;	Pointer.y += D.y * speed * 0.1f;	int iter = 5;	float smoothness = 5.0f / (float) iter;	if (smoothness > 1.0f) smoothness = 1.0f;	for(int j = 0; j < iter; j ++)	{				for(int i = 0; i < m_iNumSegments; i ++)		{			Vector Q = GetClosestPointOnSegment(Seg[i][0], Seg[i][1], Pointer);			glPointSize(3.0f);			glEnable(GL_POINT_SMOOTH);			glColor4f(1.0f, 0.0f, 0.0f, 1.0f);			glBegin(GL_POINTS);			glVertex2fv(&Q.x);			glEnd();			if (PointInCircle(Pointer, radius, Q))			{				Pointer = ConstrainCircleToPoint(Pointer, radius, Q, smoothness);			}		}	}}void GameRender(void){	GameRenderStats();		glPointSize(3.0f);	glEnable(GL_POINT_SMOOTH);	glColor4f(1.0f, 0.0f, 0.0f, 1.0f);	glBegin(GL_POINTS);	glVertex2fv(&Pointer.x);	glEnd();	glColor4f(0.0f, 1.0f, 0.0f, 1.0f);	glLineWidth(1.0f);	glBegin(GL_LINES);		for(int i = 0; i < 10; i ++)	{		Vector P;		Vector Q;		P.x = Pointer.x + cos(i * TwoPi() / 10.0f) * radius;		P.y = Pointer.y + sin(i * TwoPi() / 10.0f) * radius;		Q.x = Pointer.x + cos((i+1) * TwoPi() / 10.0f) * radius;		Q.y = Pointer.y + sin((i+1) * TwoPi() / 10.0f) * radius;		glVertex2fv(&P.x);		glVertex2fv(&Q.x);	}	glEnd();	glColor4f(1.0f, 1.0f, 1.0f, 1.0f);	glLineWidth(1.0f);	glBegin(GL_LINES);	for(int i = 0; i < m_iNumSegments; i ++)	{		glVertex2fv(&Seg[i][0].x);		glVertex2fv(&Seg[i][1].x);	}	glEnd();}float fCoF  = 0.3f;float fCoR  = 0.7f;float fSep  = 0.5f;float Clamp(float a, float min, float max){	return (a < min)? min : (a > max)? max : a;}void GameOnKeyCallback(char keypressed){	switch(keypressed)	{	case ''p'':	case ''P'':		dbg_Pause = !dbg_Pause;		break;	case '' '':		GameInit();		break;	case ''h'':	case ''H'':		ikeypressedtimer = 0;	default:		printf("\n");		printf("--------------------------------\n");		printf("- Keys                         -\n");		printf("--------------------------------\n");		printf("- Pause      On/Off : ''p''\n");		printf("- help              : ''h''\n");		printf("--------------------------------\n");		printf("\n");		break;	}}void GameMouse(float x, float y, int buttons){	mousex = x;	mousey = y;}void GameRenderStats(){	if (dbg_Pause)		ikeypressedtimer = 0;	if (ikeypressedtimer < 256)	{		unsigned int a = (255 - ikeypressedtimer);		unsigned int r = 0xFF;		unsigned int g = 0xFF;		unsigned int b = 0xFF;		unsigned int c = ((a << 24) | (r << 16) | (g << 8) | b);		int x = 2;		int y = 3;		Printf(2, y++, c, "- Mouse      [%d, %d]", (int) mousex, (int) mousey);			x = 47;		y = 3;		Printf(x, y++, c, "--------------------------------");		Printf(x, y++, c, "- Pause      On/Off : ''p''");		Printf(x, y++, c, "- help              : ''h''");		Printf(x, y++, c, "--------------------------------");		ikeypressedtimer+=8;	}}

Everything is better with Metal.

you can see the shortcoming with that method by the way It''s just for a start

Everything is better with Metal.

Wow, it works great Thanks a lot
Now I''m gonna try to make it work with collision with other circles... ( I have no idea if I''ll be able to do that )
it''s even simpler.

took me 15 minutes here is the full code, since you have to change the main collision loop slightly to take care of player/player collisions.


don''t kid yourself, this algo is simplistic, it''s just a start for your game. you''ll need to do things a lot more complicated so the collsion detection becomes bullet proof. For example, if the sphere colides with two parallel walls, you''ll have problems. to get rid of those cases, you can either fudge it (detect two collisions walls that are parallel => set player movement to the player before collision, but for that, you need to detect collisions ahead of the frame, so a bit more code), or do it properly (swept spheres, and the problem of sorting collisions, grouping objects in potentially colliding clusters, ect...).

#include "GameCode.h"static bool dbg_Pause		 = false;static int  ikeypressedtimer = 0;static int  itimer			 = 0;static float mousex			 = 0;static float mousey			 = 0;#define for if (0) {} else forfloat frand(float x) { return (rand() / (float) RAND_MAX) * x; }float clamp(float a, float min, float max) { return (a < min)? min : (a > max)? max : a; }float TwoPi() { static float two_pi = atan(1) * 8.0f; return two_pi; }struct Vector{	float x, y;};struct CPlayer{    Vector P;    float  r;	CPlayer()	{		P.x = frand(dbg_world_size);		P.y = frand(dbg_world_size);		r   = frand(dbg_world_size * 0.04f) + 0.04f;	}};enum { eNumSegments = 50 };Vector Seg[eNumSegments][2];int m_iNumSegments = eNumSegments;enum { eMaxPlayers = 20 };CPlayer Player[eMaxPlayers];int iNumPlayers = 10;Vector GetClosestPointOnSegment(Vector S0, Vector S1, Vector P){	Vector E; // edge direction	E.x = S1.x - S0.x; // E = S1 - S0	E.y = S1.y - S0.y; //	Vector D; // relative position of point to the edge	D.x = P.x - S0.x; // D = P - S0 	D.y = P.y - S0.y; //	float de; // project point on edge (dot product)	de = D.x*E.x + D.y*E.y; // de = D dot E	float e2; // length of the edge, squared	e2 = E.x*E.x + E.y*E.y; // e^2 = E dot E	if (de < 0.0f) // if projection is before the edge start point	return S0; // return edge start point	if (de > e2) // if projection after edge end point	return S1; // return edge end point	float t; // percentage on how far the point projects on the edge	t = de / e2; // t = projection / edge length^2	Vector Q; // vector projection of point on edge	Q.x = S0.x + E.x * t;	Q.y = S0.y + E.y * t;	return Q;}bool PointInCircle(Vector C, float r, Vector P){	Vector D; // relative position of point to circle centre	D.x = P.x - C.x; // D = P - C	D.y = P.y - C.y; //	float d2; // distance squared of the point to the circle centre	d2 = D.x*D.x + D.y*D.y; // d^2 = D dot D	float r2; // radius squared of the circle	r2 = r*r; // r^2 = r * r	if (d2 > r2) // distance squared greater than radius squared		return false; // point not inside the circle		return true; // yes, point is inside}// returns the new circle position so the point is right on the // surface of the circleVector ConstrainCircleToPoint(Vector C, float r, Vector P, float smoothness){	Vector D; // relative position of circle centre to point	D.x = C.x - P.x; // D = C - P	D.y = C.y - P.y;	float d2; // distance squared between points	d2 = D.x*D.x + D.y*D.y; // d^2 = D dot D	float d; // distance between points	d = (float) sqrt(d2); // d = dqrt(d^2)	float l = r - d; // how far is the point to the circle surface	D.x *= l / d * smoothness; // the movement vector required to push the circle	D.y *= l / d * smoothness; // centre away from the point	// D *= l / d	Vector NewC; // the new circle centre position,	NewC.x = C.x + D.x; // so that the point is on the circle surface	NewC.y = C.y + D.y; // NewC = C + D;	return NewC;}// check if distance squared between the centre are more than the sqaure of the sum of the radius// if not, compute the penetration vector (depth and direction in one single vector)// the separation (penetration vector), if the vector required to push the spheres apart so// they stop intersecting.bool CircleCircleCollide(Vector C0, float r0, Vector C1, float r1, Vector* pSeparation){    Vector D;    D.x = C0.x - C1.x;    D.y = C0.y - C1.y;    float d2 = (D.x * D.x + D.y * D.y);    float r = r0 + r1;    float r2 = r * r;    if (d2 > r2)        return false;    if (!pSeparation) // this call was just a query, so return that the spheres do collide        return true;    float d = (float) sqrt(d2);    float l = r - d;    D.x *= l / d;    D.y *= l / d;    *pSeparation = D;        return true;}void GameInit(void){	for(int i = 0; i < m_iNumSegments; i ++)	{		Seg[i][0].x = frand(dbg_world_size);		Seg[i][0].y = frand(dbg_world_size);		Seg[i][1] = Seg[i][0];		Seg[i][1].x += frand(dbg_world_size * 0.3f) - dbg_world_size * 0.15f;		Seg[i][1].y += frand(dbg_world_size * 0.3f) - dbg_world_size * 0.15f;	}	for(int i = 0; i < iNumPlayers; i ++)	{		Player[i] = CPlayer();	}}void CheckPlayerSegmentsCollisions(int iPlayer, float smoothness){	Vector& Pointer = Player[iPlayer].P;	float radius    = Player[iPlayer].r;	for(int i = 0; i < m_iNumSegments; i ++)	{		Vector Q = GetClosestPointOnSegment(Seg[i][0], Seg[i][1], Pointer);		if (PointInCircle(Pointer, radius, Q))		{			Pointer = ConstrainCircleToPoint(Pointer, radius, Q, smoothness);		}	}}void CheckPlayerPlayersCollisions(int iPlayer, float smoothness){	int i = iPlayer;	for(int j = i+1; j < iNumPlayers; j ++)    {            Vector Separation;		if (CircleCircleCollide(Player[i].P, Player[i].r, Player[j].P, Player[j].r, &Separation))        {            Player[i].P.x += Separation.x * 0.5f * smoothness;            Player[i].P.y += Separation.y * 0.5f * smoothness;            Player[j].P.x -= Separation.x * 0.5f * smoothness;            Player[j].P.y -= Separation.y * 0.5f * smoothness;        }    }}	void GameUpdate(float dt){	if (dbg_Pause)		return;	Vector& Pointer = Player[0].P;	Vector D;	D.x = mousex - Pointer.x;	D.y = mousey - Pointer.y;	float d = sqrt(D.x*D.x + D.y*D.y);	D.x /= d;	D.y /= d;		float speed = d;	if (speed > dbg_world_size * 0.1f) 		speed = dbg_world_size * 0.1f;	Pointer.x += D.x * speed * 0.1f;	Pointer.y += D.y * speed * 0.1f;	int iter = 2;	float smoothness = 5.0f / (float) iter;	if (smoothness > 1.0f) smoothness = 1.0f;	// core collision loop	for(int j = 0; j < iter; j ++)	{		for(int i = 0; i < iNumPlayers; i ++)		{			CheckPlayerSegmentsCollisions(i, smoothness); // player vs world collision			CheckPlayerPlayersCollisions (i, smoothness); // player vs other players collision		}	}}void GameRender(void){	GameRenderStats();	glPointSize(3.0f);	glEnable(GL_POINT_SMOOTH);	glColor4f(1.0f, 0.0f, 0.0f, 1.0f);	glBegin(GL_POINTS);	for(int i = 0; i < iNumPlayers; i ++)	{		glVertex2fv(&Player[i].P.x);	}	glEnd();	glColor4f(0.0f, 1.0f, 0.0f, 1.0f);	glLineWidth(1.0f);	glBegin(GL_LINES);		for(int p = 0; p < iNumPlayers; p ++)	{		Vector Pointer = Player[p].P;		float radius   = Player[p].r;		for(int i = 0; i < 10; i ++)		{			Vector P;			Vector Q;			P.x = Pointer.x + cos(i * TwoPi() / 10.0f) * radius;			P.y = Pointer.y + sin(i * TwoPi() / 10.0f) * radius;			Q.x = Pointer.x + cos((i+1) * TwoPi() / 10.0f) * radius;			Q.y = Pointer.y + sin((i+1) * TwoPi() / 10.0f) * radius;			glVertex2fv(&P.x);			glVertex2fv(&Q.x);		}	}	glEnd();	glColor4f(1.0f, 1.0f, 1.0f, 1.0f);	glLineWidth(1.0f);	glBegin(GL_LINES);	for(int i = 0; i < m_iNumSegments; i ++)	{		glVertex2fv(&Seg[i][0].x);		glVertex2fv(&Seg[i][1].x);	}	glEnd();}void GameOnKeyCallback(char keypressed){	switch(keypressed)	{	case ''p'':	case ''P'':		dbg_Pause = !dbg_Pause;		break;	case '' '':		GameInit();		break;	case ''h'':	case ''H'':		ikeypressedtimer = 0;	default:		printf("\n");		printf("--------------------------------\n");		printf("- Keys                         -\n");		printf("--------------------------------\n");		printf("- Pause      On/Off : ''p''\n");		printf("- help              : ''h''\n");		printf("--------------------------------\n");		printf("\n");		break;	}}void GameMouse(float x, float y, int buttons){	mousex = x;	mousey = y;}void GameRenderStats(){	if (dbg_Pause)		ikeypressedtimer = 0;	if (ikeypressedtimer < 256)	{		unsigned int a = (255 - ikeypressedtimer);		unsigned int r = 0xFF;		unsigned int g = 0xFF;		unsigned int b = 0xFF;		unsigned int c = ((a << 24) | (r << 16) | (g << 8) | b);		int x = 2;		int y = 3;		Printf(2, y++, c, "- Mouse      [%d, %d]", (int) mousex, (int) mousey);			x = 47;		y = 3;		Printf(x, y++, c, "--------------------------------");		Printf(x, y++, c, "- Pause      On/Off : ''p''");		Printf(x, y++, c, "- help              : ''h''");		Printf(x, y++, c, "--------------------------------");		ikeypressedtimer+=8;	}}

Everything is better with Metal.

...
damn you.. I wish I was as much good as you in maths!

This code is just awesome! and you did it in 15min!

Well, I''m gonna try to understand that.. maybe it''s not so complicated after all

Thanks again

This topic is closed to new replies.

Advertisement