Jump to content

  • Log In with Google      Sign In   
  • Create Account

Banner advertising on our site currently available from just $5!


1. Learn about the promo. 2. Sign up for GDNet+. 3. Set up your advert!


rip-off

Member Since 16 Mar 2005
Offline Last Active Yesterday, 01:19 AM

#4902283 C++ center command

Posted by rip-off on 13 January 2012 - 03:48 AM

What do you mean? Can't I just simply somehow put my text in the center of the console application?

The point being made is that standard, portable C++ does not make any assumptions about the nature of the standard output streams. They may not be consoles. They could also be files, sockets, printers, IPC devices such as pipes, the bit bucket or something more esoteric again. Not all of these have the concept of a fixed width which you could use to calculate a "center" from.

For instance, you can make std::cout a file in your program (shown here as foo.exe), by running it from cmd.exe like so:
C:\path\to\executable> foo.exe > output.txt
You can make std::cin a file using < input.txt too. It is also possible to redirect std::cerr, using 2>.

Running the entire program non-interactively and logging all output to standard streams could be done like so:

C:\path\to\executable> foo.exe < input.txt > output.txt 2> error.txt

Just FYI, you can also merge stdout and stderr output by using the following:

C:\path\to\executable> foo.exe > output.txt 2>&1

It is also possible to set up pipes to other processes, and that other program might print the data, send it across the network or do any number of things with it.

These interesting tricks aside, the proper solution is to use a console/terminal library, like ncurses.

However, as a beginner, assuming a fixed width console isn't all that bad, and you would be right in ignoring the "proper solution" for the time being and concentrating on learning the core language skills you will need.


#4901455 [SDL] How to recieve data from server correctly?

Posted by rip-off on 10 January 2012 - 05:44 PM

Looking at your code, there are a number of other things you need to fix before you can "recieve data from server correctly". Right now it just appears to work.

First of all, your code has minimal error checking. This will cost you in the long run, because someday each of these function calls are going to fail, and they'll fail silently. Even simply writing a line to a log file, indicating the function being called and the result of SDL_GetError() or SDLNet_GetError(), that would be much better because when your program crashes on someone else's machine, you'll have something you can look at to diagnose the issue.

The next step is to have proper error handling, where your program either gracefully handles minor errors, or perhaps shuts down cleanly (rather than unceremoniously crashing).

Your server doesn't handle multiple clients. Perhaps this is a legitimate design decision, because the game you are writing will only be two player. However, mostly you will want to manage multiple clients at the same time.

Another problem is that your program doesn't seem to handle TCP's stream-like behaviour. There is no guarantee that the data you give to a send() call will all come in a single recv() call. Due to TCP's internal buffering, you might get the first half of the data from one recv(), and the second half from the next. Or you might get the data from two send() calls in a single recv(). Or both! The only guarantee you do get is that the bytes will come out in the same order as you put them in.

Most games don't want to send a continuous stream, they want to send lots of individual messages. There are two common approaches to solving this, delimited messages and length prefixed messages.

