making a pokemon game

Pages: 123
Mar 1, 2012 at 7:49pm
i have a class for pokemon, player, and attacks.

this is my player data structure

class player
{
public:

Pokemon Pokemon[6]; //array to hold 6 pokemon in your party
};


heres the class for the pokemon

class pokemon
{
public:

Attacks Attacks[4]; //array to hold 4 attacks
};


class attacks
{
public:
int power;
int pp;
int accuracy;

};

what is the best way to create attack objects and store them in the array in the pokemon class?
Mar 1, 2012 at 7:56pm
Well, you could create them dynamically, but since you have a set limit on how many you want to create, you could just do something like:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int main()
{
    attacks att1, att2, att3, att4;
    pokemon pok1;
    player ply1;

    att1.power = 50;
    att1.pp = 5;
    att1.accuracy = 85;
    pok1.Attacks[1] = att1;
    ply1.Pokemon[1] = pok1;

    ...
    ...
}
Mar 2, 2012 at 4:23am
what if i say do this?

attack Ember;
Ember.power=40;

how would i store that and call it during the battle loop?

not looking for you to do my work just need to be pushed in the right direction. any help is appreciated! :)
Mar 5, 2012 at 6:43pm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#include <iostream>
#include <string>

struct attack
{
    std::string name;
    int power;
    int pp;
    int accuracy;
} att1, att2, att3, att4; // make 4 attack slots e.g "attack att1"

struct attack_ember: public attack
{
    attack_ember() // constructor
    {
        name = "Ember";
        power = 40;
        pp = 30;
        accuracy = 95;
    }
} ember; // the same as "attack_ember ember"

struct attack_hydropump: public attack
{
    attack_hydropump()  // constructor
    {
        name = "HydroPump";
        power = 120;
        pp = 5;
        accuracy = 75;
    }
} hydropump; // the same as "attack_hydropump hydropump"

int main()
{
    att1 = ember; // initialize values of att1(name, power, pp, accuracy) with the constructor values of attack_ember.
    att2 = hydropump; // initialize values of att2(name, power, pp, accuracy) with the constructor values of attack_hydropump.

    std::cout << att1.name << ": " << att1.power << " power" <<  std::endl; // ember on slot 1
    std::cout << att2.name << ": " << att2.power << " power" <<  std::endl; // hydropump on slot 2

    att1 = hydropump; // make slot 1 hydropump
    att2 = ember; // make slot 2 ember

    std::cout << att2.name << ": " << att2.accuracy << " accuracy" << std::endl; // hydropump on slot 1
    std::cout << att1.name << ": " << att1.accuracy << " accuracy" <<  std::endl;  // ember on slot 2
}


hope that helps, took me a while to figure it out, good fun doing it though.
Last edited on Mar 5, 2012 at 6:43pm
Mar 5, 2012 at 6:50pm
You're kind of missing the point of classes and inheritance. That's a very bad example.
Mar 5, 2012 at 8:18pm
why is it a bad example? from what I know, classes are just a kind of structure, heck just change it to work with classes instead of structures if it is so bad, I used structures because I found it simpler.

but I really would love an explanation as to why it is a bad way of doing it.
Last edited on Mar 5, 2012 at 8:20pm
Mar 5, 2012 at 8:25pm
Because the point of an object is that you can create a type of object, such as an attack. Then you can create multiple instances of that object that have different characteristics such as the names being different from one another, or the power, pp or accuracy.

Like with a pen. My pen is black with a silver tip. It has a soft ridged grip, writes with black ink, and is a click pen. Each of those are characteristics of my pen. You probably have a different pen. It might be a twist or a fountain pen. It might write in blue ink, or it could be a quill type that writes in whatever color it's dipped in. It could be gold on the outside, but it's still a pen.

That's the point of classes/structs. You define what types of characteristics that the pen has, like mBarrelColor, mInkColor, mClip, mWritingType, mSize, etc.

Then each instance of pen has slightly different values for each of those characteristics.

EDIT: Grammar
Last edited on Mar 5, 2012 at 8:25pm
Mar 5, 2012 at 8:44pm
How did my code before not do that? you can make any number of new attack_xyz structures and then define different objects of the attack structure to have the same values for their attributes. in any case, here it is but with classes.

Unless I've misunderstood why he wanted to be able to just say [attack att1; att1 ember;] instead of [attack att1; att1.name = "Ember"; att1.power = 40; att1.pp = 30; att1.accuracy = 95;]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#include <iostream>
#include <string>

//http://www.cplusplus.com/forum/general/63358/

