293 lines
		
	
	
		
			8.3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			293 lines
		
	
	
		
			8.3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /////////////////////////////////////////////////////////////////////////////
 | |
| // Name:        pile.cpp
 | |
| // Purpose:     Forty Thieves patience game
 | |
| // Author:      Chris Breeze
 | |
| // Modified by:
 | |
| // Created:     21/07/97
 | |
| // Copyright:   (c) 1993-1998 Chris Breeze
 | |
| // Licence:     wxWindows licence
 | |
| //---------------------------------------------------------------------------
 | |
| // Last modified: 22nd July 1998 - ported to wxWidgets 2.0
 | |
| /////////////////////////////////////////////////////////////////////////////
 | |
| //+-------------------------------------------------------------+
 | |
| //| Description:                                                |
 | |
| //| The base class for holding piles of playing cards.          |
 | |
| //+-------------------------------------------------------------+
 | |
| 
 | |
| // For compilers that support precompilation, includes "wx/wx.h".
 | |
| #include "wx/wxprec.h"
 | |
| 
 | |
| #ifdef __BORLANDC__
 | |
| #pragma hdrstop
 | |
| #endif
 | |
| 
 | |
| #ifndef WX_PRECOMP
 | |
| #include "wx/wx.h"
 | |
| #endif
 | |
| 
 | |
| #include <stdlib.h>
 | |
| #include <stdio.h>
 | |
| #include <time.h>
 | |
| #include <string.h>
 | |
| #include "card.h"
 | |
| #include "pile.h"
 | |
| #include "forty.h"
 | |
| #include "canvas.h"
 | |
| 
 | |
| #include "wx/app.h"
 | |
| 
 | |
| //+-------------------------------------------------------------+
 | |
| //| Pile::Pile()                                                |
 | |
| //+-------------------------------------------------------------+
 | |
| //| Description:                                                |
 | |
| //| Initialise the pile to be empty of cards.                   |
 | |
| //+-------------------------------------------------------------+
 | |
| Pile::Pile(int x, int y, int dx, int dy)
 | |
| {
 | |
|     m_x = x;
 | |
|     m_y = y;
 | |
|     m_dx = dx;
 | |
|     m_dy = dy;
 | |
|     for (m_topCard = 0; m_topCard < NumCards; m_topCard++)
 | |
|     {
 | |
|         m_cards[m_topCard] = 0;
 | |
|     }
 | |
|     m_topCard = -1; // i.e. empty
 | |
| }
 | |
| 
 | |
| 
 | |
| //+-------------------------------------------------------------+
 | |
| //| Pile::Redraw()                                              |
 | |
| //+-------------------------------------------------------------+
 | |
| //| Description:                                                |
 | |
| //| Redraw the pile on the screen. If the pile is empty         |
 | |
| //| just draw a NULL card as a place holder for the pile.       |
 | |
| //| Otherwise draw the pile from the bottom up, starting        |
 | |
| //| at the origin of the pile, shifting each subsequent         |
 | |
| //| card by the pile's x and y offsets.                         |
 | |
| //+-------------------------------------------------------------+
 | |
| void Pile::Redraw(wxDC& dc )
 | |
| {
 | |
|     FortyFrame *frame = (FortyFrame*) wxTheApp->GetTopWindow();
 | |
|     wxWindow *canvas = (wxWindow *) NULL;
 | |
|     if (frame)
 | |
|     {
 | |
|         canvas = frame->GetCanvas();
 | |
|     }
 | |
| 
 | |
|     if (m_topCard >= 0)
 | |
|     {
 | |
|         if (m_dx == 0 && m_dy == 0)
 | |
|         {
 | |
|             if ((canvas) && (canvas->IsExposed(m_x,m_y,(int)(Card::GetScale()*60),(int)(Card::GetScale()*200))))
 | |
|                 m_cards[m_topCard]->Draw(dc, m_x, m_y);
 | |
|         }
 | |
|         else
 | |
|         {
 | |
|             int x = m_x;
 | |
|             int y = m_y;
 | |
|             for (int i = 0; i <= m_topCard; i++)
 | |
|             {
 | |
|                 if ((canvas) && (canvas->IsExposed(x,y,(int)(Card::GetScale()*60),(int)(Card::GetScale()*200))))
 | |
|                     m_cards[i]->Draw(dc, x, y);
 | |
|                               x += (int)Card::GetScale()*m_dx;
 | |
|                               y += (int)Card::GetScale()*m_dy;
 | |
|             }
 | |
|         }
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|         if ((canvas) && (canvas->IsExposed(m_x,m_y,(int)(Card::GetScale()*60),(int)(Card::GetScale()*200))))
 | |
|             Card::DrawNullCard(dc, m_x, m_y);
 | |
|     }
 | |
| }
 | |
