- It is now possible to have avatars associated to each Deck
- Added SFX
- Added Music files
- Possibility to choose your opponent
- Opponents' difficulty is measured according to their number of victories against a given deck
This commit is contained in:
wagic.the.homebrew
2008-11-24 09:24:47 +00:00
parent a9e70c0bdc
commit 3721247bee
69 changed files with 734 additions and 259 deletions

View File

@@ -0,0 +1,5 @@
you can put AI avatars in this folder.
they have to be 35x50 pixels, and in jpeg format.
The naming convention is avatarXX.jpg , where XX is the number of the associated deck.
For example, avatar1.jpg will be the avatar associated to deck1.txt

View File

@@ -2041,7 +2041,7 @@ id=1182
name=Terror
rarity=C
type=Instant
mana={0}
mana={1}{B}
[/card]
[card]
text=As The Rack comes into play, choose an opponent. At the beginning of the chosen player's upkeep, The Rack deals X damage to that player, where X is 3 minus the number of cards in his or her hand.

View File

@@ -1,50 +1,50 @@
100
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
100
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0

View File

@@ -1,92 +1,92 @@
1167
460
1202
525
1340
92
1284
101
1149
20
1264
20
1321
20
1272
437
1126
485
1334
107
1352
91
1279
20
1154
481
1328
551
1335
20
1227
500
1236
489
1186
20
1219
20
1175
459
1136
111
1332
545
1250
21
1204
19
1381
499
1170
484
1097
102
1102
46
1282
485
1378
490
1300
20
1363
495
129665
90
1387
4
129652
5
174957
108
175030
5
130378
107
175031
5
1312
19
130386
97
1275
21
1148
103
135185
20
1100
109
153441
19
1167
460
1202
525
1340
92
1284
101
1149
20
1264
20
1321
20
1272
437
1126
485
1334
107
1352
91
1279
20
1154
481
1328
551
1335
20
1227
500
1236
489
1186
20
1219
20
1175
459
1136
111
1332
545
1250
21
1204
19
1381
499
1170
484
1097
102
1102
46
1282
485
1378
490
1300
20
1363
495
129665
90
1387
4
129652
5
174957
108
175030
5
130378
107
175031
5
1312
19
130386
97
1275
21
1148
103
135185
20
1100
109
153441
19

View File

@@ -0,0 +1,2 @@
Track0.mp3 and Track1.mp3 have to be in this folder for the music options to be available.
These file must not contain any ID3v2 tag, or they won't play on the PSP.

View File

@@ -0,0 +1,8 @@
you can put wave files in this folder.
the name of the file can be any ability (flying.wav, trample.wav, lifelink.wav, ...)
or a supertype (artifact.wav, sorcery.wav, creature.wav...)
or a type (human.wav, dragon.wav...)
The game will automatically use the files ( if they are available) when a card comes into play.
Special files are mana.wav and graveyard.wav

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -29,7 +29,8 @@ class AIPlayer: public Player{
int getCreaturesInfo(Player * player, int neededInfo = INFO_NBCREATURES , int untapMode = 0, int canAttack = 0);
AIStats * getStats();
public:
virtual int displayStack(){return 0;}
void End(){};
virtual int displayStack(){return 0;};
AIStats * stats;
ManaCost * getPotentialMana();
AIPlayer(MTGPlayerCards * _deck, string deckFile);
@@ -48,14 +49,14 @@ class AIPlayerBaka: public AIPlayer{
int timer;
MTGCardInstance * FindCardToPlay(ManaCost * potentialMana, const char * type);
public:
AIPlayerBaka(MTGPlayerCards * _deck, char * deckFile);
AIPlayerBaka(MTGPlayerCards * _deck, char * deckFile, char * avatarFile);
virtual int Act(float dt);
void initTimer();
};
class AIPlayerFactory{
public:
AIPlayer * createAIPlayer(MTGAllCards * collection, MTGPlayerCards * oponents_deck);
AIPlayer * createAIPlayer(MTGAllCards * collection, MTGPlayerCards * oponents_deck, int deckid = 0);
};

View File

@@ -8,6 +8,7 @@
#include "CardDisplay.h"
#include "Subtypes.h"
#include "CardGui.h"
#include "GameOptions.h"
#include <JGui.h>
#include <hge/hgeparticle.h>
@@ -570,6 +571,11 @@ class AManaProducer: public MTGAbility{
y0 = cardg->y + 20;
}
controller = source->controller();
if (GameOptions::GetInstance()->values[OPTIONS_SFXVOLUME] > 0){
JSample * sample = SampleCache::GetInstance()->getSample("sound/sfx/mana.wav");
if (sample) JSoundSystem::GetInstance()->PlaySample(sample);
}
return 1;
}

View File

@@ -21,7 +21,7 @@ class CardGui: public PlayGuiObject{
virtual void Render();
virtual void Update(float dt);
void RenderBig(float x=-1, float y = -1);
void RenderBig(float x=-1, float y = -1, int alternate = 0);
static void alternateRender(MTGCard * card, JLBFont * mFont, JQuad ** manaIcons, float x, float y, float rotation= 0, float scale=1);
~CardGui();
};

View File

@@ -0,0 +1,36 @@
#ifndef _DECKSTATS_H_
#define _DECKSTATS_H_
#include <map>
#include <string>
using namespace std;
class Player;
class GameObserver;
class DeckStat{
public:
int nbgames;
int victories;
DeckStat(int _nbgames = 0 , int _victories = 0):nbgames(_nbgames),victories(_victories){};
int percentVictories();
};
class DeckStats{
protected:
static DeckStats * mInstance;
public:
map<string, DeckStat *>stats;
static DeckStats * GetInstance();
void saveStats(Player * player, Player * opponent, GameObserver * game);
void save(const char * filename);
void save(Player * player);
void load(const char * filename);
void load(Player * player);
void cleanStats();
~DeckStats();
int percentVictories(string opponentsDeckFile);
};
#endif

View File

