<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Last Stop &#187; linux</title>
	<atom:link href="http://laststop.spaceislimited.org/tag/linux/feed/" rel="self" type="application/rss+xml" />
	<link>http://laststop.spaceislimited.org</link>
	<description>it&#039;s going to be a long ride</description>
	<lastBuildDate>Wed, 28 Jan 2009 13:21:30 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>Programming Pong in C and OpenGL &#8211; Part VI</title>
		<link>http://laststop.spaceislimited.org/2009/01/19/programming-pong-in-c-and-opengl-part-vi/</link>
		<comments>http://laststop.spaceislimited.org/2009/01/19/programming-pong-in-c-and-opengl-part-vi/#comments</comments>
		<pubDate>Mon, 19 Jan 2009 13:32:23 +0000</pubDate>
		<dc:creator>Timothy M. Rodriguez</dc:creator>
				<category><![CDATA[Technical Nonsense]]></category>
		<category><![CDATA[Tutorial]]></category>
		<category><![CDATA[c]]></category>
		<category><![CDATA[glut]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[mac]]></category>
		<category><![CDATA[mac os x]]></category>
		<category><![CDATA[opengl]]></category>
		<category><![CDATA[pong]]></category>
		<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://laststop.spaceislimited.org/?p=57</guid>
		<description><![CDATA[Here&#8217;s the last part of my multi-part series on programming your very own pong clone in c and opengl!  It&#8217;s been a long time coming, so I hope you enjoy.  There&#8217;s lots of improvements in this version including a completely custom old-style &#8220;LED Alarm Clock&#8221; scoreboard, flashes on bounce, funky changing colors, improved collision detection, [...]]]></description>
			<content:encoded><![CDATA[<div id="attachment_61" class="wp-caption aligncenter" style="width: 409px"><a href="http://laststop.spaceislimited.org/wp-content/uploads/2009/01/timgl_05.png"><img class="size-full" title="Awesome Flashy Pong!" src="http://laststop.spaceislimited.org/wp-content/uploads/2009/01/timgl_05.png" alt="The latest version of my sample clone with scoreboard, etc." width="399" height="414" /></a><p class="wp-caption-text">The latest version of my sample clone!</p></div>
<p>Here&#8217;s the last part of my multi-part series on programming your very own pong clone in c and opengl!  It&#8217;s been a long time coming, so I hope you enjoy.  There&#8217;s lots of improvements in this version including a completely custom old-style &#8220;LED Alarm Clock&#8221; scoreboard, flashes on bounce, funky changing colors, improved collision detection, and a round ball! <img src='http://laststop.spaceislimited.org/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p><span id="more-57"></span></p>
<p>Here&#8217;s the code!</p>
<pre class="brush: c">

#include &lt;stdlib.h&gt;
#include &lt;stdio.h&gt;
#include &lt;math.h&gt;

#include &lt;OpenAL/al.h&gt;
#include &lt;GLUT/glut.h&gt;

#define PADDLE_MOVE_SPEED 350
#define CLEAR_COLOR_DECAY 2.0
#define BALL_RADIUS 10
#define BALL_FACETS 60
#define START_SPEED 200

int lastFrameTime = 0, windowWidth = 0, windowHeight = 0, now = 0;
float midWidth = 0, midHeight = 0;
float elapsedTime = 0, elapsedMilliSeconds = 0;
char player1Move = 0, player2Move = 0;
float player1V = 0, player2V = 0;

float PI = 3.14159265358979323846264;

//scores
int player1Score = 0, player2Score = 0;

//the following variables calculate a random starting projectile trajectory
float randomDirection;
long longMax = 0x7fffffff;	//max of longs 2^31-1 (2^(n-1)-1 for 2&#039;s complement) float trajectory[2] = {0, 0};

float projMove[2] = {0, 0};
double trajectory[2] = {0, 0};
short moveSpeed = START_SPEED;

//glitz and glamour
float player1ColorDirection[3];
float player2ColorDirection[3];
float player1Color[3];
float player2Color[3];
float colorMoveSpeed = 2.0;
double vectorLength1 = 0;
double vectorLength2 = 0;

float ballColorDirection[3];
float ballColor[3];
double ballVectorLength = 0;

//background explosion color
float clearColor[3];

int i = 0;

//scoreboard
char player1Num1[7] = {1, 1, 1, 0, 1, 1, 1};	//digital display set to zero, (each segment is enabled or disabled)
char player1Num2[7] = {1, 1, 1, 0, 1, 1, 1};
char player2Num1[7] = {1, 1, 1, 0, 1, 1, 1};	//digital display set to zero, (each segment is enabled or disabled)
char player2Num2[7] = {1, 1, 1, 0, 1, 1, 1};

//digit representations
char digit0[7] = {1, 1, 1, 0, 1, 1, 1};
char digit1[7] = {0, 0, 1, 0, 0, 0, 1};
char digit2[7] = {0, 1, 1, 1, 1, 1, 0};
char digit3[7] = {0, 1, 1, 1, 0, 1, 1};
char digit4[7] = {1, 0, 1, 1, 0, 0, 1};
char digit5[7] = {1, 1, 0, 1, 0, 1, 1};
char digit6[7] = {1, 1, 0, 1, 1, 1, 1};
char digit7[7] = {0, 1, 1, 0, 0, 0, 1};
char digit8[7] = {1, 1, 1, 1, 1, 1, 1};
char digit9[7] = {1, 1, 1, 1, 0, 1, 1};

void setSpaceEffect(void) {
for (i=0; i &lt; 3; i++) {
player1ColorDirection[i] = (float) random() / (float) 0x7fffffff; //random vector
player2ColorDirection[i] = (float) random() / (float) 0x7fffffff;
ballColorDirection[i] = (float) random() / (float) 0x7fffffff;
}
//figure out vector lenngth
for (i=0; i &lt; 3; i++) {
vectorLength1 += player1ColorDirection[i] * player1ColorDirection[i];
vectorLength2 += player2ColorDirection[i] * player2ColorDirection[i];
ballVectorLength += ballColorDirection[i] * ballColorDirection[i];
}
sqrt(vectorLength1);
sqrt(vectorLength2);
sqrt(ballVectorLength);
//normalize vector
for (i=0; i &lt; 3; i++) {
player1ColorDirection[i] /= vectorLength1;
player2ColorDirection[i] /= vectorLength2;
ballColorDirection[i] /= ballVectorLength;
}
}

void calculateColor(float color[3], float colorDirection[3]) {
//caculate the next color based on the direction and elapsed time values
for (i=0; i &lt; 3; i++) {
color[i] += colorDirection[i] * colorMoveSpeed * elapsedTime;
if (color[i] &gt; 1) {
color[i] = 1;
colorDirection[i] *= -1;
}
else if (color[i] &lt; 0) {
color[i] = 0;
colorDirection[i] *= -1;
}
}
}

void calculateClearColor(float color[3]) {
for (i=0; i &lt; 3; i++) {
color[i] -= CLEAR_COLOR_DECAY * elapsedTime;
if(color[i] &lt; 0)
color[i] = 0;
}
}

void setClearColor(float color[3]) {
for (i=0; i &lt; 3; i++) {
color[i] = 1.0;
}
}

void resetProjectile(void) {
//set starting random trajectory
randomDirection = 2 * PI * (float) random() / (float) 0x7fffffff;
trajectory[0] = (float) cos(randomDirection);
trajectory[1] = (float) sin(randomDirection);
projMove[0] = midWidth;
projMove[1] = midHeight;
}

/*draw a digital (a la clock style) digit some place specified by x and y
*the enabled array is which segments of the display are enabled (counted starting from top left in a snake/8 fasion)
*
* 1 -
* 0| |2
* 3 -
* 4| |6
* 5 -
*/
void drawDigit(char enabled[7], float x, float y) {
glPushMatrix();
glTranslatef(x, y, 0);	//position digit to be drawn
//draw digital number (a la digital clock) segment by segment
glColor3f(1.0, 1.0, 1.0);
//draw segment 5
if(enabled[5]) {
glBegin(GL_QUADS);
glVertex2f(0,0);
glVertex2f(10,0);
glVertex2f(10,2);
glVertex2f(0,2);
glEnd();
}

//draw segment 3
if(enabled[3]) {
glBegin(GL_QUADS);
glVertex2f(0,9);
glVertex2f(10,9);
glVertex2f(10,11);
glVertex2f(0,11);
glEnd();
}

//draw segment 1
if(enabled[1]) {
glBegin(GL_QUADS);
glVertex2f(0,18);
glVertex2f(10,18);
glVertex2f(10,20);
glVertex2f(0,20);
glEnd();
}

//draw segment 4
if(enabled[4]) {
glBegin(GL_QUADS);
glVertex2f(0,2);
glVertex2f(2,2);
glVertex2f(2,9);
glVertex2f(0,9);
glEnd();
}

//draw segment 0
if(enabled[0]) {
glBegin(GL_QUADS);
glVertex2f(0,11);
glVertex2f(2,11);
glVertex2f(2,20);
glVertex2f(0,20);
glEnd();
}

//draw segment 6
if(enabled[6]) {
glBegin(GL_QUADS);
glVertex2f(8,2);
glVertex2f(10,2);
glVertex2f(10,9);
glVertex2f(8,9);
glEnd();
}

//draw segment 2
if(enabled[2]) {
glBegin(GL_QUADS);
glVertex2f(8,11);
glVertex2f(10,11);
glVertex2f(10,20);
glVertex2f(8,20);
glEnd();
}

glPopMatrix();
}

void setDigitEnablePattern(char enabled[7], char digit) {

switch(digit) {
case 0:
for(i=0; i&lt;7; i++) {
enabled[i] = digit0[i];
}
break;
case 1:
for(i=0; i&lt;7; i++) {
enabled[i] = digit1[i];
}
break;
case 2:
for(i=0; i&lt;7; i++) {
enabled[i] = digit2[i];
}
break;
case 3:
for(i=0; i&lt;7; i++) {
enabled[i] = digit3[i];
}
break;
case 4:
for(i=0; i&lt;7; i++) {
enabled[i] = digit4[i];
}
break;
case 5:
for(i=0; i&lt;7; i++) {
enabled[i] = digit5[i];
}
break;
case 6:
for(i=0; i&lt;7; i++) {
enabled[i] = digit6[i];
}
break;
case 7:
for(i=0; i&lt;7; i++) {
enabled[i] = digit7[i];
}
break;
case 8:
for(i=0; i&lt;7; i++) {
enabled[i] = digit8[i];
}
break;
case 9:
for(i=0; i&lt;7; i++) {
enabled[i] = digit9[i];
}
break;
}
}

void drawScore(char player1, char player2) {

if(player1 &lt; 10) {
setDigitEnablePattern(player1Num1, 0);
setDigitEnablePattern(player1Num2, player1);
}
else if (player1 &lt; 100) {
setDigitEnablePattern(player1Num1, player1 / 10);
setDigitEnablePattern(player1Num2, player1 - ((player1/10) * 10));
}
else {	//max out at 99
setDigitEnablePattern(player1Num1, 9);
setDigitEnablePattern(player1Num2, 9);
}

if(player2 &lt; 10) {
setDigitEnablePattern(player2Num1, 0);
setDigitEnablePattern(player2Num2, player2);
}
else if (player2 &lt; 100) {
setDigitEnablePattern(player2Num1, player2 / 10);
setDigitEnablePattern(player2Num2, player2 - ((player2/10) * 10));
}
else {	//max out at 99
setDigitEnablePattern(player2Num1, 9);
setDigitEnablePattern(player2Num2, 9);
}

drawDigit(player1Num1, (windowWidth/4)-15, 20);
drawDigit(player1Num2, (windowWidth/4)+5, 20);
drawDigit(player2Num1, ((windowWidth/4)*3)-15, 20);
drawDigit(player2Num2, ((windowWidth/4)*3)+5, 20);

}

void display(void)
{
//get window parameters
windowWidth = glutGet(GLUT_WINDOW_WIDTH);
windowHeight = glutGet(GLUT_WINDOW_HEIGHT);

midWidth = windowWidth/2;
midHeight = windowHeight/2;

//start timing code
if (lastFrameTime == 0) {
lastFrameTime = glutGet(GLUT_ELAPSED_TIME);
resetProjectile();	//since this is the fist time, this is actually a set <img src='http://laststop.spaceislimited.org/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' />
player1V = midHeight;
player2V = midHeight;
//initialize the space effect colors
setSpaceEffect();
glClearColor(0.0, 0.0, 0.0, 0.0);	//set clear color to black
}

now = glutGet(GLUT_ELAPSED_TIME);
elapsedMilliSeconds = now - lastFrameTime;
elapsedTime = elapsedMilliSeconds/1000.0f;
lastFrameTime = now;

calculateClearColor(clearColor);
glClearColor(clearColor[0], clearColor[1], clearColor[2], 0.0);
glClear(GL_COLOR_BUFFER_BIT);
glShadeModel(GL_FLAT);

//draw score
drawScore(player1Score, player2Score);

//calculate move distances
switch (player1Move) {
case 1:		//move up
player1V += PADDLE_MOVE_SPEED * elapsedTime;
break;
case -1:	//move up
player1V -= PADDLE_MOVE_SPEED * elapsedTime;
break;
default:	//do nothing
break;
}
//check out of bounds
if (player1V &gt; windowHeight-50) {
//bounce back
player1Move = -1;
}
if (player1V &lt; 0+50) {
//bounce back other way
player1Move = 1;
}

switch (player2Move) {
case 1:		//move up
player2V += PADDLE_MOVE_SPEED * elapsedTime;
break;
case -1:	//move up
player2V -= PADDLE_MOVE_SPEED * elapsedTime;
break;
default:	//do nothing
break;
}
//check out of bounds
if (player2V &gt; windowHeight-50) {
//bounce back
player2Move = -1;
}
if (player2V &lt; 0+50) {
//bounce back other way
player2Move = 1;
}

//create and position player 1
glPushMatrix();

calculateColor(player1Color, player1ColorDirection);
glColor3f(player1Color[0], player1Color[1], player1Color[2]);	//player 1 color

glTranslatef(30.0f, player1V, 0.0f);

glBegin(GL_QUADS);
glVertex2f(-10, -50);
glVertex2f(-10, 50);
glVertex2f(10, 50);
glVertex2f(10, -50);
glEnd();

glPopMatrix();

//create and position player 2
glPushMatrix();

calculateColor(player2Color, player2ColorDirection);
glColor3f(player2Color[0], player2Color[1], player2Color[2]);	//player 2 color

glTranslatef(windowWidth-30, player2V, 0.0f);

glBegin(GL_QUADS);
glVertex2f(-10, -50);
glVertex2f(-10, 50);
glVertex2f(10, 50);
glVertex2f(10, -50);
glEnd();

glPopMatrix();

/***************************************
*	Projectile CODE!!!
*
***************************************/

//calculate move distances
projMove[0] += moveSpeed * trajectory[0] * elapsedTime;
projMove[1] += moveSpeed * trajectory[1] * elapsedTime;

//create and move projectile
glPushMatrix();

calculateColor(ballColor, ballColorDirection);
glColor3f(ballColor[0], ballColor[1], ballColor[2]);	//player 1 color

glTranslatef(projMove[0], projMove[1], 0.0f);

glBegin(GL_TRIANGLE_FAN);
for(i=0; i &lt; 360; i += 360 / BALL_FACETS) {
glVertex2f(sin(i * PI / 180) * BALL_RADIUS, cos(i * PI / 180) * BALL_RADIUS);
}
glEnd();

glPopMatrix();

//set bounds for projectile
if (projMove[0] &gt; (windowWidth)) {	//player 1 scored - out of bounds right
player1Score++;
moveSpeed = START_SPEED;
printf(&quot;Player 1 Scored!  Score: %f &quot;, player1Score);
resetProjectile();
}

else if (projMove[0] &lt; (0)) {		//player 2 scored - out of bounds left
player2Score++;
moveSpeed = START_SPEED;
resetProjectile();
}

else if (projMove[1] &gt; (windowHeight-10)) {	//out of bounds top
trajectory[1] *= -1;
projMove[1] -= 0.5;
}

else if (projMove[1] &lt; (10)) {	//out of bounds bottom
trajectory[1] *= -1;
projMove[1] += 0.5;
}

//collision detection code
else if (projMove[0] &lt; 50 &amp;amp;amp;amp;amp;amp;amp;amp;&amp;amp;amp;amp;amp;amp;amp;amp; projMove[0] &gt; 49) {		//intersecting with line of left paddle
if (projMove[1] &lt;= player1V + 50 &amp;amp;amp;amp;amp;amp;amp;amp;&amp;amp;amp;amp;amp;amp;amp;amp; projMove[1] &gt;= player1V-50) {
trajectory[0] *= -1;
moveSpeed += 30;
setClearColor(clearColor);
projMove[0] += 0.5;
}
}

else if (projMove[0] &gt; windowWidth-50 &amp;amp;amp;amp;amp;amp;amp;amp;&amp;amp;amp;amp;amp;amp;amp;amp; projMove[0] &lt; windowWidth-49) {		//intersecting with line of right paddle
if (projMove[1] &lt;= player2V + 50 &amp;amp;amp;amp;amp;amp;amp;amp;&amp;amp;amp;amp;amp;amp;amp;amp; projMove[1] &gt;= player2V-50) {
trajectory[0] *= -1;
moveSpeed += 30;
setClearColor(clearColor);
projMove[0] -= 0.5;
}
}

/******************************
*  END PROJECTILE CODE
*
******************************/

glutSwapBuffers();

}

void reshape(int width, int height)
{
glViewport(0, 0, width, height);

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0, width, 0, height);
glMatrixMode(GL_MODELVIEW);
}

void idle(void)
{
glutPostRedisplay();
}

void keyboard(unsigned char key, int x, int y) {
switch (key) {
case &#039;w&#039;:
//do something
player1Move=1;
glutPostRedisplay();
break;
case &#039;s&#039;:
//do something
player1Move=-1;
glutPostRedisplay();
break;
case &#039;o&#039;:
//do something
player2Move=1;
glutPostRedisplay();
break;
case &#039;l&#039;:
//do something
player2Move=-1;
glutPostRedisplay();
break;
default:
//some other key
break;
}

}

void keyboardup(unsigned char key, int x, int y) {
switch (key) {
case &#039;w&#039;:
//do something
player1Move=0;
glutPostRedisplay();
break;
case &#039;s&#039;:
player1Move=0;
glutPostRedisplay();
break;
case &#039;o&#039;:
player2Move=0;
glutPostRedisplay();
break;
case &#039;l&#039;:
player2Move=0;
glutPostRedisplay();
break;
default:
//some other key
break;
}

}

int main(int argc, char** argv)
{
glutInit(&amp;amp;amp;amp;amp;amp;amp;amp;argc, argv);

glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
glutInitWindowSize(500, 500);

glutCreateWindow(&quot;Tim GL&quot;);

glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutKeyboardFunc(keyboard);
glutKeyboardUpFunc(keyboardup);
glutIdleFunc(idle);

glutMainLoop();
return EXIT_SUCCESS;
}
</pre>
<p>I delayed so long because I wanted to refactor this code to better separate components and functions, but I didn&#8217;t get the time to do so.  (That&#8217;s why I should do it that way from the start!)  You can get a direct copy of the binary <a title="TimGL 0.5!" href="/downloads/TimGL_0.5.zip">here</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://laststop.spaceislimited.org/2009/01/19/programming-pong-in-c-and-opengl-part-vi/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Programming Pong in C and OpenGL &#8211; Part II</title>
		<link>http://laststop.spaceislimited.org/2008/06/02/programming-pong-in-c-and-opengl-part-ii/</link>
		<comments>http://laststop.spaceislimited.org/2008/06/02/programming-pong-in-c-and-opengl-part-ii/#comments</comments>
		<pubDate>Tue, 03 Jun 2008 01:50:22 +0000</pubDate>
		<dc:creator>Timothy M. Rodriguez</dc:creator>
				<category><![CDATA[Tutorial]]></category>
		<category><![CDATA[animation]]></category>
		<category><![CDATA[c]]></category>
		<category><![CDATA[game]]></category>
		<category><![CDATA[game programming]]></category>
		<category><![CDATA[glut]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[loop]]></category>
		<category><![CDATA[mac]]></category>
		<category><![CDATA[opengl]]></category>
		<category><![CDATA[os x]]></category>
		<category><![CDATA[pong]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[This]]></category>
		<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://laststop.spaceislimited.org/?p=17</guid>
		<description><![CDATA[This is the second part in what should be a four part series on how to program your very own Pong clone. The first article went over setting up your environment in your favorite OS, now this part gets into some of the mechanics or details on how to actually get started. Before I start [...]]]></description>
			<content:encoded><![CDATA[<p>This is the second part in what should be a four part series on how to program your very own Pong clone.  The first article went over setting up your environment in your favorite OS, now this part gets into some of the mechanics or details on how to actually get started.</p>
<p>Before I start with anything, we have to think about simple animation.  In fact, <a title="Animation" href="http://en.wikipedia.org/wiki/Animation" target="_blank">animation</a> is just simply a series of static images, with each image slightly displaced from the last.</p>
<p>So what does that mean?<span id="more-17"></span></p>
<p>For example, if I&#8217;m going to <span style="text-decoration: line-through;">draw</span> animate a ball falling from mid-air, I would first start with an image of the ball in mid-air, precisely as it would look the moment it began to fall.  The next <em>frame</em>, or image, would be exactly that, but with the ball a little bit lower down.  I would then continue to draw sequential images of the ball, with each image showing it a little bit further than the last.  This is how <strong>every</strong> moving image you see works (well, just about).  A series of images is drawn in front of you, quick enough that you can&#8217;t tell.</p>
<p>So the next question is, what&#8217;s quick enough?  It turns out, this isn&#8217;t such a simple question.  In fact, the answer is different for different animals!  But for humans, it turns out, about 30fps, or 30 frames-per-second, is what it takes to fool us.  The movies you see in the theatre are (at-the-moment anyways) displayed at 24fps, but most computer screens require 60fps to prevent you from seeing the flicker (some, like myself, need an 85Hz (fps) refresh rate, others up to 120!).  The reasons for these differences has a lot to do with the way the image is drawn and the way your eye views things.  It&#8217;s a pretty involved topic, but if you guys would like me to go into it more, let me know in the comments.</p>
<h3>A Simple Animation Loop</h3>
<p>Taking what we just learned, let&#8217;s think about how to draw a box moving across the screen.  Let&#8217;s pretend we have a function that draws a box centered at a point we specify on the screen (in 2-D Space).  It&#8217;s C function prototype would look something like this:</p>
<blockquote><p>void drawbox(int x, int y);</p></blockquote>
<p>So if we were going to draw a box that just infinitely moved to the right (or at least until it was off screen).  We might decide to create a loop that drew it a little bit further each time.  That might look something like this:</p>
<blockquote><p>#define TRUE 1</p>
<p>int x=0;</p>
<p>while(TRUE) {</p>
<p>drawbox(0+x, 0);</p>
<p>x++;</p>
<p>}</p></blockquote>
<p>This little snippet of code, runs an infinite loop and draws a box at a point 0+x, 0 and then increments x.  Let&#8217;s look a little further.  First it draws a box at point(0,0) since x is 0 on first count.  Then x is incremented and the loop goes on again.  Next, it draws a box at (1,0) and increments x.  And so on.  Congratulations, you just made your first animation loop!</p>
<h3>Marching Onward</h3>
<p>In the beginning, video games were hand-coded in assembly directly to a particular hardware.  This had a lot of benefits, primarily speed, which was very important when hardware was relatively expensive.  But as computers progressed and the market expanded, it became necessary to program for a multitude of different hardwares.  And this is when a nasty problem reared it&#8217;s head.  You see, when you decide to have the computer draw something on the screen, it doesn&#8217;t just do it instantaneously.  The computer has to go and draw each individual pixel on the screen (also a topic for another discussion).</p>
<p>This</p>
<p style="padding-left: 30px;">takes</p>
<p style="padding-left: 60px;">time.</p>
<p>Moreover, the time it takes on your brand-spanking new ultra-super processor is not the same time it takes your friend down the street who isn&#8217;t as <em>enthusiastic</em> as you are.  This is a problem, because if you set up all your animations expecting the processor to draw 30 frames per second on your machine.  It&#8217;s going to run at less than that on your friends machine.  (In fact, there&#8217;s some math that shows it will be a fraction/multiple of their refresh rate).  Great, so your fast-action shoot-em-up just got stuck in the mud.</p>
<h3>What&#8217;s a game programmer to do?</h3>
<p>There&#8217;s a really simple answer to all of this&#8211;use our friend (archenemy) time.  You see, rather than making your animation speed depend on the animation loop (which depends on your processor speed), have the your animation be a fixed function of time.</p>
<p>Take another look at our first example.  The movement speed of the box can really be expressed as 1 unit in the x direction per loop iteration.  Really what we want is for the box to move some number of units in the x direction per second (our hour if you like).  To do this we need to express our box movement as a function of time and then know how long its been since the computer last drew the box.  Essentially, we want our animation loop to look like this.</p>
<blockquote><p>#define TRUE 1</p>
<p>int speed = 1;     //1 unit per second</p>
<p>int x = 0;</p>
<p>startTime = 0;</p>
<p>elapsedTime = 0;</p>
<p>while(TRUE) {</p>
<p>startTime = getTime();</p>
<p>x += speed * elapsedTime;</p>
<p>drawbox(0+x, 0)</p>
<p>elapsedTime = getTime() &#8211; startTime;</p>
<p>}</p></blockquote>
<p>As you can see, this simple example becomes a lot more complicated once we add timing to the mix.  First, we defined a universal speed for our box.  We still kept the x value, as this represents the boxes point in space, not it&#8217;s speed.  Then we created variables for keep track when we started our animation loop and how long we were in it.  We&#8217;re also assuming we have a function that gives us the time, called getTime() here, and that it returns us the current time in seconds.</p>
<p>First we enter our loop and fetch our start time from the getTime() function.  Next we set our x position based on how long it&#8217;s been since our last loop.  We multiply our elapsedTime by the speed of our box and add that <em>distance</em> to our x-position.  Then, we draw our box at it&#8217;s new position.  Finally, we figure out how long it took us to draw that box by setting our elapsed time equal to the current time minus the time we started drawing the box.  Now, no matter the computer, our box will move along the screen at the same speed.  Note, this does not mean the animation is fluid!  If your friend&#8217;s computer is really slow (and I mean really if it can&#8217;t draw a box) it may only get to draw a box once every 5 seconds.  By then, our box may already be off the screen!</p>
<p>So I hope that&#8217;s enough for you to digest for a while. Stay tuned for my next post on some of the basic mechanics of GLUT and OpenGL.  Until then, it might be useful to brush up on your C programming on the interwebs!</p>
]]></content:encoded>
			<wfw:commentRss>http://laststop.spaceislimited.org/2008/06/02/programming-pong-in-c-and-opengl-part-ii/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Programming Pong in C and OpenGL &#8211; Part I</title>
		<link>http://laststop.spaceislimited.org/2008/05/17/programming-a-pong-clone-in-c-and-opengl-part-i/</link>
		<comments>http://laststop.spaceislimited.org/2008/05/17/programming-a-pong-clone-in-c-and-opengl-part-i/#comments</comments>
		<pubDate>Sun, 18 May 2008 00:48:35 +0000</pubDate>
		<dc:creator>Timothy M. Rodriguez</dc:creator>
				<category><![CDATA[Tutorial]]></category>
		<category><![CDATA[c]]></category>
		<category><![CDATA[game]]></category>
		<category><![CDATA[glut]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[mac]]></category>
		<category><![CDATA[opengl]]></category>
		<category><![CDATA[os x]]></category>
		<category><![CDATA[pong]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://laststop.spaceislimited.org/?p=13</guid>
		<description><![CDATA[If you ever wanted to program your own video game, this is a good place to start. I remember when I started learning programming it was surprisingly difficult to find out how to make an honest and simple game. In fact, after reading most programming books, the only type of game you could make would [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://laststop.spaceislimited.org/wp-content/uploads/2008/05/pongactionshot.png"><img class="aligncenter size-full wp-image-14" title="Pong" src="http://laststop.spaceislimited.org/wp-content/uploads/2008/05/pongactionshot.png" alt="Unbelievable Action!" width="499" height="518" /></a></p>
<p>If you ever wanted to program your own video game, this is a good place to start.  I remember when I started learning programming it was surprisingly difficult to find out how to make an honest and simple game.  In fact, after reading most programming books, the only type of game you could make would be a <a href="http://en.wikipedia.org/wiki/Zork">Zork</a> clone.</p>
<blockquote><p>You are in a dank cave and you can see nothing, but you hear a walrus in the distance.</p>
<p>What do you do?</p>
<ol>
<li>Look for the walrus.</li>
<li>Watch <a href="http://www.imdb.com/title/tt0118715/">The Big Lebowski</a></li>
<li>Decide that the walrus is Paul.</li>
</ol>
</blockquote>
<p>This is not to knock Zork in any way!  Zork is a clever, well written, and extremely well thought out game (even if my pseudo-quote isn&#8217;t).  But in a world where we&#8217;re spoiled by moving objects, you want to know how to move and interact with something on screen.  The problem is it takes a lot of different knowledge sets to get the job done.  But in this post, you&#8217;ll get started learning how to make your very own <a title="Pong" href="http://http//en.wikipedia.org/wiki/Pong" target="_blank">Pong</a> clone.<span id="more-13"></span></p>
<h3>A Few Notes..</h3>
<p>First, a few notes about setting up.  I&#8217;m writing this tutorial from the Mac OS X perspective.  However, everything we are about to code is, essentially, <strong>cross-platform</strong>.  This is because, it is written using plaing old C, OpenGL, and GLUT.  All of these things are themselves cross-platform, and therefore, can be compiled anywhere you have a C compiler (OpenGL and GLUT are just C libraries).</p>
<h3>Setting up your environment</h3>
<h4>Mac OS X</h4>
<p>For some reason, this always seems to be the hardest part whenever learning something new in programming.  Fortunately, I found a great blog post that makes setting up XCode for compiling an app using OpenGL and GLUT very easy.  Read all about setting up your <a title="XCode with OpenGL and GLUT" href="http://blog.onesadcookie.com/2007/12/xcodeglut-tutorial.html" target="_blank">XCode</a>.</p>
<h4>Windows</h4>
<p>The process in Windows is actually a bit easier (gasp!) than in Mac OS X and there&#8217;s plenty of resources available on Google for getting setup.  Here&#8217;s one in <a title="Setting up OpenGL and GLUT in Windows" href="http://csf11.acs.uwosh.edu/cs371/visualstudio/" target="_blank">particular</a>.</p>
<h4>Linux</h4>
<p>Here&#8217;s something unusual, you guys get a <a title="OpenGL and GLUT in Linux" href="http://www.youtube.com/watch?v=p4hA-lcKTmE" target="_blank">video</a>.</p>
<p>Congratulations, the hardest part is done!  In my next blog post.  We&#8217;ll start to get knee deep in game programming concepts.</p>
<h2>Update!</h2>
<p><a title="Programming a Pong Clone - Part II" href="http://laststop.spaceislimited.org/2008/06/02/programming-pong-in-c-and-opengl-part-ii/" target="_self">Part II</a> is Up!</p>
]]></content:encoded>
			<wfw:commentRss>http://laststop.spaceislimited.org/2008/05/17/programming-a-pong-clone-in-c-and-opengl-part-i/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
