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 Today, 01:31 AM

#5238614 Setting variable typename after declaration

Posted by rip-off on 06 July 2015 - 08:37 AM

Any particular reason not to use an existing database solution? They've already solved a lot of the correctness / scalability issues you are likely to run into if you try to put a hand-rolled solution into production, along with coming with suites of monitoring, mining and backup tools.




#5238488 Setting variable typename after declaration

Posted by rip-off on 05 July 2015 - 05:04 PM

It is important to understand the distinction between compile time, link time and run time. Templates are resolved at compile time, though some toolchains delegate to the linker to generate the actual machine code. At run time all this has already been decided, you can't go back and change things now (aside from things like dynamically generating machine code or loading dynamic libraries).

I'd be interested in knowing what the actual contents of the file is as there might be alternative designs. For example, configuration data appears to have types but you can get away loading / passing a dictionary of strings to strings as the data structure, deferring the type conversion until you're actually applying the configuration to some internal state. Depending on how dynamic this data is supposed to be, maybe a scripting language is what you're really looking for.


#5237980 Java Integer and Double memory question

Posted by rip-off on 02 July 2015 - 06:11 AM

I'm not sure I'd accept that advice. In general comparing via equals() and compareTo() == 0 should be interchangeable. From the Comparable documentation:

The natural ordering for a class C is said to be consistent with equals if and only if e1.compareTo(e2) == 0 has the same boolean value as e1.equals(e2) for every e1 and e2 of class C. Note that null is not an instance of any class, and e.compareTo(null) should throw a NullPointerException even though e.equals(null) returns false.

It is strongly recommended (though not required) that natural orderings be consistent with equals. This is so because sorted sets (and sorted maps) without explicit comparators behave "strangely" when they are used with elements (or keys) whose natural ordering is inconsistent with equals. In particular, such a sorted set (or sorted map) violates the general contract for set (or map), which is defined in terms of the equals method.

For example, if one adds two keys a and b such that (!a.equals(b) && a.compareTo(b) == 0) to a sorted set that does not use an explicit comparator, the second add operation returns false (and the size of the sorted set does not increase) because a and b are equivalent from the sorted set's perspective.


