Name: Anonymous 2014-08-06 8:14
Okay I hope I'll get some comments on this project I've been working on. Usually /prog/ doesn't comment on my code and that sucks.
Summary: I want to write a card game like Tetra Master from FFIX (see https://www.youtube.com/watch?v=ooDZWBadKfE#t=2m50s if you are not familiar). I plan to write it in C++ using OpenGL. I have no previous experience with OpenGL, but I do have the math background required for this sort of thing.
Here's the code thusfar. It's not much but perhaps already some of you can spot some design inefficiency. Anyhow, I plan to make it work without a UI. I don't want any attachment between dependency between OpenGL and the actual code that works the card placing/battling/etc (so it could be entirely possible to write a CLI client too).
To learn OpenGL, after the core code is done, I will use http://www.opengl-tutorial.org/ which seems to use the most recent version and features of OpenGL.
Summary: I want to write a card game like Tetra Master from FFIX (see https://www.youtube.com/watch?v=ooDZWBadKfE#t=2m50s if you are not familiar). I plan to write it in C++ using OpenGL. I have no previous experience with OpenGL, but I do have the math background required for this sort of thing.
Here's the code thusfar. It's not much but perhaps already some of you can spot some design inefficiency. Anyhow, I plan to make it work without a UI. I don't want any attachment between dependency between OpenGL and the actual code that works the card placing/battling/etc (so it could be entirely possible to write a CLI client too).
To learn OpenGL, after the core code is done, I will use http://www.opengl-tutorial.org/ which seems to use the most recent version and features of OpenGL.
/* TODOs:
(naming the project Metra Taster?)
When placing a card, you get to choose which you want to fight from the
9 directions (max). Then, if you win that fight, you should be fighting the rest
of the cards in ascending order of possibility of winning: i.e. from strongest card to
weakest.
Write function to calculate possibilities of winning.
Write function to translate 9P3F to stats (almost done).
Write a function that places a card and finds the
resting cards on the board that the challenger must fight
Deck to choose 5 cards from
id=0 not yet played (empty block)?
id=1 cards are unplayable blocks placed at the start of the game
There's a fake generation of numbers in battle. The real HP makes those numbers
drop at a certain rate. Emulate that.
*/
#include <algorithm> // min, find
#include <string>
// board is incomplete, game is draw, p1 won, p2 won
enum class Status { incomplete, draw, p1, p2};
// types of cards
enum class Battle_Type { physical, magical, flexible, assault };
// type of block: free means you can put down a card there, a block is random, p1/p2 is ownership of cards.
enum class CType { free, block, p1, p2 };
class Values {
public:
/* E.g. 9P3F means
9 attack
P physical type
3 defense
F=15 magic defense*/
int atk, def, mdef;
Battle_Type type;
/* Note: Values constructor is not safe. Must check the string for proper format before using */
Values(std::string& s) {
static const char hex[] = "0123456789ABCDEF";
atk = std::find(hex, hex + sizeof hex, s[0]) - hex;
def = std::find(hex, hex + sizeof hex, s[2]) - hex;
mdef = std::find(hex, hex + sizeof hex, s[3]) - hex;
switch (s[1]) {
case 'P':
type = Battle_Type::physical;
break;
case 'M':
type = Battle_Type::magical;
break;
case 'X':
type = Battle_Type::flexible;
break;
case 'A':
type = Battle_Type::assault;
break;
}
};
};
class Card {
public:
Card(int id = 0) : id(id) { };
int id; // card id
bool arrows[3][3]; // card arrows for attack, what should [1][1] be?
Values values("0P00");
};
class Board {
public:
Board() {
for (int i = 0; i < 4; i++)
for (int j = 0; j < 4; j++)
t[i][j] = CType::free;
// place random blocks here
};
~Board();
Status status() const;
Card m[4][4];
CType t[4][4];
};
// return 0 if card is placed, 1 otherwise
bool Place(Board& b, Card& c, int x, int y) {
if (b.m[x][y].id == 0) {
b.m[x][y] = c; // now check the arrows and fight
for (int i = -1; i < 2; i++)
for (int j = -1; j < 2; j++) {
if (x + i > 0 && y + j > 0) { // not out of bounds ; need to add more (currently for only one corner)
if (b.m[x][y].arrows[i + 1][j + 1]) {
if (b.m[x + i][y + j].arrows[1 - i][1 - j])
battle(b.m[x][y], b.m[x + i][y + j]);
else 0; // win the card by default
}
}
}
}
else return 1;
}
// return 0 if challenging card won, 1 if resting card won
bool battle(Card& chg , Card& rtg) {
int cHP[3], rHP[3];
HP(chg, cHP);
HP(rtg, rHP);
switch (chg.values.type) {
case Battle_Type::physical:
return cHP[0] > rHP[1];
break;
case Battle_Type::magical:
cHP[0] > rHP[2];
break;
case Battle_Type::flexible:
cHP[0] > std::min(rHP[1], rHP[2]);
break;
case Battle_Type::assault:
cHP[0] > std::min(rHP[0], rHP[1], rHP[2]);
break;
}
}
// return a random number between 0 and range-1
int random(int range) {
return 0; // for now
}
// roll random HP
void HP(Card& c, int *HP) {
// random(16) rolls between 0 and 15
HP[0] = c.values.atk * 16 + random(16);
HP[1] = c.values.def * 16 + random(16);
HP[2] = c.values.mdef * 16 + random(16);
}