123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338 |
- /*
- CS 349 A1 Skeleton Code - Snake
- - - - - - - - - - - - - - - - - - - - - - -
- Commands to compile and run:
- g++ -o snake snake.cpp -L/usr/X11R6/lib -lX11 -lstdc++
- ./snake
- Note: the -L option and -lstdc++ may not be needed on some machines.
- */
- #include <iostream>
- #include <list>
- #include <cstdlib>
- #include <sys/time.h>
- #include <math.h>
- #include <stdio.h>
- #include <unistd.h>
- /*
- * Header files for X functions
- */
- #include <X11/Xlib.h>
- #include <X11/Xutil.h>
- using namespace std;
-
- /*
- * Global game state variables
- */
- const int Border = 1;
- const int BufferSize = 10;
- const int FPS = 30;
- const int width = 800;
- 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;
- };
- /*
- * Function to put out a message on error exits.
- */
- void error( string str ) {
- cerr << str << endl;
- exit(0);
- }
- /*
- * An abstract class representing displayable things.
- */
- class Displayable {
- public:
- virtual void paint(XInfo &xinfo) = 0;
- };
- class Snake : public Displayable {
- public:
- virtual void paint(XInfo &xinfo) {
- XFillRectangle(xinfo.display, xinfo.window, xinfo.gc[0], x, y, 25, blockSize);
- }
-
- void move(XInfo &xinfo) {
- x = x + direction;
- if (x < 0 || x > width) {
- direction = -direction;
- }
- // ** ADD YOUR LOGIC **
- // Here, you will be performing collision detection between the snake,
- // the fruit, and the obstacles depending on what the snake lands on.
- }
-
- int getX() {
- return x;
- }
-
- int getY() {
- return y;
- }
- /*
- * ** ADD YOUR LOGIC **
- * 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 didHitObstacle() {
- }
- void turnLeft() {
- }
- void turnRight() {
- }
-
- Snake(int x, int y): x(x), y(y) {
- direction = 5;
- blockSize = 10;
- }
-
- private:
- int x;
- int y;
- int blockSize;
- int direction;
- };
- class Fruit : public Displayable {
- public:
- virtual void paint(XInfo &xinfo) {
- XFillRectangle(xinfo.display, xinfo.window, xinfo.gc[0], x, y, 10, 10);
- }
- Fruit() {
- // ** ADD YOUR LOGIC **
- // generate the x and y value for the fruit
- x = 50;
- y = 50;
- }
- // ** ADD YOUR LOGIC **
- /*
- * The fruit needs to be re-generated at new location every time a snake eats it. See the assignment webpage for more details.
- */
- private:
- int x;
- int y;
- };
- list<Displayable *> dList; // list of Displayables
- Snake snake(100, 450);
- Fruit fruit;
- /*
- * Initialize X and create a window
- */
- 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." );
- }
-
- /*
- * Find out some things about the display you're using.
- */
- xInfo.screen = DefaultScreen( xInfo.display );
- white = XWhitePixel( xInfo.display, xInfo.screen );
- black = XBlackPixel( xInfo.display, xInfo.screen );
- hints.x = 100;
- hints.y = 100;
- hints.width = 800;
- hints.height = 600;
- hints.flags = PPosition | PSize;
- 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(
- 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
- /*
- * Create Graphics Contexts
- */
- int i = 0;
- xInfo.gc[i] = XCreateGC(xInfo.display, xInfo.window, 0, 0);
- XSetForeground(xInfo.display, xInfo.gc[i], BlackPixel(xInfo.display, xInfo.screen));
- XSetBackground(xInfo.display, xInfo.gc[i], WhitePixel(xInfo.display, xInfo.screen));
- XSetFillStyle(xInfo.display, xInfo.gc[i], FillSolid);
- XSetLineAttributes(xInfo.display, xInfo.gc[i],
- 1, LineSolid, CapButt, JoinRound);
- XSelectInput(xInfo.display, xInfo.window,
- ButtonPressMask | KeyPressMask |
- PointerMotionMask |
- EnterWindowMask | LeaveWindowMask |
- StructureNotifyMask); // for resize events
- /*
- * Put the window on the screen.
- */
- XMapRaised( xInfo.display, xInfo.window );
- XFlush(xInfo.display);
- }
- /*
- * Function to repaint a display list
- */
- 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;
- XGetWindowAttributes(xinfo.display, xinfo.window, &windowInfo);
- unsigned int height = windowInfo.height;
- unsigned int width = windowInfo.width;
- // big black rectangle to clear background
-
- // draw display list
- while( begin != end ) {
- Displayable *d = *begin;
- d->paint(xinfo);
- begin++;
- }
- XFlush( xinfo.display );
- }
- 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(
- (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) {
- printf("Got key press -- %c\n", text[0]);
- if (text[0] == 'q') {
- error("Terminating normally.");
- }
- }
- }
- 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() {
- timeval tv;
- gettimeofday(&tv, NULL);
- return tv.tv_sec * 1000000 + tv.tv_usec;
- }
- void eventLoop(XInfo &xinfo) {
- // Add stuff to paint to the display list
- dList.push_front(&snake);
- dList.push_front(&fruit);
-
- XEvent event;
- unsigned long lastRepaint = 0;
- int inside = 0;
- while( true ) {
- /*
- * This is NOT a performant event loop!
- * It needs help!
- */
-
- if (XPending(xinfo.display) > 0) {
- XNextEvent( xinfo.display, &event );
- cout << "event.type=" << event.type << "\n";
- switch( event.type ) {
- case KeyPress:
- handleKeyPress(xinfo, event);
- break;
- case EnterNotify:
- inside = 1;
- break;
- case LeaveNotify:
- inside = 0;
- break;
- }
- }
- usleep(1000000/FPS);
- handleAnimation(xinfo, inside);
- repaint(xinfo);
- }
- }
- /*
- * Start executing here.
- * First initialize window.
- * Next loop responding to events.
- * Exit forcing window manager to clean up - cheesy, but easy.
- */
- int main ( int argc, char *argv[] ) {
- XInfo xInfo;
- initX(argc, argv, xInfo);
- eventLoop(xInfo);
- XCloseDisplay(xInfo.display);
- }
|