Welcome, Guest. Please login or register.
Did you miss your activation email?

Login with username, password and session length

 
Advanced search

1075910 Posts in 44152 Topics- by 36120 Members - Latest Member: Royalhandstudios

December 29, 2014, 02:25:41 PM
  Show Posts
Pages: 1 ... 14 15 [16] 17 18 ... 67
301  Developer / Technical / Re: Your favorite scripting language on: March 02, 2012, 05:41:55 AM
The only scripting language I care for is bash.
302  Developer / Technical / Re: Suppressing terminal/command line? on: March 01, 2012, 12:35:30 PM
I was hoping to keep a single code base for all platforms,

I used to do that too, but then I realized that it's far easier to use a back-end/front-end system.  I keep a platform neutral back-end that probably contains 95% of my code, and write platform specific front-ends to interface with it.  Much easier to deal with in the long run.
303  Developer / Technical / Re: Suppressing terminal/command line? on: March 01, 2012, 05:48:45 AM
Be extremely cautious about using argv[0] for this sort of thing.  argv[0] is the command used to execute your program, which doesn't necessarily have anything to do with its location, or even the actual binary.

If someone makes a link or shortcut to your program and executes it using that, argv[0] will be the path to the link/shortcut.  This has burned me in the past.

The best Mac way I've found to switch to your resources directory is this:

Code:
NSFileManager *fm = [[NSFileManager alloc] init];
   
[fm changeCurrentDirectoryPath:[[NSBundle mainBundle] resourcePath]];

[fm release];
304  Developer / Technical / Re: Client-Server architecture for two player card-game. on: February 26, 2012, 02:37:28 PM
Can you create some graph or simple code showing how the approach works in practice? I'm currently developing a turn-based game too and I'd like to know how to implement this behaviour.

Here's some of the code, although it's in Ada so you may not completely understand it.

This is the interface that client-side connections implement:

Code:
-- Connection interface for the game client

with Franchise_Messages;
with Client_Processors;

use Franchise_Messages;
use Client_Processors;

package Client_Connections is
    pragma Preelaborate;

    -- Interface for connections used by the client.
    type Client_Connection is limited interface;
    type Client_Connection_Access is access all Client_Connection'Class;
    subtype NN_Client_Connection_Access is not null Client_Connection_Access;

    -- Send a message to the game server.
    not overriding
    procedure Send_To_Server(This: in out Client_Connection; M: in Message) is abstract;

    -- Set the object that will handle incoming messages.
    not overriding
    procedure Set_Processor(This: in out Client_Connection; P: in NN_Client_Processor_Access) is abstract;

    -- Get the connection's username.
    not overriding
    function Get_Name(This: Client_Connection) return String is abstract;
end Client_Connections;

The key operation here is Send_To_Server.  The client has a handle to something that implements this interface, and it just calls Send_To_Server with whatever message it wants to send.

This is the network based client connection:

Code:
-- Network connection at the client

with Ada.Finalization;
with Client_Connections;
with Franchise_Messages;
with Socket_Wrappers;
with Client_Processors;
with Message_Readers;
private with Ada.Strings.Unbounded;

use Ada.Finalization;
use Client_Connections;
use Franchise_Messages;
use Socket_Wrappers;
use Client_Processors;
use Message_Readers;

