SDL game programming

Started by
19 comments, last by Sykth 17 years, 1 month ago
Thanks man much appreciated!
Advertisement
Hey guys,


sorry to keep dragging this topic up, but i just wanted to ask one more question about this whole struct and unit location stuff.

I'm now using the struct Point2D in a class Selection.h which is included in my building and unit classes basically as a main way to set and get x,y values.

For example, my selection.h:

#ifndef SELECTION_H
#define SELECTION_H

#include "SDL/SDL.h"

class Selection {
private:
mX, mY;
enum SelectionStates { NOT_SELECTING, SELECTING };
SelectionStates state;
public:

struct Point2D
{
double getX() const {return mX;}

double getY() const {return mY;}

void setX(double x) {mX = x;}

void setY(double y) {mY = y;}

void setXY(double x, double y) {setX(x); setY(y);}
}

double mouseX, mouseY;
Selection();
Selection s1, s2; /* im trying to pass 2 instances of selection so i can use s1.getminX(), s1.getMinY(), s2.getMaxX(), and s2.getMaxY() to set selected or not selected for the units and draw the selection area */
bool update();
void render( SDL_Surface *screen );
double getMinX() const;
double getMaxX() const;
double getMinY() const;
double getMaxY() const;
};


Am i doing this wrong ? Im geting errors that Point2D is unreferenced and so is s1 and s2. And invalid use of non static data member "Selection::mX and mY ?

My selection.cpp looks like this:

#include "selection.h"
#include <iostream>
#include <stdlib.h>
#include <SDL/SDL.h>

Selection::Selection()
{
state = NOT_SELECTING;
mX = 0;
mY = 0;
}

bool Selection::update(double mouseX, mouseY) {
//int mouseX, mouseY;
Uint8 mouseState = SDL_GetMouseState( &mouseX, &mouseY );

if( state == SELECTING ) {
if( !( mouseState & SDL_BUTTON(1) ) ) {
state = NOT_SELECTING;
return true;
} else {
s1.setX( mouseX );
s1.setY( mouseY );

}
} else {
if( mouseState & SDL_BUTTON(1) ) {
state = SELECTING;
s1.setX( mouseX );
s1.setY( mouseY );
s2.setX( mouseX );
s2.setY( mouseY );
}
}

return false;

}

void
Selection::render( SDL_Surface *screen ) {
if( state == SELECTING ) {
rectangleColor( screen, s1.getMinX(), s1.getMinY() , s2.getMaxX(), s2.getMaxY(), 0xfee19080 );
}
}

double
Selection::getMinX() const {
return ( s1.getX() < s2.getX() ? s1.getX() : s2.getX() );
}

double
Selection::getMaxX() const {
return ( s1.getX() > s2.getX() ? s1.getX() : s2.getX() );
}

double
Selection::getMinY() const {
return ( s1.getY() < s2.getY() ? s1.getY() : s2.getY() );
}

double
Selection::getMaxY() const {
return ( s1.getY() > s2.getY() ? s1.getY() : s2.getY() );
}


Sorry for long post!

Any ideas ?

Sykth
Update:

could i use

typedef Point2D SelectionOne, SelectionTwo;

struct Selections
{
selectionOne s1;
selectionTwo s2;
}


In my selection class with the orignal Pointer2D ? and then use calls like s1.getX() and so on to set my selection area ?
That would be a bad idea. SelectionOne and SelectioTwo does not deserve to be data types. It sounds to me that they should be two instances of Point2D:
Point2D SelectionOne, SelectionTwo;
Infact, I would rather make a rectangle struct and only have one of them.

Some changes you might find clearifying:

