您的位置:首页 > 其它

SDL游戏之路(七)--屏幕自适应+图片加载+配置文件

2014-01-13 00:26 363 查看

屏幕自适应:

实现方法:定义一个游戏的基础屏幕大小:1366*768.

游戏中所有的坐标和长宽都是基于游戏基础坐标体系

然后定义一个 游戏坐标到屏幕坐标体系的转换函数。

在所有绘图的地方,都通过坐标转换:

#define _S2B(input) (g_m_bRatio ? (((int)input)*1000/g_m_fRatio): ((int)input))
#define _B2S(input) (g_m_bRatio ? (((int)input)*g_m_fRatio/1000): ((int)input))
#define _S2BX(input) (g_m_bRatio ? ((((int)input)-g_m_iPositionX)*1000/g_m_fRatio): ((int)input)-g_m_iPositionX)
#define _B2SX(input) (g_m_bRatio ? (g_m_iPositionX+((int)input)*g_m_fRatio/1000): g_m_iPositionX+((int)input))
#define _S2BY(input) (g_m_bRatio ? ((((int)input)-g_m_iPositionY)*1000/g_m_fRatio): ((int)input)-g_m_iPositionY)
#define _B2SY(input) (g_m_bRatio ? (g_m_iPositionY+((int)input)*g_m_fRatio/1000): g_m_iPositionY+((int)input))


ScreenParameter::ScreenParameter() {
m_iBaseWidth = 1366;
m_iBaseHeight = 768;
m_iPositionX = 0;
m_iPositionY = 0;
m_bRatio = false;
m_fRatio = 1.0;
}
//用来调节屏幕自动适应的参数
class ScreenParameter {
public:
Sint32 m_iBaseWidth; //默认宽度=1366
Sint32 m_iBaseHeight; //默认高度=768
Sint32 m_iPositionX; //左顶点位置
Sint32 m_iPositionY;
Sint32 m_iScreenWidth;
Sint32 m_iScreenHeight;
Sint32 m_iWindowWidth;
Sint32 m_iWindowHeight;

bool m_bRatio; //是否图形有屏幕自适应
float m_fRatio; //屏幕自适应系数
ScreenParameter();
//设置屏幕分辨率,计算最适合的变化比例
void setScreen(Sint32 iWidth, Sint32 iHeight);
};


void ScreenParameter::setScreen(Sint32 iWidth, Sint32 iHeight) {
m_iScreenWidth = iWidth;
m_iScreenHeight = iHeight;
if (m_iBaseWidth == iWidth && iHeight >= m_iBaseHeight) {
m_iPositionY = (iHeight - m_iBaseHeight) / 2;
m_iWindowWidth = m_iBaseWidth;
m_iWindowHeight = m_iBaseHeight;
return;
}
int fw = (iWidth * 1000 / m_iBaseWidth);
int fh = (iHeight * 1000 / m_iBaseHeight);
if (fw > fh) {
fw = fh;
m_iPositionX = (iWidth - m_iBaseWidth * fw / 1000) / 2;
} else {
m_iPositionY = (iHeight - m_iBaseHeight * fw / 1000) / 2;
}
m_bRatio = true;
m_fRatio = fw / 1000.0;

g_m_bRatio = m_bRatio;
g_m_iPositionX = m_iPositionX;
g_m_iPositionY = m_iPositionY;
g_m_fRatio = fw;
m_iWindowWidth = m_iBaseWidth * fw / 1000;
m_iWindowHeight = m_iBaseHeight * fw / 1000;
}


图片加载:

主要注意路径的问题

windows+mac+ios+linux:程序相当路径

android:通过AAssetManager_open

wp8:使用D2D,相对路径

加载图片代码:

#ifndef SKIMAGE_H_
#define SKIMAGE_H_

#include "SkComm.h"
namespace sk_park {
class SkImage {
public:
Sint32 m_iWidth;
Sint32 m_iHeight;
SkSurface m_skSurface;
SkImage();
~SkImage();
int load(const char * pFilePath, Sint32 iWidth = 0, Sint32 iHeight = 0);
void init(Sint32 iWidth, Sint32 iHeight,
SkSurface & skSurface);
void init(SkImage & obj);
};
}

extern sk_park::SkImage g_SkImage;

#endif /* SKIMAGE_H_ */


#include "pch.h"

#include "SkImage.h"
#include "SkFile.h"
#include "SkShow.h"
using namespace sk_park;