@@ -4,7 +4,8 @@
#define MAX_OPTIONS 50
#define OPTIONS_MUSICVOLUME 0
#define OPTIONS_INTERRUPTATENDOFPHASE_OFFSET 1
#define OPTIONS_SFXVOLUME 1
#define OPTIONS_INTERRUPTATENDOFPHASE_OFFSET 2
#define OPTIONS_SAVEFILE "Res/settings/options.txt"
class GameOptions {
public:

View File

@@ -202,7 +202,7 @@ class GameStateDeckViewer: public GameState, public JGuiListener
}
GameApp::music = JSoundSystem::GetInstance()->LoadMusic("sound/track1.mp3");
if (GameApp::music){
JSoundSystem::GetInstance()->PlayMusic(GameApp::music, true);
JSoundSystem::GetInstance()->PlayMusic(GameApp::music, true);
}
}
colorFilter = ALL_COLORS;

View File

@@ -14,6 +14,7 @@
#define ERROR_NO_DECK 4
#define DUEL_PLAY 5
#define DUEL_MENU 6
#define CHOOSE_OPPONENT 7
#ifdef TESTSUITE
@@ -32,10 +33,12 @@ class GameStateDuel: public GameState, public JGuiListener
MTGPlayerCards * deck[2];
GameObserver * game;
SimpleMenu * deckmenu;
SimpleMenu * opponentMenu;
SimpleMenu * menu;
JLBFont* mFont;
JLBFont* mFont, *opponentMenuFont;
int nbAIDecks;
void loadPlayer(int playerId, int decknb = 0);
void loadPlayer(int playerId, int decknb = 0, int isAI = 0);
public:
GameStateDuel(GameApp* parent);
virtual ~GameStateDuel();

View File

@@ -134,9 +134,11 @@ class GameStateMenu: public GameState, public JGuiListener
virtual void Destroy()
{
if (mGuiController)
delete mGuiController;
if (subMenuController)
delete subMenuController;
@@ -147,8 +149,10 @@ class GameStateMenu: public GameState, public JGuiListener
delete mIcons[i];
}
if (mBg) delete mBg;
if (mMovingW) delete mMovingW;
SAFE_DELETE(mBg);
SAFE_DELETE(mMovingW);
SAFE_DELETE(movingWTexture);
SAFE_DELETE(bgTexture);
//SAFE_DELETE (bgMusic);
}
@@ -265,15 +269,18 @@ class GameStateMenu: public GameState, public JGuiListener
if( subMenuController != NULL){
subMenuController->Update(dt);
}else{
subMenuController = NEW SimpleMenu(102, this,mFont, 50,170,SCREEN_WIDTH-120);
if (subMenuController){
subMenuController->Add(11,"1 Player");
subMenuController->Add(11,"1 Player");
subMenuController->Add(12, "2 Players");
subMenuController->Add(13,"Demo");
subMenuController->Add(14, "Cancel");
#ifdef TESTSUITE
subMenuController->Add(666, "Test Suite");
#endif
}
}
}

View File

