我最近开始学习编程,在iPhone上制作我自己的3D OpenGL游戏,到目前为止已取得了相当不错的进展。我开始使用随iPhone SDK提供的基本OpenGL示例,这帮助我开始了一个良好的开端。然而,当我开始掌握一些事情时,我发现我在Objective C中进行了不必要的编程,这将使得将来将游戏移植到其他平台变得更加困难。所以我认为最好现在正确地使用C ++来避免以后的大量额外工作。
澄清一下:我实际上并没有使用任何对Apple(Objective C)函数或其他任何函数的调用,只是因为我将所有的条款都基于Objective C风格的init / dealloc / etc,所以我的引擎使用时看起来像Objective C类。我的目标是用C ++等价物替换所有目标C的东西...麻烦的是,对C ++来说还是新手,我不确定与什么相符!
这是我的一个类(myLight)的简单示例,在其当前的Objective C版本中:
// myLight.h
#import <OpenGLES/EAGL.h>
#import <OpenGLES/ES1/gl.h>
#import <OpenGLES/ES1/glext.h>
@interface myLight : NSObject {
char *name;
GLfloat *ambient, *diffuse, *specular, *position, *spotDirection;
GLfloat spotRadius;
GLfloat *matAmbient, *matDiffuse, *matSpecular;
GLfloat shininess;
Byte lightType;
}
@property (readonly) char *name;
@property (assign) GLfloat *position;
@property (assign) GLfloat *spotDirection;
@property (assign) GLfloat *ambient;
@property (assign) GLfloat *diffuse;
@property (assign) GLfloat *specular;
- (id)initWithContentsFromDatastream:(NSData *)fileData;
- (void)set;
@end
和相应的.mm文件:
// myLight.m
#import "myLight.h"
@implementation myLight
@synthesize name, ambient, diffuse, specular, position, spotDirection;
- (id)initWithContentsFromDatastream:(NSData *)fileData {
self = [super init];
NSData *fileContents = fileData;
uint ptr = 0;
Byte nameLength;
[fileContents getBytes:&nameLength range: NSMakeRange(ptr, sizeof(Byte))];
ptr++;
name = new char[nameLength];
[fileContents getBytes:name range: NSMakeRange(ptr, (nameLength * sizeof(char)) )];
ptr = ptr + (nameLength * sizeof(char) );
[fileContents getBytes:&lightType range: NSMakeRange(ptr, sizeof(Byte))];
ptr++;
position = new GLfloat[4];
for(int j = 0; j < (4); j++)
[fileContents getBytes:&position[j] range: NSMakeRange( (j* sizeof(float) ) + ptr, sizeof(float))];
ptr = ptr + (4 * sizeof(float));
if(lightType==2){
spotDirection = new GLfloat[3];
for(int j = 0; j < (3); j++)
[fileContents getBytes:&spotDirection[j] range: NSMakeRange( (j* sizeof(float) ) + ptr, sizeof(float))];
ptr = ptr + (3 * sizeof(float));
[fileContents getBytes:&spotRadius range: NSMakeRange(ptr, sizeof(float))];
ptr = ptr + sizeof(float);
} else
spotDirection = NULL;
diffuse = new GLfloat[4];
for(int j = 0; j < (4); j++)
[fileContents getBytes:&diffuse[j] range: NSMakeRange( (j* sizeof(float) ) + ptr, sizeof(float))];
ptr = ptr + (4 * sizeof(float));
ambient = new GLfloat[4];
for(int j = 0; j < (4); j++)
[fileContents getBytes:&ambient[j] range: NSMakeRange( (j* sizeof(float) ) + ptr, sizeof(float))];
ptr = ptr + (4 * sizeof(float));
specular = new GLfloat[4];
for(int j = 0; j < (4); j++)
[fileContents getBytes:&specular[j] range: NSMakeRange( (j* sizeof(float) ) + ptr, sizeof(float))];
ptr = ptr + (4 * sizeof(float));
[self set];
return self;
}
- (void)set{
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
glLightfv(GL_LIGHT0, GL_SPECULAR, specular);
glLightfv(GL_LIGHT0, GL_POSITION, position);
if(lightType==2)
glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, spotDirection);
}
- (void)dealloc {
delete[] specular;
delete[] ambient;
delete[] diffuse;
if (spotDirection)
delete[] spotDirection;
delete[] position;
delete[] name;
[super dealloc];
}
@end
如果有人可以指出哪些行需要更改,更重要的是,应该将它们更改为使其编译为纯C ++,我真的很感激。
非常感谢!
答案 0 :(得分:10)
首先,请记住,Objective-C不仅仅是C的“不同格式”,它是一种单独的语言,更重要的是,在Cocoa的情况下,一个单独的框架。因此,如果您希望将来能够将项目移植到其他平台,您不仅需要摆脱Objective-C,还需要摆脱Cocoa框架。
要将类从Objective-C映射到C ++,您必须执行以下操作:
-init...
方法-dealloc
方法#import
替换为#include
指令,因为此指令仅存在于Objective-C中(确保您包含的标题受到多个包含的保护)您应该花些时间考虑如何使用您正在撰写的代码。移植1:1可能不是一个好主意,因为在Cocoa和C ++(或任何其他语言/框架)中编码之间的习语存在很多差异。
答案 1 :(得分:8)
大多数应用程序逻辑可以翻译成C ++,但是在C ++中会有一些没有直接等价的东西。例如:
@encode()
编译器指令(用于NSValue和其他一些类)。doesNotRecognizeSelector:
,respondsToSelector:
,conformsToProtocol:
或performSelector:
(和其他类似性质的方法)。nil
发送消息,但在C ++中,在空指针上调用成员函数是不行的。NSString
添加一个方法,该方法计算名为numberOfSpaces
的空格数,并且它将可供所有NSString
使用finally
1}}你的应用程序中的实例。try
/ catch
的{{1}}块,但Objective-C对@finally
/ @try
有@catch
。 如果您计划将应用程序发布到多个平台,那么您可以尝试尽可能多地抽象到一个单独的库中。您的iPhone应用程序可以使用Objective-C编写并使用库中的函数,如果您计划将其移植到其框架需要C ++的另一个系统,那么您可以编写C ++应用程序并使用相同库中的相同函数。我想你的图书馆基本上都是[至少]你的绘图程序和核心游戏引擎逻辑。