For delimited messages, pick a byte (or sequence of bytes) as your delimiter. As you read data from the stream, move it into an application buffer. Any time the application buffer contains the delimiter, you have a full message that your application can process. Process the message, and then clear the message from the buffer (taking care to preserve any extra bytes you've received from the next message). Repeat while the client is sending you data. For example, a simple chat server might use the newline character as a delimiter. A more advanced chat server might choose the NUL character as a delimiter, allowing the user to send multi-line responses as a single message. This strategy is common in text formats, and rare with binary formats.

Length prefixed messages are as they sound, before you write a message, you write a few bytes beforehand, indicating the length of the next message payload. A simple example is to write a single byte of size, and then the message. For obvious reasons, this limits your message payload size to 256 bytes long. Or you might choose 2, 3, 4 or more bytes of length data, allowing messages of length 2^16 and 2^24, 2^32, etc. For many games, you won't need some of these longer limits. The process here is to read the N bytes that make up the length prefix first. You will need to be able to buffer a partial message prefix if you want to avoid blocking. When you have a full length prefix, you can attempt to read that many bytes into an application buffer, and send this buffer off for processing.

You could also do some application side buffering on the sending side - again if you don't want to block the sender. If you don't care about blocking you can keep trying to send until the OS finally accepts all your data into it's buffer. However, if blocking is a concern. and you detect that (another) call to send() would block, put any pending data in an outbound buffer. In particular, the remaining data from a partial send should be buffered, otherwise you can break your delimited data, causing the messages to leak together.

On the server, you might wrap the client TCP socket and associated buffers in a structure, which you would manage in a container.


#4901323 SDL vs SFML

Posted by rip-off on 10 January 2012 - 09:44 AM

The SDL 1.2 branch isn't undergoing active development of new features. New features are present in the less stable, more experimental SDL 1.3 branch. SDL 1.3 is set to bring hardware acceleration to platforms that have OpenGL or Direct3D backends.

SDL 1.2 is still supported for bug fixes. Only 4 days ago a PRERELEASE snapshot of SDL 1.2.15 has been announced to the SDL mailing list.

I hope that dispels your misconceptions.


#4901301 Problem Textbox

Posted by rip-off on 10 January 2012 - 08:31 AM

Yes. The alignment enum does not introduce a new name space, so the correct version would be Text::Centre rather that Text::Alignment::Centre.

I've actually gone and tested it this time:

text.hpp

#ifndef TEXT_HPP
#define TEXT_HPP

#include <string>
#include "SDL.h"
#include "SDL_ttf.h"

// Usually in a separate utility header
class noncopyable
{
protected:
        noncopyable() {}
private:
        // Deliberately private and unimplemented!
        noncopyable(const noncopyable &);
        noncopyable &operator=(const noncopyable &);
};

class Font : noncopyable
{
public:
        Font(const std::string &font, int size);

        ~Font();

        SDL_Surface *renderText(const std::string &text, const SDL_Color &colour) const;
        bool sizeText(const std::string &text, int &width, int &height) const;

private:
        TTF_Font *font;
};

class Text : noncopyable
{
public:
        enum Alignment
        {
                Left, Right, Centre
        };

        Text(Font *font);
        ~Text();

        void setText(const std::string &text);
        void setAlignment(Alignment alignment);
        void setColour(int r, int g, int b);

        void draw(SDL_Surface *screen, int x, int y);

private:
        Font *font;
        SDL_Surface *message;
        Alignment alignment;
        SDL_Color colour;
        std::string string;
};

#endif


text.cpp

#include "text.hpp"
#include <stdexcept>

Font::Font(const std::string &filename, int size)
{
        font = TTF_OpenFont(filename.c_str(), size);
        if(!font)
        {
                // Error handling
                throw std::runtime_error(std::string("Failed to open font: ") + filename);
        }
}

Font::~Font()
{
        TTF_CloseFont(font);
}

SDL_Surface *Font::renderText(const std::string &text, const SDL_Color &colour) const
{
        SDL_Surface *result = TTF_RenderText_Blended(font, text.c_str(), colour);
        if(result == NULL)
        {
                // Error handling
                throw std::runtime_error(std::string("Failed to render blended text: ") + text);
        }
        return result;
}

bool Font::sizeText(const std::string &text, int &width, int &height) const
{
        int result = TTF_SizeText(font, text.c_str(), &width, &height);
        return (result == 0);
}

Text::Text(Font *font)
:
        font(font),
        message(0),
        alignment(alignment)
{
        if(font == NULL)
        {
                // Error handling
                throw std::runtime_error("Cannot construct Text will NULL Font");
        }
        colour.r = 0;
        colour.g = 0;
        colour.b = 0;
}

Text::~Text()
{
        if(message)
        {
                SDL_FreeSurface(message);
        }
}

Uint8 sanitiseColour(int component)
{
        if(component < 0)
        {
                return 0;
        }
        else if(component > 0xff)
        {
                return 0xff;
        }
        return component;
}

void Text::setColour(int r, int g, int b)
{
        colour.r = sanitiseColour(r);
        colour.g = sanitiseColour(g);
        colour.b = sanitiseColour(b);
}

void Text::setText(const std::string &text)
{
        if(string == text)
        {
                return;
        }
        string = text;

        SDL_Surface *temp = font->renderText(string, colour);
        if(temp)
        {
                std::swap(temp, message);
                SDL_FreeSurface(temp);
        }
        else
        {
            throw std::runtime_error(std::string("Failed to render text: ") + string);
            // Error handling
        }
}

void Text::setAlignment(Alignment alignment)
{
        this->alignment = alignment;
}

void Text::draw(SDL_Surface *screen, int x, int y)
{
        if(!message)
        {
                return;
        }

        int width = 0;
        int height = 0;
        bool result = font->sizeText(string, width, height);
        if(!result)
        {
                // Error handling...
                throw std::runtime_error(std::string("Failed to size text: ") + string);
        }
        SDL_Rect destination = { x, y };
        switch(alignment)
        {
        case Left:
                destination.x = x - width;
                break;
        case Right:
                destination.x = x;
                break;
        case Centre:
                destination.x = x - width / 2;
                break;
        default:
                // Error handling...
                throw std::runtime_error("Unknown alignment");
                break;
        }

        if(SDL_BlitSurface(message, NULL, screen, &destination) < 0)
        {
                // Error handling
                throw std::runtime_error("Failed to blit text");
        }
}


main.cpp

#include <sstream>
#include <cstdlib>

#include "SDL.h"
#include "text.hpp"

int main( int argc, char* args[] )
{
        if( SDL_Init( SDL_INIT_EVERYTHING ) < 0 )
        {
                return 1;
        }

        std::atexit(&SDL_Quit);

        if( TTF_Init() < 0)
        {
                return 1;
        }

        std::atexit(&TTF_Quit);

        SDL_Surface *screen = SDL_SetVideoMode( 800, 600, 0, SDL_SWSURFACE);
        if(!screen)
        {
                return 1;
        }

        Font font("lazy.ttf", 16);
        Text text(&font);

        text.setColour(0xff, 0x00, 0x00);
        text.setAlignment(Text::Centre);
        text.setText("FPS: ?");

        int frames = 0;
        Uint32 previousTime = SDL_GetTicks();

        bool running = true;
        while(running)
        {
                SDL_Event event;
                while( SDL_PollEvent(&event) )
                {
                        if( event.type == SDL_QUIT )
                        {
                                running = false;
                        }
                        else if(event.type == SDL_KEYDOWN)
                        {
                            switch(event.key.keysym.sym)
                            {
                            case SDLK_DOWN:
                            case SDLK_UP:
                                text.setAlignment(Text::Centre);
                                break;
                            case SDLK_LEFT:
                                text.setAlignment(Text::Left);
                                break;
                            case SDLK_RIGHT:
                                text.setAlignment(Text::Right);
                                break;
                            case SDLK_ESCAPE:
                                running = false;
                                break;
                            }
                        }
                }

                ++frames;
                Uint32 now = SDL_GetTicks();
                if(now - previousTime > 1000)
                {
                        std::stringstream stream;
                        stream << "FPS: " << frames;
                        text.setText(stream.str().c_str());
                        frames = 0;
                        previousTime = now;
                }

                SDL_FillRect(screen, 0, 0);                
                text.draw(screen, screen->w / 2, screen->h / 2);

                if( SDL_Flip( screen ) < 0 )
                {
                        return 1;
                }
        }

        return 0;
}


Not exhaustively, mind you. I threw in some very rudimentary error handling. I'm using lazy.ttf from here. I've also added a way to dynamically change the alignment, using the cursor keys.


#4901266 SDL vs SFML

Posted by rip-off on 10 January 2012 - 05:48 AM

sdla is depricated unsupported and doeant support hardware exceleration... Teaching yourself to use outdated software will more than likely just teach you bad habits.

SDL is not deprecated, nor unsupported. SDL supports certain classes of hardware acceleration - though these are becoming more and more irrelevant, and are no longer defaults. However, it does allow you to get an OpenGL context very easily, and from there you have all the hardware acceleration you could want. SDL is far more portable than SFML. SDL is also much maturer than SFML. SFML is a C++ API, whereas SDL has bindings to most popular languages.

There are plenty of legitimate reasons to continue using SDL. It will not teach you bad habits.


#4900991 What are the evils of "using namespace std;"

Posted by rip-off on 09 January 2012 - 11:28 AM

They should never be used in a header because there is no way to "un-use" a namespace.

In addition, SiCrane has often mentioned a specific problem where the order of inclusion, combined with a using declaration, caused the meaning of the code to change. Unfortunately I cannot find a reference for this at the moment.


#4900982 Multi Threading

Posted by rip-off on 09 January 2012 - 10:56 AM

If you are new to programming the very last thing you should be doing is thinking about multi-threading. Seriously - I do not mean to put you down, even advanced programmers have difficulty designing multi-threaded systems that are correct.

As for your question, by using the synchronized keyword inside the function body, one can be more explicit about the object being locked*. You can also reduce the area being locked to less than the entire function. Typically, you might only have a couple of lines that need co-ordination.

And no, threads don't move onto another method while the lock is held. Each thread blocks on the lock, causing them to stop running until the thread using the lock has relinquished it.

Even advanced programmers try to use higher level patterns (such as futures, thread pools, concurrent data structures) rather than trying to write things in terms of low level locking. For this reason, again I would advise you write non-multi-threaded programs first. The book is perhaps too advanced for you at the moment.

* Locking an arbitrary, publicly visibly object is dangerous and can lead to deadlocks if not handled carefully. A common idiom is to have a private final Object lock = new Object(), and synchronise on that.


#4900029 C++ Remove - deleting a file

Posted by rip-off on 05 January 2012 - 11:49 AM

When you open a file to write, it clears it. Then you try to delete it. According to the link you gave, remove() returns 0 on success. So your condition is wrong. Remove might not work because on some runtimes/operating systems, the file is "locked" while it is open.

Why even check if the file exists? Let the remove() function do that too!

Consider the following instead:
if(remove(fileName.c_str()) == 0) {
    output("Deletion successful\n");
} else {
    output("Deletion unsuccessful\n");
}



#4899554 Handling sprite (array or vector)

Posted by rip-off on 04 January 2012 - 05:37 AM

Don't use linked lists, regardless of how "groovy" they might appear, unless you have proof that they actually are what you want. For common usage patterns, a dynamic array will often have superior performance, even where one might not expect it due to the algorithmic complexity theory.

The algorithmic complexity theory is great, but it only makes sense for large N (typically, millions or more). For small N (like the thousands the OP is handling), the constants that are assumed by the theory to become irrelevant actually become more and more important - in some cases they can dominate. This is where you might often find the cache friendly vector outperforming linked lists for many operations on the kinds of data sets your program can handle.

Don't forget that a linked list implementation requires two algorithms, you have the basic linked list algorithm and the memory management algorithm. The latter is often ignored in highly theoretical discussions, but again it can make a massive difference.

Likewise, the dynamic array complexity ignores techniques like the "remove/erase idiom", which is often suitable for "bag" like data structures (append only, random remove). If the order is irrelevant, you can also use the "swap and pop" trick too.

Most games do not feature millions of sprites, because it would make the game unplayable. As such, you don't have to design the game to work with millions of sprites. If your game is working fine at the expected level of activity on the target hardware, you can stop. However, if you hadn't implemented, for example, collision and you went on to find that you aren't getting the required performance with either linked lists or vectors, you might need to reach for a more complex data structure, such as a spatial based one.


#4899216 Sharing a socket between processes VC++

Posted by rip-off on 03 January 2012 - 05:30 AM

I don't believe your approach will work. WSADuplicateSocket is intended for socket handoff, not socket sharing:

The descriptors that reference a shared socket can be used independently for I/O. However, the Windows Sockets interface does not implement any type of access control, so it is up to the processes involved to coordinate their operations on a shared socket. Shared sockets are typically used to having one process that is responsible for creating sockets and establishing connections, and other processes that are responsible for information exchange.

Maybe this is what you want to do?

If not, a simple solution to the original problem to that is to to have the secondary servers connect to the primary one, and have the primary one demultiplex the data as it comes in (however you propose to handle that) and copy it to the correct "local" connection to the secondary server.

One approach might be for the secondary server to connect to the problematic socket, and identify itself as a server somehow. The primary server would echo data back out that socket when it is intended for this sub-server. Another might use a local IPC mechanism, like a named pipe, to connect to the primary server, not unlike what you were trying to do with the socket description, but with the actual data instead.

That said, this is still highly unusual. Multiplexing connections like that is generally handled at a different level (e.g. a SSH tunnel), if it is indeed necessary at all.


#4898749 Java Game Programmer

Posted by rip-off on 01 January 2012 - 02:06 PM

60 fps is plenty - users will not be able to see any visual difference above this frame rate. The frame rate is probably vsync capped anyway. Either way, it is not a conclusive argument against using Java for games.

Generally one does not use AWT for games (unless they are the kind that lend themselves particularly to such a "standard" GUI, or a prototype). There are many libraries or frameworks which allow you to use Java with something like OpenGL for rendering.


#4897496 I'm currently working on a C-Like scripting language.

Posted by rip-off on 26 December 2011 - 03:40 PM

You can write game logic with C, but the whole reason I'm working on this project is for fun, really. The way I plan on implementing it into a project is by putting scripts into the map BSP, or allowing users to make mods.

Ok, I think I understand your design reasons a bit better now.

Besides more access to the memory, this scripting language will not make it easily possible to do something malicious.

Sure, but I believe you'll have your work cut out for you. Once you have relatively unrestricted access to memory, the script can easily crash the host application accidentally.

Well, I guess with some of the built in functions, you could theoretically delete system files...

If one is a malicious hacker (e.g. you can include scripts in custom maps that are then downloaded peer to peer) you have huge amounts of choice for exploiting the host. Not just deleting critical system files. One could drop some kind of system on the remote client.

... but I might add in some security to prevent things like that from happening.

It will be very difficult to sandbox the script in an a safe manner. It isn't realistic to believe you can just "add some security", the overall architecture of your application would need to be thought about carefully if you want to actually secure your application.


#4896274 [Java] Detecting collision between rectangles between classes

Posted by rip-off on 21 December 2011 - 01:34 PM

Something like this:
public class Main extends BasicGame{

    int px = 100, py = 100;
	
	private List<Entity> entities = new ArrayList<Entity>();
	
    Rectangle player = new Rectangle(px, py, 16, 16);
        
	public Main() {
		super("Test");
	}
        
	public static void main(String[] args) throws SlickException{
		AppGameContainer app = new AppGameContainer(new Main());
		app.start();
	}

	@Override
	public void render(GameContainer gc, Graphics g) throws SlickException {
		for(Entity entity : entities) {
			entity.render(gc, g);
		}
		
		g.drawString("X:" + player.getX() + "\nY: " + player.getY(), 10, 40);
		//Draw player
		g.drawRect(px, py, 16 ,16);
    }

	@Override
	public void init(GameContainer gc) throws SlickException {
		Entity m1 = new Entity("Monster1", 100, 400, 200);
		entities.add(m1);
		
		Entity m2 = new Entity("Monster2", 100, 550, 200);
		entities.add(m2);
		
		Entity m3 = new Entity("Monster3", 100, 500, 300); 
		entities.add(m3);
	}

	@Override
	public void update(GameContainer gc, int arg) throws SlickException {
		// Movement
		if(Keyboard.isKeyDown(Keyboard.KEY_W)) py -= 0.1;
		else if(Keyboard.isKeyDown(Keyboard.KEY_S)) py ++;
		else if(Keyboard.isKeyDown(Keyboard.KEY_D)) px ++;
		else if(Keyboard.isKeyDown(Keyboard.KEY_A)) px -= 0.1;
		
		player.setX(px);
		player.setY(py);
		
		// Collision
		boolean collision = false;
		for(Entity entity : entities) {
			if(player.intersects(entity.r)){
				collision = true;
				break;
			}
		}
		
		if(collision) {
			System.out.println("Collision");
		} else {
			System.out.println("No collision");
		}
	}
}
I would recommend you research about containers, as they are the building blocks you'll need for any complex program.


#4896107 Critical library design question

Posted by rip-off on 21 December 2011 - 03:22 AM

It is an arbitrary convention. You might as well toss a coin.

I prefer +Y meaning UP, because it matches with standard mathematics. Then again, I like to use the centre of the screen as my origin, which I find convenient for doing small test programs (you need to do almost no work to get stuff drawn in the middle of the screen).


#4895709 Copying Legal Stuff

Posted by rip-off on 20 December 2011 - 08:17 AM

Don't write your own license, unless you are a lawyer.

Licences themselves fall under copywrite (unless you can find evidence to the contrary, e.g. that they have been donated to the public domain). For example, the wikipedia has a short section with regards to the copyright on the GPL:

The text of the GPL is itself copyrighted, and the copyright is held by the Free Software Foundation. However, the FSF does not hold the copyright for a work released under the GPL, unless an author explicitly assigns copyrights to the FSF (which seldom happens except for programs that are part of the GNU project). Only the individual copyright holders have the authority to sue when a license violation takes place.

The FSF permits people to create new licenses based on the GPL, as long as the derived licenses do not use the GPL preamble without permission. This is discouraged, however, since such a license might be incompatible with the GPL.[39] and causes a perceived license proliferation.
Other licenses created by the GNU project include the GNU Lesser General Public License and the GNU Free Documentation License.

Emphasis added.




PARTNERS