| 
 | |
| 
 | |
| //+-------------------------------------------------------------+
 | |
| //| Pile::GetTopCard()                                          |
 | |
| //+-------------------------------------------------------------+
 | |
| //| Description:                                                |
 | |
| //| Return a pointer to the top card in the pile or NULL        |
 | |
| //| if the pile is empty.                                       |
 | |
| //| NB: Gets a copy of the card without removing it from the    |
 | |
| //| pile.                                                       |
 | |
| //+-------------------------------------------------------------+
 | |
| Card* Pile::GetTopCard()
 | |
| {
 | |
|     Card* card = 0;
 | |
| 
 | |
|     if (m_topCard >= 0)
 | |
|     {
 | |
|         card = m_cards[m_topCard];
 | |
|     }
 | |
|     return card;
 | |
| }
 | |
| 
 | |
| 
 | |
| //+-------------------------------------------------------------+
 | |
| //| Pile::RemoveTopCard()                                       |
 | |
| //+-------------------------------------------------------------+
 | |
| //| Description:                                                |
 | |
| //| If the pile is not empty, remove the top card from the      |
 | |
| //| pile and return the pointer to the removed card.            |
 | |
| //| If the pile is empty return a NULL pointer.                 |
 | |
| //+-------------------------------------------------------------+
 | |
| Card* Pile::RemoveTopCard()
 | |
| {
 | |
|     Card* card = 0;
 | |
| 
 | |
|     if (m_topCard >= 0)
 | |
|     {
 | |
|         card = m_cards[m_topCard--];
 | |
|     }
 | |
|     return card;
 | |
| }
 | |
| 
 | |
| 
 | |
| //+-------------------------------------------------------------+
 | |
| //| Pile::RemoveTopCard()                                       |
 | |
| //+-------------------------------------------------------------+
 | |
| //| Description:                                                |
 | |
| //| As RemoveTopCard() but also redraw the top of the pile      |
 | |
| //| after the card has been removed.                            |
 | |
| //| NB: the offset allows for the redrawn area to be in a       |
 | |
| //| bitmap ready for 'dragging' cards acrosss the screen.       |
 | |
| //+-------------------------------------------------------------+
 | |
| Card* Pile::RemoveTopCard(wxDC& dc, int xOffset, int yOffset)
 | |
