tarfeef101 vor 6 Jahren
Ursprung
Commit
b668b871d6
2 geänderte Dateien mit 357 neuen und 0 gelöschten Zeilen
  1. 19 0
      assignments/a1/Makefile
  2. 338 0
      assignments/a1/snake.cpp

+ 19 - 0
assignments/a1/Makefile

@@ -0,0 +1,19 @@
+# super simple makefile
+# call it using 'make NAME=name_of_code_file_without_extension'
+# (assumes a .cpp extension)
+NAME = snake
+
+#
+# Add $(MAC_OPT) to the compile line for Mac OSX.
+MAC_OPT = "-I/opt/X11/include"
+
+all:
+	@echo "Compiling..."
+	g++ -o $(NAME) $(NAME).cpp -L/opt/X11/lib -lX11 -lstdc++ $(MAC_OPT)
+
+run: all
+	@echo "Running..."
+	./$(NAME) 
+
+clean:
+	rm ./snake

+ 338 - 0
assignments/a1/snake.cpp

@@ -0,0 +1,338 @@
+/*
+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);
+}