This is GameView.m in view mode; [Download] [Up]
/* Generated by Interface Builder */ #import "GameView.h" #import "Animator.h" // timer controller #import "GameBrain.h" // Partner in crime #import "PreferencesBrain.h" // for user's preferences #import <appkit/color.h> // Colors #import <appkit/Application.h> // event stuff, misc. #import <appkit/Speaker.h> // for dragging #import <appkit/Listener.h> // for dragging #import <appkit/NXImage.h> // for tiff rendering #import <appkit/OpenPanel.h> // for setting backgrounds #import <appkit/publicWraps.h> // used to set up dragging (get windownum) #import <appkit/nextstd.h> // for NX_FREE, 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 - initFrame:(const NXRect *)frm // designated initializer for a view { char *slashPos; [super initFrame:frm]; // seed random number generator srandom(time(0)); // some defaults demoMode = NO; grayBorder = YES; // get .app wrapper pathname and then load .snd files appPath = (char *)malloc(256); strcpy(appPath, NXArgv[0]); if (slashPos = strrchr(appPath, '/')) { sprintf(slashPos+1, "\0"); } else { strcpy(appPath, "./"); } // initialize game variables 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 allocateGState]; return self; } - loadPix { const char *tmpStr; char *okStr; float r, g, b; // 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); 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; } - 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. { if (myevent->data.key.charSet == NX_ASCIISET && (myevent->flags&(NX_CONTROLMASK|NX_ALTERNATEMASK|NX_COMMANDMASK)) == 0) { if (myevent->data.key.charCode == 'p') { // allow pause if (paused) [controller unpause]; else [controller pause]; } else if (paused) { // any keyDown unpauses game (except 'p'). [controller unpause]; } else if (myevent->data.key.charCode == 'n') { // allow new game if (([self gameState] != GAMEOVER) && ([preferences alert])) { // if game in progress, alert user about this if (NXRunAlertPanel(NULL, "Do you want to throw away the current game?", "You betcha!", "Um, no.", NULL) != NX_ALERTDEFAULT) { return self; // allow "graceful escape" } } if ([self gameState] != GAMEOVER) { [controller gameOver]; // Force Game Over. state = GAMEOVER; } [controller startNewGame:self]; // re-start the game } } else return [super keyDown:myevent]; return self; } - (BOOL)acceptsFirstResponder // to grab keyboard events { return YES; } - getPreferences { soundEffects = [preferences effects]; music = [preferences music]; return self; } - soundOn // turn on sound effects { soundEffects = YES; return self; } - soundOff // turn off sound effects { soundEffects = NO; return self; } - musicOn // turn on music { music = YES; return self; } - musicOff // turn off music { music = NO; return self; } - free // get rid of support objects { [animator free]; [self unregisterWindow]; return [super free]; } - setUpScreen { if ((demoMode)||(doingBorder)) [self display]; return self; } - changeBorder:(BOOL)borderOn { // move view about in the window & do sizing // NOT USED in PacMan...it's best if you don't use it, in fact. 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 { 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]; if (fileName) { [backGround useFromFile:fileName]; if (remember) { NXWriteDefault ([NXApp appName], "BackGround", fileName); } } else { [backGround useFromSection:"BackGround.eps"]; if (remember) { NXRemoveDefault ([NXApp appName], "BackGround"); } } backIsColor = NO; [self writeColor]; [backGround setBackgroundColor:NX_COLORWHITE]; [backGround setScalable:YES]; [self display]; return self; } // The following two methods allow changing the background image from // menu items or buttons. - changeBackground:sender { const char *const types[] = {"tiff", "eps", NULL}; if ([[OpenPanel new] runModalForTypes:types]) { [self setBackgroundFile:[[OpenPanel new] filename] andRemember:YES]; [self display]; } return self; } - revertBackground:sender { [self setBackgroundFile:NULL andRemember:YES]; [self display]; return self; } - back1:sender { char *tempStr; tempStr = malloc(256); sprintf(tempStr, "%sBack1.tiff", appPath); [self setBackgroundFile:tempStr andRemember:YES]; free(tempStr); [self display]; return self; } - back2:sender { char *tempStr; tempStr = malloc(256); sprintf(tempStr, "%sBack2.tiff", appPath); [self setBackgroundFile:tempStr andRemember:YES]; free(tempStr); [self display]; return self; } - back3:sender { char *tempStr; tempStr = malloc(256); sprintf(tempStr, "%sBack3.tiff", appPath); [self setBackgroundFile:tempStr andRemember:YES]; free(tempStr); [self display]; return self; } - 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_WHITE); 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:(NXPoint *)aPoint { backIsColor = YES; backColor = color; [[self writeColor] update]; return self; } - writeColor { char def[256]; char bic[16] = "YES"; float r, g, b; if (!backIsColor) sprintf(bic, "NO"); NXConvertColorToRGB(backColor, &r, &g, &b); sprintf(def, "%s %f %f %f", bic, r, g, b); NXWriteDefault ([NXApp appName], "BackColor", def); return self; } // The drag and drop .tiff/.eps is borrowed and modified from the // Adobe example NX_ImportAdv which demonstrates tiff/eps handling. // I've taken the code chunk for drag and drop and modified it to // work for setting backgrounds. /* * Registers the document window with the Workspace Manager so that when the * user picks up an icon in the Workspace and drags it over our document window * and lets go, iconEntered:... and iconReleasedAt::ok: messages will be * sent to the DrawDocument from the Workspace Manager. Allows the user to * drag PostScript and TIFF files into the document. */ - registerWindow { return self; } /* Undoes what registerWindow does. */ - unregisterWindow { return self; } /* * Called whenever an icon is dragged from the Workspace over the document * window. At this point, all that is done is to salt away the list of files * represented by the icon. All the real work is done in iconReleasedAt::ok:. */ - (int)iconEntered:(int)windowNum at:(double)x :(double)y iconWindow:(int)iconWindowNum iconX:(double)iconX iconY:(double)iconY iconWidth:(double)iconWidth iconHeight:(double)iconHeight pathList:(char *)pathList { if (!iconPathList || strcmp(iconPathList, pathList)) { // if new list of files, copy it in for us to look at later NX_FREE(iconPathList); NX_MALLOC(iconPathList, char, strlen(pathList)+1); strcpy(iconPathList, pathList); } return 0; } /* * Goes through the list of files associated with the icon dragged * from the Workspace and checks if any of them are PostScript or TIFF. * If any are, then the GraphicView is asked to load those in as objects. * Very important: an NX_DURING handler is required around all the processing * of this method since an uncaught raised error will cause this method not * to return and thus hang the Workspace Manager for a while. */ - (int)iconReleasedAt:(double)x :(double)y ok:(int *)flag { volatile int foundOne = NO; char *file, *tab, *extension; NX_DURING file = iconPathList; tab = strchr(file, '\t'); if (tab) *tab = '\0'; extension = strrchr(file, '.'); if (extension) { if (!strcmp(extension, ".eps") || !strcmp(extension, ".tiff")) { [self setBackgroundFile:file andRemember:YES]; foundOne = YES; } } if (foundOne) { [NXApp activateSelf:YES]; [window makeKeyAndOrderFront:self]; } NX_HANDLER NX_ENDHANDLER *flag = foundOne; return 0; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.