ios Scenekit三维开发以及外接SpriteKit二维界面开发

来源:互联网 发布:linux 创建www用户 编辑:程序博客网 时间:2024/06/03 10:10

1.File->New ->Project...

2.选择Game模板工程,然后点击Next;

3.设置工程名,GameTechnology选择Scenekit,此为三维模板基类;SpriteKit为二维游戏的基础模板;语言选择的是ObejectC,当然了,好多人是选择swift的,这个好开发嘛;点击Next,选择工程保存位置;OK,工程建好了。

4.然后运行查看效果,是一个支持手势操作的旋转的飞机。下方有一个统计面板。方便开发时候查看性能,发布的时候可以代码关闭。

5.接下来说一些技术:

5.1 加载obj文件方法

    NSString* resPath = [[NSBundle mainBundle] resourcePath];    NSString * str2 = @"/art.scnassets/car/yjjcar.obj";    NSString *string = [resPath stringByAppendingString:str2];    NSURL* nsurl = [NSURL fileURLWithPath:string];    MDLAsset *asset = [[MDLAsset alloc] initWithURL:nsurl];    carnode = [SCNNode nodeWithMDLObject:[asset objectAtIndex:0]];    carnode.scale = SCNVector3Make(0.01, 0.01, 0.01);    [self.scene.rootNode addChildNode:carnode];

 

5.2 模型旋转

    floorNode.transform = SCNMatrix4Rotate(floorNode.transform, M_PI/2, 1, 0, 0);    [self.scene.rootNode addChildNode:floorNode];

5.3 计时器

[NSTimer scheduledTimerWithTimeInterval:0.15 target:self selector:@selector(actionTimer:) userInfo:nil repeats:YES];

- (void)actionTimer:(NSTimer *)timer{}

5.4 添加手势操作

初始化的时候

[selfaddGesture];

addGesture定义