class attack
{
public:
    std::string GetName() {return name;} //loads of Get's and Set's, use accordingly.
    int GetPower() {return power;}
    int GetPP() {return pp;}
    int GetAccuracy() {return accuracy;}

    void SetName(std::string n) {name = n;}
    void SetPower(int x) {power = x;}
    void SetPP(int x) {pp = x;}
    void SetAccuracy(int x) {accuracy = x;}
private:
    std::string name;
    int power;
    int pp;
    int accuracy;
} att1, att2, att3, att4; // make 4 attack slots e.g "attack att1"

class attack_ember: public attack
{
public:
    attack_ember() // constructor to set values of parent object
    {
        attack::SetName("Ember");
        attack::SetPower(40);
        attack::SetPP(30);
        attack::SetAccuracy(95);
    }
} ember; // the same as "attack_ember ember"

class attack_hydropump: public attack
{
public:
    attack_hydropump()  // constructor to set values of parent object
    {
        attack::SetName("HydroPump");
        attack::SetPower(120);
        attack::SetPP(5);
        attack::SetAccuracy(75);
    }
} hydropump; // the same as "attack_hydropump hydropump"

int main()
{
    attack att1;

    att1 = ember; // initialize values of att1(name, power, pp, accuracy) using the attack_ember constructor
    att2 = hydropump; // initialize values of att2(name, power, pp, accuracy) using the attack_hydropump constructor

    std::cout << att1.GetName() << ": " << att1.GetPower() << " power" <<  std::endl; // ember on slot 1
    std::cout << att2.GetName() << ": " << att2.GetPower() << " power" <<  std::endl; // hydropump on slot 2

    att1 = hydropump; // make slot 1 hydropump
    att2 = ember; // make slot 2 ember

    std::cout << att2.GetName() << ": " << att2.GetAccuracy() << " accuracy" << std::endl; // hydropump on slot 1
    std::cout << att1.GetName() << ": " << att1.GetPP() << " PP" <<  std::endl;  // ember on slot 2

}
Last edited on Mar 5, 2012 at 8:47pm
Mar 5, 2012 at 8:51pm
This:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class attack
{
private:
    std::string mName;
    int mPower, mPP, mAccuracy;
public:
    attack(const std::string& inName, int inPower, int inPP, int inAccuracy);
    ~attack() {}
};

attack::attack(const std::string& inName, int inPower, int inPP, int inAccuracy)
{
    mName = inName;
    mPower = inPower;
    mPP = inPP;
    mAccuracy = inAccuracy;
}

int main()
{
    attack *att1 = new attack("HydroPump", 120, 5, 75);
    attack *att2 = new attack("Ember", 40, 30, 95);

    ...
    delete att1;
    delete att2;
    return 0;
}
Last edited on Mar 5, 2012 at 8:52pm
Mar 5, 2012 at 9:04pm
I wouldnt even use inheritance in this, its not needed, just a simple class that has pointers to another class would work because you arent going to be changing the accuracy/power of each ability, just maybe add modifiers in combat, therefore you can just use a constant for each attack eg:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
class Attack
{
public:
	Attack (int, int, int);
	int power,
		pp,
		accuracy;
}

constant Attack Hydropump (120, 5, 75),
	Ember (40, 30, 95),
	Splash (0, 15, 0),
	Dig (90, 20, 90);

class Pokemon
{
	Pokemon (Attack, Attack, Attack, Attack);
	
	Attack *attack1,
		*attack2,
		*attack3,
		*attack4;
	
	int offense,
		defense,
		specOffense,
		specDefense,
		pp; //OG blue/red stats :P
	
	double health;
	
} Blastoise (Hydropump, Ember, Splash, Dig);
Mar 5, 2012 at 9:15pm
:b that looks amazingly nice and clean compared to what I wrote, however there are errors, did you try and compile it beforehand?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include <iostream>
#include <string>

class Attack
{
public:
	Attack (int, int, int);
	int power,
		pp,
		accuracy;
}

constant Attack Hydropump (120, 5, 75),
	Ember (40, 30, 95),
	Splash (0, 15, 0),
	Dig (90, 20, 90);

class Pokemon
{
	Pokemon (Attack, Attack, Attack, Attack);

	Attack *attack1,
		*attack2,
		*attack3,
		*attack4;

	int offense,
		defense,
		specOffense,
		specDefense,
		pp; //OG blue/red stats :P

	double health;

} Blastoise (Hydropump, Ember, Splash, Dig);

int main()
{
    std::cout << Blastoise.attack1->power;
}


I believe I did that right (Blastoise.attack1->power;)

