zoukankan      html  css  js  c++  java
  • SpriteKit项目——消灭怪兽、效果图及详细代码,

    一、注意
    1.新建项目并改为横屏运行
    2.导入游戏素材
    3.创建GameSence
    4.添加忍者
    5.隐藏状态栏,配置游戏场景大小

    #pragma mark - 隐藏状态栏

    - (BOOL)prefersStatusBarHidden

    {

        return YES;

    }

    二、添加忍者

    // 1. 设置背景颜色

    self.backgroundColor = [SKColor colorWithWhite:1.0 alpha:1.0];

    // 2. 创建忍者

    SKSpriteNode *player = [SKSpriteNode spriteNodeWithImageNamed:@"player"];

    CGPoint location = CGPointMake(0, self.size.height / 2);

    [player setPosition:location];

    // 3. 添加到场景

    [self addChild:player];

    三、iOS中视图大小变化简述

    •系统加载完成nib文件后,会立即给应用程序发送viewDidLoad消息。此时,该视图尚未被加载至视图的层次结构。因此此时的视图大小并不会根据设备的方向重新调整大小
    •视图的frame是相对其父视图坐标空间的,对于根视图而言,父视图是UIWindow,UIWindow负责处理旋转并调整子视图的变化
    •在横屏应用中,shouldAutorotate和supportedInterfaceOrientations方法会被多次调用,而视图的bounds大小变化为横屏的尺寸,发生在第一次调用viewWillLayoutSubviews时
     
    四、配置游戏场景大小

    {

        [super viewWillLayoutSubviews];

        // 1. 获取根视图

          SKView * skView = (SKView *)self.view;

        // 2. 判断场景是否已经创建

          if (!skView.scene) {

            // 2.1 配置SK视图

                 skView.showsFPS = YES;

            skView.showsNodeCount = YES;

            // 2.2 创建并配置游戏场景

                 SKScene * scene = [GameScene sceneWithSize:skView.bounds.size];

            // 2.3 展现游戏场景

            [skView presentScene:scene];

        }

    }

    五、忍者登场

    CGPoint location = CGPointMake(player.size.width / 2,

    self.size.height / 2);

    六、添加妖怪

    SKSpriteNode *monster = [SKSpriteNode spriteNodeWithImageNamed:@"monster"];

    // 2. 计算怪物出现的位置

    NSInteger maxY = self.size.height - monster.size.height;

    NSInteger randomY = arc4random_uniform(maxY);

    NSInteger monsterY = randomY + monster.size.height / 2;

    NSInteger monsterX = self.size.width - monster.size.width / 2;

    monster.position = CGPointMake(monsterX, monsterY);

    // 3. 添加妖怪

    [self addChild:monster];

    // 4. 妖怪从右向左移动

    CGFloat duration = arc4random_uniform(4) + 2.0;

    CGPoint to = CGPointMake(-monster.size.width / 2, monsterY);

    SKAction *move = [SKAction moveTo:to duration:duration];

    SKAction *moveDone = [SKAction removeFromParent];

    [monster runAction:[SKAction sequence:@[move, moveDone]]];

    七、示意图

    八、不断添加妖怪

    // 4.1 添加一个妖怪的Action

    SKAction *addMonster = [SKAction runBlock:^{

        [self addMonster];

    }];

    // 4.2 等待Action

    SKAction *waitAction = [SKAction waitForDuration:1.0f];

    // 4.3 系列Action

    SKAction *seqence = [SKAction sequence:@[addMonster, waitAction]];

    // 4.4 循环执行Action,不断添加妖怪

    [self runAction:[SKAction repeatActionForever:seqence]];

    九、滚滚不断地妖怪大军来啦~~~

    十、发射飞镖示意图

    十一、发射飞镖

    CGPoint from = CGPointMake(_player.size.width + projectile.size.width / 2, self.size.height / 2);

    CGPoint offset = CGPointMake(location.x - from.x, location.y - from.y);

    // 仅允许向右侧发射

    if (offset.x <= 0) return;

    // 3. 计算目标点

    CGFloat toX = projectile.size.width / 2.0 + self.size.width;

    CGFloat toY = offset.y / offset.x * toX + from.y;

    CGPoint to = CGPointMake(toX, toY);

    // 4. 通过飞镖距离,计算飞行时间

    CGPoint p = CGPointMake(to.x - from.x, to.y - from.y);

    CGFloat distance = sqrtf(powf(p.x, 2.0) + powf(p.y, 2.0));

    CGFloat volcity = self.size.width;

    NSTimeInterval duration = distance / volcity;

    十二、多点触摸支持

    // 多点触摸支持

    for (UITouch *touch in touches) {

        [self addProjectileAtPoint:[touch locationInNode:self]];

    }

    十三、消灭妖怪在场景更新方法中做碰撞检测

    for (SKSpriteNode *projectile in _projectiles) {

        NSMutableSet *monsterToDelete = [NSMutableSet set];

        for (SKSpriteNode *monster in _monsters) {

            if (CGRectIntersectsRect(monster.frame, projectile.frame)) {

                [monsterToDelete addObject:monster];

            }

        }

        for (SKSpriteNode *monster in monsterToDelete) {

            [_monsters removeObject:monster];

            SKAction *rotate = [SKAction rotateToAngle:-M_PI_2 duration:0.1];

            [monster runAction:rotate completion:^{

                [monster removeFromParent];

            }];

        }

        if (monsterToDelete.count > 0) {

            [projectileToDelete addObject:projectile];

        }

    }

    十四、游戏结束处理

    _killedMonster++;

    if (_killedMonster > 10) {

        GameOverScene *gameOver = [[GameOverScene alloc] initWithSize:self.size won:YES];

        SKTransition *transition = [SKTransition doorsOpenHorizontalWithDuration:0.5f];

        [self.scene.view presentScene:gameOver transition:transition];

    }

    // 在用户触摸事件中遍历用户点击的节点

    SKNode *node = [self nodeAtPoint:[touch locationInNode:self]];

    if ([node.name isEqualToString:@"click"]) {

        GameScene *gameScene = [GameScene sceneWithSize:self.size];

        SKTransition *transition = [SKTransition doorsCloseHorizontalWithDuration:0.5f];

        [self.scene.view presentScene:gameScene transition:transition];

    }

    十五、碰撞检测(1——设置类别掩码,并设置物理世界

    tic uint32_t projectileCategory = 1 << 0;

    static uint32_t monsterCategory = 1 << 1;

    // 1) 物理仿真世界的重力方向

    self.physicsWorld.gravity = CGVectorMake(0, 0);

    // 2) 仿真世界的关联代理

    self.physicsWorld.contactDelegate = self;

    十六、碰撞检测(2——设置妖怪的物理刚体属性

    // 1.2 设置妖怪的物理刚体属性

    // 1) 使用妖怪的尺寸创建一个矩形刚体

    monster.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:monster.size];

    // 2) 标示物体的移动是否由仿真引擎负责

    monster.physicsBody.dynamic = YES;

    // 3) 设置类别掩码

    monster.physicsBody.categoryBitMask = monsterCategory;

    // 4) 设置碰撞检测类别掩码

    monster.physicsBody.contactTestBitMask = projectileCategory;

    // 5) 设置回弹掩码

    monster.physicsBody.collisionBitMask = 0;

    十七、碰撞检测(3——设置飞镖的物理刚体属性

    属性

    // 1) 使用飞镖的尺寸创建一个圆形刚体

    projectile.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:projectile.size.width / 2.0];

    // 2) 标示物体的移动是否由仿真引擎负责

    projectile.physicsBody.dynamic = YES;

    // 3) 设置类别掩码

    projectile.physicsBody.categoryBitMask = projectileCategory;

    // 4) 设置碰撞检测类别掩码

    projectile.physicsBody.contactTestBitMask = monsterCategory;

    // 5) 设置回弹掩码

    projectile.physicsBody.collisionBitMask = 0;

    // 6) 设置精确的碰撞检测,避免出现“遂穿”

    projectile.physicsBody.usesPreciseCollisionDetection = YES;

    十八、碰撞检测——消灭妖怪

    / 1. 使用类别掩码判断发生碰撞的对象类别

    SKPhysicsBody *projectileBody = nil;

    SKPhysicsBody *monsterBody = nil;

    if (contact.bodyA.categoryBitMask == projectileCategory) {

        projectileBody = contact.bodyA;

        monsterBody = contact.bodyB;

    } else {

        projectileBody = contact.bodyB;

        monsterBody = contact.bodyA;

    }

    // 2. 从场景中移除飞镖

    [projectileBody.node removeFromParent];

    // 3. 从场景中移出妖怪

    SKSpriteNode *monster = (SKSpriteNode *)monsterBody.node;

    SKAction *rotate = [SKAction rotateToAngle:-M_PI_2 duration:0.1];

    SKAction *rotateDone = [SKAction removeFromParent];

    [monster runAction:[SKAction sequence:@[rotate, rotateDone]]];

    十九、战斗开始啦~~

    二十、添加声音

    •[self runAction:[SKAction playSoundFileNamed:@"pew-pew-lei.caf" waitForCompletion:NO]];
  • 相关阅读:
    JS---元素属性的操作
    JS---异常
    JS---OOP
    T-SQL---分页语句
    mui---在关闭webview之前给出提示
    mui---通过plus.webview.create创建webview并打开新页面并传参到新页面
    mui---要打开的页面loaded不自动显示,等服务器返回数据后,再做处理逻辑
    winform/timer控件/权限设置/三级联动
    winform 进程、线程
    winform 之MDI容器
  • 原文地址:https://www.cnblogs.com/changxs/p/3484984.html
Copyright © 2011-2022 走看看