diff --git a/Tetris/app/src/main/java/but/androidstudio/tetris/GameFragment.kt b/Tetris/app/src/main/java/but/androidstudio/tetris/GameFragment.kt index 2be892e..a9185a4 100644 --- a/Tetris/app/src/main/java/but/androidstudio/tetris/GameFragment.kt +++ b/Tetris/app/src/main/java/but/androidstudio/tetris/GameFragment.kt @@ -3,16 +3,14 @@ package but.androidstudio.tetris import android.content.Context import android.hardware.Sensor import android.hardware.SensorManager +import android.media.MediaPlayer import android.os.Bundle -import android.util.Log import androidx.fragment.app.Fragment import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.Button -import kotlinx.coroutines.GlobalScope -import kotlinx.coroutines.delay -import kotlinx.coroutines.launch +import android.widget.TextView import androidx.core.content.ContextCompat.getSystemService import modele.Game import views.ViewsGame @@ -41,17 +39,22 @@ class GameFragment : Fragment(){ override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - // La vue se refresh quand on fait quelque chose dessus (changer un parametre ) viewGame = view.findViewById(R.id.tabGame) viewGame.nbCaseHauteur = heightGame viewGame.nbCaseLargeur = withGame - modeleGame = Game(height = heightGame, width = withGame, viewGame = viewGame) + val sensorManager = activity?.getSystemService(Context.SENSOR_SERVICE) as SensorManager + val sensor: Sensor? = sensorManager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR) + val mediaPlayer = MediaPlayer.create(context,R.raw.tetris) val buttonRight:Button = view.findViewById(R.id.Button_Right) val buttonLeft:Button = view.findViewById(R.id.Button_Left) val buttonRotateRight:Button = view.findViewById(R.id.Button_Right_Rotation) val buttonRotateLeft:Button = view.findViewById(R.id.Button_Left_Rotation) + val points:TextView = view.findViewById(R.id.Id_Points) + + modeleGame = Game(height = heightGame, width = withGame, viewGame = viewGame, points = points) + buttonRight.setOnClickListener { modeleGame.dashBoard.moveRight(modeleGame.currentShape) } @@ -65,7 +68,8 @@ class GameFragment : Fragment(){ modeleGame.dashBoard.rotateShapeLeft(modeleGame.currentShape) } - + mediaPlayer.start() modeleGame.startGame() } + } \ No newline at end of file diff --git a/Tetris/app/src/main/java/modele/DashBoard.kt b/Tetris/app/src/main/java/modele/DashBoard.kt index e376a92..d2eecaa 100644 --- a/Tetris/app/src/main/java/modele/DashBoard.kt +++ b/Tetris/app/src/main/java/modele/DashBoard.kt @@ -1,15 +1,13 @@ package modele -import android.util.Log import kotlinx.coroutines.delay import views.ViewsGame +import kotlin.io.path.fileVisitor class DashBoard(private val width: Int,private val height: Int,private val view: ViewsGame) { val gridOfGame = Array(this.height) { IntArray(this.width) } - // To set something to occupied - fun toOccupied(col: Int, row: Int, value: Int) { gridOfGame[row][col] = value } @@ -17,7 +15,7 @@ class DashBoard(private val width: Int,private val height: Int,private val view: // To check if an position is occupied fun isOccupied(col: Int, row: Int): Boolean = gridOfGame[row][col] != 0 - fun isLineFull(row: Int): Boolean { + private fun isLineFull(row: Int): Boolean { for (col in 0 until this.width) { if (gridOfGame[row][col] == 0) { return false @@ -26,48 +24,48 @@ class DashBoard(private val width: Int,private val height: Int,private val view: return true } - fun clearLine(row: Int) { + private fun clearLine(row: Int) { for (col in 0 until this.width) { gridOfGame[row][col] = 0 } } - fun shiftDown(rowToBegin: Int) { - for (row in (height - 1)..rowToBegin) { - for (col in 0 until this.width) { - gridOfGame[row][col] = gridOfGame[row - rowToBegin][col] - } - } - for (row in 0 until rowToBegin) { - for (col in 0 until this.width) { - gridOfGame[row][col] = 0 + private fun shiftDown(listeLine:MutableList) { + + println("Shift Down") + for( index in listeLine){ + println(index) + for ( line in index downTo 1 ){ + for ( column in 0 until width){ + gridOfGame[line][column] = gridOfGame[line-1][column] + } } } + updateViewGame() } //To check each grid line and remove if a line is full. Uses clearLine(), isLineFull() and shiftDown() - fun clearLines() { + fun clearLines():Int{ + val listeLine = mutableListOf() var nbRowCleared: Int = 0 for (row in 0 until this.height) { if (isLineFull(row)) { clearLine(row) ++nbRowCleared + listeLine.add(row) } } if (nbRowCleared != 0) { - shiftDown(nbRowCleared) + shiftDown(listeLine) } + return nbRowCleared } fun addShape(shape: Shape): Boolean { for (line in 0..3) { // On vérifie que l'espace est disponible for (column in 0..3) { - if ((isOccupied( - shape.position.x + column, - shape.position.y + line - )) and (shape.typeShape.showShape[line][column] == 1) - ) { + if ( (shape.typeShape.showShape[line][column] == 1) and (gridOfGame[shape.position.y+line][shape.position.x+column] != 0)){ return false } } @@ -111,9 +109,6 @@ class DashBoard(private val width: Int,private val height: Int,private val view: val pos:MutableList = shape.sharePositionLeft() for ( position in pos){ - println("X -> : "+position.x) - println("X -> : "+position.y) - if ( shape.position.x < 0 ){ return false } @@ -139,7 +134,7 @@ class DashBoard(private val width: Int,private val height: Int,private val view: } private fun moveDownPossible(shape: Shape):Boolean{ - val pos:MutableList = shape.sharePositionRight() + val pos:MutableList = shape.sharePositionDown(shape) for ( position in pos){ if ( position.y+shape.position.y >= height){ @@ -175,8 +170,11 @@ class DashBoard(private val width: Int,private val height: Int,private val view: for ( line in 0..3){ for ( column in 0..3){ - if ( (matrix[line][column] == 1) and (shape.typeShape.showShape[line][column] == 0 )){ - if ( gridOfGame[shape.position.y+column][shape.position.x+line] != 0 ) { + if ( matrix[line][column] == 1){ + if ( (shape.position.y+line >= height) or (shape.position.x+column >= width)){ + return false + } + if (gridOfGame[shape.position.y+line][shape.position.x+column] != 0 ){ return false } } @@ -189,6 +187,7 @@ class DashBoard(private val width: Int,private val height: Int,private val view: fun rotateShapeRight(shape: Shape){ println("Shape action -> Rotation right ! ") + deleteShape(shape) rotationShapePossible(shape,0) writeShape(shape) @@ -197,6 +196,7 @@ class DashBoard(private val width: Int,private val height: Int,private val view: fun rotateShapeLeft(shape: Shape){ println("Shape action -> Rotation left ! ") + deleteShape(shape) rotationShapePossible(shape,1) writeShape(shape) @@ -217,8 +217,6 @@ class DashBoard(private val width: Int,private val height: Int,private val view: // Write the shape in gridOfGame private fun writeShape(shape: Shape){ - println("Final X : "+shape.position.x) - println("Final Y : "+shape.position.y) for (line in 0..3) { for (column in 0..3) { @@ -237,8 +235,12 @@ class DashBoard(private val width: Int,private val height: Int,private val view: view.invalidate() } - suspend fun fallingShape(shape: Shape){ - delay(800) - moveDown(shape) + suspend fun fallingShape(shape: Shape, difficulty: Difficulty):Boolean{ + when(difficulty){ + Difficulty.EASY -> delay(700) + Difficulty.MEDIUM -> delay(500) + Difficulty.HARD -> delay(300) + } + return moveDown(shape) } } \ No newline at end of file diff --git a/Tetris/app/src/main/java/modele/Game.kt b/Tetris/app/src/main/java/modele/Game.kt index 32f566e..32fe266 100644 --- a/Tetris/app/src/main/java/modele/Game.kt +++ b/Tetris/app/src/main/java/modele/Game.kt @@ -1,54 +1,70 @@ package modele -import android.util.Log +import android.widget.TextView import kotlinx.coroutines.GlobalScope -import kotlinx.coroutines.cancel import kotlinx.coroutines.launch import views.ViewsGame +import kotlin.random.Random -class Game(private val width: Int,private val height: Int,private val viewGame:ViewsGame) { +class Game(private val width: Int,private val height: Int,private val viewGame:ViewsGame,private val points:TextView) { val dashBoard: DashBoard = DashBoard(width,height,viewGame) lateinit var currentShape: Shape - var difficulty: Difficulty = Difficulty.EASY - - + private var difficulty: Difficulty = Difficulty.EASY + + + //To get the next shape + private fun getNextShape(): TypeShape { + return when(Random.nextInt(1,7)){ + 1 -> TypeShape(EnumTypeShape.IShape) + 2 -> TypeShape(EnumTypeShape.SquareShape) + 3 -> TypeShape(EnumTypeShape.JShape) + 4 -> TypeShape(EnumTypeShape.LShape) + 5 -> TypeShape(EnumTypeShape.SShape) + 6 -> TypeShape(EnumTypeShape.TShape) + 7 -> TypeShape(EnumTypeShape.ZShape) + else -> throw Exception("Problème de random getNextShape()") + } + } // The start game function fun startGame(){ - //this.setCurrentShape(TypeShape.SquareShape) - currentShape = Shape(TypeShape(EnumTypeShape.SShape),Position(1,1)) - dashBoard.addShape(currentShape) - currentShape = Shape(TypeShape(EnumTypeShape.IShape),Position(2,5)) + currentShape = Shape(getNextShape(),Position(width/2,0)) dashBoard.addShape(currentShape) - //currentShape = Shape(TypeShape(EnumTypeShape.SquareShape),Position(2,6)) - //dashBoard.addShape(currentShape) - - //currentShape = Shape(TypeShape(EnumTypeShape.TShape),Position(2,8)) - //dashBoard.addShape(currentShape) - - //currentShape = Shape(TypeShape(EnumTypeShape.ZShape),Position(2,10)) - //dashBoard.addShape(currentShape) - - //currentShape = Shape(TypeShape(EnumTypeShape.SShape),Position(1,1)) - //dashBoard.addShape(currentShape) - - //currentShape = Shape(TypeShape(EnumTypeShape.JShape),Position(1,1)) - //dashBoard.addShape(currentShape) - - //dashBoard.gridOfGame[2][0] = 5 - println("RUN !!") dashBoard.updateViewGame() + // Ne pas utiliser de global scope !!!! SA ENLEVE DES POINTS !!!!!! GlobalScope.launch { - while (true){ - dashBoard.fallingShape(currentShape) + while(true){ + if(dashBoard.fallingShape(currentShape,difficulty)){ + + // Clear line + val nbLine = dashBoard.clearLines() + + // Score + if ( (nbLine > 0) and (nbLine<4)){ + val tmpPoints:String = points.text as String + points.text = (tmpPoints.toInt()+(nbLine*100)).toString() + } + if ( nbLine == 4 ){ + val tmpPoints:String = points.text as String + points.text = (tmpPoints.toInt()+1200).toString() + } + } + else { + // New shape + currentShape = Shape(getNextShape(),Position(width/2,0)) + if ( !dashBoard.addShape(currentShape)){ + break + } + } } + println("Game end !!") } } } \ No newline at end of file diff --git a/Tetris/app/src/main/java/modele/Shape.kt b/Tetris/app/src/main/java/modele/Shape.kt index 464f509..8b59686 100644 --- a/Tetris/app/src/main/java/modele/Shape.kt +++ b/Tetris/app/src/main/java/modele/Shape.kt @@ -1,8 +1,6 @@ package modele -import java.lang.reflect.Type - -class Shape(val typeShape: TypeShape,var position: Position) { +class Shape(val typeShape: TypeShape, var position: Position) { fun sharePositionRight():MutableList{ val sharePosition = mutableListOf() for( line in 0..3){ @@ -51,28 +49,26 @@ class Shape(val typeShape: TypeShape,var position: Position) { } } } - return sharePosition } -<<<<<<< HEAD - fun sharePositionUp(shape: Shape): MutableList{ + fun sharePositionUp(shape: Shape): MutableList { val sharePosition = mutableListOf() - for( line in 0..3){ + for (line in 0..3) { for (column in 0..3) { - if ( line != 3 ){ - if ( (typeShape.showShape[line][column] == 1) and (typeShape.showShape[line+1][column] == 0)){ - sharePosition.add(Position(column,line)) + if (line != 3) { + if ((typeShape.showShape[line][column] == 1) and (typeShape.showShape[line + 1][column] == 0)) { + sharePosition.add(Position(column, line)) } } - if ( (line == 3) and (typeShape.showShape[line][column] == 1) ){ - sharePosition.add(Position(column,line)) + if ((line == 3) and (typeShape.showShape[line][column] == 1)) { + sharePosition.add(Position(column, line)) } } } - return sharePosition -======= + } + fun sharePositionRotationRight(shape: Shape):Array{ var leftmostCol = 4 @@ -104,8 +100,9 @@ class Shape(val typeShape: TypeShape,var position: Position) { return rotatedMatrix } - fun sharePositionRotationLeft(shape: Shape):Array{ - var leftmostCol = 4 + fun sharePositionRotationLeft(shape: Shape):Array { + var leftMostCol = 4 + var topMostLine = 4 // Pivoter la matrice val rotatedMatrix = Array(4) { row -> IntArray(4) { col -> @@ -115,24 +112,28 @@ class Shape(val typeShape: TypeShape,var position: Position) { // Trouver l'index de la colonne la plus à gauche for (row in 0 until 4) { for (col in 0 until 4) { - if (rotatedMatrix[row][col] != 0 && col < leftmostCol) { - leftmostCol = col + if (rotatedMatrix[row][col] != 0 && col < leftMostCol) { + leftMostCol = col + } + if ( rotatedMatrix[row][col] != 0 && row < topMostLine){ + topMostLine = row } } } + // Décaler chaque ligne de la matrice vers la gauche - for (row in 0 until 4) { - for (col in 0 until leftmostCol) { - rotatedMatrix[row][col] = 0 + for (col in 0 until 4) { + for (line in 0 until topMostLine) { + rotatedMatrix[line][col] = 0 } - for (col in leftmostCol until 4) { - rotatedMatrix[row][col - leftmostCol] = rotatedMatrix[row][col] - if ( col - leftmostCol != col){ - rotatedMatrix[row][col] = 0 + for (line in topMostLine until 4) { + rotatedMatrix[line - topMostLine][col] = rotatedMatrix[line][col] + if ( line - topMostLine != line){ + rotatedMatrix[line][col] = 0 } } } + return rotatedMatrix ->>>>>>> Enzo } } \ No newline at end of file diff --git a/Tetris/app/src/main/java/modele/TypeShape.kt b/Tetris/app/src/main/java/modele/TypeShape.kt index ceeb7db..3c3a4db 100644 --- a/Tetris/app/src/main/java/modele/TypeShape.kt +++ b/Tetris/app/src/main/java/modele/TypeShape.kt @@ -3,9 +3,8 @@ package modele import java.lang.reflect.Type import kotlin.random.Random -class TypeShape(val type: EnumTypeShape){ +class TypeShape(private val type: EnumTypeShape){ - private var currentIndex = 0 var showShape:Array = Array(4){ IntArray(4 ) { 0 } } var couleur:Int = 0 @@ -64,45 +63,4 @@ class TypeShape(val type: EnumTypeShape){ } } } - - /* - fun getPoints(): Array{ - val positions = ArrayList() - val typeShape = getCurrentType() - for (i in typeShape.indices){ - for (j in typeShape[i].indices){ - if (typeShape[i][j] != 0) { - positions.add(Position(j, i)) - } - } - } - return positions.toTypedArray() - } - - //to augmente of 1 the current index - fun getNextType(): TypeShape { - currentIndex++ - return this - } - - - //To get the next shape - fun getNextShape(){ - val random: Int = Random.nextInt(1,7) - when(random){ - 1 -> TypeShape(EnumTypeShape.IShape, arrayOf(arrayOf(arrayOf()))) - 2 -> TypeShape(EnumTypeShape.SquareShape, arrayOf(arrayOf(arrayOf()))) - 3 -> TypeShape(EnumTypeShape.JShape, arrayOf(arrayOf(arrayOf()))) - 4 -> TypeShape(EnumTypeShape.LShape, arrayOf(arrayOf(arrayOf()))) - 5 -> TypeShape(EnumTypeShape.SShape, arrayOf(arrayOf(arrayOf()))) - 6 -> TypeShape(EnumTypeShape.TShape, arrayOf(arrayOf(arrayOf()))) - 7 -> TypeShape(EnumTypeShape.ZShape, arrayOf(arrayOf(arrayOf()))) - else -> throw Exception("Problème de random getNextShape()") - } - } - - // To get the table of position of the current shape type - private fun getCurrentType(): Array> { - return showShape[currentIndex] - }*/ } \ No newline at end of file diff --git a/Tetris/app/src/main/res/layout/fragment_game.xml b/Tetris/app/src/main/res/layout/fragment_game.xml index 1efa397..e8e1c32 100644 --- a/Tetris/app/src/main/res/layout/fragment_game.xml +++ b/Tetris/app/src/main/res/layout/fragment_game.xml @@ -38,12 +38,32 @@ android:background="@drawable/flechegauche" android:layout_marginStart="15dp"/> + + + + + + + +