123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136 |
- /*
- * Copyright (c) 2019 - 2020 Arnaud Vergnet.
- *
- * This file is part of Campus INSAT.
- *
- * Campus INSAT 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 3 of the License, or
- * (at your option) any later version.
- *
- * Campus INSAT is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Campus INSAT. If not, see <https://www.gnu.org/licenses/>.
- */
-
- // @flow
-
- export type CoordinatesType = {
- x: number;
- y: number;
- };
-
- export type ShapeType = Array<Array<number>>;
-
- /**
- * Abstract class used to represent a BaseShape.
- * Abstract classes do not exist by default in Javascript: we force it by throwing errors in the constructor
- * and in methods to implement
- */
- export default class BaseShape {
- #currentShape: ShapeType;
-
- #rotation: number;
-
- position: CoordinatesType;
-
- theme: ReactNativePaper.Theme;
-
- /**
- * Prevent instantiation if classname is BaseShape to force class to be abstract
- */
- constructor(theme: ReactNativePaper.Theme) {
- if (this.constructor === BaseShape) {
- throw new Error("Abstract class can't be instantiated");
- }
- this.theme = theme;
- this.#rotation = 0;
- this.position = {x: 0, y: 0};
- this.#currentShape = this.getShapes()[this.#rotation];
- }
-
- /**
- * Gets this shape's color.
- * Must be implemented by child class
- */
- getColor(): string {
- throw new Error("Method 'getColor()' must be implemented");
- }
-
- /**
- * Gets this object's all possible shapes as an array.
- * Must be implemented by child class.
- *
- * Used by tests to read private fields
- */
- getShapes(): Array<ShapeType> {
- throw new Error("Method 'getShapes()' must be implemented");
- }
-
- /**
- * Gets this object's current shape.
- */
- getCurrentShape(): ShapeType {
- return this.#currentShape;
- }
-
- /**
- * Gets this object's coordinates.
- * This will return an array of coordinates representing the positions of the cells used by this object.
- *
- * @param isAbsolute Should we take into account the current position of the object?
- * @return {Array<CoordinatesType>} This object cells coordinates
- */
- getCellsCoordinates(isAbsolute: boolean): Array<CoordinatesType> {
- const coordinates = [];
- for (let row = 0; row < this.#currentShape.length; row += 1) {
- for (let col = 0; col < this.#currentShape[row].length; col += 1) {
- if (this.#currentShape[row][col] === 1) {
- if (isAbsolute) {
- coordinates.push({
- x: this.position.x + col,
- y: this.position.y + row,
- });
- } else {
- coordinates.push({x: col, y: row});
- }
- }
- }
- }
- return coordinates;
- }
-
- /**
- * Rotate this object
- *
- * @param isForward Should we rotate clockwise?
- */
- rotate(isForward: boolean) {
- if (isForward) {
- this.#rotation += 1;
- } else {
- this.#rotation -= 1;
- }
- if (this.#rotation > 3) {
- this.#rotation = 0;
- } else if (this.#rotation < 0) {
- this.#rotation = 3;
- }
- this.#currentShape = this.getShapes()[this.#rotation];
- }
-
- /**
- * Move this object
- *
- * @param x Position X offset to add
- * @param y Position Y offset to add
- */
- move(x: number, y: number) {
- this.position.x += x;
- this.position.y += y;
- }
- }
|