SDL game programming

Started by
19 comments, last by Sykth 17 years ago
Hi there, basically i'm looking for some help with a 2d real time strategy game i'm currently working on using C++ and SDL. I've got a basic understanding of SDL and how to use it, but im struggling with how to assign variables to the mouses X and Y location and hence assign a location for a unit to move to a destination specified by the mouse. If anyone has any SDL tutorials on real time strategy games it would be greatly appreciated! I'm also having problems with drawing a GUI, sort of warcraft style with the minmap and build options when i select my building. If i seem too vague i apologise, when it boils down to it, all i'm really after is a stepping stone guide to get my game off the ground and i can learn from there. Any help greatly appreciated, sykth.
Advertisement
I don't know of any websites or tutorials about strategy games, but I can give you some ideas.

Get mouse position:
int x,y; // variables to hold the current position of the mouseSDL_GetMouseState(&x,&y); // get mouse xy


Input and some walking code:
// struct to hold the destinationstruct Destination {    int x;    int y;};// this structure can for example be a temporary struct which you later copy// into a member structure in a player classDestination dest;// input codeif (event.type == SDL_MOUSEBUTTONDOWN) {    // if left mouse button is pressed    if (event.button.button == SDL_BUTTON_LEFT) {        dest.x = mousex;        dest.y = mousey;    }}// and then in the actual player move code you can have something that// checks if the player haven't reached the current destination// you have specified by pressing on the screen, like below// these if statements will simply check if the player x and y is greater than// or lower than the destionation xy position. It will move the player position// to the destination until it's reachedif (player.x < dest.x)     player.x++; else if (player.x > dest.x)     player.x--;// if player y position is lower than the destionation ypos, increase player.yif (player.y < dest.y)    player.y++; else if (player.x > dest.y)     player.y--;


This code should work if you have a player class, else you have to change the code a little. Hope that helped..
I usually use the following:

Uint8 Buttons;Uint8 *Keys;int MousePosX, MousePosY;Buttons=SDL_GetMouseState(&MousePosX, &MousePosY);Keys=SDL_GetKeyState(NULL);


What the above code does is set the position of the cursor to the variables MousePosX and MousePosY. GetKeyState will also record which keys are currently pressed down. GetMouseState also records which buttons are being held down at that moment.

I use Buttons and Keys like this:
if(Buttons & 1)//left click{     //stuff for left clicking}else if(Buttons & 4)//right click, don't ask me why it's 4{     //stuff for right clicking}if(Keys[SDLK_w])//if the 'w' key is pressed...{     //do stuff for the 'w' key}


On my machine 'Buttons & 4' will get you a right click. I've heard it's sometimes different.

You can also use events to get keyboard and mouse input but I'm not a fan of it.

As for tutorials you should check out what Lazy Foo has, his tutorials really helped me when I was first starting out.
His tutorials can be found at:
http://lazyfoo.net/SDL_tutorials/index.php

Also if you're writing a RTS you'll most definitely want to use path finding. Here's a great tutorail complete with source code that helped me learn A*:
http://www.policyalmanac.org/games/aStarTutorial.htm

Though if you're just starting out save that link for later... it can give you a real headache.

As for me, I'm still learning to make a GUI so I'm no real help there. Anyway, I hope that got a couple of your questions answered.

-Artum.
Quote:Original post by Artum

I use Buttons and Keys like this:
*** Source Snippet Removed ***

On my machine 'Buttons & 4' will get you a right click. I've heard it's sometimes different.



It's probably better to use the SDL_BUTTON definitions than arbitrary numbers :)

SDL_BUTTON_LEFTSDL_BUTTON_MIDDLESDL_BUTTON_RIGHTSDL_BUTTON_WHEELUPSDL_BUTTON_WHEELDOWN
Ok awesome help so far guys!

Just a bit more help if you could, I know i'll prob get slapped on the wrists for some basic programming errors but i'd like you experts to have a nosey at my unit.h code to see where i went wrong.

Basically i tried to create two structs within my unit.h class called unitLocation and unitDestination, and set two sets of variables for x and y locations. Ill paste unitLocation up now:

struct unitLocation
{
double x;
double y;
}


and then i wanted to use setUnitXLocation() and getUnitXLocation() (and same for Y) so i could create a selection method that tested the units X and Y location to see if its within the minX, maxX, minY and MaxY values and thus assign it a SELECTED or NOT_SELECTED value using a enum unitState {SELECTED, NOT_SELECTED} variable.

My get and set methods look like this but i think im doing this wrong:

}

double getXUnitLocation()
{
return unitXloc;
}

double getYUnitLocation()
{
return unitYloc;
}

void setXUnitLocation(int x)
{
this->x = x;
unitXloc = x;
}


void setYUnitLocation(int y)
{
this->y = y;
unitYloc = y;
}
// with my unitYloc and unitXloc being protected variables declared in this file.

Im obviously getting errors but can someone show me a better way to get a units location so i can use it in my selection method.


Sorry for long message.

Sykth
Quote:Original post by sprite_hound
It's probably better to use the SDL_BUTTON definitions than arbitrary numbers :)


Well, yeah... I mean if you want to write proper code sure, but who does that?! ;)
Pfft... proper code... *Starts rewriting input functions*

