a good OO way to do this (c++) - c++

i need some advice. i have 2 classes for a game that i am making, and those classes are:
Graphics
Sprite
the sprite class consists of an image buffer for the image, an (x, y) offset, and a width and a height. the graphics class has a buffer for the screen. the screen buffer can have things blitted to it like the image buffer for the sprite.
are there any recommended ways of blitting the sprite's image buffer to the graphics screen buffer? i had 2 ideas:
have a method like this (in the sprite class):
void Sprite::blit(SDL_Surface* screen)
{
// code goes here
}
or this (in the graphics class):
void Graphics::blit(Sprite sprite)
{
// code
}
or even this (also in the graphics class):
void Graphics::blit(SDL_Surface* aSpritesImageBuffer)
{
// code
}
there are problems with all of these tho. in both classes, i use encapsulation to hide both the sprite's image buffer and the graphics component's screen buffer. they are returned as a constant so no one can manipulate them without using the functions provided in the class. this is how i did it:
class Graphics
{
public:
const getScreenBuffer() const {return screenBuffer;}
private:
screenBuffer;
};
^ same with the sprite's image buffer.
so if i tried (in my main class)
void handleRendering()
{
graphics.blit(sprite.getImageBuffer());
}
that would not be very good?
or even:
void handleRendering()
{
graphics.blit(sprite);
}
and i don't think this is good:
void handleRendering()
{
sprite.blit(graphics.getScreenBuffer());
}
are there any better methods of doing this without getting errors like const to non-const? << i get an error like that.

