Skip to main content
gamedev.net
🔒 Locked

My programming style :(

Started by Lode 54 replies 4.4k views
Original Post
Lode
Lode
In a beginning space shooter project, I use structs for ships, planets, vectors, ...., and for multiple ships I just use an array of ship-structs with a for loop. I make the arrays of structs extern in the headers. Do you think structs are object oriented enough, or does this really suck? Please give comments. [edited by - Lode on August 1, 2002 3:36:06 PM]
Cahaan
Cahaan
I personally only use classes when needed. (Or when I know I will need it later).

I think it may be useful in your case if you want to override your ship class to make "special" kinds of ships for example.
Darkhaven Beta-test stage coming soon.
Arild Fines
Arild Fines
quote:
Original post by Cahaan
I personally only use classes when needed.


Classes are never necessary. Nor are structs. Or functions...




"I would defend the liberty of concenting adult creationists to practice whatever intellectual perversions they like in the privacy of their own homes; but it is also necessary to protect the young and innocent."
Arthur C Clarke
--AnkhSVN - A Visual Studio .NET Addin for the Subversion version control system.[Project site] [IRC channel] [Blog]
civguy
civguy
Instead of array, I advice you to use STL containers. They''re safer and offer more than an array does. A linked list is probably a good choice for ships and planets.

And as AP said, you should use classes instead of structs. At least in 99% of cases .
lasher
lasher
Classes and structs in c++ are exactly the same. The only differance is the name.
nope, nothin intersting to say yet. gimme time.
Laroche
Laroche
Lasher: structs have a public visibility as default, where as classes have a private visibility as default
Check out my music at: http://zed.cbc.ca/go.ZeD?user_id=41947&user=Laroche&page=content
Zipster
Zipster
And here''s something else I learned: only in a C++ compiler are they even that similar. In a regular C compiler, a structure is quite stripped down in terms of what it can do.
merlin9x9
merlin9x9
civguy is right: use the STL.

quote:
In a regular C compiler, a structure is quite stripped down in terms of what it can do.

Well, yeah, nor are there classes at all. That''s the language, not just the compiler. In C, structs only contain members, and there are no access specifiers.
DerekSaw
DerekSaw
quote:
Original post by Lode
Do you think structs are object oriented enough, or does this really suck?


It doesn''t suck. It''s just the way similar to Quake2 source, all structs. ... solving problems doesn''t need the OO-ness... the main thing is that you understand your own code clearly, it works, consider a nice design, and ''no'' bugs (on normal occasion, there is no ''no bugs'' in software).

Anyway, if you are doing the following (or similarly):

...
for (j = 0; j < maxsize; ++j)
{
switch (object[j]->type)
{
case SHIP:
((Ship*)object[j])->DrawShipBeautifully();
break;
case PLANET:
((Planet*)object[j])->DrawPlanetColorfully();
break;
...
}
}
...

Then I think you need to redesign your structs/classes.
"after many years of singularity, i'm still searching n the event horizon" o
Lode
Lode
Well to give an example: here's the part that calculates gravity from planets affecting the enemy ships and then get their direction:



        
void moveEnemies()
{
vector gravity;
vector enemyVel;
vector enemyAccel;
vector oldPos;

previousTime = thisTime;
thisTime = timeGetTime()*0.001 ;
timeDifference = thisTime-previousTime;
if (previousTime == 0) timeDifference = 0;

for (int a=0;a<numEnemies;a++)
{
enemies[a].accel.x = 0;
enemies[a].accel.y = 0;
enemies[a].accel.z = 0;

for(int x=0;x<numPlanets;x++)
{
gravity = substract(planets[x].pos, enemies[a].pos);
EPDdistance = distance3D(enemies[a].pos, planets[x].pos); //EPDistance = Enemy Planet Distance

if (EPDistance < planets[x].size) EPDistance = sqrtplanets[x].size;
gravity = normalize(gravity);
gravity = multiplyBy(gravity, enemies[a].mass*planets[x].mass/(EPDistance*EPDistance));
//if (gravity.x < 1 && gravity.y < 1 && gravity.z < 1)

enemies[a].accel = add(gravity, enemies[a].accel);
}


enemyAccel = multiplyBy(enemies[a].accel, (timeDifference)); //the accel in m/t² with t = time since last frame

enemies[a].vel = add(enemyAccel, enemies[a].vel);
enemyVel = multiplyBy(enemies[a].vel, (timeDifference)); //the vel in m/t with t = time since last frame

oldPos = enemies[a].pos;
enemies[a].pos = add(enemies[a].pos, enemyVel);
enemies[a].dir = normalize(substract(enemies[a].pos, oldPos));
if ( enemies[a].dir.x == 0 && enemies[a].dir.y == 0 && enemies[a].dir.z == 0)
{
enemies[a].dir = defaultEnemyDir;
}

}
}


Does that look OK or bad?

[edited by - Lode on August 2, 2002 5:34:55 AM]
cearny
cearny
quote:
Original post by Lode
Well to give an example: here''s the part that calculates gravity from planets affecting the enemy ships and then get their direction:




          
void moveEnemies()
{
vector gravity;
vector enemyVel;
vector enemyAccel;
vector oldPos;

previousTime = thisTime;
thisTime = timeGetTime()*0.001 ;
timeDifference = thisTime-previousTime;
if (previousTime == 0) timeDifference = 0;

for (int a=0;a<numEnemies;a++)
{
enemies[a].accel.x = 0;
enemies[a].accel.y = 0;
enemies[a].accel.z = 0;

for(int x=0;x<numPlanets;x++)
{
gravity = substract(planets[x].pos, enemies[a].pos);
EPDdistance = distance3D(enemies[a].pos, planets[x].pos); //EPDistance = Enemy Planet Distance

if (EPDistance < planets[x].size) EPDistance = sqrtplanets[x].size;
gravity = normalize(gravity);
gravity = multiplyBy(gravity, enemies[a].mass*planets[x].mass/(EPDistance*EPDistance));
//if (gravity.x < 1 && gravity.y < 1 && gravity.z < 1)

enemies[a].accel = add(gravity, enemies[a].accel);
}


enemyAccel = multiplyBy(enemies[a].accel, (timeDifference)); //the accel in m/t² with t = time since last frame

enemies[a].vel = add(enemyAccel, enemies[a].vel);
enemyVel = multiplyBy(enemies[a].vel, (timeDifference)); //the vel in m/t with t = time since last frame

oldPos = enemies[a].pos;
enemies[a].pos = add(enemies[a].pos, enemyVel);
enemies[a].dir = normalize(substract(enemies[a].pos, oldPos));
if ( enemies[a].dir.x == 0 && enemies[a].dir.y == 0 && enemies[a].dir.z == 0)
{
enemies[a].dir = defaultEnemyDir;
}

}
}


Does that look OK or bad?

[edited by - Lode on August 2, 2002 5:34:55 AM]

OUCH! Better read on code neatness rules I don''t say that it''s unreadable, but it does require a lot of effort on one''s side.



[ Libraries - STLport | boost | SDL | wxWindows ]

[ Manuals - MSDN | STL Docs ]

[ Compilers - VS.NET | MingW | DJGPP ]

[ Editors/Tools - EditPlus 2 | Anjuta | Dev-C++ ]





siaspete
siaspete
I''d advocate the use of structs and arrays over classes and STL containers in the first game you do.

Then in the next one you''ll know the basics of how classes and containers work internally, and you''ll save yourself a lot of headaches.


Helpful links:
How To Ask Questions The Smart Way | Google can help with your question | Search MSDN for help with standard C or Windows functions
civguy
civguy
Ok, I did some refactoring to your code and added lots of comments that should be somewhat helpful. Take a while to read it, it took me a while to write it

The code may contain some minor flaws since I haven't written C++ in 6 months (just Java).

To make things easier (you don't have to reinvent the wheel), you could use Bas Kuenen's vector class. It's pretty good. See here and sources here.

              
void moveEnemies() {
//don't put too much code in one block. Use more methods

calculateTimeDifference();

for (int a = 0; a < numEnemies; a++) {
//I don't know the type of "enemies".. but make it clear that you're dealing

//with a single enemy at a time. Better yet, use STL containers

Enemy* enemy = &enemies[a];
//implement moveTo() to your vector class. It should be helpful later on too

enemy->accel.moveTo(0, 0, 0);

//this is wrong way, sorry.. You should actually do a function call to

//enemy->calculateAcceleration(planets);

//which would look nicer. But I'm not touching your enemy class here

calculateAccelerationForEnemy(enemy);

//i'm not gonna touch the following stuff. But it needs work :). Mostly operator overloading

vector enemyAccel = multiplyBy(enemy->accel, timeDifference);
enemy->vel = add(enemyAccel, enemy->vel);
vector enemyVel = multiplyBy(enemy->vel, timeDifference);
vector oldPos = enemy->pos;
enemy->pos = add(enemy->pos, enemyVel);
enemy->dir = normalize(substract(enemy->pos, oldPos));
//I have a feeling that your vectors will never be 0. Something is wrong here:

if (enemy->dir.x == 0 && enemy->dir.y == 0 && enemy->dir.z == 0) {
enemy->dir = defaultEnemyDir;
}
}
}

void calculateAccelerationForEnemy(Enemy* enemy) {
for (int x = 0; x < numPlanets; x++) {
//once again, deal with a planet, not with planet array

Planet* planet = &planets[x];
//don't give variables too much scope. Instantiate them where they're needed (I moved "vector gravity" to here)

//Learn about operator overloading and fix this then.

//Could be written: vector gravity = planet->pos - enemy->pos;

vector gravity = substract(planet->pos, enemy->pos);
//where is EPDdistance instantiated? Instantiate it here where it's needed, thanks ;)

//also, implement distanceTo() in your vector class

EPDdistance = enemy->pos.distanceTo(planet->pos);
//sqrtplanets?

if (EPDistance < planet->size) EPDistance = sqrtplanets[x].size;
//implement normalize in the vector class

gravity.normalize();
//once again, operator overloading will make these rows look cleaner

gravity = multiplyBy(gravity, enemy->mass * planet->mass / (EPDistance * EPDistance));
enemy->accel = add(gravity, enemy->accel);
}
}

void calculateTimeDifference() {
previousTime = thisTime;
thisTime = timeGetTime() * 0.001;
timeDifference = thisTime - previousTime;
if (previousTime == 0) timeDifference = 0;
}


[edited by - civguy on August 2, 2002 6:35:37 AM]

[edited by - civguy on August 2, 2002 6:49:52 AM]

[edited by - civguy on August 2, 2002 6:50:54 AM]
dta1
dta1
Operator overloading would make the code much easier to read.

gravity = substract(planets[x].pos, enemies[y].pos);
gravity = planets[x].pos - enemies[y].pos;

[edited by - dta1 on August 2, 2002 6:43:46 AM]
Erase, rewind and improve
Cahaan
Cahaan
quote:
Original post by Arild Fines
[quote]Original post by Cahaan
I personally only use classes when needed.


Classes are never necessary. Nor are structs. Or functions...




"I would defend the liberty of concenting adult creationists to practice whatever intellectual perversions they like in the privacy of their own homes; but it is also necessary to protect the young and innocent."
Arthur C Clarke

Did I say "necessary" ? No I said "needed". Try to read or buy some new glasses.

Darkhaven Beta-test stage coming soon.
gimp
gimp
AP. I disagree. I think the poster did the right thing. My website is called fourth. It''s the fourth major rewrite of my engine and THIS time I''ve got it right. I bought code complete, Effective C++, Efficient C++, STL books, read coding style faq etc, etc to get where I am.

Lode, taking time to do things right is setting yourself up best to handle how you will use your code in a few months time. Poor coding today will see you painting yourself in to a corner tomorrow.

If you, like me want a massive game X killer you want to get to know your tools really well before you''ll get there. You may want to take steps to get there but since your posting this question I''m guessing your interested in improving yourself.

As for using classes or structs I personally use structs to store data when no operations will ever need to take place on any of that data. I use classes in all other cases. If only for convention.

I used to be just like AP. If it works who gives a rats about how it got done? Well, after three crap engines you would expect that I work out that good design DOES matter and taking time to forward thing our design will pay off in the long run.

AP : "Not because it is bad, but because you''re getting distracted from your primary goal, which is to get your game made."
Good point. If Lode can finish a game with the code as posted then then good luck to him. If he can''t or it becomes a painfully hard to read mess, then this is the correct the kind of question to ask. Better he ask it now rather than waste a few months and chuck the whole design.

My ~general~ advice:
-Get a book on standard c++. Use the tool(c++) as it was meant to be used. Don''t hack it or you''ll feel pain.
-Get Code Complete for good personal coders hygene
-Get Effective c++ \ more effective c++, or at least read them in the bookstore
-Set some standards for yourself and stick to them. Perhaps have a coder you respect give you his feel on your standard. Get a few quotes from people and average out the info you get.

HTH


Chris Brodie
http:\\fourth.flipcode.com
Chris Brodie
civguy
civguy
AP, if the person wants to know about coding style and good coding conventions, should we just say him "You don''t need that, just make your game with what you know". He *wants* to know this stuff apparently.

IMO one should use classes instead of structs even if the difference between those two is minimal. Structs exist simply because there were structs in C. I see them as something like ''downwards compatibility keyword'', something that makes the language (slightly) more complicated without adding any benefit.
davepermen
davepermen
there is no need to call your stuff classes instead of structs. i prefer the word structs, it does remind me to let stuff be simple, and oo doesn''t mean to inherit all from everything and such and this and that. i had just bad moments at the time i learned classes, so i always will use structs, and if i need to #define struct class in the header (i use public and private all the time so i don''t need a default behaviour anyways)

most important is to get your stuff working. but some tipps:

learning stl is never a fault, its really powerful and saves you from much work that most of us dislike. a vector class should have overloaded operators for simplicity. means a + and a - and a * overloaded. dot and cross stay as methods or functions as best, to avoid operator precedence faults, and other bugs.
kiss is always good, keep it simple, stupid. don''t think about a complex my engine then has levels and each level is one of a html-view of a menu or a gamelevel and you can load that from dll to provide others and each level then contains data from thera and we need for this a factory and all that.

its a spaceshooter.. basically you need

  
std::vector<Ship> g_ships;
std::vector<Planet> g_planets;
std::vector<Bullets> g_bullets;
std::vector<Powerups> g_powerups;

bool load_level(char* _levelfile) {
//fills the 4 dynamic arrays..

}

int main() {
levelscript script("scriptname");
while(script.has_next()&&load_level(script.next())) {
mainloop();
}
}


thats about it..

kiss..

"take a look around" - limp bizkit
www.google.com
If that's not the help you're after then you're going to have to explain the problem better than what you have. - joanusdmentia
My Page davepermen.net | My Music on Bandcamp and on Soundcloud
Lode
Lode
Thanks for extremely useful posts. Also thanks for your rewrite of the code, civguy.

I come from QBasic and back then I didn't know it, but now I know that QBasic doesn't provide a good example of coding style. GOSUB - RETURN can by handy sometimes though

Last year, my first year at university, one of our courses was "Object Oriented Programming in Java". For me that was a terrible course, I really hated it, we had to make classes for EVERYTHING, even for something that contains a piece of code that reads a file. And the assistants cared about some strange details and had weird preferences for certain coding styles that according to me slow down the performance.

During the same year I wanted to redo some of my QBasic projects for Windows and because I didn't like Java I learned myself some C++ and I was amazed by the similarities between the two (well compared to QBasic, Java and C++ are very similar). My first C++ experience was editing the Wolf3D source code with a Borland C++ for DOS but now I'm using DevC++ for Windows and can do some OpenGL and such.

So now I'm here, hanging between two extremes: QBasic and a course about OOP in Java. The course was not able to convince me to use their coding style, but I also know that what I did in QBasic isn't right, and I've got no idea what coding style to use now. I guess that if I make a mistake now I'll see the trouble about it later and learn it the hard way but I hope to prevent it. This post was quite helpful, but I see some divided opinions here

Considering my project is a one-man project, I think I shouldn't go too OOP, right? What's a "Good" one-man coding style?

I'm probably going to rewrite my code (it wasn't that big yet, and I know what math/physics/opengl problems to take care of and how to solve them now), with classes and a better vector class (now I used some 3dmath.cpp and 3dmath.h files that I had put together a few months ago already for some other projects).

Oh and I think I'll need to learn about std's and operator overloading, but I accidently just found a book on C++ in my brother's room. I don't think you'll know the book though, it's Dutch, written by Leen Ammeraal and the title is simply: "C++".

[edited by - Lode on August 2, 2002 10:01:26 AM]
civguy
civguy
quote:
I think that structs can't have functions as members. classes and structs are not the same
That's wrong. Structs can even be inherited from classes and classes can be inherited from structs. The only difference is the default visibility, which is "private" in classes and "public" in structs.

[edited by - civguy on August 2, 2002 10:23:40 AM]

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.