void CBeamEffectCreator::DrawBeamLightningBolt (CG16bitImage &Dest, SLineDesc &Line, SViewportPaintCtx &Ctx) // DrawBeamLightningBolt // // Draws the appropriate beam { int i; // Compute a set of points for the lightning int iPointCount = LIGHTNING_POINT_COUNT; CVector *pPoints = new CVector [iPointCount]; pPoints[0] = CVector(Line.xFrom, Line.yFrom); pPoints[iPointCount - 1] = CVector(Line.xTo, Line.yTo); ComputeLightningPoints(iPointCount, pPoints, 0.3); // Draw based on intensity switch (m_iIntensity) { // Draw nothing case 0: break; // At intensity 1 or 2 just draw a lightning line with the primary color case 1: case 2: { for (i = 0; i < iPointCount-1; i++) { const CVector &vFrom = pPoints[i]; const CVector &vTo = pPoints[i + 1]; Dest.DrawLine((int)vFrom.GetX(), (int)vFrom.GetY(), (int)vTo.GetX(), (int)vTo.GetY(), m_iIntensity, m_wPrimaryColor); } break; } // At intensity 3 or 4 draw secondary color around primary. case 3: case 4: { for (i = 0; i < iPointCount-1; i++) { const CVector &vFrom = pPoints[i]; const CVector &vTo = pPoints[i + 1]; Dest.DrawLine((int)vFrom.GetX(), (int)vFrom.GetY(), (int)vTo.GetX(), (int)vTo.GetY(), m_iIntensity, m_wSecondaryColor); } for (i = 0; i < iPointCount-1; i++) { const CVector &vFrom = pPoints[i]; const CVector &vTo = pPoints[i + 1]; Dest.DrawLine((int)vFrom.GetX(), (int)vFrom.GetY(), (int)vTo.GetX(), (int)vTo.GetY(), m_iIntensity - 2, m_wPrimaryColor); } break; } // At intensity 5-10 we draw a glow around the beam case 5: case 6: case 7: case 8: case 9: case 10: { // Create a polygon for the glow shaped like a wide version of the // lightning bolt. CG16bitRegion GlowRegion; CreateLightningGlow(Line, iPointCount, pPoints, m_iIntensity, &GlowRegion); // Paint the glow GlowRegion.FillTrans(Dest, 0, 0, m_wSecondaryColor, 128); // Paint the main bolt for (i = 0; i < iPointCount-1; i++) { const CVector &vFrom = pPoints[i]; const CVector &vTo = pPoints[i + 1]; Dest.DrawLine((int)vFrom.GetX(), (int)vFrom.GetY(), (int)vTo.GetX(), (int)vTo.GetY(), 4, m_wSecondaryColor); } for (i = 0; i < iPointCount-1; i++) { const CVector &vFrom = pPoints[i]; const CVector &vTo = pPoints[i + 1]; Dest.DrawLine((int)vFrom.GetX(), (int)vFrom.GetY(), (int)vTo.GetX(), (int)vTo.GetY(), 2, m_wPrimaryColor); } break; } // For even larger beams we do a double glow default: { // Create a polygon for the glow shaped like a wide version of the // lightning bolt. CG16bitRegion GlowRegion1; CreateLightningGlow(Line, iPointCount, pPoints, m_iIntensity, &GlowRegion1); CG16bitRegion GlowRegion2; CreateLightningGlow(Line, iPointCount, pPoints, 10, &GlowRegion2); // Paint the glow GlowRegion1.FillTrans(Dest, 0, 0, m_wSecondaryColor, 48); GlowRegion2.FillTrans(Dest, 0, 0, m_wSecondaryColor, 96); // Paint the main bolt for (i = 0; i < iPointCount-1; i++) { const CVector &vFrom = pPoints[i]; const CVector &vTo = pPoints[i + 1]; Dest.DrawLine((int)vFrom.GetX(), (int)vFrom.GetY(), (int)vTo.GetX(), (int)vTo.GetY(), 4, m_wSecondaryColor); } for (i = 0; i < iPointCount-1; i++) { const CVector &vFrom = pPoints[i]; const CVector &vTo = pPoints[i + 1]; Dest.DrawLine((int)vFrom.GetX(), (int)vFrom.GetY(), (int)vTo.GetX(), (int)vTo.GetY(), 2, m_wPrimaryColor); } break; } } // Done delete [] pPoints; }
void DrawFilledCircleTrans (CG16bitImage &Dest, int xDest, int yDest, int iRadius, WORD wColor, DWORD byOpacity) // DrawFilledCircleTrans // // Draws an transparent filled circle { // Deal with edge-conditions if (iRadius <= 0) { Dest.DrawPixelTrans(xDest, yDest, wColor, (BYTE)byOpacity); return; } else if (byOpacity == 255) { DrawFilledCircle(Dest, xDest, yDest, iRadius, wColor); return; } // Initialize some stuff int x = 0; int y = iRadius; int d = 1 - iRadius; int deltaE = 3; int deltaSE = -2 * iRadius + 5; Dest.FillLineTrans(xDest - iRadius, yDest, 1 + 2 * iRadius, wColor, byOpacity); // Loop while (y > x) { if (d < 0) { d += deltaE; deltaE += 2; deltaSE += 2; } else { d += deltaSE; deltaE += 2; deltaSE += 4; Dest.FillLineTrans(xDest - x, yDest - y, 1 + 2 * x, wColor, byOpacity); Dest.FillLineTrans(xDest - x, yDest + y, 1 + 2 * x, wColor, byOpacity); y--; } x++; if (y >= x) { Dest.FillLineTrans(xDest - y, yDest - x, 1 + 2 * y, wColor, byOpacity); Dest.FillLineTrans(xDest - y, yDest + x, 1 + 2 * y, wColor, byOpacity); } } }
void CBeamEffectCreator::DrawBeamLightning (CG16bitImage &Dest, SLineDesc &Line, SViewportPaintCtx &Ctx) // DrawBeamLightning // // Draws the appropriate beam { // The central part of the beam is different depending on the // intensity. if (m_iIntensity < 4) { WORD wStart = CG16bitImage::BlendPixel(Ctx.wSpaceColor, m_wPrimaryColor, 128); Dest.DrawBiColorLine(Line.xFrom, Line.yFrom, Line.xTo, Line.yTo, 3, Ctx.wSpaceColor, wStart); WORD wEnd = CG16bitImage::BlendPixel(Ctx.wSpaceColor, m_wPrimaryColor, 155); Dest.DrawBiColorLine(Line.xFrom, Line.yFrom, Line.xTo, Line.yTo, 1, wEnd, m_wPrimaryColor); } else if (m_iIntensity < 10) { WORD wStart = CG16bitImage::BlendPixel(Ctx.wSpaceColor, m_wSecondaryColor, 155); Dest.DrawBiColorLine(Line.xFrom, Line.yFrom, Line.xTo, Line.yTo, 5, Ctx.wSpaceColor, wStart); Dest.DrawBiColorLine(Line.xFrom, Line.yFrom, Line.xTo, Line.yTo, 3, Ctx.wSpaceColor, m_wSecondaryColor); WORD wEnd = CG16bitImage::BlendPixel(Ctx.wSpaceColor, m_wPrimaryColor, 155); Dest.DrawBiColorLine(Line.xFrom, Line.yFrom, Line.xTo, Line.yTo, 1, wEnd, m_wPrimaryColor); } else { // Convert to an angle relative to xTo, yTo CVector vVec(Line.xFrom - Line.xTo, Line.yFrom - Line.yTo); Metric rRadius; int iAngle = VectorToPolar(vVec, &rRadius); int iRadius = (int)rRadius; // Can't deal with 0 sized lines if (iRadius == 0) return; CG16bitRegion Region; SPoint Poly[8]; // Paint the outer-most glow WORD wColor = CG16bitImage::BlendPixel(Ctx.wSpaceColor, m_wSecondaryColor, 100); CreateBlasterShape(iAngle, iRadius, iRadius / 6, Poly); Region.CreateFromConvexPolygon(8, Poly); Region.Fill(Dest, Line.xTo, Line.yTo, wColor); // Paint the inner transition wColor = CG16bitImage::BlendPixel(m_wSecondaryColor, m_wPrimaryColor, 128); wColor = CG16bitImage::BlendPixel(Ctx.wSpaceColor, wColor, 200); CreateBlasterShape(iAngle, iRadius * 2 / 3, iRadius / 7, Poly); Region.CreateFromConvexPolygon(8, Poly); Region.Fill(Dest, Line.xTo, Line.yTo, wColor); // Paint the inner core CreateBlasterShape(iAngle, iRadius / 2, iRadius / 8, Poly); Region.CreateFromConvexPolygon(8, Poly); Region.Fill(Dest, Line.xTo, Line.yTo, m_wPrimaryColor); } // Compute the half-way point int xHalf = (Line.xFrom + Line.xTo) / 2; int yHalf = (Line.yFrom + Line.yTo) / 2; // Draw lightning int iCount = m_iIntensity + mathRandom(0, 2); for (int j = 0; j < iCount; j++) if (mathRandom(1, 2) == 1) DrawLightning(Dest, xHalf, yHalf, Line.xTo, Line.yTo, m_wPrimaryColor, LIGHTNING_POINT_COUNT, 0.5); else DrawLightning(Dest, Line.xFrom, Line.yFrom, Line.xTo, Line.yTo, m_wSecondaryColor, LIGHTNING_POINT_COUNT, 0.3); }
void CListSaveFilesTask::CreateFileEntry (CGameFile &GameFile, const CTimeDate &ModifiedTime, int yStart, IAnimatron **retpEntry, int *retcyHeight) // CreateFileEntry // // Creates a display entry for the save file { const CVisualPalette &VI = m_HI.GetVisuals(); const CG16bitFont &MediumFont = VI.GetFont(fontMedium); const CG16bitFont &SubTitleFont = VI.GetFont(fontSubTitle); int x = 0; int y = 0; int xText = x + ADVENTURE_ICON_WIDTH + ICON_SPACING_HORZ; int cxText = m_cxWidth - (ADVENTURE_ICON_WIDTH + 2 * ICON_SPACING_HORZ + SHIP_IMAGE_WIDTH); // Start with a sequencer CAniSequencer *pRoot = new CAniSequencer; pRoot->SetPropertyVector(PROP_POSITION, CVector(0, yStart)); // Add the character name and current star system CString sHeading = strPatternSubst(CONSTLIT("%s — %s"), GameFile.GetPlayerName(), GameFile.GetSystemName()); IAnimatron *pName = new CAniText; pName->SetPropertyVector(PROP_POSITION, CVector(xText, y)); pName->SetPropertyVector(PROP_SCALE, CVector(10000, 1000)); pName->SetPropertyColor(PROP_COLOR, VI.GetColor(colorTextDialogInput)); pName->SetPropertyFont(PROP_FONT, &SubTitleFont); pName->SetPropertyString(PROP_TEXT, sHeading); pRoot->AddTrack(pName, 0); y += SubTitleFont.GetHeight(); // Now add some additional information CShipClass *pClass = g_pUniverse->FindShipClass(GameFile.GetPlayerShip()); CString sShipClass = (pClass ? pClass->GetName() : NULL_STR); CString sGenome = strCapitalize(GetGenomeName(GameFile.GetPlayerGenome())); CString sState; if (GameFile.IsGameResurrect()) sState = strPatternSubst(CONSTLIT("Resurrect in the %s System"), GameFile.GetSystemName()); else sState = strPatternSubst(CONSTLIT("Continue in the %s System"), GameFile.GetSystemName()); CString sDesc; if (!sGenome.IsBlank() && !sShipClass.IsBlank()) sDesc = strPatternSubst(CONSTLIT("%s — %s — %s"), sGenome, sShipClass, sState); else sDesc = sState; IAnimatron *pDesc = new CAniText; pDesc->SetPropertyVector(PROP_POSITION, CVector(xText, y)); pDesc->SetPropertyVector(PROP_SCALE, CVector(cxText, 1000)); pDesc->SetPropertyColor(PROP_COLOR, VI.GetColor(colorTextDialogInput)); pDesc->SetPropertyFont(PROP_FONT, &MediumFont); pDesc->SetPropertyString(PROP_TEXT, sDesc); RECT rcLine; pDesc->GetSpacingRect(&rcLine); pRoot->AddTrack(pDesc, 0); y += RectHeight(rcLine); // Adventure info CExtension *pAdventure = NULL; bool bHasAdventureIcon = false; if (g_pUniverse->FindExtension(GameFile.GetAdventure(), 0, &pAdventure)) { // Adventure icon CG16bitImage *pIcon; pAdventure->CreateIcon(ADVENTURE_ICON_WIDTH, ADVENTURE_ICON_HEIGHT, &pIcon); if (pIcon) { int xOffset = (ADVENTURE_ICON_WIDTH - pIcon->GetWidth()) / 2; IAnimatron *pIconAni = new CAniRect; pIconAni->SetPropertyVector(PROP_POSITION, CVector(x + xOffset, 0)); pIconAni->SetPropertyVector(PROP_SCALE, CVector(pIcon->GetWidth(), pIcon->GetHeight())); pIconAni->SetFillMethod(new CAniImageFill(pIcon, true)); pRoot->AddTrack(pIconAni, 0); bHasAdventureIcon = true; } // Adventure name pName = new CAniText; pName->SetPropertyVector(PROP_POSITION, CVector(xText, y)); pName->SetPropertyVector(PROP_SCALE, CVector(10000, 1000)); pName->SetPropertyColor(PROP_COLOR, VI.GetColor(colorTextDialogLabel)); pName->SetPropertyFont(PROP_FONT, &MediumFont); pName->SetPropertyString(PROP_TEXT, pAdventure->GetName()); pRoot->AddTrack(pName, 0); y += MediumFont.GetHeight(); } // Create an image of the ship class if (pClass) { const CObjectImageArray &ObjImage = pClass->GetImage(); if (!ObjImage.IsEmpty()) { RECT rcRect = ObjImage.GetImageRect(); CG16bitImage &Image = ObjImage.GetImage(NULL_STR); int cxImage = RectWidth(rcRect); int cyImage = RectHeight(rcRect); int cxNewWidth = Min(SHIP_IMAGE_WIDTH, cxImage); int cyNewHeight = cxNewWidth; CG16bitImage *pNewImage = new CG16bitImage; pNewImage->CreateFromImageTransformed(Image, rcRect.left, rcRect.top, cxImage, cyImage, (Metric)cxNewWidth / cxImage, (Metric)cyNewHeight / cyImage, 0.0); // Position int xImage = x + m_cxWidth - SHIP_IMAGE_WIDTH + (SHIP_IMAGE_WIDTH - cxNewWidth) / 2; int yImage = (SHIP_IMAGE_HEIGHT - cyNewHeight) / 2; // New image frame IAnimatron *pImageFrame = new CAniRect; pImageFrame->SetPropertyVector(PROP_POSITION, CVector(xImage, yImage)); pImageFrame->SetPropertyVector(PROP_SCALE, CVector(cxNewWidth, cyNewHeight)); pImageFrame->SetFillMethod(new CAniImageFill(pNewImage, true)); pRoot->AddTrack(pImageFrame, 0); } } // Extra information CString sEpitaph = GameFile.GetEpitaph(); int iScore = GameFile.GetScore(); CTimeDate LocalTime = ModifiedTime.ToLocalTime(); CString sModifiedTime = LocalTime.Format("%d %B %Y %I:%M %p"); CString sFilename = pathGetFilename(GameFile.GetFilespec()); CString sGameType; if (GameFile.IsRegistered()) sGameType = CONSTLIT("Registered"); else if (GameFile.IsDebug()) sGameType = CONSTLIT("Debug"); else sGameType = CONSTLIT("Unregistered"); CString sExtra; if (!sEpitaph.IsBlank()) sExtra = strPatternSubst(CONSTLIT("Score %d — %s\n%s — %s — %s"), iScore, sEpitaph, sGameType, sModifiedTime, sFilename); else if (iScore > 0) sExtra = strPatternSubst(CONSTLIT("Score %d\n%s — %s — %s"), iScore, sGameType, sModifiedTime, sFilename); else sExtra = strPatternSubst(CONSTLIT("%s — %s — %s"), sGameType, sModifiedTime, sFilename); pDesc = new CAniText; pDesc->SetPropertyVector(PROP_POSITION, CVector(xText, y)); pDesc->SetPropertyVector(PROP_SCALE, CVector(cxText, 1000)); pDesc->SetPropertyColor(PROP_COLOR, VI.GetColor(colorTextDialogLabel)); pDesc->SetPropertyFont(PROP_FONT, &MediumFont); pDesc->SetPropertyString(PROP_TEXT, sExtra); pDesc->GetSpacingRect(&rcLine); pRoot->AddTrack(pDesc, 0); y += RectHeight(rcLine); // Done *retpEntry = pRoot; if (retcyHeight) *retcyHeight = (bHasAdventureIcon ? Max(ADVENTURE_ICON_HEIGHT, y) : y); }
void DrawAlphaGradientCircle (CG16bitImage &Dest, int xDest, int yDest, int iRadius, WORD wColor) // DrawAlphaGradientCircle // // Draws a filled circle of the given color. The circle has an alpha gradient // that ranges from fully opaque in the center to fully transparent at the edges. { // Deal with edge-conditions if (iRadius <= 0) { Dest.DrawPixel(xDest, yDest, wColor); return; } // Initialize some stuff int x = 0; int y = iRadius; int d = 1 - iRadius; int deltaE = 3; int deltaSE = -2 * iRadius + 5; // Prepare struct SAlphaGradientCircleLineCtx Ctx; Ctx.pDest = &Dest; Ctx.xDest = xDest; Ctx.yDest = yDest; Ctx.iRadius = iRadius; Ctx.wColor = wColor; // Pre-compute some color info DWORD dwColor = wColor; Ctx.dwRed = (dwColor >> 11) & 0x1f; Ctx.dwGreen = (dwColor >> 5) & 0x3f; Ctx.dwBlue = dwColor & 0x1f; // Draw central line DrawAlphaGradientCircleLine(Ctx, iRadius, 0); // Draw lines above and below the center int iLastDraw = -1; while (y > x) { if (d < 0) { d += deltaE; deltaE += 2; deltaSE += 2; } else { d += deltaSE; deltaE += 2; deltaSE += 4; // Draw lines DrawAlphaGradientCircleLine(Ctx, x, y); iLastDraw = y; // Next y--; } x++; // Draw lines if (x != iLastDraw) DrawAlphaGradientCircleLine(Ctx, y, x); } }
void CCompositeEntry::GetImage (const CCompositeImageSelector &Selector, CObjectImageArray *retImage) // GetImage // // Fills in the image { int i; // Null case if (m_Layers.GetCount() == 0) { *retImage = EMPTY_IMAGE; return; } // Get all the layers TArray<CObjectImageArray> Result; Result.InsertEmpty(m_Layers.GetCount()); for (i = 0; i < m_Layers.GetCount(); i++) m_Layers[i]->GetImage(Selector, &Result[i]); // Create the composited image // // First we need to determine the size of the final image, based // on the size and position of each layer. int xMin = 0; int xMax = 0; int yMin = 0; int yMax = 0; for (i = 0; i < m_Layers.GetCount(); i++) { CObjectImageArray &LayerImage = Result[i]; const RECT &rcRect = LayerImage.GetImageRect(); int xImageOffset = 0; int yImageOffset = 0; int xMaxImage = (RectWidth(rcRect) / 2) + xImageOffset; int xMinImage = xMaxImage - RectWidth(rcRect); int yMaxImage = (RectHeight(rcRect) / 2) + yImageOffset; int yMinImage = yMaxImage - RectHeight(rcRect); xMin = Min(xMin, xMinImage); xMax = Max(xMax, xMaxImage); yMin = Min(yMin, yMinImage); yMax = Max(yMax, yMaxImage); } // Create destination image int cxWidth = xMax - xMin; int cyHeight = yMax - yMin; if (cxWidth <= 0 || cyHeight <= 0) { *retImage = EMPTY_IMAGE; return; } CG16bitImage *pComp = new CG16bitImage; pComp->CreateBlank(cxWidth, cyHeight, false); pComp->SetTransparentColor(); int xCenter = cxWidth / 2; int yCenter = cyHeight / 2; // Blt on the destination for (i = 0; i < m_Layers.GetCount(); i++) { CObjectImageArray &LayerImage = Result[i]; const RECT &rcRect = LayerImage.GetImageRect(); // Paint the image LayerImage.PaintImage(*pComp, xCenter, yCenter, 0, 0); } // Initialize an image RECT rcFinalRect; rcFinalRect.left = 0; rcFinalRect.top = 0; rcFinalRect.right = cxWidth; rcFinalRect.bottom = cyHeight; CObjectImageArray Comp; Comp.Init(pComp, rcFinalRect, 0, 0, true); // Done retImage->TakeHandoff(Comp); }
void GenerateTopologyMap (CUniverse &Universe, CXMLElement *pCmdLine) { int i, j; STopologyMapCtx Ctx; // Initialize the output COutputChart Output; Output.SetStyleFont(STYLE_NAME, pCmdLine->GetAttribute(CONSTLIT("font"))); Output.SetStyleColor(STYLE_NAME, CG16bitImage::RGBValue(0xFF, 0xFF, 0xFF)); Output.SetOutputFilespec(pCmdLine->GetAttribute(CONSTLIT("output"))); // Get the topology node CTopologyNode *pFirstNode = Universe.GetFirstTopologyNode(); if (pFirstNode == NULL) { printf("ERROR: Unable to find topology node.\n"); return; } // Get the system map for the node Ctx.pMap = pFirstNode->GetDisplayPos(); if (Ctx.pMap == NULL) { printf("ERROR: No system map for node %s.\n", pFirstNode->GetID().GetASCIIZPointer()); return; } // Create a background image CG16bitImage *pImage = Ctx.pMap->CreateBackgroundImage(); // Create the output Output.SetContentSize((pImage ? pImage->GetWidth() : 1024), (pImage ? pImage->GetHeight() : 1024)); CG16bitImage &Dest = Output.GetOutputImage(); // Blt if (pImage) Dest.Blt(0, 0, pImage->GetWidth(), pImage->GetHeight(), *pImage, 0, 0); // Done with background image delete pImage; pImage = NULL; // Compute the size of the map (in pixels) Ctx.cxMap = Dest.GetWidth(); Ctx.cyMap = Dest.GetHeight(); Ctx.xCenter = Ctx.cxMap / 2; Ctx.yCenter = Ctx.cyMap / 2; // Loop over all nodes and clear marks on the ones that we need to draw for (i = 0; i < Universe.GetTopologyNodeCount(); i++) { CTopologyNode *pNode = Universe.GetTopologyNode(i); int xPos, yPos; pNode->SetMarked(pNode->GetDisplayPos(&xPos, &yPos) != Ctx.pMap || pNode->IsEndGame()); } // Paint the nodes for (i = 0; i < Universe.GetTopologyNodeCount(); i++) { CTopologyNode *pNode = Universe.GetTopologyNode(i); if (!pNode->IsMarked()) { int xPos, yPos; pNode->GetDisplayPos(&xPos, &yPos); // Convert to view coordinates int x = Ctx.xCenter + xPos; int y = Ctx.yCenter - yPos; // Draw gate connections for (j = 0; j < pNode->GetStargateCount(); j++) { CTopologyNode *pDestNode = pNode->GetStargateDest(j); if (pDestNode && !pDestNode->IsMarked()) { int xPos, yPos; pDestNode->GetDisplayPos(&xPos, &yPos); int xDest = Ctx.xCenter + xPos; int yDest = Ctx.yCenter - yPos; Dest.DrawLine(x, y, xDest, yDest, STARGATE_LINE_WIDTH, STARGATE_LINE_COLOR); } } // Draw star system DrawNode(Ctx, Output, pNode, x, y); pNode->SetMarked(); } } // Done Output.Output(); }
void CUIHelper::CreateClassInfoSpecialItem (CItemType *pItemIcon, const CString &sText, int x, int y, int cxWidth, DWORD dwOptions, int *retcyHeight, IAnimatron **retpInfo) const // CreateClassInfoSpecialItem // // Creates a special item info animation { const CVisualPalette &VI = m_HI.GetVisuals(); // Figure out some dimensions and metrics. Everything is relative to x, y. bool bRightAlign = ((dwOptions & OPTION_ITEM_RIGHT_ALIGN) ? true : false); int cxIcon = SMALL_ICON_WIDTH; int cyIcon = SMALL_ICON_HEIGHT; int xIcon = (bRightAlign ? -cxIcon : 0); int yIcon = 0; int cxText = cxWidth - (cxIcon + ITEM_INFO_SPACING_HORZ); int xText = (bRightAlign ? -cxWidth : cxIcon + ITEM_INFO_SPACING_HORZ); int yText = 0; // Create a sequencer to hold all the controls CAniSequencer *pRoot; CAniSequencer::Create(CVector(x, y), &pRoot); // Create a small item icon if (pItemIcon) { const CObjectImageArray &Image = pItemIcon->GetImage(); RECT rcImage = Image.GetImageRect(); if (!Image.IsEmpty()) { CG16bitImage *pIcon = new CG16bitImage; pIcon->CreateFromImageTransformed(Image.GetImage(), rcImage.left, rcImage.top, RectWidth(rcImage), RectHeight(rcImage), (Metric)SMALL_ICON_WIDTH / RectWidth(rcImage), (Metric)SMALL_ICON_HEIGHT / RectHeight(rcImage), 0.0); IAnimatron *pImageFrame = new CAniRect; pImageFrame->SetPropertyVector(PROP_POSITION, CVector(xIcon, yIcon)); pImageFrame->SetPropertyVector(PROP_SCALE, CVector(SMALL_ICON_WIDTH, SMALL_ICON_HEIGHT)); pImageFrame->SetFillMethod(new CAniImageFill(pIcon, true)); pRoot->AddTrack(pImageFrame, 0); } } // Create some text int cyText = 0; IAnimatron *pRef = new CAniRichText(VI); pRef->SetPropertyVector(PROP_POSITION, CVector(xText, yText + cyText)); pRef->SetPropertyVector(PROP_SCALE, CVector(cxText, 1000)); pRef->SetPropertyString(PROP_TEXT, sText); if (bRightAlign) pRef->SetPropertyString(PROP_TEXT_ALIGN_HORZ, ALIGN_RIGHT); pRoot->AddTrack(pRef, 0); RECT rcRef; pRef->GetSpacingRect(&rcRef); cyText += RectHeight(rcRef); // Done if (retcyHeight) *retcyHeight = Max(cyText, SMALL_ICON_HEIGHT); *retpInfo = pRoot; }
void DrawNebulosity8bit (CG16bitImage &Dest, int x, int y, int cxWidth, int cyHeight, int iScale, BYTE byMin, BYTE byMax) // DrawNebulosity8bit // // Draws 8-bit clouds. { int i; ASSERT(iScale > 0); NoiseInit(); // Make sure we're in bounds if (!Dest.HasAlpha() || !Dest.AdjustCoords(NULL, NULL, 0, 0, &x, &y, &cxWidth, &cyHeight)) return; // We need noise generators for each frequency struct SFreq { int iFreq; float Amplitude; CNoiseGenerator *pNoise; SNoisePos x; SNoisePos y; }; TArray<SFreq> FreqList; // At iMinFreq = 1 we create detail all the way to the pixel level. int iMinFreq = 1;//Max(iScale / 256, 1); // In theory, the noise function returns values from -1.0 to 1.0, but // in practice the values are clutered between -0.5 to 0.5. We multiply // the result by this amplitude adjustment so that we get a greater // dynamic range. float rAmplitudeAdj = 2.0f; // As we get to smaller and smaller detail, the amplitude decreases // (by half for each frequency). But if there are too many levels of // detail, the amplitude decreases so much that it is invisible. // Thus we have a minimum amplitude. float rMinAmplitude = (float)iScale / 32.0f; // Create noise generators are each frequency. float rMaxValue = 0.0; int iFreq = iScale; while (iFreq >= iMinFreq) { SFreq *pFreq = FreqList.Insert(); pFreq->iFreq = iFreq; pFreq->pNoise = new CNoiseGenerator(iFreq); pFreq->Amplitude = rAmplitudeAdj * Max((float)iFreq, rMinAmplitude); rMaxValue += (pFreq->Amplitude / rAmplitudeAdj); iFreq = iFreq / 2; }; // Compute the factor to adjust the pixel value float rRange = (float)(byMax - byMin) + 0.99999f; float rFactor = rRange / (2.0f * rMaxValue); int iFreqCount = FreqList.GetCount(); // Fill for (i = 0; i < iFreqCount; i++) FreqList[i].pNoise->Reset(FreqList[i].y, y); BYTE *pRow = Dest.GetAlphaRow(y); BYTE *pRowEnd = Dest.GetAlphaRow(y + cyHeight); while (pRow < pRowEnd) { for (i = 0; i < iFreqCount; i++) FreqList[i].pNoise->Reset(FreqList[i].x, x); BYTE *pPos = pRow; BYTE *pPosEnd = pRow + cxWidth; while (pPos < pPosEnd) { float rValue = rMaxValue; for (i = 0; i < iFreqCount; i++) { SFreq *pFreq = &FreqList[i]; rValue += pFreq->pNoise->GetAt(pFreq->x, pFreq->y) * pFreq->Amplitude; pFreq->pNoise->Next(pFreq->x); } *pPos = (BYTE)Clamp((DWORD)byMin + (DWORD)(rFactor * rValue), (DWORD)byMin, (DWORD)byMax); // Next pixel pPos++; } // Next row pRow = Dest.NextAlphaRow(pRow); for (i = 0; i < iFreqCount; i++) FreqList[i].pNoise->Next(FreqList[i].y); } // Free the noise generators for (i = 0; i < iFreqCount; i++) delete FreqList[i].pNoise; }
void GenerateShipImageChart (CUniverse &Universe, CXMLElement *pCmdLine) { int i; enum OrderTypes { orderSmallest = 1, orderLargest = 2, orderName = 3, }; // Options bool bTextBoxesOnly = pCmdLine->GetAttributeBool(CONSTLIT("textBoxesOnly")); // Figure out what order we want CString sOrder = pCmdLine->GetAttribute(CONSTLIT("sort")); int iOrder; if (strEquals(sOrder, CONSTLIT("smallest"))) iOrder = orderSmallest; else if (strEquals(sOrder, CONSTLIT("largest"))) iOrder = orderLargest; else iOrder = orderName; // Image size int cxDesiredWidth; if (pCmdLine->FindAttributeInteger(CONSTLIT("width"), &cxDesiredWidth)) cxDesiredWidth = Max(512, cxDesiredWidth); else cxDesiredWidth = 1280; // Spacing int cxSpacing = pCmdLine->GetAttributeInteger(CONSTLIT("xSpacing")); int cxExtraMargin = pCmdLine->GetAttributeInteger(CONSTLIT("xMargin")); // Rotation int iRotation = pCmdLine->GetAttributeInteger(CONSTLIT("rotation")); // Font for text CString sTypeface; int iSize; bool bBold; bool bItalic; if (!CG16bitFont::ParseFontDesc(pCmdLine->GetAttribute(CONSTLIT("font")), &sTypeface, &iSize, &bBold, &bItalic)) { sTypeface = CONSTLIT("Arial"); iSize = 10; bBold = false; bItalic = false; } CG16bitFont NameFont; NameFont.Create(sTypeface, -PointsToPixels(iSize), bBold, bItalic); WORD wNameColor = CG16bitImage::RGBValue(255, 255, 255); // Output file CString sFilespec = pCmdLine->GetAttribute(CONSTLIT("output")); if (!sFilespec.IsBlank()) sFilespec = pathAddExtensionIfNecessary(sFilespec, CONSTLIT(".bmp")); // Generate a table of ships CSymbolTable Table(FALSE, TRUE); for (i = 0; i < Universe.GetShipClassCount(); i++) { CShipClass *pClass = Universe.GetShipClass(i); // Skip player ship classes if (pClass->GetPlayerSettings()) continue; // Skip non-generic classes if (!pClass->HasAttribute(CONSTLIT("genericClass"))) continue; // Compute the sort key char szBuffer[1024]; switch (iOrder) { case orderLargest: wsprintf(szBuffer, "%04d%s%x", 2048 - RectWidth(pClass->GetImage().GetImageRect()), pClass->GetName().GetASCIIZPointer(), pClass); break; case orderSmallest: wsprintf(szBuffer, "%04d%s%x", RectWidth(pClass->GetImage().GetImageRect()), pClass->GetName().GetASCIIZPointer(), pClass); break; default: wsprintf(szBuffer, "%s%x", pClass->GetName().GetASCIIZPointer(), pClass); break; } // Add to list Table.AddEntry(CString(szBuffer), (CObject *)pClass); } // Allocate a map that tracks where to paint each ship CPaintMap Map(Table.GetCount()); // Arrange the ships SArrangeDesc Desc; Desc.cxDesiredWidth = Max(512, cxDesiredWidth - (2 * (cxSpacing + cxExtraMargin))); Desc.cxSpacing = cxSpacing; Desc.cxExtraMargin = cxExtraMargin; Desc.pHeader = &NameFont; ArrangeByRow(Table, Desc, Map); //ArrangeByCell(Table, cxDesiredWidth, Map); // Create a large image CG16bitImage Output; int cxWidth = Max(cxDesiredWidth, Map.GetWidth()); int cyHeight = Map.GetHeight(); Output.CreateBlank(cxWidth, cyHeight, false); printf("Creating %dx%d image.\n", cxWidth, cyHeight); // Paint the images for (i = 0; i < Table.GetCount(); i++) { CShipClass *pClass = (CShipClass *)Table.GetValue(i); int x = Map.GetX(i); int y = Map.GetY(i); if (x != -1) { if (!bTextBoxesOnly) pClass->GetImage().PaintImageUL(Output, x, y, 0, Angle2Direction(iRotation)); // Paint name int xText = Map.GetTextX(i); int yText = Map.GetTextY(i); if (xText != -1) { if (bTextBoxesOnly) Output.Fill(xText, yText, Map.GetTextWidth(i), Map.GetTextHeight(i), 0xffff); if (!bTextBoxesOnly) { Output.FillColumn(x + (Map.GetWidth(i) / 2), y + Map.GetHeight(i), yText - (y + Map.GetHeight(i)), wNameColor); NameFont.DrawText(Output, xText, yText, wNameColor, 255, pClass->GetNounPhrase(0)); } } } } // Write to file or clipboard OutputImage(Output, sFilespec); }
void CUIHelper::CreateClassInfoItem (const CItem &Item, int x, int y, int cxWidth, DWORD dwOptions, const CString &sExtraDesc, int *retcyHeight, IAnimatron **retpInfo) const // CreateClassInfoItem // // Creates an item info animation { const CVisualPalette &VI = m_HI.GetVisuals(); const CG16bitFont &MediumFont = VI.GetFont(fontMedium); const CG16bitFont &MediumBoldFont = VI.GetFont(fontMediumBold); const CG16bitFont &SubTitleFont = VI.GetFont(fontSubTitle); // Handle some edge conditions CItemType *pType = Item.GetType(); if (pType == NULL) { if (retcyHeight) *retcyHeight = 0; CAniSequencer::Create(CVector(x, y), (CAniSequencer **)retpInfo); return; } // Figure out some dimensions and metrics. Everything is relative to x, y. bool bRightAlign = ((dwOptions & OPTION_ITEM_RIGHT_ALIGN) ? true : false); int cxIcon = SMALL_ICON_WIDTH; int cyIcon = SMALL_ICON_HEIGHT; int xIcon = (bRightAlign ? -cxIcon : 0); int yIcon = 0; int cxText = cxWidth - (cxIcon + ITEM_INFO_SPACING_HORZ); int xText = (bRightAlign ? -cxWidth : cxIcon + ITEM_INFO_SPACING_HORZ); int yText = 0; // Create a sequencer to hold all the controls CAniSequencer *pRoot; CAniSequencer::Create(CVector(x, y), &pRoot); // Create a small item icon const CObjectImageArray &Image = pType->GetImage(); RECT rcImage = Image.GetImageRect(); if (!Image.IsEmpty()) { CG16bitImage *pIcon = new CG16bitImage; pIcon->CreateFromImageTransformed(Image.GetImage(), rcImage.left, rcImage.top, RectWidth(rcImage), RectHeight(rcImage), (Metric)SMALL_ICON_WIDTH / RectWidth(rcImage), (Metric)SMALL_ICON_HEIGHT / RectHeight(rcImage), 0.0); IAnimatron *pImageFrame = new CAniRect; pImageFrame->SetPropertyVector(PROP_POSITION, CVector(xIcon, yIcon)); pImageFrame->SetPropertyVector(PROP_SCALE, CVector(SMALL_ICON_WIDTH, SMALL_ICON_HEIGHT)); pImageFrame->SetFillMethod(new CAniImageFill(pIcon, true)); pRoot->AddTrack(pImageFrame, 0); } // Create text int cyText = 0; IAnimatron *pName = new CAniText; pName->SetPropertyVector(PROP_POSITION, CVector(xText, yText + cyText)); pName->SetPropertyVector(PROP_SCALE, CVector(cxText, 1000)); pName->SetPropertyColor(PROP_COLOR, VI.GetColor(colorTextDialogInput)); pName->SetPropertyFont(PROP_FONT, &MediumBoldFont); pName->SetPropertyString(PROP_TEXT, pType->GetNounPhrase(nounActual)); if (bRightAlign) pName->SetPropertyString(PROP_TEXT_ALIGN_HORZ, ALIGN_RIGHT); pRoot->AddTrack(pName, 0); cyText += MediumBoldFont.GetHeight(); // Add the damage type adjustment CItemDataAnimatron *pDamageDesc = new CItemDataAnimatron(VI, Item); if (!pDamageDesc->IsEmpty()) { pDamageDesc->SetPropertyVector(PROP_POSITION, CVector(xText, yText + cyText)); pDamageDesc->SetPropertyVector(PROP_SCALE, CVector(cxText, 1000)); if (bRightAlign) pDamageDesc->SetPropertyString(PROP_TEXT_ALIGN_HORZ, ALIGN_RIGHT); pRoot->AddTrack(pDamageDesc, 0); RECT rcRect; pDamageDesc->GetSpacingRect(&rcRect); cyText += RectHeight(rcRect); } else delete pDamageDesc; // Add the reference text CItemCtx ItemCtx; CString sRef = pType->GetReference(ItemCtx, -1, CItemType::FLAG_ACTUAL_ITEM); if (sRef.IsBlank()) sRef = strPatternSubst(CONSTLIT("Level %s%s"), strLevel(pType->GetLevel()), sExtraDesc); else sRef = strPatternSubst(CONSTLIT("Level %s — %s%s"), strLevel(pType->GetLevel()), sRef, sExtraDesc); IAnimatron *pRef = new CAniText; pRef->SetPropertyVector(PROP_POSITION, CVector(xText, yText + cyText)); pRef->SetPropertyVector(PROP_SCALE, CVector(cxText, 1000)); pRef->SetPropertyColor(PROP_COLOR, VI.GetColor(colorTextDialogLabel)); pRef->SetPropertyFont(PROP_FONT, &MediumFont); pRef->SetPropertyString(PROP_TEXT, sRef); if (bRightAlign) pRef->SetPropertyString(PROP_TEXT_ALIGN_HORZ, ALIGN_RIGHT); pRoot->AddTrack(pRef, 0); RECT rcRef; pRef->GetSpacingRect(&rcRef); cyText += RectHeight(rcRef); // Done if (retcyHeight) *retcyHeight = Max(cyText, SMALL_ICON_HEIGHT); *retpInfo = pRoot; }
void CNewGameSession::SetShipClassImage (CShipClass *pClass, int x, int y, int cxWidth) // SetShipClassImage // // Sets the current ship class image { const CPlayerSettings *pPlayerSettings = pClass->GetPlayerSettings(); const CG16bitImage *pImage = g_pUniverse->GetLibraryBitmap(pPlayerSettings->GetLargeImage()); // Delete the previous one DeleteElement(ID_SHIP_CLASS_IMAGE); // Add the new one, if we've got one. const CG16bitImage *pImageToUse = NULL; bool bFree = false; if (pImage && !pImage->IsEmpty()) { // If this image is not the right size, then create a resized version // that is. if (pImage->GetWidth() != SHIP_IMAGE_WIDTH || pImage->GetHeight() != SHIP_IMAGE_HEIGHT) { int cxNewWidth = SHIP_IMAGE_WIDTH; int cyNewHeight = cxNewWidth * pImage->GetHeight() / pImage->GetWidth(); if (cyNewHeight > SHIP_IMAGE_HEIGHT) { cyNewHeight = SHIP_IMAGE_HEIGHT; cxNewWidth = cyNewHeight * pImage->GetWidth() / pImage->GetHeight(); } CG16bitImage *pNewImage = new CG16bitImage; pNewImage->CreateFromImageTransformed(*pImage, 0, 0, pImage->GetWidth(), pImage->GetHeight(), (Metric)cxNewWidth / pImage->GetWidth(), (Metric)cyNewHeight / pImage->GetHeight(), 0.0); pImageToUse = pNewImage; bFree = true; } else { pImageToUse = pImage; bFree = false; } } // If we don't have an image then ask the class to paint it else { CG16bitImage *pNewImage = new CG16bitImage; pNewImage->CreateBlank(SHIP_IMAGE_WIDTH, SHIP_IMAGE_HEIGHT, false); ViewportTransform Trans; pClass->Paint(*pNewImage, SHIP_IMAGE_WIDTH / 2, SHIP_IMAGE_HEIGHT / 2, Trans, 0, 0, false, false ); pImageToUse = pNewImage; bFree = true; } // Position int xImage = x + (cxWidth - pImageToUse->GetWidth()) / 2; int yImage = y + (SHIP_IMAGE_HEIGHT - pImageToUse->GetHeight()) / 2; // New image frame IAnimatron *pImageFrame = new CAniRect; pImageFrame->SetID(ID_SHIP_CLASS_IMAGE); pImageFrame->SetPropertyVector(PROP_POSITION, CVector(xImage, yImage)); pImageFrame->SetPropertyVector(PROP_SCALE, CVector(pImageToUse->GetWidth(), pImageToUse->GetHeight())); pImageFrame->SetFillMethod(new CAniImageFill(pImageToUse, bFree)); m_pRoot->AddLine(pImageFrame); }
void AGScreen::Paint (CG16bitImage &Dest) // Paint // // Paint the whole screen. // // Dest is the entire display area; its origin is 0,0. { if (!IsRectEmpty(&m_rcInvalid)) { int i; // Convert to Window coordinates RECT rcUpdate = m_rcInvalid; OffsetRect(&rcUpdate, m_rcRect.left, m_rcRect.top); // Clip appropriately. Note that Dest is always in // window coordinates. Dest.SetClipRect(rcUpdate); // Blank the screen Dest.Fill(rcUpdate.left, rcUpdate.top, RectWidth(rcUpdate), RectHeight(rcUpdate), CG16bitImage::RGBValue(0,0,0)); // Let each area paint for (i = 0; i < GetAreaCount(); i++) { AGArea *pArea = GetArea(i); // m_rcInvalid is in Screen coordinates, and so is the rect // for each area. The intersection is the portion of the // area's rect that is invalid. RECT rcIntersect; if (pArea->IsVisible() && ::IntersectRect(&rcIntersect, &m_rcInvalid, &pArea->GetRect())) { // Calculate the rect of the area relative to the Window RECT rcArea = pArea->GetRect(); OffsetRect(&rcArea, m_rcRect.left, m_rcRect.top); // Clip appropriately OffsetRect(&rcIntersect, m_rcRect.left, m_rcRect.top); Dest.SetClipRect(rcIntersect); // Paint pArea->Paint(Dest, rcArea); } } // Reset the invalid rect memset(&m_rcInvalid, 0, sizeof(m_rcInvalid)); Dest.ResetClipRect(); } }
void CFilterColorizeEntry::GetImage (const CCompositeImageSelector &Selector, CObjectImageArray *retImage) // GetImage // // Fills in the image { // Null case if (m_pSource == NULL) { *retImage = EMPTY_IMAGE; return; } // Get the source image (which we want to colorize) CObjectImageArray Source; m_pSource->GetImage(Selector, &Source); const RECT &rcSource = Source.GetImageRect(); CG16bitImage &SourceImage = Source.GetImage(NULL_STR); int cxWidth = RectWidth(rcSource); int cyHeight = RectHeight(rcSource); if (Source.IsEmpty() || cxWidth == 0 || cyHeight == 0) { *retImage = EMPTY_IMAGE; return; } // Create the destination image CG16bitImage *pDest = new CG16bitImage; pDest->CreateBlank(cxWidth, cyHeight, SourceImage.HasAlpha()); if (!SourceImage.HasAlpha()) pDest->SetTransparentColor(); // Blt the to the destination with colorization CopyBltColorize(*pDest, 0, 0, cxWidth, cyHeight, SourceImage, rcSource.left, rcSource.top, m_dwHue, m_dwSaturation); // Initialize an image RECT rcFinalRect; rcFinalRect.left = 0; rcFinalRect.top = 0; rcFinalRect.right = cxWidth; rcFinalRect.bottom = cyHeight; CObjectImageArray Comp; Comp.Init(pDest, rcFinalRect, 0, 0, true); // Done retImage->TakeHandoff(Comp); }
void CParticleEffect::PaintSmokeParticles (SParticleArray *pGroup, CG16bitImage &Dest, int x, int y, SViewportPaintCtx &Ctx) // PaintSmokeParticles // // Paint particles as smoke { SParticleType *pType = pGroup->pType; SParticle *pParticle = pGroup->pParticles; SParticle *pEnd = pParticle + pGroup->iCount; while (pParticle < pEnd) { if (pParticle->IsValid()) { // Compute color int iColor = 64 + (pParticle->iDestiny % 192); WORD wColor = CG16bitImage::RGBValue(iColor, iColor, iColor); // Compute how much to fade out the smoke int iFade = 0; int iSize = 0; if (pType->iLifespan) { iFade = 255 * pParticle->iLifeLeft / pType->iLifespan; iSize = 5 - (5 * pParticle->iLifeLeft / pType->iLifespan); } int iFade2 = iFade / 2; // Compute the position int x, y; Ctx.XForm.Transform(GetPos() + pParticle->vPos, &x, &y); // Paint switch (iSize) { case 0: Dest.DrawPixelTrans(x, y, wColor, iFade); break; case 1: Dest.DrawPixelTrans(x, y, wColor, iFade); Dest.DrawPixelTrans(x + 1, y, wColor, iFade2); Dest.DrawPixelTrans(x, y + 1, wColor, iFade2); break; case 2: Dest.DrawPixelTrans(x, y, wColor, iFade); Dest.DrawPixelTrans(x + 1, y, wColor, iFade2); Dest.DrawPixelTrans(x, y + 1, wColor, iFade2); Dest.DrawPixelTrans(x - 1, y, wColor, iFade2); Dest.DrawPixelTrans(x, y - 1, wColor, iFade2); break; case 3: Dest.DrawPixelTrans(x, y, wColor, iFade); Dest.DrawPixelTrans(x + 1, y, wColor, iFade); Dest.DrawPixelTrans(x, y + 1, wColor, iFade); Dest.DrawPixelTrans(x - 1, y, wColor, iFade); Dest.DrawPixelTrans(x, y - 1, wColor, iFade); Dest.DrawPixelTrans(x + 1, y + 1, wColor, iFade2); Dest.DrawPixelTrans(x + 1, y - 1, wColor, iFade2); Dest.DrawPixelTrans(x - 1, y + 1, wColor, iFade2); Dest.DrawPixelTrans(x - 1, y - 1, wColor, iFade2); break; case 4: default: { Dest.FillTransRGB(x - 1, y - 1, 3, 3, RGB(192, 192, 192), iFade); Dest.DrawPixelTrans(x + 2, y, wColor, iFade2); Dest.DrawPixelTrans(x, y + 2, wColor, iFade2); Dest.DrawPixelTrans(x - 2, y, wColor, iFade2); Dest.DrawPixelTrans(x, y - 2, wColor, iFade2); } } } pParticle++; } }
CG16bitImage *CSystemMap::CreateBackgroundImage (void) // CreateBackgroundImage // // Creates an image containing the map. // Caller is responsible for freeing the returned image. { int i; CG16bitImage *pImage = g_pUniverse->GetLibraryBitmapCopy(m_dwBackgroundImage); if (pImage == NULL) return NULL; int xCenter = pImage->GetWidth() / 2; int yCenter = pImage->GetHeight() / 2; // Paint all annotations if (m_Annotations.GetCount() > 0) { SViewportPaintCtx Ctx; for (i = 0; i < m_Annotations.GetCount(); i++) { SMapAnnotation *pAnnotation = &m_Annotations[i]; Ctx.iTick = pAnnotation->iTick; Ctx.iRotation = pAnnotation->iRotation; pAnnotation->pPainter->Paint(*pImage, xCenter + pAnnotation->xOffset, yCenter - pAnnotation->yOffset, Ctx); } } #ifdef DEBUG #if 0 // Test noise function CG16bitImage Alpha; Alpha.CreateBlankAlpha(pImage->GetWidth(), pImage->GetHeight()); DrawNebulosity8bit(Alpha, 0, 0, pImage->GetWidth(), pImage->GetHeight(), 256, 0, 255); pImage->Fill(0, 0, pImage->GetWidth(), pImage->GetHeight(), 0); pImage->FillMask(0, 0, pImage->GetWidth(), pImage->GetHeight(), Alpha, CG16bitImage::RGBValue(255, 255, 255), 0, 0); #endif #endif return pImage; }
void CParticleEffect::OnPaint (CG16bitImage &Dest, int x, int y, SViewportPaintCtx &Ctx) // OnPaint // // Paint the effect { SParticleArray *pGroup = m_pFirstGroup; while (pGroup) { SParticleType *pType = pGroup->pType; // Paint image switch (pType->iPaintStyle) { case paintFlame: PaintFlameParticles(pGroup, Dest, x, y, Ctx); break; case paintImage: { int iTick = GetSystem()->GetTick(); SParticle *pParticle = pGroup->pParticles; SParticle *pEnd = pParticle + pGroup->iCount; while (pParticle < pEnd) { if (pParticle->IsValid()) { int x, y; Ctx.XForm.Transform(GetPos() + pParticle->vPos, &x, &y); pType->Image.PaintImage(Dest, x, y, iTick + pParticle->iDestiny, 0); } pParticle++; } break; } case paintSmoke: PaintSmokeParticles(pGroup, Dest, x, y, Ctx); break; default: { WORD wColor = CG16bitImage::RGBValue(0, 255, 0); SParticle *pParticle = pGroup->pParticles; SParticle *pEnd = pParticle + pGroup->iCount; while (pParticle < pEnd) { if (pParticle->IsValid()) { int x, y; Ctx.XForm.Transform(GetPos() + pParticle->vPos, &x, &y); Dest.DrawDot(x, y, wColor, CG16bitImage::markerSmallRound); } pParticle++; } } } pGroup = pGroup->pNext; } }
void COrbit::Paint (CG16bitImage &Dest, const ViewportTransform &Trans, COLORREF rgbColor) // Paint // // Paint the orbit { DWORD redValue = GetRValue(rgbColor); DWORD greenValue = GetGValue(rgbColor); DWORD blueValue = GetBValue(rgbColor); // Paint circular orbits in a single color; eccentric orbits change color // since they are not equidistant from the sun if (m_rEccentricity == 0.0) { Metric rAngle; const Metric rIncrement = g_Pi / 90.0; int xPrev, yPrev; WORD wColor; // The orbit color fades depending on the distance from the sun Metric rFade = 0.25 + (LIGHT_SECOND * 180.0 / m_rSemiMajorAxis); if (rFade < 1.0) wColor = CG16bitImage::RGBValue((int)(redValue * rFade), (int)(greenValue * rFade), (int)(blueValue * rFade)); else wColor = CG16bitImage::RGBValue((WORD)redValue, (WORD)greenValue, (WORD)blueValue); // Compute the position of the starting point Trans.Transform(GetPointCircular(0.0), &xPrev, &yPrev); // Paint the orbit in multiple segments for (rAngle = rIncrement; rAngle < g_Pi * 2.0; rAngle += rIncrement) { // Compute the end point int x, y; Trans.Transform(GetPointCircular(rAngle), &x, &y); // Draw a line segment Dest.DrawLine(xPrev, yPrev, x, y, 1, wColor); // Next point xPrev = x; yPrev = y; } } else { Metric rAngle; const Metric rIncrement = g_Pi / 90.0; int xPrev, yPrev; // Compute the position of the starting point Trans.Transform(GetPoint(0.0), &xPrev, &yPrev); // Paint the orbit in multiple segments for (rAngle = rIncrement; rAngle < g_Pi * 2.0; rAngle += rIncrement) { Metric rRadius; CVector vPos = GetPointAndRadius(rAngle, &rRadius); WORD wColor; // Compute the end point int x, y; Trans.Transform(vPos, &x, &y); // The orbit color fades depending on the distance from the sun Metric rFade = 0.25 + (LIGHT_SECOND * 180.0 / rRadius); if (rFade < 1.0) wColor = CG16bitImage::RGBValue((int)(redValue * rFade), (int)(greenValue * rFade), (int)(blueValue * rFade)); else wColor = CG16bitImage::RGBValue((WORD)redValue, (WORD)greenValue, (WORD)blueValue); // Draw a line segment Dest.DrawLine(xPrev, yPrev, x, y, 1, wColor); // Next point xPrev = x; yPrev = y; } } }