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

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 添加手势操作

初始化的时候

[self addGesture];

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! 三维中有了二维面板了。


模糊效果图如下:













  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值