I don't know if your sprite class is only a low-level rendering element (so, basically only a wrapper around SDL_Surface*), or if it's already the actual representation of a creature in your game. In the latter case, as an alternative to your different solutions, you could only keep an id of the bitmap in the sprite class, among other properties like coordinates, size, speed... And the actual code dependent of the rendering technology in a separate set of classes, like "Graphics", "BitmapCollection"...
So on one side, you would have a "clean" sprite class with simple properties like position, size, speed... and on the other side, the "dirty stuff", with low level SDL_nnn objects and calls. And one day, that id would not represent a bitmap, but for example a 3D model.
That would give something like that:
void handleRendering()
{
graphics.blit( bitmapCollection.Get( sprite.getImageId());
}
I don't know if the image of a sprite really has to be private or read only. Several sprites could share the same image, other classes like "SpecialEffects" could modify the sprite bitmaps, swap them, make semi-transparent following ghosts on screen and so on.

A common way to do this would be to have a container in your Graphics object that holds all of the sprites in the scene. Your main loop would call Graphics::blit(), and the Graphics object would iterate through the container of sprites and call the Sprite::blit(SDL_Surface* screen) function on each one passing in its screen buffer.

Related

Scrolling in SDL2, ie, changing integral coordinates of the giu's layout

I'm trying to simulate 'scrolling' in an application in SDL2, however i dont think that moving each individual object on the screen every time the scroll event occurs is an efficient/elegant way of doing it. What i know of SDL2 is the top left begins at 0,0 in coordinates. For me to make this much easier to implement, is it possible to change the top left starting point of the GUI so that, when i scroll, it moves to say, 0,100 and next scroll, 0,200 etc. How could I do this? Thanks
Rather than changing the x,y position of the object itself, or changing the reference co-ordinate of SDL (which cannot be done), you can instead create offset variables.
For example, create an SDL_Point called ViewPointOffset:
SDL_Point ViewPointOffset;
The best practice is to put this in your window class (if you have one), or even better, a Camera class that is a member of the window class.
Then, when you're drawing, just subtract the offset from the x and y co-ordinates that you're drawing:
void draw(SDL_Renderer* renderer, const SDL_Point ViewPointOffset, SDL_Texture* tex, const SDL_Rect* srcrect, const SDL_Rect* dstrect){
SDL_Rect* drawrect;
drawrect->w = dstrect->w;
drawrect->h = dstrect->h;
drawrect->x = dstrect->x - ViewPortOffset.x;
drawrect->y = dstrect->y - ViewPortOffset.y;
SDL_RenderCopy(renderer, tex, srcrect, drawrect);
}
You can either create a second function, or attach a boolean to the input of that function, to allow you to ignore the offset; what if you have a GUI button that you don't want the offset to apply to, etc?
https://github.com/Helliaca/SDL2-Game is a small open source game using a similar method. You can find this code in base.cpp/.h

SDL2 Object Oriented Wrapper; 1000+ Virtual Function calls a frame; Is there any way to optimize this?

I'm writing an object oriented wrapper for SDL2. I have decided to make 2 classes: a Sprite class, and a Rectangle Class. I used a bit of polymorphism so I don't have to overload the draw function for every drawable object. I have a base class Drawable which has a pure virutal function draw.
Now Sprite and Rect inherit Drawable and define the draw function to suit the style of class. Now, when I have to draw many things to the screen, I'm taking a pointer to Drawable, then calling the draw method. This is happening 1000+ times a second.
If I look at my CPU usage, it's about 10%. I know 1000+ Sprites being drawn every 60 times a second is going to hinder my CPU usage, but I didn't think it would this much.
Now, my question: Is there any way to optimize this? Maybe take out the pure virtual function and just overload the functions?
My Code (I tried to shorten it as much as possible):
Sprite::Draw Declaration
void Draw() override;
Sprite::Draw Function
void Sprite::Draw() {
// rect is SDL_Rect
rect.x = rect.x - window->getCamera().getCoords().x;
rect.y = rect.y - window->getCamera().getCoords().y;
SDL_RenderCopyEx(window->renderer, texture, NULL, &rect, 0, NULL, flip);
}
The Function that calls Sprite::Draw
void Window::Draw(Drawable *d) {
d->Draw();
}
Drawing Loop
// 1024 grass Sprites
for (int i = 0; i < 1024; i++) {
mainWindow.Draw(&grass[i]); // Calls Window::Draw
}
As I said earlier, it is eating up about 10% of my CPU usage. I have an AMD 6300, and a NVIDIA GTX 750Ti. I am using Microsoft Visual Studio Express 2013.
The executable name is OBA.exe
Can the textures for these grass sprites be condensed into 1 texturemap and then you draw a portion of it (the third param, srcrect -- https://wiki.libsdl.org/SDL_RenderCopyEx)?
I'm guessing you don't have 1024 unique grass textures, but a handful of repeated ones. Combine them all into one image and load that as a grass texture.
Your sprite class then needs to just define a SDL_Rect for which part of the texture it uses to draw.
Sample texture:
Say your sprite uses texture 0, it's srcrect would be 0,0,32,32. Drawing it just adds one parameter to your RenderCopy call.
SDL_RenderCopyEx(window->renderer, texture, &srcrect, &rect, 0, NULL, flip);
This should improve performance for drawing a lot of sprites. Additionally, you could only draw sprites if they are in the camera view.
I fixed it, what I did was just draw the Sprites that were currently in the Camera's view. The reason SDL_LogCritical was being called so much is being every SDL_RenderCopyEx call, SDL_LogCritical is called, along with other SDL functions. But by drawing just what the user can see, I got the CPU usage down to about 0.1%

C++ Why is global static class not keeping its information in other classes?

Okay, so I asked a question about this code of mine earlier, but no one gave any kind of advice (probably since I couldn't give a more exact area to focus on), so I continued my testing and pinpointed the problem to a much more precise area. (That link will show the majority of my code if there is something missing here for some reason).
So basically, I have a global static class, static sf::Texture PlayerTexture, that keeps a texture so that any and all sprites can point to it for their texture. I have a function, void SetUp(), that then makes all of the textures load in their information for use. I use this function at the start of int main() so that these global static textures will all have their textures ready. However, when I create a new Object that has a sprite set it's texture to PlayerTexture, the texture is not loaded, unless I use the SetUp() function inside of the constructor.
Code:
//rpg.h
static sf::Texture PlayerTexture;
/*
NOTE: --Loads in All Textures for use
*/
static void SetUp()
{
//Load texture.
if(!PlayerTexture.loadFromFile("C:/Program Files (x86)/Terentia/Files/Textures/player.png"))
{
std::cout<<"Error: texture failed to load..."<<std::endl;
}
}
...
//main.cpp
typedef std::shared_ptr<rpg::GameObject> ptrGameObject;
int main()
{
//Should prepare all textures for use...
rpg::SetUp();
sf::Sprite tempSprite;
//Texture is loaded from rpg::SetUp() and works.
tempSprite.setTexture(rpg::PlayerTexture);
//Unless rpg::SetUp() is called in constructor, the texture will be empty.
//Even though rpg::SetUp() is called before object is created.
ptrGameObject player = rpg::CreatePlayer();
}
So why is static sf::Texture PlayerTexture not keeping its texture for use inside of other classes? And how can I set it up so that PlayerTexture will have it's texture ready for use anywhere in the code?
(If this code isn't enough to answer my question, the link at the top has much, much more.)

Drawing with OpenGL without killing the CPU and without parallelizing

I'm writing a simple but useful OpenGL program for my work, which consists of showing how a vector field looks like. So the program simply takes the data from a file and draws arrows. I need to draw a few thousands of arrows. I'm using Qt for windows and OpenGL API.
The arrow unit is a cylinder and a cone, combined together in the function Arrow().
for(long i = 0; i < modifiedArrows.size(); i++) {
glColor4d(modifiedArrows[i].color.redF(),modifiedArrows[i].color.greenF(),
modifiedArrows[i].color.blueF(),modifiedArrows[i].opacity);
openGLobj->Arrow(modifiedArrows[i].fromX,modifiedArrows[i].fromY,
modifiedArrows[i].fromZ,modifiedArrows[i].toX,
modifiedArrows[i].toY,modifiedArrows[i].toZ,
simulationSettings->vectorsThickness);
}
Now the problem is that running an infinite loop to keep drawing this gets the CPU fully busy, which is not so nice. I tried as much as possible to remove all calculations from the paintGL() functions, and only simple ones remained. I end The paintGL() function with glFlush() and glFinish(), and yet I always have the main CPU full.
If I remove this loop, the CPU doesn't get too busy anymore. But I have to draw thousands of arrows anyway.
Is there any solution to this other than parallelizing?
You didn't pointed out on how you have implemented your openGLobj->Arrow method, but if you are using 100% CPU time on this, you are probably painting the arrows with immediate mode. This is really CPU intensive, because you have to transfer data from CPU to the GPU for every single instruction inside glBegin() and glEnd(). If you are using GLUT to draw your data, it's really ineficient too.
The way to go here is use GPU memory and processing power to dipslay your data. Phyatt has already pointed you some directions, but I will try to be more specific: use a Vertex Buffer Object (VBO).
The idea is to pre-allocate the needed memory for display your data on GPU and just update this chunk of memory when needed. This will probably make a huge difference on the efficience of your code, because you will use the efficient video card driver to handle the CPU->GPU transfers.
To illustrate the concept, I will show you just some pseudo-code in the end of the answer, but it's by no means completely correct. I didn't tested it and didn't had time to implement the drawing for you, but's it's a concept that can clarify your mind.
class Form
{
public:
Form()
{
// generate a new VBO and get the associated ID
glGenBuffers(1, &vboId);
// bind VBO in order to use
glBindBuffer(GL_ARRAY_BUFFER, vboId);
//Populate the buffer vertices.
generateVertices();
// upload data to VBO
glBufferData(GL_ARRAY_BUFFER_ARB, vertices.size(), vertices.data(), GL_STATIC_DRAW_ARB);
}
~Form()
{
// it is safe to delete after copying data to VBO
delete [] vertices;
// delete VBO when program terminated
glDeleteBuffersARB(1, &vboId);
}
//Implementing as virtual, because if you reimplement it on the child class, it will call the child method :)
//Generally you will not need to reimplement this class
virtual void draw()
{
glBindBuffer(GL_ARRAY_BUFFER, vboId);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, 0);
//I am drawing the form as triangles, maybe you want to do it in your own way. Do it as you need! :)
//Look! I am not using glBegin() and glEnd(), I am letting the video card driver handle the CPU->GPU
//transfer in a single instruction!
glDrawElements(GL_TRIANGLES, vertices.size(), GL_UNSIGNED_BYTE, 0);
glDisableClientState(GL_VERTEX_ARRAY);
// bind with 0, so, switch back to normal pointer operation
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
}
private:
//Populate the vertices vector with the form vertices.
//Remember, any geometric form in OpenGL is rendered as primitives (points, quads, triangles, etc).
//The common way of rendering this is to use multiple triangles.
//You can draw it using glBegin() and glEnd() just to debug. After that, instead of rendering the triangles, just put
//the generated vertices inside the vertices buffer.
//Consider that it's at origin. You can use push's and pop's to apply transformations to the form.
//Each form(cone or cilinder) will have its own way of drawing.
virtual void generateVertices() = 0;
GLuint vboId;
std::vector<GLfloat> vertices;
}
class Cone : public Form
{
public:
Cone() : Form() {}
~Cone() : ~Form() {}
private:
void generateVertices()
{
//Populate the vertices with cone's formula. Good exercise :)
//Reference: http://mathworld.wolfram.com/Cone.html
}
GLuint vboId;
std::vector<GLfloat> vertices;
}
class Cilinder : public Form
{
public:
Cone() : Form() {}
~Cone() : ~Form() {}
private:
void generateVertices()
{
//Populate the vertices with cilinders's formula. Good exercise :)
//Reference: http://math.about.com/od/formulas/ss/surfaceareavol_3.htm
}
GLuint vboId;
std::vector<GLfloat> vertices;
}
class Visualizer : public QOpenGLWidget
{
public:
//Reimplement the draw function to draw each arrow for each data using the classes below.
void updateGL()
{
for(uint i = 0; i<data.size(); i++)
{
//I really don't have a clue on how you position your arrows around your world model.
//Keep in mind that those functions glPush, glPop and glMatrix are deprecated. I recommend you reading
//http://duriansoftware.com/joe/An-intro-to-modern-OpenGL.-Chapter-3:-3D-transformation-and-projection.html if you want to implement this in the most efficient way.
glPush();
glMatrix(data[i].transform());
cilinder.draw();
cone.draw();
glPop();
}
}
private:
Cone cone;
Cilinder cilinder;
std::vector<Data> data;
}
As a final note, I can't assure you that this is the most efficient way of doing things. Probably, if you have a HUGE ammount of data, you would need some data-structure like Octrees or scene-graphs to optimize your code.
I recommend you taking a look at OpenSceneGraph or Visualization ToolKit to see if that methods are not already implemented for you, what would save you a lot of time.
Try this link for some ideas:
What are some best practices for OpenGL coding (esp. w.r.t. object orientation)?
Basically what I've seen that people do to increase their FPS and drop quality includes the following:
Using DisplayLists. (cache complex or repetitive matrix stacks).
Using Vertex Arrays.
Using simpler geometry with fewer faces.
Using simpler lighting.
Using simpler textures.
The main advantage of OpenGL is that is works with a lot of graphics cards, which are built to do a lot of the 4x4 matrix transformations, multiplications, etc, very quickly and they provide more RAM memory for storing rendered or partially rendered objects.
Assuming that all the vectors are changing so much and often that you can't cache any of the renderings...
My approach to this problem would be to simplify the drawing down to just lines and points, and get that to draw at the desired frame rate. (A line for your cylinder and a colored point on the end for the direction.)
After that draws fast enough, try making the drawing more complex, like a rectangular prism instead of a line, and a pyramid instead of a colored point.
Rounded objects typically require a lot more surfaces and calculations.
I am not an expert on the subject, but I would google other OpenGL tutorials that deal with optimization.
Hope that helps.
EDIT: Removed references to NeHe tutorials because of comments.

C++ / SDL encapsulation design help

So I am semi-new to C++, and completely new to SDL. Most of my conceptual knowledge of OOP comes from Java and PHP. So bear with me.
I am trying to work out some simple design logic with my program / soon to be side-scroller. My problem lies with trying to make my 'screen' layer (screen = SDL_SetVideoMode(...)) accessible to all my other classes; Hero class, background layer, enemies, etc. I have been loosely following some more procedural tutorials, and have been trying to adapt them to a more object oriented approach. Here is a little bit of what I have so far:
main.cpp
#include "Game.h"
#include "Hero.h"
int main(int argc, char* argv[])
{
//Init Game
Game Game;
//Load hero
Hero Hero(Game.screen);
//While game is running
while(Game.runningState())
{
//Handle Window and Hero inputs
Game.Input();
Hero.userInput();
//Draw
Game.DrawBackground();
Hero.drawHero();
//Update
Game.Update();
}
//Clean up
Game.Clean();
return 0;
}
As you can see, I have a Game class, and a Hero class. The Game class is responsible for setting up the initial window, and placing a background. It also updates the screen as you can see.
Now, since my Game class holds the 'screen' property, which is a handle for SDL_SetVideoMode, I am stuck passing this into any other class (ex: Hero Hero(Game.screen);) that needs to update to this screen... say via SDL_BlitSurface.
Now, this works, however I am getting the idea there has GOT to be a more elegant approach. Like possibly keeping that screen handler on the global scope (if possible)?
TLDR / Simple version: What is the best way to go about making my window / screen handler accessible to all my subsequent classes?
I like the way you are doing it.
Though rather than passing the screen reference I would pass a reference to a game itself. Thus each hero object knows which game it belongs too, it can then ask the game object for the screen as required.
The reason I would do this is so that in a few years when your game is a wide and successful product and you convert it for online-play you really need to do no work. The game server will be able to easily support multiple game objects, each game object hosting multiple hero objects. As each hero object wants to draw it asks the game for the screen abd updates the screen (the screen can now very from game object to game object and still work perfectly (as long as they have the same interface).
class Game
{
public:
Game(Screen& screen)
: screen(screen)
{}
virtual ~Game() {}
virtual Screen& screen() { return theGameScreen;}
void update() { /* Draw Screen. Then draw all the heros */ }
private:
friend Hero::Hero(Game&);
friend Hero::~Hero();
void addHero(Hero& newHero) {herosInGame.push_back(&newHero);}
void delHero(Hero& newHeor) {/* Delete Hero from herosInGame */}
// Implementation detail about how a game stores a screen
// I do not have enough context only that a Game should have one
// So theoretically:
Screen& theGameScreen;
std::vector<Hero*> herosInGame;
};
class Hero
{
public:
Hero(Game& game)
: game(game)
{game.addHero(*this);}
virtual ~Hero()
{game.delHero(*this);}
virtual void Draw(Screen& screen) {/* Draw a hero on the screen */}
private:
Game& game;
};
Main.
#include "Game.h"
#include "Hero.h"
int main(int argc, char* argv[])
{
//Init Game
Screen aScreenObject
Game game(aScreenObject);
//Load hero
Hero hero(game); // or create one hero object for each player
//While game is running
while(game.runningState())
{
//Handle Window and Hero inputs
Game.Input();
Hero.userInput();
//Update
Game.update();
}
//Clean up
// Game.Clean(); Don't do this
// This is what the destructor is for.
}
I don't know if it's elegant, but what I do for the side-scrolling game I'm making is to make a show() function in each class than draws to the screen, and passing the screen handle as a parameter. Then whenever I want to draw something to the screen I just do foo.show(screen). The screen handle is in main().
The first, and honestly, easiest solution, is to use a global variable. Yes, yes, yes, everyone says global variables are horrible, but in this situation, it's perfectly fine.
The other solution, which is a bit more work, but can result in somewhat more portable code, is to encapsulate your drawing functions into a single, static class. This way, you can draw to the screen directly without having to pass around a variable, or have to lie awake at night thinking the code review police will get you because you used a global variable. Plus, this can potentially make it easier if you ever decide to port your game to a new library. Some quick and dirty pseudocode:
class Drawing
public:
static void Draw(x, y, sdl_surface graphic, sdl_rect & clip=null);
static void init(sdl_surface & screen);
private:
sdl_surface screen;
void Drawing::Draw(x, y, sdl_surface graphic, sdl_rect & clip=null)
{
sdl_blit(x, y, graphic, clip);
}
void Drawing::init(sdl_surface & screen)
{
this.screen=screen;
}
It sounds like you're looking for a way to implement the Singleton design pattern, where you would have a single Screen object. If you know you're only ever going to have a single Screen object it should work fine.
In this case you would implement a static method on the Game class:
class Game
{
public:
static Game *GetTheSceenObject();
private:
static Screen *theScreen; // details of initialisation ommitted
}
that would return a pointer to the single Screen object.
If there is a possibility that you'll end up using multiple SDL screens, though, it may be worth creating a Draw() method in your Hero class that is responsible for drawing the hero on each of the Screens managed by the Game class by iterating through a list provided by the Game class.
That functionality could be contained in the methods of a common DrawableThingy class that Hero and Enemy are derived from.
Passing Game.screen around is more OO (though it might be better to have a getter function) than having one instance of it that can be accessed from any class, because if you have one global version, you can't have more than one Game.screen at any one time.
However if you know you'll only ever need one in the entire lifetime of the program, you might consider making Game::Screen() a public static function in the Game class that returns a private static member screen. That way, anyone can call Game::Screen() and get the screen.
Example (assuming ScreenType is the type of screen and that you store a pointer to it):
class Game {
public:
static ScreenType* Screen() {
if (!screen)
screen = GetScreenType(args);
return screen;
}
}
private:
// if you don't already know:
// static means only one of this variable exists, *not* one per instance
// so there is only one no matter how many instances you make
// the same applies to static functions, which you don't need an instance to call
static ScreenType* screen;
};
// and somewhere in a .cpp file
ScreenType* Game::screen = NULL;
// and you use it like this
ScreenType* scr = Game::Screen();
// use scr