/****************/ /* tictacd.cpp */ /****************/ // Esimerkki pelistä jossa piirretään nappuloita. // Projektiin tictacd.cpp, tictac.rc // Lisäksi tarvitaan TYHJA.BMP, RUKSI.BMP, PALLO.BMP ja TICTAC.ICO // sekä ALI\delaymov.h ja ALI\liikkuva.h // // Vesa Lappalainen 6.11.1996 // TWindow-ikkunasta perittyä luokkaa käyttävä versio // // Muutoksia: 7.11.1996 ix<->iy taulukoissa // 9.11.1996 liikkuvat nappulat // 11.11.1996 muutokset alaspäin OWL 5.0 => OWL 2.5 // - owl\pch.h => owl\owlpch.h // - bitmampissa Size().cx => Width() // Size().cy => Height() // - ei metodia SetIconSm => pois (ehdollisesti) // .RC -tiedostossa: // - DS_3DLOOK => pois // - SS_SUNKEN => pois // Näidenkään muutosten jälkeen bittikarta eivät näy // Syy: MoveWindow -ei toimi rakentajassa (OWL 2.5:ssa!) // - TLiikkuvaNappi rakentajassa: SetOriginalPt(pt()); pois // - (metodi lis. cLiikkuva: SetOriginalPt(aix,aiy); ) // cLiikkuva rakentajaan : originalpt(wnd->Attr.X,wnd->Attr.Y) // - TNappi::MoveWindow(TRect(id)); => // Attr.X = id.x(); Attr.Y = id.y(); // Attr.W = id.w(); Attr.H = id.h(); // // Lisäksi liikkuva.h:ssa bugi: // - rakentajaan lisättävä MouseDown(false) // Menussa ei toimi ALT-valinta: (auttaa myös OWL 5.0:ssa) => // - otetaan pois .RC:ssä dialogista tyyli WS_SYSMENU // // Tehtäviä: (vrt. myös BC5\EXAMPLES\OWL\GAMES\TTT\*.cpp) // 1) Laita uusi peli sellaiseksi, että laudan alkunappulat // ovat hujan hajan pitkin pöytää ja "konvergoivat" kohti oikeaa // paikkansa // 2) Koska StretchBlt on hidas, niin muuta ohjelmaa siten, että uuden pelin // alussa bittikartat kopioidaan venytetyinä toisiin bittikarttoihin, // jotka sitten varsinaisesti piirretään. // #include #include "owl\liikkuva.h" #include "tictac.rh" LIIKKUVATBL // Jos ei jakseta laittaa projektiin liikkuva.cpp:ta const int MAX_NX = 11; const int MAX_NY = 11; const int MAX_PELAAJIA = 2; //------------------------------------------------------------------------------ class TNapSize { // Nappulan kokoa ja alkupaikkaa kuvaava luokka TPoint origo; TSize koko; public: TNapSize(TPoint &p,TSize &k) : origo(p), koko(k) {} const TPoint &Origo() const { return origo; } const TSize &Koko() const { return koko; } }; // TNapSize //------------------------------------------------------------------------------ class TId { // Luokka, joka osaa muttua ID <-> x,y ja ix,iy int ix,iy; // index x,y (0-2) const TNapSize &ns; public: TId(int aix,int aiy, const TNapSize &s) : ns(s), ix(aix), iy(aiy) { } virtual int x() const { return ns.Origo().x + ix*ns.Koko().cx; } virtual int y() const { return ns.Origo().y + iy*ns.Koko().cy; } virtual int w() const { return ns.Koko().cx; } virtual int h() const { return ns.Koko().cy; } virtual int inx() const { return ix; } virtual int iny() const { return iy; } virtual TPoint pt() const { return TPoint(x(),y()); } virtual TSize sz() const { return TSize(w(),h()); } virtual operator TPoint() const { return pt(); } virtual operator TSize() const { return sz(); } virtual operator TRect() const { return TRect(pt(),sz()); } }; // TId //------------------------------------------------------------------------------ class TLauta; // Eteenpäin viittaus, koska nyt Lauta ja Nappi "keskustelevat" //------------------------------------------------------------------------------ class TNappi : public TWindow { // Varsinainen pelinappula protected: TLauta &lauta; // Tietää mihin lautaan kuuluu int type; // ja mitä tyyppiä itse on TId id; // sekä oman paikkansa indekseinä public: TNappi(TWindow* parent, int aix, int aiy, const TNapSize &ns, TLauta <, int t=0, TModule* module = 0) : id(aix,aiy,ns), lauta(lt), type(t), TWindow(parent) { Attr.Style |= WS_CHILD | WS_VISIBLE; Attr.X = id.x(); Attr.Y = id.y(); Attr.W = id.w(); Attr.H = id.h(); } virtual const TBitmap &b(); virtual void Draw(TDC &dc) { // TClientDC dc(*this); TMemoryDC memDC(dc); memDC.SelectObject(b()); #if 1 dc.StretchBlt(0,0,id.w(),id.h(),memDC, 0,0,b().Width(),b().Height(),SRCCOPY); #else dc.BitBlt(0,0,id.w(),id.h(),memDC,0,0,SRCCOPY); #endif } virtual void SetType(int t) { type = t; Invalidate(); } virtual int Type() { return type; } virtual int Includes(const TPoint &p) { #if 1 TRect rc; GetWindowRect(rc); if ( p.x <= Attr.X ) return 0; if ( Attr.X + Attr.W <= p.x ) return 0; if ( p.y <= Attr.Y ) return 0; if ( Attr.Y + Attr.H <= p.y ) return 0; return 1; #else // Seuraava ei toimi, koska rc näytön koordinaateissa ja p isäikkunan RECT rc; ::GetWindowRect(*this,&rc); return PtInRect(&rc,p); #endif } virtual void Paint(TDC &dc,bool,TRect &) { Draw(dc); } virtual void EvLButtonDown(uint modKeys, TPoint& point); DECLARE_RESPONSE_TABLE(TNappi); }; // TNappi DEFINE_RESPONSE_TABLE1(TNappi, TWindow) EV_WM_PAINT, EV_WM_LBUTTONDOWN, END_RESPONSE_TABLE; //------------------------------------------------------------------------------ class TLiikkuvaNappi : virtual public TNappi, public cLiikkuva { // Liikkuva pelinappula public: TLiikkuvaNappi(TWindow* parent, int aix, int aiy, const TNapSize &ns, TLauta <, int t=0, TModule* module = 0) : TNappi(parent,aix,aiy,ns,lt,t,module), cLiikkuva(this) { SetAutoReturn(4000); Attr.Style |= WS_CLIPSIBLINGS | WS_CLIPCHILDREN; } void Drop(TPoint pt); DECLARE_RESPONSE_TABLE(TLiikkuvaNappi); }; // TLiikkuvaNappi DEFINE_RESPONSE_TABLE2(TLiikkuvaNappi, cLiikkuva, TNappi) END_RESPONSE_TABLE; //------------------------------------------------------------------------------ class TLauta { int nx,ny; TNapSize ns; TNappi *lauta[MAX_NX][MAX_NY]; TLiikkuvaNappi *lnappi[MAX_PELAAJIA]; TBitmap *bmps[MAX_PELAAJIA+1]; TWindow *Wnd; int pelaaja; protected: void CreateButtons(); void DeleteButtons(); public: TLauta(TWindow *awnd,int anx=3,int any=3); ~TLauta(); void uusi(int unx=0,int uny=0) { pelaaja = 0; Wnd->Show(SW_HIDE); DeleteButtons(); if ( unx != 0 && uny != 0 ) { nx = unx; ny = uny; } CreateButtons(); Wnd->Show(SW_SHOW); } TNappi *etsi(const TPoint &pt); int Hit(TNappi &nap) { nap.SetType(pelaaja+1); pelaaja++; if ( pelaaja >= MAX_PELAAJIA ) pelaaja = 0; return 0; } int Hit(const TPoint &pt,int type) { if ( type != pelaaja+1 ) return -1; TNappi *nap = etsi(pt); if ( !nap || nap->Type() ) return -1; return Hit(*nap); } const TBitmap &BitMap(int i) { return *bmps[i]; } }; // TLauta TNappi *TLauta::etsi(const TPoint &pt) { for (int iy=0; iyIncludes(pt) ) return nap; } return NULL; } TLauta::TLauta(TWindow *awnd,int anx,int any) : nx(anx), ny(any), ns(TPoint(20,20),TSize(30,30)), Wnd(awnd) { pelaaja = 0; const TModule &module(*Wnd->GetModule()); for (int i=0; iSetAutoReturn(500); } if ( nx >= MAX_NX ) nx = MAX_NX-1; if ( ny >= MAX_NY ) ny = MAX_NY-1; for (int iy=0; iyCreateChildren(); // Jos tämä on täällä, ei saa kutsua konstruktorissa } // jollei ole, PITÄÄ kutsua!!! void TLauta::DeleteButtons() { for (int iy=0; iyuusi(); } void CmNxN(WPARAM id) { lauta->uusi(id%100,id%100); } DECLARE_RESPONSE_TABLE(TTicTacDialog); }; // TTicTacDialog DEFINE_RESPONSE_TABLE1(TTicTacDialog, TDialog) EV_COMMAND(CM_GAMEEXIT ,CmExit), EV_COMMAND(CM_GAMENEW ,CmNew), EV_COMMAND_AND_ID(CM_GAME_3x3 ,CmNxN), EV_COMMAND_AND_ID(CM_GAME_4x4 ,CmNxN), END_RESPONSE_TABLE; //------------------------------------------------------------------------------ class TTicTacApp : public TApplication { public: TTicTacApp(const char *title) : TApplication(title) {} void InitMainWindow() { TDecoratedFrame *fw = new TDecoratedFrame(0, Name, new TTicTacDialog(0, IDD_TICTAC) ); fw->SetFlag(wfShrinkToClient); fw->AssignMenu(IDM_PAAMENU); fw->SetIcon(this, IDI_IKONI); #if (__BORLANDC__ >= 0x500) fw->SetIconSm(this, IDI_IKONI); #endif fw->Attr.AccelTable = IDM_PAAMENU; SetMainWindow(fw); } }; // TTicTacApp /********************* Pääohjelma *********************************************/ int OwlMain(int ,char far * []) { return TTicTacApp("TicTacToe").Run(); }