|
|
|
@ -1,5 +1,8 @@ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define OLC_PGE_APPLICATION |
|
|
|
|
#include "olcPixelGameEngine.h" |
|
|
|
|
#define OLC_PGEX_QUICKGUI |
|
|
|
|
#include "olcPGEX_QuickGUI.h" |
|
|
|
|
|
|
|
|
|
using namespace olc; |
|
|
|
|
|
|
|
|
@ -45,7 +48,7 @@ public: |
|
|
|
|
Decal*crossImg; |
|
|
|
|
Decal*gridImg; |
|
|
|
|
|
|
|
|
|
int pieceCount=5; |
|
|
|
|
int pieceCount=5,pieceCount2=5; |
|
|
|
|
PieceType playerSide=CIRCLE; |
|
|
|
|
PieceType opponentSide=CROSS; |
|
|
|
|
|
|
|
|
@ -56,11 +59,16 @@ public: |
|
|
|
|
float aiThinkTime=0; |
|
|
|
|
|
|
|
|
|
bool playingAgainstAI=true; |
|
|
|
|
GameState state=PLAYING; |
|
|
|
|
GameState state=MENU; |
|
|
|
|
Winner outcome=TIE; |
|
|
|
|
|
|
|
|
|
vf2d winLine1,winLine2; |
|
|
|
|
|
|
|
|
|
bool player1Turn=true; |
|
|
|
|
|
|
|
|
|
QuickGUI::Button*aiButton; |
|
|
|
|
QuickGUI::Button*twoPlayerButton; |
|
|
|
|
|
|
|
|
|
void SetOutcome(int score){ |
|
|
|
|
if(score==3){ |
|
|
|
|
outcome=PLAYER_1; |
|
|
|
@ -169,6 +177,8 @@ public: |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
QuickGUI::Manager gui; |
|
|
|
|
|
|
|
|
|
public: |
|
|
|
|
bool OnUserCreate() override |
|
|
|
|
{ |
|
|
|
@ -183,6 +193,9 @@ public: |
|
|
|
|
circleImg=new Decal(new Sprite("circle.png")); |
|
|
|
|
crossImg=new Decal(new Sprite("cross.png")); |
|
|
|
|
gridImg=new Decal(new Sprite("grid.png")); |
|
|
|
|
|
|
|
|
|
aiButton=new QuickGUI::Button(gui,"Play Against AI",{8,64},{ScreenWidth()-16.f,12}); |
|
|
|
|
twoPlayerButton=new QuickGUI::Button(gui,"Play As 2 Players",{8,80},{ScreenWidth()-16.f,12}); |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -192,17 +205,30 @@ public: |
|
|
|
|
|
|
|
|
|
switch(state){ |
|
|
|
|
case MENU:{ |
|
|
|
|
DrawStringDecal({0,0},"This is the menu."); |
|
|
|
|
gui.Update(this); |
|
|
|
|
gui.Draw(this); |
|
|
|
|
|
|
|
|
|
if(aiButton->bPressed){ |
|
|
|
|
state=PLAYING; |
|
|
|
|
playingAgainstAI=true; |
|
|
|
|
} |
|
|
|
|
if(twoPlayerButton->bPressed){ |
|
|
|
|
state=PLAYING; |
|
|
|
|
playingAgainstAI=false; |
|
|
|
|
} |
|
|
|
|
}break; |
|
|
|
|
case PLAYING: |
|
|
|
|
case GAMEOVER:{ |
|
|
|
|
vf2d gridOffset={16,16}; |
|
|
|
|
|
|
|
|
|
Decal*pieceImg; |
|
|
|
|
Decal*opponentPieceImg; |
|
|
|
|
if(playerSide==CIRCLE){ |
|
|
|
|
pieceImg=circleImg; |
|
|
|
|
opponentPieceImg=crossImg; |
|
|
|
|
}else{ |
|
|
|
|
pieceImg=crossImg; |
|
|
|
|
opponentPieceImg=circleImg; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if(state==GAMEOVER){ |
|
|
|
@ -228,19 +254,34 @@ public: |
|
|
|
|
DrawStringDecal(vf2d{ScreenWidth()/2.f,4}-gameOverTextSize/2,gameOverText,BLACK,{0.5,0.5}); |
|
|
|
|
DrawStringDecal(vf2d{ScreenWidth()/2.f,12}-winnerTextSize/2,winnerText,BLACK,{0.5,0.5}); |
|
|
|
|
}else{ |
|
|
|
|
if(aiThinkTime>0){ |
|
|
|
|
aiThinkTime-=fElapsedTime; |
|
|
|
|
if(playingAgainstAI){ |
|
|
|
|
if(aiThinkTime>0){ |
|
|
|
|
aiThinkTime-=fElapsedTime; |
|
|
|
|
|
|
|
|
|
if(aiThinkTime<=0){ |
|
|
|
|
int chosenIndex=rand()%9; |
|
|
|
|
while(gamePieces[chosenIndex].piece!=BLANK){ |
|
|
|
|
chosenIndex=rand()%9; |
|
|
|
|
if(aiThinkTime<=0){ |
|
|
|
|
int chosenIndex=rand()%9; |
|
|
|
|
while(gamePieces[chosenIndex].piece!=BLANK){ |
|
|
|
|
chosenIndex=rand()%9; |
|
|
|
|
} |
|
|
|
|
gamePieces[chosenIndex].piece=opponentSide; |
|
|
|
|
player1Turn=!player1Turn; |
|
|
|
|
AnalyzeBoard(); |
|
|
|
|
} |
|
|
|
|
gamePieces[chosenIndex].piece=opponentSide; |
|
|
|
|
AnalyzeBoard(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
std::string displayText=" The AI \nis thinking..."; |
|
|
|
|
std::string displayText=" The AI \nis thinking..."; |
|
|
|
|
vf2d textSize=vf2d{GetTextSize(displayText)}*0.5; |
|
|
|
|
DrawStringDecal(vf2d{ScreenWidth()/2.f,8}-textSize/2,displayText,BLACK,{0.5,0.5}); |
|
|
|
|
}else{ |
|
|
|
|
std::string displayText="Player's Turn"; |
|
|
|
|
vf2d textSize=vf2d{GetTextSize(displayText)}*0.5; |
|
|
|
|
DrawStringDecal(vf2d{ScreenWidth()/2.f,8}-textSize/2,displayText,BLACK,{0.5,0.5}); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
else{ |
|
|
|
|
std::string displayText="Player 1's Turn"; |
|
|
|
|
if(!player1Turn){ |
|
|
|
|
displayText="Player 2's Turn"; |
|
|
|
|
} |
|
|
|
|
vf2d textSize=vf2d{GetTextSize(displayText)}*0.5; |
|
|
|
|
DrawStringDecal(vf2d{ScreenWidth()/2.f,8}-textSize/2,displayText,BLACK,{0.5,0.5}); |
|
|
|
|
} |
|
|
|
@ -255,11 +296,22 @@ public: |
|
|
|
|
if(GetMouseX()>=upperLeftCorner.x&&GetMouseX()<lowerRightCorner.x&&GetMouseY()>=upperLeftCorner.y&&GetMouseY()<lowerRightCorner.y){ |
|
|
|
|
FillRectDecal(gridOffset+vf2d{float(x),float(y)}*32,{32,32},{0,0,0,64}); |
|
|
|
|
|
|
|
|
|
if(dragging&&GetMouse(Mouse::LEFT).bPressed&&aiThinkTime<=0){ |
|
|
|
|
if(dragging&&GetMouse(Mouse::LEFT).bPressed&&aiThinkTime<=0&&state!=GAMEOVER){ |
|
|
|
|
if(gamePieces[index].piece==BLANK){ |
|
|
|
|
gamePieces[index].piece=playerSide; |
|
|
|
|
if(!playingAgainstAI){ |
|
|
|
|
if(player1Turn){ |
|
|
|
|
gamePieces[index].piece=playerSide; |
|
|
|
|
}else{ |
|
|
|
|
gamePieces[index].piece=opponentSide; |
|
|
|
|
} |
|
|
|
|
}else{ |
|
|
|
|
gamePieces[index].piece=playerSide; |
|
|
|
|
} |
|
|
|
|
dragging=false; |
|
|
|
|
aiThinkTime=rand()%3+1; |
|
|
|
|
if(playingAgainstAI){ |
|
|
|
|
aiThinkTime=rand()%3+1; |
|
|
|
|
} |
|
|
|
|
player1Turn=!player1Turn; |
|
|
|
|
AnalyzeBoard(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -281,13 +333,25 @@ public: |
|
|
|
|
FillRectDecal({0,120},{float(ScreenWidth()),40},{0,0,0,64}); |
|
|
|
|
|
|
|
|
|
if(GetMouse(Mouse::LEFT).bPressed){ |
|
|
|
|
if(dragging){ |
|
|
|
|
pieceCount++; |
|
|
|
|
dragging=false; |
|
|
|
|
if(playingAgainstAI||player1Turn){ |
|
|
|
|
if(dragging){ |
|
|
|
|
pieceCount++; |
|
|
|
|
dragging=false; |
|
|
|
|
}else |
|
|
|
|
if(pieceCount>0){ |
|
|
|
|
dragging=true; |
|
|
|
|
pieceCount--; |
|
|
|
|
} |
|
|
|
|
}else |
|
|
|
|
if(pieceCount>0){ |
|
|
|
|
dragging=true; |
|
|
|
|
pieceCount--; |
|
|
|
|
{ |
|
|
|
|
if(dragging){ |
|
|
|
|
pieceCount2++; |
|
|
|
|
dragging=false; |
|
|
|
|
}else |
|
|
|
|
if(pieceCount2>0){ |
|
|
|
|
dragging=true; |
|
|
|
|
pieceCount2--; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -299,12 +363,21 @@ public: |
|
|
|
|
DrawDecal(gridOffset,gridImg); |
|
|
|
|
|
|
|
|
|
if(dragging){ |
|
|
|
|
DrawRotatedDecal(GetMousePos(),pieceImg,0,pieceImg->sprite->Size()/2); |
|
|
|
|
if(playingAgainstAI||player1Turn){ |
|
|
|
|
DrawRotatedDecal(GetMousePos(),pieceImg,0,pieceImg->sprite->Size()/2); |
|
|
|
|
}else{ |
|
|
|
|
DrawRotatedDecal(GetMousePos(),opponentPieceImg,0,opponentPieceImg->sprite->Size()/2); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
for(int i=0;i<pieceCount;i++){ |
|
|
|
|
DrawDecal(vf2d{4.f+i*8,128},pieceImg); |
|
|
|
|
} |
|
|
|
|
if(!playingAgainstAI){ |
|
|
|
|
for(int i=0;i<pieceCount2;i++){ |
|
|
|
|
DrawDecal(vf2d{ScreenWidth()-4.f-32-i*8,128},opponentPieceImg); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
}break; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|