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!


Khatharr

Member Since 24 Apr 2010
Offline Last Active Today, 12:18 AM

#5219893 How can I create a text based adventure game?

Posted by Khatharr on 28 March 2015 - 06:21 PM

A thread for the ages...




#5219777 Collision detection with triangles as the basis of all computer graphics…?

Posted by Khatharr on 27 March 2015 - 11:28 PM

I'm not sure what a "normal" is.

Is it possible to illustrate a very simple example of this concept?

 

A normal is a vector which is orthogonal (at a right angle) to another vector or plane. In a 2D space you can get a right-side normal as follows:

 

vector = {x, y}

normal = {-y, x}

 

Normals are used in a variety of calculations, especially collision and lighting. The reasons become clear when you study dot products and cross products, which can be found within the materials linked by jacmoe.




#5219776 VS2010: fatal error C1083: Cannot open source file

Posted by Khatharr on 27 March 2015 - 11:20 PM

Did they un**** intellisense in 2015?




#5219775 Global Consts

Posted by Khatharr on 27 March 2015 - 11:16 PM

Yeaaaaaaaaaaaah...

 

Anyway, if a constant relates to a specific class, make it a static const in the class. That's always handy because it's available directly within its own context and available publicly the same way it would be through a namespace:

class Foo {
public:
  static const int BAR = 42;
}

Foo::BAR; //is 42

Also, setting aside readability, avoiding magic numbers means that if you have to change the value at some point then you don't have to do the easter-egg hunt for all the relevant replacement positions. Even for trivial cases this can make sense:

const int ARY_SZ = 10;
int ary[ARY_SZ];
for(int i = 0; i < ARY_SZ; i++) {
  baz(ary[i]);
}

If you change the size of the array then you only have to change it in one place. In more complex code this can save a lot of heartache.




#5217998 C++ do while error

Posted by Khatharr on 20 March 2015 - 10:48 PM

It's not OOP's fault either, though. That's like picking up your car and carrying it to work and then complaining that cars are inefficient.

 

If someone tries to use OOP because of peer pressure rather than because it's the right tool for the job then the problem is with their peers and the response to those peers, not with OOP itself.




#5217216 How to Acess a singleton from everywhere?

Posted by Khatharr on 17 March 2015 - 06:01 PM

Ah, right. YOU SEE HOW THE POISON SPREADS?




#5216993 How to Acess a singleton from everywhere?

Posted by Khatharr on 16 March 2015 - 08:25 PM

So much static, so little reason for it...

 

Anyway, concerning ankhd's question: Maybe try something like this:

struct Foo {
  Foo() : var(10) {
    //nop
  }
  
  int var;
  SomeObjetNotStatic object;
};

main() {
  Foo foo;

  //then use from now on
  foo::object->doStuff();
}



#5216811 How to check application version with HTTP GET?

Posted by Khatharr on 16 March 2015 - 03:38 AM

Just use plain old TCP, write a client and server, and send some bytes back and forth.

 

Oh, I thought we deprecated TCP in favor of REST because of Parkinson's Law.

 

Seriously though, you could even just use UDP for something like this since the payload is more or less constant and is less than a packet in length.

 

OP says he's already got a web server running though, so his idea isn't really a bad one, since it doesn't really incur any additional overhead to speak of and it can easily be updated dynamically. That being the case, another +1 for libcurl here.




#5216805 Need help changing the date of a game

Posted by Khatharr on 16 March 2015 - 02:52 AM

The only real way to do this is to buy this neat program called "FIFA 15"

 

It's a trap! They'll just do the same thing again next year!




#5216736 Rate this number guessing game

Posted by Khatharr on 15 March 2015 - 05:10 PM

Hmm... Something wrong while building. brb

 

You do not include <string> anywhere, so Game.cpp can't build.

/********* main.cpp **********/
#include <iostream> //not used
#include "Game.h"

using namespace std; //not used - also sometimes not recommended

int main()
{
    Game game;

    game.initialize();
}

/**************** Game.h *****************/
#ifndef GAME_H_INCLUDED
#define GAME_H_INCLUDED

#include <string>

using namespace std; //do not 'using namespace' in the global scope of a header file: it forces the namespace on everything that includes the header.