SkImage::SkImage() {
m_iWidth = 0;
m_iHeight = 0;
}
SkImage::~SkImage() {

}
void SkImage::init(Sint32 iWidth, Sint32 iHeight, SkSurface & skSurface) {
m_iWidth = iWidth;
m_iHeight = iHeight;
m_skSurface = skSurface;
}
void SkImage::init(SkImage & obj) {
m_iWidth = obj.m_iWidth;
m_iHeight = obj.m_iHeight;
m_skSurface = obj.m_skSurface;
}
int SkImage::load(const char * pFilePath, Sint32 iWidth, Sint32 iHeight) {
#ifndef __WP8__
SDL_Surface * pSDL_Surface = g_SkFile.getPic(pFilePath);
m_iWidth = pSDL_Surface->w;
m_iHeight = pSDL_Surface->h;
g_SkComm.log("name:%s w:%d h:%d",pFilePath,m_iWidth,m_iHeight);

if (iWidth != 0) {
if (iHeight == 0) {
iHeight = (int) (iWidth * 1.0 / m_iWidth * m_iHeight);
}
m_iWidth = (iWidth);
m_iHeight = (iHeight);
} else if (iHeight != 0) {
iWidth = (int) (iHeight * 1.0 / m_iHeight * m_iWidth);
m_iWidth = (iWidth);
m_iHeight = (iHeight);
}
SDL_Texture * pSDL_Texture = SDL_CreateTextureFromSurface(
g_SkShow.m_pSkRenderer, pSDL_Surface);
SDL_FreeSurface(pSDL_Surface);
m_skSurface.setSurface(pSDL_Texture);
m_skSurface.w = m_iWidth;
m_skSurface.h = m_iHeight;
#else
ComPtr<IWICBitmapDecoder> decoder;
g_SkComm.getRenderer()->m_wicFactory->CreateDecoderFromFilename(
stows(pFilePath).c_str(),
nullptr,
GENERIC_READ,
WICDecodeMetadataCacheOnDemand,
&decoder
);
ComPtr<IWICBitmapFrameDecode> frame;
decoder->GetFrame(0, &frame);

Microsoft::WRL::ComPtr<IWICFormatConverter> wicFormatConverter;
g_SkComm.getRenderer()->m_wicFactory->CreateFormatConverter(&wicFormatConverter);

UINT originalWidth, originalHeight;
frame->GetSize(&originalWidth, &originalHeight);
m_iWidth = originalWidth;
m_iHeight = originalHeight;
if (iWidth != 0 )
{
if(iHeight==0){
iHeight = (int)(iWidth*1.0/m_iWidth*m_iHeight);
}
Microsoft::WRL::ComPtr<IWICBitmapScaler> pScaler;
g_SkComm.getRenderer()->m_wicFactory->CreateBitmapScaler(&pScaler);
pScaler->Initialize(
frame.Get(),
_B2S(iWidth),
_B2S(iHeight),
WICBitmapInterpolationModeCubic
);
m_iWidth = iWidth;
m_iHeight = iHeight;

wicFormatConverter->Initialize(
pScaler.Get(),
GUID_WICPixelFormat32bppPBGRA,
WICBitmapDitherTypeNone,
nullptr,
0.0f,
WICBitmapPaletteTypeCustom // premultiplied BGRA has no paletting, so this is ignored
);
}else if (iHeight != 0 ){
iWidth = (int)(iHeight*1.0/m_iHeight*m_iWidth);
Microsoft::WRL::ComPtr<IWICBitmapScaler> pScaler;
g_SkComm.getRenderer()->m_wicFactory->CreateBitmapScaler(&pScaler);
pScaler->Initialize(
frame.Get(),
_B2S(iWidth),
_B2S(iHeight),
WICBitmapInterpolationModeCubic
);
m_iWidth = iWidth;
m_iHeight = iHeight;

wicFormatConverter->Initialize(
pScaler.Get(),
GUID_WICPixelFormat32bppPBGRA,
WICBitmapDitherTypeNone,
nullptr,
0.0f,
WICBitmapPaletteTypeCustom // premultiplied BGRA has no paletting, so this is ignored
);
}
else{
if(g_SP.m_bRatio){
Microsoft::WRL::ComPtr<IWICBitmapScaler> pScaler;
g_SkComm.getRenderer()->m_wicFactory->CreateBitmapScaler(&pScaler);
pScaler->Initialize(
frame.Get(),
_B2S(m_iWidth),
_B2S(m_iHeight),
WICBitmapInterpolationModeCubic
);
wicFormatConverter->Initialize(
pScaler.Get(),
GUID_WICPixelFormat32bppPBGRA,
WICBitmapDitherTypeNone,
nullptr,
0.0f,
WICBitmapPaletteTypeCustom // premultiplied BGRA has no paletting, so this is ignored
);
}
else{
wicFormatConverter->Initialize(
frame.Get(),
GUID_WICPixelFormat32bppPBGRA,
WICBitmapDitherTypeNone,
nullptr,
0.0f,
WICBitmapPaletteTypeCustom // premultiplied BGRA has no paletting, so this is ignored
);
}
}

g_SkComm.getRenderer()->m_d2dContext->CreateEffect(CLSID_D2D1BitmapSource, &m_skSurface.m_pSurface);
m_skSurface.m_pSurface->SetValue(
D2D1_BITMAPSOURCE_PROP_WIC_BITMAP_SOURCE,
wicFormatConverter.Get() // IWICFormatConverter inherits from IWICBitmapSource
);
m_skSurface.m_pSurface->SetValue(
D2D1_BITMAPSOURCE_PROP_INTERPOLATION_MODE,
D2D1_BITMAPSOURCE_INTERPOLATION_MODE_LINEAR
);
m_skSurface.m_pSurface->SetValue(
D2D1_PROPERTY_CACHED,
TRUE // Direct2D effect properties use TRUE/FALSE instead of true/false.
);
#endif
return 0;
}

