This is Board3D.m in view mode; [Download] [Up]
#import <c.h> #include <sys/types.h> #include <sys/time.h> #import <appkit/appkit.h> #import "chess_strings.h" #import "Chess.h" #import "gnuchess.h" #import "Board3D.h" #import "Square3D.h" #define PIECE_WIDTH_3D 55 #define BACK_STORE_WIDTH 80 #define PIECE_HEIGHT_3D 95 #define BACK_STORE_HEIGHT 110 extern PSWtrapezoid (); /* Each set of points describes the vertical lines along the board. */ struct NXLine { NXPoint a,b; }; #define BASE_X 89 struct NXLine vertical[] = { {{BASE_X,122},{BASE_X+61,467}}, {{BASE_X+71,122},{BASE_X+111,467}}, {{BASE_X+135,122},{BASE_X+162,467}}, {{BASE_X+200,122},{BASE_X+212,467}}, {{BASE_X+265,122},{BASE_X+265,467}}, {{BASE_X+330,122},{BASE_X+316,467}}, {{BASE_X+393,122},{BASE_X+367,467}}, {{BASE_X+459,122},{BASE_X+419,467}}, {{BASE_X+524,122},{BASE_X+469,467}} }; /* Each coordinate describes the y value of each line of the board. */ #define BASE_Y 132 NXCoord horizontal[] = { BASE_Y, BASE_Y+54, BASE_Y+106, BASE_Y+153, BASE_Y+196, BASE_Y+237, BASE_Y+277, BASE_Y+312, BASE_Y+345 }; id pieces3D; void convert_point( NXPoint *p, int *r, int *c ); @implementation Board3D + newFrame: (const NXRect *)f { int r, c, i; self = [super newFrame: f]; [self allocateGState]; background = [Bitmap newFromMachO: "3d_board.tiff"]; [background setFlip: NO]; pieces3D = [Bitmap newFromMachO: "3d_pieces.tiff"]; [pieces3D setFlip: NO]; backBitmap = [Bitmap newSize: BACK_STORE_WIDTH: BACK_STORE_HEIGHT type: NX_UNIQUEBITMAP]; [backBitmap setFlip: NO]; for( r = 0; r < 8; r++ ) for( c = 0; c < 8; c++ ) square[r][c] = [Square3D new]; [self setupPieces]; return self; } - setBackgroundBitmap: sender { background = sender; [background setFlip: NO]; } - setupPieces { [self layoutBoard: Stboard color:Stcolor]; } - layoutBoard: (short *)b color: (short *)c { int sq, row, col; PSgsave(); PSrotate ( 10.0 ); for (sq = 0; sq < 64; sq++){ row = sq / 8; col = sq % 8; [self placePiece: b[sq] at: row: col color: c[sq]]; } PSgrestore(); } squareOrigin( int r, int c, NXCoord *x, NXCoord *y ) { NXCoord dx,m,b; *y = horizontal[r]; dx = (vertical[c].a.x-vertical[c].b.x); m = (vertical[c].a.y - vertical[c].b.y) / dx; b = vertical[c].b.y - (m*vertical[c].b.x); *x = dx ? (horizontal[r] - b)/m : vertical[c].a.x; } squareBounds( int r, int c, NXPoint *p1, NXPoint *p2, NXPoint *p3, NXPoint *p4 ) /* (p2)----(p4) | | | | (p1)----(p3) */ { NXCoord dx,m,b; dx = (vertical[c].a.x-vertical[c].b.x); m = (vertical[c].a.y - vertical[c].b.y) / dx; b = vertical[c].b.y - (m*vertical[c].b.x); p1->y = floor( horizontal[r] ); p1->x = floor( dx ? (horizontal[r] - b)/m : vertical[c].a.x ); p2->y = floor( horizontal[r+1] ); p2->x = floor( dx ? (horizontal[r+1] - b)/m : vertical[c].a.x ); dx = (vertical[c+1].a.x-vertical[c+1].b.x); m = (vertical[c+1].a.y - vertical[c+1].b.y) / dx; b = vertical[c+1].b.y - (m*vertical[c+1].b.x); p3->y = floor( horizontal[r] ); p3->x = floor( dx ? (horizontal[r] - b)/m : vertical[c+1].a.x ); p4->y = floor( horizontal[r+1] ); p4->x = floor( dx ? (horizontal[r+1] - b)/m : vertical[c+1].a.x ); } - slidePieceFrom: (int)r1 : (int)c1 to: (int)r2 : (int)c2 { NXPoint p, backP, centerP, endP; NXRect backR; int controlGState, type, color, increments, dr, dc, i; NXRect newLocation, oldLocation; NXCoord incX, incY; [self lockFocus]; type = [square[r1][c1] type]; color = [square[r1][c1] colorVal]; oldLocation = *[square[r1][c1] location]; if( !type ) return self; squareOrigin( r2, c2, &endP.x, &endP.y ); /* Remove piece and then save background */ [square[r1][c1] setType: 0 color: 0]; [self drawSelf: 0 : 0]; squareOrigin( r1, c1, &backP.x, &backP.y ); controlGState = [self gState]; [backBitmap lockFocus]; PSgsave(); PScomposite( backP.x, backP.y, BACK_STORE_WIDTH, BACK_STORE_HEIGHT, controlGState, 0.0, 0.0, NX_COPY); PSgrestore(); [backBitmap unlockFocus]; [square[r1][c1] setType: type color: color]; [square[r1][c1] drawInside: 0 inView: self]; [square[r1][c1] setMoving: YES]; PSflushgraphics(); NXPing(); incX = endP.x - backP.x; incY = endP.y - backP.y; increments = (int) MAX( ABS(incX), ABS(incY) ) / 7; // was 5 gcr incX = incX / increments; incY = incY / increments; for( i = 0; i < increments; i++ ){ /* Restore old background */ [self lockFocus]; [backBitmap composite:NX_COPY toPoint: &backP]; [self unlockFocus]; backP.x += incX; backP.y += incY; convert_point( &backP, &dr, &dc ); /* Save new background */ [backBitmap lockFocus]; // PSgsave(); PScomposite( backP.x, backP.y, BACK_STORE_WIDTH, BACK_STORE_HEIGHT, controlGState, 0.0, 0.0, NX_COPY); // PSgrestore(); [backBitmap unlockFocus]; /* Draw piece at new location. */ [square[r1][c1] setRow: dr]; newLocation.origin = backP; newLocation.size.width = PIECE_WIDTH_3D; newLocation.size.height = PIECE_HEIGHT_3D; [square[r1][c1] setLocation: &newLocation]; [square[r1][c1] drawInside: 0 inView: self]; PSflushgraphics(); NXPing(); } [square[r1][c1] setMoving: NO]; [self unlockFocus]; } - placePiece: (int)p at: (int)r : (int)c color: (int)col { NXRect l; NXCoord m,b,dx,x; [square[r][c] setType: p color: col]; [square[r][c] setRow: r]; l.origin.y = horizontal[r]; dx = (vertical[c].a.x-vertical[c].b.x); m = (vertical[c].a.y - vertical[c].b.y) / dx; b = vertical[c].b.y - (m*vertical[c].b.x); x = dx ? (horizontal[r] - b)/m : vertical[c].a.x; l.origin.x = x; dx = (vertical[c+1].a.x-vertical[c+1].b.x); m = (vertical[c+1].a.y - vertical[c+1].b.y) / dx; b = vertical[c+1].b.y - (m*vertical[c+1].b.x); x = dx ? (horizontal[r] - b)/m : vertical[c+1].a.x; l.size.width = x - l.origin.x; l.size.height = 99999; [square[r][c] setLocation: &l]; } - (int)typeAt: (int)r : (int)c { return( (r>=0 && c>=0) ? [square[r][c] type] : 0 ); } - (int)colorAt: (int)r : (int)c { return( (r>=0 && c>=0) ? [square[r][c] colorVal] : 0 ); } - drawRows: (int)r from: (int)c { while( r >= 0 ){ if( [self typeAt: r : c] && ![square[r][c] moving] ) [square[r][c] drawInside: 0 inView: self]; r--; } } - unhighlightSquareAt: (int)r : (int) c { NXPoint p1,p2,p3,p4,to; NXRect backR; squareBounds( r, c, &p1, &p2, &p3, &p4 ); p1.x = p1.x - 3; p1.y = p1.y - 3; p2.x = p2.x - 3; p2.y = p2.y + 3; p3.x = p3.x + 3; p3.y = p3.y - 3; p4.x = p4.x + 3; p4.y = p4.y + 3; to.y = p1.y; to.x = MIN(p1.x,p2.x); backR.origin = to; backR.size.width = MAX(p3.x,p4.x) - to.x; backR.size.height = p2.y - p1.y; [self lockFocus]; PSgsave(); PSsetlinewidth( 3.0 ); PSsetgray( 1.0 ); PSnewpath(); PSmoveto( p1.x, p1.y ); PSlineto( p2.x, p2.y ); PSlineto( p4.x, p4.y ); PSlineto( p3.x, p3.y ); PSlineto( p1.x, p1.y ); PSclosepath; PSclip(); [background composite: NX_COPY fromRect: &backR toPoint: &to]; PSgrestore(); if( [self typeAt:r :c] || ( r > 0 && [self typeAt:r-1 :c]) ) [self drawRows: r from: c]; PSflushgraphics(); NXPing(); [self unlockFocus]; } - highlightSquareAt: (int)r : (int) c { struct timeval timeout; NXPoint p1,p2,p3,p4; short idx; float color = 0.0; squareBounds( r, c, &p1, &p2, &p3, &p4 ); [self lockFocus]; PSgsave(); PSsetlinewidth( 3.0 ); PSmoveto( p1.x, p1.y ); PSlineto( p2.x, p2.y ); PSlineto( p4.x, p4.y ); PSlineto( p3.x, p3.y ); PSlineto( p1.x, p1.y ); PSclosepath(); /* flash 2 times */ for ( idx=1; idx <= 3; idx++ ) { color = 1.0 - color; PSsetgray( color ); PSgsave(); PSstroke(); PSgrestore(); if( [self typeAt:r :c] || ( r > 0 && [self typeAt:r-1 :c]) ) [self drawRows: r from: c]; PSflushgraphics(); NXPing(); if( ![square[r][c] moving] ){ timeout.tv_sec = 0; timeout.tv_usec = 15000; select( 0, 0, 0, 0, &timeout ); } } PSgrestore(); /**** PSgsave(); PSsetlinewidth( 3.0 ); PSsetgray( 0.0 ); PSnewpath(); PSmoveto( p1.x, p1.y ); PSlineto( p2.x, p2.y ); PSlineto( p4.x, p4.y ); PSlineto( p3.x, p3.y ); PSlineto( p1.x, p1.y ); PSclosepath; PSstroke(); PSgrestore(); if( [self typeAt:r :c] || ( r > 0 && [self typeAt:r-1 :c]) ) [self drawRows: r from: c]; PSflushgraphics(); NXPing(); if( ![square[r][c] moving] ){ timeout.tv_sec = 0; timeout.tv_usec = 150000; select( 0, 0, 0, 0, &timeout ); } PSgsave(); PSsetlinewidth( 3.0 ); PSsetgray( 1.0 ); PSnewpath(); PSmoveto( p1.x, p1.y ); PSlineto( p2.x, p2.y ); PSlineto( p4.x, p4.y ); PSlineto( p3.x, p3.y ); PSlineto( p1.x, p1.y ); PSclosepath; PSstroke(); PSgrestore(); if( [self typeAt:r :c] || ( r > 0 && [self typeAt:r-1 :c]) ) [self drawRows: r from: c]; PSflushgraphics(); NXPing(); if( ![square[r][c] moving] ){ timeout.tv_sec = 0; timeout.tv_usec = 150000; select( 0, 0, 0, 0, &timeout ); } ******/ [self unhighlightSquareAt: r : c]; [self unlockFocus]; } - flashSquareAt: (int)r : (int) c { NXPoint p1,p2,p3,p4; squareBounds( r, c, &p1, &p2, &p3, &p4 ); [self lockFocus]; PSgsave(); PSsetlinewidth( 3.0 ); PSsetgray( 1.0 ); PSnewpath(); PSmoveto( p1.x, p1.y ); PSlineto( p2.x, p2.y ); PSlineto( p4.x, p4.y ); PSlineto( p3.x, p3.y ); PSlineto( p1.x, p1.y ); PSclosepath; PSstroke(); PSgrestore(); if( [self typeAt:r :c] || ( r > 0 && [self typeAt:r-1 :c]) ) [self drawRows: r from: c]; [self unlockFocus]; } - printPSCode: sender { id pi = [NXApp printInfo]; const NXRect *pr; NXCoord lm, rm, tm, bm; pr = [pi paperRect]; lm = rm = (pr->size.width - frame.size.width) / 2.0; tm = bm = (pr->size.height - frame.size.height) / 2.0; [pi setMarginLeft: lm right: rm top: tm bottom: bm]; [self lockFocus]; NXSizeBitmap( &bounds, &print_size, &print_pwide, &print_phigh, &print_bps, &print_ssp, &print_config, &print_mask ); print_image = (void *)malloc( print_size ); NXReadBitmap( &bounds, print_pwide, print_phigh, print_bps, print_ssp, print_config, print_mask, print_image, 0, 0, 0, 0 ); [super printPSCode: self]; free( print_image ); [self unlockFocus]; return self; } - drawSelf:(const NXRect *)f :(int)rectCount; { int r, c; NXRect cr; NXPoint p; p.x = p.y = 0.0; if( NXDrawingStatus == NX_DRAWING ){ PSgsave(); [background composite: NX_COPY toPoint: &p]; for( r = 7; r >= 0; r-- ){ for( c = 7; c >= 0; c-- ){ [square[r][c] drawSelf: &cr inView: self]; } } PSgrestore(); } else{ NXImageBitmap( &bounds, print_pwide, print_phigh, print_bps, print_ssp, print_config, print_mask, print_image, 0, 0, 0, 0 ); } } - mouseDown: (NXEvent *)event { NXPoint p, pickedP, backP, centerP; NXHandler handler; NXRect pieceRect, backR; int r, c, r2, c2, mask, controlGState, t, col; unsigned short mv; NXRect newLocation, oldLocation; NXCoord x, y; int hi_r = -1, hi_c = -1; if ( [NXApp bothsides] ) { NXBeep(); return self; } if( [NXApp finished] ){ [NXApp finishedAlert]; handler.code = 0; [window addToEventMask: NX_MOUSEUPMASK|NX_MOUSEDRAGGEDMASK]; NX_DURING while (event->type != NX_MOUSEUP){ event = [NXApp getNextEvent:NX_MOUSEUPMASK|NX_MOUSEDRAGGEDMASK]; } NX_HANDLER handler = NXLocalHandler; NX_ENDHANDLER return self; } pickedP = event->location; [self convertPoint:&pickedP fromView:nil]; backP = pickedP; r = -1; c = -1; convert_point( &pickedP, &r, &c ); if( r == -1 || c == -1 ) return self; [self lockFocus]; t = [square[r][c] type]; col = [square[r][c] colorVal]; oldLocation = *[square[r][c] location]; if( t ){ [square[r][c] setType: 0 color: 0]; [self drawSelf: 0 : 0]; [self flashSquareAt: r : c]; hi_r = r; hi_c = c; /* Save background */ squareOrigin( r, c, &x, &y ); backP.x = x; backP.y = y; controlGState = [self gState]; [backBitmap lockFocus]; PSgsave(); PScomposite( backP.x, backP.y, BACK_STORE_WIDTH, BACK_STORE_HEIGHT, controlGState, 0.0, 0.0, NX_COPY); PSgrestore(); [backBitmap unlockFocus]; [square[r][c] setType: t color: col]; [square[r][c] drawInside: 0 inView: self]; [square[r][c] setMoving: YES]; PSflushgraphics(); NXPing(); pickedP.x = floor( pickedP.x - x ); pickedP.y = floor( pickedP.y - y ); } r2 = 0; c2 = 0; handler.code = 0; [window addToEventMask: NX_MOUSEUPMASK|NX_MOUSEDRAGGEDMASK]; NX_DURING while (event->type != NX_MOUSEUP){ event = [NXApp getNextEvent:NX_MOUSEUPMASK|NX_MOUSEDRAGGEDMASK]; if( !t ) continue; p = event->location; [self convertPoint:&p fromView:nil]; /* Restore old background */ [self lockFocus]; [backBitmap composite:NX_COPY toPoint: &backP]; [self unlockFocus]; backP.x = p.x - pickedP.x; backP.y = p.y - pickedP.y; /* Un/highlight square */ centerP.y = backP.y + PIECE_HEIGHT_3D/4.0; centerP.x = backP.x + PIECE_WIDTH_3D/2.0; convert_point( ¢erP, &r2, &c2); if( r2 != hi_r || c2 != hi_c ){ if( hi_r != -1 && hi_c != -1 ) [self unhighlightSquareAt: hi_r : hi_c]; hi_r = r2; hi_c = c2; [self flashSquareAt: r2 : c2]; } /* Save new background */ [backBitmap lockFocus]; PSgsave(); PScomposite( backP.x, backP.y, BACK_STORE_WIDTH, BACK_STORE_HEIGHT, controlGState, 0.0, 0.0, NX_COPY); PSgrestore(); [backBitmap unlockFocus]; /* Draw piece at new location. */ [square[r][c] setRow: r2]; newLocation.origin.x = p.x - pickedP.x; newLocation.origin.y = p.y - pickedP.y; newLocation.size.width = PIECE_WIDTH_3D; newLocation.size.height = PIECE_HEIGHT_3D; [square[r][c] setLocation: &newLocation]; [square[r][c] drawInside: 0 inView: self]; PSflushgraphics(); NXPing(); } NX_HANDLER handler = NXLocalHandler; NX_ENDHANDLER if( t ){ [square[r][c] setMoving: NO]; if( r2 != r || c2 != c ){ if( ![NXApp makeMoveFrom: r : c to: r2 : c2] ){ [square[r][c] setLocation: &oldLocation]; [square[r][c] setType: t color: col]; [square[r][c] setRow: r]; } } else{ [square[r][c] setLocation: &oldLocation]; [square[r][c] setType: t color: col]; [square[r][c] setRow: r]; } [self display]; PSflushgraphics(); NXPing(); } [self unlockFocus]; if (handler.code) { NX_RAISE(handler.code, handler.data1, handler.data2); } } NXCoord check_point( struct NXLine *l, NXPoint *p ) { NXCoord dx,dy,dx1,dy1; dx = l->a.x - l->b.x; dy = l->a.y - l->b.y; dx1 = p->x - l->a.x; dy1 = p->y - l->a.y; return( dx*dy1 - dy*dx1 ); } void convert_point( NXPoint *p, int *r, int *c ) { NXCoord dx,dy,dx1,dy1,m; int i; for( i = 0; i < 8; i++ ) if( p->y >= horizontal[i] && p->y <= horizontal[i+1] ){ *r = i; break; } for( i = 0; i < 8; i++ ){ NXCoord m1,m2; m1 = check_point( &vertical[i], p ); m2 = check_point( &vertical[i+1], p ); if( m1 > 0 && m2 < 0 ){ *c = i; break; } } } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.