This is EmpireImageVendor.m in view mode; [Download] [Up]
//
// $Id: EmpireImageVendor.m,v 1.11 1997/10/31 04:51:48 nygard Exp $
//
//
// This file is a part of Empire, a game of exploration and conquest.
// Copyright (C) 1996 Steve Nygard
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// You may contact the author by:
// e-mail: nygard@telusplanet.net
//
#import "Empire.h"
RCSID ("$Id: EmpireImageVendor.m,v 1.11 1997/10/31 04:51:48 nygard Exp $");
#import "EmpireImageVendor.h"
#import "Token.h"
static EmpireImageVendor *_instance = nil;
// Common images
static NSImage *default_cursor;
static NSImage *direction_cursor;
static NSImage *explosion;
struct image_names
{
NSString *i_name;
NSImage **i_image;
};
static struct image_names class_images[] =
{
{ @"cursor.tiff", &default_cursor },
{ @"direction_cursor.tiff", &direction_cursor },
{ @"explosion.tiff", &explosion },
};
//======================================================================
// This provides access to many of the images required by Empire,
// especially since most of them are dynamically generated. It also
// provides notification to observers when any of the player colors
// change, so that views that use these images can be updated with the
// new colors.
//======================================================================
#define EmpireImageVendor_VERSION 1
@implementation EmpireImageVendor
+ (void) initialize
{
if (self == [EmpireImageVendor class])
{
[self setVersion:EmpireImageVendor_VERSION];
// It appears that there is no guarantee that we can get the bundle
// in this method, so we have to work around this.
if ([NSBundle bundleForClass:self] == nil)
{
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector (loadClassImages)
name:NSApplicationDidFinishLaunchingNotification
object:NSApp];
}
else
{
[self loadClassImages];
}
}
}
//----------------------------------------------------------------------
+ (void) loadClassImages
{
int l;
NSBundle *thisBundle;
NSString *imagePath;
if (self == [EmpireImageVendor class])
{
thisBundle = [NSBundle bundleForClass:self];
NSAssert (thisBundle != nil, @"Could not get bundle.");
// load class images
for (l = 0; l < sizeof (class_images) / sizeof (struct image_names); l++)
{
imagePath = [thisBundle pathForImageResource:class_images[l].i_name];
NSAssert1 (imagePath != nil, @"Could not find image: '%@'", class_images[l].i_name);
*(class_images[l].i_image) = [[NSImage alloc] initByReferencingFile:imagePath];
NSAssert1 (*(class_images[l].i_image) != nil, @"Couldn't load image: '%@'\n", class_images[l].i_name);
}
}
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
//----------------------------------------------------------------------
+ instance
{
// Might want to grab colors from defaults.
if (_instance == nil)
{
NSColor *player1 = [NSColor colorWithCalibratedRed:34 / 255.0 green:255 / 255.0 blue:248 / 255.0 alpha:1.0];
NSColor *player2 = [NSColor colorWithCalibratedRed:255 / 255.0 green:26 / 255.0 blue:6 / 255.0 alpha:1.0];
NSColor *player3 = [NSColor colorWithCalibratedRed:243 / 255.0 green:255 / 255.0 blue:0 / 255.0 alpha:1.0];
_instance = [[EmpireImageVendor alloc] initWithColors:player1:player2:player3];
}
return _instance;
}
//----------------------------------------------------------------------
- initWithColors:(NSColor *)color1:(NSColor *)color2:(NSColor *)color3
{
Icon loop_to_land[] = {i_army, i_sentry, i_fighter, i_hovercraft};
Icon loop_to_water[] = {i_fighter, i_unloaded_transport, i_loaded_transport, i_submarine, i_destroyer,
i_cruiser, i_unloaded_carrier, i_loaded_carrier, i_battleship, i_hovercraft};
Player p;
int l;
[super init];
for (p = p_neutral; p <= p_player3; p++)
{
cityTokens[p] = [[Token alloc] initIcon:i_none onTerrain:t_city forPlayer:p];
cityImages[p] = [cityTokens[p] tokenImage];
}
for (p = p_neutral; p <= p_player3; p++)
{
for (l = 0; l < 4; l++)
{
onLandTokens[p][l] = [[Token alloc] initIcon:loop_to_land[l] onTerrain:t_land forPlayer:p];
onLandImages[p][l] = [onLandTokens[p][l] tokenImage];
}
for (l = 0; l < 10; l++)
{
onWaterTokens[p][l] = [[Token alloc] initIcon:loop_to_water[l] onTerrain:t_water forPlayer:p];
onWaterImages[p][l] = [onWaterTokens[p][l] tokenImage];
}
for (l = 0; l < 12; l++)
{
onCityTokens[p][l] = [[Token alloc] initIcon:i_army + l onTerrain:t_city forPlayer:p];
onCityImages[p][l] = [onCityTokens[p][l] tokenImage];
}
}
unknown = [[Token alloc] initIcon:i_none onTerrain:t_unknown forPlayer:p_neutral];
land = [[Token alloc] initIcon:i_none onTerrain:t_land forPlayer:p_neutral];
water = [[Token alloc] initIcon:i_none onTerrain:t_water forPlayer:p_neutral];
[self setColor:[NSColor lightGrayColor] forPlayer:p_neutral];
[self setColor:color1 forPlayer:p_player1];
[self setColor:color2 forPlayer:p_player2];
[self setColor:color3 forPlayer:p_player3];
observers = [[NSMutableArray array] retain];
return self;
}
//----------------------------------------------------------------------
- (void) dealloc
{
int l;
Player p;
for (p = p_neutral; p <= p_player3; p++)
{
SNRelease (cityTokens[p]);
for (l = 0; l < 4; l++)
SNRelease (onLandTokens[p][l]);
for (l = 0; l < 10; l++)
SNRelease (onWaterTokens[p][l]);
for (l = 0; l < 12; l++)
SNRelease (onCityTokens[p][l]);
}
// Notify things using this? Observer pattern?
SNRelease (observers);
[super dealloc];
}
//----------------------------------------------------------------------
- (NSColor *) colorForPlayer:(Player)p
{
return [Token colorForPlayer:p];
}
//----------------------------------------------------------------------
- (void) setColor:(NSColor *)aColor forPlayer:(Player)p
{
[Token setColor:aColor forPlayer:p];
[self recacheImagesForPlayer:p];
[self notify:(p == p_player1):(p == p_player2):(p == p_player3):(p == p_neutral)];
}
//----------------------------------------------------------------------
- (void) recacheImagesForPlayer:(Player)p
{
int l;
[cityImages[p] recache];
for (l = 0; l < 4; l++)
[onLandImages[p][l] recache];
for (l = 0; l < 10; l++)
[onWaterImages[p][l] recache];
for (l = 0; l < 12; l++)
[onCityImages[p][l] recache];
}
//----------------------------------------------------------------------
- (NSImage *) cursor
{
return default_cursor;
}
//----------------------------------------------------------------------
- (NSImage *) directionCursor
{
return direction_cursor;
}
//----------------------------------------------------------------------
- (NSImage *) unknown
{
return [unknown tokenImage];
}
//----------------------------------------------------------------------
- (NSImage *) land
{
return [land tokenImage];
}
//----------------------------------------------------------------------
- (NSImage *) water
{
return [water tokenImage];
}
//----------------------------------------------------------------------
- (NSImage *) explosion
{
return explosion;
}
//----------------------------------------------------------------------
- (NSImage *) neutralCity
{
return cityImages[p_neutral];
}
//----------------------------------------------------------------------
- (void) player:(Player)aPlayer:(NSImage **)city:(NSImage ***)onLand:(NSImage ***)onWater:(NSImage ***)onCity:(NSImage ***)odd
{
if (city != NULL)
*city = cityImages[aPlayer];
if (onLand != NULL)
*onLand = onLandImages[aPlayer];
if (onWater != NULL)
*onWater = onWaterImages[aPlayer];
if (onCity != NULL)
*onCity = onCityImages[aPlayer];
if (odd != NULL)
*odd = [Token oddballsForPlayer:aPlayer];
}
@end
//======================================================================
@implementation EmpireImageVendor (ObserverPattern)
- (void) attach:observer
{
// What if same observer attached twice, detached once?
[observers addObject:observer];
}
//----------------------------------------------------------------------
- (void) detach:observer
{
[observers removeObject:observer];
}
//----------------------------------------------------------------------
- (void) notify:(BOOL)player1:(BOOL)player2:(BOOL)player3:(BOOL)other
{
NSEnumerator *observerEnumerator = [observers objectEnumerator];
id tmp;
while (tmp = [observerEnumerator nextObject])
{
if ([tmp respondsToSelector:@selector (vendorImagesUpdated::::)] == YES)
{
[tmp vendorImagesUpdated:player1:player2:player3:other];
}
}
}
@end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.