Jump to content
  • Advertisement


  • Content Count

  • Joined

  • Last visited

Community Reputation

1568 Excellent

About Sunsharior

  • Rank

Personal Information

  • Interests
  1. I solved this error. Here is the solution. When creating the buffer, create it with the current renderscale. In my case, my render scale was 2. buffer = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_TARGET, screenwidth * renderScaleX, screenheight * renderScaleY); Then when switching buffer, Reset the render scale. You will need to do this every frame. SDL_SetRenderTarget(renderer, buffer ); SDL_RenderSetScale(renderer, renderScaleX, renderScaleY); The reason for this is that, in my case, everytime i switched buffer, the RenderScale got changed to some weird value like 1.024. This is what resulted in the scaled down sprite being rendered all blurry. I hope this will help people who google stuff in the futur. Oh and by the way, this fix both solve my bleeding pixel issue and the blurry issue.
  2. Hello everyone. I am working on a project using SDL2 and so far its been pretty straightforward. However, I’ve come to a problem i cannot solve, so I’ve come here for your opinion. You see, i had a problem with “bleeding pixel” a while back, and i successfully resolved it by using SDL_RenderSetIntegerScale. While this worked, it had the drawback that i could not make my SDL2 project full screen without having letterbox, both vertically and horizontally. I was content for a while, but now i would like to actually be able to go full screen without the letterboxing. I’ve read that i can use a backbuffer, change my render target with SDL_SetRenderTarget, renderCopy to the back buffer then switch and renderpresent. It work flawlessly for solving the bleeding pixel issue and removing the letterboxing. Obviousbly, my sprite are rendered stretched, but this is not the issue at hand. MY current issue is that i noticed all the sprite i render scalling down look very blurry. With back buffer https://imgur.com/8jglxNZ 1 Without back buffer https://imgur.com/bAW4Xf2 1 As you can see, my font is rendered extremely blurry with the back buffer. No other sprites are rendered blurry unless it is scaled down. I’ve tried for the last three days to fix the issue, but alas, i’ve failed and now i’m turning to you. If someone have experience with this problem, i’ll be more than happy to listen. More information: I do use SDL_RenderSetLogicalSize, SDL_RenderSetScale, which is twice my logical size, SDL_RenderSetIntegerScale (false when using back buffer, true otherwise) I use SDL_RenderCopyEx for my rendering SDL_RenderPresent for my rendering For reference, this was the bleeding pxiel issue here https://imgur.com/KkWtfoC Thank you for your time.
  3. I would sacrifice a lot more things (i've already sacrificed so much), but i wouldn't sacrifice my happiness.
  4. Sunsharior

    2D Polygon Collision Detection

    The question is vague, but i'll try to answer anyway. Not too long ago, i've been at the same place where you are at the moment. The biggest problem i had was trying to assimilate everything at once.   Start with small bites.   1. First, design a simple Polygon class. Just try to make it work, and focus on that. 2. Once it's working, try to implement your own  SAT algorithm that work with your own polygon class. You'll need to understand how SAT work. 3. Once that is working, modify your sat algorythm to include the MTV.   Now i realize this might not help you, so here is my own SAT function you can read and try to understand (or even use if you want, but a mention would be nice, just don't claim it as your own). The code is well documented, should you have more question, i'll be happy to answer.   The Sat Function [spoiler] ////////////////////////////////////////////////////////////////////////// // Try to find if an Axis can disprove collision. bool CMath::Sat(CPolygon *_a, CPolygon *_b, Collision &_col) const { //A slope can be 6 pixel off and still be considered the best resolving vector. //this fix the polygon being wrongly accused of being a square when they are an exotic shape. const unsigned short slopebias = VERTICAL_TOUCH_DISTANCE; float overlap = 1000; // Large value. CVector smallestMTV(0,0); //MTV (Minimum translation vector). This is the resolving vector. //For polygon A... for (int i = 0; i < _a->n; i++) { // Get the direction vector CVector axis = _a->edges[i].dir; // Get the normal of the vector (90 degrees) axis = Perp(axis); bool slope = axis.x != 0 && axis.y != 0; // Find the projection of a and b onto axis CVector p1 = Project(_a,axis), p2 = Project(_b,axis); // If they do not overlap, then no collision float o = 1000; if (!Overlap(p1,p2, o)) return false; //Update the MTV else { //If the mtv is the smallest OR if the Axis is a slope, update it. //The slope part will fix the bug when the actor get stuck in slope's corners. if(o < overlap || (o < overlap + slopebias && slope) ) { if(o < overlap) overlap = o; smallestMTV = axis; } } } // repeat for b for (int i = 0; i < _b->n; i++) { CVector axis = _b->edges[i].dir; axis = Perp(axis); bool slope = axis.x != 0 && axis.y != 0; CVector p1 = Project(_a,axis), p2 = Project(_b,axis); float o = 1000; if (!Overlap(p1,p2, o)) return false; else { if(o == 0) return true; if(o < overlap || (o < overlap + slopebias && slope) ) { if(o < overlap) overlap = o; smallestMTV = axis; } } } //No Axis can prove the Polygon is not colliding, so it must be colliding. //Calculate the slope (if it's infinite, just put zero.) _col.slope = GetSlope(smallestMTV.x, smallestMTV.y); //normalize (to put things into pixel) smallestMTV = Normalize(smallestMTV); //Calculate the MTV; // If the slope is positive, take ceiling value, else take floor value. (FOR X ONLY) _col.mtv.x = _col.slope >= 0 ? -ceil(smallestMTV.x * overlap) : -floor(smallestMTV.x * overlap); //y is alway the ceil value. _col.mtv.y = -ceil(smallestMTV.y * overlap); return true; } ////////////////////////////////////////////////////////////////////////// // Perpendicular vector. CVector CMath::Perp(CVector _p) const {     CVector p(-_p.y, _p.x);     return p; } ////////////////////////////////////////////////////////////////////////// // bool CMath::Overlap(CVector _p1, CVector _p2, float &_overlap) const {     if (Contains(_p1,_p2, _overlap) )         return true;     return false; } ////////////////////////////////////////////////////////////////////////// // Projection bool CMath::Contains(CVector _range1, CVector _range2, float &_overlap) const {     _overlap = FastAbs(_range1.y - _range2.x);     return (_range1.y >= _range2.x && _range1.x <= _range2.y); } ////////////////////////////////////////////////////////////////////////// // CVector CMath::Project(CPolygon *_a, CVector _axis) const {     _axis = Normalize(_axis);     // min and max are the start and finish points     float min = Dot(_a->vertices[0], _axis);     float max = min;     for (int i = 0; i < _a->n; i++)     {         // find the projection of every point on the polygon onto the line.         float proj = Dot(_a->vertices[i], _axis);                  if (proj < min)             min = proj;         if (proj > max)             max = proj;     }     CVector arr (min, max); // To fix a warning.     return arr; } ////////////////////////////////////////////////////////////////////////// //Dot product float CMath::Dot(CVector _a, CVector _b) const {     return (_a.x * _b.x + _a.y * _b.y); } ////////////////////////////////////////////////////////////////////////// //Make the vector lenght = 1 CVector CMath::Normalize(CVector _p) const {     float l = SquareRoot(_p.x * _p.x + _p.y * _p.y);     // vector b is only of distance 1 from the origin     CVector b (_p.x / l, _p.y / l);     return b; } ////////////////////////////////////////////////////////////////////////// // float CMath::GetSlope(const CSegment &_s) const {     return GetSlope( (_s.second.y - _s.first.y), (_s.second.x - _s.first.x) ); } ////////////////////////////////////////////////////////////////////////// // Overload float CMath::GetSlope(const float &_risex, const float &_risey) const {     if(_risex != 0)         return _risey / _risex;     return 0; } [/spoiler]     The Collision structure, including the MTV.   [spoiler] //The result of a collision. //Mtv is the minimum translation vector. //slope is the slope of the touched segment. //Usefull for calculating if the actor slide off it if it's too steep. struct Collision { //default ctor Collision() : mtv(CVector(0,0) ), slope(0) {;} Collision(CVector _mtv, float _slope) : mtv(_mtv), slope(_slope) {;} CVector mtv; float slope; }; [/spoiler]   The Polygon struct. [spoiler] //A polygon is N Vector and N segment struct CPolygon { // Only pass clockwise set of vertices. CPolygon(std::vector _vectices) {Edit(_vectices);} //Edit the polygon void Edit(std::vector _vertices) { vertices.clear(); edges.clear(); n = _vertices.size(); if(n >= MIN_VALID_VERTICES) { for (size_t i = 0; i < _vertices.size() - 1; i++) { vertices.push_back(_vertices[i] ); edges.push_back(CSegment(_vertices[i], _vertices[i+1] ) ); } vertices.push_back(_vertices[n - 1] ); edges.push_back( CSegment(_vertices[n - 1], _vertices[0] ) ); } } int n; std::vector vertices; std::vector edges; }; [/spoiler]   The Segment struct   [spoiler] //A Segment is 2 vector and a direction. struct CSegment { CSegment() : first(CVector(0.0f, 0.0f)), second(CVector(0.0f, 0.0f)), dir( CVector(second.x - first.x, second.y - first.y) ) {;} CSegment(CVector _a, CVector _b) : first(_a), second(_b), dir( CVector(second.x - first.x, second.y - first.y) ) {;} void Clear() {first = CVector(0.0f, 0.0f); second = CVector(0.0f, 0.0f); dir = CVector(second.x - first.x, second.y - first.y);} CVector first, second, dir; }; [/spoiler]   The Vector struct [spoiler] //A vector is a X and a Y; struct CVector { CVector() : x(0), y(0) {;} CVector(float _x, float _y) : x(_x), y(_y){;} friend bool operator==(const CVector &_lhs, const CVector &_rhs){ return (_lhs.x == _rhs.x && _lhs.y == _rhs.y);} friend bool operator!=(const CVector &_lhs, const CVector &_rhs){ return !operator==(_lhs, _rhs);} CVector operator*(const float _rhs){ return CVector (x * _rhs, y * _rhs);} CVector operator+(const CVector &_rhs){ return CVector (x + _rhs.x, y + _rhs.y);} CVector operator-(const CVector &_rhs){ return CVector (x - _rhs.x, y - _rhs.y);} CVector& operator*=(const CVector &_rhs){x *= _rhs.x; y *= _rhs.y; return *this;} CVector& operator/=(const CVector &_rhs){x /= _rhs.x; y /= _rhs.y; return *this;} void Negate() {x = -x; y = -y;} double Dot(CVector _v2) { return x * _v2.x + y * _v2.y;} float x, y; }; [/spoiler]   Edit: I highly recommend this book. It explain everything you'll ever want to know about collisions.
  5. Sunsharior

    Creating menus using Codeblocks (C++)

    Also, each Menus can be a state inside the engine you are using, making a simple interface with Update, Draw and Clear or what ever fit your need. Consider using one state per menu, unless your design do not need it.   Just plug the current state inside the main game loop and change it when you need it.   We'll be happy to answers more question.
  6. I finally figured out the algorithm i needed. Here is my solution, in case some one need it (in C++).   Please note that my solution will scan along the X axis all the way to the end before going to the next row. This is exactly how my game need it, but i feel the need to mention it. The algorithm is not optimized. In my case, it did not need to be optimized. ////////////////////////////////////////////////////////////////////////// // Calculate the rectangles that can exist in a grid. std::vector<SDL_Rect> MapManager::CalculateVoidZones() {     std::vector<SDL_Point> corners;     std::vector<SDL_Point> sizes;     // Retrieve the maximum col and row. note that the col and row are already shrinked by 1.     SDL_Point max = {mInfo->GetCol(), mInfo->GetRow()};     // scan a col. Start from top left.     for(int row = 0; row <= max.y; row++)     {         // remember the current width for consecutive void state.         const short INVALID = -1;         SDL_Point lastcorner = {INVALID, INVALID}; // invalid corner.         int width = 0;         // scan a col. go right.         for(int col = 0; col <= max.x; col++)         {             bool lastcol = (col == mInfo->GetCol() && width > 0);             bool addnewcorner = false, nonvoid = true;             // if the cell is a void.             if(GetTile(row, col)->IsState(STATE_TILE_VOID))             {                 nonvoid = false;                 if(lastcorner.x == INVALID && lastcorner.y == INVALID)                 {                     lastcorner.x = col;                     lastcorner.y = row;                 }                                  bool addwidth = lastcorner.x == (col - width);                 if (addwidth)                     width++;                 if(!addwidth || lastcol)                     addnewcorner = true;             }             if(addnewcorner || (nonvoid && width))             {                 bool fit = false; // do the rectangle fit into a previous one?                 // loop through all existing corners                 for(unsigned int i = 0; i < corners.size(); i++)                 {                     if(corners[i].x == lastcorner.x &&                         corners[i].y == (lastcorner.y - sizes[i].y) &&                         width == sizes[i].x)                     {                         // increase the height                         sizes[i].y++;                         fit = true;                     }                 }                 if(!fit)                 {                     corners.push_back(lastcorner);                     SDL_Point size = SDL_Point();                     size.x = width;                     size.y = 1;                     sizes.push_back(size);                 }                 // reset                 lastcorner.x = INVALID;                 lastcorner.y = INVALID;                 width = 0;             }           }     }     // finally, create the rects     std::vector<SDL_Rect> voidzones;     if(corners.size() && corners.size() == sizes.size())     {         for(int i = corners.size(); i--;)         {             SDL_Point corner = corners[i];             SDL_Point size = sizes[i];                          // mTw and mTh is the width and height of a tile, respectively.             SDL_Rect rect = {corner.x * mTw,                              corner.y * mTh,                              size.x * mTw,                              size.y * mTh};             rects.push_back(rect);         }     } return voidzones;     } Have a good day.
  7. I've googled your answer, but what i found didn't seems related to my problem. I'll google more for the moment.
  8. Only the rectangles are interesting me.   This means a "star" shape composed of one 3x3 square and 1 filled cell on each side on the middle will be counted as 5 different rectangles. (the 3x3, and 4 1x1s).   0001000 0011100 0111110 0011100 0001000
  9. Hi. I'm currently trying to find a solution to a grid filling problem. Unfortunately, i'm having trouble imagining the implementation.   I will explain. In a 2D grid, a cell can be filled or not. I need to retrieve the total number of contiguous rectangles that can be formed by the filled regions. I'm fairly sure what i'm looking after have a name, but it's hard to google it without the proper name. I have attached an image of what i mean at the end of this post.   Currently, i have a double for loop for each rows and each columns. I remember the amount of "widths" of consecutive filled cell of the last row and if the current row have the same "widths" at the same place, i add one to that width height. But this is where i'm stuck, i can't find the rest of the logic. // This function will calculate the number of void zone and store it in mVoidZones void MapManager::CalculateVoidZones() { // array of rectangle (X, Y, W, H). mVoidZones.clear(); std::vector<SDL_Point> lastcorners; std::vector<int> widths; std::vector<int> heights; // scan a col. for(int col = 0; col < mInfo->GetCol(); col++) { // remember the current width a consecutive void state. int width = 0; SDL_Point lastcorner = SDL_Point(); lastcorner.x = -1; lastcorner.y = -1; // scan a row. for(int row = 0; row < mInfo->GetRow(); row++) { // fetch if the cell is "filled" if(GetTile(row, col)->IsState(STATE_TILE_VOID)) { // add a corner if(lastcorner.x == -1 && lastcorner.y == -1) { lastcorner.x = col; lastcorner.y = row; width = 1; } // increment the current width else if (lastcorner.x == col - 1) width++; } // a gap is found. Close the current width. else if(width > 0) { lastcorners.push_back(lastcorner); widths.push_back(width); lastcorner.x = -1; lastcorner.y = -1; width = 0; } } } // TODO this function is incomplete. // It is missing the "corner" comparison, then adding the height // then creating the rectangle and pushing it to mVoidZones. } Take note that the grid can be massively scrambled or even checkered, creating a huge number of small rectangles.   As always, thank you for your time. I will continue searching in the meantime.
  10. Sunsharior

    Code Management in a Project

    I'll add my advices as well. Code writting : Write small and focused function. The smaller and simpler, the better. Write Self documenting code. Your code must be so simple, just reading throught it explain what it does. The fonction name and it's parameters should explain near 100% of what it'll do. Exemple : If i look at "void Math::SortArray(std::array<T> &_array, bool _ascending) const;" i know that it return nothing, that the parameter _array will be modified by the function, that i can sort ascending or not with the second parameter and that the function will not motify the class "Math", as it is const. Comment anything that could be misinterpreted or cannot be made simple. If you have a programming style, stick to it. Never deviate. Everyone in your team must be up to date with the programming style and must follow it. Never use magic numbers. Use enumerators, or const in c/c++ and final in java. Never duplicate large chunk of code. Example: if you have a function that sort integer and another that sort double, rewrite it as a template. If you are programming with objects, encapsulate everything that can be encapsulated. Every class function must be private, unless it need to be public. Learn the most usefull programming patterns*. *Try to avoid the singleton programming patterns. Sometime, take the time to return to something that you finished and think about if it could be written simpler. Do a little optimization and refactoring here and there during developpement. Don't forget to retest what you change. if you are using a language that use header, try as hard as you can to maintain a clean and well sorted header (with comment). Group all draws function, group all getter, all setters, etc... This fall into your programming style or choice. Remove anything that become obsolete or unused. Don't worry about losing anything, you have a source control. The worst thing you could do is commenting whole functions. Its making scrolling through the code unnecessary obfuscated. Don't over-complicate anything. A lot of thing can be made simple just by taking the time to think it through. If you are writing something new, make sure it don't already exist first. Nobody wants three functionally identical functions that return the bounding box or an actor, written by 3 different guys / gals. This wikipedia page list a lot of things that can overcomplicate code and make it harder to manage. Print it and pin it on the dashboard where you work.   Code documentation :   Use a version control, git, mercurial, etc... and a version control software like svn or SourceTree. Always commit something with zero errors, zero warnings. Try to maintain the documentation up to date with the code. Atlassian have a wide variety of tools for a small team, without paying too much (Confluence for documentation, Jira for bugs, Hipchat for chat, Bamboo for building new versions. Bitbucket for source control). I highly recommend it.
  11. The observer design pattern is a good idea for decoupled achievements. Here is a link to an article describing it: http://gameprogrammingpatterns.com/observer.html
  12. Sunsharior

    please help with SDL

    You are missing the methods "clean" and "update" from the file SDLGameObject.cpp
  13. If you prefer to do thing yourself, i have something for you that you might like. I'll just explain how i did something similar in my game. With more than 250 weapons sprites, it was out of the question to actually draw each sprite. So what i did was creating my own tool to manage the sprite animations and hitboxes. After that, i added "anchors" to each frame of animation to set where the weapon goes. Good thing is, i can even set anchor point for the weapon when it's sheathed. You need two anchors, one to set where it goes and another to set the angle. So basically, i'm not using a complexe bone system but only anchor points to tell my game "that weapon goes there" at that frame. Obviously, this method was very time consuming, but it give you an alternative to Spine.
  14. Sunsharior

    Rotating a sprite in SDL2?

    With this simple snipet, you will be able to draw a sprite. // for this to work, i will assume you already have a SDL_Renderer and a SDL_Window. SDL_Texture *texture = IMG_LoadTexture(renderer, "image.png"); // if the texture was loaded. if(texture) { SDL_Rect rect = {0, 0, 32, 32}; // the rect is where you wants the texture to be drawn (screen coordinate). SDL_Rect crop = {0, 0, 16, 16}; // the crop is what part of the image we want to display. float angle = 180.0f; // set the angle. SDL_Point center = {8, 8}; // the center where the texture will be rotated. SDL_RendererFlip flip = SDL_FLIP_NONE; // the flip of the texture. // now, try to draw something int result = SDL_RenderCopyEx(renderer, texture, &crop , &rect, angle, &center, flip); if(result!= 0) std::cout << SDL_GetError() << std::endl; } else std::cout << Error << "Couldn't render texture." << std::endl; Using this example, you will draw an image rotated 180 degree. It will be drawn at 0,0 with a width of 32 and a height of 32. The crop is 16x16 and the rotation is 180 that is centered at 8,8.   I hope this help. If you have errors, feel free to post it.
  15. Sunsharior

    Text Based RPG help

    Like Josh Petrie said, you declared functions in a header file that were never defined elsewhere. I have enclosed 3 of your project's file code with the error fixed.   You will noticed a few things:   1. I have created the Prologue.cpp file and moved the content from Char info.cpp to it. 2. The prologue is now used as a class instead of static. See the modification i did to Main.cpp to notice it's scope remain inaffected. 3. The fonctions and member variables of the class Prologue are no longer static. Prologue.cpp now have the proper definition of thoses fonctions, and a constructor aswell. 4. The file Char info.cpp has been deleted.
  • Advertisement

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!