OOP design question

Sorry the title is pretty vague but I didn't know a short way to word my question. I'm trying to really grasp the concepts behind OOP programing and the correct ways to structure my programs and I'm a bit stumped as to the correct way to solve this issue.

Say I have a Pig class that's encapsulates the entire pig object as it should (as far as I know). ...

This is not my exact class but more or less it's what I plan to use for this.
1
2
3
4
5
6
7
8
9
10
11
class pig
{
public:
    pig();
    ~pig();
    
    bool move();
private:
    int x;
    int y;
};


I have a pig that can "move" by updating the x and y location with the move function.

The next step for me is making a graphics class. (I'm using SDL for this since it seems like a simple place to start for testing)
This is not the full class but the main idea is to be able to draw the pigs to the screen...
1
2
3
4
5
6
7
8
9
10
11
12
13
class CGraphics
 {
public:
	CGraphics(int screenheight, int screenWidth);
	~CGraphics();

	void drawSprite(SDL_Surface* imageSurface,
             int srcX, int srcY, 
             int dstX, int dstY,
             int width, int height);
private:
    SDL_Surface* screen;
 };


Now what would be the normal way to actually draw the pig to the screen... I can think of two and both seem odd to me.

one would be using the CGraphics class inside my pigs class so it could just use the private x and y for drawing, but I think this would be against the idea of encapsulation and oop design in general? correct me if I'm wrong.

Other then that I'd just have every object drawn in the main loop...
 
graphicsObject->drawSprite( /*some kinda structured array of object?*/ );

Last edited on
You'd use some kind of adapter to draw that pig on that image system.

Let's say your CGraphics thing could render a Sprite. The method would look like:
 
void draw(Sprite* sprite);


You could invent some PigSprite that looked like:
1
2
3
4
5
class PigSprite : public Sprite
{
    Pig* pig;
    //...
};


Then can render your pig:
1
2
3
4
5
CGraphics* surface =  createSurface(...);
Pig* flyingPig = createPig(...);
PigSprite* pigImage = createPigImage(flyingPig, ...);
//...
surface->draw(pigImage);
Hm, I'm lost as to why you'd do it like that. Why would I need another class Pigsprite if CGraphics already handles all graphics functions, pig could hold the string contain the sprite is should load.. (string sprite = "pig.bmp") in the pigs class.

This is my main atm using a Npc class and Graphics class (Npc is just acting as a pig object for now and the pig will be derived from Npc class later on)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include "main.h"

int main( int argc, char* args[] )
{
	CGraphics* gr = new CGraphics(800, 600, "Hello", 20, 107, 47);

	SDL_Surface* pig = gr->loadBitmap("pig.bmp", 255, 255, 255);

	NPC* woink = new NPC();
	woink->setX(50);
	woink->setY(50);
	woink->setSpeed(3);

	NPC* woink2 = new NPC();
	woink2->setX(500);
	woink2->setY(450);
	woink2->setSpeed(18);

	while(1)
	{
		woink->move(400, 350);
		woink2->move(20, 14);

		gr->beginScene();

		gr->drawSprite(pig, 0, 0, woink->getX(), woink->getY(), 32, 32); 
		gr->drawSprite(pig, 0, 0, woink2->getX(), woink2->getY(), 32, 32); 

		SDL_Delay(50);

		gr->endScene();
	}

	delete woink;
	delete woink2;

	gr->closeBitmap(pig);

	gr->~CGraphics();

	return 0;
}


More or less I just manually created a couple pigs objects and draw them to the screen and they move to where I tell them to. Is this not a good way to do it?

Edit: I'll check this tomarrow , I have to get to bed. thanks for any replies and good night.
Last edited on
first off, make sure your working with SDL properly, doing this first
 
SDL_Surface * screen = SDL_SetVideoMode(WIDTH,HEIGHT,BPP,FLAGS);


secondly, any class which has a graphical purpose needs an (SDL_Surface *) image to hold the surface that you want to bilt, and a function called render() to bilt. or more precisely,

1
2
3
4
5
6
7
void render(int destinationX, int destinationY){
   SDL_Rect clipBox;
   clipBox.x = destinationX;
   clipBox.y = destinationY;

   SDL_BlitSurface( image, NULL, screen, &clipBox );
}


remember that SDL is not an OOP designed library, it was written in C a long long time ago, nevertheless its good. When trying to do the OOP approach in SDL, try to have all your graphical objects follow the game design and have the three features of any game.

void capture_events();
void handle_logic();
void render();

even though for now you can just leave the first two empty, but you should get used to having those three function. cause eventually your objects will be inside an infinite loop and that's how things work in there.

I highly recommend you try this tutorial http://lazyfoo.net/SDL_tutorials/
I don't think you understand my question, I'm not having a issue with SDL or a error in my code really. I'm just trying to find out the correct way to structure this program while keeping within the OOP standards? I guess that's a good way to put it.

I understand the idea of

collect user input

do logic

then draw to the screen and that's what I plan to do but I want to make sure I have the right idea as far as how to use my objects and to keep the idea of encapsulation correctly.

I'm thinking I need to derive a class from CGraphics (CGraphics encapsulates all graphics functions) the new class would be called CRender, all it would really do is have a method of getting every other objects sprite position and any other data I need like status of the object (walking, attacking, idling) perhaps. then draw them all to the screen at once.

Maybe the render class should be a template so I can just pass any type of object and use it's members functions to get all the data I need?

more or less I'd do something like this..

Maybe the render function should just be part of the graphics class? ...Ugh, this is what confuses me about OOP programming it's having a good structure.
Last edited on
The idea is this. A pig is a pig. It can live on a farm. It can live in the wild. It can be drawn on a GDI surface. It can be drawn on a SDL surface. But none of these things affect what a pig is. It may be grey or pink, but it living on a farm, in the wild, being drawn with CGI or SDL doesn't change the pig's colour.

You need an adapter to fit the pig to an environment. And that's the thinking to my proposal. You don't have to do it the way I suggested, but the principle is not unreasonable.

Edit:
BTW, the pig doesn't have coordinates. The coordinates are properties of the windowing system, it belongs in the adapter.
Last edited on
I'm not sure he needs to be this portable right now, kbw.

I'm usually sticking to this design.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

class Pig: public Animal{ public:

   Pig( Game * pointer, startX, startY, others): father(pointer), levelX(startX),levelY(startY){}
   Game * father;      //points to whoever created it
   SDL_Surface * image;  //at some point you need to load this before use


   int levelX, levelY;   //the coordinates
   int angle;
   //other variables

   virtual void handle_events();
   virtual void do_logic();
   virtual void render();
};

/* the idea behind this design that all objects have a pointer to their father, this way they can pull the events from the father. The do_logic is calculations based per frame. And the render() takes the coordinates and blits the surface to the screen, which in my case the screen is always a global variable. 

besides that a pig should inherit from the abstract Animal because then you can have a list of Animals and render them all in a loop, without caring which specific animal it is. If Pig is the only thing you have then there is nothing to be OOP about. */ 


hope this helps
Edit: actually I think I get what you're saying tinyteetree, I do only have a pig for now but it's a member of the Npc class as I'll have many creatures and Npc's in the future. I'm just trying to learn how people structure things like this, ...well cause it's what I want to do right now.

The father idea is something I've been working on as a system class but kbw suggests the pig doesn't have a location? I'm not sure why you would do this since the pig would need to hold it's methods and data members and location seems to be a must to me.

The system class in my case Is what handles the games rendering, logic, input and the creation of all objects...

main
|
system
|
graphics----------input
|
SDL--------...other things


Edit: Kbw, when you say I need to create an "adapter" to do your approach at things what is it you mean exactly? Would you give me an example? It doesn't need to be real working code, I just want to get a better grasp of what you mean.
Last edited on
I'm not sure why you would do this since the pig would need to hold it's methods and data members and location seems to be a must to me.
Replace Pig with Player. Each player has health, armor, amo, weapons, ... But the location is a property of the environment, especially as the units will be in that of the graphics system.

Kbw, when you say I need to create an "adapter" to do your approach at things what is it you mean exactly?
That PigSprite thing I came up is in an adapter that maps a pig onto a sprite.

Design isn't about hard and fast rules. It's an elastic process that's meant help, not be another abstract useless task.
I see, I'll keep it in mind and play around with the idea but it seems more complicate to me (at first glance) then just having 1 render function in a system class, it'll make a list of all the Npc objects in the world and get all their member data for locations and what image to draw.

thanks for all the advice everyone.

Last edited on


Exempt if you are serious about doing good design, go to this source, its great
http://lazyfoo.net/articles/article06/index.php
This will help you much more then I ever could.

It will teach you how to do the game state engine, with an extensive example of objects within that game state.

Its c++ OOP design meant for SDL, sounds too good to be true hu?
Last edited on
Topic archived. No new replies allowed.