• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdegames API Reference
  • KDE Home
  • Contact Us
 

granatier

  • sources
  • kde-4.14
  • kdegames
  • granatier
  • src
player.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2009 Mathias Kraus <k.hias@gmx.de>
3  * Copyright 2007-2008 Thomas Gallinari <tg8187@yahoo.fr>
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License as
7  * published by the Free Software Foundation; either version 2 of
8  * the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 #include "player.h"
20 #include "bonus.h"
21 #include "bomb.h"
22 #include "arena.h"
23 #include "config/playersettings.h"
24 #include "settings.h"
25 
26 #include <QKeyEvent>
27 #include <QTimer>
28 
29 #include <cmath>
30 
31 const int onIceSpeedIncrease = 2;
32 const int badBonusTimerTimeout = 100;
33 const int badBonusCountdown = 10000;
34 
35 Player::Player(qreal p_x, qreal p_y, const QString& p_playerID, const PlayerSettings* p_playerSettings, Arena* p_arena) : Character(p_x, p_y, p_arena)
36 {
37  m_type = Granatier::Element::PLAYER;
38  m_desktopFilePath = p_playerSettings->playerDesktopFilePath(p_playerID);
39  m_graphicsFile = p_playerSettings->playerGraphicsFile(p_playerID);
40  m_playerName = p_playerSettings->playerName(p_playerID);
41 
42  m_points = 0;
43 
44  m_direction = Granatier::Direction::EAST;
45 
46  m_badBonusCountdownTimer = new QTimer;
47  m_badBonusCountdownTimer->setInterval(badBonusTimerTimeout);
48  m_badBonusMillisecondsToElapse = 0;
49  connect(m_badBonusCountdownTimer, SIGNAL(timeout()), this, SLOT(slot_badBonusTimerTimeout()));
50 
51  resurrect();
52 
53  m_key.moveLeft = p_playerSettings->keyLeft(p_playerID);
54  m_key.moveRight = p_playerSettings->keyRight(p_playerID);
55  m_key.moveUp = p_playerSettings->keyUp(p_playerID);
56  m_key.moveDown = p_playerSettings->keyDown(p_playerID);
57  m_key.dropBomb = p_playerSettings->keyPutBomb(p_playerID);
58 }
59 
60 Player::~Player()
61 {
62  delete m_badBonusCountdownTimer;
63 }
64 
65 void Player::setShortcuts(const Shortcuts &keys)
66 {
67  m_key = keys;
68 }
69 
70 QString Player::getGraphicsFile() const
71 {
72  return m_graphicsFile;
73 }
74 
75 QString Player::getDesktopFilePath() const
76 {
77  return m_desktopFilePath;
78 }
79 
80 QString Player::getPlayerName() const
81 {
82  return m_playerName;
83 }
84 
85 void Player::init()
86 {
87  updateDirection();
88  stopMoving();
89  int row = m_arena->getRowFromY(m_y);
90  int column = m_arena->getColFromX(m_x);
91  m_arena->setCellElement(row, column, this);
92 }
93 
94 void Player::pause()
95 {
96  m_badBonusCountdownTimer->stop();
97 }
98 
99 void Player::resume()
100 {
101  if(m_badBonusMillisecondsToElapse > 0)
102  {
103  m_badBonusCountdownTimer->start();
104  }
105 }
106 
107 void Player::goUp()
108 {
109  m_askedXSpeed = 0;
110 
111  int nSpeed = m_speed;
112  if(m_onIce)
113  {
114  nSpeed = m_speed + onIceSpeedIncrease;
115  }
116  m_askedYSpeed = -nSpeed;
117 
118  m_direction = Granatier::Direction::NORTH;
119 }
120 
121 void Player::goDown()
122 {
123  m_askedXSpeed = 0;
124 
125  int nSpeed = m_speed;
126  if(m_onIce)
127  {
128  nSpeed = m_speed + onIceSpeedIncrease;
129  }
130  m_askedYSpeed = nSpeed;
131 
132  m_direction = Granatier::Direction::SOUTH;
133 }
134 
135 void Player::goRight()
136 {
137  int nSpeed = m_speed;
138  if(m_onIce)
139  {
140  nSpeed = m_speed + onIceSpeedIncrease;
141  }
142  m_askedXSpeed = nSpeed;
143 
144  m_askedYSpeed = 0;
145 
146  m_direction = Granatier::Direction::EAST;
147 }
148 
149 void Player::goLeft()
150 {
151  int nSpeed = m_speed;
152  if(m_onIce)
153  {
154  nSpeed = m_speed + onIceSpeedIncrease;
155  }
156  m_askedXSpeed = -nSpeed;
157 
158  m_askedYSpeed = 0;
159 
160  m_direction = Granatier::Direction::WEST;
161 }
162 
163 void Player::updateDirection()
164 {
165  if(m_death)
166  {
167  return;
168  }
169 
170  setXSpeed(m_askedXSpeed);
171  setYSpeed(m_askedYSpeed);
172  m_askedXSpeed = 0;
173  m_askedYSpeed = 0;
174  // Signal to the player item that the direction changed
175  emit directionChanged();
176 }
177 
178 void Player::updateMove()
179 {
180  if(m_death)
181  {
182  return;
183  }
184 
185  //check if there is a hurdle in the way
186  if(m_askedXSpeed != 0 || m_xSpeed != 0 || m_askedYSpeed != 0 || m_ySpeed != 0)
187  {
188  int xDirection = 0; //x-direction: -1: move left; 0: not moving; 1: move right
189  int yDirection = 0; //y-direction: -1: move up; 0: not moving; 1: move down
190  int straightDirection = 0; //straight direction: -1: backward; 1:foreward; while foreward is right for moving in x-direction and down for y-direction
191  qreal deltaStraightMove = 0; //the move in straight direction
192  qreal deltaPerpendicularMove = 0; //the move in perpendicular direction; e.g. the player is not in cell center and will collide with a wall in the cell above, so the player has to be moved to the cell center
193  qreal deltaAskedMove; //how far to move; positive for right/down move and negative for left/up
194  qreal deltaStraightCellCorner; //move in x-direction: the x-pos from the top left cell corner; move in y-direction: the y-pos from the top left cell corner
195  qreal deltaPerpendicularCellCorner; //move in x-direction: the y-pos from the top left cell corner; move in y-direction: the x-pos from the top left cell corner
196  qreal deltaStraightCellCenter; //distance to the cell center in moving direction; positive if left/up from cell center, negative if right/down
197  qreal deltaPerpendicularCellCenter; //distance to the cell center perpendicular to moving direction; positive if up/left from cell center, negative if down/right
198  bool bMoveWithinNextCellCenter = false; //move is completed without exceeding the cell center
199  int cellCol;
200  int cellRow;
201 
202  // Get the current cell coordinates from the character coordinates
203  int moveStartRow = m_arena->getRowFromY(m_y);
204  int moveStartCol = m_arena->getColFromX(m_x);
205  int curCellRow = moveStartRow;
206  int curCellCol = moveStartCol;
207 
208  //set variables for right/left move
209  if(m_askedXSpeed != 0 || m_xSpeed != 0)
210  {
211  //how far to move
212  deltaAskedMove = (m_askedXSpeed != 0 ? m_askedXSpeed : m_xSpeed);
213 
214  //direction to move
215  xDirection = sign(deltaAskedMove);
216  straightDirection = xDirection;
217 
218  deltaStraightCellCorner = m_x - curCellCol * Granatier::CellSize;
219  deltaPerpendicularCellCorner = m_y - curCellRow * Granatier::CellSize;
220  }
221  else //set variables for down/up move
222  {
223  //how far to move
224  deltaAskedMove = (m_askedYSpeed != 0 ? m_askedYSpeed : m_ySpeed);
225 
226  //direction to move
227  yDirection = sign(deltaAskedMove);
228  straightDirection = yDirection;
229 
230  deltaStraightCellCorner = m_y - curCellRow * Granatier::CellSize;
231  deltaPerpendicularCellCorner = m_x - curCellCol * Granatier::CellSize;
232  }
233 
234  //how far to current cell center
235  deltaStraightCellCenter = Granatier::CellSize/2 - deltaStraightCellCorner;
236  deltaPerpendicularCellCenter = Granatier::CellSize/2 - deltaPerpendicularCellCorner;
237 
238  //check if the move exceeds a cell center
239  if(straightDirection*deltaStraightCellCenter >= 0)
240  {
241  if(fabs(deltaAskedMove) <= fabs(deltaStraightCellCenter))
242  {
243  bMoveWithinNextCellCenter = true;
244  }
245  }
246  else if(fabs(deltaAskedMove) + fabs(deltaStraightCellCenter) <= Granatier::CellSize)
247  {
248  bMoveWithinNextCellCenter = true;
249  }
250 
251  //the move is within two cell centers
252  if(bMoveWithinNextCellCenter)
253  {
254  bool isHurdle = false;
255  if(!(m_badBonusCountdownTimer->isActive() && m_badBonusType == Granatier::Bonus::SCATTY))
256  {
257  bool kickBomb = false;
258  QList<Element*> bombElements;
259  //moving towards cell center; don't move if there is a bomb in the cell
260  if(deltaStraightCellCenter * straightDirection > 0 && !m_arena->getCell(moveStartRow, moveStartCol).isWalkable(this) && !m_omitBombCurrentCell)
261  {
262  isHurdle = true;
263  if(m_kickBomb)
264  {
265  kickBomb = true;
266  bombElements = m_arena->getCell(moveStartRow, moveStartCol).getElements(Granatier::Element::BOMB);
267  }
268  }
269  //moving away of cell center; don't move if there is a bomb in the next cell; ignore a bomb in the current cell
270  else if(deltaStraightCellCenter * straightDirection < 0 && !m_arena->getCell(moveStartRow + yDirection, moveStartCol + xDirection).isWalkable(this))
271  {
272  isHurdle = true;
273  if(m_kickBomb)
274  {
275  kickBomb = true;
276  bombElements = m_arena->getCell(moveStartRow + yDirection, moveStartCol + xDirection).getElements(Granatier::Element::BOMB);
277  }
278  }
279  if(kickBomb)
280  {
281  foreach(Element* element, bombElements)
282  {
283  dynamic_cast <Bomb*> (element)->setKicked(m_direction);
284  }
285  }
286  }
287  if(!isHurdle)
288  {
289  deltaStraightMove += deltaAskedMove;
290  //move to perpendicular center if needed
291  if(deltaPerpendicularCellCenter != 0 && (straightDirection * deltaStraightCellCenter) < 0) //not in perpendicular center and entering a new cell
292  {
293  if(fabs(deltaPerpendicularCellCenter) > Granatier::CellSize/2 - fabs(deltaStraightMove - deltaStraightCellCenter)) //check if it already can collide with a hurdle
294  {
295  cellRow = curCellRow + yDirection - qAbs(xDirection)*signZeroPositive(deltaPerpendicularCellCenter);
296  cellCol = curCellCol + xDirection - qAbs(yDirection)*signZeroPositive(deltaPerpendicularCellCenter);
297  if(!m_arena->getCell(cellRow, cellCol).isWalkable(this))
298  {
299  deltaPerpendicularMove = deltaPerpendicularCellCenter + signZeroPositive(deltaPerpendicularCellCenter) * (fabs(deltaStraightMove - deltaStraightCellCenter) - Granatier::CellSize/2);
300  if(fabs(deltaPerpendicularMove) > fabs(deltaPerpendicularCellCenter)) //check if moved over perpendicular center
301  {
302  deltaPerpendicularMove = deltaPerpendicularCellCenter;
303  }
304  }
305  }
306  }
307  }
308  }
309  else //the move exceeds a cell center
310  {
311  //at first move to the cell center
312  deltaStraightMove += deltaStraightCellCenter;
313  deltaAskedMove -= deltaStraightCellCenter;
314  if(straightDirection * deltaStraightCellCenter < 0) //the cell center to move is in the next cell
315  {
316  deltaStraightMove += straightDirection * Granatier::CellSize;
317  deltaAskedMove -= straightDirection * Granatier::CellSize;
318 
319  //move to perpendicular center if needed
320  if(deltaPerpendicularCellCenter != 0)
321  {
322  cellRow = curCellRow + yDirection - qAbs(xDirection)*signZeroPositive(deltaPerpendicularCellCenter);
323  cellCol = curCellCol + xDirection - qAbs(yDirection)*signZeroPositive(deltaPerpendicularCellCenter);
324  if(!m_arena->getCell(cellRow, cellCol).isWalkable(this))
325  {
326  deltaPerpendicularMove = deltaPerpendicularCellCenter;
327  }
328  }
329 
330  //update the current cell and row
331  curCellCol += xDirection;
332  curCellRow += yDirection;
333  }
334  while(fabs(deltaAskedMove) > 0) //complete the move
335  {
336  if(m_arena->getCell(curCellRow + yDirection, curCellCol + xDirection).isWalkable(this)) //check if next cell is walkable
337  {
338  if(fabs(deltaAskedMove) > Granatier::CellSize) //move to next cell center if the remaining move exceeds a cell center
339  {
340  deltaStraightMove += straightDirection * Granatier::CellSize;
341  deltaAskedMove -= straightDirection * Granatier::CellSize;
342  //move to perpendicular center if needed
343  if(deltaPerpendicularCellCenter != 0)
344  {
345  cellRow = curCellRow + yDirection - qAbs(xDirection)*signZeroPositive(deltaPerpendicularCellCenter);
346  cellCol = curCellCol + xDirection - qAbs(yDirection)*signZeroPositive(deltaPerpendicularCellCenter);
347  if(!m_arena->getCell(cellRow, cellCol).isWalkable(this))
348  {
349  deltaPerpendicularMove = deltaPerpendicularCellCenter;
350  }
351  }
352  }
353  else
354  {
355  deltaStraightMove += deltaAskedMove;
356  //move to perpendicular center if needed
357  if(deltaPerpendicularMove != deltaPerpendicularCellCenter && fabs(deltaPerpendicularCellCenter) > (Granatier::CellSize/2 - fabs(deltaStraightMove - deltaStraightCellCenter))) //check if it is in or already moved to perpendicular center and if it already can collide with a hurdle ***TODO: it seems to be wrong to use deltaStraightMove here, because ist could be greater than Granatier::CellSize
358  {
359  cellRow = curCellRow + yDirection - qAbs(xDirection)*signZeroPositive(deltaPerpendicularCellCenter);
360  cellCol = curCellCol + xDirection - qAbs(yDirection)*signZeroPositive(deltaPerpendicularCellCenter);
361  if(!m_arena->getCell(cellRow, cellCol).isWalkable(this))
362  {
363  deltaPerpendicularMove = signZeroPositive(deltaPerpendicularCellCenter) * fabs(deltaAskedMove);
364  if(fabs(deltaPerpendicularMove) > fabs(deltaPerpendicularCellCenter))
365  {
366  deltaPerpendicularMove = deltaPerpendicularCellCenter; //check if moved over perpendicular center
367  }
368  }
369  }
370  deltaAskedMove = 0;
371  }
372  //update the current cell and row
373  curCellCol += xDirection;
374  curCellRow += yDirection;
375  }
376  else //there is a hurdle in the next cell, so stop moving
377  {
378  deltaAskedMove = 0;
379  cellRow = curCellRow + yDirection;
380  cellCol = curCellCol + xDirection;
381  //check if bomb
382  if(m_kickBomb)
383  {
384  QList<Element*> bombElements = m_arena->getCell(cellRow, cellCol).getElements(Granatier::Element::BOMB);
385  {
386  foreach(Element* element, bombElements)
387  {
388  dynamic_cast <Bomb*> (element)->setKicked(m_direction);
389  }
390  }
391  }
392  }
393  }
394  }
395 
396  // Update the direction
397  if(m_askedXSpeed != 0 || m_askedYSpeed != 0)
398  {
399  updateDirection();
400  }
401 
402  // Move the player
403  if(xDirection != 0)
404  {
405  move(m_x + deltaStraightMove, m_y + deltaPerpendicularMove);
406  }
407  else
408  {
409  move(m_x + deltaPerpendicularMove, m_y + deltaStraightMove);
410  }
411 
412  //check if the player is on ice
413  // Get the current cell coordinates from the character coordinates
414  int newCellRow = m_arena->getRowFromY(m_y);
415  int newCellCol = m_arena->getColFromX(m_x);
416  if(!m_onIce)
417  {
418  if(m_arena->getCell(newCellRow, newCellCol).getType() == Granatier::Cell::ICE)
419  {
420  if(xDirection != 0)
421  {
422  setXSpeed(m_xSpeed + xDirection * onIceSpeedIncrease);
423  }
424  else
425  {
426  setYSpeed(m_ySpeed + yDirection * onIceSpeedIncrease);
427  }
428  m_onIce = true;
429  }
430  }
431  else
432  {
433  if(m_arena->getCell(newCellRow, newCellCol).getType() != Granatier::Cell::ICE)
434  {
435  if(m_arena->getCell(newCellRow, newCellCol).getType() != Granatier::Cell::HOLE)
436  {
437  if(xDirection != 0)
438  {
439  setXSpeed(m_xSpeed - xDirection * onIceSpeedIncrease);
440  }
441  else
442  {
443  setYSpeed(m_ySpeed - yDirection * onIceSpeedIncrease);
444  }
445  }
446  m_onIce = false;
447 
448  if(m_xSpeed == 0 && m_ySpeed == 0 && m_askedXSpeed == 0 && m_askedYSpeed == 0)
449  {
450  stopMoving();
451  }
452  }
453  }
454 
455  //check if the player move in a hole
456  if(m_arena->getCell(newCellRow, newCellCol).getType() == Granatier::Cell::HOLE)
457  {
458  m_falling = true;
459  //check if cell center passed
460  if(xDirection != 0)
461  {
462  qreal cellCenter = newCellCol * Granatier::CellSize + 0.5 * Granatier::CellSize;
463  qreal deltaCellCenter = cellCenter - (m_x + m_xSpeed);
464  if (cellCenter - m_x == 0)
465  {
466  setXSpeed(0);
467  emit falling();
468  }
469  else if (xDirection * deltaCellCenter < 0)
470  {
471  setXSpeed(cellCenter - m_x);
472  }
473  }
474  else if (yDirection != 0)
475  {
476  qreal cellCenter = newCellRow * Granatier::CellSize + 0.5 * Granatier::CellSize;
477  qreal deltaCellCenter = cellCenter - (m_y + m_ySpeed);
478  if (cellCenter - m_y == 0)
479  {
480  setYSpeed(0);
481  emit falling();
482  }
483  else if (yDirection * deltaCellCenter < 0)
484  {
485  setYSpeed(cellCenter - m_y);
486  }
487  }
488  }
489 
490  if(moveStartCol != newCellCol || moveStartRow != newCellRow)
491  {
492  m_arena->removeCellElement(moveStartRow, moveStartCol, this);
493  m_arena->setCellElement(newCellRow, newCellCol, this);
494  m_omitBombCurrentCell = false;
495  }
496  }
497 
498  //check if bad bonus scatty and drop bombs
499  if(m_badBonusCountdownTimer->isActive() && m_badBonusType == Granatier::Bonus::SCATTY && m_bombArmory > 0)
500  {
501  //TODO: improve
502  emit bombDropped(this, m_x, m_y, true, 0);
503  }
504 }
505 
506 void Player::move(qreal x, qreal y)
507 {
508  // Move the Character
509  m_x = x;
510  m_y = y;
511  emit moved(m_x, m_y);
512 }
513 
514 void Player::addBonus(Bonus* p_bonus)
515 {
516  Granatier::Bonus::Type bonusType = p_bonus->getBonusType();
517 
518  if(m_badBonusCountdownTimer->isActive())
519  {
520  m_badBonusCountdownTimer->stop();
521  slot_removeBadBonus();
522  }
523 
524  switch (bonusType)
525  {
526  case Granatier::Bonus::SPEED:
527  m_speed += 1;
528  if(m_speed > m_maxSpeed)
529  {
530  m_speed = m_maxSpeed;
531  }
532  setXSpeed(sign(m_xSpeed) * m_speed);
533  setYSpeed(sign(m_ySpeed) * m_speed);
534  break;
535  case Granatier::Bonus::POWER:
536  m_bombPower++;
537  if(m_bombPower > 10)
538  {
539  m_bombPower = 10;
540  }
541  break;
542  case Granatier::Bonus::BOMB:
543  m_maxBombArmory++;
544  if(m_maxBombArmory > 10)
545  {
546  m_maxBombArmory = 10;
547  }
548  m_bombArmory++;
549  if(m_bombArmory > m_maxBombArmory)
550  {
551  m_bombArmory = m_maxBombArmory;
552  }
553  break;
554  case Granatier::Bonus::SHIELD:
555  if(m_listShield.isEmpty() || m_listShield.last() != 0)
556  {
557  m_listShield.append(0);
558  }
559  break;
560  case Granatier::Bonus::THROW:
561  m_throwBomb = true;
562  break;
563  case Granatier::Bonus::KICK:
564  m_kickBomb = true;
565  break;
566  case Granatier::Bonus::HYPERACTIVE:
567  {
568  int askedXSpeedTemp = m_askedXSpeed;
569  int askedYSpeedTemp = m_askedYSpeed;
570  m_normalSpeed = m_speed;
571  m_speed = m_maxSpeed * 3;
572  m_askedXSpeed = sign(m_xSpeed) * m_speed;
573  m_askedYSpeed = sign(m_ySpeed) * m_speed;
574  updateDirection();
575  m_askedXSpeed = askedXSpeedTemp;
576  m_askedYSpeed = askedYSpeedTemp;
577 
578  m_badBonusType = Granatier::Bonus::HYPERACTIVE;
579  m_badBonusMillisecondsToElapse = badBonusCountdown;
580  m_badBonusCountdownTimer->start();
581  }
582  break;
583  case Granatier::Bonus::SLOW:
584  {
585  int askedXSpeedTemp = m_askedXSpeed;
586  int askedYSpeedTemp = m_askedYSpeed;
587  m_normalSpeed = m_speed;
588  m_speed = 1;
589  m_askedXSpeed = sign(m_xSpeed) * m_speed;
590  m_askedYSpeed = sign(m_ySpeed) * m_speed;
591  updateDirection();
592  m_askedXSpeed = askedXSpeedTemp;
593  m_askedYSpeed = askedYSpeedTemp;
594 
595  m_badBonusType = Granatier::Bonus::SLOW;
596  m_badBonusMillisecondsToElapse = badBonusCountdown;
597  m_badBonusCountdownTimer->start();
598  }
599  break;
600  case Granatier::Bonus::MIRROR:
601  {
602  int askedXSpeedTemp = m_askedXSpeed;
603  int askedYSpeedTemp = m_askedYSpeed;
604  m_askedXSpeed = -m_xSpeed;
605  m_askedYSpeed = -m_ySpeed;
606  switch(m_direction)
607  {
608  case Granatier::Direction::EAST:
609  m_direction = Granatier::Direction::WEST;
610  break;
611  case Granatier::Direction::WEST:
612  m_direction = Granatier::Direction::EAST;
613  break;
614  case Granatier::Direction::NORTH:
615  m_direction = Granatier::Direction::SOUTH;
616  break;
617  case Granatier::Direction::SOUTH:
618  m_direction = Granatier::Direction::NORTH;
619  break;
620  }
621  updateDirection();
622  m_askedXSpeed = -askedXSpeedTemp;
623  m_askedYSpeed = -askedYSpeedTemp;
624 
625  QKeySequence tempKey = m_key.moveLeft;
626  m_key.moveLeft = m_key.moveRight;
627  m_key.moveRight = tempKey;
628  tempKey = m_key.moveUp;
629  m_key.moveUp = m_key.moveDown;
630  m_key.moveDown = tempKey;
631 
632  m_moveMirrored = true;
633  m_badBonusType = Granatier::Bonus::MIRROR;
634  m_badBonusMillisecondsToElapse = badBonusCountdown;
635  m_badBonusCountdownTimer->start();
636  }
637  break;
638  case Granatier::Bonus::SCATTY:
639  m_badBonusType = Granatier::Bonus::SCATTY;
640  m_badBonusMillisecondsToElapse = badBonusCountdown;
641  m_badBonusCountdownTimer->start();
642  break;
643  case Granatier::Bonus::RESTRAIN:
644  m_normalBombArmory = m_bombArmory;
645  m_bombArmory = 0;
646  m_badBonusType = Granatier::Bonus::RESTRAIN;
647  m_badBonusMillisecondsToElapse = badBonusCountdown;
648  m_badBonusCountdownTimer->start();
649  break;
650  case Granatier::Bonus::RESURRECT:
651  emit resurrectBonusTaken();
652  break;
653  default:
654  break;
655  }
656 
657  bonusUpdated(this, bonusType, 0);
658 }
659 
660 bool Player::shield(int nExplosionID)
661 {
662  for(int i = 0; i < m_listShield.count(); i++)
663  {
664  if(m_listShield[i] == nExplosionID)
665  {
666  return true;
667  }
668  else if(m_listShield[i] == 0)
669  {
670  m_listShield[i] = nExplosionID;
671  if(i == m_listShield.count()-1)
672  {
673  emit bonusUpdated(this, Granatier::Bonus::SHIELD, 100);
674  }
675  return true;
676  }
677  }
678  return false;
679 }
680 
681 bool Player::hasShield()
682 {
683  if(m_listShield.count() > 0 && m_listShield.last() == 0)
684  {
685  return true;
686  }
687  return false;
688 }
689 
690 bool Player::hasThrowBomb()
691 {
692  return m_throwBomb;
693 }
694 
695 bool Player::hasKickBomb()
696 {
697  return m_kickBomb;
698 }
699 
700 bool Player::hasBadBonus()
701 {
702  if(m_badBonusCountdownTimer->isActive())
703  {
704  return true;
705  }
706  return false;
707 }
708 
709 void Player::die()
710 {
711  if(!m_death)
712  {
713  m_death = true;
714  emit dying();
715  m_xSpeed = 0;
716  m_xSpeed = 0;
717 
718  if(m_badBonusCountdownTimer->isActive())
719  {
720  m_badBonusCountdownTimer->stop();
721  slot_removeBadBonus();
722  }
723  int row = m_arena->getRowFromY(m_y);
724  int column = m_arena->getColFromX(m_x);
725  m_arena->removeCellElement(row, column, this);
726  }
727 }
728 
729 bool Player::isAlive() const
730 {
731  return !m_death;
732 }
733 
734 void Player::resurrect()
735 {
736  if(m_badBonusMillisecondsToElapse > 0)
737  {
738  slot_removeBadBonus();
739  }
740 
741  m_onIce = false;
742  m_falling = false;
743  m_death = false;
744  m_maxSpeed = 10;
745  m_speed = Settings::self()->initialSpeed();
746  m_normalSpeed = m_speed;
747  m_moveMirrored = false;
748  m_bombPower = Settings::self()->initialBombPower();
749  m_maxBombArmory = Settings::self()->initialBombArmory();
750  m_bombArmory = m_maxBombArmory;
751  if(m_listShield.count() != 0)
752  {
753  m_listShield.clear();
754  emit bonusUpdated(this, Granatier::Bonus::SHIELD, 100);
755  }
756  if(m_throwBomb)
757  {
758  m_throwBomb = false;
759  emit bonusUpdated(this, Granatier::Bonus::THROW, 100);
760  }
761  if(m_kickBomb)
762  {
763  m_kickBomb = false;
764  emit bonusUpdated(this, Granatier::Bonus::KICK, 100);
765  }
766  m_omitBombCurrentCell = false;
767  if(m_badBonusCountdownTimer->isActive())
768  {
769  m_badBonusCountdownTimer->stop();
770  slot_removeBadBonus();
771  }
772 
773  //check if the player is above a hole
774  if(m_arena)
775  {
776  int cellRow = m_arena->getRowFromY(m_y);
777  int cellCol = m_arena->getColFromX(m_x);
778 
779  m_arena->removeCellElement(cellRow, cellCol, this); //just to be really sure
780 
781  if(m_arena->getCell(cellRow, cellCol).getType() == Granatier::Cell::HOLE)
782  {
783  move(m_xInit, m_yInit);
784  cellRow = m_arena->getRowFromY(m_yInit);
785  cellCol = m_arena->getColFromX(m_xInit);
786  }
787 
788  m_arena->setCellElement(cellRow, cellCol, this);
789  }
790 
791  emit resurrected();
792 }
793 
794 int Player::points() const
795 {
796  return m_points;
797 }
798 
799 void Player::addPoint()
800 {
801  m_points++;
802 }
803 
804 void Player::emitGameUpdated()
805 {
806  emit gameUpdated();
807 }
808 
809 qreal Player::getAskedXSpeed() const
810 {
811  return m_askedXSpeed;
812 }
813 
814 qreal Player::getAskedYSpeed() const
815 {
816  return m_askedYSpeed;
817 }
818 
819 int Player::direction()
820 {
821  return m_direction;
822 }
823 
824 int Player::getBombPower() const
825 {
826  return m_bombPower;
827 }
828 
829 void Player::decrementBombArmory()
830 {
831  m_bombArmory--;
832  if(m_bombArmory < 0)
833  {
834  m_bombArmory = 0;
835  }
836 }
837 
838 void Player::slot_refillBombArmory()
839 {
840  int* bombArmory = &m_bombArmory;
841  if(m_badBonusCountdownTimer->isActive() && m_badBonusType == Granatier::Bonus::RESTRAIN)
842  {
843  bombArmory = &m_normalBombArmory;
844  }
845  (*bombArmory)++;
846  if((*bombArmory) > m_maxBombArmory)
847  {
848  (*bombArmory) = m_maxBombArmory;
849  }
850 }
851 
852 void Player::slot_badBonusTimerTimeout()
853 {
854  m_badBonusMillisecondsToElapse -= badBonusTimerTimeout;
855  if(m_badBonusMillisecondsToElapse <= 0)
856  {
857  slot_removeBadBonus();
858  }
859  else
860  {
861  bonusUpdated(this, m_badBonusType, (badBonusCountdown - m_badBonusMillisecondsToElapse)/(badBonusCountdown/100.));
862  }
863 }
864 
865 void Player::slot_removeBadBonus()
866 {
867  m_badBonusCountdownTimer->stop();
868  m_badBonusMillisecondsToElapse = 0;
869 
870  switch (m_badBonusType)
871  {
872  case Granatier::Bonus::HYPERACTIVE:
873  case Granatier::Bonus::SLOW:
874  {
875  int askedXSpeedTemp = m_askedXSpeed;
876  int askedYSpeedTemp = m_askedYSpeed;
877  m_speed = m_normalSpeed;
878  m_askedXSpeed = sign(m_xSpeed) * m_speed;
879  m_askedYSpeed = sign(m_ySpeed) * m_speed;
880  updateDirection();
881  m_askedXSpeed = askedXSpeedTemp;
882  m_askedYSpeed = askedYSpeedTemp;
883  }
884  break;
885  case Granatier::Bonus::MIRROR:
886  {
887  int askedXSpeedTemp = m_askedXSpeed;
888  int askedYSpeedTemp = m_askedYSpeed;
889  m_askedXSpeed = -m_xSpeed;
890  m_askedYSpeed = -m_ySpeed;
891  switch(m_direction)
892  {
893  case Granatier::Direction::EAST:
894  m_direction = Granatier::Direction::WEST;
895  break;
896  case Granatier::Direction::WEST:
897  m_direction = Granatier::Direction::EAST;
898  break;
899  case Granatier::Direction::NORTH:
900  m_direction = Granatier::Direction::SOUTH;
901  break;
902  case Granatier::Direction::SOUTH:
903  m_direction = Granatier::Direction::NORTH;
904  break;
905  }
906  updateDirection();
907  m_askedXSpeed = -askedXSpeedTemp;
908  m_askedYSpeed = -askedYSpeedTemp;
909 
910  QKeySequence tempKey = m_key.moveLeft;
911  m_key.moveLeft = m_key.moveRight;
912  m_key.moveRight = tempKey;
913  tempKey = m_key.moveUp;
914  m_key.moveUp = m_key.moveDown;
915  m_key.moveDown = tempKey;
916 
917  m_moveMirrored = false;
918  }
919  break;
920  case Granatier::Bonus::RESTRAIN:
921  m_bombArmory = m_normalBombArmory;
922  break;
923  default:
924  break;
925  }
926 
927  bonusUpdated(this, m_badBonusType, 100);
928 }
929 
930 void Player::stopMoving()
931 {
932  setXSpeed(0);
933  setYSpeed(0);
934  m_askedXSpeed = 0;
935  m_askedYSpeed = 0;
936  emit stopped();
937 }
938 
939 void Player::keyPressed(QKeyEvent* keyEvent)
940 {
941  if(m_death || m_falling)
942  {
943  return;
944  }
945 
946  QKeySequence key = QKeySequence(keyEvent->key());
947 
948  if(key == m_key.moveLeft || key == m_key.moveRight || key == m_key.moveUp || key == m_key.moveDown || key == m_key.dropBomb)
949  {
950  keyEvent->accept();
951  if(keyEvent->isAutoRepeat())
952  {
953  return;
954  }
955  }
956  else
957  {
958  return;
959  }
960 
961  if(key == m_key.moveLeft)
962  {
963  goLeft();
964  updateDirection();
965  }
966  else if(key == m_key.moveRight)
967  {
968  goRight();
969  updateDirection();
970  }
971  else if(key == m_key.moveUp)
972  {
973  goUp();
974  updateDirection();
975  }
976  else if(key == m_key.moveDown)
977  {
978  goDown();
979  updateDirection();
980  }
981  else if(key == m_key.dropBomb)
982  {
983  if(m_bombArmory > 0)
984  {
985  emit bombDropped(this, m_x, m_y, true, 2);
986  m_omitBombCurrentCell = true;
987  }
988  else
989  {
990  emit bombDropped(this, m_x, m_y, false, 2);
991  }
992  }
993 
994 }
995 
996 void Player::keyReleased(QKeyEvent* keyEvent)
997 {
998  if(m_death || m_falling)
999  {
1000  return;
1001  }
1002 
1003  QKeySequence key = QKeySequence(keyEvent->key());
1004 
1005  if(key == m_key.moveLeft || key == m_key.moveRight || key == m_key.moveUp || key == m_key.moveDown || key == m_key.dropBomb)
1006  {
1007  keyEvent->accept();
1008  if(keyEvent->isAutoRepeat())
1009  {
1010  return;
1011  }
1012  }
1013  else
1014  {
1015  return;
1016  }
1017 
1018  int nSpeed = 0;
1019  if(m_onIce)
1020  {
1021  nSpeed = onIceSpeedIncrease;
1022  }
1023 
1024  if(key == m_key.moveLeft && m_xSpeed < 0)
1025  {
1026  setXSpeed(-nSpeed);
1027  }
1028  else if(key == m_key.moveRight && m_xSpeed > 0)
1029  {
1030  setXSpeed(nSpeed);
1031  }
1032  else if(key == m_key.moveUp && m_ySpeed < 0)
1033  {
1034  setYSpeed(-nSpeed);
1035  }
1036  else if(key == m_key.moveDown && m_ySpeed > 0)
1037  {
1038  setYSpeed(nSpeed);
1039  }
1040  else if(key == m_key.dropBomb)
1041  {
1042  //emit bomb(this);
1043  }
1044 
1045  if(m_xSpeed == 0 && m_ySpeed == 0 && m_askedXSpeed == 0 && m_askedYSpeed == 0) stopMoving();
1046 }
1047 
1048 int Player::signZeroPositive(const qreal value)
1049 {
1050  return (value >= 0 ? 1 : -1);
1051 }
1052 
1053 int Player::sign(const qreal value)
1054 {
1055  if(value == 0)
1056  {
1057  return 0;
1058  }
1059  return (value > 0 ? 1 : -1);
1060 }
Player::stopped
void stopped()
Emitted when the player stops moving.
QTimer::setInterval
void setInterval(int msec)
QList::clear
void clear()
PlayerSettings::playerDesktopFilePath
const QString playerDesktopFilePath(const QString &strPlayerID) const
Definition: playersettings.cpp:134
Player::emitGameUpdated
void emitGameUpdated()
Emits a signal to PlayerItem in order to manage collisions.
Definition: player.cpp:804
Player::direction
int direction()
Definition: player.cpp:819
Settings::initialBombArmory
static int initialBombArmory()
Get The initial bomb armory.
Definition: settings.h:201
Player::sign
int sign(const qreal value)
Returns the sign of a value with 0 for zero.
Definition: player.cpp:1053
Granatier::Cell::ICE
Definition: granatierglobals.h:77
Element::m_type
Granatier::Element::Type m_type
The Element type.
Definition: element.h:39
Element::m_x
qreal m_x
The Element current x-coordinate.
Definition: element.h:48
Character::m_key
Shortcuts m_key
Definition: character.h:46
Element::m_y
qreal m_y
The Element current y-coordinate.
Definition: element.h:51
Player::addBonus
void addBonus(Bonus *p_bonus)
Manages the points won.
Definition: player.cpp:514
Character::Shortcuts::moveRight
QKeySequence moveRight
Definition: character.h:41
badBonusCountdown
const int badBonusCountdown
Definition: player.cpp:33
Arena::setCellElement
void setCellElement(const int p_row, const int p_column, Element *p_element)
Sets the Element that is on the Cell whose coordinates are given in parameters.
Definition: arena.cpp:72
Player::hasThrowBomb
bool hasThrowBomb()
Definition: player.cpp:690
Granatier::Bonus::KICK
Definition: granatierglobals.h:111
Bonus
This class represents a Bonus for the Player.
Definition: bonus.h:29
Granatier::Bonus::SHIELD
Definition: granatierglobals.h:109
Player::getBombPower
int getBombPower() const
Definition: player.cpp:824
Character
This class describes the common characteristics and behaviour of the game characters (Players)...
Definition: character.h:31
Settings::initialSpeed
static int initialSpeed()
Get The initial speed.
Definition: settings.h:163
Granatier::Element::PLAYER
Definition: granatierglobals.h:93
Player::getPlayerName
QString getPlayerName() const
Gets the Player name.
Definition: player.cpp:80
Player::getDesktopFilePath
QString getDesktopFilePath() const
Gets the path to the Player Desktop file.
Definition: player.cpp:75
PlayerSettings::keyUp
const QKeySequence keyUp(const QString &strPlayerID) const
Definition: playersettings.cpp:149
Player::keyPressed
void keyPressed(QKeyEvent *keyEvent)
Manages the keys for moving and dropping bombs.
Definition: player.cpp:939
Player::goDown
void goDown()
Makes the Player ask to go down.
Definition: player.cpp:121
Player::bombDropped
void bombDropped(Player *player, qreal x, qreal y, bool newBomb, int throwDistance)
Emitted when the player drops a bomb.
Bonus::getBonusType
Granatier::Bonus::Type getBonusType() const
Definition: bonus.cpp:42
PlayerSettings::playerName
const QString playerName(const QString &strPlayerID) const
Definition: playersettings.cpp:129
Player::resurrect
void resurrect()
resurrects the player
Definition: player.cpp:734
Player::addPoint
void addPoint()
adds a point
Definition: player.cpp:799
Cell::getElements
QList< Element * > getElements() const
Gets all the Elements that are on the Cell.
Definition: cell.cpp:62
Player::dying
void dying()
Emitted when the player is dying.
Player::goLeft
void goLeft()
Makes the Player ask to go to the left.
Definition: player.cpp:149
PlayerSettings::keyRight
const QKeySequence keyRight(const QString &strPlayerID) const
Definition: playersettings.cpp:154
QKeyEvent::isAutoRepeat
bool isAutoRepeat() const
Player::pause
void pause()
pause the timer
Definition: player.cpp:94
Player::points
int points() const
returns the points
Definition: player.cpp:794
Character::setXSpeed
void setXSpeed(qreal p_xSpeed)
Set the Character x-speed value.
Definition: character.cpp:83
Arena::removeCellElement
void removeCellElement(const int p_row, const int p_column, Element *p_element)
Removes the Element that is on the Cell whose coordinates are given in parameters.
Definition: arena.cpp:81
Player::isAlive
bool isAlive() const
returns if the player is alive
Definition: player.cpp:729
Element::m_xInit
qreal m_xInit
The Element initial x-coordinate.
Definition: element.h:42
player.h
Granatier::Bonus::BOMB
Definition: granatierglobals.h:107
Character::setYSpeed
void setYSpeed(qreal p_ySpeed)
Set the Character y-speed value.
Definition: character.cpp:88
PlayerSettings::keyDown
const QKeySequence keyDown(const QString &strPlayerID) const
Definition: playersettings.cpp:159
Granatier::Bonus::SCATTY
Definition: granatierglobals.h:115
Player::keyReleased
void keyReleased(QKeyEvent *keyEvent)
Manages the keys for moving and dropping bombs.
Definition: player.cpp:996
Player::gameUpdated
void gameUpdated()
Signals to PlayerItem that the game has been updated.
Granatier::Bonus::HYPERACTIVE
Definition: granatierglobals.h:113
Character::Shortcuts
Keyboard shortcuts for moving and dropping a bomb.
Definition: character.h:38
Settings::self
static Settings * self()
Definition: settings.cpp:17
Element::moved
void moved(qreal p_x, qreal p_y)
Emitted on Element move.
PlayerSettings::keyPutBomb
const QKeySequence keyPutBomb(const QString &strPlayerID) const
Definition: playersettings.cpp:169
Player::Player
Player(qreal p_x, qreal p_y, const QString &p_playerID, const PlayerSettings *p_playerSettings, Arena *p_arena)
Creates a new Player instance.
Definition: player.cpp:35
Player::resume
void resume()
resume the timer
Definition: player.cpp:99
QList::count
int count(const T &value) const
Granatier::CellSize
const qreal CellSize
The Cell size.
Definition: granatierglobals.h:31
QList::append
void append(const T &value)
QTimer
Granatier::Direction::WEST
Definition: granatierglobals.h:129
Player::updateMove
void updateMove()
Updates the Player move.
Definition: player.cpp:178
Element::m_arena
Arena * m_arena
The Arena the Element is on.
Definition: element.h:54
Player::bonusUpdated
void bonusUpdated(Player *player, Granatier::Bonus::Type bonusType, int percentageElapsed)
Emitted when the player has taken a bonus.
Player::falling
void falling()
Emitted when the player is falling in a hole.
Player::directionChanged
void directionChanged()
Emitted when the direction changed.
Character::Shortcuts::moveDown
QKeySequence moveDown
Definition: character.h:43
QList::isEmpty
bool isEmpty() const
onIceSpeedIncrease
const int onIceSpeedIncrease
Definition: player.cpp:31
Bomb
This class describes the common characteristics and behaviour of the bomb item.
Definition: bomb.h:30
Character::move
void move()
Moves the Character function of its current coordinates and speed.
Definition: character.cpp:33
Granatier::Bonus::RESURRECT
Definition: granatierglobals.h:117
Arena
This class represents the Arena of the game.
Definition: arena.h:36
Player::setShortcuts
void setShortcuts(const Shortcuts &keys)
Shortcuts for moving and dropping bombs.
Definition: player.cpp:65
Player::getAskedXSpeed
qreal getAskedXSpeed() const
Definition: player.cpp:809
PlayerSettings
Definition: playersettings.h:27
QString
QList< Element * >
Player::decrementBombArmory
void decrementBombArmory()
decrements the bomb armory
Definition: player.cpp:829
Settings::initialBombPower
static int initialBombPower()
Get The initial bomb power.
Definition: settings.h:182
bonus.h
PlayerSettings::playerGraphicsFile
const QString playerGraphicsFile(const QString &strPlayerID) const
Definition: playersettings.cpp:139
Granatier::Bonus::THROW
Definition: granatierglobals.h:110
QKeyEvent::key
int key() const
Element
This class describes the common characteristics and behaviour of any game Element (character or item)...
Definition: element.h:32
playersettings.h
Player::hasBadBonus
bool hasBadBonus()
Definition: player.cpp:700
QEvent::accept
void accept()
Granatier::Element::BOMB
Definition: granatierglobals.h:94
Granatier::Direction::NORTH
Definition: granatierglobals.h:126
QTimer::stop
void stop()
Character::m_ySpeed
qreal m_ySpeed
The Character y-speed.
Definition: character.h:54
Granatier::Bonus::MIRROR
Definition: granatierglobals.h:114
Character::Shortcuts::moveLeft
QKeySequence moveLeft
Definition: character.h:40
Player::die
void die()
Implements the Character function.
Definition: player.cpp:709
Player::goUp
void goUp()
Makes the Player ask to go up.
Definition: player.cpp:107
Granatier::Bonus::RESTRAIN
Definition: granatierglobals.h:116
Granatier::Bonus::SPEED
Definition: granatierglobals.h:106
Character::m_xSpeed
qreal m_xSpeed
The Character x-speed.
Definition: character.h:51
QKeyEvent
Player::getGraphicsFile
QString getGraphicsFile() const
Gets the file for the Player SVG.
Definition: player.cpp:70
Player::resurrected
void resurrected()
Emitted when the player has resurrected.
settings.h
Player::signZeroPositive
int signZeroPositive(const qreal value)
Returns the sign of a value with a positive sign for zero.
Definition: player.cpp:1048
Player::hasShield
bool hasShield()
Definition: player.cpp:681
QKeySequence
Player::getAskedYSpeed
qreal getAskedYSpeed() const
Definition: player.cpp:814
Player::resurrectBonusTaken
void resurrectBonusTaken()
Emitted when the player has taken the resurrect bonus.
QList::last
T & last()
Character::m_maxSpeed
qreal m_maxSpeed
The maximum character speed.
Definition: character.h:63
Character::Shortcuts::dropBomb
QKeySequence dropBomb
Definition: character.h:44
Player::~Player
~Player()
Deletes the Player instance.
Definition: player.cpp:60
Arena::getColFromX
int getColFromX(const qreal p_x) const
Gets the column index corresponding to the given x-coordinate.
Definition: arena.cpp:154
Cell::isWalkable
bool isWalkable(Element *p_element) const
Returns if it is possible to move into the cell or not, because of a wall, bomb, etc.
Definition: cell.cpp:30
badBonusTimerTimeout
const int badBonusTimerTimeout
Definition: player.cpp:32
Character::Shortcuts::moveUp
QKeySequence moveUp
Definition: character.h:42
Element::m_yInit
qreal m_yInit
The Element initial y-coordinate.
Definition: element.h:45
Granatier::Direction::EAST
Definition: granatierglobals.h:128
arena.h
QTimer::start
void start(int msec)
PlayerSettings::keyLeft
const QKeySequence keyLeft(const QString &strPlayerID) const
Definition: playersettings.cpp:164
Player::goRight
void goRight()
Makes the Player ask to go to the right.
Definition: player.cpp:135
Player::shield
bool shield(int n_ExplosionID)
Manages the points won.
Definition: player.cpp:660
Granatier::Bonus::POWER
Definition: granatierglobals.h:108
QTimer::isActive
bool isActive() const
QObject::connect
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
Granatier::Cell::HOLE
Definition: granatierglobals.h:73
Character::m_speed
qreal m_speed
The character speed.
Definition: character.h:57
bomb.h
Cell::getType
Granatier::Cell::Type getType() const
Gets the Cell type.
Definition: cell.cpp:52
Arena::getCell
Cell getCell(const int p_row, const int p_column) const
Gets the Cell at the given coordinates.
Definition: arena.cpp:120
Granatier::Direction::SOUTH
Definition: granatierglobals.h:127
Granatier::Bonus::Type
Type
Definition: granatierglobals.h:103
Granatier::Bonus::SLOW
Definition: granatierglobals.h:112
Player::slot_refillBombArmory
void slot_refillBombArmory()
refills the bomb armory after a bomb is exploded
Definition: player.cpp:838
Arena::getRowFromY
int getRowFromY(const qreal p_y) const
Gets the row index corresponding to the given y-coordinate.
Definition: arena.cpp:144
Player::hasKickBomb
bool hasKickBomb()
Definition: player.cpp:695
Player::init
void init()
Initializes the Player.
Definition: player.cpp:85
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:18:10 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

granatier

Skip menu "granatier"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members

kdegames API Reference

Skip menu "kdegames API Reference"
  • granatier
  • kapman
  • kblackbox
  • kgoldrunner
  • kigo
  • kmahjongg
  • KShisen
  • ksquares
  • libkdegames
  •   highscore
  •   libkdegamesprivate
  •     kgame
  • libkmahjongg
  • palapeli
  •   libpala

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal