Application Android et IOS pour l'amicale des élèves
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

BaseShape.ts 3.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. /*
  2. * Copyright (c) 2019 - 2020 Arnaud Vergnet.
  3. *
  4. * This file is part of Campus INSAT.
  5. *
  6. * Campus INSAT is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * Campus INSAT is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with Campus INSAT. If not, see <https://www.gnu.org/licenses/>.
  18. */
  19. // @flow
  20. export type CoordinatesType = {
  21. x: number;
  22. y: number;
  23. };
  24. export type ShapeType = Array<Array<number>>;
  25. /**
  26. * Abstract class used to represent a BaseShape.
  27. * Abstract classes do not exist by default in Javascript: we force it by throwing errors in the constructor
  28. * and in methods to implement
  29. */
  30. export default class BaseShape {
  31. #currentShape: ShapeType;
  32. #rotation: number;
  33. position: CoordinatesType;
  34. theme: ReactNativePaper.Theme;
  35. /**
  36. * Prevent instantiation if classname is BaseShape to force class to be abstract
  37. */
  38. constructor(theme: ReactNativePaper.Theme) {
  39. if (this.constructor === BaseShape) {
  40. throw new Error("Abstract class can't be instantiated");
  41. }
  42. this.theme = theme;
  43. this.#rotation = 0;
  44. this.position = {x: 0, y: 0};
  45. this.#currentShape = this.getShapes()[this.#rotation];
  46. }
  47. /**
  48. * Gets this shape's color.
  49. * Must be implemented by child class
  50. */
  51. getColor(): string {
  52. throw new Error("Method 'getColor()' must be implemented");
  53. }
  54. /**
  55. * Gets this object's all possible shapes as an array.
  56. * Must be implemented by child class.
  57. *
  58. * Used by tests to read private fields
  59. */
  60. getShapes(): Array<ShapeType> {
  61. throw new Error("Method 'getShapes()' must be implemented");
  62. }
  63. /**
  64. * Gets this object's current shape.
  65. */
  66. getCurrentShape(): ShapeType {
  67. return this.#currentShape;
  68. }
  69. /**
  70. * Gets this object's coordinates.
  71. * This will return an array of coordinates representing the positions of the cells used by this object.
  72. *
  73. * @param isAbsolute Should we take into account the current position of the object?
  74. * @return {Array<CoordinatesType>} This object cells coordinates
  75. */
  76. getCellsCoordinates(isAbsolute: boolean): Array<CoordinatesType> {
  77. const coordinates = [];
  78. for (let row = 0; row < this.#currentShape.length; row += 1) {
  79. for (let col = 0; col < this.#currentShape[row].length; col += 1) {
  80. if (this.#currentShape[row][col] === 1) {
  81. if (isAbsolute) {
  82. coordinates.push({
  83. x: this.position.x + col,
  84. y: this.position.y + row,
  85. });
  86. } else {
  87. coordinates.push({x: col, y: row});
  88. }
  89. }
  90. }
  91. }
  92. return coordinates;
  93. }
  94. /**
  95. * Rotate this object
  96. *
  97. * @param isForward Should we rotate clockwise?
  98. */
  99. rotate(isForward: boolean) {
  100. if (isForward) {
  101. this.#rotation += 1;
  102. } else {
  103. this.#rotation -= 1;
  104. }
  105. if (this.#rotation > 3) {
  106. this.#rotation = 0;
  107. } else if (this.#rotation < 0) {
  108. this.#rotation = 3;
  109. }
  110. this.#currentShape = this.getShapes()[this.#rotation];
  111. }
  112. /**
  113. * Move this object
  114. *
  115. * @param x Position X offset to add
  116. * @param y Position Y offset to add
  117. */
  118. move(x: number, y: number) {
  119. this.position.x += x;
  120. this.position.y += y;
  121. }
  122. }