| {
 | |
|     int topX, topY;
 | |
| 
 | |
|     GetTopCardPos(topX, topY);
 | |
|     Card* card = RemoveTopCard();
 | |
| 
 | |
|     if (card)
 | |
|     {
 | |
|         int x, y;
 | |
|         card->Erase(dc, topX - xOffset, topY - yOffset);
 | |
|         GetTopCardPos(x, y);
 | |
|         if (m_topCard < 0)
 | |
|         {
 | |
|             Card::DrawNullCard(dc, x - xOffset, y - yOffset);
 | |
|         }
 | |
|         else
 | |
|         {
 | |
|             m_cards[m_topCard]->Draw(dc, x - xOffset, y - yOffset);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return card;
 | |
| }
 | |
| 
 | |
| 
 | |
| void Pile::GetTopCardPos(int& x, int& y)
 | |
| {
 | |
|     if (m_topCard < 0)
 | |
|     {
 | |
|         x = m_x;
 | |
|         y = m_y;
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|         x = m_x + (int)Card::GetScale()*m_dx * m_topCard;
 | |
|         y = m_y + (int)Card::GetScale()*m_dy * m_topCard;
 | |
|     }
 | |
| }
 | |
| 
 | |
| void Pile::AddCard(Card* card)
 | |
| {
 | |
|     if (m_topCard < -1) m_topCard = -1;
 | |
| 
 | |
|     m_cards[++m_topCard] = card;
 | |
| }
 | |
| 
 | |
| void Pile::AddCard(wxDC& dc, Card* card)
 | |
| {
 | |
|     AddCard(card);
 | |
|     int x, y;
 | |
|     GetTopCardPos(x, y);
 | |
|     card->Draw(dc, x, y);
 | |
| }
 | |
| 
 | |
| // Can the card leave this pile.
 | |
| // If it is a member of the pile then the answer is yes.
 | |
| // Derived classes may override this behaviour to incorporate
 | |
| // the rules of the game
 | |
| bool Pile::CanCardLeave(Card* card)
 | |
| {
 | |
|     for (int i = 0; i <= m_topCard; i++)
 | |
|     {
 | |
|         if (card == m_cards[i]) return true;
 | |
|     }
 | |
|     return false;
 | |
| }
 | |
| 
 | |
| // Calculate how far x, y is from top card in the pile
 | |
| // Returns the square of the distance
 | |
| int Pile::CalcDistance(int x, int y)
 | |
| {
 | |
|     int cx, cy;
 | |
|     GetTopCardPos(cx, cy);
 | |
|     return ((cx - x) * (cx - x) + (cy - y) * (cy - y));
 | |
| }
 | |
| 
 | |
| 
 | |
| // Return the card at x, y. Check the top card first, then
 | |
| // work down the pile. If a card is found then return a pointer
 | |
| // to the card, otherwise return NULL
 | |
| Card* Pile::GetCard(int x, int y)
 | |
| {
 | |
|     int cardX;
 | |
|     int cardY;
 | |
|     GetTopCardPos(cardX, cardY);
 | |
| 
 | |
|     for (int i = m_topCard; i >= 0; i--)
 | |
|     {
 | |
|         if (x >= cardX && x <= cardX + Card::GetWidth() &&
 | |
|             y >= cardY && y <= cardY + Card::GetHeight())
 | |
|         {
 | |
|             return m_cards[i];
 | |
|         }
 | |
|         cardX -= (int)Card::GetScale()*m_dx;
 | |
|         cardY -= (int)Card::GetScale()*m_dy;
 | |
|     }
 | |
|     return 0;
 | |
| }
 | |
| 
 | |
| 
 | |
| // Return the position of the given card. If it is not a member of this pile
 | |
| // return the origin of the pile.
 | |
| void Pile::GetCardPos(Card* card, int& x, int& y)
 | |
| {
 | |
|     x = m_x;
 | |
|     y = m_y;
 | |
| 
 | |
|     for (int i = 0; i <= m_topCard; i++)
 | |
|     {
 | |
|         if (card == m_cards[i])
 | |
|         {
 | |
|             return;
 | |
|         }
 | |
|         x += (int)Card::GetScale()*m_dx;
 | |
|         y += (int)Card::GetScale()*m_dy;
 | |
|     }
 | |
| 
 | |
|     // card not found in pile, return origin of pile
 | |
|     x = m_x;
 | |
|     y = m_y;
 | |
| }
 | |
| 
 | |
| 
 | |
| bool Pile::Overlap(int x, int y)
 | |
| {
 | |
|     int cardX;
 | |
|     int cardY;
 | |
|     GetTopCardPos(cardX, cardY);
 | |
| 
 | |
|     if (x >= cardX - Card::GetWidth()  && x <= cardX + Card::GetWidth() &&
 | |
|         y >= cardY - Card::GetHeight() && y <= cardY + Card::GetHeight())
 | |
|     {
 | |
|         return true;
 | |
|     }
 | |
|     return false;
 | |
| }
 |