Search…

Quản Lý Vị Trí Các Đối Tượng trong Game

29/09/20204 min read
Cấu hình vị trí của các đối tượng trong Game để quản lý game đa màn hình.

Thông thường khi khởi tạo 1 đối tượng trong game, các lập trình viên đều khởi tạo 1 vị trí nào đó cho chúng. Điều đó có nghĩa là các đối tượng luôn tồn tại trong game với 1 vị trí nào đó tuỳ thời điểm.

Vị trí đó được thể hiện qua 2 con số xy, tương ứng với toạ độ của 1 điểm trên mặt phẳng. Tuy nhiên, cùng 1 tọa độ, nhưng khi lên 2 thiết bị có kích thước màn hình khác nhau thì vị trí (so với màn hình) hiển thị trên màn hình cũng khác nhau.

Hơn nữa, trong games (games cỡ vừa hoặc lớn) không chỉ tồn tại 1 hay là 2 đối tượng mà lại có rất là nhiều, kéo theo việc kiểm soát và chỉnh sửa vị trí cho chúng khi cần thiết là rất khó khăn. Do vậy, việc quản lý các đối tượng trong games được đặc biệt quan tâm.

Kế thừa từ bài viết Quản Lý Vị Trí Của Các Đối Tượng trong Cocos2d-x, tiến hành hiện thực lại lớp PositionManager.

Ý tưởng

Để tiện cho việc quản lý số lượng lớn vị trí của các đối tượng, tiến hành đưa tất cả chúng vào 1 file XML và lưu chúng dưới dạng key/value, đồng thời để hỗ trợ đa màn hình khi load các đối tượng lên game tiến hành thêm đoạn code sau vào hàm applicationDidFinishLaunching()

// Set the design resolution
glview->setDesignResolutionSize(width, height, ResolutionPolicy::EXACT_FIT);

Trong đó:

  • width, height: kích thước background tương ứng được thiết kế.  
  • EXACT_FIT: 1 tuỳ chọn hình ảnh trong game sẽ co giãn theo kích thước của màn hình và không cần tuân theo tỷ lệ ban đầu của thiết kế.

Hiện thực

File plist lưu trữ vị trí các đối tượng

Dưới đây là cấu trúc của 1 file plist để lưu trữ vị trí các đối tượng trong game.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN"
       "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>sidebar_background</key>
    <string>-317,768</string>
	<key>title</key>
    <string>317,1382</string>
	
	<key>score_gameplay</key>
    <string>317,768</string>
	<key>score_lightmap_gamplay</key>
    <string>317,768</string>
	<key>board_background_gameplay</key>
    <string>1341,768</string>
	
	<key>mode_light</key>
    <string>1024,768</string>
	<key>icon_mode</key>
    <string>1024,768</string>
</dict>
</plist>

PositionManager

Tiến hành hiện thực lớp PositionManager như sau:

class PositionManager
{
private:
    static PositionManager* m_instance;
    std::map<int, Vec2>		m_objPosMap;
 
public:
    static PositionManager* getInstance();

    PositionManager();
    ~PositionManager();
 
	void		loadObjectsPosition(const char* pListPath);
	Vec2		getObjectPosition(int obj_id);
};

PositionManager được hiện thực với 2 phương thức chủ yếu là loadObjectsPosition và getObjectPosition

Phương thức loadObjectsPosition

Phương thức này load toàn bộ dữ liệu lưu trữ trong file plist và lưu trữ vào biến m_objPosMap.

void PositionManager::loadObjectsPosition(const char* pListPath)
{
	auto objData = FileUtils::getInstance()->getValueMapFromFile(pListPath);
	auto strToVec2 = [](std::string str) -> Vec2
	{
		Vec2 position;
		int value = 0;

		for (int i = 0; i < str.length(); i++)
		{
			if (str[i] != ',')
			{
				value *= 10;
				value += str[i] - '0';
			}
			else
			{
				position.x = value;
				value = 0;
			}
		}
		position.y = value;
		return position;
	};

	for (int i = 0; i < TOTAL_OBJ; i++)
	{
		m_objPosMap[i] = strToVec2(objData.at(OBJ_POS[i]).asString());
	}
}