SkImage g_SkImage;


配置文件:

使用tinyxml 作为配置读写解析器。

在android上,读自有目录用SDL_AndroidGetInternalStoragePath,读原始目录用AAssetManager_open

读写文件代码:

#ifndef SKFILE_H_
#define SKFILE_H_

#include "SkComm.h"
#include "SkString.h"

namespace sk_park {
class SkFile {
public:
#ifndef __WP8__
SDL_Surface * getPic(const char * pPath);
#endif
const char * getRootPath();
int readTxtFile(const char * pPath, SkString & sData);
int saveTxtFile(const char * pPath, const char * pData);
#ifdef __ANDROID__
int readAndroidFile(const char * pPath, SkString & sData);
#endif
};

class SkDoc: public SkFile {
public:
bool init(const char * pPath);
bool save(SkString & data);
void clear();
SkString m_path;
SkString m_data;
};
}
extern sk_park::SkFile g_SkFile;
extern sk_park::SkDoc g_SkDoc;

#endif /* SKFILE_H_ */


#include "pch.h"
#ifdef __ANDROID__
#include "../src/SkyparkJni.hpp"
#endif
#include "SkFile.h"
using namespace sk_park;
#ifndef __WP8__

SDL_Surface * SkFile::getPic(const char * pPath) {
#ifdef __ANDROID__
SDL_Surface *temp = NULL;

JNIEnv* pJNIEnv = (JNIEnv*) SDL_AndroidGetJNIEnv();
jboolean iscopy;
jstring filename = pJNIEnv->NewStringUTF(pPath);
const char *mfile = pJNIEnv->GetStringUTFChars(filename, &iscopy);
AAsset* asset = AAssetManager_open(g_SkyparkJni.m_pAAssetManager, mfile,
AASSET_MODE_UNKNOWN);
if (asset != 0) {
off_t bufferSize = AAsset_getLength(asset);
//SDL_Log("[%s][%d]file size:%d\n", __FILE__, __LINE__, bufferSize);
char *buffer = (char *) malloc(bufferSize + 1);
buffer[bufferSize] = 0;
int numBytesRead = AAsset_read(asset, buffer, bufferSize);
//SDL_Log("[%s][%d]read numBytesRead:%d\n", __FILE__, __LINE__,numBytesRead);
if (numBytesRead == bufferSize) {
SDL_RWops *src;
src = SDL_RWFromMem(buffer, bufferSize);
/* 将BMP文件加载到一个surface*/
temp = IMG_Load_RW(src, 1);
}
free(buffer);
AAsset_close(asset);

}
pJNIEnv->ReleaseStringUTFChars(filename, mfile);
pJNIEnv->DeleteLocalRef(filename);

return temp;
#else
char filepath[256];
snprintf(filepath, sizeof(filepath), "%s/%s", getRootPath(), pPath);
SDL_Surface *surface = IMG_Load(filepath);
g_SkComm.log("[%s][%d]path:%s ptr:%d err:%s", __FILE__, __LINE__, filepath,
surface, g_SkComm.getErrMsg());
return surface;
#endif
}