As you allude to, the documentation explicitly calls out BigDecimal as a class that violates this (I'm not aware of a "Data" class):

Virtually all Java core classes that implement Comparable have natural orderings that are consistent with equals. One exception is java.math.BigDecimal, whose natural ordering equates BigDecimal objects with equal values and different precisions (such as 4.0 and 4.00).

This seems more like a design flaw in that class - the reasoning is interesting, but then having compareTo() ignore the precision seems confusing. As mentioned in one of the comments, an explicit method to compare including (or excluding) the precision would probably have been a better idea.

It would be a shame to complicate the rest of your code that probably doesn't even use such classes just because this one exception exists.

That said, perhaps a more interesting reason might be that if a class has a compareTo() method, the comparison has almost certainly been thought about (not always with inheritance), whereas you can call equals() on an unfamiliar class only to find it uses the default implementation from Object, which is not usually helpful.


#5237560 Avoid rewriting type to access member typedef

Posted by rip-off on 29 June 2015 - 02:43 PM

I've not used much of the most recent versions of C++, but the "using" keyword's recent upgrade might be worth looking into:

namespace some {
  namespace name {
    namespace space {
       template <typename T> struct Foo {
         typedef int SomeTypedef;
         SomeTypedef hi() { return 42; }
       };
    }
  }
}
 
struct Bar {};
 
int main() {
  using fubar = some::name::space::Foo<Bar>;
  fubar test;
  fubar::SomeTypedef stuff = test.hi();
}

 

There is also decltype, but it looks funky:

struct Bar {};
 
int main() {
  some::name::space::Foo<Bar> test;
  decltype(test)::SomeTypedef stuff = test.hi();
}



#5237087 Can't convert array of strings to char array

Posted by rip-off on 27 June 2015 - 07:27 AM

Here is an interesting one:
Menu::Menu( std::string mitem_source[] )
{
    // ...
    int stringcount = ( ( sizeof( mitem_source ) / sizeof( mitem_source[ 0 ] ) ) + 1 );
    // ...
}
In C++, arrays declarations for parameters aren't actually arrays, they are syntactic sugar for pointers. A real array's type encodes information about the arrays length, hence, sizeof(someArray) is the total size of the full array. Pointers lack such information, so sizeof(somePointer) is just the size of the pointer object, typically a machine address.

This, the sizeof(x) / sizeof(x[0]) trick does not work for array parameters, it can only work for local or global arrays.

A type safe trick in C++ is to use a template to extract the length of the array:
template<typename T, unsigned N>
unsigned array_size(T (&)[N]) {
    return N;
}
This will work with local / global arrays, but won't silently do the wrong thing with pointers or array parameters:
#include <iostream>

template<typename T, unsigned N>
unsigned array_size(T (&)[N]) {
    return N;
}

void example(std::string array[]) {
#if 0
    std::cout << "Parameter:" << array_size(array) << std::endl;
#endif
}

int main() {
    std::string array[5];
    example(array);
    std::cout << "Local: " << array_size(array) << std::endl;
}



#5235930 Get object from std::function

Posted by rip-off on 20 June 2015 - 03:55 PM

No official / safe way. There is no guarantee that a std::function is bound to an object, it could be bound to a free function.

A potential alternative, if the code is like your example, might be to modify it so that it is std::function<Foo &(int)>, and wrap the member function in something that returns the instance.


#5235906 Code crashing when exiting if statement

Posted by rip-off on 20 June 2015 - 01:40 PM

When you're leaving a scope, any temporary variables are destroyed. For complex objects, examples in your code include std::string, std::ifstream, the destructor will be called. For example, if you have corrupted a std::string's internal representation, there could be a crash when running it's destruction logic.

You need to be very careful when interacting with low level networking APIs, a bug like a Buffer Overflow could allow an attacker to remotely take control of the server and execute their own code!

For example here:
char decodedMessage[plength];
for(int v = 6; v<totalLen; v++)
    decodedMessage[v-6] = bigBuf[v] ^ mask[(v-6)%4];
string message = string(decodedMessage).substr(0,plength);
Are you sure that "decodedMessage" will be NUL terminated? As mentioned, you cannot rely on the client submitting a NUL terminator.


#5235193 Debugging problems

Posted by rip-off on 16 June 2015 - 03:40 PM

Debugging can change the behaviour of the memory allocators to help flush out certain types of bugs. However, the downside is that your program can end up depending on the behaviour of a debug allocator, which could be why you're seeing that behaviour.

Is is possible to link the library statically and check for a crash? Executables and DLLs on Windows can have separate heaps, possibly you're seeing something related to this?

Yet more ideas here: http://stackoverflow.com/questions/1010106/how-to-debug-heap-corruption-errors

Good luck!


#5235025 C++ normalize given epoch timestamp

Posted by rip-off on 16 June 2015 - 12:56 AM

Running in codepad.org (http://codepad.org/uTC5KjnF) and locally, I get 123379200. However, the "local" in localtime does hint what might be going on - time zones. I'm in UTC + 1. Using gmtime instead of localtime, I still get the expected value.


#5234658 2D Game Logic for a RTS

Posted by rip-off on 13 June 2015 - 04:05 PM

Game logic generally excludes rendering. That is, the path finding sub-system might be able to treat the map as a two dimensional grid. A hill might be represented by a movement penalty on that tile, which you might already have to represent other terrain (e.g. fording a river).

When you go to render the unit, the height of the terrain does need to be taken into account as you have noted. If you accept certain minor limitations to your maps, such as not having multiple "levels" available at the same position, then you can compute the 3D position of a 2D point by having a "height map", a 2D grid of the height values of the terrain. The 2D position can be used to lookup the height in the height map, which can be used to calculate the position of a given object.


#5234634 float value increment in a loop?

Posted by rip-off on 13 June 2015 - 12:58 PM

For anyone interested about Java error this generates:

Same basic issue, you must use 0.3f for a float literal.


#5233387 Serialize Object to specific directory

Posted by rip-off on 07 June 2015 - 11:47 AM

Are you asking how to determine the "project's folder"?

I guess the bigger question might be what are you trying to serialize, settings, save games, something else?


#5230927 1 (interface) header with 2 cpp (implementation) files?

Posted by rip-off on 25 May 2015 - 04:43 PM

Generally, this would not be considered idiomatic and could be confusing. Where possible, classes should be small and focused - having to spread the implementation across multiple files suggests this is not the case.

For my case this is a good solution.

It could be a fine solution. You don't want to spend infinite time designing and implementing your game, so at some point you have to put the pencil down.

Peripheral code, like a menu system, doesn't deserve the same amount time and attention to the core, which you'll be iterating on more and where poor design will slow you down more and more over time.

Separating into another class will create extra complexity with interfacing and continously sending data around from one class to another.

This is the crux of design, can you come up with a way of decoupling this data that you currently feel you need to "send around"?

I'd have to see some code to understand exactly what is going on, but it isn't immediately obvious to me why the menu and application need to interact so heavily. If you were to show us the header file, and outline which functions would be implemented in the different source files, we would really start to see your design.

For very simple games, a simple menu enumeration can suffice. There is nothing wrong with a few switch statements to call your main menu rendering logic, your audio settings rendering logic and having another switch in your menu event loop dispatcher - it gets the job done.

For games with a bit more going on, I've also used a simple "game state" model, the application delegates to the current state, e.g. update, render, handle input. The current state can return a new state at the end of each loop. The state could be an PlayIntroState, a MainMenuState, various other menu states, a LevelLoadingState and a PlayLevelState. With such a design, you might end up with a lot more classes / files, but each one is very simple and does just one thing. The application can be largely ignorant of the actual details of the states it is cycling through, once it has the initial state.

For complex games (which I don't write), I imagine you'll probably be configuring / scripting / skinning whatever menu systems the game engine provides you.


#5229303 Another basic array C problem

Posted by rip-off on 16 May 2015 - 08:40 AM

It is important not to be intimidated by the more complex interface of a modern and full-featured IDE like Visual Studio. It was a mistake I made when I was starting out. Having good tools is vital.

As for your program, there are definitely a few things the compiler should be noticing for you. Look into configuring your build tools to have a very high warning level (ideally, all warnings) and also to treat warnings as errors. Particularly as a beginner, any warning is very likely to be an issue you should fix.

When I compile your program (slightly modified for Linux), I get the following output:
$ gcc gamedev.c -Wall -Werror
gamedev.c: In function ‘main’:
gamedev.c:16:1: error: statement with no effect [-Werror=unused-value]
 temp[day][city];
 ^
gamedev.c:19:1: error: format ‘%d’ expects argument of type ‘int *’, but argument 2 has type ‘double *’ [-Werror=format=]
 scanf("%d",&temp[day][city]);
 ^
gamedev.c:37:8: error: character constant too long for its type [-Werror]
 switch('select'){
        ^
gamedev.c:38:1: error: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘double’ [-Werror=format=]
 case 'H':printf("\nHighest temperature is  %d in %d city in %d day",temp[1][1],j,i);
 ^
gamedev.c:40:1: error: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘double’ [-Werror=format=]
 case 'L':printf("\nLowest temperature is %d in %d city in %d day ",temp[5][3],j,i);
 ^
cc1: all warnings being treated as errors
These should be simple enough to fix, but see if you can configure your environment to give you a similar set of warnings - the exact warnings offered vary between compilers, do don't worry if you don't get them all or see other ones.

Be consistent with your formatting and indentation. It is hard to know because without the proper [code=auto:0] tags, much of the indentation was lost, but a simple example is where you place the curly braces after a loop or conditional statement. The two most common conventions are on the same line (possibly with whitespace preceding it), or on the next line. It doesn't matter which one you pick, but it does matter that you pick one and be consistent.

Also, another thing that will make your code easier to read is to use more whitespace around expressions. Again, the exact details can vary, but almost everyone would agree that this:
for(i=1;i<=MAXDAY;i++)
{
    for(j=1;j<=MAXCITY;j++)
    {
        if(temp[i][j]>=temp[i+1][j+1])
        {
            swap=0;
            swap=temp[i][j];
            temp[i][j]=temp[i+1][j+1];
            temp[i+1][j+1]=swap;
        }
    }
}
Is a bit harder to read than this:
for (i = 1; i <= MAXDAY; i++)
{
    for (j = 1; j <= MAXCITY; j++)
    {
        if (temp[i][j] >= temp[i + 1][j + 1])
        {
            swap = 0;
            swap = temp[i][j];
            temp[i][j] = temp[i + 1][j + 1];
            temp[i + 1][j + 1] = swap;
        }
    }
}
Typically I'd put a space between function parameters too, for example:
// Instead of:
printf("Day= %d City=%d ",day,city);
// Consider
printf("Day= %d City=%d ", day, city);
Even with all this, you won't have fixed everything, but you'll be much better placed to solve the remaining issue.


#5228125 Terrible Broken Age sales...!? (steamspy)

Posted by rip-off on 09 May 2015 - 09:47 AM

Have you watched the "Double Fine Adventure" documentary series? It is now available for free on Youtube, and there are entries that cover the initial release (in particular towards the end of EP 16 and start of EP 17). It's a fascinating documentary, worth a watch I think.

I believe humble bundles include DRM free versions, which could mean that not every HB sale can be counted against the Steam numbers - and the game is available on a bunch of other platforms too.




PARTNERS