This is GameView.m in view mode; [Download] [Up]
#import <gamekit/gamekit.h> // Colors #import <daymisckit/daymisckit.h> // ExtendedApp, etc. #import <dpsclient/psops.h> // PSsetgray() #import <dpsclient/wraps.h> // PScompositerect() #import <libc.h> // for random(), etc. #import <math.h> // for floor(), etc. #import <stdio.h> // for standard C file operations @implementation GameView #define dragdef const char *dragTypes[3] =\ {NXFilenamePboardType, NXColorPboardType, NULL} #define dragNum 2 - initFrame:(const NXRect *)frm // designated initializer for a view { dragdef; [super initFrame:frm]; cycles = 0; srandom(time(0)); demoMode = NO; grayBorder = YES; state = GAMEOVER; demoWait = 0; doingBorder = NO; grayBorder = YES; backColor = NXConvertRGBToColor(0.333, 0.333, 0.333); // dark gray default backIsColor = YES; // default bg is dark gray... [self registerForDraggedTypes:dragTypes count:dragNum]; dragOperation = NX_DragOperationNone; return self; } - appDidInit:sender // forwarded by gamebrain { if (!controller) controller = [NXApp delegate]; if (!preferences) preferences = [controller preferencesBrain]; if (!scoreKeeper) scoreKeeper = [controller scoreKeeper]; if (!strings) strings = [controller mainStrings]; if (!customSound) customSound = [controller soundPlayer]; [self loadPix]; return self; } - loadPix { const char *tmpStr; char *okStr; float r, g, b; [self allocateGState]; // set background okStr = malloc(8); tmpStr = NXGetDefaultValue([NXApp appName], "BackColor"); if (tmpStr) { backIsColor = NO; sscanf(tmpStr, "%s %f %f %f", &okStr[0], &r, &g, &b); backColor = NXConvertRGBToColor(r, g, b); if (okStr[0] == 'Y') { backIsColor = YES; } } free(okStr); // get some buffers to hold our drawings. buffer = [[NXImage allocFromZone:[self zone]] initSize:&bounds.size]; staticBuffer = [[NXImage allocFromZone:[self zone]] initSize:&bounds.size]; if (!backIsColor) [self setBackgroundFile: NXGetDefaultValue([NXApp appName], "BackGround") andRemember:NO]; return self; } - animate:sender { // method to start the animation - called by appDidInit // set up Animator: (autoUpdate) this handles moving viruses and // makes sure the columns fall when they should. The animator is // an object that handles timed entries "smartly". animator = [[Animator alloc] initChronon:[self speedTime] adaptation:0.0 target:self action:@selector(autoUpdate:) autoStart:YES eventMask:0]; return self; } - (BOOL)demoMode // if last game was demo { return demoMode; } - (float)speedTime // returns time between animation frames { return GRANULARITY; // return delay between clock ticks } // 0.05 is about as fast as should be used. - (int)gameState // tell caller our state... if in demo, game is over { if (demoMode) return GAMEOVER; return state; } - (int)realGameState // tell caller our state...may need to really know... { return state; } - getOffset:(NXPoint *)aPoint // returns offset by reference { GK_VECTOR_X(aPoint) = offset.x; GK_VECTOR_Y(aPoint) = offset.y; return self; } - setOffset:(const NXPoint *)aPoint // change the offset { offset.x = GK_VECTOR_X(aPoint); offset.y = GK_VECTOR_Y(aPoint); return self; } - autoUpdate:sender // called by timed entry to update screen periodically { // ALL animation is controlled from here!!! cycles++; // you would do updates to various screen objects and // then do a [self updateSelf:&bounds :1]; return self; } - updateSelf:(NXRect *)rects :(int)rectCount // redraws the screen. { // it redraws only what has changed since last redraw. NXPing(); return self; } - mouseDown:(NXEvent *)event // handle mouseDown events. { [controller pauseGame:self]; // pause/unpause game return self; } - (BOOL)acceptsFirstMouse // let us grab activating mousedowns { // 1st click is to become 1st responder, NOT pause/unpause return NO; } - setKey:(int)keyIndex val:(char)keyVal // change key we respond to { keys[keyIndex] = keyVal; return self; } - pause:sender // set pause status. { paused = YES; return self; } - unpause:sender // remove paused status { paused = NO; return self; } - (BOOL)isPaused // tell caller is we're paused { return paused; } - keyDown:(NXEvent *)myevent // handle keyDown events. { PSobscurecursor(); // subclasses which override need to do this. if (myevent->data.key.charSet == NX_ASCIISET && (myevent->flags&(NX_CONTROLMASK|NX_ALTERNATEMASK|NX_COMMANDMASK)) == 0) { if (GKKEYCODE == 'p') { // allow pause if (paused) [controller unpause]; else [controller pause]; } else if (GKKEYCODE == 'n') { // allow new game [controller startNewGame:self]; // re-start the game // returns nil if user changes mind... } else if (paused) { // any keyDown unpauses game (except 'p'). [controller unpause]; } } else return [super keyDown:myevent]; return self; } - (BOOL)acceptsFirstResponder // to grab keyboard events { return YES; } - getPreferences { if (!preferences) preferences = [[NXApp delegate] preferencesBrain]; return self; } - free // get rid of support objects { [animator free]; return [super free]; } - setUpScreen { if ((demoMode)||(doingBorder)) [self display]; return self; } - changeBorder:(BOOL)borderOn { // move view about in the window & do sizing NXRect wFrame; if (borderOn == grayBorder) return self; if (borderOn) { [window getFrame:&wFrame]; NXInsetRect(&wFrame, -BEZELSIZE, -BEZELSIZE); [self moveBy:BEZELSIZE :BEZELSIZE]; [window placeWindowAndDisplay:&wFrame]; } else { [window getFrame:&wFrame]; NXInsetRect(&wFrame, BEZELSIZE, BEZELSIZE); [self moveBy:-BEZELSIZE :-BEZELSIZE]; [window placeWindowAndDisplay:&wFrame]; } grayBorder = borderOn; return self; } - restartGame { cycles = 0; state = NORMALSTATE; if (demoMode) { demoMode = NO; [[self window] setTitle:[strings valueForStringKey:"GameName"]]; } [scoreKeeper resetScore]; [self getPreferences]; // make sure we're up to date return self; } //// Background handling methods stolen from BreakApp: - setBackgroundFile:(const char *)fileName andRemember:(BOOL)remember // This methods allows changing the file used to paint the background of the // playing field. Set fileName to NULL to revert to the default. Set // remember to YES if you wish the write the value out in the defaults. { [backGround free]; backGround = [[NXImage allocFromZone:[self zone]] initSize:&bounds.size]; [backGround setBackgroundColor:backColor]; [backGround setScalable:YES]; if (fileName) { [backGround useFromFile:fileName]; if (remember) { NXWriteDefault ([NXApp appName], "BackGround", fileName); } } else { // default background image [backGround useFromSection:"BackGround.eps"]; if (remember) { NXRemoveDefault ([NXApp appName], "BackGround"); } } backIsColor = NO; [self buildBackground]; [self writeColor]; [self display]; return self; } - buildBackground { return self; } // for subclass use // The following two methods allow changing the background image from // menu items or buttons. - changeBackground:sender { const char *const *types = [NXImage imageFileTypes]; if ([[OpenPanel new] runModalForTypes:types]) { [self setBackgroundFile:[[OpenPanel new] filename] andRemember:YES]; [self display]; } return self; } - revertBackground:sender { backIsColor = NO; [self setBackgroundFile:NULL andRemember:YES]; [self display]; return self; } - loadAnImage:(const char *)imageName { char *tempStr = (char *)malloc(MAXPATHLEN); sprintf(tempStr, "%s/%s", [NXApp appDirectory], imageName); [self setBackgroundFile:tempStr andRemember:YES]; free(tempStr); [self display]; return self; } - back1:sender { return [self loadAnImage:"Back1.eps"]; } - back2:sender { return [self loadAnImage:"Back2.tiff"]; } - back3:sender { return [self loadAnImage:"Back3.tiff"]; } - drawBackground:(NXRect *)rect // drawBackground: just draws the specified piece of the background by // compositing from the background image. { NXRect tmpRect = *rect; if (backIsColor) { NXSetColor(backColor); NXRectFill(rect); return self; } NX_X(&tmpRect) = floor(NX_X(&tmpRect)); NX_Y(&tmpRect) = floor(NX_Y(&tmpRect)); if (NXDrawingStatus == NX_DRAWING) { PSsetgray (NX_BLACK); PScompositerect (NX_X(&tmpRect), NX_Y(&tmpRect), NX_WIDTH(&tmpRect), NX_HEIGHT(&tmpRect), NX_SOVER); } [backGround composite:NX_SOVER fromRect:&tmpRect toPoint:&tmpRect.origin]; return self; } - sizeTo:(NXCoord)width :(NXCoord)height { [super sizeTo:width :height]; [backGround setSize:&bounds.size]; return self; } // deal with drag and drop colors: - acceptColor:(NXColor)color atPoint:(const NXPoint *)aPoint { backIsColor = YES; backColor = color; [[self writeColor] update]; return self; } - writeColor { char def[256]; float r, g, b; NXConvertColorToRGB(backColor, &r, &g, &b); sprintf(def, "%s %f %f %f", (backIsColor ? "YES" : "NO"), r, g, b); NXWriteDefault ([NXApp appName], "BackColor", def); return self; } // these assume that you already locked focus. Thus, when overriding // these methods, the subclas should lock focus in the static buffer // before calling the super (this) method. - rebuildStaticBuffer { [self drawBackground:&bounds]; return self; } - rebuildStaticAt:(NXRect *)rect { [self drawBackground:rect]; return self; } // drag and drop an image into the view's background. // uses 3.0 drag kit stuff - (NXDragOperation)draggingEntered:sender { NXDragOperation sourceMask; // Ask the sender for its operation mask. sourceMask = [sender draggingSourceOperationMask]; if (sourceMask & NX_DragOperationCopy) dragOperation = NX_DragOperationCopy; else if (sourceMask & NX_DragOperationGeneric) dragOperation = NX_DragOperationGeneric; else dragOperation = NX_DragOperationNone; return dragOperation; } - (NXDragOperation)draggingUpdated:sender { return dragOperation; } - draggingExited:sender { return self; } - (BOOL)prepareForDragOperation:sender { // We do want to accept the dragged image/color. return YES; } - (BOOL)performDragOperation:sender { Pasteboard *dragPasteboard = [Pasteboard newName:NXDragPboard]; char *file; int length; dragdef; BOOL foundOne = NO; if ([dragPasteboard findAvailableTypeFrom:dragTypes num:dragNum] == NXFilenamePboardType) { if ([dragPasteboard readType:NXFilenamePboardType data:&file length:&length]) { foundOne = YES; [self setBackgroundFile:file andRemember:YES]; [dragPasteboard deallocatePasteboardData:file length:length]; [NXApp activateSelf:YES]; [window makeKeyAndOrderFront:self]; } } else if ([dragPasteboard findAvailableTypeFrom:dragTypes num:dragNum] == NXColorPboardType) { NXPoint p = [sender draggingLocation]; NXColor c = NXReadColorFromPasteboard([sender draggingPasteboard]); [self acceptColor:c atPoint:&p]; foundOne = YES; [NXApp activateSelf:YES]; [window makeKeyAndOrderFront:self]; } return foundOne; } - concludeDragOperation:sender { return self; } - gameOver // sent by GameBrain { state = GAMEOVER; return self; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.