世界在我的战略游戏是由许多塔组成。在游戏开始时,只生成一个塔,当玩家发现新的塔时,他们被创建并添加到游戏控制的塔阵列中。塔楼后的第一个塔楼以不同的设置开始。例如,他们不从工人和动物开始,不同的楼层显示和配置。
以前,我在Tower类的初始化过程中使用了所有这些代码。这个类有太多的责任,并且增加到超过1200行,所以我一直在寻找方法来重构它,以尽可能多地删除代码,这样就更容易理解了。为了实现这个目标,我创建了一个工厂类来创建一个塔。游戏调用工厂类的类方法,并得到一个完全配置的塔作为回报。这使塔类减少了近200行。
这是我第一次创建一个工厂类,我认为我的实现肯定需要一些反馈。我决定使用一个类方法,这样我就不需要这个工厂类的实际实例来创建这些塔了。其结果是,我需要在工厂类中使用C函数。其他选项是创建一个类似于normal的类,并在游戏开始时创建一个工厂类的实例。另一种选择是创建一个单例,以获得类似于类方法的语法,同时也具有拥有实例方法的能力。
我应该指出,worldSize到处传播的原因是为了确保游戏与不同的屏幕分辨率兼容。
我对代码的所有方面都持批评态度,但最重要的是这是否是一个工厂类的良好实现。
标头只包含类方法,所以我将省略它。
#import "DTAnimal.h"
#import "DTDwarf.h"
#import "DTTower.h"
#import "DTTowerFactory.h"
#import "DTTowerFloor.h"
@implementation DTTowerFactory
+(DTTower *) towerWithWorldSize:(CGSize)worldSize isFirstTower:(BOOL)isFirstTower {
DTTower *tower = [[DTTower alloc]initWithWorldSize:worldSize];
if (isFirstTower) {
createTowerFloors(tower, worldSize);
setBackgroundTypes(tower);
setupInitialTowerFloors(tower);
createTowerDwarves(tower, worldSize);
createTowerAnimals(tower, worldSize);
} else {
createTowerFloors(tower, worldSize);
setBackgroundTypes(tower);
setupTowerFloors(tower);
}
return tower;
}
#pragma mark - Tower Defaults
void createTowerFloors(DTTower* tower, CGSize worldSize) {
int topFloor = 10; // later this will be influenced by a gravity setting
//a random number of floors underground, not less than 90
int randomBottomFloor = arc4random_uniform(31) + 90;
int bottomFloor = -randomBottomFloor;
//create the floors and set them all to dirt to start
for (int i = bottomFloor; i <= topFloor; i++) {
NSNumber *floorNumber = [NSNumber numberWithInteger:i];
DTTowerFloor *floor = [[DTTowerFloor alloc]initWithType:Dirt andFloor:i andWorldSize:worldSize];
[tower.towerDict setObject:floor forKey:floorNumber];
}
//the top floors do not have ground or blocks for mining
for (int i = topFloor; i >= 0; i--) {
NSNumber *floorNumber = [NSNumber numberWithInt:i];
DTTowerFloor *floor = [tower.towerDict objectForKey:floorNumber];
[floor.groundBlocks removeAllObjects];
floor.groundType = NoGround;
}
//randomly determine where the different ground types start
int randomStartingDirtRockFloor = (arc4random_uniform(15) + 15);
int randomStartingRockFloor = (arc4random_uniform(30) + randomStartingDirtRockFloor);
int randomStartingRockLavaFloor = (arc4random_uniform(30) + randomStartingRockFloor);
//have to make them all negative inside these loops
for (int i = -randomStartingDirtRockFloor; i > -randomStartingRockFloor; i--) {
NSNumber *floorNumber = [NSNumber numberWithInt:i];
DTTowerFloor *floor = [tower.towerDict objectForKey:floorNumber];
floor.groundType = DirtRock;
}
for (int i = -randomStartingRockFloor; i > -randomStartingRockLavaFloor; i--) {
NSNumber *floorNumber = [NSNumber numberWithInt:i];
DTTowerFloor *floor = [tower.towerDict objectForKey:floorNumber];
floor.groundType = Rock;
}
for (int i = -randomStartingRockLavaFloor; i > bottomFloor; i--) {
NSNumber *floorNumber = [NSNumber numberWithInt:i];
DTTowerFloor *floor = [tower.towerDict objectForKey:floorNumber];
floor.groundType = RockLava;
}
}
void setBackgroundTypes(DTTower* tower) {
for (id key in tower.towerDict) {
DTTowerFloor *floor = [tower.towerDict objectForKey:key];
//could use this later to have a weighted average
//int floorNumber = floor.floorNumber;
//int backgroundType;
//but for now it will be a simple range
int randomNumber = arc4random_uniform(80);
//int randomNumber = skRand(0, 80);
if (randomNumber < 10) {
floor.backgroundType = 0;
} else if (randomNumber >= 10 && randomNumber < 20) {
floor.backgroundType = 1;
} else if (randomNumber >= 20 && randomNumber < 30) {
floor.backgroundType = 2;
} else if (randomNumber >= 30 && randomNumber < 40) {
floor.backgroundType = 3;
} else if (randomNumber >= 40 && randomNumber < 50) {
floor.backgroundType = 4;
} else if (randomNumber >= 50 && randomNumber < 60) {
floor.backgroundType = 5;
} else if (randomNumber >= 60 && randomNumber < 70) {
floor.backgroundType = 6;
} else if (randomNumber >= 70 && randomNumber < 80) {
floor.backgroundType = 7;
}
}
}
#pragma mark - First Tower
void setupInitialTowerFloors(DTTower* tower) {
for (int i = 0; i > -4; i--) {
NSNumber *floorNumber = [NSNumber numberWithInt:i];
DTTowerFloor *floor = [tower.towerDict objectForKey:floorNumber];
floor.isRevealed = YES;
//adds ladders here for convenience
floor.floorBuildState |= FloorHasLadder;
}
//have to do three floors manually for the top and bottom and floor 0
NSNumber *floorNumber0 = [NSNumber numberWithInt:0];
DTTowerFloor *tempFloor0 = [tower.towerDict objectForKey:floorNumber0];
tempFloor0.floorBuildState |= FloorHasWalls | FloorHasBottom | FloorHasRoom;
NSNumber *floorNumber1 = [NSNumber numberWithInt:1];
DTTowerFloor *tempFloor1 = [tower.towerDict objectForKey:floorNumber1];
tempFloor1.isRevealed = YES;
tempFloor1.floorBuildState |= FloorHasBottom;
NSNumber *floorNumber2 = [NSNumber numberWithInt:-4];
DTTowerFloor *tempFloor2 = [tower.towerDict objectForKey:floorNumber2];
tempFloor2.isRevealed = YES;
}
void createTowerDwarves(DTTower* tower, CGSize worldSize) {
int numStartingDwarves = 5;
for (int i = 0; i < numStartingDwarves; i++){
DTDwarf *newDwarf = startingDwarf(worldSize);
[tower.towerDwarves addObject:newDwarf];
[tower.dwarfListForRender addObject:newDwarf];
}
}
DTDwarf* startingDwarf(CGSize worldSize) {
DTDwarf *dwarf = [[DTDwarf alloc]initWithWorldSize:worldSize];
dwarf.dwarfMovement.currentFloor = -1;
dwarf.dwarfMovement.destinationFloor = dwarf.dwarfMovement.currentFloor;
dwarf.dwarfMovement.currentPosition = CGPointMake(0, dwarf.dwarfMovement.currentFloor * worldSize.height/6 - worldSize.height/6/3);
return dwarf;
}
void createTowerAnimals(DTTower* tower, CGSize worldSize) {
DTTowerFloor *floor = [tower.towerDict objectForKey:[NSNumber numberWithInt:0]];
int numStartingAnimals = 3;
for (int i = 0; i < numStartingAnimals; i++) {
[floor acceptAnimal:startingAnimal(worldSize)];
}
}
DTAnimal* startingAnimal(CGSize worldSize) {
int randomNumber = arc4random_uniform(3);
DTAnimal *animal = [[DTAnimal alloc]initWithAnimalType:randomNumber andWorldSize:worldSize];
return animal;
}
#pragma mark - Additional Towers
void setupTowerFloors(DTTower* tower) {
int startingFloorOffset = -51;
int randomNumber = arc4random_uniform(25);
int startingFloorInt = startingFloorOffset + randomNumber;
int oneFloorAboveInt = startingFloorInt + 1;
int oneFloorBelowInt = startingFloorInt - 1;
[tower assignStartingFloorForNewTower:startingFloorInt];
NSNumber *startFloorNum = [NSNumber numberWithInt:startingFloorInt];
DTTowerFloor *startFloor = [tower.towerDict objectForKey:startFloorNum];
[startFloor.groundBlocks removeAllObjects];
startFloor.isRevealed = YES;
startFloor.floorBuildState |= FloorHasLadder | FloorHasWalls | FloorHasBottom | FloorHasRoom | FloorHasRoomUpgrade;
[startFloor buildRoomUpgrade:RoomTypeGatewayExit];
NSNumber *oneFloorAboveNum = [NSNumber numberWithInt:oneFloorAboveInt];
DTTowerFloor *oneFloorAbove = [tower.towerDict objectForKey:oneFloorAboveNum];
oneFloorAbove.isRevealed = YES;
NSNumber *oneFloorBelowNum = [NSNumber numberWithInt:oneFloorBelowInt];
DTTowerFloor *oneFloorBelow = [tower.towerDict objectForKey:oneFloorBelowNum];
oneFloorBelow.isRevealed = YES;
}
@end这里是塔的初始化,我将包括它,因为这个方法调用它开始创建塔。这里包括实例变量和属性。我本可以在工厂类中初始化这些属性,但为了简单起见,我将它们留在这里。我不知道这是否正确的选择。
-(id) initWithWorldSize:(CGSize)worldSize {
self = [super init];
if (self){
_worldSize = worldSize;
_towerDict = [[NSMutableDictionary alloc]init];
_balanceSettings = [[DTGameBalance alloc]init];
_completedJobs = [[NSMutableArray alloc]init];
_resourcesForCollection = [[NSMutableArray alloc]init];
_dwarvesForGamePickup = [[NSMutableArray alloc]init];
_startingFloorForNewTower = 0;
_towerEnemies = [[NSMutableArray alloc]init];
_towerDwarves = [[NSMutableArray alloc]init];
_towerAnimals = [[NSMutableArray alloc]init];
_deadDwarfStatsForPickup = [[NSMutableArray alloc]init];
_dwarfListForRender = [[NSMutableArray alloc]init];
}
return self;
}发布于 2014-09-13 00:50:18
我认为工厂班是完全没有必要的。我也不明白你是如何从一个文件中节省200行的。
在我看来,DTTowerFactory.m中的代码来自几个不同的文件(可能需要返回到这些文件)。
towerWithWorldSize:isFirstTower属于DTTower.m
createTowerFloors()应该返回一个NSDictionary对象,并且属于DTTowerFloor.m。你应该做的是:
someTower.towerDict = createTowerFloor(worldSize);setBackgroundTypes()可能只是createTowerFloors()函数的一部分。在创建地板时,有什么原因不能设置地板的背景类型吗?
setupInitialTowerFloors()和setupTowerFloors()又可能成为DTTowerFloor.m的一部分,就像createTowerFloors()一样。
startingDwarf()和createTowerDwarves可以移动到DTDwarf.m中。
startingAnimal()和createTowerAnimals()可以移动到DTAnimal.m中。
https://codereview.stackexchange.com/questions/62755
复制相似问题