Trong đó:

  • TOTAL_OBJ: tổng số đối tượng được lưu trữ trong file.
  • OBJ_POS[i]: biến lưu trữ các key ở file plist.

2 giá trị này sẽ giúp các bạn lấy được ở bên dưới.

Phương thức getObjectPosition

Vec2 PositionManager::getObjectPosition(int obj_id)
{
	return m_objPosMap.at(obj_id);
}

Phương thức getObjectPosition giúp lấy ra vị trí của 1 object khi ta truyền vào 1 obj_id tương ứng, vậy làm thế nào để biết được 1 obj_id nào của 1 đối tượng nào? Dưới đây sẽ hướng dẫn bạn thực hiện điều đó dễ dàng với 1 tool đơn giản do tạo ra trong quá trình thực hiện dự án, giờ sẽ chia sẻ cho các bạn điều đó.

Tạo config từ các đối tượng lưu trữ trong file plist

Nhằm tạo ra 1 file config gồm các ID tương ứng với các key  trong file plist, và lấy được 2 giá trị mà bên trên đã nói: TOTAL_OBJ, OBJ_POS[i], hiện thực 1 tool nhỏ bằng Python để tạo ra các config của các đối tượng như sau: 

Tool

from plistlib import readPlist

FILE_NAME = 'cnf_objects_pos.plist'

def getDefineStringFromKey(key, id):
    return '#define ID_POS_' + str.upper(key) + ' ' + str(id) + '\n'
	
def generateConfigForObject(objFile):
    pl = readPlist(objFile)
    index = 0

    obj_key_id = '#define PATH_CONF_OBJ_POS "' + objFile + '"\n'
    obj_key_id += 'extern const char* OBJ_POS[];\n'
    obj_key_name = 'const char* OBJ_POS[] = { \n'
    for key in pl:
        obj_key_id += getDefineStringFromKey(key, index)
        obj_key_name += '\t"' + key + '"' + ',\n'
        index += 1

    obj_key_name = obj_key_name[:-2]
    obj_key_name += '\n};\n'
    obj_key_id += '#define TOTAL_OBJ ' + str(index) + '\n'

    obj_key_name += '\n\n';
    obj_key_id += '\n\n';
    return obj_key_id, obj_key_name
	
res_h = '#ifndef __CONFIG_H__\n#define __CONFIG_H__\n\n'
res_cpp = '#include "Config.h"\n\n'

t = generateConfigForObject(FILE_NAME)
res_h += t[0]
res_cpp += t[1]

res_h += '#endif\t//__CONFIG_H__'

#Write output to file
f = open('Config.h', 'w')
f.write(res_h);
f.close()

f = open('Config.cpp', 'w')
f.write(res_cpp)
f.close()

File Config.h

#ifndef __CONFIG_H__
#define __CONFIG_H__

#define PATH_CONF_OBJ_POS "cnf_objects_pos.plist"
extern const char* OBJ_POS[];
#define ID_POS_MODE_LIGHT 0
#define ID_POS_TITLE 1
#define ID_POS_SIDEBAR_BACKGROUND 2
#define ID_POS_SCORE_LIGHTMAP_GAMPLAY 3
#define ID_POS_ICON_MODE 4
#define ID_POS_BOARD_BACKGROUND_GAMEPLAY 5
#define ID_POS_SCORE_GAMEPLAY 6
#define TOTAL_OBJ 7

#endif	//__CONFIG_H__

File Config.cpp

#include "Config.h"

const char* OBJ_POS[] = { 
	"mode_light",
	"title",
	"sidebar_background",
	"score_lightmap_gamplay",
	"icon_mode",
	"board_background_gameplay",
	"score_gameplay"
};

Download tool

TOOL_DEMO.zip

IO Stream

IO Stream Co., Ltd

30 Trinh Dinh Thao, Hoa Thanh ward, Tan Phu district, Ho Chi Minh city, Vietnam
+84 28 22 00 11 12
developer@iostream.co

383/1 Quang Trung, ward 10, Go Vap district, Ho Chi Minh city
Business license number: 0311563559 issued by the Department of Planning and Investment of Ho Chi Minh City on February 23, 2012

©IO Stream, 2013 - 2024