This is TetApp.m in view mode; [Download] [Up]
#import <appkit/Button.h>
#import <appkit/ButtonCell.h>
#import <appkit/Panel.h>
#import <appkit/Window.h>
#import <appkit/TextField.h>
#import <appkit/graphics.h>
#import <string.h>
#import <ctype.h>
#import "TetApp.h"
#import "NextMatrix.h"
#import "ScoreKeeper.h"
#import "TetMatrix.h"
@implementation TetApp
- initForColor
{
const NXScreen *deepestScreen;
const char *str;
str = NXGetDefaultValue([NXApp appName], "ColorOff");
if (str != NULL && (strcmp(str, "YES") == 0)) {
colorOff = YES;
gameInColor = NO;
#ifdef DEBUG
fprintf(stderr, "Game wants to be B&W\n");
#endif
} else {
colorOff = NO;
deepestScreen = [NXApp colorScreen];
if ( deepestScreen->depth != NX_TwoBitGrayDepth ) {
// Then 12 bit color should be more than enough
[tetrisWindow setDepthLimit:NX_TwelveBitRGBDepth];
gameInColor = YES;
} else {
gameInColor = NO;
}
}
return self;
}
+ new
{
self = [super new];
[self setDelegate:self];
[self initForColor];
started = paused = NO;
numRandomRows = 4;
return self;
}
- setLevelLeft:anObject
{
levelLeft = anObject;
[[levelLeft cell] setHighlightsBy:NX_CONTENTS | NX_CHANGEGRAY];
[levelLeft sendActionOn:NX_MOUSEDOWNMASK];
return self;
}
- setLevelRight:anObject
{
levelRight = anObject;
[[levelRight cell] setHighlightsBy:NX_CONTENTS | NX_CHANGEGRAY];
[levelRight sendActionOn:NX_MOUSEDOWNMASK];
return self;
}
- (BOOL) isGameColor
{
return gameInColor;
}
- setTetrisWindow:anObject
{
tetrisWindow = anObject;
[tetrisWindow setDelegate:self];
[tetrisWindow setMiniwindowIcon:"Tetris"];
return self;
}
- appDidInit:sender
{
const char *str;
int levelValue;
[controlWindow removeFromEventMask:NX_KEYDOWNMASK|NX_KEYUPMASK];
[controlWindow orderFront:self];
str = NXGetDefaultValue([NXApp appName], "CurrentLevel");
if (str != NULL) {
sscanf(str, "%d", &levelValue);
[level setIntValue: levelValue];
[self updateLeft: levelValue];
[self updateRight: levelValue];
#ifdef DEBUG
fprintf(stderr, "Setting current level to %d\n", levelValue);
#endif
}
str = NXGetDefaultValue([NXApp appName], "RandomRows");
if (str != NULL) {
sscanf(str, "%d", &numRandomRows);
[randomField setIntValue:numRandomRows];
[randomSlider setIntValue:numRandomRows];
#ifdef DEBUG
fprintf(stderr, "Setting number Random rows to %d\n", numRandomRows);
#endif
}
str = NXGetDefaultValue([NXApp appName], "ShowNext");
if (str != NULL) {
if (strcmp(str, "YES") == 0) {
[showNextSwitch setIntValue: YES];
[showNext showNext:showNextSwitch]; // ID is actually ignored
}
}
[colorSwitch setIntValue: colorOff];
[tetrisWindow orderWindow:NX_ABOVE relativeTo:0];
[tetrisWindow makeKeyWindow];
return self;
}
- (BOOL) gamePaused
{
return paused;
}
- keyDown:(NXEvent *)theEvent
{
unsigned short charCode;
printf("Keydown in TetApp\n");
charCode = theEvent->data.key.charCode;
if (isupper(charCode))
charCode = tolower(charCode);
switch (charCode) {
case 13: // Pause if the user hits return
[self pause:self];
}
return self;
}
- resignActiveApp
{
if (started && !paused)
[self pause:self];
return [super resignActiveApp];
}
- updateLeft:(int) theLevel
{
if (theLevel <= MIN_LEVEL) {
[[levelLeft setEnabled:NO] setIcon:"scrollMenuLeftD"];
} else {
[[levelLeft setEnabled:YES] setIcon:"scrollMenuLeft"];
}
return self;
}
- updateRight:(int) theLevel
{
if (theLevel >= MAX_LEVEL) {
[[levelRight setEnabled:NO] setIcon:"scrollMenuRightD"];
} else {
[[levelRight setEnabled:YES] setIcon:"scrollMenuRight"];
}
return self;
}
- start:sender
{
int levelValue = [level intValue];
if (started) {
if (paused)
[self pause:sender];
[tetrisView stop:sender];
[[tetrisView window] disableFlushWindow];
[showNext end:self];
[startButton setTitle:"New game"];
[pauseButton setEnabled:NO];
[levelLeft setTransparent:NO];
[levelRight setTransparent:NO];
[self updateLeft: levelValue];
[self updateRight: levelValue];
[[[tetrisView window] reenableFlushWindow] flushWindow];
started = NO;
} else {
[[tetrisView window] disableFlushWindow];
[showNext start:self];
[startButton setTitle:"Abort"];
[pauseButton setEnabled:YES];
[scoreKeeper setZero];
[tetrisView setScoreKeeper:scoreKeeper];
[[levelLeft setTransparent:YES] setEnabled:NO];
[[levelRight setTransparent:YES] setEnabled:NO];
[[[tetrisView window] reenableFlushWindow] flushWindow];
[tetrisView newGame:levelValue];
started = YES;
}
return self;
}
- pause:sender
{
[[tetrisView window] disableFlushWindow];
if (paused) {
[pauseButton setTitle:"Pause"];
[pauseDisplay setStringValueNoCopy:""];
[tetrisView continue:sender];
paused = NO;
} else {
[tetrisView pause:sender];
[pauseButton setTitle:"Continue"];
[pauseDisplay setStringValueNoCopy:"PAUSED"];
paused = YES;
}
[[[tetrisView window] reenableFlushWindow] flushWindow];
return self;
}
- gameOver
{
int levelValue = [level intValue];
[[tetrisView window] disableFlushWindow];
[showNext end:self];
[startButton setTitle:"New game"];
[pauseButton setEnabled:NO];
[levelLeft setTransparent:NO];
[levelRight setTransparent:NO];
[self updateLeft: levelValue];
[self updateRight: levelValue];
[[[tetrisView window] reenableFlushWindow] flushWindow];
NXPing();
started = NO;
[scoreKeeper updateHighScores:levelValue];
return self;
}
- levelLeft:sender
{
int levelValue = [level intValue];
if (levelValue != MIN_LEVEL) {
[level setIntValue:--levelValue];
[self updateLeft: levelValue];
[self updateRight: levelValue];
}
return self;
}
- levelRight:sender
{
int levelValue = [level intValue];
if (levelValue != MAX_LEVEL) {
[level setIntValue:++levelValue];
[self updateLeft: levelValue];
[self updateRight: levelValue];
}
return self;
}
/*
* Set the number of rows where random pieces will appear.
*/
- setRandomRows:sender
{
int tmp;
tmp = [sender intValue];
// Will always be valid since slider is the only object that can call me!?
if (tmp >= 0 && tmp <=10) {
numRandomRows = tmp;
[randomField setIntValue: tmp];
} else {
[randomField setIntValue:numRandomRows];
}
return self;
}
/*
* Let user use monochrome blocks to get better speed.
*/
- adjustColor:sender
{
int value = [sender intValue];
colorOff = value;
if ( (colorOff == NO) && ([NXApp colorScreen] != NX_TwoBitGrayDepth)) {
gameInColor = YES;
}
if (colorOff == YES) {
[tetrisWindow setDepthLimit:NX_TwoBitGrayDepth];
} else {
[tetrisWindow setDepthLimit:NX_TwelveBitRGBDepth];
}
if (value == YES) {
fprintf(stderr, "Turing color off\n");
} else {
fprintf(stderr, "Turing color on\n");
}
return self;
}
/*
* User has clicked quit.
* If the game is in progress then verify the quit.
* Save high scores and default values.
*/
- terminate:sender
{
char buf[20];
if (started &&
NXRunAlertPanel("Quit", "Game is still in progress. Really quit?",
"Quit", "Cancel", NULL) == NX_ALERTALTERNATE)
return self;
// Clean up and die
[scoreKeeper writeScores];
sprintf(buf,"%d", [level intValue]);
NXWriteDefault ([NXApp appName], "CurrentLevel", buf);
NXWriteDefault ([NXApp appName], "ColorOff", ([colorSwitch intValue]) ? "YES" : "NO");
sprintf(buf,"%d", numRandomRows);
NXWriteDefault ([NXApp appName], "RandomRows", buf);
NXWriteDefault ([NXApp appName], "ShowNext", ([showNextSwitch intValue]) ? "YES" : "NO");
return [super terminate:sender];
}
/*
* Allow the user to set the blocks images that make up the pieces
*/
- setBlocks:sender
{
return self;
}
- windowWillMiniaturize:sender toMiniwindow:miniwindow
{
if (started && !paused)
[self pause:sender];
return self;
}
- windowDidMove:sender
{
NXRect aRect;
float newX, newY;
[[tetrisView window] getFrame:&aRect];
newX = aRect.origin.x + aRect.size.width + 5.;
newY = aRect.origin.y;
[controlWindow moveTo: newX :newY];
return self;
}
/*
* Must bring the control panel to the front too.
*/
- windowDidBecomeKey:sender
{
[controlWindow orderFront:self];
return self;
}
@end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.