- (void)addGesture{    //一指拖拽手势    UIPanGestureRecognizer *pan     = [[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(handlePan:)];    pan.minimumNumberOfTouches      = 1;    pan.maximumNumberOfTouches      = 1;    pan.delegate                    = self;    [self.view addGestureRecognizer:pan];        UIPinchGestureRecognizer *pinchRecognizer = [[UIPinchGestureRecognizer alloc]                                                                                                  initWithTarget:self action:@selector(scale:)];        UIRotationGestureRecognizer *rotationGesture = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:@selector(rotatePiece:)];        [pinchRecognizer setDelegate:self];    [self.view addGestureRecognizer:pinchRecognizer];    [self.view addGestureRecognizer:rotationGesture];}

- (void)handlePan:(UITapGestureRecognizer *)gestureRecognizer{    static float previousX,previousY;    CGPoint p = [gestureRecognizer locationInView:self.sceneView];    if (gestureRecognizer.state == UIGestureRecognizerStateEnded) {    }else if (gestureRecognizer.state == UIGestureRecognizerStateBegan) {    }else if (gestureRecognizer.state == UIGestureRecognizerStateChanged) {        float dx = p.x - previousX;        float dy = p.y - previousY;                [self transCamera:dx dy:dy];    }    previousX = p.x;previousY = p.y;}

-(void)scale:(UIPinchGestureRecognizer*)sender {    //当手指离开屏幕时,将lastscale设置为1.0    if([sender state] == UIGestureRecognizerStateEnded) {        lastScale = 1.0;        return;    }        CGFloat scale = 1.0 - (lastScale - [(UIPinchGestureRecognizer*)sender scale]);    [self ScaleCamera:scale];    lastScale = [sender scale];}

5.5 直接根据顶点数据绘制线条

-(void) drawArea{//    //三角形网格场地    SCNGeometrySource *vertexSource = [SCNGeometrySource geometrySourceWithVertices:&g_Vertices[0]                                                                              count:g_Vertices.size()];    NSData *indexData = [NSData dataWithBytes:&g_Indices[0]                                       length:g_Indices.size()*4];    SCNGeometryElement *element = [SCNGeometryElement geometryElementWithData:indexData                                                                primitiveType:SCNGeometryPrimitiveTypeTriangles                                                               primitiveCount:g_Indices.size()/3                                                                bytesPerIndex:sizeof(int)];    SCNGeometry *triangles = [SCNGeometry geometryWithSources:@[vertexSource]                                                elements:@[element]];    SCNMaterial* myMaterial = [SCNMaterial new];    [myMaterial setDoubleSided:true];    myMaterial.diffuse.contents =[UIColor colorWithRed:0.336 green:0.336 blue:0.336 alpha:1];        triangles.firstMaterial = myMaterial;    SCNNode *trianglesNode = [SCNNode nodeWithGeometry:triangles];//    [self.scene.rootNode addChildNode:trianglesNode];        //白色场地边线绘制    SCNGeometrySource *vertexSource2 = [SCNGeometrySource geometrySourceWithVertices:&m_whiteLineVertices[0]                                                                              count:m_whiteLineVertices.size()];    NSData *indexData2 = [NSData dataWithBytes:&m_whiteLineIndices[0]                                        length:m_whiteLineIndices.size()*4];    SCNGeometryElement *element2 = [SCNGeometryElement geometryElementWithData:indexData2                                                                 primitiveType:SCNGeometryPrimitiveTypeLine                                                                primitiveCount:m_whiteLineIndices.size()/2                                                                bytesPerIndex:sizeof(int)];    SCNGeometry *line = [SCNGeometry geometryWithSources:@[vertexSource2]                                                    elements:@[element2]];        SCNNode *lineNode = [SCNNode nodeWithGeometry:line];    [self.scene.rootNode addChildNode:lineNode];            //黄色场地边线绘制    SCNGeometrySource *vertexSourceYellow = [SCNGeometrySource geometrySourceWithVertices:&m_yellowLineVertices[0]                                                                               count:m_yellowLineVertices.size()];    NSData *indexDataYellow = [NSData dataWithBytes:&m_yellowLineIndices[0]                                        length:m_yellowLineIndices.size()*4];    SCNGeometryElement *elementYellow = [SCNGeometryElement geometryElementWithData:indexDataYellow                                                                 primitiveType:SCNGeometryPrimitiveTypeLine                                                                primitiveCount:m_yellowLineIndices.size()/2                                                                 bytesPerIndex:sizeof(int)];    SCNGeometry *lineYellow = [SCNGeometry geometryWithSources:@[vertexSourceYellow]                                                elements:@[elementYellow]];    SCNMaterial* MaterialYellow = [SCNMaterial new];    [MaterialYellow setDoubleSided:true];    MaterialYellow.diffuse.contents =[UIColor colorWithRed:1 green:1 blue:0 alpha:1];    lineYellow.firstMaterial = MaterialYellow;    SCNNode *lineYellowNode = [SCNNode nodeWithGeometry:lineYellow];    [self.scene.rootNode addChildNode:lineYellowNode];    }

这里需要注意:点顺序要一致,绘制线条要尽量少用图元,图元多了性能会下降很明显。

5.6 添加相机节点并控制

    //添加摄像机节点    nodeCarema = [SCNNode node];    SCNCamera* ccCamera = [SCNCamera camera];    ccCamera.xFov = 3;    ccCamera.yFov = 6;    nodeCarema.camera = ccCamera;    SCNVector3 defaultPos = [dataPool getCenterOfArea];    nodeCarema.position = SCNVector3Make(defaultPos.x, defaultPos.y, first_height);    [mEyeBaseNode addChildNode:nodeCarema];

控制:

-(void) transCamera:(float)dx dy:(float)dy{    SCNVector3 vvv = mEyeBaseNode.position;    if (isEntered) {        switch (mOperaMode) {            case HEIGHT_ZOOM:                nodeCarema.transform = SCNMatrix4Translate(nodeCarema.transform, -dx/800, dy/800, 0);                break;            case ROTATE_VIEW:                break;            case FREE_VIEW:                if(dy>0&&xRotate<=M_PI_4)                {                    xRotate+=0.01;                    mEyeBaseNode.transform = SCNMatrix4Mult(eyeBaseTransMatrix, SCNMatrix4MakeRotation(xRotate, 1, 0, 0));                }                else if(dy<0 && xRotate>=0){                    xRotate-=0.01;                    mEyeBaseNode.transform = SCNMatrix4Mult(eyeBaseTransMatrix, SCNMatrix4MakeRotation(xRotate, 1, 0, 0));                }                                if(dx>0)                    eyeRoot.transform = SCNMatrix4Mult(eyeRoot.transform, SCNMatrix4MakeRotation(-0.04, 0, 0, 1));                else                    eyeRoot.transform = SCNMatrix4Mult(eyeRoot.transform, SCNMatrix4MakeRotation(0.04, 0, 0, 1));                break;            default:                break;        }    }}-(void) ScaleCamera:(float)dz{    SCNVector3 vvv = nodeCarema.position;    if (isEntered) {        switch (mOperaMode) {            case HEIGHT_ZOOM:                if(dz>1.0 && vvv.z>3)                    nodeCarema.position = SCNVector3Make(vvv.x, vvv.y, vvv.z-0.3);                else if(dz<1.0 && vvv.z<7)                    nodeCarema.position = SCNVector3Make(vvv.x, vvv.y, vvv.z+0.3);                break;            case ROTATE_VIEW:                if(dz>1.0 && vvv.z>3)                    nodeCarema.position = SCNVector3Make(vvv.x, vvv.y, vvv.z-0.3);                else if(dz<3.0 && vvv.z<7)                    nodeCarema.position = SCNVector3Make(vvv.x, vvv.y, vvv.z+0.3);                break;            case FREE_VIEW:                if(dz>1.0 && vvv.z>3)                    nodeCarema.position = SCNVector3Make(vvv.x, vvv.y, vvv.z-0.3);                else if(dz<1.0 && vvv.z<7)                    nodeCarema.position = SCNVector3Make(vvv.x, vvv.y, vvv.z+0.3);                break;            default:                break;        }    }}


5.7 关闭自带的控制面板

self.sceneView.showsStatistics =NO;


6 Spritekit开发

1>导入SpriteKit.Framework

点击工程名,选择General,点击Linked Frameworks and Library,点击下面的+号,选择SpriteKit.Framework,添加到当前工程中去。

2>新建一个SpriteKit类

#import <SpriteKit/SpriteKit.h>@interface AAPLOverlayScene : SKScene{    SKShapeNode* lhPanel;   //离合节点    SKShapeNode* ymPanel;   //油门节点    SKShapeNode* scPanel;   //刹车节点    SKNode *fangxiangpan;   //方向盘节点        SKNode *fxpCenter;      //方向盘旋转中心节点    SKLabelNode* qsLabel;   //圈数}@property (readonly) SKNode *speedNeedle;-(void)setPanelValueWithAngle:(float)angle YM:(float)ym LH:(float)lh SC:(float)sc;@end

#import "AAPLOverlayScene.h"@implementation AAPLOverlayScene{    float commonScale;}-(id)initWithSize:(CGSize)size {    commonScale = 0.4;    if (self = [super initWithSize:size]) {        //setup the overlay scene        self.anchorPoint = CGPointMake(0.5, 0.5);                //automatically resize to fill the viewport        self.scaleMode = SKSceneScaleModeResizeFill;                //make UI larger on iPads        BOOL iPad = ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad);        float scale = iPad ? 1.5 : 1;                //add the speed gauge        SKSpriteNode *myImage = [SKSpriteNode spriteNodeWithImageNamed:@"panel3x.png"];        myImage.anchorPoint = CGPointMake(0, 0);                CGSize imgSize = myImage.size;        myImage.position = CGPointMake(-imgSize.width*0.5*commonScale, -size.height*0.5);        myImage.xScale = commonScale * scale;        myImage.yScale = commonScale * scale;        [self addChild:myImage];                        SKLabelNode *myLabel = [SKLabelNode labelNodeWithFontNamed:@"Chalkduster"];                myLabel.text = @"Blood, Error!";        myLabel.fontSize = 45;        myLabel.position = CGPointMake(CGRectGetMidX(self.frame),                                       CGRectGetMidY(self.frame));        myLabel.fontColor = [UIColor colorWithRed:1.0 green:0 blue:0 alpha:1];//        [self addChild:myLabel];                        //add the needed        fangxiangpan = [SKNode node];        SKSpriteNode *needle = [SKSpriteNode spriteNodeWithImageNamed:@"fangxiangpan3x.png"];        needle.anchorPoint = CGPointMake(0.5, 0.5);        needle.zRotation = 0;        fangxiangpan.position = CGPointMake(140,26*4);        [fangxiangpan addChild:needle];        [myImage addChild:fangxiangpan];                        qsLabel = [SKLabelNode labelNodeWithFontNamed:@"quanshu"];        qsLabel.name = @"quanshu";        qsLabel.text = @"aaaaaa";        qsLabel.fontSize = 22;        qsLabel.fontColor = [SKColor whiteColor];        qsLabel.position = CGPointMake(280,100);        [myImage addChild:qsLabel];                        UIBezierPath* bkBezierPath = [[UIBezierPath alloc] init];        [bkBezierPath moveToPoint:CGPointMake(0.0, 0.0)];        [bkBezierPath addLineToPoint:CGPointMake(0.0, 114.0)];        [bkBezierPath addLineToPoint:CGPointMake(15, 114.0)];        [bkBezierPath addLineToPoint:CGPointMake(15.0, 0.0)];                UIBezierPath* BezierPath = [[UIBezierPath alloc] init];        [BezierPath moveToPoint:CGPointMake(0.0, 0.0)];        [BezierPath addLineToPoint:CGPointMake(0.0, 114)];        [BezierPath addLineToPoint:CGPointMake(9.0, 114)];        [BezierPath addLineToPoint:CGPointMake(9.0, 0.0)];                        SKShapeNode* ymPanel_bk = [SKShapeNode node];        ymPanel_bk.path = bkBezierPath.CGPath;        ymPanel_bk.lineWidth = 1.0;        ymPanel_bk.fillColor = [UIColor grayColor];        ymPanel_bk.antialiased = NO;        ymPanel_bk.position = CGPointMake(383, 50);        [myImage addChild:ymPanel_bk];                ymPanel = [SKShapeNode node];        ymPanel.position =CGPointMake(3, 0);        ymPanel.path = BezierPath.CGPath;        ymPanel.lineWidth = 1.0;        ymPanel.fillColor = [UIColor blueColor];        ymPanel.antialiased = NO;        ymPanel.yScale = 1;        [ymPanel_bk addChild:ymPanel];        SKLabelNode* ymLabel = [SKLabelNode labelNodeWithFontNamed:@"Chalkduster"];        ymLabel.name = @"myCounterLabel";        ymLabel.text = @"油门";        ymLabel.fontSize = 20;        ymLabel.fontColor = [SKColor whiteColor];        ymLabel.position = CGPointMake(ymPanel_bk.position.x+7.5,18);        [myImage addChild:ymLabel];                SKShapeNode* scPanel_bk = [SKShapeNode node];        scPanel_bk.position =CGPointMake(448, 50);        scPanel_bk.path = bkBezierPath.CGPath;        scPanel_bk.lineWidth = 1.0;        scPanel_bk.fillColor = [UIColor grayColor];        scPanel_bk.antialiased = NO;        [myImage addChild:scPanel_bk];                scPanel = [SKShapeNode node];        scPanel.position =CGPointMake(3, 0);        scPanel.path = BezierPath.CGPath;        scPanel.lineWidth = 1.0;        scPanel.fillColor = [UIColor redColor];        scPanel.antialiased = NO;        scPanel.yScale = 0.5;        [scPanel_bk addChild:scPanel];                SKLabelNode* scLabel = [SKLabelNode labelNodeWithFontNamed:@"Chalkduster"];        scLabel.name = @"myCounterLabel";        scLabel.text = @"刹车";        scLabel.fontSize = 20;        scLabel.fontColor = [SKColor whiteColor];        scLabel.position = CGPointMake(scPanel_bk.position.x+7.5,18);        [myImage addChild:scLabel];                                SKShapeNode* lhPanel_bk = [SKShapeNode node];        lhPanel_bk.position =CGPointMake(514, 50);        lhPanel_bk.path = bkBezierPath.CGPath;        lhPanel_bk.lineWidth = 1.0;        lhPanel_bk.fillColor = [UIColor grayColor];        lhPanel_bk.antialiased = NO;        [myImage addChild:lhPanel_bk];                lhPanel = [SKShapeNode node];        lhPanel.position =CGPointMake(3, 0);        lhPanel.path = BezierPath.CGPath;        lhPanel.lineWidth = 1.0;        lhPanel.fillColor = [UIColor greenColor];        lhPanel.antialiased = NO;        lhPanel.yScale = 0.5;        [lhPanel_bk addChild:lhPanel];                SKLabelNode* lhLabel = [SKLabelNode labelNodeWithFontNamed:@"Chalkduster"];        lhLabel.name = @"Cluster";        lhLabel.text = @"离合";        lhLabel.fontSize = 20;        lhLabel.fontColor = [SKColor whiteColor];        lhLabel.position = CGPointMake(lhPanel_bk.position.x+7.5,18);        [myImage addChild:lhLabel];    }    return self;}-(void)setPanelValueWithAngle:(float)angle YM:(float)ym LH:(float)lh SC:(float)sc{    lhPanel.yScale = lh/100;    scPanel.yScale = sc/100;    ymPanel.yScale = ym/99;        fangxiangpan.zRotation = angle/180*M_PI;    NSString* strRoll;    int s = (int)angle>>31;    if(s == 0)    {        strRoll = @"左";    }else{        strRoll = @"右";    }        const int n = abs(angle);    qsLabel.text = strRoll;//    NSLog(@"%@@",strRoll);    }@end

3>将建好的二维面板导入到Scenekit中去,算是合并场景吧

@property (nonatomic,strong)AAPLOverlayScene *panelView;

    _panelView = [[AAPLOverlayScene alloc] initWithSize:self.view.bounds.size];    self.sceneView.overlaySKScene = _panelView;    self.sceneView.showsStatistics = NO;    [self.view addSubview:self.sceneView];

ok! 三维中有了二维面板了。


模糊效果图如下: