SDL游戏之路(七)

您所在的位置:网站首页 sdl加载图片 SDL游戏之路(七)

SDL游戏之路(七)

2024-07-15 00:19| 来源: 网络整理| 查看: 265



屏幕自适应:

实现方法:定义一个游戏的基础屏幕大小: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 decoder; g_SkComm.getRenderer()->m_wicFactory->CreateDecoderFromFilename( stows(pFilePath).c_str(), nullptr, GENERIC_READ, WICDecodeMetadataCacheOnDemand, &decoder ); ComPtr frame; decoder->GetFrame(0, &frame); Microsoft::WRL::ComPtr 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 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 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 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) { 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;



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3