如何正确管理对象的位置,以适应与iPhone,iPad iPod不同分辨率的应用程序

时间:2014-01-11 17:55:26

标签: cocos2d-iphone

我正在开发游戏,我对管理数百个对象的所有位置有一般性的疑问。以前它更容易,因为iPhone 3,iPhone 4 iPod touch等只有一个点是普遍存在的。现在有了不同的宽高比和不同的分辨率。 我希望我的游戏与以下所有主要设备兼容:
iPhone5,iPhone5s,iPhone5c 1136 x 640~16:9
iPod 5Gen 1136 x 640~16:9
iPhone4,iPhone4s 960×640 3:2
iPod 4Gen 960×640 3:2
iPad 3Gen,iPad 4Gen,iPad Air 2048×1536 4:3
iPad Mini Second Gen 2048×1536 4:3
iPad2 1024×768 4:3
iPad Mini First Gen 1024×768 4:3
首先,我想要正确识别这些设备。目前我正在这样做 if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)区分ipad和

if ((screenHeight==568) && (uiscale==2.0f)) {
           // it is iphone5
        } 
找到iphone5。用同样的方法我会识别不同的iPad。
这是正确的方法吗?
现在关于坐标,我在每个场景的init中都有位置计算块。我正在尝试将相对坐标设置为屏幕尺寸,例如posY=winSize.height*0.5f;不要对每个坐标进行硬编码。我希望有一些共享实例,一旦设备正在运行应用程序,屏幕大小等等,将会定义,所有这些计算都会发生在例如mainMenuPlayButtonX=winSize.height*0.5f; or gameScenePauseButtonX=winSize.height*0.5f;等等。正确?请分享做什么。

2 个答案:

答案 0 :(得分:0)