@@ -13,6 +13,8 @@ class SimpleMenu;
class GameStateOptions: public GameState, public JGuiListener
{
private:
float timer;
public:
SimpleMenu * optionsMenu;

View File

@@ -3,7 +3,6 @@
#ifdef DOLOG
#define LOG(x) Logger::Log(x);
#else
@@ -14,7 +13,7 @@
class Logger{
public:
static void Log(char * text);
static void Log(const char * text);
};
#endif

View File

@@ -27,7 +27,7 @@ class MTGCardInstance: public MTGCard, public Damageable, public Targetable {
protected:
int untapping;
int nb_damages;
string sample;
int lifeOrig;
Blockers * blockers;
@@ -94,6 +94,7 @@ class MTGCardInstance: public MTGCard, public Damageable, public Targetable {
void tap();
int isInPlay();
void resetAllDamage();
JSample * getSample();
};

View File

@@ -1,18 +1,20 @@
#ifndef _PLAYGUIOBJECTCONTROLLER_H_
#define _PLAYGUIOBJECTCONTROLLER_H_
#define BIG_CARD_RENDER_TIME 0.4
#include "GuiLayers.h"
class PlayGuiObjectController : public GuiLayer{
protected:
float last_user_move;
int getClosestItem(int direction);
int getClosestItem(int direction, float tolerance);
static bool showBigCards;
static int showBigCards;// 0 hide, 1 show, 2 show text
public:
virtual void Update(float dt);
virtual void CheckUserInput(float dt);
PlayGuiObjectController(int id, GameObserver* _game):GuiLayer(id, _game){};
PlayGuiObjectController(int id, GameObserver* _game):GuiLayer(id, _game){last_user_move=0;};
virtual void Render(){GuiLayer::Render();};
};

View File

@@ -15,6 +15,7 @@ class Player: public Damageable, public Targetable{
ManaCost * manaPool;
public:
virtual void End();
int typeAsTarget(){return TARGET_PLAYER;}
virtual int displayStack(){return 1;}
JTexture * mAvatarTex;

View File

@@ -14,9 +14,11 @@ class SimpleMenu:public JGuiController{
JLBFont* mFont;
std::string title;
int displaytitle;
int maxItems,startId;
public:
SimpleMenu(int id, JGuiListener* listener, JLBFont* font, int x, int y, int width, const char * _title = NULL);
SimpleMenu(int id, JGuiListener* listener, JLBFont* font, int x, int y, int width, const char * _title = NULL, int _maxItems = 10);
void Render();
void Update(float dt);
void Add(int id, const char * Text);
};

View File

@@ -13,7 +13,7 @@ class SimpleMenuItem: public JGuiObject
private:
bool mHasFocus;
JLBFont *mFont;
const char* mText;
string mText;
int mX;
int mY;
@@ -25,6 +25,7 @@ class SimpleMenuItem: public JGuiObject
public:
SimpleMenuItem(int id, JLBFont *font, const char* text, int x, int y, bool hasFocus = false);
void RenderWithOffset(float yOffset);
virtual void Render();
virtual void Update(float dt);

View File

@@ -19,6 +19,7 @@ class Subtypes{
int find(const char * subtype);
int Add(string subtype);
int find(string subtype);
string find(int id);
};

View File

@@ -10,6 +10,9 @@
#include <JGE.h>
#include <JTypes.h>
#include <map>
using std::map;
#include "MTGDeck.h"
@@ -55,4 +58,16 @@ class TexturesCache{
};
class SampleCache{
protected:
map<string, JSample *> cache;
static SampleCache * mInstance;
void cleanCache();
~SampleCache();
public:
static SampleCache * GetInstance();
JSample * getSample(string filename);
};
#endif

View File

@@ -46,5 +46,5 @@ int filesize(const char * filename);
int read_file (const char * filename, char * buffer, int filesize);
int readline (char * in_buffer, char * out_buffer, int cursor);
int readfile_to_ints(const char * filename, int * out_buffer);
int fileExists(const char * filename);
#endif

View File

@@ -15,7 +15,10 @@ AIPlayer::AIPlayer(MTGPlayerCards * _deck, string file): Player(_deck, file){
AIPlayer::~AIPlayer(){
if (potentialMana) delete potentialMana;
SAFE_DELETE(stats);
if (stats){
stats->save();
delete stats;
}
}
MTGCardInstance * AIPlayer::chooseCard(TargetChooser * tc, MTGCardInstance * source, int random){
for (int i = 0; i < game->hand->nb_cards; i++){
@@ -392,24 +395,29 @@ AIStats * AIPlayer::getStats(){
return stats;
}
AIPlayer * AIPlayerFactory::createAIPlayer(MTGAllCards * collection, MTGPlayerCards * oponents_deck){
int nbdecks = 0;
int found = 1;
while (found){
found = 0;
char buffer[512];
sprintf(buffer, "Res/ai/baka/deck%i.txt",nbdecks+1);
std::ifstream file(buffer);
if(file){
found = 1;
file.close();
nbdecks++;
AIPlayer * AIPlayerFactory::createAIPlayer(MTGAllCards * collection, MTGPlayerCards * oponents_deck, int deckid){
if (!deckid){
int nbdecks = 0;
int found = 1;
while (found){
found = 0;
char buffer[512];
sprintf(buffer, "Res/ai/baka/deck%i.txt",nbdecks+1);
std::ifstream file(buffer);
if(file){
found = 1;
file.close();
nbdecks++;
}
}
if (!nbdecks) return NULL;
deckid = 1 + rand() % (nbdecks);
}
if (!nbdecks) return NULL;
int deckid = 1 + rand() % (nbdecks);
char deckFile[512];
sprintf(deckFile, "Res/ai/baka/deck%i.txt",deckid);
char avatarFile[512];
sprintf(avatarFile, "ai/baka/avatars/avatar%i.jpg",deckid);
char deckFileSmall[512];
sprintf(deckFileSmall, "ai_baka_deck%i",deckid);
#if defined (WIN32) || defined (LINUX)
@@ -420,7 +428,7 @@ AIPlayer * AIPlayerFactory::createAIPlayer(MTGAllCards * collection, MTGPlayerCa
int deck_cards_ids[100];
int nb_elements = readfile_to_ints(deckFile, deck_cards_ids);
MTGPlayerCards * deck = NEW MTGPlayerCards(collection,deck_cards_ids, nb_elements);
AIPlayerBaka * baka = NEW AIPlayerBaka(deck,deckFileSmall);
AIPlayerBaka * baka = NEW AIPlayerBaka(deck,deckFileSmall, avatarFile);
return baka;
}
@@ -460,8 +468,12 @@ MTGCardInstance * AIPlayerBaka::FindCardToPlay(ManaCost * potentialMana, const c
return nextCardToPlay;
}
AIPlayerBaka::AIPlayerBaka(MTGPlayerCards * _deck, char * file): AIPlayer(_deck,file){
mAvatarTex = JRenderer::GetInstance()->LoadTexture("ai/baka/avatar.jpg", TEX_TYPE_USE_VRAM);
AIPlayerBaka::AIPlayerBaka(MTGPlayerCards * _deck, char * file, char * avatarFile): AIPlayer(_deck,file){
if (fileExists(avatarFile)){
mAvatarTex = JRenderer::GetInstance()->LoadTexture(avatarFile, TEX_TYPE_USE_VRAM);
}else{
mAvatarTex = JRenderer::GetInstance()->LoadTexture("ai/baka/avatar.jpg", TEX_TYPE_USE_VRAM);
}
if (mAvatarTex)
mAvatar = NEW JQuad(mAvatarTex, 0, 0, 35, 50);
initTimer();

View File

@@ -61,7 +61,6 @@ void AIStats::updateStats(){
damage = ((Damage * )as->getNext(damage,ACTION_DAMAGE, RESOLVED_OK));
}
stats.sort(compare_aistats);
save();
}
bool AIStats::isInTop(MTGCardInstance * card, unsigned int max, bool tooSmallCountsForTrue ){

View File

@@ -7,6 +7,7 @@
#include "../include/GameObserver.h"
#include "../include/Damage.h"
#include "../include/ManaCost.h"
#include "../include/GameOptions.h"
/*
NextGamePhase requested by user
@@ -85,6 +86,15 @@ int Spell::resolve(){
GameObserver * game = GameObserver::GetInstance();
//TODO Remove target if it's not targettable anymore
source->controller()->game->putInPlay(source);
//Play SFX
if (GameOptions::GetInstance()->values[OPTIONS_SFXVOLUME] > 0){
JSample * sample = source->getSample();
if (sample){
JSoundSystem::GetInstance()->PlaySample(sample);
}
}
AbilityFactory af;
af.addAbilities(game->mLayers->actionLayer()->getMaxId(), this);
return 1;

View File

@@ -59,6 +59,7 @@ void CardGui::alternateRender(MTGCard * card, JLBFont * mFont, JQuad ** manaIcon
ManaCost * manacost = card->getManaCost();
int nbicons = 0;
for (int i = 1; i < MTG_NB_COLORS - 1; i++){
int cost = manacost->getCost(i);
for (int j=0; j < cost; j++){
v.x = (width/2 - 20 - 16*nbicons)*scale;
@@ -74,13 +75,13 @@ void CardGui::alternateRender(MTGCard * card, JLBFont * mFont, JQuad ** manaIcon
v.y = ((-height/2) + 14) * scale;
v.Rotate(rotation);
sprintf(buf,"%i",cost);
mFont->SetColor(ARGB(255,255,255,255));
mFont->DrawString(buf,x+v.x,y+v.y);
}
if (!card->formattedTextInit){
std::string s(card->getText());
std::string::size_type found=s.find_first_of("{}");
while (found!=string::npos)
{
s[found]='/';
@@ -201,9 +202,7 @@ void CardGui::Update(float dt){
PlayGuiObject::Update(dt);
}
void CardGui::RenderBig(float xpos, float ypos){
JRenderer * renderer = JRenderer::GetInstance();
JQuad * quad = card->getQuad();
void CardGui::RenderBig(float xpos, float ypos, int alternate){
if (xpos == -1){
xpos = 300;
if (x > SCREEN_WIDTH / 2)
@@ -211,10 +210,19 @@ void CardGui::RenderBig(float xpos, float ypos){
}
if(ypos == -1)
ypos = 20;
if (quad){
quad->SetColor(ARGB(220,255,255,255));
renderer->RenderQuad(quad, xpos , ypos , 0.0f,0.9f,0.9f);
}else{
if (!alternate){
JRenderer * renderer = JRenderer::GetInstance();
JQuad * quad = card->getQuad();
if (quad){
quad->SetColor(ARGB(220,255,255,255));
renderer->RenderQuad(quad, xpos , ypos , 0.0f,0.9f,0.9f);
}else{
alternate = 1;
}
}
if (alternate){
MTGCard * mtgcard = card->model;
JLBFont * font = GameApp::CommonRes->GetJLBFont("graphics/magic");
CardGui::alternateRender(mtgcard, font, NULL, xpos + 90 , ypos + 130, 0.0f,0.9f);

View File

@@ -0,0 +1,98 @@
#include "../include/debug.h"
#include "../include/DeckStats.h"
#include "../include/Player.h"
DeckStats * DeckStats::mInstance = NULL;
int DeckStat::percentVictories(){
if (nbgames == 0) return 50;
return (100 * victories / nbgames);
}
DeckStats * DeckStats::GetInstance(){
if (!mInstance) mInstance = NEW DeckStats();
return mInstance;
}
void DeckStats::cleanStats(){
map<string,DeckStat *>::iterator it;
for (it = stats.begin(); it != stats.end(); it++){
delete(it->second);
}
stats.clear();
}
DeckStats::~DeckStats(){
cleanStats();
}
int DeckStats::percentVictories(string opponentsFile){
map<string,DeckStat *>::iterator it = stats.find(opponentsFile);
if (it == stats.end()){
return 50;
}else{
return (it->second->percentVictories());
}
}
void DeckStats::load(Player * player){
char filename[512];
sprintf(filename, "Res/player/stats/%s.txt",player->deckFile.c_str());
load(filename);
}
void DeckStats::load(const char * filename){
cleanStats();
std::ifstream file(filename);
std::string s;
if(file){
while(std::getline(file,s)){
string deckfile = s;
std::getline(file,s);
int games = atoi(s.c_str());
std::getline(file,s);
int victories = atoi(s.c_str());
stats[deckfile] = NEW DeckStat(games,victories);
}
file.close();
}
}
void DeckStats::save(Player * player){
char filename[512];
sprintf(filename, "Res/player/stats/%s.txt",player->deckFile.c_str());
save(filename);
}
void DeckStats::save(const char * filename){
std::ofstream file(filename);
char writer[512];
if (file){
map<string,DeckStat *>::iterator it;
for (it = stats.begin(); it != stats.end(); it++){
sprintf(writer,"%s\n", it->first.c_str());
file<<writer;
sprintf(writer,"%i\n", it->second->nbgames);
file<<writer;
sprintf(writer,"%i\n", it->second->victories);
file<<writer;
}
file.close();
}
}
void DeckStats::saveStats(Player *player, Player *opponent, GameObserver * game){
int victory = 1;
if (game->gameOver == player) victory = 0;
load(player);
map<string,DeckStat *>::iterator it = stats.find(opponent->deckFile);
if (it == stats.end()){
stats[opponent->deckFile] = NEW DeckStat(1,victory);
}else{
it->second->victories+=victory;
it->second->nbgames+=1;
}
save(player);
}

View File

@@ -15,7 +15,7 @@
#include "../include/GameStateDuel.h"
#include "../include/GameStateOptions.h"
#include "../include/GameStateShop.h"
#include "../include/DeckStats.h"
const char * const GameState::menuTexts[]= {"--NEW--","Deck 1", "Deck 2", "Deck 3", "Deck 4", "Deck 5", "Deck 6"} ;
JResourceManager* GameApp::CommonRes = NEW JResourceManager();
@@ -179,6 +179,10 @@ void GameApp::Destroy()
if (Subtypes::subtypesList) delete Subtypes::subtypesList;
if (MtgSets::SetsList) delete MtgSets::SetsList;
SAFE_DELETE(music);
delete(DeckStats::GetInstance());
LOG("==Destroying GameApp Successful==");
}

View File

@@ -3,6 +3,8 @@
#include "../include/utils.h"
#include "../include/AIPlayer.h"
#include "../include/PlayerData.h"
#include "../include/DeckStats.h"
#ifdef TESTSUITE
#include "../include/TestSuiteAI.h"
@@ -16,6 +18,7 @@ GameStateDuel::GameStateDuel(GameApp* parent): GameState(parent) {
game = NULL;
deckmenu = NULL;
opponentMenu = NULL;
menu = NULL;
#ifdef TESTSUITE
testSuite = NULL;
@@ -43,6 +46,7 @@ void GameStateDuel::Start()
mFont = GameApp::CommonRes->GetJLBFont("graphics/f3");
mFont->SetBase(0); // using 2nd font
opponentMenuFont = NEW JLBFont("graphics/f3",16);
menu = NEW SimpleMenu(11,this,mFont,SCREEN_WIDTH/2-100,20,200);
@@ -79,16 +83,22 @@ void GameStateDuel::Start()
}
void GameStateDuel::loadPlayer(int playerId, int decknb){
if (decknb){ //Human Player
char deckFile[255];
sprintf(deckFile, "Res/player/deck%i.txt",decknb);
char deckFileSmall[255];
sprintf(deckFileSmall, "player_deck%i",decknb);
int deck_cards_ids[100];
int nb_elements = readfile_to_ints(deckFile, deck_cards_ids);
deck[playerId] = NEW MTGPlayerCards(mParent->collection,deck_cards_ids, nb_elements);
mPlayers[playerId] = NEW HumanPlayer(deck[playerId],deckFileSmall);
void GameStateDuel::loadPlayer(int playerId, int decknb, int isAI){
if (decknb){
if (!isAI){ //Human Player
char deckFile[255];
sprintf(deckFile, "Res/player/deck%i.txt",decknb);
char deckFileSmall[255];
sprintf(deckFileSmall, "player_deck%i",decknb);
int deck_cards_ids[100];
int nb_elements = readfile_to_ints(deckFile, deck_cards_ids);
deck[playerId] = NEW MTGPlayerCards(mParent->collection,deck_cards_ids, nb_elements);
mPlayers[playerId] = NEW HumanPlayer(deck[playerId],deckFileSmall);
}else{ //AI Player, chose deck
AIPlayerFactory playerCreator;
mPlayers[playerId] = playerCreator.createAIPlayer(mParent->collection,NULL,decknb);
deck[playerId] = mPlayers[playerId]->game;
}
}else{
AIPlayerFactory playerCreator;
mPlayers[playerId] = playerCreator.createAIPlayer(mParent->collection,NULL);
@@ -127,15 +137,21 @@ void GameStateDuel::End()
#if defined (WIN32) || defined (LINUX)
OutputDebugString("Ending GamestateDuel\n");
#endif
GameObserver::EndInstance();
game = NULL;
SAFE_DELETE(deckmenu);
JRenderer::GetInstance()->EnableVSync(false);
if (mPlayers[0] && mPlayers[1]) mPlayers[0]->End();
GameObserver::EndInstance();
game = NULL;
for (int i = 0; i < 2; i++){
SAFE_DELETE(mPlayers[i]);
SAFE_DELETE(deck[i]);
}
SAFE_DELETE(menu);
SAFE_DELETE(opponentMenu);
SAFE_DELETE(opponentMenuFont);
#ifdef TESTSUITE
SAFE_DELETE(testSuite);
#endif
@@ -176,8 +192,43 @@ void GameStateDuel::Update(float dt)
}
else{
loadPlayer(1);
mGamePhase = DUEL_PLAY;
if (mParent->players[0] == PLAYER_TYPE_HUMAN){
if (!opponentMenu){
opponentMenu = NEW SimpleMenu(13,this,opponentMenuFont,10,10,SCREEN_WIDTH/2,"choose Opponent");
opponentMenu->Add(0,"Random");
nbAIDecks = 0;
int found = 1;
while (found){
found = 0;
char buffer[512];
char aiSmallDeckName[512];
char deckDesc[512];
sprintf(buffer, "Res/ai/baka/deck%i.txt",nbAIDecks+1);
if(fileExists(buffer)){
found = 1;
nbAIDecks++;
sprintf(aiSmallDeckName, "ai_baka_deck%i",nbAIDecks);
DeckStats * stats = DeckStats::GetInstance();
stats->load(mPlayers[0]);
int percentVictories = stats->percentVictories(string(aiSmallDeckName));
string difficulty;
if (percentVictories < 34){
difficulty = "(hard)";
}else if (percentVictories < 67){
difficulty = "";
}else{
difficulty = "(easy)";
}
sprintf(deckDesc, "Deck %i %s",nbAIDecks, difficulty.c_str());
opponentMenu->Add(nbAIDecks,deckDesc);
}
}
}
opponentMenu->Update(dt);
}else{
loadPlayer(1);
mGamePhase = DUEL_PLAY;
}
}
}else if (mGamePhase == DUEL_PLAY){
@@ -259,14 +310,17 @@ void GameStateDuel::Render()
}else{
int winner = 2;
if (game->gameOver !=mPlayers[0]){
winner = 1;
winner = 1;
}
sprintf(buffer, "Player %i wins (%i)", winner, p0life );
}
mFont->DrawString(buffer, 10, 150);
}else if (mGamePhase == DUEL_CHOOSE_DECK1 || mGamePhase == DUEL_CHOOSE_DECK2){
if (deckmenu)
if (opponentMenu){
opponentMenu->Render();
}else if (deckmenu){
deckmenu->Render();
}
}else if (mGamePhase == ERROR_NO_DECK){
mFont->DrawString("NO DECK AVAILABLE,",0,SCREEN_HEIGHT/2);
mFont->DrawString("PRESS CIRCLE TO GO TO THE DECK EDITOR!",0,SCREEN_HEIGHT/2 + 20);
@@ -278,30 +332,50 @@ void GameStateDuel::Render()
void GameStateDuel::ButtonPressed(int controllerId, int controlId)
{
switch (controlId)
{
case 1:
case 2:
case 3:
case 4:
case 5:
{
if (mGamePhase == DUEL_CHOOSE_DECK1){
loadPlayer(0,controlId);
mGamePhase = DUEL_CHOOSE_DECK2;
}else{
loadPlayer(1,controlId);
mGamePhase = DUEL_PLAY;
}
break;
}
case 12:
mParent->SetNextState(GAME_STATE_MENU);
break;
switch (controllerId){
case 13:
mGamePhase = DUEL_PLAY;
break;
}
{
switch(controlId){
case 0:
loadPlayer(1);
mGamePhase = DUEL_PLAY;
break;
default:
loadPlayer(1,controlId,1);
mGamePhase = DUEL_PLAY;
break;
}
break;
}
default:
{
switch (controlId)
{
case 1:
case 2:
case 3:
case 4:
case 5:
{
if (mGamePhase == DUEL_CHOOSE_DECK1){
loadPlayer(0,controlId);
mGamePhase = DUEL_CHOOSE_DECK2;
}else{
loadPlayer(1,controlId);
mGamePhase = DUEL_PLAY;
}
break;
}
case 12:
mParent->SetNextState(GAME_STATE_MENU);
break;
case 13:
mGamePhase = DUEL_PLAY;
break;
}
}
}
}

View File

@@ -17,12 +17,15 @@ GameStateOptions::~GameStateOptions() {
void GameStateOptions::Start()
{
timer = 0;
mState = SHOW_OPTIONS;
JRenderer::GetInstance()->ResetPrivateVRAM();
JRenderer::GetInstance()->EnableVSync(true);
optionsList = NEW OptionsList();
if (GameApp::HasMusic) optionsList->Add(NEW OptionItem(OPTIONS_MUSICVOLUME, "Music volume", 100, 10));
optionsList->Add(NEW OptionItem(OPTIONS_SFXVOLUME, "SFX volume", 100, 10));
JLBFont * mFont = GameApp::CommonRes->GetJLBFont("graphics/f3");
optionsMenu = NEW SimpleMenu(102, this,mFont, 50,170,SCREEN_WIDTH-120);
optionsMenu->Add(1, "Save & Back to Main Menu");
@@ -41,6 +44,8 @@ void GameStateOptions::End()
void GameStateOptions::Update(float dt)
{
timer+= dt;
if (mState == SHOW_OPTIONS){
if (mEngine->GetButtonClick(PSP_CTRL_START)){
mState = SHOW_OPTIONS_MENU;
@@ -59,17 +64,18 @@ void GameStateOptions::Render()
{
//Erase
JRenderer::GetInstance()->ClearScreen(ARGB(0,0,0,0));
optionsList->Render();
const char * const CreditsText[] = {
"Wagic, The Homebrew ?! by WilLoW",
"This is a work in progress and it contains bugs, deal with it",
"updates on http://www.wololo.net/wagic",
"Many thanks to Abrasax and J for their help in this release",
"",
"Developped with the JGE++ Library",
"http://jge.khors.com",
"Developped with the JGE++ Library (http://jge.khors.com)",
"",
"this freeware app is not endorsed by Wizards of the Coast, Inc",
"",
"SFX From www.soundsnap.com",
};
@@ -80,24 +86,35 @@ void GameStateOptions::Render()
};
JLBFont * mFont = GameApp::CommonRes->GetJLBFont("graphics/f3");
JLBFont * mFont = GameApp::CommonRes->GetJLBFont("graphics/magic");
mFont->SetColor(ARGB(255,200,200,200));
mFont->SetScale(0.80);
for (int i = 0; i < 8; i++){
mFont->DrawString(CreditsText[i],SCREEN_WIDTH/2, 40 +18*i,JGETEXT_CENTER);
mFont->SetScale(1.0);
float startpos = 272 - timer * 10;
float pos = startpos;
for (int i = 0; i < 10; i++){
pos = startpos +20*i;
if (pos > -20){
mFont->DrawString(CreditsText[i],SCREEN_WIDTH/2,pos ,JGETEXT_CENTER);
}
}
if (GameApp::HasMusic){
for (int i = 0; i < 3; i++){
mFont->DrawString(MusicText[i],SCREEN_WIDTH/2, 40 +18*(8+i),JGETEXT_CENTER);
pos = startpos +20*(10+i);
if (pos > -20){
mFont->DrawString(MusicText[i],SCREEN_WIDTH/2, pos,JGETEXT_CENTER);
}
}
}
if (pos < -20) timer = 0;
mFont->SetScale(1.f);
if (mState == SHOW_OPTIONS_MENU){
optionsMenu->Render();
}
optionsList->Render();
}

View File

@@ -26,14 +26,19 @@ void GameStateShop::Start()
{
menu = NULL;
mFont = GameApp::CommonRes->GetJLBFont("graphics/magic");
mStage = STAGE_SHOP_SHOP;
bgTexture = JRenderer::GetInstance()->LoadTexture("graphics/shop.jpg", TEX_TYPE_USE_VRAM);
mBg = NEW JQuad(bgTexture, 0, 0, 400, 280); // Create background quad for rendering.
backTexture = JRenderer::GetInstance()->LoadTexture("sets/back.jpg", TEX_TYPE_USE_VRAM);
mBack = NEW JQuad(backTexture, 0, 0, 200, 285); // Create background quad for rendering.
JRenderer::GetInstance()->ResetPrivateVRAM();
JRenderer::GetInstance()->EnableVSync(true);
int sets[500];
int nbsets = 0;
for (int i = 0; i < MtgSets::SetsList->nb_items; i++){
@@ -48,6 +53,9 @@ void GameStateShop::Start()
setId = (rand() % MtgSets::SetsList->nb_items);
}
JQuad * mBackThumb = GameApp::CommonRes->GetQuad("back_thumb");
shop = NULL;
shop = NEW ShopItems(10, this, mFont, 10, 10, mParent->collection, setId);
sprintf(starterBuffer, "%s Starter (60 cards)",MtgSets::SetsList->values[setId].c_str());
sprintf(boosterBuffer, "%s Booster (15 cards)",MtgSets::SetsList->values[setId].c_str());
@@ -63,9 +71,9 @@ void GameStateShop::Start()
void GameStateShop::End()
{
JRenderer::GetInstance()->EnableVSync(false);
if (shop)
SAFE_DELETE(shop);
SAFE_DELETE(shop);
SAFE_DELETE(mBack);
SAFE_DELETE(backTexture);
if(bgTexture)
SAFE_DELETE(bgTexture);
if(mBg)
@@ -115,11 +123,11 @@ void GameStateShop::ButtonPressed(int controllerId, int controlId)
{
switch (controllerId){
case 10:
shop->pricedialog(controlId);
if (shop) shop->pricedialog(controlId);
break;
case 11:
if (controlId == 12){
shop->saveAll();
if (shop) shop->saveAll();
mParent->SetNextState(GAME_STATE_MENU);
}else{
mStage = STAGE_SHOP_SHOP;

View File

@@ -8,7 +8,7 @@ using namespace std;
#include <windows.h>
#endif
void Logger::Log(char * text){
void Logger::Log(const char * text){
ofstream file (LOG_FILE,ios_base::app);
if (file){
file << text;

View File

@@ -8,6 +8,7 @@
#include "../include/MTGCardInstance.h"
#include "../include/CardDescriptor.h"
#include "../include/Counters.h"
#include "../include/Subtypes.h"
MTGCardInstance::MTGCardInstance(): MTGCard(), Damageable(0){
LOG("==Creating MTGCardInstance==");
@@ -33,6 +34,7 @@ MTGCardInstance::~MTGCardInstance(){
LOG("==Deleting MTGCardInstance Succesfull==");
}
void MTGCardInstance::initMTGCI(){
sample = "";
model=NULL;
lifeOrig = 0;
doDamageTest = 0;
@@ -405,3 +407,42 @@ int MTGCardInstance::protectedAgainst(MTGCardInstance * card){
}
return 0;
}
/* Choose a sound sample to associate to that card */
JSample * MTGCardInstance::getSample(){
if (!sample.size()){
for (int i = nb_types-1; i>0; i--){
string type = Subtypes::subtypesList->find(types[i]);
type = "sound/sfx/" + type + ".wav";
#ifdef WIN32
OutputDebugString(type.c_str());
#endif
if (fileExists(type.c_str())){
sample = string(type);
break;
}
}
}
if (!sample.size()){
for (int i = 0; i < NB_BASIC_ABILITIES; i++){
if (!basicAbilities[i]) continue;
string type = MTGBasicAbilities[i];
type = "sound/sfx/" + type + ".wav";
if (fileExists(type.c_str())){
sample = type;
break;
}
}
}
if (!sample.size()){
string type = Subtypes::subtypesList->find(types[0]);
type = "sound/sfx/" + type + ".wav";
if (fileExists(type.c_str())){
sample = type;
}
}
if (sample.size()) return SampleCache::GetInstance()->getSample(sample);
return NULL;
}

View File

@@ -77,7 +77,7 @@ int MTGAllCards::processConfLine(char *buffer, MTGCard *card){
card->setType( "Artifact");
card->setColor(MTG_COLOR_ARTIFACT);
if (value.c_str()[8] == ' ' && value.c_str()[9] == 'C')
card->setSubtype("Creature");
card->setSubtype("Creature");
break;
case 'E':
card->setType( "Enchantment");

View File

@@ -1,6 +1,7 @@
#include "../include/debug.h"
#include "../include/MTGGameZones.h"
#include "../include/Player.h"
#include "../include/GameOptions.h"
#if defined (WIN32) || defined (LINUX)
#include <time.h>
@@ -90,9 +91,16 @@ void MTGPlayerCards::putInZone(MTGCardInstance * card, MTGGameZone * from, MTGGa
if (from->removeCard(card)){
to->addCard(card);
card->changedZoneRecently = 1.f;
//if (to == graveyard){
card->reset();
//}
if (GameOptions::GetInstance()->values[OPTIONS_SFXVOLUME] > 0){
if (to == graveyard){
if (card->isACreature()){
JSample * sample = SampleCache::GetInstance()->getSample("sound/sfx/graveyard.wav");
if (sample) JSoundSystem::GetInstance()->PlaySample(sample);
}
}
}
}
}

View File

@@ -95,7 +95,7 @@ void MTGGuiHand::Render(){
}
if (mCount && mObjects[mCurr] != NULL){
mObjects[mCurr]->Render();
if (showBigCards) ((CardGui *)mObjects[mCurr])->RenderBig(10);
if (showBigCards) ((CardGui *)mObjects[mCurr])->RenderBig(10,-1,showBigCards-1);
}
}
}

View File

@@ -361,8 +361,9 @@ void MTGGuiPlay::Render(){
if (mCount && mObjects[mCurr] != NULL){
mObjects[mCurr]->Render();
if (hasFocus && mCurr >= offset && showBigCards)
((CardGui *)mObjects[mCurr])->RenderBig();
if (hasFocus && mCurr >= offset && showBigCards && last_user_move > BIG_CARD_RENDER_TIME){
((CardGui *)mObjects[mCurr])->RenderBig(-1,-1,showBigCards-1);
}
}
if (mGlitterAlpha < 0){

View File

@@ -31,6 +31,7 @@ void OptionItem::Render(){
mFont->SetColor(ARGB(255,255,255,255));
}
JRenderer * renderer = JRenderer::GetInstance();
renderer->FillRoundRect(x-5,y-2,SCREEN_WIDTH -x - 5,20,2,ARGB(150,50,50,50));
mFont->DrawString(displayValue.c_str(),x,y);
char buf[512];
sprintf(buf, "%i", value);

View File

@@ -4,7 +4,7 @@
#include "../include/PlayGuiObject.h"
#include "../include/GameObserver.h"
bool PlayGuiObjectController::showBigCards = true;
int PlayGuiObjectController::showBigCards = 1;
int PlayGuiObjectController::getClosestItem(int direction){
return getClosestItem(direction, 35);
@@ -177,6 +177,7 @@ void PlayGuiObjectController::Update(float dt){
void PlayGuiObjectController::CheckUserInput(float dt){
last_user_move +=dt;
if (!mCount)
return;
if (game != NULL){
@@ -193,6 +194,8 @@ void PlayGuiObjectController::CheckUserInput(float dt){
if (mEngine->GetButtonState(PSP_CTRL_LEFT))
{
last_user_move = 0;
if (KeyRepeated(PSP_CTRL_LEFT, dt))
{
int n = getClosestItem(DIR_LEFT);
@@ -205,6 +208,7 @@ void PlayGuiObjectController::CheckUserInput(float dt){
}
else if (mEngine->GetButtonState(PSP_CTRL_RIGHT))
{
last_user_move = 0;
if (KeyRepeated(PSP_CTRL_RIGHT, dt))
{
int n = getClosestItem(DIR_RIGHT);
@@ -217,6 +221,7 @@ void PlayGuiObjectController::CheckUserInput(float dt){
}
else if (mEngine->GetButtonState(PSP_CTRL_UP))
{
last_user_move = 0;
if (KeyRepeated(PSP_CTRL_UP, dt))
{
int n = getClosestItem(DIR_UP);
@@ -229,6 +234,7 @@ void PlayGuiObjectController::CheckUserInput(float dt){
}
else if (mEngine->GetButtonState(PSP_CTRL_DOWN))
{
last_user_move = 0;
if (KeyRepeated(PSP_CTRL_DOWN, dt))
{
int n = getClosestItem(DIR_DOWN);
@@ -239,7 +245,7 @@ void PlayGuiObjectController::CheckUserInput(float dt){
}
}
}else if (mEngine->GetButtonClick(PSP_CTRL_TRIANGLE)){
showBigCards = !showBigCards;
showBigCards = (++showBigCards) %3;
}
else{

View File

@@ -1,7 +1,7 @@
#include "../include/debug.h"
#include "../include/Player.h"
#include "../include/GameObserver.h"
#include "../include/DeckStats.h"
Player::Player(MTGPlayerCards * _deck, string file): Damageable(20){
@@ -14,6 +14,11 @@ Player::Player(MTGPlayerCards * _deck, string file): Damageable(20){
type_as_damageable = DAMAGEABLE_PLAYER;
}
/*Method to call at the end of a game, before all objects involved in the game are destroyed */
void Player::End(){
DeckStats::GetInstance()->saveStats(this, opponent(),GameObserver::GetInstance());
}
Player::~Player(){
if (manaPool) delete manaPool;
if (mAvatarTex) delete mAvatarTex;

View File

@@ -2,7 +2,7 @@
#include "../include/SimpleMenu.h"
#include "../include/SimpleMenuItem.h"
SimpleMenu::SimpleMenu(int id, JGuiListener* listener, JLBFont* font, int x, int y, int width, const char * _title): JGuiController(id, listener){
SimpleMenu::SimpleMenu(int id, JGuiListener* listener, JLBFont* font, int x, int y, int width, const char * _title, int _maxItems): JGuiController(id, listener){
mHeight = 0;
mWidth = width;
mX = x;
@@ -15,6 +15,8 @@ SimpleMenu::SimpleMenu(int id, JGuiListener* listener, JLBFont* font, int x, int
}else{
displaytitle = 0;
}
startId = 0;
maxItems = _maxItems;
}
void SimpleMenu::Render(){
@@ -25,10 +27,24 @@ void SimpleMenu::Render(){
renderer->FillRoundRect(mX+2,mY+2,mWidth - 4,mHeight-4,10,ARGB(255,62,62,62));
if (displaytitle)
mFont->DrawString(title.c_str(), mX+10, mY+10);
JGuiController::Render();
for (int i = startId; i < startId + maxItems ; i++){
if (i > mCount-1) break;
((SimpleMenuItem * )mObjects[i])->RenderWithOffset(-20*startId);
}
}
void SimpleMenu::Update(float dt){
JGuiController::Update(dt);
if (mCurr > startId + maxItems-1){
startId = mCurr - maxItems +1;
}else if (mCurr < startId){
startId = mCurr;
}
}
void SimpleMenu::Add(int id, const char * text){
JGuiController::Add(NEW SimpleMenuItem(id, mFont, text, mWidth/2 + mX + 10, mY + 10 + mHeight, (mCount == 0)));
mHeight += 20;
int y = mCount*20;
if (displaytitle) y+=20;
JGuiController::Add(NEW SimpleMenuItem(id, mFont, text, mWidth/2 + mX + 10, mY + 10 + y, (mCount == 0)));
if (mCount <= maxItems) mHeight += 20;
}

View File

@@ -2,10 +2,10 @@
#include "../include/SimpleMenuItem.h"
SimpleMenuItem::SimpleMenuItem(int id, JLBFont *font, const char* text, int x, int y, bool hasFocus): JGuiObject(id), mFont(font), mText(text), mX(x), mY(y)
SimpleMenuItem::SimpleMenuItem(int id, JLBFont *font, const char* text, int x, int y, bool hasFocus): JGuiObject(id), mFont(font), mX(x), mY(y)
{
mText = text;
mHasFocus = hasFocus;
mScale = 1.0f;
@@ -20,7 +20,7 @@ SimpleMenuItem::SimpleMenuItem(int id, JLBFont *font, const char* text, int x, i
}
void SimpleMenuItem::Render()
void SimpleMenuItem::RenderWithOffset(float yOffset)
{
mFont->SetScale(mScale);
@@ -29,10 +29,16 @@ void SimpleMenuItem::Render()
{
mFont->SetColor(ARGB(255,255,255,0));
}
mFont->DrawString(mText, mX, mY, JGETEXT_CENTER);
mFont->DrawString(mText.c_str(), mX, mY + yOffset, JGETEXT_CENTER);
mFont->SetScale(1.0f);
}
void SimpleMenuItem::Render()
{
RenderWithOffset(0);
}
void SimpleMenuItem::Update(float dt)
{
if (mScale < mTargetScale)

View File

@@ -43,3 +43,12 @@ int Subtypes::find(const char * subtype){
return (find(value));
}
/*This will be slow... */
string Subtypes::find(int id){
map<string,int>::iterator it;
for (it = values.begin(); it != values.end(); it++){
if (it->second == id) return it->first;
}
return NULL;
}

View File

@@ -117,3 +117,37 @@ CardTexture::~CardTexture(){
LOG("CardTexture Object deletion Succesful");
}
SampleCache * SampleCache::mInstance = NULL;
SampleCache * SampleCache::GetInstance(){
if (!mInstance) mInstance = NEW SampleCache();
return mInstance;
}
JSample * SampleCache::getSample(string filename){
map<string,JSample *>::iterator it = cache.find(filename);
if (it == cache.end()){
if (cache.size() >10) cleanCache(); //Poor man's limit
JSample * sample = JSoundSystem::GetInstance()->LoadSample(filename.c_str());
if (!sample && fileExists(filename.c_str())){ //Out of Ram ??
cleanCache();
sample = JSoundSystem::GetInstance()->LoadSample(filename.c_str());
}
return sample;
}else{
return (it->second);
}
}
void SampleCache::cleanCache(){
map<string,JSample *>::iterator it;
for (it = cache.begin(); it != cache.end(); it++){
delete(it->second);
}
cache.clear();
}
SampleCache::~SampleCache(){
cleanCache();
}

View File

@@ -142,3 +142,20 @@ int readfile_to_ints(const char * filename, int * out_buffer){
return count;
}
int fileExists(const char * filename){
std::ifstream fichier(filename);
if(fichier){
fichier.close();
return 1;
}
char alternateFilename[512];
sprintf(alternateFilename, "Res/%s",filename);
std::ifstream fichier2(alternateFilename);
if(fichier2){
fichier2.close();
return 1;
}
return 0;
}

View File

@@ -276,6 +276,10 @@
RelativePath=".\src\DeckDataWrapper.cpp"
>
</File>
<File
RelativePath=".\src\DeckStats.cpp"
>
</File>
<File
RelativePath=".\src\DuelLayers.cpp"
>
@@ -565,6 +569,10 @@
RelativePath=".\include\DeckDataWrapper.h"
>
</File>
<File
RelativePath=".\include\DeckStats.h"
>
</File>
<File
RelativePath=".\include\DuelLayers.h"
>