1

Obj C 和一般编程的新手 - 从这个站点学到了很多东西,非常感谢每个人的贡献。

我的场景如下(编写一个解释有趣名字的 iPhone 游戏)

在我的主游戏循环(在我的视图控制器中)中,如果满足某个条件,我会创建一个敌人 - 樱桃炸弹

if (bounceCounterGlobal % 2 == 0 && bounceCounterGlobal > 1 && cherryBombSwitch == 0){
    [self addCherryBomb];
}

addCherryBomb 方法如下:

-(void) addCherryBomb{
    CherryBomb *myCherryBomb = [[CherryBomb alloc] init];
    [cherryBombArray insertObject:myCherryBomb atIndex:0];
    [myCherryBomb release];
    [[cherryBombArray objectAtIndex:0] initializeCherryBomb];
     [self.view addSubview:[[cherryBombArray objectAtIndex:0] cherryBombView]];
    cherryBombSwitch = 1;
}

CherryBomb 头文件很短:

#import <Foundation/Foundation.h>
#import "SimpleGameViewController.h"

    @interface CherryBomb : NSObject {

        UIImageView *cherryBombView;
        NSTimer *cherryBombDetonateTimer;
        NSTimer *cherryBombMoveTimer;
    }

    @property (nonatomic, retain) UIView *cherryBombView;

    -(void) initializeCherryBomb;
    -(void) detonateCherryBomb;
    -(void) moveCherryBomb;

    @end

我想要做的是当樱桃炸弹引爆(这是在cherryBomb 对象中确定的)时,我希望该对象从cherryBombArray 中移除自己,它是视图控制器的一个ivar。

我尝试调用视图控制器类方法来执行此操作 - 但我无法访问视图控制器的 ivars(因为它是一个类方法)。我不知道如何与视图控制器类进行通信以告诉它删除爆炸的对象。

@implementation CherryBomb
...
-(void) detonateCherryBomb{
    NSLog(@"KABOOM!");
    cherryBombDetonateTimer = nil;
    [cherryBombMoveTimer invalidate];
    [cherryBombView removeFromSuperview];
    //I would like to remove this object from the view controller's cherryBombArray
}
@end

非常感谢您的帮助。先感谢您!

4

4 回答 4

2

我建议您创建一些“环境”对象来处理所有游戏逻辑。

樱桃炸弹不应该处理它的爆炸。cherryBomb 可以存储许多信息(爆炸的大小、爆炸的类型等),但cherryBomb 对其他“事物”(字符、炸弹等)的影响不应由cherryBomb 本身计算。

我不太习惯游戏编程,但架构/设计的这一方面很常见:每个对象/类都有其职责。

cherryBomb 代表炸弹,仅此而已(也不是“图形”方面)。

环境代表当前时刻的“世界”,并建模世界元素之间的动作/交互。

关于设计游戏的最佳方式有很多话要说……

无论如何,要给您的问题一个答案,您仍然可以使用“事件”。炸弹可以向您的控制器发送一条消息,告诉他:“我爆炸了,请移开我”。

在炸弹中:

[[NSNotificationCenter defaultCenter] postNotificationName:@"kaBOOM" 
                                                    object:self];

在控制器中:

[NSNotificationCenter defaultCenter] addObserver:self
                                        selector:@selector(methodToCallWhenKaBOOM) 
                                            name:@"kaBOOM" 
                                          object:nil];

- (void)methodToCallWhenKaBOOM:(NSNotification *)note
{
    // do stuffs
}

http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSNotificationCenter_Class/Reference/Reference.html

于 2010-10-20T20:45:45.067 回答
1

有很多方法可以做到这一点,您可能需要考虑这里的确切分工,在控制器和模型方面。如果您来回调用太多,事情可能会变得非常意大利面。

但是,如果不深入了解所有这些,您需要做的基本事情是允许一个对象访问另一个对象,即为第一个对象提供对第二个对象的引用。

在这种情况下,您实际上是CherryBomb在视图控制器中创建 ,因此很容易在此时向它传递一个引用。给你的CherryBomb班级另一个像这样的 ivar:

SimpleGameViewController* cherryBombViewController;

修改CherryBomb以便init方法或您的方法initializeCherryBomb(这些可能应该只是一个方法,顺便说一句)采用这样的指针并将其分配给 ivar:

- (void) initializeCherryBomb:(SimpleGameViewController*)vc
{
    // ... whatever other stuff you do in here, plus something like:
    cherryBombViewController = vc;
}

当你调用它时,将它self作为vc参数传递。稍后,当你的炸弹引爆时,它可以调用你在控制器上添加的一些方法来移除自身:

[cherryBombViewController handleDetonationOfCherryBomb:self];

请注意,您绝对不应该直接访问控制器的数组——这是您的炸弹不应该知道的实现细节。在简单的情况下,您可以避免在控制结构中稍微马虎,但永远不要搞砸您的封装。

于 2010-10-20T21:11:29.460 回答
0

我认为这是关键值观察的一个很好的应用。您需要一个代表其状态的樱桃炸弹的属性,例如

@property (assign) BOOL isExploded;

任何对樱桃炸弹是否爆炸感兴趣的对象都会在 isExploded 属性上为 KVO 注册自己。例如,视图控制器可能会:

[cherryBomb addObserver: self
             forKeyPath: @"isExploded"
                options: ....
                context: ....];

并在-observeValueForKeyPath:ofObject:change:context:视图控制器中从数组中删除樱桃炸弹。

您的 detonate 方法执行以下操作以及它当前正在执行的所有其他操作:

[self setExploded: YES];
于 2010-10-21T10:14:27.920 回答
0

阅读 MVC 设计模式。如果您发现需要在视图之间共享的 ivars,它们可能应该进入更高级别的模型对象(MVC 的 M),而不是让某些视图在其他视图的 ivars 中达到峰值。然后可以将指向此模型对象的指针向下传递给需要访问它的所有视图对象。

于 2010-10-20T22:26:46.413 回答