// selection.h:#ifndef SELECTION_H#define SELECTION_H#include "SDL/SDL.h"struct Point2D{    double getX() const {return mX;}    double getY() const {return mY;}    void setX(double x) {mX = x;}    void setY(double y) {mY = y;}           void setXY(double x, double y) {setX(x); setY(y);}	private:	double mX, mY;	}; // Dont forget to finish a class/struct with a ;class Selection {private:	enum SelectionStates { NOT_SELECTING, SELECTING };	SelectionStates state;public:                    	Selection();	// I dont think the Point2D class belong inside a Selection class. 	// Rather just create two instances of it	Point2D s1, s2; 	bool update();	void render( SDL_Surface *screen );	double getMinX() const;	double getMaxX() const;	double getMinY() const;	double getMaxY() const;};#endif // dont forget this// Selection.cpp//#include "selection.h"#include <iostream>#include <stdlib.h>#include <SDL/SDL.h>Selection::Selection() {	state = NOT_SELECTING;}bool Selection::update(int mouseX, int mouseY, int mouseState) {	if( state == SELECTING ) 	{		if( !( mouseState & SDL_BUTTON(1) ) ) 		{			state = NOT_SELECTING;			return true;		} 		else 		{			s1.setX( mouseX );			s1.setY( mouseY );		}	} 	else 	{		if( mouseState & SDL_BUTTON(1) ) 		{			state = SELECTING;			s1.setX( mouseX );			s1.setY( mouseY );			s2.setX( mouseX );			s2.setY( mouseY );		}	}		return false;	}void Selection::render( SDL_Surface *screen ) {	if( state == SELECTING ) 	{		rectangleColor( screen, s1.getMinX(), s1.getMinY() , s2.getMaxX(), s2.getMaxY(),  0xfee19080 );	}}double Selection::getMinX() const {   return ( s1.getX() < s2.getX() ? s1.getX() : s2.getX() );}double Selection::getMaxX() const {   return ( s1.getX() < s2.getX() ? s1.getX() : s2.getX() ); }double Selection::getMinY() const {   return ( s1.getY() < s2.getY() ? s1.getY() : s2.getY() ); }double Selection::getMaxY() const {   return ( s1.getY() < s2.getY() ? s1.getY() : s2.getY() ); }int main(){	    int mouseX, mouseY;	Uint8 mouseState;		// ...	while(game_is_still_running)	{		// I placed the SDL_GetMouseState here. No need to call it once for each selection in the game.		// Once per cycle will do		mouseState = SDL_GetMouseState( &mouseX, &mouseY );				unit1.selection.update(mouseX, mouseY, mouseState);		// ...	}	// ...}

I assume that you want to have a selection rectangle so that the player can select units by dragging a selection over them.
Once the player release the mouse button, the units contained in the selection rectangle
should be considered selected. Is this right?
yes thats correct :) thanks for your input :)
No problem =)

You said that you thought it was too simple earlier, but Id say it is the other way around.
You should convince yourself that there must be a simpler/slickier way to do it and find it :D
Its a lot of tools in the language and the libraries to make things like this look easy, and it seems like you still need to read up on some of them.

Anyway, I suggest that you also create a Player struct and place an instance of Selection in there. Not in the Unit struct.
A game often have more units than players, so there would typically be one struct for each of them. The Selection object would go in the Player struct, and all the Unit struct need is a bool selected.
The Unit struct's render function can check this variable, and if it is true, you add some extra graphics to indicate that this unit is selected.
This variable is also needed other places in the game, like in the AI module.

This is ofcourse just one way to do it. There is many, and most of them are more sophisticated.

Feel free to ask, and good luck
Hey,

massive thanks for the input so far. Unfortunately i'm still experiencing problems with this struct stuff. I have taken aboard pulp's advice, and at the moment all of my files were compiling ok until I suffered a minor hick up with s1, s2 being "undeclared" and by getMinX() etc. not being a member of my struct Point2D.

I rectified this by declaring the getMinxX() methods inside the Point2D struct and then declaring their contents in the public section of my selection.h

This was wonderful except when i compile main, even tho i have included selection.h in all relevant files such as my baseBuilding, testBuliding (or soon to be barracks) and unit.h i get error messages that all my mini structs for setting building and unit locations are undeclared. For example:


// above is class testBuilding : sprite and includes (including selection.h)
public:

typedef Point2D tBuildingLocation, tBuildingDrawArea;

struct tBuilding
{
tBuildingLocation tBLoc;
tBuildingDrawArea tBDArea;
}; //added semi-colon still same errors

void setTBuildingXLoc(int mouseX)
{
tBLoc.mX = mouseX;
}


void setTbuildingYLoc(int mouseY)
{
tBLoc.mY = mouseY;
}


double getTbuildingXLoc()
{
return tBLoc.mX;
}

double getTbuildingYloc()
{
return tBLoc.mY;
}


I really cant see anything wrong with it, but im getting these errors tBloc undeclared. My baseBuilding is the same and it produces similar errors except its called bLoc. Any ideas ?

[Edited by - Sykth on March 5, 2007 6:24:54 AM]
*shameless bump*

Quote:
at the moment all of my files were compiling ok until I suffered a minor hick up with s1, s2 being "undeclared" and by getMinX() etc. not being a member of my struct Point2D.

s1 and s2 should be declared if you place the Point2D struct outside and above the Selection struct.
Note that a struct is very different from an instance of a struct.
The Point2D struct is like a blueprint for the compiler so that it knows how to create a Point2D.
For example, if you want to have a Point2D inside the Selection struct it would look like this.
// First we must create the blueprint of a Point2D:struct Point2D{// same old...};// At this point the compiler knows how to create a Point2D and will give us no errors if we do.struct Selection{    // Here we create an instance of a Point2D. This one happens to be inside the Selection struct    Point2D s1;};// Putting a struct inside another struct, like this:struct Selection{    struct Point2D    {        // ...    };};/*This is like putting a blueprint inside another blueprint. It is possible, but it does not make sense in this situation. This kind of construct is rarely needed.To create a Point2D instance we would now have to type Selection::Point2D myPoint;*/