不同的屏幕几何形状存在(至少)两个主要问题。

  1. 当您尝试在不同的几何图形中使用它时,通常无法正常使用适合特定几何图形的艺术作品(例如,纵向为横向,4:3对比16:9等)。
  2. 屏幕上的项目位置四处移动,可能并不总是很好。
  3. 让我们先做第一个(this is from this post):

    图稿尺寸

    我已经为iOS制作了几个应用程序,并且在iPhone和iPad之间进行按钮和背景的图形时出现“长宽比问题”问题,这些问题具有不同的宽高比。也将方向投入混合物中。

    我使用Gimp,Inkscape,Spine,Cocos2d-x和许多其他工具作为参考。

    据我所知,“不同屏幕几何”问题的一般选项是(如果有其他问题,请告诉我):

    1. 每个几何体的不同图形。
    2. 按几何比例缩放图形。
    3. 相同的图形,基于一个维度按比例缩放     然后使用固定内容的百分比将图形放在屏幕上。
    4. 选项1 意味着额外的工作......对于业余爱好者或独立开发者(如我)开发人员来说是不可接受的。

      选项2 通常看起来像垃圾。通常会产生沮丧和悲伤。

      选项3 是我经常使用的选项。我发现偶尔我必须根据设备或几何体添加小的更改(读取:hacks)。在iOS的情况下,它并不太糟糕,因为只有两种几何形状可以处理。对于Android,有许多不同的平板电脑几何形状,您可以通过处理几何范围并为您的应用选择固定方向来减少它。

      在一天结束时,按单个尺寸(高度或宽度)按比例缩放让我获得了最大的收益。

      我通常会使图形比我需要的“更大”,所以我只需缩小尺寸。这会消耗更多的内存,但我会重复使用,使用精灵表等。管理每一块内存(你必须在AAA级的大型游戏中做)都有一定的权衡,你可以得到什么远离小型独立应用程序。我不鼓励邋or或记忆管理不善;我鼓励平衡资源与简单的发展需求......为不同的情况制作相同的图形会燃烧很多日光。

      UI元素位置 这特别适用于菜单按钮,开火按钮,操纵杆等项目。通常,我创建一个表格,其中包含标称屏幕比例的屏幕尺寸百分比的比例和位置。创建每个元素时,它会在表中查找其标称信息并使用它。

      然后我为其他主要几何创建了一些这样的副本,并在运行时将指针更改为表。所以我可能有一张4:3的“肖像”表,一张19:16的“风景”表等。在开发过程中,我根据需要调整了“其他表”。我通常只需要创建其中一些。

      **这是这种方法的一个例子:**

      <强> DeviceGeometry.h

      #ifndef __MultiDimension__DeviceGeometry__
      #define __MultiDimension__DeviceGeometry__
      
      #include "cocos2d.h"
      
      using namespace cocos2d;
      
      class DeviceGeometry
      {
      public:
          DeviceGeometry();
          virtual ~DeviceGeometry();
      
         typedef enum
         {
            SG_1024_768 = 0,
            SG_16_9,
            SG_MAX
         } SCREEN_GEOMETRY_T;
      
      
         typedef enum
         {
            SE_JOYSTICK = 0,
            SE_LEFT_FIRE_1,
            SE_LEFT_FIRE_2,
            SE_EXIT,
            SE_MAX
         } SCREEN_ELEMENTS_T;
      
         typedef struct
         {
            // You can include any other pieces of information
            // here as well to fine tune the placement or
            // use of the element.
            SCREEN_ELEMENTS_T element;
            CCPoint position;
            float scale;
         } SCREEN_ELEMENT_DATA_T;
      
      
         // Call this when you need to change to a different
         // geometry.
         void Init(SCREEN_GEOMETRY_T geometry);
         CCPoint GetPosition(SCREEN_ELEMENTS_T element);
         float GetScale(SCREEN_ELEMENTS_T element);
      
      protected:
      private:
         SCREEN_ELEMENT_DATA_T* _elements;
      };
      
      #endif /* defined(__MultiDimension__DeviceGeometry__) */
      

      <强> DeviceGeometry.cpp

      #include "DeviceGeometry.h"
      
      DeviceGeometry::SCREEN_ELEMENT_DATA_T _elements_1024_768[DeviceGeometry::SE_MAX] =
      {
         { DeviceGeometry::SE_JOYSTICK,    ccp(0.8f,    0.1f),    1.0f  },
         { DeviceGeometry::SE_LEFT_FIRE_1, ccp(0.2f,    0.075f),  1.0f  },
         { DeviceGeometry::SE_LEFT_FIRE_2, ccp(0.2f,    0.15f),   1.0f  },
         { DeviceGeometry::SE_EXIT,        ccp(0.1f,    0.9f),    1.0f  },
      };
      
      DeviceGeometry::SCREEN_ELEMENT_DATA_T _elements_16_9[DeviceGeometry::SE_MAX] =
      {
         { DeviceGeometry::SE_JOYSTICK,    ccp(0.9f,    0.1f),    1.0f  },
         { DeviceGeometry::SE_LEFT_FIRE_1, ccp(0.15f,   0.075f),  1.0f  },
         { DeviceGeometry::SE_LEFT_FIRE_2, ccp(0.15f,   0.15f),   1.0f  },
         { DeviceGeometry::SE_EXIT,        ccp(0.125f,  0.925f),  1.0f  },
      };
      
      DeviceGeometry::DeviceGeometry()
      {
          _elements = _elements_1024_768;
      }
      
      DeviceGeometry::~DeviceGeometry()
      {
      
      }
      
      void DeviceGeometry::Init(SCREEN_GEOMETRY_T geometry)
      {
         switch(geometry)
         {
            case SG_1024_768:
               _elements = _elements_1024_768;
               break;
            case SG_16_9:
               _elements = _elements_16_9;
               break;
            default:
               assert(false);
               break;
         }
      }
      
      CCPoint DeviceGeometry::GetPosition(SCREEN_ELEMENTS_T element)
      {
         // Sanity checks.
         assert(element < SE_MAX);
         assert(_elements[element].element == element);
      
         if(_elements[element].element == element)
         {
            CCPoint& pt = _elements[element].position;
            CCSize scrSize = CCDirector::sharedDirector()->getWinSize();
            return ccp(pt.x * scrSize.width, pt.y * scrSize.height);
         }
         return ccp(0,0);
      }
      
      
      float DeviceGeometry::GetScale(SCREEN_ELEMENTS_T element)
      {
         // Sanity checks.
         assert(element < SE_MAX);
         assert(_elements[element].element == element);
      
         if(_elements[element].element == element)
         {
            return _elements[element].scale;
         }
         return 1.0;
      }
      

      游戏元素位置 这是所有主要游戏元素本身的位置......宇宙飞船,流星,小行星等。为此,我使用了一种视口方法。这有点复杂。 See this post for details

      这有用吗?

答案 1 :(得分:0)

您是否知道Retina和非Retina设备使用相同的坐标系(点,而不是像素)?所以你真的只有3种不同的屏幕尺寸可供支持:iPhone,iPhone宽屏和iPad。

此外,您可以将iPhone版本设计为在iPhone宽屏上运行,只需确保您不会在可能被切断的边界处显示关键信息或用户界面元素。或者,您可以决定单个元素相对于当前设备的屏幕边框定位它们,这会在宽屏幕上将它们进一步分开,但会将它们保留在常规iPhone屏幕的边框上。