class Game{
private:
    string playerName; //you do not #include <string> in this header. (see notes after code)
    int amountOfGuesses;
    void initializeDifficulty(int difficulty); //maybe "setDifficulty()"?
public:
    void initialize(); //constructors are for initialization
    void startGame(); //this name is not correctly descriptive
};


#endif // GAME_H_INCLUDED
// ^ good work on commenting this to match the opening clause

/**************** Game.cpp *****************/

#include <cstdlib>
#include <iostream>
#include "Game.h"

void Game::initializeDifficulty(int difficulty)
{
    while(amountOfGuesses == 0){ //what? why is this a loop? More importantly, why would the var be zero!?
            if(difficulty == 1) //use a 'switch()' here
                amountOfGuesses = 9;
            if(difficulty == 2) //why isn't this 'else if()' ?
                amountOfGuesses = 6;
            if(difficulty == 3)
                amountOfGuesses = 3;
            if(difficulty != 1 && difficulty != 2 && difficulty != 3)
                cout << "Invalid input, please try again." << endl; //this does not belong in this function
    }
}

void Game::initialize()
{
    int userInput;

    cout << "Hello there, let's play a number guessing game!" << endl << "What's your name?" << endl << "Name: "; //see notes after code on use of std::endl
    cin >> playerName;
    cout << "Hello, " << playerName << " do you want to play Easy (1), Normal (2) or Hard (3)?" << endl;
    cin >> userInput; //you need to sanitize input
    initializeDifficulty(userInput);
    startGame(); //does this belong here?
}

void Game::startGame()
{
    int userInput;
    int timesGuessed = 0;
    int randomNumber; //this could stand to have a better name - name should describe purpose rather than origin

    do{
      randomNumber = rand() % 25 + 1; //minor point - see notes on rand()
      cout << "Okey let's start " << playerName
           << " you need to guess a number between 1 and 25." << endl
           << "You may guess " << amountOfGuesses << " times max. Good luck!" << endl << endl;

      while(amountOfGuesses - timesGuessed > 0) { //inconsistent brace style
          cout << "You have still " << amountOfGuesses - timesGuessed << " chances left." << endl;
          cout << "Enter a number: " << endl;
          cin >> userInput; //sanitize input
          if(userInput == randomNumber)
              break;
          else{
              timesGuessed++;
              if(userInput > randomNumber)
                  cout << "That's too high try again" << endl;
              if(userInput < randomNumber) //'else if'
                  cout << "That's too low try again" << endl;
          }
      }

      if(userInput == randomNumber)
          cout << "Good job, you guessed my number in " << timesGuessed + 1 << " times" << endl;
      if(userInput != randomNumber) //'else if'
          cout << "You didn't guess my number in time. My number was " << randomNumber << endl;

      cout << "Do you want to play again (1) or quit (000)" << endl;
      cin >> userInput; //sanitize input
    } while(userInput != 000); //why '000'? (see notes after code)

}


Beginning with main.cpp:

 

You include <iostream> but do not make use of it. Probably this is because you were having trouble with Game.h, where you declare a std::string but don't include <string>. You state 'using namespace std', but there is no use of the std namespace here.

 

Game.h

 

You declare a std::string here, but don't include <string>. This can be a gotcha in VS because <iostream> prototypes std::string but does not define it. The result is that Game.cpp won't compile because there are missing operator overloads. I added the <string> inclusion to Game.h to make the project compile.

 

initializeDifficulty() is simply setting the values associated with difficulty. It may be more descriptive to call it 'setDifficulty()'.

 

Constructors are used to initialize classes. An initialize() member function is always a red flag. (see notes in Game.cpp section below)

 

startGame() is here, but it actually runs the whole game rather than starting it.

 

Game.cpp

 

Game::initialize() is not initializing the Game object. It's gathering user input and doing miscellaneous work, then calling the function that runs the game. It also does not sanitize its input, which I'll explain later. For now, you should probably rename this function to something like "get player data", and remove the call to startGame().

 