#endif

const char * SkFile::getRootPath() {
#ifdef __SKYPARK_MAC__
return "/Users/vickenyang/Desktop/test/SkyparkGame/assets";
#endif
#ifdef __ANDROID__
return SDL_AndroidGetInternalStoragePath();
#endif
return ".";
}
#ifdef __ANDROID__
int SkFile::readAndroidFile(const char * pPath, SkString & sData) {
int iRet = -1;

JNIEnv* m_pJNIEnv = (JNIEnv*) SDL_AndroidGetJNIEnv();
jboolean iscopy;
jstring filename = m_pJNIEnv->NewStringUTF(pPath);
const char *mfile = m_pJNIEnv->GetStringUTFChars(filename, &iscopy);
AAsset* asset = AAssetManager_open(g_SkyparkJni.m_pAAssetManager, mfile,
AASSET_MODE_UNKNOWN);
if (asset != 0) {
off_t bufferSize = AAsset_getLength(asset);
//SDL_Log("[%s][%d]file size:%d\n", __FILE__, __LINE__, bufferSize);
char * buffer = (char *) malloc(bufferSize + 1);
buffer[bufferSize] = 0;
int numBytesRead = AAsset_read(asset, buffer, bufferSize);
//SDL_Log("[%s][%d]read numBytesRead:%d\n", __FILE__, __LINE__,numBytesRead);
if (numBytesRead == bufferSize) {
iRet = 0;
sData.append(buffer,bufferSize);
} else {
free(buffer);
iRet = -1;
}

AAsset_close(asset);
free(buffer);
}
m_pJNIEnv->ReleaseStringUTFChars(filename, mfile);
m_pJNIEnv->DeleteLocalRef(filename);

return iRet;
}
#endif
int SkFile::readTxtFile(const char * pPath, SkString & sData) {
char tmpFile[256];
snprintf(tmpFile, sizeof(tmpFile), "%s/%s", getRootPath(), pPath);
FILE *fp2 = fopen(tmpFile, "rb");
if (fp2 == NULL) {
return -2;
}
sData.clear();
char buf[1024];
while (true) {
int iLen = fread(buf, 1, sizeof(buf), fp2);
if (iLen <= 0) {
break;
}
sData.append(buf, iLen);
}
fclose(fp2);
return 0;
}
int SkFile::saveTxtFile(const char * pPath, const char * pData) {
char tmpFile[256];
snprintf(tmpFile, sizeof(tmpFile), "%s/%s", getRootPath(), pPath);
FILE *fp2 = fopen(tmpFile, "wb");
if (fp2 == NULL) {
return -2;
}
fwrite(pData, strlen(pData), 1, fp2);
fclose(fp2);
return 0;
}

bool SkDoc::init(const char * pPath) {
m_path = pPath;
#ifdef __ANDROID__
m_path.replaceAll('/','-');
#endif
SkString sData;
//先读保存的文件
SkString m_savePath = m_path;
m_savePath.append(".save");
int iRet = readTxtFile(m_savePath.c_str(), sData);
g_SkComm.log("[%s][%d]init SkDoc:%s ret=%d len=%d", __FILE__, __LINE__,
m_savePath.c_str(), iRet, sData.length());
if (iRet == 0 && sData.length() > 0) {
m_data = sData;
return true;
}
//读取失败,再读取原始文件
#ifdef __ANDROID__
iRet = readAndroidFile(pPath, sData);
#else
iRet = readTxtFile(m_path.c_str(), sData);
#endif
g_SkComm.log("[%s][%d]init SkDoc:%s ret=%d len=%d", __FILE__, __LINE__,
m_path.c_str(), iRet, sData.length());
if (iRet == 0 && sData.length() > 0) {
m_data = sData;
return true;
}
return false;
}
bool SkDoc::save(SkString & data) {
m_data = data;
SkString m_savePath = m_path;
m_savePath.append(".save");
int iRet = saveTxtFile(m_savePath.c_str(), m_data.c_str());
g_SkComm.log("[%s][%d]saveMyFile:%s ret=%d len=%d", __FILE__, __LINE__,
m_savePath.c_str(), iRet, m_data.length());
if (iRet == 0) {
return true;
}
return false;
}
void SkDoc::clear() {
m_data = "";
}

