summaryrefslogtreecommitdiffstats
path: root/kwin4/kwin4/kwin4view.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kwin4/kwin4/kwin4view.cpp')
-rw-r--r--kwin4/kwin4/kwin4view.cpp729
1 files changed, 729 insertions, 0 deletions
diff --git a/kwin4/kwin4/kwin4view.cpp b/kwin4/kwin4/kwin4view.cpp
new file mode 100644
index 00000000..20d83dee
--- /dev/null
+++ b/kwin4/kwin4/kwin4view.cpp
@@ -0,0 +1,729 @@
+/***************************************************************************
+ kwin4view.cpp - View of the kwin4 program
+ -------------------
+ begin : Sun Mar 26 12:50:12 CEST 2000
+ copyright : (C) |1995-2000 by Martin Heni
+ email : martin@heni-online.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "kwin4view.h"
+
+#include <stdio.h>
+#include <math.h>
+
+#include <kconfig.h>
+#include <klocale.h>
+#include <kapplication.h>
+#include <kstandarddirs.h>
+
+#include "kwin4doc.h"
+#include "scorewidget.h"
+#include "statuswidget.h"
+#include "kspritecache.h"
+
+#include <qlabel.h>
+#include <qlcdnumber.h>
+
+#define COL_STATUSLIGHT QColor(210,210,255)
+#define COL_STATUSFIELD QColor(130,130,255)
+#define COL_STATUSDARK QColor(0,0,65)
+
+#define COL_STATUSBORDER black
+#define COL_PLAYER QColor(255,255,0)
+#define COL_RED red
+#define COL_YELLOW yellow
+
+class KIntroMove : public KSpriteMove
+{
+ public:
+ KIntroMove() : KSpriteMove() {mode=0;cnt=0;}
+ virtual bool spriteMove(double tx,double ty,KSprite *sp)
+ {
+ double sign=1.0;
+ if (!dir) sign=-1.0;
+ if (mode==0)
+ {
+ cnt++;
+ if (sp->x()<120.0)
+ {
+ sp->spriteMove(tx,ty);
+ return true;
+ }
+ else
+ {
+ cnt=0;
+ mode=1;
+ cx=sp->x();
+ cy=sp->y()-sign*50;
+ }
+ }
+ if (mode==1)
+ {
+ if (cnt<360)
+ {
+ double x,y;
+ x=cx+50*cos((sign*90.0-sign*(double)cnt)/180.0*M_PI);
+ y=cy+50*sin((sign*90.0-sign*(double)cnt)/180.0*M_PI);
+ sp->move(x,y);
+ cnt+=5;
+ }
+ else
+ {
+ cnt=0;
+ mode=2;
+ }
+ }
+ if (mode==2)
+ {
+ return sp->spriteMove(tx,ty);
+ }
+
+ return true;
+ }
+
+ void setDir(bool d) {dir=d;}
+
+private:
+
+ bool dir;
+ int mode;
+ int cnt;
+ double cx,cy;
+
+};
+
+Kwin4View::Kwin4View(Kwin4Doc *theDoc, QWidget *parent, const char *name)
+ : QCanvasView(0,parent, name), doc(theDoc)
+{
+ mLastArrow=-1;
+
+
+ // localise data file
+ QString file="kwin4/grafix/default/grafix.rc";
+ QString mGrafix=kapp->dirs()->findResourceDir("data",file);
+ if (mGrafix.isNull())
+ mGrafix="grafix/default/";
+ else
+ mGrafix+="kwin4/grafix/default/";
+ if (global_debug>3)
+ kdDebug(12010) << "Localised grafix dir " << mGrafix << endl;
+
+ // Allow overriding of the grafix directory
+ // This is a cheap and dirty way for theming
+ kapp->config()->setGroup("Themes");
+ mGrafix = kapp->config()->readPathEntry("grafixdir", mGrafix);
+
+
+ setVScrollBarMode(AlwaysOff);
+ setHScrollBarMode(AlwaysOff);
+
+ //setBackgroundMode(PaletteBase);
+ setBackgroundColor(QColor(0,0,128));
+
+ mCanvas=new QCanvas(parent);
+ mCanvas->resize(parent->width(),parent->height());
+ mCanvas->setDoubleBuffering(true);
+ mCanvas->setBackgroundColor(QColor(0,0,128));
+ setCanvas(mCanvas);
+
+ mCache=new KSpriteCache(mGrafix,this);
+ mCache->setCanvas(mCanvas);
+ KConfig *config=mCache->config();
+
+ QPoint pnt;
+ config->setGroup("game");
+
+ pnt=config->readPointEntry("scorewidget");
+ mScoreWidget=new ScoreWidget(viewport());
+ addChild(mScoreWidget);
+ mScoreWidget->move(pnt);
+
+ pnt=config->readPointEntry("statuswidget");
+ mStatusWidget=new StatusWidget(this);
+ mStatusWidget->move(pnt);
+ QPalette pal;
+ pal.setColor(QColorGroup::Light, COL_STATUSLIGHT);
+ pal.setColor(QColorGroup::Mid, COL_STATUSFIELD);
+ pal.setColor(QColorGroup::Dark, COL_STATUSDARK);
+ mStatusWidget->setPalette(pal);
+ mStatusWidget->setBackgroundColor(COL_STATUSFIELD);
+
+ mStatusWidget->wins->setBackgroundColor(COL_STATUSFIELD);
+ mStatusWidget->draws->setBackgroundColor(COL_STATUSFIELD);
+ mStatusWidget->loses->setBackgroundColor(COL_STATUSFIELD);
+ mStatusWidget->num->setBackgroundColor(COL_STATUSFIELD);
+ mStatusWidget->bk->setBackgroundColor(COL_STATUSFIELD);
+
+ mStatusWidget->p1_name->setBackgroundColor(COL_STATUSFIELD);
+ mStatusWidget->p1_w->setBackgroundColor(COL_STATUSFIELD);
+ mStatusWidget->p1_d->setBackgroundColor(COL_STATUSFIELD);
+ mStatusWidget->p1_l->setBackgroundColor(COL_STATUSFIELD);
+ mStatusWidget->p1_n->setBackgroundColor(COL_STATUSFIELD);
+ mStatusWidget->p1_b->setBackgroundColor(COL_STATUSFIELD);
+
+ mStatusWidget->p2_name->setBackgroundColor(COL_STATUSFIELD);
+ mStatusWidget->p2_w->setBackgroundColor(COL_STATUSFIELD);
+ mStatusWidget->p2_d->setBackgroundColor(COL_STATUSFIELD);
+ mStatusWidget->p2_l->setBackgroundColor(COL_STATUSFIELD);
+ mStatusWidget->p2_n->setBackgroundColor(COL_STATUSFIELD);
+ mStatusWidget->p2_b->setBackgroundColor(COL_STATUSFIELD);
+
+ mScoreWidget->hide();
+ mStatusWidget->hide();
+
+ move(0,0);
+ adjustSize();
+
+ initView(false);
+}
+
+void Kwin4View::initView(bool deleteall)
+{
+ KSprite *sprite=0;
+ // mCanvas->setAdvancePeriod(period);
+ mCanvas->setAdvancePeriod(15);
+
+ KConfig *config=mCache->config();
+ config->setGroup("game");
+ mSpreadX=config->readNumEntry("spread_x",0);
+ mSpreadY=config->readNumEntry("spread_y",0);
+ //kdDebug(12010) << "Spread : x=" << mSpreadX << " y=" << mSpreadY << endl;
+
+ QPixmap *pixmap=loadPixmap("background.png");
+ if (pixmap)
+ mCanvas->setBackgroundPixmap(*pixmap);
+ else
+ mCanvas->setBackgroundColor(QColor(0,0,128));
+ delete pixmap;
+
+ if (doc->gameStatus()==KGame::Intro)
+ {
+ mScoreWidget->hide();
+ mStatusWidget->hide();
+ drawIntro(deleteall);
+ }
+ else
+ {
+ // TODO in start functions to distinguish from intro
+ kdDebug(12010) << "Clearing board" <<endl;
+ drawBoard(deleteall);
+ mScoreWidget->show();
+ mStatusWidget->show();
+ // Hide pieces in any case
+ for (int i=0;i<42;i++)
+ {
+ sprite=(KSprite *)(mCache->getItem("piece",i));
+ if (sprite)
+ {
+ introMoveDone(sprite,0 );
+ sprite->hide();
+ }
+ }
+ hideIntro();
+ }
+
+ // Hide stars in any case
+ for (int i=0;i<8;i++)
+ {
+ sprite=(KSprite *)(mCache->getItem("star",i));
+ if (sprite) sprite->hide();
+ }
+ // Hide GameOver in any case
+ sprite=(KSprite *)(mCache->getItem("gameover",1));
+ if (sprite) sprite->hide();
+
+
+ // Hide hint in any case
+ setHint(0,0,false);
+
+ // Clear error text
+ clearError();
+}
+
+QPixmap *Kwin4View::loadPixmap(QString name)
+{
+ if (!mCache)
+ return 0;
+ return mCache->loadPixmap(name);
+}
+
+/**
+ * Called by the doc/app to signal the end of the game
+ */
+void Kwin4View::EndGame()
+{
+ KSprite *sprite;
+ sprite=(KSprite *)(mCache->getItem("gameover",1));
+ KConfig *config=mCache->config();
+ int dest=config->readNumEntry("destY",150);
+ int src=config->readNumEntry("y",0);
+ //kdDebug(12010) << "MOVING gameover to " << dest << endl;
+
+ if (sprite)
+ {
+ sprite->show();
+ sprite->setY(src);
+ sprite->moveTo(sprite->x(),dest);
+ }
+}
+
+/**
+ * Draw Sprites
+ */
+void Kwin4View::drawStar(int x,int y,int no)
+{
+ int dx,dy;
+ y=5-y;
+ KSprite *piece=(KSprite *)(mCache->getItem("piece",0));
+ if (piece)
+ {
+ dx=piece->width();
+ dy=piece->height();
+ }
+ else
+ {
+ dx=0;
+ dy=0;
+ }
+
+ KSprite *sprite=(KSprite *)(mCache->getItem("star",no));
+ //kdDebug(12010) << " setStar("<<x<<","<<y<<","<<no<<") sprite=" << sprite<<endl;
+ if (sprite)
+ {
+ sprite->move(dx/2-sprite->width()/2+x*(dx+mSpreadX)+mBoardX,
+ dy/2-sprite->height()/2+y*(dy+mSpreadY)+mBoardY);
+ sprite->show();
+ sprite->setAnimation(0);
+ }
+}
+
+void Kwin4View::hideIntro()
+{
+ KSprite *sprite=0;
+ sprite=(KSprite *)(mCache->getItem("about",1));
+ if (sprite) sprite->hide();
+ sprite=(KSprite *)(mCache->getItem("win4about",1));
+ if (sprite) sprite->hide();
+ sprite=(KSprite *)(mCache->getItem("win4about",2));
+ if (sprite) sprite->hide();
+
+ QCanvasText *text;
+ text=(QCanvasText *)(mCache->getItem("intro1",1));
+ if (text) text->hide();
+ text=(QCanvasText *)(mCache->getItem("intro2",1));
+ if (text) text->hide();
+ text=(QCanvasText *)(mCache->getItem("intro3",1));
+ if (text) text->hide();
+}
+
+void Kwin4View::drawIntro(bool /*remove*/)
+{
+ KSprite *sprite=0;
+ // background
+ sprite=(KSprite *)(mCache->getItem("about",1));
+ if (sprite) sprite->show();
+
+ sprite=(KSprite *)(mCache->getItem("win4about",1));
+ if (sprite) sprite->show();
+ sprite=(KSprite *)(mCache->getItem("win4about",2));
+ if (sprite)
+ {
+ KConfig *config=mCache->config();
+ double dest=config->readDoubleNumEntry("x2",250.0);
+ sprite->setX(dest);
+ sprite->show();
+ }
+
+ QCanvasText *text;
+ text=(QCanvasText *)(mCache->getItem("intro1",1));
+ if (text)
+ {
+ text->setText(i18n("1. intro line, welcome to win4","Welcome"));
+ text->show();
+ }
+ text=(QCanvasText *)(mCache->getItem("intro2",1));
+ if (text)
+ {
+ text->setText(i18n("2. intro line, welcome to win4","to"));
+ text->show();
+ }
+ text=(QCanvasText *)(mCache->getItem("intro3",1));
+ if (text)
+ {
+ text->setText(i18n("3. intro line, welcome to win4","KWin4"));
+ text->show();
+ }
+ // text
+
+ // animation
+ for (int no=0;no<42;no++)
+ {
+ sprite=(KSprite *)(mCache->getItem("piece",no));
+ if (sprite)
+ {
+ KIntroMove *move=new KIntroMove;
+ connect(sprite->createNotify(),SIGNAL(signalNotify(QCanvasItem *,int)),
+ this,SLOT(introMoveDone(QCanvasItem *,int)));
+ sprite->setMoveObject(move);
+ if (no%2==0)
+ {
+ sprite->move(0-20*no,0);
+ sprite->moveTo(150+2*no,105+4*no);
+ move->setDir(true);
+ sprite->setFrame((no/2)%2);
+ }
+ else
+ {
+ sprite->move(0-20*no,height());
+ sprite->moveTo(340-2*(no-1),105+4*(no-1));
+ move->setDir(false);
+ sprite->setFrame(((no-1)/2)%2);
+ }
+ // Increase the nz coord for consecutive peices
+ // to allow proper intro
+ // Carefule: The number must be more then the
+ // z coord of [empty] and less than [empty2]
+ sprite->setZ(sprite->z()+no/2);
+ // kdDebug(12010) << "Z("<<no<<")="<<sprite->z()<<endl;
+ sprite->show();
+ }
+ }
+}
+
+/**
+ * received after the movment of an intro sprite is finished
+ **/
+void Kwin4View::introMoveDone(QCanvasItem *item,int )
+{
+ KSprite *sprite=(KSprite *)item;
+ sprite->deleteNotify();
+ KIntroMove *move=(KIntroMove *)sprite->moveObject();
+ if (move)
+ {
+ delete move;
+ sprite->setMoveObject(0);
+ }
+}
+
+void Kwin4View::drawBoard(bool remove)
+{
+ KSprite *sprite=0;
+ KSprite *board=0;
+ int x,y;
+
+ // Board
+ // TODO: Without number as it is unique item
+ board=(KSprite *)(mCache->getItem("board",1));
+ if (board)
+ {
+ if (remove) board->hide();
+ else if (!board->isVisible()) board->show();
+ mBoardX=(int)(board->x());
+ mBoardY=(int)(board->y());
+ }
+ else
+ {
+ mBoardX=0;
+ mBoardY=0;
+ }
+ //kdDebug(12010) << "Board X=" << mBoardX << " y="<<mBoardY<<endl;
+
+ // Arrows
+ for (x=0;x<7;x++)
+ {
+ sprite=(KSprite *)(mCache->getItem("arrow",x));
+ if (sprite)
+ {
+ sprite->setFrame(0);
+ sprite->setX(x*(sprite->width()+mSpreadX)+mBoardX);
+ if (remove) sprite->hide();
+ else if (!sprite->isVisible()) sprite->show();
+ }
+ }/* end arrows */
+
+ // Field
+ for (y=5;y>=0;y--)
+ {
+ for (x=0;x<7;x++)
+ {
+ // Lower layer
+ sprite=(KSprite *)(mCache->getItem("empty2",x+7*y));
+ if (sprite)
+ {
+ sprite->move(x*(sprite->width()+mSpreadX)+mBoardX,
+ y*(sprite->height())+mBoardY);
+ if (remove) sprite->hide();
+ else if (!sprite->isVisible()) sprite->show();
+ }
+ // upper layer
+ sprite=(KSprite *)(mCache->getItem("empty",x+7*y));
+ if (sprite)
+ {
+ sprite->move(x*(sprite->width()+mSpreadX)+mBoardX,
+ y*(sprite->height())+mBoardY);
+ if (remove) sprite->hide();
+ else if (!sprite->isVisible()) sprite->show();
+ }
+ }
+ }/* end field */
+}
+
+void Kwin4View::setSprite(int no, int x, int col, bool enable)
+{
+ KSprite *sprite;
+ sprite=(KSprite *)(mCache->getItem("piece",no));
+ if (sprite) sprite->setVisible(enable);
+ setArrow(x,col);
+}
+
+void Kwin4View::setHint(int x,int y,bool enabled)
+{
+ KSprite *sprite;
+ sprite=(KSprite *)(mCache->getItem("hint",1));
+ y=5-y;
+ if (sprite)
+ {
+ if (enabled)
+ {
+ sprite->move(x*(sprite->width()+mSpreadX)+mBoardX,
+ y*(sprite->height()+mSpreadY)+mBoardY);
+ }
+ sprite->setVisible(enabled);
+ }
+}
+
+void Kwin4View::setPiece(int x,int y,int color,int no,bool animation)
+{
+ KSprite *sprite=0;
+
+ y=5-y;
+
+ sprite=(KSprite *)(mCache->getItem("piece",no));
+
+ //kdDebug(12010) << " setPiece("<<x<<","<<y<<","<<color<<","<<no<<") sprite=" << sprite<<endl;
+
+ // Check for removal of sprite
+ if (color==Niemand)
+ {
+ sprite->hide();
+ return ;
+ }
+
+ // Make sure the frames are ok
+ int c;
+ if (color==Gelb) c=0;
+ else c=1;
+
+ if (sprite)
+ {
+ if (animation)
+ {
+ sprite->move(x*(sprite->width()+mSpreadX)+mBoardX,
+ mBoardY-sprite->height()-mSpreadY);
+ sprite->moveTo(sprite->x(),
+ sprite->y()+y*(sprite->height()+mSpreadY)+mBoardY);
+ connect(sprite->createNotify(),SIGNAL(signalNotify(QCanvasItem *,int)),
+ doc,SLOT(moveDone(QCanvasItem *,int)));
+ }
+ else
+ {
+ sprite->move(x*(sprite->width()+mSpreadX)+mBoardX,
+ mBoardY-sprite->height()-mSpreadY+
+ y*(sprite->height()+mSpreadY)+mBoardY);
+ // Prevent moving (== speed =0)
+ sprite->moveTo(sprite->x(),sprite->y());
+ connect(sprite->createNotify(),SIGNAL(signalNotify(QCanvasItem *,int)),
+ doc,SLOT(moveDone(QCanvasItem *,int)));
+ sprite->emitNotify(3);
+ }
+
+ sprite->setFrame(c);
+ sprite->show();
+ }
+}
+
+void Kwin4View::setArrow(int x,int color)
+{
+ KSprite *sprite=0;
+
+ if (mLastArrow>=0)
+ sprite=(KSprite *)(mCache->getItem("arrow",mLastArrow));
+ else
+ sprite=0;
+ if (sprite)
+ sprite->setFrame(0);
+
+ sprite=(KSprite *)(mCache->getItem("arrow",x));
+
+ //kdDebug(12010) << " setArrow("<<x<<","<<color<<") sprite=" << sprite<<endl;
+
+ // Make sure the frames are ok
+ int c = 0;
+ if (color==Gelb)
+ c=1;
+ else if (color==Rot)
+ c=2;
+
+ if (sprite)
+ sprite->setFrame(c);
+ mLastArrow=x;
+}
+
+
+/**
+ * Error message if the wrong player moved
+ */
+bool Kwin4View::wrongPlayer(KPlayer *player,KGameIO::IOMode io)
+{
+ // Hack to find out whether there is a IO Device whose turn it is
+ KGame::KGamePlayerList *playerList=doc->playerList();
+ KPlayer *p;
+
+ bool flag=false;
+ for ( p=playerList->first(); p!= 0; p=playerList->next() )
+ {
+ if (p==player) continue;
+ if (p->hasRtti(io) && p->myTurn()) flag=true;
+ }
+
+ if (flag)
+ return false;
+
+ clearError();
+ int rnd=(kapp->random()%4) +1;
+ QString m;
+ m=QString("text%1").arg(rnd);
+ QString ms;
+ if (rnd==1) ms=i18n("Hold on... the other player has not been yet...");
+ else if (rnd==2) ms=i18n("Hold your horses...");
+ else if (rnd==3) ms=i18n("Ah ah ah... only one go at a time...");
+ else ms=i18n("Please wait... it is not your turn.");
+
+ // TODO MH can be unique
+ QCanvasText *text=(QCanvasText *)(mCache->getItem(m,1));
+ if (text)
+ {
+ text->setText(ms);
+ text->show();
+ }
+ return true;
+}
+
+/**
+ * This slot is called when a key event is received. It then prduces a
+ * valid move for the game.
+ **/
+// This is analogous to the mouse event only it is called when a key is
+// pressed
+void Kwin4View::slotKeyInput(KGameIO *input,QDataStream &stream,QKeyEvent *e,bool *eatevent)
+{
+ // Ignore non running
+ if (!doc->isRunning())
+ return;
+ // kdDebug(12010) << "KEY EVENT" << e->ascii() << endl;
+
+ // Ignore non key press
+ if (e->type() != QEvent::KeyPress) return ;
+
+ // Our player
+ KPlayer *player=input->player();
+ if (!player->myTurn())
+ {
+ *eatevent=wrongPlayer(player,KGameIO::KeyIO);
+ return;
+ }
+
+ int code=e->ascii();
+ if (code<'1' || code>'7')
+ {
+ //kdDebug(12010) << "Key not supported\n";
+ return ;
+ }
+
+ // Create a move
+ Q_INT32 move,pl;
+ move=code-'1';
+ pl=player->userId();
+ stream << pl << move;
+ *eatevent=true;
+}
+
+/**
+ * This slot is called when a mouse key is pressed. As the mouse is used as
+ * input for all players
+ * this slot is called to generate a player move out of a mouse input, i.e.
+ * it converts a QMouseEvent into a move for the game. We do here some
+ * simple nonsense and use the position of the mouse to generate
+ * moves containing the keycodes
+ */
+void Kwin4View::slotMouseInput(KGameIO *input,QDataStream &stream,QMouseEvent *mouse,bool *eatevent)
+{
+ // Only react to key pressed not released
+ if (mouse->type() != QEvent::MouseButtonPress ) return ;
+ if (!doc->isRunning())
+ return;
+
+ // Our player
+ KPlayer *player=input->player();
+ if (!player->myTurn())
+ {
+ *eatevent=wrongPlayer(player,KGameIO::MouseIO);
+ return;
+ }
+
+ if (mouse->button()!=LeftButton) return ;
+ //if (!doc->IsRunning()) return ;
+
+ QPoint point;
+ int x,y;
+
+ point=mouse->pos() - QPoint(15,40) - QPoint(20,20);
+ if (point.x()<0) return ;
+
+ x=point.x()/FIELD_SPACING;
+ y=point.y()/FIELD_SPACING;
+
+ if (y>=FIELD_SIZE_Y) return ;
+ if (x<0 || x>=FIELD_SIZE_X) return;
+
+ // Create a move
+ Q_INT32 move,pl;
+ move=x;
+ pl=player->userId();
+ stream << pl << move;
+ *eatevent=true;
+ // kdDebug(12010) << "Mouse input done..eatevent=true" << endl;
+}
+
+/**
+ * Hide all the error sprites
+ */
+void Kwin4View::clearError()
+{
+ QCanvasText *text;
+
+ text=(QCanvasText *)(mCache->getItem("text1",1));
+ if (text) text->hide();
+ text=(QCanvasText *)(mCache->getItem("text2",1));
+ if (text) text->hide();
+ text=(QCanvasText *)(mCache->getItem("text3",1));
+ if (text) text->hide();
+ text=(QCanvasText *)(mCache->getItem("text4",1));
+ if (text) text->hide();
+}
+
+void Kwin4View::resizeEvent(QResizeEvent *e)
+{
+ if (mCanvas) mCanvas->resize(e->size().width(),e->size().height());
+}
+
+#include "kwin4view.moc"