मेरे पास यह 800x600square है जो मैं स्क्रीन पर आकर्षित करना चाहता हूं। मैं इसमें सर्कल 'कट' करना चाहता हूं (जहां अल्फा 0 होगा)। असल में मैं इस पूरे आयत को मानचित्र पर खींच रहा हूं, इसलिए मैंने इन 'मंडलियों' को खींचा है, आप नक्शा देख सकते हैं, अन्यथा आप ग्रे स्क्वायरएसडीएल - ड्राइंग 'नकारात्मक' मंडल (युद्ध का धुंध)
उत्तर
तो, मुझे लगता है कि आप युद्ध के धुंध को जोड़ने की कोशिश कर रहे हैं आप में से एक खेल?
मेरे पास एक छोटे से डेमो था जिसे मैंने कुछ हफ्ते पहले एक * पथदर्शी दिखाने के लिए बनाया था, इसलिए मैंने सोचा कि मैं आपके लिए युद्ध के धुंध को जोड़ सकता हूं। यहाँ परिणाम है:
प्रारंभिक नक्शा
सबसे पहले, आप
फिर एक पूरा नक्शा, पूरी तरह से दिखाई
कोहरा के साथ शुरू, मैं करने के लिए एक सतह जोड़ा पूरी स्क्रीन को कवर करें (ध्यान दें कि मेरा नक्शा स्क्रीन से छोटा है, इसलिए इस मामले के लिए मैंने बस स्कैन पर युद्ध का धुंध जोड़ा रीन, लेकिन अगर आप स्क्रॉल है, सुनिश्चित करें कि यह प्रत्येक नक्शे पिक्सेल 1 शामिल हैं: 1)
mFogOfWar = SDL_CreateRGBSurface(SDL_HWSURFACE, in_Width, in_Height, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000);
SDL_Rect screenRect = {0, 0, in_Width, in_Height};
SDL_FillRect(mFogOfWar, &screenRect, 0xFF202020);
उसके बाद, आप यह आकर्षित करने की आवश्यकता है ... मैं खेल वस्तुओं ड्राइंग के बाद और यूआई निकालने से पहले इस कॉल जोड़ा
DrawSurface(mFogOfWar, 0, 0);
कहाँ
void RenderingManager::DrawSurface(SDL_Surface* in_Surface, int in_X, int in_Y)
{
SDL_Rect Dest = { in_X, in_Y, 0, 0 };
SDL_BlitSurface(in_Surface, NULL, mScreen, &Dest);
}
कौन आपको निम्न परिणाम देना चाहिए:
"पंच भूतल"
मैं तो एक 32 बिट .png
कि इस तरह दिखता है बनाया (बिसात से पता चलता अल्फा)
जब मेरे मुख्य चरित्र प्रतिपादन, मैं इस कॉल जोड़ा :
gRenderingManager.RemoveFogOfWar(int(mX) + SPRITE_X_OFFSET, int(mY) + SPRITE_Y_OFFSET);
ऑफ़सेट केवल स्प्राइट के साथ पंच को केंद्र में रखने के लिए है, मूल रूप से, जो मैं RemoveFogOfWar
पर जा रहा हूं वह मेरे स्प्राइट का केंद्र है।
युद्ध
अब युद्ध के कोहरे के मांस के कोहरे निकालें। मैंने दो संस्करण किए, एक जहां युद्ध का धुंध स्थायी रूप से हटा दिया जाता है और एक जहां युद्ध का धुंध रीसेट हो जाता है। युद्ध रीसेट का मेरा धुंध मेरी punch
सतह पर निर्भर करता है जहां अल्फा 0
पर रीसेट हो जाता है और तथ्य यह है कि मेरे चरित्र प्रति फ्रेम में कॉन्टूर की तुलना में कम पिक्सेल की चाल चलती है, अन्यथा मैं Rect
रखूंगा जहां मेरा पंच लागू किया गया था और मैं फिर से नया पंच खींचने से पहले इसे फिर से भर दूंगा।
चूंकि मुझे एसडीएल के साथ "गुणा" मिश्रण नहीं मिला, इसलिए मैंने एक साधारण कार्य लिखने का फैसला किया जो पंच सतह पर पुनरावृत्त करता है और युद्ध की सतह के धुंध पर अल्फा अपडेट करता है। सबसे महत्वपूर्ण हिस्सा वहाँ कुछ फसल कार्यों हो सकता है, लेकिन मैं जाँच परेशान नहीं किया करें कि आप अपने सतहों की सीमा के भीतर रहने बनाने के लिए है, इसलिए यह कोड के सबसे तक ले जाता है ...:
void RenderingManager::RemoveFogOfWar(int in_X, int in_Y)
{
const int halfWidth = mFogOfWarPunch->w/2;
const int halfHeight = mFogOfWarPunch->h/2;
SDL_Rect sourceRect = { 0, 0, mFogOfWarPunch->w, mFogOfWarPunch->h };
SDL_Rect destRect = { in_X - halfWidth, in_Y - halfHeight, mFogOfWarPunch->w, mFogOfWarPunch->h };
// Make sure our rects stays within bounds
if(destRect.x < 0)
{
sourceRect.x -= destRect.x; // remove the pixels outside of the surface
sourceRect.w -= sourceRect.x; // shrink to the surface, not to offset fog
destRect.x = 0;
destRect.w -= sourceRect.x; // shrink the width to stay within bounds
}
if(destRect.y < 0)
{
sourceRect.y -= destRect.y; // remove the pixels outside
sourceRect.h -= sourceRect.y; // shrink to the surface, not to offset fog
destRect.y = 0;
destRect.h -= sourceRect.y; // shrink the height to stay within bounds
}
int xDistanceFromEdge = (destRect.x + destRect.w) - mFogOfWar->w;
if(xDistanceFromEdge > 0) // we're busting
{
sourceRect.w -= xDistanceFromEdge;
destRect.w -= xDistanceFromEdge;
}
int yDistanceFromEdge = (destRect.y + destRect.h) - mFogOfWar->h;
if(yDistanceFromEdge > 0) // we're busting
{
sourceRect.h -= yDistanceFromEdge;
destRect.h -= yDistanceFromEdge;
}
SDL_LockSurface(mFogOfWar);
Uint32* destPixels = (Uint32*)mFogOfWar->pixels;
Uint32* srcPixels = (Uint32*)mFogOfWarPunch->pixels;
static bool keepFogRemoved = false;
for(int x = 0; x < destRect.w; ++x)
{
for(int y = 0; y < destRect.h; ++y)
{
Uint32* destPixel = destPixels + (y + destRect.y) * mFogOfWar->w + destRect.x + x;
Uint32* srcPixel = srcPixels + (y + sourceRect.y) * mFogOfWarPunch->w + sourceRect.x + x;
unsigned char* destAlpha = (unsigned char*)destPixel + 3; // fetch alpha channel
unsigned char* srcAlpha = (unsigned char*)srcPixel + 3; // fetch alpha channel
if(keepFogRemoved == true && *srcAlpha > 0)
{
continue; // skip this pixel
}
*destAlpha = *srcAlpha;
}
}
SDL_UnlockSurface(mFogOfWar);
}
कौन सा तो मुझे keepFogRemoved = false
के साथ इस दे दी है के बाद भी चरित्र keepFogRemoved = true
और यह चला गया था
मान्यता
महत्वपूर्ण हिस्सा सुनिश्चित करें कि आप अपने पिक्सेल बफर के बाहर कुछ भी न लिखें, ताकि नकारात्मक ऑफसेट या ऑफसेट है कि आप चौड़ाई या ऊंचाई से बाहर लाना होगा के साथ बाहर देखने के लिए वास्तव में है। मेरे कोड को मान्य करने के लिए, मैं RemoveFogOfWar
के लिए एक सरल कॉल जोड़ा जब माउस क्लिक किया और मैं एक "द्वारा बंद एक" समस्या
case SDL_MOUSEBUTTONDOWN:
{
if(Event.button.button == SDL_BUTTON_LEFT)
{
gRenderingManager.RemoveFogOfWar(Event.button.x, Event.button.y);
}
break;
}
नोट्स नहीं था सुनिश्चित करने के लिए करने की कोशिश की कोनों और किनारों है
जाहिर है, आपको "पंच" के लिए 32 बिट्स बनावट की आवश्यकता नहीं है, लेकिन यह स्पष्ट तरीका था कि मैं आपको यह दिखाने के लिए सोच सकता था कि इसे कैसे किया जाए। यह 1 बिट प्रति पिक्सेल (चालू/बंद) के रूप में कम से कम किया जा सकता है। तुम भी कुछ ढाल जोड़ सकते हैं, और
if(*srcAlpha > *destAlpha)
{
continue;
}
की तरह कुछ करने के लिए
if(keepFogRemoved == true && *srcAlpha > 0)
{
continue; // skip this pixel
}
बदल इस तरह एक चिकनी मिश्रण रखने के लिए:
3 राज्य युद्ध के कोहरा
I सोचा कि मुझे यह जोड़ना चाहिए ... मैंने युद्ध के 3 राज्य कोहरे बनाने के लिए एक तरीका जोड़ा: visible
, seen
और fogged
।
ऐसा करने के लिए, मैं बस SDL_Rect
रखता हूं जहां से मैंने युद्ध के कोहरे को "पेंच" किया है, और यदि अल्फा एक निश्चित मूल्य से कम है, तो मैं इसे उस मान पर क्लैंप करता हूं।
तो, बस सही पाश जहां युद्ध के कोहरे "मुक्का मारा" से पहले
for(int x = 0; x < mLastFogOfWarPunchPosition.w; ++x)
{
for(int y = 0; y < mLastFogOfWarPunchPosition.h; ++y)
{
Uint32* destPixel = destPixels + (y + mLastFogOfWarPunchPosition.y) * mFogOfWar->w + mLastFogOfWarPunchPosition.x + x;
unsigned char* destAlpha = (unsigned char*)destPixel + 3;
if(*destAlpha < 0x60)
{
*destAlpha = 0x60;
}
}
}
mLastFogOfWarPunchPosition = destRect;
जोड़कर, मैं तुम्हें StarCraft की तरह खेल में हो सकता था क्या करने के लिए इसी तरह के युद्ध के कोहरे मिल
अब, के बाद से "देखा" युद्ध के कोहरे अर्द्ध पारदर्शी है, ताकि आप उन्हें है, लेकिन आप नहीं देखते हैं आप अपने प्रतिपादन विधि बदलाव करने को ठीक से "दुश्मन" है कि कोहरे में होगा क्लिप करने की आवश्यकता होगी अभी भी इलाके देखें।
आशा है कि इससे मदद मिलती है!
मैं वास्तव में आपके द्वारा किए गए काम की सराहना करता हूं। यह एक ट्यूटोरियल की तरह है! +1 –
@ BartekBanachewicz धन्यवाद! उम्मीद है कि जवाब पर्याप्त स्पष्ट है! :) – emartel
woah। आदमी तुम अद्भुत हो! मैं स्टैक ओवरफ्लो के साथ अनुभव नहीं कर रहा हूं, क्या आपके और उत्तर देने के जवाब देने के अलावा मैं कुछ और कर सकता हूं? : पी – will
तो क्या आप सर्कल छवि को सीधे मानचित्र के अल्फा चैनल में मुद्रित करना चाहते हैं? – Tommy
मैं एक ग्रे बॉक्स रखना चाहता हूं, जिसमें सर्कल 'मिटाया गया' है, इसलिए मैं पूरी तरह से परत के माध्यम से ग्रे बॉक्स को खींचा जा रहा हूं। – will