SkFile g_SkFile;
SkDoc g_SkDoc;


配置文件代码:

#ifndef SKCONFXML_H_
#define SKCONFXML_H_

#include "SkComm.h"
#include "SkFile.h"
#include "../tinyxml/tinyxml.h"

namespace sk_park {
class SkConfXml {
public:
TiXmlDocument m_xml;
SkDoc m_doc;
SkConfXml();
bool init(const char * filename);
bool save();
bool delfile();

Sint32 getKKValueInt32(const char * K1, const char * K2);
bool setKKValueInt32(const char * K1, const char * K2, Sint32 iValue);
bool setKKValueStr(const char * K1, const char * K2, const char * pStr);
SkString getKKValueStr(const char * K1, const char * K2);
private:
std::string m_filename;
SkConfXml(const SkConfXml & obj);

};
}
extern sk_park::SkConfXml g_SkConfXml;

#endif /* SKCONFXML_H_ */


#include "pch.h"

#include "SkConfXml.h"
using namespace sk_park;

SkConfXml::SkConfXml() {
}
bool SkConfXml::init(const char * filename) {
m_filename = filename;
bool bRet = m_doc.init(filename);
if (bRet == true) {
SkString sData = m_doc.m_data;
m_xml.Parse(sData.c_str());
return true;
}
return false;
}
bool SkConfXml::save() {
TiXmlPrinter printer;
printer.SetIndent("    ");
m_xml.Accept(&printer);
SkString xmltext = printer.CStr();
return m_doc.save(xmltext);
}
bool SkConfXml::delfile() {
SkString stmp = "";
return m_doc.save(stmp);
}

Sint32 SkConfXml::getKKValueInt32(const char * K1, const char * K2) {
SkString sData = getKKValueStr(K1, K2);
return atoi(sData.c_str());
}
bool SkConfXml::setKKValueInt32(const char * K1, const char * K2,
Sint32 iValue) {
char pStr[24];
snprintf(pStr, sizeof(pStr), "%d", iValue);
return setKKValueStr(K1, K2, pStr);
}
bool SkConfXml::setKKValueStr(const char * K1, const char * K2,
const char * pStr) {
TiXmlHandle docHandle(&m_xml);
TiXmlElement * pRootTiXmlElement =
docHandle.FirstChildElement("root").ToElement();
if (pRootTiXmlElement == NULL) {
pRootTiXmlElement = new TiXmlElement("root");
docHandle.ToElement()->LinkEndChild(pRootTiXmlElement);
}
TiXmlElement * pK1TiXmlElement = pRootTiXmlElement->FirstChildElement(K1);
if (pK1TiXmlElement == NULL) {
pK1TiXmlElement = new TiXmlElement(K1);
pRootTiXmlElement->LinkEndChild(pK1TiXmlElement);
}
TiXmlElement * pK2TiXmlElement = pK1TiXmlElement->FirstChildElement(K2);
if (pK2TiXmlElement == NULL) {
pK2TiXmlElement = new TiXmlElement(K2);
pK1TiXmlElement->LinkEndChild(pK2TiXmlElement);
}
const char * pOldData = pK2TiXmlElement->GetText();
if (pOldData != NULL) {
if (strcmp(pOldData, pStr) == 0) {
return true;
}
}
pK2TiXmlElement->Clear();
TiXmlText *pValue = new TiXmlText(pStr);
pK2TiXmlElement->LinkEndChild(pValue);
return true;
}

SkString SkConfXml::getKKValueStr(const char * K1, const char * K2) {
SkString sRet = "";
TiXmlHandle docHandle(&m_xml);
TiXmlHandle rootHandle = docHandle.FirstChildElement("root");
if (rootHandle.ToElement() != NULL) {
TiXmlHandle handleK1 = rootHandle.FirstChildElement(K1);
if (handleK1.ToElement() != NULL) {
TiXmlHandle handleK2 = handleK1.FirstChildElement(K2);
if (handleK2.ToElement() != NULL) {
const char * pData = handleK2.ToElement()->GetText();
if (pData != NULL) {
sRet = SkString(pData);
}
}
}
}
return sRet;
}

SkConfXml g_SkConfXml;
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: