#define NODEBUG
/*
* This is your template code for a simple maze “game”. The player’s task
* is to drag an arrow through the maze from the red starting dot to touch
* the Blue middle square without touching the black maze walls on the way.
* The game starts when you drag across the red starting dot. The arrow you
* are dragging is red if you have not yet touched the starting dot or if
* you’ve already won or lost. It turns blue to show when the game is
* running and to indicate that your job is to get to the blue square.
* If you touch the maze walls or release your button press (this is
* to prevent cheating by skipping over walls) the arrow becomes red
* to show that you have lost the game and need to start again.
* Its NOT as easy as it seems especially if you have a laptop trackpad!!!
*
* By the way, the maze came from …
* http://commons.wikimedia.org/wiki/Image:Triple-Spiral-labyrinth.svg
* I added the blue square and red starting dot, and made the background
* greeen. The resulting ppm image files that you need are
* http://staff.psc.edu/awetzel/mymaze.ppm or a much easier one called
* http://staff.psc.edu/awetzel/easymaze.ppm
*
* Your assignment of course is to fill out this template to reimplement
* some of the things that are removed from my working version. These
* are marked in the code at the comment positions “XXX Your code here”
* The particular tasks are
* 1. test the RGB image value corresponding to the current mouse position
* 2. compute the estimated direction of current motion
* 3. “manually” rotate and position the arrow in the direction of motion
* 4. print some additional text on the screen to count redraw cycles
* 5. design a new arrow shape and make it work properly
* 6. fix the game ending with something to better distinguish a win
* 7. EXTRA CREDIT – any other SIGNIFICANT improvement of your own design
*
* The specific aims of these tasks is to 1) reinforce your understanding
* of what an image is and how its laid out in memory. 2+3) refresh your
* understanding of elementary trig which will be very important later
* 4) show you how to position and print bitmap text 5) understand 2D
* shapes and their manipulation 6+7) exercise your creativity
* Before you change anything the program should already successfully
* show the maze image but not do anything except handle the ESCape key.
*
* Please email your completed solution code to me before the next class.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#ifdef __APPLE__
#include <GLUT/glut.h>
#else
#include <GL/glut.h>
#endif
#ifndef M_PI // Microsoft forgot to put this in their math.h !
#define M_PI 3.14159265358979
#endif
void init(int argc, char **argv);
void init_glut(int argc, char **argv);
void init_gl(int argc, char **argv);
void reshape(int w, int h);
void display(void);
void keyboard(unsigned char key, int x, int y);
void mouse_buttons(int button, int state, int mousex, int mousey);
void mouse_motion(int mousex, int mousey);
int arrowx = 0, arrowy = 0;
float arrow_lastx = 0, arrow_lasty = 0; // floats to do a lagged average
int gamerunning;
int ppm_wid, ppm_ht, ppm_range;
unsigned char *pixels;
int main(int argc, char **argv) {
init(argc, argv);
init_glut(argc, argv);
init_gl(argc, argv);
glutReportErrors();
glutMainLoop();
return(0);
}
// initialize, in this case, means read the maze image file
// WARNING: this does not handle PPM header comments and other variations!!!
void init(int argc, char **argv) {
FILE *fp;
char tmptext[100], *fname = “easymaze.ppm”;
if(!(fp = fopen(fname, “rb”))) { // open binary file for read
fprintf(stderr, “ERROR: can’t open %sn”, fname);
fname = “tinymaze.ppm”;
if(!(fp = fopen(fname, “rb”))) {
fprintf(stderr, “ERROR: can’t open %sn”, fname);
exit(1);
}
}
fscanf (fp, “%[^n] “, tmptext);
fprintf(stderr, “file magic string <%s>n”, tmptext);
if(strcmp(tmptext, “P6”)) {
fprintf(stderr, “Sorry: this only does P6 == PPMn”);
exit(1);
}
fscanf (fp, “%d%d”, &ppm_wid, &ppm_ht);
fprintf(stderr, “ppm image size %d X by %d Yn”, ppm_wid, ppm_ht);
fscanf(fp, “%dn”, &ppm_range);
if(ppm_range != 255) {
fprintf(stderr, “Sorry: range %d is not allowedn”, ppm_range);
exit(1);
}
pixels = (unsigned char *)malloc(ppm_ht*ppm_wid*3);
if(!pixels) {
fprintf(stderr, “malloc failed on image size %d %dn”,
ppm_ht, ppm_wid);
exit(1);
}
fread(pixels, 1, ppm_ht*ppm_wid*3, fp);
fclose(fp);
}
void init_glut(int argc, char **argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA|GLUT_DEPTH|GLUT_DOUBLE);
glutInitWindowPosition(300, 200); // a reasonable screen XY ???
glutInitWindowSize(ppm_wid, ppm_ht); // window size same as image
//glutFullScreen(); // if you want to experiment
glutCreateWindow(“Assignment 02”);
glutDisplayFunc(display); // this does the 1st drawing
glutReshapeFunc(reshape);
glutMouseFunc(mouse_buttons); // this catches mouse buttons
glutMotionFunc(mouse_motion); // this works even if no button pressed
glutKeyboardFunc(keyboard);
}
void init_gl(int argc, char **argv) {
glClearColor(1, 1, 1, 1);
glDisable(GL_DEPTH_TEST);
glDisable(GL_LIGHTING);
glEnable(GL_COLOR_MATERIAL);
}
void reshape(int w, int h) {
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, ppm_wid, 0, ppm_ht, 1, 100);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0, 0, 10, 0, 0, 0, 0, 1, 0);
}
void keyboard(unsigned char key, int x, int y) {
switch(key) {
case 27: // escape key
exit(0);
break;
default:
fprintf(stderr, “unknown key %d at %d %dn”, key, x, y);
}
glutPostRedisplay();
}
void draw_string(float x, float y, char *s) {
glColor3f(0.0, 0.0, 0.0);
glRasterPos2f(x, y) ; // place left baseline text start position
while(*s)
glutBitmapCharacter(GLUT_BITMAP_9_BY_15, *s++);
}
int mouse_saved_button, mouse_saved_state; // useful in mouse_motion()
void mouse_buttons(int button, int state, int mousex, int mousey) {
mouse_saved_button = button;
mouse_saved_state = state;
switch(button) {
case GLUT_LEFT_BUTTON:
if(state == GLUT_DOWN) {
//fprintf(stderr, “just pressed %d %dn”, mousex, mousey); // help debug
}
if(state == GLUT_UP) {
if(gamerunning == 1) { // may change this for debug
fprintf(stderr, “No button lifting!!!n”);
gamerunning = -1; // Don’t cheat!!!
}
glutPostRedisplay();
//fprintf(stderr, “just released %d %dn”, mousex, mousey); // help debug
}
break;
}
}
void mouse_motion(int mousex, int mousey) {
int R, G, B;
unsigned char *p;
switch(mouse_saved_button) {
case GLUT_LEFT_BUTTON:
//fprintf(stderr, “%f %f %d %d %d %dn”,
//arrow_lastx, arrow_lasty, arrowx, arrowy, mousex, mousey);
arrow_lastx = 0.7 * arrow_lastx + 0.3 * arrowx;
arrow_lasty = 0.7 * arrow_lasty + 0.3 * arrowy;
arrowx = mousex;
arrowy = mousey;
if(mouse_saved_state == GLUT_DOWN) {
// 1) XXX Your code retrieve the RGB of cursor pixel.
// First make the pointer p point to the R value
// for the current pixel inside the pixels array.
// Then successively retrive the R, G, B values.
// Its about 4 lines of code.
#ifdef DEBUG
fprintf(stderr, “GLUT_DOWN at %d %d RGB %d %d %d %dn”,
mousex, mousey, R, G, B, gamerunning);
#endif
// 6) XXX Your code to make the ending more dramatic
// make the screen flash or something else in the
// following if else sections
if(R == 255) {
if(gamerunning == 0)
fprintf(stderr, “Game started!n”);
gamerunning = 1;
} else if(gamerunning == 1 && B > 10) {
fprintf(stderr, “You Won :-)n”);
gamerunning = 2;
} else if(gamerunning == 1 && G < 100) {
fprintf(stderr, “Gameover, You Lost :-(n”);
gamerunning = -1;
}
}
glutPostRedisplay(); // something moved so redisplay here
break;
}
}
// 5) XXX Your code to make a new and improved arrow shape
#define NPTS 4 // there are 4 points in this arrowhead shape
// the ashape array contains the original shape XY coordinate pairs
float ashape[NPTS][2] = { 0.0, 0.0, 24.0, -10.0, 20.0, 0, 24.0, 10.0 };
void display(void) {
char text[100]; // for holding screen print text
float rev_y, cosdir, sindir;
float rshape[NPTS][2]; // transformed coordinates for the shape
float dx, dy, hyp; // current motion and its right triangle hypotenuse
int i;
static int n_display = 0;
glPixelZoom(1, -1); // “Proper” orientation for pixel ops
glRasterPos2f(0.0, ppm_ht); // XY position to draw the maze
// now put the maze image into the frame buffer (try leaving this out)
glDrawPixels(ppm_wid, ppm_ht, GL_RGB, GL_UNSIGNED_BYTE, pixels);
// 4) XXX Your code to print a display cycle counter in lower left
// about 3 lines – look back to GLBase.c
switch(gamerunning) {
case -1:
draw_string(10.0, ppm_ht – 20.0, “You Lost :-(“);
break;
case 0:
draw_string(10.0, ppm_ht – 20.0, “Start on Red Circle”);
break;
case 1:
draw_string(10.0, ppm_ht – 20.0, “GAME Running”);
sprintf(text, “X = %3d Y = %3d”, arrowx, arrowy);
draw_string(10.0, ppm_ht – 40.0, text);
break;
case 2:
draw_string(10.0, ppm_ht – 20.0, “You Won :-)”);
break;
}
// 2) XXX Your code to compute cosdir and sindir from the values
// of the current and last arrow positions (arrowx, arrow_lastx,
// arrowy, arrow_lasty … BEWARE arrow_lastxy are floats
// you should first compute dx, dy and hyp then sindir and cosdir
// about 5 lines of code.
#ifdef DEBUG
fprintf(stderr, “%d %g %d %g %g %g %g %g %gn”,
arrowx, arrow_lastx, arrowy, arrow_lasty, dx, dy, hyp, sindir, cosdir);
#endif
rev_y = ppm_ht – arrowy – 1; // rev_y is just Y flipped
for(i = 0; i < NPTS; i++) {
// 3) XXX Your code to produce properly transformed 2D
// shape coordinates in the rshape array by using the
// current arrow position, the ashape values and the
// sindir, cosdir values you computed for item 2)
// Two to four lines depending on your spacing.
}
// Make the color coded filled arrow shape
if(gamerunning == 1)
glColor3ub(0, 0, 255);
else
glColor3ub(255, 0, 0);
glBegin(GL_POLYGON);
for(i = 0; i < NPTS; i++)
glVertex2fv(rshape[i]);
glEnd();
// It looks nicer with a black outline
glColor3ub(0, 0, 0);
glBegin(GL_LINE_LOOP);
for(i = 0; i < NPTS; i++)
glVertex2fv(rshape[i]);
glEnd();
glutSwapBuffers();
}
// 7) XXX Your extra credit code could go anywhere
Delivering a high-quality product at a reasonable price is not enough anymore.
That’s why we have developed 5 beneficial guarantees that will make your experience with our service enjoyable, easy, and safe.
You have to be 100% sure of the quality of your product to give a money-back guarantee. This describes us perfectly. Make sure that this guarantee is totally transparent.
Read moreEach paper is composed from scratch, according to your instructions. It is then checked by our plagiarism-detection software. There is no gap where plagiarism could squeeze in.
Read moreThanks to our free revisions, there is no way for you to be unsatisfied. We will work on your paper until you are completely happy with the result.
Read moreYour email is safe, as we store it according to international data protection rules. Your bank details are secure, as we use only reliable payment systems.
Read moreBy sending us your money, you buy the service we provide. Check out our terms and conditions if you prefer business talks to be laid out in official language.
Read more