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

来源:互联网 发布:南京壹鼎诚网络 编辑:程序博客网 时间:2024/05/18 00:05


屏幕自适应:

实现方法:定义一个游戏的基础屏幕大小: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; //默认宽度=1366Sint32 m_iBaseHeight; //默认高度=768Sint32 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;#elseComPtr<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. );#endifreturn 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);#endifconst 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;#elsechar 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}#endifconst char * SkFile::getRootPath() {#ifdef __SKYPARK_MAC__return "/Users/vickenyang/Desktop/test/SkyparkGame/assets";#endif#ifdef __ANDROID__return SDL_AndroidGetInternalStoragePath();#endifreturn ".";}#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;}#endifint 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('/','-');#endifSkString 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);#elseiRet = readTxtFile(m_path.c_str(), sData);#endifg_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;


0 0