package Remote_Client_Connections is
    pragma Elaborate_Body;

    -- Network based connection to the server.
    type Remote_Client_Connection is new Limited_Controlled and
                                         Client_Connection with private;
    type Remote_Client_Connection_Access is access Remote_Client_Connection;

    -- Limited_Controlled overrides.
    overriding
    procedure Finalize(This: in out Remote_Client_Connection);

    -- Client_Connection overrides.
    -- Send a message via network socket to a server.
    overriding
    procedure Send_To_Server(This: in out Remote_Client_Connection; M: in Message);

    -- Set the processor for incoming messages.
    overriding
    procedure Set_Processor(This: in out Remote_Client_Connection;
                            P: in NN_Client_Processor_Access);

    -- Get this player's name.
    overriding
    function Get_Name(This: Remote_Client_Connection) return String;

    -- New operations.
    -- Set the socket to be used.
    procedure Set_Socket(This: in out Remote_Client_Connection'Class;
                         Socket: in Socket_Wrapper;
                         Reader: in Message_Reader := Null_Reader);

    -- Set the player's name.
    procedure Set_Name(This: in out Remote_Client_Connection'Class; Name: in String);

private
    use Ada.Strings.Unbounded;

    task type Socket_Monitor(Parent: access Remote_Client_Connection) is
        entry Start;
        entry Die;
    end Socket_Monitor;

    type Remote_Client_Connection is new Limited_Controlled and
                                         Client_Connection with
    record
        Monitor: Socket_Monitor(Remote_Client_Connection'Access);
        Socket: Socket_Wrapper;
        Processor: Client_Processor_Access;
        Reader: Message_Reader;
        Name: Unbounded_String;
    end record;
end Remote_Client_Connections;

This connection contains a socket and overrides Send_To_Server to dispatch on the socket.  It also contains a thread that monitors the socket for incoming messages and passes them to an object that I call a 'processor' that determines what to do with them.

Now this is the interface that the server connections use:

Code:
-- Interface to the server's connection objects

with Franchise_Messages;

use Franchise_Messages;

package Server_Connections is
    pragma Preelaborate;

    -- Interface for network connections at the server.
    type Server_Connection is limited interface;
    type Server_Connection_Access is access all Server_Connection'Class;

    -- Send a message to the client on the other end.
    not overriding
    procedure Send_To_Client(This: in out Server_Connection; M: in Message) is abstract;

    -- Get the client's name.
    not overriding
    function Get_Name(This: Server_Connection) return String is abstract;
end Server_Connections;

The important thing here is Send_To_Client, which forwards a message to whatever is on the other end.

Like Remote_Client_Connection, I also have a Remote_Server_Connection type that implements this interface with a socket and thread.  I'm not going to bother posting it, since it's not too terribly different from the other one.

This is the interesting one:

Code:
-- Local connection between the client and server

with Server_Connections;
with Client_Connections;
with Client_Processors;
with Franchise_Messages;
private with Ada.Strings.Unbounded;

use Server_Connections;
use Client_Connections;
use Client_Processors;
use Franchise_Messages;

package Local_Connections is
    pragma Elaborate_Body;

    -- Simulated network connection between a client and a local server.
    type Local_Connection is new Server_Connection and
                                 Client_Connection with private;
    pragma Preelaborable_Initialization(Local_Connection);

    -- Server_Connection overrides.
    -- Send a message to the player.
    overriding
    procedure Send_To_Client(This: in out Local_Connection; M: in Message);

    -- Get the player's in-game name.
    overriding
    function Get_Name(This: Local_Connection) return String;

    -- Client_Connection overrides.
    -- Send a message to the local server.
    overriding
    procedure Send_To_Server(This: in out Local_Connection; M: in Message);

    -- Set the message processing object.
    overriding
    procedure Set_Processor(This: in out Local_Connection; P: in NN_Client_Processor_Access);

    -- New operations.
    -- Set the player's name.
    procedure Set_Name(This: out Local_Connection'Class; Name: in String);

private
    use Ada.Strings.Unbounded;

    type Local_Connection is new Server_Connection and
                                 Client_Connection with
    record
        Name: Unbounded_String;
        Processor: Client_Processor_Access;
    end record;
end Local_Connections;

This is the connection used for local games.  Notice that it implements both Client_Connection and Server_Connection.  All this object does internally is pass messages between the two, no sockets or anything fancy are involved.  In practice, both the client and the server have handles to the same instance of this object for local games.

I know that was a lot of code, but that's really the best way I can come up with to explain it.

Quote from: dr.crow
And by the way: What kind of pattern did you use for method invocation? My intuition says some kind of command pattern probably is a good idea, but since we're programming in java, I'm also considering rmi, although I've never tried it before. Any experiences or suggestions?

My game logic is not object-oriented, so the patterns you mention don't really come into it.

All client-server communication is done with messages.  Messages contain a type identifier (chat, user join, move, etc...) and a set of key-value pairs containing additional information.  The server interprets the data in the messages, validates them (checking for illegal moves, and so on) and then sends messages to the clients that instruct them on what to do.  The clients receive these messages and then instruct the various screen elements on how to act.

For example, when a client makes a move, it sends a Move_Request message to the server with the desired move.  The server ensures that the move is legal, and if so it conducts the move on its own game state.  It then sends a Move message to all clients that contains the move and its results.  The clients read this message and do whatever is necessary to represent the move locally.

Centralizing the logic in the server allowed me to very easily implement a stand alone internet server.  In fact, my server has very little code of its own (mostly lobby stuff) and just shares most of the server code from the game.

Hopefully that all makes sense, but I will gladly answer any more specific questions.
305  Developer / Technical / Re: Client-Server architecture for two player card-game. on: February 26, 2012, 10:38:58 AM
I've just done this myself, and if I'm understanding your diagrams correctly, option 3 is what I went with.

I defined two interfaces, Server_Connection and Client_Connection that were responsible for delivering messages to wherever they had to go.

For clients, there are two implementations of Client_Connection, Local_Connection and Remote_Client_Connection.  Remote_Client_Connection sends messages through a TCP socket, while Local_Connection just passes them to the local server.

On the server side, Local_Connection does double duty, it actually implements both Server_Connection and Client_Connection, and in local games the client and server actually have handles to the same object.  Remote_Server_Connection handle TCP communication, and my game involves AI players, so servers may also have AI_Connections.

This approach worked beautifully for me.  I developed the game with just the Local_Connection, and when it came time to add network play I just dropped in the Remote_Connections with almost no issues.
306  Feedback / DevLogs / Re: Screenshot Saturday on: February 25, 2012, 03:57:01 PM


Looks funky because we don't have the unit models yet, and terrain still needs texturing.



My weekend project, just getting started.
307  Developer / Technical / Re: One .h for text rendering in OpenGL on: February 24, 2012, 02:43:06 PM

I could have also done:

Code:
// Option 1:
static void printf( const int X, const int Y, const char* Format, ... )

// Option 2
namespace {

Option 1 works but I don't fully understand why (i think it gives the same result as Option 2). Option 2 works by using an anonymous namespace essentially making a new function definition each time its included keeping the linker happy (I think).  If anyone can explain correctly why these work it would be most appreciated.


Declaring a top level entity static gives it internal linkage, it's not visible from outside the source file.  This is the C way of declaring file-local entities, and it's actually deprecated in C++, although it does still work.

The anonymous namespace is the C++ replacement for top level statics.  Entities in the anonymous namespace are still visible to the outside world, but they exist in a secret namespace known only to the compiler.  This gets you the practical effects of statics, but still allows exported templates to access the entities if necessary.  Since only two compilers (that I'm aware of) implement exported templates, and export was actually removed from C++2011, the distinction is less important than it used to be.  Top level statics are still deprecated though, and the anonymous namespace is just much cleaner overall than declaring a pile of things static.
308  Feedback / DevLogs / Re: Franchise: Single/multiplayer tactics game on: February 24, 2012, 12:07:22 PM
More of the same this week, single player testing and various bug fixes.

I only have four single player stages left to test.  I plan to get them all done next week, which will free up a lot more time for working on other things.

The usual download links:

Linux x86
Mac OS X (Intel only)
Windows
309  Developer / Technical / Re: One .h for text rendering in OpenGL on: February 24, 2012, 09:27:41 AM
This is not a very good header file at all.  If you #include this in more than one file, you're going to get linker collisions all over the damn place.

Code:
bash-4.1$ g++ file1.cpp file2.cpp
/tmp/cccdMl7a.o:(.data+0x0): multiple definition of `OGL::FontPageWidth'
/tmp/ccY07DR9.o:(.data+0x0): first defined here
/tmp/cccdMl7a.o:(.data+0x4): multiple definition of `OGL::FontPageHeight'
/tmp/ccY07DR9.o:(.data+0x4): first defined here
/tmp/cccdMl7a.o:(.data+0x8): multiple definition of `OGL::CharWidth'
/tmp/ccY07DR9.o:(.data+0x8): first defined here
etc...

You really need to split this into a header/source pair.  Oh, and you need to #include <cstring> to get strlen.  Also, your casing of the OpenGL header won't work on Unix systems.  Try #include <GL/gl.h>.  Macs need #include <OpenGL/gl.h>.
310  Developer / Technical / Re: Producing .exe by code on: February 22, 2012, 05:59:31 AM
Do Windows applications know-- or can they get-- their own file path? Is it safe to just open argv[0]? (For that matter, what about this same question on Linux?)

I believe that method works on both Windows and Linux.  I know it works that way on Linux.

Cheers,
Michael

This works for opening the binary itself, but be careful not to trust the directory path you get from argv[0].  If someone made a shortcut/link to your binary, the path will the be to the link, not to the original binary.  This has burned me in past when trying to locate my program's directory.

There are better, more reliable ways to find your binary than argv[0], such as the GetModuleFileName function in Windows.
311  Feedback / DevLogs / Re: Franchise: Single/multiplayer tactics game on: February 17, 2012, 11:40:21 AM
Once again, very little visible progress this week.  I'm almost done with single player testing, and I've fixed a few AI and pathing bugs and did a little bit of interface improvement.

The usual download links:

Linux x86
Mac OS X (Intel only)
Windows
312  Developer / Technical / Re: Next-Gen-Consoles, what do you expect? on: February 16, 2012, 08:46:26 PM
Something else I forgot, as a fighting game player I would love to see controllers that don't completely suck for fighting games.  We haven't had controllers like that since the Saturn.  I'm sort of tired of having to buy a secondary set of controllers for fighters.
313  Developer / Technical / Re: Next-Gen-Consoles, what do you expect? on: February 16, 2012, 09:44:54 AM
I love consoles, but I don't like the direction they've gone in.

I would like to see three major things:

1. A return to cartridges.  With the capacity of flash memory chips, I think it's time to drop optical disks.  They're too fragile, and long term lifespan is shaky.  Out of my 50 or so Sega Saturn games, I'd say at least 30% just don't work anymore, and I took pretty damn good care of them.  This would also reduce and probably eliminate the number of moving parts in a console, which should drastically increase its reliability.  My roughly 30 year old Atari 5200 still works perfectly, my 13 year old Dreamcast is slowly dieing.

2. Go back to just being a game console.  When I buy a game console, I just want something I can pop a game into and play.  I don't want a goddamn media center,  I don't want to have to make user accounts,  I don't want to fiddle with system settings.  I don't want hard drives and firmware updates and all that bullshit.  Insert game -> play.  It's pretty simple.

3. Get off the damn Internet.  Many people won't agree with this, certainly, but I don't want to have to deal with the Internet.  If I want to play a game on the Internet, I have a computer for that.  Once a console is on the Internet, suddenly everything needs it.  Keep the net off of my system.
314  Developer / Technical / Re: [C++] String's messing up order of its parts o.O //in hurry on: February 14, 2012, 03:41:53 PM
The only thing I can think of is that your nick string is being corrupted somehow with some control characters that affect printing, a carriage return, for example.

How do you obtain nick?  Have you tried using a hard coded value instead, like this?

Code:
std::string s = "data/players" + std::string("nick1212") + ".dat";

This might lend to support to the nick string's internals getting messed up somehow.  Is this a member function of some class?  If so, is nick a part of the object?  Try looking at the value of this to see if you have a null pointer or something.
315  Developer / Technical / Re: [C++] String's messing up order of its parts o.O //in hurry on: February 14, 2012, 03:23:47 PM
AFAIK you cannot use + operator on raw const char* strings which you have there. You'd need the first object to be a std::string.

It works as long as either operand is a std::string, there's an operator + defined for both combinations.

It would help if we knew what data type 'nick' was.
316  Developer / Technical / Re: Int or Float on: February 14, 2012, 12:33:53 PM
CDs have been largely replaced by digital.

That's quite a trick, considering that CDs are digital.
317  Developer / Technical / Re: A c++ approach to snake - 100 lines total - ncurses on: February 14, 2012, 12:32:21 PM
Code:
[quote author=SplinterOfChaos link=topic=24344.msg690200#msg690200 date=1329246097]
A) Are you sure that operator equal is required? After all, the fallowing definition works perfectly for me (compiles and runs).

std::vector requires both default constructability and operator =.  Keep in mind that compilers only tend to instantiate the parts of std::vector that you actually use, so if you aren't touching the functions that use operator =, you won't get an error.  In real world usage, you will almost certainly hit one.

Code:
B) If the only problem is need of an operator=, what's the problem with writing one?

What sensible operator = can you write for a object whose members are all constant?  An assignment operator is supposed to alter the left hand object's data, but you can't do that, they're constant.
318  Developer / Technical / Re: A c++ approach to snake - 100 lines total - ncurses on: February 14, 2012, 06:39:58 AM
The point is,
Code:
int GetX() const{...}
is practically not different from
Code:
const int x;
. Just because you write the same thing in other "more sophisticated" code, doesn't really mean it's different.

No, it's very different.  With const member variables the compiler can't generate an operator =.  This breaks a lot of things, in particular std::vector, since vector requires operator =.

Code:
bash-4.1$ cat main.cpp
#include <vector>

class Broken
{
public:
    Broken(int x, int y) : x(x), y(y) { }

private:
    const int x, y;
};

int main()
{
    Broken b1(1, 2), b2(2, 1);
    std::vector<Broken> vb;

    b1 = b2; // BROKEN
    vb.push_back(b1); // BROKEN
}

bash-4.1$ g++ main.cpp
main.cpp: In member function 'Broken& Broken::operator=(const Broken&)':
main.cpp:3:7: error: non-static const member 'const int Broken::x', can't use default assignment operator
main.cpp:3:7: error: non-static const member 'const int Broken::y', can't use default assignment operator
main.cpp: In function 'int main()':
main.cpp:17:10: note: synthesized method 'Broken& Broken::operator=(const Broken&)' first required here
bash-4.1$

The purpose of const member functions is to inform the compiler of which member functions can be used on constant objects.  This is very important as programs get larger, since it allows a much higher degree of error checking.  Without them, you couldn't have a const std::string, for example.

Code:
bash-4.1$ cat main.cpp
#include <iostream>

class Integer
{
public:
    Integer(int val) : val(val)
    {
    }

    int get_val() const { return val; }

    void set_val(int val) { this->val = val; }

private:
    int val;
};

int main()
{
    const Integer i(10);

    std::cout << i.get_val() << std::endl; // OK!  get_val is const.

    i.set_val(5); // ERROR!  i is a constant.
}

bash-4.1$ g++ main.cpp
main.cpp: In function 'int main()':
main.cpp:24:16: error: passing 'const Integer' as 'this' argument of 'void Integer::set_val(int)' discards qualifiers [-fpermissive]
bash-4.1$

const member functions and const member variables are pretty much completely unrelated.  I think you're confusing concepts.
319  Developer / Technical / Re: A c++ approach to snake - 100 lines total - ncurses on: February 14, 2012, 06:07:35 AM
Here are some things you should fix that others haven't mentioned:

Code:
#include <list>
#include <ncurses.h>
#include <cstdlib>
#include <ctime>

stdlib.h and time.h are C standard library headers.  While you can certainly use these, cstdlib and ctime are the proper C++ versions of these headers.  They contain some useful overloads of C functions, and more importantly they should wrap everything in namespace std.  (Some libraries do both).

Code:
class snake {
int getX() const { return x; }
int getY() const { return y; }
};
   

getX and getY should be tagged const since they don't modify the object.

Code:
int main() {
// Init
std::srand ( std::time(NULL) );

This is related to the header change above, srand and time should now be found in std.

Quote
If I recall, an underscore and a capital letter or two underscores at the beginning of a name hazards collision with system stuff.  Otherwise you should be okay.  I've had trouble with "_S", for instance

The actual rule is that any name beginning with an underscore followed by a capital letter, or containing (not just starting with) two consecutive underscores is reserved for the system.

Personally, I've always thought that if you want a way to identify member variables, why not just always prefix them with this-> ?  That way, the compiler can catch you if you're wrong.

Quote
Although I admit I don't use consts almost at all, I think you can add

Code:
const int x, y;

const member variables are almost always a bad idea because you break object assignment.  Declare a const Snake if you want one that can't change.
320  Developer / Technical / Re: "Correct" way to link OpenAL on Linux? on: February 13, 2012, 05:54:23 AM
Creative Labs made OpenAL closed source and proprietary at some point.  OpenAL Soft is an open source reimplementation of the current closed OpenAL.  As far as I know, it's the only current OpenAL you can get for Linux.
Pages: 1 ... 14 15 [16] 17 18 ... 67
Theme orange-lt created by panic