1
2
3
4
5
6
7
8
9
|13|error: expected initializer before 'Attack'|
|35|error: 'Hydropump' was not declared in this scope|
|35|error: 'Ember' was not declared in this scope|
|35|error: 'Splash' was not declared in this scope|
|35|error: 'Dig' was not declared in this scope|
||In function 'int main()':|
|22|error: 'Attack* Pokemon::attack1' is private|
|39|error: within this context|
||=== Build finished: 7 errors, 0 warnings ===|
Mar 5, 2012 at 9:17pm
You can't access it...it's private.
Mar 5, 2012 at 9:22pm
herpa derp

and no i did not compile it, im texting this from my phone :)

i can when i get home if u cant get it to work still

plus i did not finish the constructors, you would have to do something like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#ifndef PKMN_H
#define PKMN_H

constant Attack Hydropump (120, 5, 75),
	Ember (40, 30, 95),
	Splash (0, 15, 0),
	Dig (90, 20, 90); //can add more constants here, just moved it to the top

class Attack
{
public:
	Attack (int, int, int);
	int power,
		pp,
		accuracy;
}

Attack::Attack(int pow, int pp, int ac)
{
	this->power = pow;
	this->pp = pp;
	this->accuracy = ac;
}

class Pokemon
{
public:
	Pokemon (Attack, Attack, Attack, Attack); //you could add arguements for stats :/
	
	Attack *attack1,
		*attack2,
		*attack3,
		*attack4;
	
	int offense,
		defense,
		specOffense,
		specDefense,
		pp; //OG blue/red stats :P
	
	double health;
	
} Blastoise (Hydropump, Ember, Splash, Dig); //just an example, should be deleted for real use

Pokemon::Pokemon (Attack one, Attack two, Attack three, Attack four) //you would also have to add those stat args here (from the class constructor line)
{
	this->attack1 = &one;
	this->attack2 = &two;
	this->attack3 = &three;
	this->attack4 = &four;
}

#endif 


now put all that in a header, and you can #include "YourHeader.h"

and you can just create new pokemon via:

Pokemon Charizard (Fly, FireBreath, BodySlam, Ember)

assuming you make constants for those abilities, then something like this:

1
2
3
4
Charizard->offense = 80;
Charizard->defense = 95;
Charizard->specOffense = 110;
Charizard->specDefense = 75;


come to think of it, you could actually make the stats short ints
and also come to think of it, you definately should not do this as two classes extending each other because then the initializer for the attack class will be called every time the initializer for the pokemon is called, making the a combination (attack+pokemon) object, which would be kinda retarded :/
it should only be done with things that are also something else, for example:

class Boss is a type of unit
class FootSoldier is another type of unit

BUT

since they are both types of units, they both extend the base unit class Unit

but although they contain data for other classes like location class Loc they do not extend it, get it?
Last edited on Mar 5, 2012 at 9:51pm
Mar 5, 2012 at 9:25pm
I realize that, cipher, that isn't the real problem as making it public is easy enough, I meant the errors before that, expected intializer before Attack, and the arguments of the Blastoise object not being declared.

I can't personally get it to work, me and pointers don't share the same brain cells, not yet anyway, hence why I mentioned (Blastoise.attack1->power;) as I've never done that before.
Mar 5, 2012 at 9:29pm
constant
doesn't mean anything.
1
2
3
4
const Attack Hydropump (120, 5, 75),
	Ember (40, 30, 95),
	Splash (0, 15, 0),
	Dig (90, 20, 90);
Mar 5, 2012 at 9:29pm
That doesn't fix any of the errors.
Mar 5, 2012 at 9:32pm
Why don't you just do it the way I showed you?
Mar 5, 2012 at 9:36pm
I don't like the way you did it, dynamic memory and inability to pre-fill the variables of moves.

Edit:

Gfreak, moving them to the top only makes it worse, since the compiler doesn't know what "Attack" is. and I'm pretty certain that you can't do

1
2
3
4
const Attack Hydropump (120, 5, 75),
	Ember (40, 30, 95),
	Splash (0, 15, 0),
	Dig (90, 20, 90); //can add more constants here, just moved it to the top 


inside the global scope, it will have to be in a function or class.
Last edited on Mar 5, 2012 at 9:40pm
Mar 5, 2012 at 9:38pm
closed account (zb0S216C)
This thread is starting to turn into a bit of a war on who's code is better.

Wazzak
Mar 5, 2012 at 9:38pm
Then change
attack *att1 = new attack("HydroPump", 120, 5, 75);
to
attack att1("HydroPump", 120, 5, 75);
Pages: 123