This is SplatView.m in view mode; [Download] [Up]
/*
* SplatView.m
* Description
* subclass of BoardView specific to the game "Splat"
* History
* 14-Feb-93 Erik Kay Created
* 15-Mar-93 Erik Kay added sound
*/
#import "SplatView.h"
#import "SplatApp.h"
#import "SplatGame.h"
#import "SplatDefaults.h"
extern void animateMove (DPSTimedEntry te, double now, void *data);
extern void animateChange (DPSTimedEntry te, double now, void *data);
@implementation SplatView
- initFrame:(const NXRect *)r
{
NXSize sz;
[super initFrame:r];
/* image initialization */
obstructionImg = [[NXImage findImageNamed:"obstruction"] setScalable:YES];
one = [[NXImage findImageNamed:"one"] setScalable:YES];
two = [[NXImage findImageNamed:"two"] setScalable:YES];
numAnimationFrames = 9;
currentFrame = -1;
[obstructionImg getSize:&sz];
pieceSize = sz.width;
squareSize = pieceSize + 4;
/* sound initialization */
soundManager = [NXApp soundManager];
return self;
}
- drawHighlightedSquare:(NXRect *)rect at:(int)col :(int)row
{
NXRect r;
NX_WIDTH(rect) -= 4;
NX_HEIGHT(rect) -= 4;
NX_X(rect) += 2;
NX_Y(rect) += 2;
NXSetRect(&r,(currentFrame % 3) * pieceSize,
((8-currentFrame) / 3) * pieceSize, pieceSize, pieceSize);
if (currentPlayer == SQUARE_ONE)
[one composite:NX_SOVER fromRect:&r toPoint:&rect->origin];
else
[two composite:NX_SOVER fromRect:&r toPoint:&rect->origin];
currentFrame++;
return self;
}
- drawObstruction:(NXRect *)r at:(int)col :(int)row
{
NX_WIDTH(r) -= 4;
NX_HEIGHT(r) -= 4;
NX_X(r) += 2;
NX_Y(r) += 2;
[obstructionImg composite:NX_SOVER toPoint:&r->origin];
return self;
}
- drawPlayerOne:(NXRect *)r at:(int)col :(int)row
{
NXRect rect;
NX_WIDTH(r) -= 4;
NX_HEIGHT(r) -= 4;
NX_X(r) += 2;
NX_Y(r) += 2;
if ((moving && ((selectedCol == col) && (selectedRow == row))) ||
(changing))
{
NXSetRect(&rect,((8-currentFrame) % 3) * pieceSize,
((currentFrame) / 3) * pieceSize, pieceSize, pieceSize);
[one composite:NX_SOVER fromRect:&rect toPoint:&r->origin];
} else {
if (!((col == currentMove.from.col) && (row == currentMove.from.row) &&
(selectedCol == -1) && moving))
{
NXSetRect(&rect,pieceSize * 2, 0, pieceSize, pieceSize);
[one composite:NX_SOVER fromRect:&rect toPoint:&r->origin];
}
}
return self;
}
- drawPlayerTwo:(NXRect *)r at:(int)col :(int)row
{
NXRect rect;
NX_WIDTH(r) -= 4;
NX_HEIGHT(r) -= 4;
NX_X(r) += 2;
NX_Y(r) += 2;
if ((moving && ((selectedCol == col) && (selectedRow == row))) ||
(changing))
{
NXSetRect(&rect,((8-currentFrame) % 3) * pieceSize,
((currentFrame) / 3) * pieceSize, pieceSize, pieceSize);
[two composite:NX_SOVER fromRect:&rect toPoint:&r->origin];
} else {
if (!((col == currentMove.from.col) && (row == currentMove.from.row) &&
(selectedCol == -1) && moving))
{
NXSetRect(&rect, pieceSize * 2, 0, pieceSize, pieceSize);
[two composite:NX_SOVER fromRect:&rect toPoint:&r->origin];
}
}
return self;
}
- drawSelf:(const NXRect *)rects :(int)count
{
int tmpFrame;
if (resized) {
tmpFrame = currentFrame;
currentFrame = 0;
[super drawSelf:rects :count];
resized = NO;
currentFrame = tmpFrame;
} else
[super drawSelf:rects :count];
return self;
}
- doMoveAnimation:(move *)mv
{
if (abortGame) {
if (moveEntry) {
DPSRemoveTimedEntry(moveEntry);
moveEntry = NULL;
}
abortGame = NO;
}
currentMove = *mv;
board->currentMove = *mv;
if ((abs(currentMove.from.col - currentMove.to.col) > 1) ||
(abs(currentMove.from.row - currentMove.to.row) > 1))
moving = YES;
[self selectSquare:mv->from.col :mv->from.row];
moveEntry = DPSAddTimedEntry(0.02,animateMove,(void *)self,NX_BASETHRESHOLD);
currentFrame = 0;
currentPlayer = [board pieceAt:mv->from.col :mv->from.row];
[self display];
[self playSound:MOVE_SOUND atCol:mv->to.col];
return self;
}
- doAnimateMove
{
if (highlightedCol == -1) {
highlightedCol = currentMove.to.col;
highlightedRow = currentMove.to.row;
}
[boardCopy setPiece:SQUARE_ERROR at:highlightedCol :highlightedRow];
[self display];
return self;
}
- finishChangeAnimation
{
changing = NO;
currentFrame = -1;
[boardDiffs free];
boardDiffs = nil;
[board free];
board = newBoard;
newBoard = nil;
[self display];
[super finishChangeAnimation];
return self;
}
- finishMoveAnimation
{
currentFrame = -1;
[super finishMoveAnimation];
moving = NO;
return self;
}
- doChangeAnimation:(Board *)orig
{
move *mv;
int r, c, diffcount;
BOOL doit = NO;
boardDiffs = [board trueCopy];
[boardDiffs clearBoard];
newBoard = board;
board = [orig trueCopy];
for (c = 0; c < cols; c++) {
for (r = 0; r < rows; r++) {
if (([board pieceAt:c :r] != [newBoard pieceAt:c :r]) &&
([board pieceAt:c :r] != SQUARE_EMPTY) &&
([newBoard pieceAt:c :r] != SQUARE_EMPTY)) {
doit = YES;
[boardDiffs setPiece:[newBoard pieceAt:c :r] at:c :r];
}
}
}
if (doit) {
changeEntry = DPSAddTimedEntry(0.001,animateChange,(void *)self,NX_BASETHRESHOLD);
currentFrame = 0;
changing = YES;
mv = [orig currentMove];
currentPlayer = [board pieceAt:mv->from.col :mv->from.row];
diffcount = [boardDiffs numberOfPiece:SQUARE_ONE] +
[boardDiffs numberOfPiece:SQUARE_TWO];
if (diffcount >= 7)
[self playSound:WOWCHANGE_SOUND atCol:mv->to.col];
else if (diffcount >= 4)
[self playSound:BIGCHANGE_SOUND atCol:mv->to.col];
else
[self playSound:CHANGE_SOUND atCol:mv->to.col];
}
else
[self finishChangeAnimation];
return self;
}
- doAnimateChange
{
int r, c;
NXRect rect;
[self lockFocus];
for (c = 0; c < cols; c++)
for (r = 0; r < rows; r++) {
if ([boardDiffs pieceAt:c :r] == SQUARE_EMPTY)
continue;
NXSetRect(&rect,c * squareSize, r * squareSize,
squareSize, squareSize);
[self drawEmptySquare:&rect at:c :r];
switch ([boardDiffs pieceAt:c :r]) {
case SQUARE_ONE:
if (direction == -1)
[self drawPlayerOne:&rect at:c :r];
else
[self drawPlayerTwo:&rect at:c :r];
break;
case SQUARE_TWO:
if (direction == -1)
[self drawPlayerTwo:&rect at:c :r];
else
[self drawPlayerOne:&rect at:c :r];
break;
case SQUARE_BLOCKED:
case SQUARE_EMPTY:
default:
break;
}
}
[self unlockFocus];
currentFrame += direction;
[window flushWindow];
NXPing();
return self;
}
- scaleImages
{
NXSize sz;
int c, r;
if (scalable) {
[obstructionImg getSize:&sz];
if (sz.width == pieceSize)
return self;
if (obstructionImg != [NXImage findImageNamed:"obstruction"]) {
[obstructionImg free];
[one free];
[two free];
obstructionImg = [NXImage findImageNamed:"obstruction"];
one = [NXImage findImageNamed:"one"];
two = [NXImage findImageNamed:"two"];
}
sz.width = sz.height = pieceSize;
obstructionImg = [obstructionImg copy];
one = [one copy];
two = [two copy];
[obstructionImg setSize:&sz];
[one getSize:&sz];
c = sz.width / 48.0;
r = sz.height / 48.0;
sz.width = c * pieceSize;
sz.height = r * pieceSize;
[one setSize:&sz];
[two getSize:&sz];
c = sz.width / 48.0;
r = sz.height / 48.0;
sz.width = c * pieceSize;
sz.height = r * pieceSize;
[two setSize:&sz];
}
return self;
}
- setBoard:(Board *)b
{
[window disableFlushWindow];
squareSize = (int)[[NXApp defaultsManager] squareSize];
pieceSize = squareSize - 4;
[super setBoard:b];
moving = changing = NO;
currentFrame = 0;
if (squareSize != 52)
scalable = YES;
if (scalable)
[self scaleImages];
if (boardCopy) {
[boardCopy free];
boardCopy = nil;
}
[window display];
[window reenableFlushWindow];
[window flushWindow];
return self;
}
- windowDidResize:sender
{
scalable = YES;
squareSize = NX_HEIGHT(&frame) / rows; // both width and height should work
[[NXApp defaultsManager] setSquareSize:squareSize];
pieceSize = squareSize - 4;
[self scaleImages];
[boardCopy free];
boardCopy = nil;
resized = YES;
[self display];
[window flushWindow];
return self;
}
- windowWillResize:sender toSize:(NXSize *)newSize
{
NXRect winR;
NXSize curSize, minSize;
float dx, dy, ratio;
ratio = (float)rows / cols;
[window getFrame:&winR];
curSize = winR.size;
dx = newSize->width - curSize.width;
dy = newSize->height - curSize.height;
if (abs(dx) > abs(dy)) {
dy = dx * ratio;
} else if (abs(dy) > abs(dx)) {
dx = dy / ratio;
} else {
if (rows > cols)
dx = dy / ratio;
else if (rows < cols)
dy = dx / ratio;
}
newSize->width = curSize.width + dx;
newSize->height = curSize.height + dy;
[window getMinSize:&minSize];
if (newSize->width < minSize.width) {
dx = minSize.width - newSize->width;
dy = dx * ratio;
newSize->width = minSize.width;
newSize->height += dy;
}
if (newSize->height < minSize.height) {
dy = minSize.height - newSize->height;
dx = dy / ratio;
newSize->height = minSize.height;
newSize->width += dx;
}
return self;
}
- windowWillClose:sender
{
id ret = [game windowWillClose:sender];
if (ret)
[game perform:@selector(free) with:nil
afterDelay:100 cancelPrevious:NO];
return ret;
}
- gameOver
{
[super gameOver];
return self;
}
- playSound:(int)which atCol:(int)c
{
float l, r;
if ([[NXApp defaultsManager] playSounds]) {
l = 1 - ((float)(c + 1)/(float)cols);
r = 1 - l;
[soundManager playSound:which withGainLeft:l right:r];
}
return self;
}
@end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.