|
@@ -26,7 +26,7 @@ Note: the -L option and -lstdc++ may not be needed on some machines.
|
|
|
#include <X11/Xutil.h>
|
|
|
|
|
|
using namespace std;
|
|
|
-
|
|
|
+
|
|
|
/*
|
|
|
* Global game state variables
|
|
|
*/
|
|
@@ -39,80 +39,99 @@ const int height = 600;
|
|
|
/*
|
|
|
* Information to draw on the window.
|
|
|
*/
|
|
|
-struct XInfo {
|
|
|
- Display *display;
|
|
|
- int screen;
|
|
|
- Window window;
|
|
|
- GC gc[3];
|
|
|
- int width; // size of window
|
|
|
- int height;
|
|
|
-};
|
|
|
+typedef struct XInfo
|
|
|
+{
|
|
|
+ Display * display;
|
|
|
+ int screen;
|
|
|
+ Window window;
|
|
|
+ GC gc[3];
|
|
|
+ int width; // size of window
|
|
|
+ int height;
|
|
|
+} Xinfo;
|
|
|
|
|
|
|
|
|
/*
|
|
|
* Function to put out a message on error exits.
|
|
|
*/
|
|
|
-void error( string str ) {
|
|
|
+void error(string str)
|
|
|
+{
|
|
|
cerr << str << endl;
|
|
|
exit(0);
|
|
|
}
|
|
|
|
|
|
|
|
|
/*
|
|
|
- * An abstract class representing displayable things.
|
|
|
+ * An abstract class representing displayable things.
|
|
|
*/
|
|
|
-class Displayable {
|
|
|
+class Displayable
|
|
|
+{
|
|
|
public:
|
|
|
- virtual void paint(XInfo &xinfo) = 0;
|
|
|
-};
|
|
|
+ virtual void paint(XInfo & xinfo) = 0;
|
|
|
+};
|
|
|
|
|
|
-class Snake : public Displayable {
|
|
|
+class Snake : public Displayable
|
|
|
+{
|
|
|
public:
|
|
|
- virtual void paint(XInfo &xinfo) {
|
|
|
+ virtual void paint(XInfo & xinfo)
|
|
|
+ {
|
|
|
XFillRectangle(xinfo.display, xinfo.window, xinfo.gc[0], x, y, 25, blockSize);
|
|
|
}
|
|
|
-
|
|
|
- void move(XInfo &xinfo) {
|
|
|
+
|
|
|
+ void move(XInfo &xinfo)
|
|
|
+ {
|
|
|
x = x + direction;
|
|
|
- if (x < 0 || x > width) {
|
|
|
+
|
|
|
+ if (x < 0 || x > width)
|
|
|
+ {
|
|
|
direction = -direction;
|
|
|
}
|
|
|
|
|
|
// ** ADD YOUR LOGIC **
|
|
|
- // Here, you will be performing collision detection between the snake,
|
|
|
+ // Here, you will be performing collision detection between the snake,
|
|
|
// the fruit, and the obstacles depending on what the snake lands on.
|
|
|
}
|
|
|
-
|
|
|
- int getX() {
|
|
|
+
|
|
|
+ int getX()
|
|
|
+ {
|
|
|
return x;
|
|
|
}
|
|
|
-
|
|
|
- int getY() {
|
|
|
+
|
|
|
+ int getY()
|
|
|
+ {
|
|
|
return y;
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
* ** ADD YOUR LOGIC **
|
|
|
- * Use these placeholder methods as guidance for implementing the snake behaviour.
|
|
|
+ * Use these placeholder methods as guidance for implementing the snake behaviour.
|
|
|
* You do not have to use these methods, feel free to implement your own.
|
|
|
- */
|
|
|
- void didEatFruit() {
|
|
|
+ */
|
|
|
+ void didEatFruit()
|
|
|
+ {
|
|
|
+
|
|
|
}
|
|
|
|
|
|
- void didHitObstacle() {
|
|
|
+ void didHitObstacle()
|
|
|
+ {
|
|
|
+
|
|
|
}
|
|
|
|
|
|
- void turnLeft() {
|
|
|
+ void turnLeft()
|
|
|
+ {
|
|
|
+
|
|
|
}
|
|
|
|
|
|
- void turnRight() {
|
|
|
+ void turnRight()
|
|
|
+ {
|
|
|
+
|
|
|
}
|
|
|
-
|
|
|
- Snake(int x, int y): x(x), y(y) {
|
|
|
+
|
|
|
+ Snake(int x, int y): x(x), y(y)
|
|
|
+ {
|
|
|
direction = 5;
|
|
|
- blockSize = 10;
|
|
|
+ blockSize = 10;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
private:
|
|
|
int x;
|
|
|
int y;
|
|
@@ -120,15 +139,18 @@ class Snake : public Displayable {
|
|
|
int direction;
|
|
|
};
|
|
|
|
|
|
-class Fruit : public Displayable {
|
|
|
+class Fruit : public Displayable
|
|
|
+{
|
|
|
public:
|
|
|
- virtual void paint(XInfo &xinfo) {
|
|
|
+ virtual void paint(XInfo & xinfo)
|
|
|
+ {
|
|
|
XFillRectangle(xinfo.display, xinfo.window, xinfo.gc[0], x, y, 10, 10);
|
|
|
- }
|
|
|
+ }
|
|
|
|
|
|
- Fruit() {
|
|
|
+ Fruit()
|
|
|
+ {
|
|
|
// ** ADD YOUR LOGIC **
|
|
|
- // generate the x and y value for the fruit
|
|
|
+ // generate the x and y value for the fruit
|
|
|
x = 50;
|
|
|
y = 50;
|
|
|
}
|
|
@@ -152,26 +174,28 @@ Fruit fruit;
|
|
|
/*
|
|
|
* Initialize X and create a window
|
|
|
*/
|
|
|
-void initX(int argc, char *argv[], XInfo &xInfo) {
|
|
|
+void initX(int argc, char * argv[], XInfo & xInfo)
|
|
|
+{
|
|
|
XSizeHints hints;
|
|
|
unsigned long white, black;
|
|
|
|
|
|
/*
|
|
|
* Display opening uses the DISPLAY environment variable.
|
|
|
* It can go wrong if DISPLAY isn't set, or you don't have permission.
|
|
|
- */
|
|
|
- xInfo.display = XOpenDisplay( "" );
|
|
|
- if ( !xInfo.display ) {
|
|
|
- error( "Can't open display." );
|
|
|
+ */
|
|
|
+ xInfo.display = XOpenDisplay("");
|
|
|
+ if (!xInfo.display)
|
|
|
+ {
|
|
|
+ error("Can't open display.");
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
/*
|
|
|
* Find out some things about the display you're using.
|
|
|
*/
|
|
|
- xInfo.screen = DefaultScreen( xInfo.display );
|
|
|
+ xInfo.screen = DefaultScreen(xInfo.display);
|
|
|
|
|
|
- white = XWhitePixel( xInfo.display, xInfo.screen );
|
|
|
- black = XBlackPixel( xInfo.display, xInfo.screen );
|
|
|
+ white = XWhitePixel(xInfo.display, xInfo.screen);
|
|
|
+ black = XBlackPixel(xInfo.display, xInfo.screen);
|
|
|
|
|
|
hints.x = 100;
|
|
|
hints.y = 100;
|
|
@@ -179,25 +203,29 @@ void initX(int argc, char *argv[], XInfo &xInfo) {
|
|
|
hints.height = 600;
|
|
|
hints.flags = PPosition | PSize;
|
|
|
|
|
|
- xInfo.window = XCreateSimpleWindow(
|
|
|
+ xInfo.window = XCreateSimpleWindow
|
|
|
+ (
|
|
|
xInfo.display, // display where window appears
|
|
|
DefaultRootWindow( xInfo.display ), // window's parent in window tree
|
|
|
hints.x, hints.y, // upper left corner location
|
|
|
hints.width, hints.height, // size of the window
|
|
|
Border, // width of window's border
|
|
|
black, // window border colour
|
|
|
- white ); // window background colour
|
|
|
-
|
|
|
- XSetStandardProperties(
|
|
|
+ white
|
|
|
+ ); // window background colour
|
|
|
+
|
|
|
+ XSetStandardProperties
|
|
|
+ (
|
|
|
xInfo.display, // display containing the window
|
|
|
xInfo.window, // window whose properties are set
|
|
|
"animation", // window's title
|
|
|
"Animate", // icon's title
|
|
|
None, // pixmap for the icon
|
|
|
argv, argc, // applications command line args
|
|
|
- &hints ); // size hints for the window
|
|
|
+ &hints
|
|
|
+ ); // size hints for the window
|
|
|
|
|
|
- /*
|
|
|
+ /*
|
|
|
* Create Graphics Contexts
|
|
|
*/
|
|
|
int i = 0;
|
|
@@ -208,9 +236,9 @@ void initX(int argc, char *argv[], XInfo &xInfo) {
|
|
|
XSetLineAttributes(xInfo.display, xInfo.gc[i],
|
|
|
1, LineSolid, CapButt, JoinRound);
|
|
|
|
|
|
- XSelectInput(xInfo.display, xInfo.window,
|
|
|
- ButtonPressMask | KeyPressMask |
|
|
|
- PointerMotionMask |
|
|
|
+ XSelectInput(xInfo.display, xInfo.window,
|
|
|
+ ButtonPressMask | KeyPressMask |
|
|
|
+ PointerMotionMask |
|
|
|
EnterWindowMask | LeaveWindowMask |
|
|
|
StructureNotifyMask); // for resize events
|
|
|
|
|
@@ -224,12 +252,13 @@ void initX(int argc, char *argv[], XInfo &xInfo) {
|
|
|
/*
|
|
|
* Function to repaint a display list
|
|
|
*/
|
|
|
-void repaint( XInfo &xinfo) {
|
|
|
+void repaint( XInfo &xinfo)
|
|
|
+{
|
|
|
list<Displayable *>::const_iterator begin = dList.begin();
|
|
|
list<Displayable *>::const_iterator end = dList.end();
|
|
|
|
|
|
XClearWindow( xinfo.display, xinfo.window );
|
|
|
-
|
|
|
+
|
|
|
// get height and width of window (might have changed since last repaint)
|
|
|
|
|
|
XWindowAttributes windowInfo;
|
|
@@ -238,72 +267,86 @@ void repaint( XInfo &xinfo) {
|
|
|
unsigned int width = windowInfo.width;
|
|
|
|
|
|
// big black rectangle to clear background
|
|
|
-
|
|
|
+
|
|
|
// draw display list
|
|
|
- while( begin != end ) {
|
|
|
- Displayable *d = *begin;
|
|
|
+ while (begin != end)
|
|
|
+ {
|
|
|
+ Displayable * d = *begin;
|
|
|
d->paint(xinfo);
|
|
|
begin++;
|
|
|
}
|
|
|
- XFlush( xinfo.display );
|
|
|
+ XFlush(xinfo.display);
|
|
|
}
|
|
|
|
|
|
-void handleKeyPress(XInfo &xinfo, XEvent &event) {
|
|
|
+void handleKeyPress(XInfo & xinfo, XEvent & event)
|
|
|
+{
|
|
|
KeySym key;
|
|
|
char text[BufferSize];
|
|
|
-
|
|
|
+
|
|
|
/*
|
|
|
* Exit when 'q' is typed.
|
|
|
* This is a simplified approach that does NOT use localization.
|
|
|
*/
|
|
|
- int i = XLookupString(
|
|
|
+ int i = XLookupString
|
|
|
+ (
|
|
|
(XKeyEvent *)&event, // the keyboard event
|
|
|
text, // buffer when text will be written
|
|
|
BufferSize, // size of the text buffer
|
|
|
&key, // workstation-independent key symbol
|
|
|
- NULL ); // pointer to a composeStatus structure (unused)
|
|
|
- if ( i == 1) {
|
|
|
+ NULL
|
|
|
+ );
|
|
|
+ // pointer to a composeStatus structure (unused)
|
|
|
+ if (i == 1)
|
|
|
+ {
|
|
|
printf("Got key press -- %c\n", text[0]);
|
|
|
- if (text[0] == 'q') {
|
|
|
+ if (text[0] == 'q')
|
|
|
+ {
|
|
|
error("Terminating normally.");
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-void handleAnimation(XInfo &xinfo, int inside) {
|
|
|
+void handleAnimation(XInfo & xinfo, int inside)
|
|
|
+{
|
|
|
/*
|
|
|
* ADD YOUR OWN LOGIC
|
|
|
* This method handles animation for different objects on the screen and readies the next frame before the screen is re-painted.
|
|
|
- */
|
|
|
+ */
|
|
|
snake.move(xinfo);
|
|
|
}
|
|
|
|
|
|
// get microseconds
|
|
|
-unsigned long now() {
|
|
|
+unsigned long now()
|
|
|
+{
|
|
|
timeval tv;
|
|
|
gettimeofday(&tv, NULL);
|
|
|
return tv.tv_sec * 1000000 + tv.tv_usec;
|
|
|
}
|
|
|
|
|
|
-void eventLoop(XInfo &xinfo) {
|
|
|
+void eventLoop(XInfo & xinfo)
|
|
|
+{
|
|
|
// Add stuff to paint to the display list
|
|
|
dList.push_front(&snake);
|
|
|
- dList.push_front(&fruit);
|
|
|
-
|
|
|
+ dList.push_front(&fruit);
|
|
|
+
|
|
|
XEvent event;
|
|
|
unsigned long lastRepaint = 0;
|
|
|
int inside = 0;
|
|
|
|
|
|
- while( true ) {
|
|
|
+ while(1)
|
|
|
+ {
|
|
|
/*
|
|
|
- * This is NOT a performant event loop!
|
|
|
+ * This is NOT a performant event loop!
|
|
|
* It needs help!
|
|
|
*/
|
|
|
-
|
|
|
- if (XPending(xinfo.display) > 0) {
|
|
|
- XNextEvent( xinfo.display, &event );
|
|
|
+
|
|
|
+ if (XPending(xinfo.display) > 0)
|
|
|
+ {
|
|
|
+ XNextEvent(xinfo.display, &event);
|
|
|
cout << "event.type=" << event.type << "\n";
|
|
|
- switch( event.type ) {
|
|
|
+
|
|
|
+ switch( event.type )
|
|
|
+ {
|
|
|
case KeyPress:
|
|
|
handleKeyPress(xinfo, event);
|
|
|
break;
|
|
@@ -314,7 +357,7 @@ void eventLoop(XInfo &xinfo) {
|
|
|
inside = 0;
|
|
|
break;
|
|
|
}
|
|
|
- }
|
|
|
+ }
|
|
|
|
|
|
usleep(1000000/FPS);
|
|
|
handleAnimation(xinfo, inside);
|
|
@@ -329,7 +372,8 @@ void eventLoop(XInfo &xinfo) {
|
|
|
* Next loop responding to events.
|
|
|
* Exit forcing window manager to clean up - cheesy, but easy.
|
|
|
*/
|
|
|
-int main ( int argc, char *argv[] ) {
|
|
|
+int main (int argc, char * argv[])
|
|
|
+{
|
|
|
XInfo xInfo;
|
|
|
|
|
|
initX(argc, argv, xInfo);
|