bool Rect::contains(const Int2 &point) const { return (point.getX() >= this->getLeft()) && (point.getY() >= this->getTop()) && (point.getX() < this->getRight()) && (point.getY() < this->getBottom()); }
void drawLine(const Int2& pos1, const Int2& pos2, const Color& color, float thickness) { glLineWidth(thickness); glColor4f(color.r()/256.f, color.g()/256.f, color.b()/256.f, color.a()/256.f); glDisable(GL_TEXTURE_2D); glMatrixMode(GL_MODELVIEW); glBegin(GL_LINES); glVertex2i(pos1.x(), pos1.y()); glVertex2i(pos2.x(), pos2.y()); glEnd(); glColor4f(1.f, 1.f, 1.f, 1.f); }
int ListBox::getClickedIndex(const Int2 &point) const { // Only the Y component of the point really matters here. const int index = this->scrollIndex + ((point.getY() - this->point.getY()) / this->font.getCharacterHeight()); return index; }
void EditText::draw(float fontScale) { Scene2D& scene2D = Engine::instance().getScene2DMgr(); //AssertRelease(font != NULL); if (isCrypted) { Int2 posRes = pos; for (size_t i = 0; i < text.size(); ++i) { //posx = font->drawText(color, Int2(posx,pos.y()),"*",fontScale).x(); posRes = scene2D.drawText(NULL, "*", posRes, fontScale, color); } } else { //font->drawText(color, Int2(pos.x(), pos.y()),text.c_str(),fontScale); scene2D.drawText(NULL, text.c_str(), pos, fontScale, color); } if (isFocused) { int64_t tim = Utils::getMillisecond(); if (tim > timeCount + 500) { timeCount = tim; timeIsDisplayed = !timeIsDisplayed; } if (timeIsDisplayed) { if (isCrypted) { //font->drawText(color, Int2(pos.x()+font->getWidth("*",-1,fontScale)*keypos-3,pos.y()),"|",fontScale); Int2 size = scene2D.getSizeText(NULL, "*", fontScale); scene2D.drawText(NULL, "|", Int2(pos.x()+size.width()*keypos-3,pos.y()), fontScale, color); } else { Int2 size = scene2D.getSizeText(NULL, text.c_str(), fontScale, keypos); //font->drawText(color, Int2(pos.x()+font->getWidth(text.c_str(),keypos,fontScale)-3,pos.y()),"|",fontScale); scene2D.drawText(NULL, "|", Int2(pos.x()+size.width()-3,pos.y()), fontScale, color); } } } }
void drawRectangle(const Int2& pos1, const Int2& pos2, const Color& color, float borderSize, bool isFilled) { glLineWidth(borderSize); glColor4f(color.r()/256.f, color.g()/256.f, color.b()/256.f, color.a()/256.f); //glColor4f(color.r()/255.f, color.g()/255.f, color.b()/255.f, color.a()/255.f); glDisable(GL_TEXTURE_2D); glMatrixMode(GL_MODELVIEW); glBegin(isFilled ? GL_QUADS : GL_LINE_LOOP); glVertex2i(pos1.x(), pos1.y()); glVertex2i(pos2.x(), pos1.y()); glVertex2i(pos2.x(), pos2.y()); glVertex2i(pos1.x(), pos2.y()); glEnd(); glColor4f(1.f, 1.f, 1.f, 1.f); }
Renderer::Renderer(int width, int height, bool fullscreen, double letterboxAspect) { Debug::mention("Renderer", "Initializing."); assert(width > 0); assert(height > 0); this->letterboxAspect = letterboxAspect; // Initialize window. The SDL_Surface is obtained from this window. this->window = [width, height, fullscreen]() { std::string title = "OpenTESArena"; return fullscreen ? SDL_CreateWindow(title.c_str(), SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 0, 0, SDL_WINDOW_FULLSCREEN_DESKTOP) : SDL_CreateWindow(title.c_str(), SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height, SDL_WINDOW_RESIZABLE); }(); Debug::check(this->window != nullptr, "Renderer", "SDL_CreateWindow"); // Initialize renderer context. this->renderer = this->createRenderer(); // Use window dimensions, just in case it's fullscreen and the given width and // height are ignored. Int2 windowDimensions = this->getWindowDimensions(); // Initialize native frame buffer. this->nativeTexture = this->createTexture(Renderer::DEFAULT_PIXELFORMAT, SDL_TEXTUREACCESS_TARGET, windowDimensions.getX(), windowDimensions.getY()); Debug::check(this->nativeTexture != nullptr, "Renderer", "Couldn't create native frame buffer, " + std::string(SDL_GetError())); // Initialize 320x200 frame buffer. this->originalTexture = this->createTexture(Renderer::DEFAULT_PIXELFORMAT, SDL_TEXTUREACCESS_TARGET, Renderer::ORIGINAL_WIDTH, Renderer::ORIGINAL_HEIGHT); // Don't initialize the game world buffer until the 3D renderer is initialized. this->clProgram = nullptr; this->gameWorldTexture = nullptr; this->fullGameWindow = false; // Set the original frame buffer to not use transparency by default. this->useTransparencyBlending(false); }
void AppSetup::manageRender() { if (m_isUsingVirtualSize) { Int2 virtualPos = this->getVirtualTopLeftCornerInWindow(); Float2 ppp = this->getPixelPerPoint(); Int2 sizeOrtho2DWindow = this->getSizeOrtho2DWindow(); this->setPixelPerPointLowLevel(Float2(1.f,1.f), Int2(0,0)); if (m_inf.virtualSizeBorderColor.a() != 0) { if (m_inf.virtualSize.width() < sizeOrtho2DWindow.width()) { Engine::instance().getScene2DMgr().drawRectangle( Int2(0,0), Int2(virtualPos.width(), m_inf.windowSize.height()), m_inf.virtualSizeBorderColor, true); Engine::instance().getScene2DMgr().drawRectangle( Int2(m_inf.windowSize.width()-virtualPos.width(), 0), m_inf.windowSize, m_inf.virtualSizeBorderColor, true); } else if (m_inf.virtualSize.height() < sizeOrtho2DWindow.height()) { Engine::instance().getScene2DMgr().drawRectangle( Int2(0, 0), Int2(m_inf.windowSize.width(), virtualPos.height()), m_inf.virtualSizeBorderColor, true); Engine::instance().getScene2DMgr().drawRectangle( Int2(0, m_inf.windowSize.height()-virtualPos.height()), m_inf.windowSize, m_inf.virtualSizeBorderColor, true); } } this->setPixelPerPointLowLevel(ppp, virtualPos); } #if defined(USES_WINDOWS_OPENGL) || defined(USES_LINUX) m_openGL->manageOpenGL(m_inf.windowSize); #else #endif }
void AppSetup::onResizeWindow(const Int2& newSize) { m_inf.windowSize = newSize; Float2 newSizeF = Float2((float)newSize.width(), (float)newSize.height()); Float2 virtualSizeF = Float2((float)m_inf.virtualSize.width(), (float)m_inf.virtualSize.height()); if (m_inf.automaticFitToWindowSize && (newSize.width() != m_inf.virtualSize.width() || newSize.height() != m_inf.virtualSize.height())) { Float2 ppp(-1.f,-1.f); Int2 virtualPos(-1,-1); float ratioW = (float)newSize.width() / (float)m_inf.virtualSize.width(); float ratioH = (float)newSize.height() / (float)m_inf.virtualSize.height(); if (m_inf.virtualSizeAllowRatioDeformation) { ppp = Float2(ratioW,ratioH); virtualPos = Int2(0,0); } else if (newSizeF.width()/newSizeF.height() > virtualSizeF.width() / virtualSizeF.height()) { ppp = Float2(ratioH,ratioH); virtualPos = Int2((int)((newSizeF.width()-virtualSizeF.width()*ratioH)/2.f), 0); } else { ppp = Float2(ratioW,ratioW); virtualPos = Int2(0, (int)((newSizeF.height()-virtualSizeF.height()*ratioW)/2.f)); } this->setPixelPerPointLowLevel(ppp, virtualPos); } else { this->setPixelPerPointLowLevel(Float2(1.f,1.f), Int2(0,0)); #if defined(USES_WINDOWS_OPENGL) || defined(USES_LINUX) m_openGL->setRealWindowSize(newSize); m_openGL->set2DMode(); #else // do nothing here #endif } m_isUsingVirtualSize = (this->getPixelPerPoint() != Float2(1.f, 1.f) || this->getVirtualTopLeftCornerInWindow() != Int2(0, 0)); }
bool AdvancedBox::isThereIntersectionSlow(const Int2& pointToTest) const { //cas courant if (data[0].y() == data[1].y() && data[2].y() == data[2].y() && data[1].x() == data[2].x() && data[3].x() == data[0].x() && data[0].x() > data[1].x() && data[1].y() > data[2].y()) { return pointToTest.x() < data[0].x() && pointToTest.x() > data[1].x() && pointToTest.y() < data[1].y() && pointToTest.y() > data[2].y(); } Int2 pointBox1InNewReference; Int2 pointBox2InNewReference; int j = 0; for (; j < 4; ++j) { const Int2& pointBox1 = data[j]; const Int2& pointBox2 = data[(j + 1) % 4]; //verifie si pointToTest est du bon cote de la droite (pointBox1, pointBox2) pointBox1InNewReference = pointBox1 - pointToTest; pointBox2InNewReference = pointBox2 - pointToTest; float anglePointBox1 = atan2(-(float)pointBox1InNewReference.y(), (float)pointBox1InNewReference.x()); float anglePointBox2 = atan2(-(float)pointBox2InNewReference.y(), (float)pointBox2InNewReference.x()); if (anglePointBox1 > anglePointBox2 + MathUtils::PI) { anglePointBox1 -= MathUtils::PI * 2; Assert(anglePointBox1 <= anglePointBox2 + MathUtils::PI); } else if (anglePointBox2 > anglePointBox1 + MathUtils::PI) { anglePointBox2 -= MathUtils::PI * 2; Assert(anglePointBox2 <= anglePointBox1 + MathUtils::PI); } if (anglePointBox1 <= anglePointBox2) break; } return j == 4; }
DesktopWindow::DesktopWindow(HINSTANCE hInstance, int nCmdShow, DesktopWindowMessageHandler* messageReceiver, bool isFullscreen, const Int2& windowSize, const std::string& windowTitle) :m_messageReceiver(messageReceiver), m_mustBeDestroyed(false) { // Register class WNDCLASSEX wcex; wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = WndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; wcex.hIcon = LoadIcon(hInstance, (LPCTSTR)IDI_APPLICATION); wcex.hCursor = LoadCursor(nullptr, IDC_ARROW); wcex.hbrBackground = (HBRUSH)(5 + 1); wcex.lpszMenuName = nullptr; wcex.lpszClassName = L"TutorialWindowClass"; wcex.hIconSm = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_APPLICATION); if (!RegisterClassEx(&wcex)) Assert(false); // Create window RECT rc = { 0, 0, windowSize.width(), windowSize.height() }; AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, FALSE); ; HWND hwnd = CreateWindow(L"TutorialWindowClass", Utils::convertStringToWString(windowTitle).c_str(), isFullscreen ? WS_POPUP : WS_OVERLAPPEDWINDOW, // WS_VISIBLE | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_THICKFRAME CW_USEDEFAULT, CW_USEDEFAULT, rc.right - rc.left, rc.bottom - rc.top, nullptr, nullptr, hInstance, nullptr); Assert(hwnd != nullptr); ShowWindow(hwnd, isFullscreen ? SW_MAXIMIZE : nCmdShow); // resize to take into consideration the border size /*RECT rcClient, rcWind; POINT ptDiff; GetClientRect(hwnd, &rcClient); GetWindowRect(hwnd, &rcWind); ptDiff.x = (rcWind.right - rcWind.left) - rcClient.right; ptDiff.y = (rcWind.bottom - rcWind.top) - rcClient.bottom; MoveWindow(hwnd, rcWind.left, rcWind.top, (rc.right - rc.left) + ptDiff.x, (rc.bottom - rc.top) + ptDiff.y, TRUE);*/ m_hwnd = hwnd; s_hwnds[hwnd] = this; }
Int2 Renderer::originalPointToNative(const Int2 &originalPoint) const { // From original point to letterbox point. double originalXPercent = static_cast<double>(originalPoint.getX()) / static_cast<double>(Renderer::ORIGINAL_WIDTH); double originalYPercent = static_cast<double>(originalPoint.getY()) / static_cast<double>(Renderer::ORIGINAL_HEIGHT); const auto letterbox = this->getLetterboxDimensions(); Int2 letterboxPoint( static_cast<double>(letterbox.w) * originalXPercent, static_cast<double>(letterbox.h) * originalYPercent); // Then from letterbox point to native point. Int2 nativePoint( letterboxPoint.getX() + letterbox.x, letterboxPoint.getY() + letterbox.y); return nativePoint; }
void drawTextLayout(ID2D1DeviceContext* context, const Float2& zoomRatio, ID2D1SolidColorBrush* solidBrush, IDWriteTextLayout* textLayout, const Int2& position, const Float2& scale) { D2D1_MATRIX_3X2_F transformTmp; context->GetTransform(&transformTmp); context->SetTransform(D2D1::Matrix3x2F::Translation(zoomRatio.x() + (float)position.x() / scale.x(), zoomRatio.y() + (float)position.y() / scale.y()));// * s_ppp.x() * s_ppp.y( // TODO scale with s_ppp context->DrawTextLayout(D2D1::Point2F(0.0f, 0.0f), textLayout, solidBrush); context->SetTransform(transformTmp); }
void drawLine(ID2D1DeviceContext* context, const Float2& zoomRatio, const Int2& pos1, const Int2& pos2, const Color& color, float thickness) { D2D1::ColorF colorDx(color.r() / 256.f, color.g() / 256.f, color.b() / 256.f, color.a() / 256.f); //D2D1::ColorF colorDx = D2D1::ColorF::MidnightBlue; ID2D1SolidColorBrush* solidBrush; DX::ThrowIfFailed(context->CreateSolidColorBrush(colorDx, &solidBrush)); D2D1_POINT_2F pt1; pt1.x = zoomRatio.x() + (float)pos1.x(); pt1.y = zoomRatio.y() + (float)pos1.y(); D2D1_POINT_2F pt2; pt2.x = zoomRatio.x() + (float)pos2.x(); pt2.y = zoomRatio.y() + (float)pos2.y(); context->SetTransform(D2D1::Matrix3x2F::Identity()); //s_context->SetDpi(DirectXDraw::getDefaultDpi().x(), DirectXDraw::getDefaultDpi().y()); context->DrawLine(pt1, pt2, solidBrush, thickness); solidBrush->Release(); //delete solidBrush; }
SDL_Surface *Renderer::getScreenshot() const { const Int2 dimensions = this->getWindowDimensions(); SDL_Surface *screenshot = Surface::createSurfaceWithFormat( dimensions.getX(), dimensions.getY(), Renderer::DEFAULT_BPP, Renderer::DEFAULT_PIXELFORMAT); int status = SDL_RenderReadPixels(this->renderer, nullptr, screenshot->format->format, screenshot->pixels, screenshot->pitch); if (status == 0) { Debug::mention("Renderer", "Screenshot taken."); } else { Debug::crash("Renderer", "Couldn't take screenshot, " + std::string(SDL_GetError())); } return screenshot; }
void drawRoundedRectangle(ID2D1DeviceContext* context, const Float2& zoomRatio, const Int2& posLeftTop, const Int2& posRightBottom, const Color& color, float round, float borderSize, bool fill) { D2D1::ColorF colorDx(color.r() / 256.f, color.g() / 256.f, color.b() / 256.f, color.a() / 256.f); ID2D1SolidColorBrush* solidBrush; DX::ThrowIfFailed(context->CreateSolidColorBrush(colorDx, &solidBrush)); D2D1_ROUNDED_RECT rrect; rrect.radiusX = round; rrect.radiusY = round; rrect.rect.left = zoomRatio.x() + (float)posLeftTop.x(); rrect.rect.top = zoomRatio.y() + (float)posLeftTop.y(); rrect.rect.right = zoomRatio.x() + (float)posRightBottom.x(); rrect.rect.bottom = zoomRatio.y() + (float)posRightBottom.y(); context->SetTransform(D2D1::Matrix3x2F::Identity()); if (fill) context->FillRoundedRectangle(rrect, solidBrush); //if (borderSize > 0.f) context->DrawRoundedRectangle(rrect, solidBrush, borderSize); solidBrush->Release(); //delete solidBrush; }
Int2 Renderer::nativePointToOriginal(const Int2 &nativePoint) const { // From native point to letterbox point. Int2 windowDimensions = this->getWindowDimensions(); const auto letterbox = this->getLetterboxDimensions(); Int2 letterboxPoint( nativePoint.getX() - letterbox.x, nativePoint.getY() - letterbox.y); // Then from letterbox point to original point. double letterboxXPercent = static_cast<double>(letterboxPoint.getX()) / static_cast<double>(letterbox.w); double letterboxYPercent = static_cast<double>(letterboxPoint.getY()) / static_cast<double>(letterbox.h); Int2 originalPoint( static_cast<double>(Renderer::ORIGINAL_WIDTH) * letterboxXPercent, static_cast<double>(Renderer::ORIGINAL_HEIGHT) * letterboxYPercent); return originalPoint; }
void SDLDraw::drawRectangle(const Int2& pos1, const Int2& pos2, const Color& color, bool fill) { SDL_SetRenderDrawColor(s_sdlRenderer, color.r(), color.g(), color.b(), color.a()); SDL_Rect rect; rect.x = MathUtils::minimum(pos1.x(), pos2.x()); rect.y = MathUtils::minimum(pos1.y(), pos2.y()); rect.w = abs(pos2.x()-pos1.x()); rect.h = abs(pos2.x()-pos1.x()); if (fill) SDL_RenderFillRect(s_sdlRenderer, &rect); else SDL_RenderDrawRect(s_sdlRenderer, &rect); }
void OpenGLApp_onPointerPressedOrReleased(int button, int state,int x, int y) { Int2 pos = AppSetup::instance().convertRealPositionToVirtualPosition(Int2(x,y)); if (button==GLUT_WHEEL_UP) { s_mainClass->onPointerWheelChanged(120, pos.x(), pos.y()); } else if (button==GLUT_WHEEL_DOWN) { s_mainClass->onPointerWheelChanged(-120, pos.x(), pos.y()); } else if (state==GLUT_DOWN) { Engine::instance().onPointerPressedInternals(button, x, y); s_mainClass->onPointerPressed(button, pos.x(), pos.y()); } else if (state==GLUT_UP) { Engine::instance().onPointerReleasedInternals(button, x, y); s_mainClass->onPointerReleased(button, pos.x(), pos.y()); } s_eventHappened = true; }
void MainClass::init() { Scene2D& scene2D = Engine::instance().getScene2DMgr(); Int2 winSize = scene2D.getWindowSize(); Engine::instance().startRender(); //Engine::instance().clearScreen(Color(57,155,230, 255)); Engine::instance().getScene2DMgr().drawRectangle(Int2(0,0), winSize, Color(57,155,230, 255), true);//clearScreen(Color(57,155,230, 255)); Bitmap* loading = new Bitmap("data/loading.png"); Int2 bitmapPos = winSize*0.5f - loading->size()*0.5f; loading->draw(winSize*0.5f-loading->size()*0.5f, 1.f, Float2(1.f, 1.f)); #if defined(USES_WINDOWS8_METRO) Engine::instance().getScene2DMgr().drawRectangle(bitmapPos + Int2(362, 411), bitmapPos + Int2(463, 440), CoreUtils::colorWhite, true);// hide "Esc: quit" #endif delete loading; Engine::instance().endRender(); //----- m_isHelpOpened = true; m_help = new Sprite("data/help.png"); m_help->setPosition(winSize*0.5f-m_help->getScaledSize()*0.5f); m_pressF1Help = new Sprite("data/pressf1help.png"); m_pressF1Help->setPosition(Int2(10, winSize.height()-30)); m_background = new Sprite("data/background.png"); m_background->setPosition(Int2(0,0)); m_collisionImage = new Image("data/collision.png"); m_structure = new Bitmap("data/structure.png"); m_structureForeground = new Bitmap("data/structure_foreground.png"); m_engineSystem = new EngineSystem; m_chara = new Chara(); m_cannon = new Cannon(); m_clouds.push_back(new Cloud); m_clouds.push_back(new Cloud); m_clouds.push_back(new Cloud); m_clouds.push_back(new Cloud); m_burning = new Burning; m_waterSystem = new WaterSystem; m_swarm = new Swarm; m_gameOver = new Bitmap("data/game_over.png"); #if defined(USES_WINDOWS_OPENGL) || defined(USES_LINUX) m_music = Engine::instance().getSoundMgr().loadSound("data/sounds/opengameart_cynicmusic_battleThemeA.ogg"); #else m_music = Engine::instance().getSoundMgr().loadSound("data/sounds/opengameart_cynicmusic_battleThemeA.wav"); #endif m_music->setVolume(m_musicVolume); m_music->play(); }
void SDLDraw::drawLine(const Int2& pos1, const Int2& pos2, const Color& color) { SDL_SetRenderDrawColor(s_sdlRenderer, color.r(), color.g(), color.b(), color.a()); SDL_RenderDrawLine(s_sdlRenderer, pos1.x(), pos1.y(), pos2.x(), pos2.y()); }
void drawBitmap( ID2D1DeviceContext* context, const Float2& zoomRatio, const Float2& m_defaultDpi, ID2D1Bitmap* bitmap, const Float2& position, const Float2& scale, float opacity, D2D1_RECT_F* rectSource, D2D1_RECT_F* rectDest, float angleDegree, const Int2& rotationCenterPos, bool horizontalMirror, bool verticalMirror) { D2D1_MATRIX_3X2_F transformTmp; context->GetTransform(&transformTmp); D2D1::Matrix3x2F matTranslation = D2D1::Matrix3x2F::Translation(zoomRatio.x() + position.x(), zoomRatio.y() + position.y());// / scale.x() / scale.y() if (angleDegree != 0.f || horizontalMirror || verticalMirror) { D2D1::Matrix3x2F matMirroring = D2D1::Matrix3x2F::Scale(horizontalMirror ? -1.f : 1.f, verticalMirror ? -1.f : 1.f); D2D1_POINT_2F imageRotationCenterPos = D2D1::Point2F((float)rotationCenterPos.x(), (float)rotationCenterPos.y()); D2D1::Matrix3x2F matRotation = D2D1::Matrix3x2F::Rotation(angleDegree, imageRotationCenterPos); context->SetTransform(matMirroring * matRotation * matTranslation); } else { context->SetTransform(matTranslation);// * s_ppp.x() * s_ppp.y() } //Assert(scale.x() > 0.f && scale.y() > 0.f); // note about bitmaps: https://msdn.microsoft.com/en-us/library/windows/desktop/dd371150%28v=vs.85%29.aspx Float2 dpiBitmap; bitmap->GetDpi(&dpiBitmap.data[0], &dpiBitmap.data[1]); Float2 scaleToApply = dpiBitmap / m_defaultDpi * scale;//s_ppp * dpiBitmap / dpiContext * scale; D2D1_RECT_F rectDestFinal; if (rectDest == 0) { D2D1_SIZE_F sz = bitmap->GetSize(); rectDestFinal.left = 0.f; rectDestFinal.top = 0.f; rectDestFinal.right = sz.width * scaleToApply.x(); rectDestFinal.bottom = sz.height *scaleToApply.y(); context->DrawBitmap(bitmap, &rectDestFinal, opacity, D2D1_BITMAP_INTERPOLATION_MODE_LINEAR, rectSource); } else { rectDestFinal = *rectDest; rectDestFinal.left *= scaleToApply.x(); rectDestFinal.top *= scaleToApply.y(); rectDestFinal.right *= scaleToApply.x(); rectDestFinal.bottom *= scaleToApply.y(); Float2 srcScaleToApply = dpiBitmap / m_defaultDpi; D2D1_RECT_F rectSourceFinal; rectSourceFinal = *rectSource; rectSourceFinal.left /= srcScaleToApply.x(); rectSourceFinal.top /= srcScaleToApply.y(); rectSourceFinal.right /= srcScaleToApply.x(); rectSourceFinal.bottom /= srcScaleToApply.y(); context->DrawBitmap(bitmap, &rectDestFinal, opacity, D2D1_BITMAP_INTERPOLATION_MODE_LINEAR, &rectSourceFinal); } context->SetTransform(transformTmp);//D2D1::Matrix3x2F::Translation(0.f, 0.f)); //s_context->Flush(); }
void OpenGLApp_onPointerMovingPassive(int x,int y) { Int2 pos = AppSetup::instance().convertRealPositionToVirtualPosition(Int2(x,y)); Engine::instance().onPointerMovedInternals(false, pos.x(), pos.y()); s_mainClass->onPointerMoved(false, pos.x(), pos.y()); }
static bool intersectionSegments(const Int2& ptA, const Int2& ptB, const Int2& ptC, const Int2& ptD) { Float2 ptS; if (ptA.x() == ptB.x()) { if (ptC.x() == ptD.x()) return false; else { float pCD = (float)(ptC.y() - ptD.y()) / (float)(ptC.x() - ptD.x()); ptS.data[0] = (float)ptA.x(); ptS.data[1] = pCD*(float)(ptA.x() - ptC.x()) + (float)ptC.y(); } } else { if (ptC.x() == ptD.x()) { float pAB = (float)(ptA.y() - ptB.y()) / (float)(ptA.x() - ptB.x()); ptS.data[0] = (float)ptC.x(); ptS.data[1] = pAB*(float)(ptC.x() - ptA.x()) + (float)ptA.y(); } else { float pCD = (float)(ptC.y() - ptD.y()) / (float)(ptC.x() - ptD.x()); float pAB = (float)(ptA.y() - ptB.y()) / (float)(ptA.x() - ptB.x()); float oCD = (float)ptC.y() - pCD*(float)ptC.x(); float oAB = (float)ptA.y() - pAB*(float)ptA.x(); ptS.data[0] = (oAB - oCD) / (pCD - pAB); ptS.data[1] = pCD*ptS.data[0] + oCD; } } Int2 ptSInt; ptSInt.data[0] = (int)ptS.data[0];//roundNumber(ptS.data[0]); ptSInt.data[1] = (int)ptS.data[1];//roundNumber(ptS.data[1]); if ((ptSInt.x() < ptA.x() && ptSInt.x() < ptB.x()) || (ptSInt.x() > ptA.x() && ptSInt.x() > ptB.x()) || (ptSInt.x() < ptC.x() && ptSInt.x() < ptD.x()) || (ptSInt.x() > ptC.x() && ptSInt.x() > ptD.x()) || (ptSInt.y() < ptA.y() && ptSInt.y() < ptB.y()) || (ptSInt.y() > ptA.y() && ptSInt.y() > ptB.y()) || (ptSInt.y() < ptC.y() && ptSInt.y() < ptD.y()) || (ptSInt.y() > ptC.y() && ptSInt.y() > ptD.y())) { return false; } return true; }
GameWorldPanel::GameWorldPanel(GameState *gameState) : Panel(gameState) { assert(gameState->gameDataIsActive()); this->playerNameTextBox = [gameState]() { int x = 17; int y = 154; Color color(215, 121, 8); std::string text = gameState->getGameData()->getPlayer().getFirstName(); auto &font = gameState->getFontManager().getFont(FontName::Char); auto alignment = TextAlignment::Left; return std::unique_ptr<TextBox>(new TextBox( x, y, color, text, font, alignment, gameState->getRenderer())); }(); this->automapButton = []() { auto function = [](GameState *gameState) { std::unique_ptr<Panel> automapPanel(new AutomapPanel(gameState)); gameState->setPanel(std::move(automapPanel)); }; return std::unique_ptr<Button>(new Button(function)); }(); this->characterSheetButton = []() { auto function = [](GameState *gameState) { std::unique_ptr<Panel> sheetPanel(new CharacterPanel(gameState)); gameState->setPanel(std::move(sheetPanel)); }; return std::unique_ptr<Button>(new Button(function)); }(); this->logbookButton = []() { auto function = [](GameState *gameState) { std::unique_ptr<Panel> logbookPanel(new LogbookPanel(gameState)); gameState->setPanel(std::move(logbookPanel)); }; return std::unique_ptr<Button>(new Button(function)); }(); this->pauseButton = []() { auto function = [](GameState *gameState) { std::unique_ptr<Panel> pausePanel(new PauseMenuPanel(gameState)); gameState->setPanel(std::move(pausePanel)); }; return std::unique_ptr<Button>(new Button(function)); }(); this->worldMapButton = []() { auto function = [](GameState *gameState) { std::unique_ptr<Panel> mapPanel(new WorldMapPanel(gameState)); gameState->setPanel(std::move(mapPanel)); }; return std::unique_ptr<Button>(new Button(function)); }(); // Set all of the cursor regions relative to the current window. const Int2 screenDims = gameState->getRenderer().getWindowDimensions(); this->updateCursorRegions(screenDims.getX(), screenDims.getY()); }
void GameWorldPanel::render(Renderer &renderer) { assert(this->getGameState()->gameDataIsActive()); // Clear full screen. renderer.clearNative(); renderer.clearOriginal(); // Draw game world onto the native frame buffer. The game world buffer // might not completely fill up the native buffer (bottom corners), so // clearing the native buffer beforehand is still necessary. renderer.renderWorld(); // Set screen palette. auto &textureManager = this->getGameState()->getTextureManager(); textureManager.setPalette(PaletteFile::fromName(PaletteName::Default)); // Set original frame buffer blending to true. renderer.useTransparencyBlending(true); // Draw game world interface. const auto &gameInterface = textureManager.getTexture( TextureFile::fromName(TextureName::GameWorldInterface)); renderer.drawToOriginal(gameInterface.get(), 0, Renderer::ORIGINAL_HEIGHT - gameInterface.getHeight()); // Draw player portrait. const auto &player = this->getGameState()->getGameData()->getPlayer(); const auto &headsFilename = PortraitFile::getHeads( player.getGenderName(), player.getRaceName(), true); const auto &portrait = textureManager.getTextures(headsFilename) .at(player.getPortraitID()); const auto &status = textureManager.getTextures( TextureFile::fromName(TextureName::StatusGradients)).at(0); renderer.drawToOriginal(status.get(), 14, 166); renderer.drawToOriginal(portrait.get(), 14, 166); // Draw compass slider (the actual headings). +X is north, +Z is east. // Should do some sin() and cos() functions to get the pixel offset. auto *compassSlider = textureManager.getSurface( TextureFile::fromName(TextureName::CompassSlider)); Texture compassSliderSegment = [&renderer, &compassSlider]() { SDL_Surface *segmentTemp = Surface::createSurfaceWithFormat(32, 7, Renderer::DEFAULT_BPP, Renderer::DEFAULT_PIXELFORMAT); SDL_Rect clipRect; clipRect.x = 60; // Arbitrary offset until compass rotation works. clipRect.y = 0; clipRect.w = segmentTemp->w; clipRect.h = segmentTemp->h; SDL_BlitSurface(compassSlider, &clipRect, segmentTemp, nullptr); SDL_Texture *segment = renderer.createTextureFromSurface(segmentTemp); SDL_FreeSurface(segmentTemp); return Texture(segment); }(); renderer.drawToOriginal(compassSliderSegment.get(), (Renderer::ORIGINAL_WIDTH / 2) - (compassSliderSegment.getWidth() / 2), compassSliderSegment.getHeight()); // Draw compass frame over the headings. const auto &compassFrame = textureManager.getTexture( TextureFile::fromName(TextureName::CompassFrame)); renderer.drawToOriginal(compassFrame.get(), (Renderer::ORIGINAL_WIDTH / 2) - (compassFrame.getWidth() / 2), 0); // If the player's class can't use magic, show the darkened spell icon. if (!player.getCharacterClass().canCastMagic()) { const auto &nonMagicIcon = textureManager.getTexture( TextureFile::fromName(TextureName::NoSpell)); renderer.drawToOriginal(nonMagicIcon.get(), 91, 177); } // Draw text: player name. renderer.drawToOriginal(this->playerNameTextBox->getTexture(), this->playerNameTextBox->getX(), this->playerNameTextBox->getY()); // Scale the original frame buffer onto the native one. // This shouldn't be done for the game world interface because it needs to // clamp to the screen edges, not the letterbox edges. // Fix this eventually... again. renderer.drawOriginalToNative(); // Draw cursor, depending on its position on the screen. const Int2 mousePosition = this->getMousePosition(); const Texture &cursor = [this, &mousePosition, &textureManager]() -> const Texture& // Interesting how this return type isn't deduced in MSVC. { // See which arrow cursor region the native mouse is in. for (int i = 0; i < this->nativeCursorRegions.size(); ++i) { if (this->nativeCursorRegions.at(i)->contains(mousePosition)) { return textureManager.getTextures( TextureFile::fromName(TextureName::ArrowCursors)).at(i); } } // If not in any of the arrow regions, use the default sword cursor. return textureManager.getTexture( TextureFile::fromName(TextureName::SwordCursor)); }(); renderer.drawToNative(cursor.get(), mousePosition.getX(), mousePosition.getY(), static_cast<int>(cursor.getWidth() * this->getCursorScale()), static_cast<int>(cursor.getHeight() * this->getCursorScale())); // Set the transparency blending back to normal (off). renderer.useTransparencyBlending(false); }
void GameWorldPanel::handleMouse(double dt) { static_cast<void>(dt); const auto &renderer = this->getGameState()->getRenderer(); const uint32_t mouse = SDL_GetRelativeMouseState(nullptr, nullptr); const bool leftClick = (mouse & SDL_BUTTON(SDL_BUTTON_LEFT)) != 0; if (leftClick) { // Horizontal camera movement rough draft. The original camera controls for // Arena are bad, but I am simulating them before thinking of adding modern // 3D camera support (like Daggerfall) as an option. const Int2 screenDimensions = renderer.getWindowDimensions(); const Int2 mousePosition = this->getMousePosition(); // Strength of turning is determined by proximity of the mouse cursor to // the left or right screen edge. const double dx = [this, &mousePosition, &screenDimensions]() { const int mouseX = mousePosition.getX(); // Native cursor regions (scaled to the current window). const Rect &middleLeft = *this->nativeCursorRegions.at(3).get(); const Rect &middleRight = *this->nativeCursorRegions.at(5).get(); // Measure the magnitude of rotation. -1.0 is left, 1.0 is right. double percent = 0.0; if (middleLeft.contains(mousePosition)) { percent = -1.0 + (static_cast<double>(mouseX) / middleLeft.getWidth()); } else if (middleRight.contains(mousePosition)) { percent = static_cast<double>(mouseX - middleRight.getLeft()) / middleRight.getWidth(); } // Reduce the magnitude by a lot as a baseline. Sensitivity can be // tweaked in the options. percent *= 0.010; // No NaNs or infinities allowed. return std::isfinite(percent) ? percent : 0.0; }(); auto &player = this->getGameState()->getGameData()->getPlayer(); const auto &options = this->getGameState()->getOptions(); // Yaw the camera left or right. No vertical movement in classic camera mode. player.rotate(dx, 0.0, options.getHorizontalSensitivity(), options.getVerticalSensitivity(), options.getVerticalFOV()); } // Later in development, a 3D camera would be fun (more like Daggerfall), but // for now the objective is to more closely resemble the original game, so the // rough draft 3D camera code below is commented out as a result. // Make the camera look around. /*int dx, dy; const auto mouse = SDL_GetRelativeMouseState(&dx, &dy); bool leftClick = (mouse & SDL_BUTTON(SDL_BUTTON_LEFT)) != 0; bool rightClick = (mouse & SDL_BUTTON(SDL_BUTTON_RIGHT)) != 0; bool turning = ((dx != 0) || (dy != 0)) && leftClick; if (turning) { auto dimensions = this->getGameState()->getRenderer().getWindowDimensions(); double dxx = static_cast<double>(dx) / static_cast<double>(dimensions.getX()); double dyy = static_cast<double>(dy) / static_cast<double>(dimensions.getY()); // Pitch and/or yaw the camera. const auto &options = this->getGameState()->getOptions(); this->getGameState()->getGameData()->getPlayer().rotate(dxx, -dyy, options.getHorizontalSensitivity(), options.getVerticalSensitivity(), options.getVerticalFOV()); }*/ }
void AdvancedBox::calculate(const Int2& parPos, const Int2& parSize, const Int2& parHotSpot, float angleDegrees, int xTopDeformation, int xBottomDeformation) { float angleRadians = angleDegrees * MathUtils::PI / 180.0f; data[0] = getRotatedPoint( parPos.x() + parSize.width() - parHotSpot.x(), parPos.y() + parSize.height() - parHotSpot.y(), angleRadians, parPos.x()/*-1*/, parPos.y(), xBottomDeformation); data[1] = getRotatedPoint( parPos.x() - parHotSpot.x(), parPos.y() + parSize.height() - parHotSpot.y(), angleRadians, parPos.x(), parPos.y(), xBottomDeformation); data[2] = getRotatedPoint( parPos.x() - parHotSpot.x(), parPos.y() - parHotSpot.y(), angleRadians, parPos.x(), parPos.y(), xTopDeformation); data[3] = getRotatedPoint( parPos.x() + parSize.width() - parHotSpot.x(), parPos.y() - parHotSpot.y(), angleRadians, parPos.x()/*-1*/, parPos.y(), xTopDeformation); /*PrintValue(data[0]); PrintValue(data[1]); PrintValue(data[2]); PrintValue(data[3]); Print("");*/ }