Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added : DinoGame #25

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 15 additions & 1 deletion app/src/main/java/dev/baseio/composeplayground/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.BoxWithConstraints
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material.MaterialTheme
Expand Down Expand Up @@ -41,6 +42,7 @@ import dev.baseio.composeplayground.ui.animations.anmolverma.BellAnimation
import dev.baseio.composeplayground.ui.animations.anmolverma.ShootingStarsAnimation
import dev.baseio.composeplayground.ui.animations.anmolverma.planetarysystem.PlanetarySystem
import dev.baseio.composeplayground.ui.animations.anmolverma.pulltorefresh.PullToRefreshOne
import dev.baseio.composeplayground.ui.animations.niket.dino_game.game.DinoGameView
import dev.baseio.composeplayground.ui.theme.ComposePlaygroundTheme

class MainActivity : ComponentActivity() {
Expand Down Expand Up @@ -81,7 +83,7 @@ class MainActivity : ComponentActivity() {
) {
HorizontalPager(
modifier = Modifier.fillMaxSize(),
count = 15, state = pagerState,
count = 21, state = pagerState,
) { page ->
// Our page content
when (page) {
Expand Down Expand Up @@ -183,6 +185,18 @@ class MainActivity : ComponentActivity() {
ShubhamSingh(modifier = Modifier.align(Alignment.BottomCenter))
}
}
20 -> {
BoxWithConstraints(
modifier = Modifier
.fillMaxSize()
) {
DinoGameView(
windowResource = applicationContext.resources,
maxWidth = maxWidth,
maxHeight = maxHeight,
)
}
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package dev.baseio.composeplayground.contributors

import androidx.compose.foundation.layout.*
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import dev.baseio.composeplayground.R
import dev.baseio.composeplayground.ui.theme.Typography


const val niketJainImageUrl = "https://avatars.githubusercontent.com/u/52085669?v=4"

@Composable
fun NiketJain(modifier: Modifier = Modifier) {
Row(verticalAlignment = Alignment.CenterVertically, modifier = modifier.padding(4.dp)) {
CoilImageBox(Modifier.size(64.dp), niketJainImageUrl)
Column(verticalArrangement = Arrangement.Center, modifier = Modifier.padding(8.dp)) {
Text(
text = stringResource(id = R.string.niket_name),
style = Typography.h6.copy(MaterialTheme.colors.onSurface),
)
Text(
text = stringResource(id = R.string.niket_email),
style = Typography.subtitle1.copy(MaterialTheme.colors.onSurface),
)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
package dev.baseio.composeplayground.ui.animations.niket.dino_game.game

import androidx.compose.animation.core.Animatable
import androidx.compose.animation.core.LinearEasing
import androidx.compose.animation.core.animateFloat
import androidx.compose.animation.core.infiniteRepeatable
import androidx.compose.animation.core.rememberInfiniteTransition
import androidx.compose.animation.core.tween
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import dev.baseio.composeplayground.ui.animations.niket.dino_game.model.CactusObstacles
import dev.baseio.composeplayground.ui.animations.niket.dino_game.model.CloudCoordinates
import dev.baseio.composeplayground.ui.animations.niket.dino_game.model.CloudModel
import dev.baseio.composeplayground.ui.animations.niket.dino_game.model.DinoGameModel
import dev.baseio.composeplayground.ui.animations.niket.dino_game.model.DinoModel
import dev.baseio.composeplayground.ui.animations.niket.dino_game.model.ObstacleModel

/*
Various methods to handle and change the state of the
different objects.
*/
@Composable
fun dinoGameState(
obstaclesList: MutableList<ObstacleModel>,
cloudList: MutableList<CloudCoordinates>,
): DinoGameModel {
val animationScope = rememberCoroutineScope()

val obstaclesList = createRandomGameObstacles(obstaclesList = obstaclesList)
val cloudList = createRandomClouds(cloudList = cloudList)

// Create Dino
val dinoXPosition by remember { mutableStateOf(200f) }
val dinoYPosition by remember { mutableStateOf(1320f) }
val animatableDinoX = remember { Animatable(initialValue = dinoXPosition) }
val animatableDinoY = remember { Animatable(initialValue = dinoYPosition) }
val isRunning by remember { mutableStateOf(true) }
val isJumping by remember { mutableStateOf(false) }
val isCollided by remember { mutableStateOf(false) }

val infiniteTransition = rememberInfiniteTransition()
val runningDinoAnimationState = infiniteTransition.animateFloat(
initialValue = 0f,
targetValue = 5f,
animationSpec = infiniteRepeatable(
animation = tween(
durationMillis = 400,
easing = LinearEasing
)
)
)

val dino = DinoModel(
xPosition = dinoXPosition,
yPosition = dinoYPosition,
isRunning = isRunning,
isJumping = isJumping,
isCollided = isCollided,
animateX = animatableDinoX,
animateY = animatableDinoY,
dinoState = runningDinoAnimationState
)

return DinoGameModel(
dino = dino,
coroutineScope = animationScope,
obstaclesList = obstaclesList,
cloudList = cloudList
)
}

@Composable
fun createRandomClouds(cloudList: MutableList<CloudCoordinates>): MutableList<CloudModel> {

val isMoving by remember { mutableStateOf(true) }
val cloudStateList = mutableListOf<CloudModel>()

for (cloud: CloudCoordinates in cloudList) {
val infiniteTransition = rememberInfiniteTransition()
val floatingCloudToLeftInfiniteTransition = infiniteTransition.animateFloat(
initialValue = cloud.xPosition,
targetValue = -cloud.xPosition,
animationSpec = infiniteRepeatable(
animation = tween(
durationMillis = (cloud.xPosition * 15).toInt() / 2,
easing = LinearEasing
)
)
)

cloudStateList.add(
CloudModel(
cloudCoordinates = cloud,
isMoving = isMoving,
cloudState = floatingCloudToLeftInfiniteTransition
)
)
}

return cloudStateList
}


@Composable
fun createRandomGameObstacles(
obstaclesList: MutableList<ObstacleModel>
): MutableList<CactusObstacles> {
val cactusObstaclesList = mutableListOf<CactusObstacles>()

for (obstacles: ObstacleModel in obstaclesList) {
val isCollision by remember {
mutableStateOf(false)
}

val infiniteObstaclesTransition = rememberInfiniteTransition()
val obstaclesTransition = infiniteObstaclesTransition.animateFloat(
initialValue = obstacles.xPosition,
targetValue = -obstacles.xPosition.div(1000f),
animationSpec = infiniteRepeatable(
animation = tween(
durationMillis = (obstacles.xPosition * 5).toInt() / 2,
easing = LinearEasing
)
)
)

cactusObstaclesList.add(
CactusObstacles(
obstacleModel = obstacles,
isCollision = isCollision,
isPassedOutOfScreen = false,
cactusObstaclesState = obstaclesTransition
)
)
}

return cactusObstaclesList
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
package dev.baseio.composeplayground.ui.animations.niket.dino_game.game

import android.content.res.Resources
import androidx.compose.animation.core.LinearOutSlowInEasing
import androidx.compose.animation.core.tween
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.background
import androidx.compose.foundation.gestures.detectTapGestures
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.drawscope.DrawScope
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.unit.Dp
import dev.baseio.composeplayground.ui.animations.niket.dino_game.model.CactusObstacles
import dev.baseio.composeplayground.ui.animations.niket.dino_game.model.CloudModel
import dev.baseio.composeplayground.ui.animations.niket.dino_game.model.DinoGameModel
import dev.baseio.composeplayground.ui.animations.niket.dino_game.util.createRandomCloudsList
import dev.baseio.composeplayground.ui.animations.niket.dino_game.util.createRandomObstaclesList
import dev.baseio.composeplayground.contributors.NiketJain
import dev.baseio.composeplayground.ui.theme.DarkDinoGameBackground
import kotlinx.coroutines.launch

@Composable
fun DinoGameView(
windowResource: Resources,
maxWidth: Dp,
maxHeight: Dp,
) {
val dinoGameState = dinoGameState(
createRandomObstaclesList(maxHeight),
createRandomCloudsList(maxWidth)
)

/**
* Drawing every object at the canvas
*/
Box(
modifier = Modifier.fillMaxSize(),
contentAlignment = Alignment.BottomCenter
) {
CreateGameCanvas(
gameState = dinoGameState,
drawGameView = { drawScope ->
drawScope.drawGround(resource = windowResource)
drawScope.drawDino(
gameState = dinoGameState,
resource = windowResource
)
removeThePassedObstacles(dinoGameState)
for (obstacles: CactusObstacles in dinoGameState.obstaclesList) {
drawScope.drawObstacles(
resource = windowResource,
obstacles = obstacles,
dinoGameState = dinoGameState
)
}
for (cloud: CloudModel in dinoGameState.cloudList) {
drawScope.drawCloud(
resources = windowResource,
cloudModel = cloud
)
}
}
)
NiketJain()
}
}

@Composable
private fun CreateGameCanvas(
gameState: DinoGameModel,
drawGameView: (DrawScope) -> Unit
) {
Canvas(
modifier = Modifier
.fillMaxSize()
.background(
color = DarkDinoGameBackground
)
.pointerInput(Unit) {
/** When Clicked make the Dino Jump **/
detectTapGestures {
gameState.dino.isJumping = true
if (gameState.dino.isJumping) {
gameState.coroutineScope.launch {
gameState.dino.isRunning = false
gameState.dino.animateY.animateTo(
targetValue = gameState.dino.yPosition - 175,
animationSpec = tween(
durationMillis = 275,
easing = LinearOutSlowInEasing
)
)
gameState.dino.animateY.animateTo(
targetValue = gameState.dino.yPosition,
animationSpec = tween(
durationMillis = 325,
easing = LinearOutSlowInEasing
)
)
gameState.dino.isRunning = true
gameState.dino.isJumping = false
}
}
}
},
) {
drawGameView(this)
}
}

/*
Removing the Obstacles to save the Resources
We are removing the item that has been passed the X-axis screen.
*/
fun removeThePassedObstacles(gameState: DinoGameModel) {
gameState.obstaclesList.removeAll { obstacles ->
obstacles.isPassedOutOfScreen && (obstacles.obstacleModel.xPosition <= 0)
}

}
Loading