And to answer your lastest question, Sykth, I created a struct/class for my positions. I call it a Pair (who'd of thunk it) as it only contains two variables: an x and a y.

class/struct Pair{     int/double/whatever x;     int/double/whatever y;};class Unit{     Pair Position;     Pair Destination;};


The Pair can be a position, a destination, whatever. With this approach you only need one class/struct since you can just use the Pair class for both current positions and destinations. Hmm... now I'm not sure if I even answered your question. Oh well, let me know.

-Artum.
Hey artum,

thanks for input, ure struct idea really helped, ive managed to partially complete my unit class now and my baseBuilding class :)

I'm just using structs to contain the various x or y variables then assigning them to my mouse X and mouse Y variables.

So far its working out great :)

Now all i have to do is figure out how to draw the png image i got onto the SDL_surface i have created :) Although i have a fair idea how to do that anyways :)

I'm getting on the way to having a working prototype so thanks :D

One more question tho, in SDL should i have an setX and SetY AND a setXmapped and setYmapped, you know taking into account the screenWidth and screenHeight variables to make sure it gets copied correctly to my sdl surface ? Is this needed ? i got the idea from a QONK game and im not sure if i need it.


CHeers,

sykth
If I understand you correctly you're asking how to draw stuff to the screen.

So the way I do it is simple (in my head at least). Each unit has a X/Y coordinate. I created a Camera Class that holds one of my Pairs for its position as well. So, I've got a Unit Pair and a Camera Pair.

Normally when you blit a image to the screen you supply it with an X and Y value so it knows where to put the image. That's fine an dandy... but what if your camera has moved? DUN DUN DUN!

So lets say that Unit1's position is (50,50) and the camera is at (0,0). To draw the unit at (50,50) you'd just need to blit for (50,50).

Well, now lets say you've moved the camera to (100, 100). If you try and blit the unit's image at (50,50) you'll really be blitting it to (150,150). And that's no good. I'm a really bad teacher so I appologize if this doesn't make sense.

So what I do is this...
//handy-dandy drawing function/*Image is the image you are drawing to the Screen.x and y are the positions on the screen where you want to draw the image.*/DrawImage(SDL_Surface *Image, SDL_Surface *Screen, int x, int y){    SDL_Rect rect;    rect.x = x;    rect.y = y;    SDL_BlitSurface(Image, NULL, Screen, &rect);}//in use...DrawImage(Unit1Image, Screen, Unit1XPos-CamXPos, Unit1YPos-CamYPos);


You'll have to excuse my crappy code... it's crappy. I have no excuse, I'm just a bad programmer.

Anyway... as you can see when I use my DrawImage function I don't just give it my Unit's position. I actually give it my unit's position minus the camera's position. This offsets the unit so that when you move the camera the unit is adjusted to where it needs to be on the screen. In fact, everything I draw is offset by the camera's position: tiles, units, objects, everything. If you don't do this all of your objects will never move on the screen when you move your camera.

So no, you don't need to have two sets of positions for each unit. You just need to have one position for your unit and one position for your camera. Then offset the unit's position by the camera's position whenever you're drawing to the screen.

Man I hope that makes sense. Like I said, I'm not a good teacher. Nor am I the best programmer so take what I say with the biggest grain of salt you can find.

Let me know if this doesn't make sense so I can try and find you proper help.

-Artum.
Hey artum,

yeah i think i know what you are getting at, i have a player class that sets the frame++ when a direction is pushed, so i just have to pass the x and y coordinates from the "player location" to the draw image. (player loc is really just where the screen is centered at).

In terms of this unit code could you verify my changed code will actually send the current location of my unit, i hope it does but just wanted an expert to double check before i progress:

struct unitLocation
{
double x;
double y;
};

struct unitDestination
{
double unitXdest;
double unitYdest;
};

unitDestination unitDest;
unitLocation unitLoc;

///sets unitDest
void setUnitDestination(int mouseX, int mouseY)
{
unitDest.unitXdest = mouseX;
unitDest.unitYdest = mouseY;
}

double getXUnitLocation()
{
return unitXloc;
}

double getYUnitLocation()
{
return unitYloc;
}

// sets unitXlocation from the variable in the struct to the variable assigned later in the protected bit, is this right ?
void setXUnitLocation(int x)
{
unitLoc.x = unitXloc;
}


void setYUnitLocation(int y)
{
unitLoc.y = unitYloc;
}


IF this isn't right or im missing some code please let me know, i have a feeling its not just this simple, i mean where am i getting the x and y variables of the unit from ? im a tad confused lol :S

Cheers,


Sykth
Here is some changes you might find useful.
I made the accessor functions part of the Point2D struct's interface.
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;};// As long as a Location and a Destination is the same as a Point2D we can define them as suchtypedef Point2D Location, Destination;struct Unit{	Destination dest;	Location loc;};int main(){	Unit unit1;        ...	unit1.dest.setXY(mouseX, mouseY);        ...        // Artum's DrawImage with some changes        DrawImage(Image, Screen, unit1.loc.getX(), unit1.loc.getY());        // or if we make the x and y arguments to the DrawImage function a Point2D        DrawImage(Image, Screen, unit1.loc);}

This topic is closed to new replies.

Advertisement