Game::initializeDifficulty() has several problems. For now let's correct the use of what's here:

  1. Why on earth is there a while() loop here? If the input is bad this creates an infinite loop of failure. If the input is good then the loop simply does not repeat. More importantly, if the value of amountOfGuesses is not zero to start with (protip: it's not zero) then this loop will NEVER RUN!
  2. You're printing out an error message to the user here, but this function is not intended for user interaction. The function should attempt to set the relevant value, and if it fails then it should return an error to the calling function. The calling function interacts with the user, so print the error message from there.
  3. You have a series of 'if()' statements that are logically exclusive. Use 'else if()' for this. In this instance it doesn't cause an error, but it does cause needless work. In slightly more complicated cases it can cause all kinds of errors.
  4. Research the use of the 'switch()' statement.

Game::startGame() uses a modulated rand() call. This application is trivial, so it's not a big deal, but modulating on rand() does not result in an even distribution. More importantly, you forgot to seed the randomizer, so it's likely that the number is going to be the same every time the program runs (http://puu.sh/gC3hR/494c867093.png). There's an excellent lecture on this by Stephan Lavavej here: http://channel9.msdn.com/Events/GoingNative/2013/rand-Considered-Harmful

 

Your brace style is inconsistent. You use hanging braces for functions and inline braces in other places. You may want to pick one and stick with it. (Personally I hate hanging braces, but they appear to be getting more popular.)

 

At the end of your loop you check for (userInput != 000). Do not add zeroes to things where they are not needed. This changes the type of the numeric value. In this case the value is the same, but if you had said 008, for instance, you'd have gotten a compiler error because a number starting with an extra zero is interpreted as a value in octal.  Also, boolean tests in C and C++ accept zero as false and non-zero as true. You can just say "while(userInput)", though in this case it makes sense to compare to zero explicitly because you're using zero as a token value from the user.

 

General Issues:

 

You use std::endl all over the place. That doesn't just insert a line-break. It also flushes the stream. When you're just printing out a boat-load of text, use the "\n" escape character to insert a new-line. Use std::endl when you are done with output and you want the buffer to flush before moving on to the next line.

 

You do not sanitize your user input! I can get this program to go crazy at almost any point by simply providing a string in a place where a number is expected. Try it out.

 

std::cin is kind of a pain in the butt in this case. Here's a function I use to get numbers from cin:

template<typename T>
T getUserValue(string requestString) {
  T retval;
  while(true) {
    cout << requestString;
    cin >> retval;
    bool ok = cin.good();
    cin.clear();
    cin.ignore(numeric_limits<streamsize>::max(), '\n');
    if(ok) {break;}
    cout << "Invalid response.\n";
  }
  return retval;
}

//usage:
int result = getUserValue<int>("Enter an integer: ");
float otherResult = getUserValue<float>("Enter a float: ");

See if you can sort out everything that's going on there and understand the pitfalls of std::cin and how this function deals with them.

 

Once the technical problems are corrected, let us know and we can talk about the overall program structure a little bit.




#5215200 Questions; adding elements to already existing games

Posted by Khatharr on 07 March 2015 - 04:54 PM

Where would you guys go to create something like this?

 

Prison?




#5214100 What are the recommended places to store save data?

Posted by Khatharr on 02 March 2015 - 10:14 PM

If custom and practice is any indication then the correct save location for Android is my root folder.

 

Of course you'll end up on my LIST if you do that.

 

...

 

Be told...




#5213021 Initialize vector of vectors after declaration.

Posted by Khatharr on 25 February 2015 - 10:36 PM

 

std::vector<std::vector<int> > myArray;

You must realize that this is quite improper.

You have used template of a variable memory type as another vector template type.

 

I don't know if I'd call it "improper". OP wants member containers of static length, so a std::array is better than a std::vector. A vector of arrays will be contiguous in memory, which is nice. However, sometimes you actually do want a variable-length container of variable-length containers, so a vector of vectors would make sense. The templates don't really have much to do with it. It's perfectly legal to nest template types.




#5213017 Read data from specified adress of memory.

Posted by Khatharr on 25 February 2015 - 10:04 PM

If it's a single value rather than an array of values then you can just cast it. In any case, he needs to put more effort into explaining what he's talking about before we should start trying to answer him.




#5213012 Read data from specified adress of memory.

Posted by Khatharr on 25 February 2015 - 09:09 PM

 

He doesn't want to read and write, he wants to read and write.


He doesn't want to "he doesn't want to read and write, he wants to read and write", he wants to "he doesn't want to read and write, he wants to read and write" with variables.

 

 

Dynamically.

 

(I think he's asking why he can't deref a void pointer.)






PARTNERS