Quote:
I rectified this by declaring the getMinxX() methods inside the Point2D struct and then declaring their contents in the public section of my selection.h

getMinX() does not belong in the Point2D struct. Remember that there is only one x in a Point2D so MinX does not make sense here.
It seems to me that what you need inside the Selection struct is a rectangle.
This rectangle will replace s1 and s2.
I have made a rectangle struct that will take care of your needs.
It has a bit more functionality than a traditional Rectangle, so I called it Area:
struct Area{	Area() { setAll(0, 0, 0, 0); }	void setLeft(int left) 	{ 		mLeft = left; 		if(mLeft > mRight) 			swap(mLeft, mRight);	}	void setTop(int top) 	{ 		mTop = top; 		if(mTop > mBottom)			swap(mTop, mBottom);	}	void setRight(int right) 	{ 		mRight = right; 		if(mRight < mLeft)			swap(mRight, mLeft);	}	void setBottom(int bottom) 	{ 		mBottom = bottom; 		if(mBottom < mTop)			swap(mBottom, mTop);	}		void setAll(int left, int top, int right, int bottom)	{		mLeft = left;		mTop = top;		setRight(right);		setBottom(bottom);	}	int left() const { return mLeft; }	int top() const { return mTop; }	int right() const { return mRight; }	int bottom() const { return mBottom; }private:	int mLeft, mTop, mRight, mBottom;	void swap(int& a, int& b)	{		int c = a;		a = b;		b = c;	}};

Now, rather than having Point2D s1, s2; in the Selection struct you get Area selection;
This Area struct will also make sure that left <= right and top <= bottom, as long as you only use the get* and set* functions to change its variables (left, top, right, bottom)
Using this you no longer need the Min/Max functions at all.

Quote:
This was wonderful except when i compile main, even tho i have included selection.h in all relevant files such as my baseBuilding, testBuliding (or soon to be barracks) and unit.h i get error messages that all my mini structs for setting building and unit locations are undeclared. For example:

// above is class testBuilding : sprite and includes (including selection.h)
public:

typedef Point2D tBuildingLocation, tBuildingDrawArea;

struct tBuilding
{
tBuildingLocation tBLoc;
tBuildingDrawArea tBDArea;
}; //added semi-colon still same errors

void setTBuildingXLoc(int mouseX)
{
tBLoc.mX = mouseX;
}


void setTbuildingYLoc(int mouseY)
{
tBLoc.mY = mouseY;
}


double getTbuildingXLoc()
{
return tBLoc.mX;
}

double getTbuildingYloc()
{
return tBLoc.mY;
}


I really cant see anything wrong with it, but im getting these errors tBloc undeclared. My baseBuilding is the same and it produces similar errors except its called bLoc. Any ideas ?


I can use setTBuildingXLoc as an example.
If you change it to
void setTBuildingXLoc(tBuilding& building, int mouseX){    building.tBLoc.setX(mouseX);    // building.tBLoc.mX = mouseX;     // The above line will work if you remove the private: keyword in the     // Point2D struct, but it is not recommended.     // (See the chapter about classes for more info about these things)}

it will work, or at least one step closer to working.

Another option (the one I used earler with the Point2D struct) is to make the functions part of the tBuilding struct.
After all, all these functions do is to operate on the variables inside a tBuilding struct.

This line:
typedef Point2D tBuildingLocation, tBuildingDrawArea;
is rely not needed. We already made a data type called Location for this purpose, or just use a Point2D and skip the typedef all together.
The last one, tBuildingDrawArea sounds like a rectangle (area = rectange right?), so use the Area struct from my earlier code example instead. Something along these lines:
struct tBuilding{    Point2D location;    Area drawArea;    void setXLoc(int mouseX)    {        location.setX(mouseX);    }    int getXLoc() const     {        return location.getX();     }    // ...};


Also note that a struct is like a package. Everything you put inside a struct is "invisible" to the rest of the code. Thats a simple way to put it but what the heck...
So, we can do like this:
struct tBuilding{    Point2D location;    ...};struct tPlayer{    Point2D location;    ...};Point2D location;...

None of these three variables will get a naming conflict.
From the compilers viewpoint they are called
tBuilding::location, tPlayer::location and location
In other words, it is able to differenciate between them so there is no error =)

PS:
You dont want to bump on gamedev m8 =)
If you dont get response on your post, it is usually becouse you did not express yourself clearly or becouse you ask something you should know already.
Thanks for all your help pulpfist, artum and co., and apologies for the bump, im new to forums :)

This topic is closed to new replies.

Advertisement