# Teki – The barriers

In the very last chapter we implemented in our Teki Android game tutorial the jump and the crawl movement. So our heroine, Teki is closer and closer the have the chance to avoid the barriers.

In this chapter we gonna add this barriers to our game. A barrier can be a colorful, flying bird with different flight altitude or a stone on the ground. Further grit to the birds are flapping every second. 😉

#### Step 1 – The Textures

As always we are going to add first the Textures of the barriers. Basically we have birds and stones. In case of the birds we have up and down flapstates. There are several ways to solve how to add the images. My solution is to have 2 mutableList of Textures. One for the upflaps and one for the downflaps. Both of them contains the same stones as well.

If you have a better solution, leave me a comment. 😉
###### The Textures

Add this 2 lines to the beginning of the TekiTutorial::class, where we have declared the other variables.

var downFlapBirdsAndStones = mutableListOf<Texture>()
var upFlapBirdsAndStones = mutableListOf<Texture>()

###### create()

Still the MutableLists are empty, so now we gonna add for them the images. We have 10 different barriers, so we will add 10 different images to the MutableLists.

#### Step 2 – The draw

This step will be a little bit difficult, because we have to set 4 things, to have a left moving, random stones and flapping birds. So what do we have to define?

1. The position X
2. The position Y
3. Which barrier?
4. Velocity
5. If the barrier is out of the screen, redraw.
###### Declare the variables

Here we gonna declare all fo the variables, what we will gonna use later. Don’t be affraid, it it looks like to much, but all of them will have important part in the barriers-system. 😉

val numberOfBarriers = 10
val barrierX = mutableListOf<Float>()
val barrierY = mutableListOf<Float>()
val barrierYPositions = mutableListOf<Float>()
var randomBarrier = mutableListOf<Int>()
var constOfJumpCrawlDist = 0
var minBarrierOffset = 0f
var birdsFlapState = 0
var random = 0

numberOfBarriers – To set all of the state and the positions, we are going to use a for-loop. This loop will set every time when the render() method executes. For this we need to know how many barriers do we have.

barrierX and barrierY – The positions of the barriers on the screen or outside of it.

barrierYPositions – The barriers can get 4 Y positions on the screen. It depends on what is the barrier. If it is a bird, then this position can get 4 different value. If it is a stone, then it can be always on the ground. We need to keep an eye on that later.

randomBarrier – This will set the image of the barrier. We won’t have always the same sequence of the barriers. During the game it can be various.

constOfJumpCrawlDist – We have to take care the maximum distance of the jump and of the crawl. Otherwise our game will finish to early.

minBarrierOffset – We will have a plus offset between the barriers as well. It is needed to have some time to think about what the user should do, jump/stay/crawl.

birdsFlapState – The state of the birds will be changed every second.

random – It will be a random number between 0 and 2. We will use it to have additionally an offset between the barriers.

###### create()

Next we have to add values for the MutableLists.

We gonna start with the barrierYPositions. As we have talked about, it will contain 4 positions. So in this 4 positions can be the barriers. We will compare the Y positions to Teki, because they have to be front of her. 😉

The next 3 variables we have to clear first, because when we later on restart the game, we have to all of them empyt to have a clear state.

barrierX.clear()
barrierY.clear()
randomBarrier.clear()

After the clear we gonna upload them using a for-loop. This loop will iterate throw from 0 utnil the numbers of the barriers, so until 10 in our case.

Inside of this for-loop first we gonna generate a random number between 0 and 9. This will select the image for the barrier.

Then we will have an if-else-statement. Because we have to separet the index 0. It will appear on the screen immediatelly, when the user pushes the Play button. To the X positions of the other barriers we will add the constOfJumpCrawlDist, minBarrierOffset and the size multiplied by the random number.

The constOfJumpCrawlDist gonna be the maximum distance of the jump, so (size*8).toInt().

The minBarrierOffset will size*2. You can play with it.

Inside the for-loop we have to define one more if-else-statement to know which barrier is a bird and which is a stone. At the beginning we added the stones last to the list of the Textures. So if the rand number is between 6 and 9, then it has to be a stone.

``````for(i in 0 until numberOfBarriers)
{
val rand = Random().nextInt(10)
if(i == 0)
{
random = Random().nextInt(3)
}
else
{
random = Random().nextInt(3)
barrierX.add(barrierX.max()!! + constOfJumpCrawlDist + minBarrierOffset + random*size)
}

if(rand in 6..9)
{
}
else
{
}
}

for-loop in the create() method``````
###### render()

Similarly to the create() method we will have here also a for loop. One difference is that we won’t handle the index 0 separately. The second is the velocity, because during the game the barriers have to move to left. The velocity gonna be the same like the velocity of the background.

When the barrier is outside of the screen at the left side, then it must be reset. In other words the position X and Y, and the image must be reset.

``````for ( i in 0 until numberOfBarriers)
{
val rand = Random().nextInt(10)
if(barrierX[i] < -size*1.2f)
{
random = Random().nextInt(3)
barrierX[i] = barrierX.max()!! + constOfJumpCrawlDist + minBarrierOffset + size*random
randomBarrier[i] = rand

if(rand in 6..9)
{
barrierY[i] = barrierYPositions[0]
}
else
{
barrierY[i] = barrierYPositions[Random().nextInt(4)]
}
}
else
{
barrierX[i] = barrierX[i] - velocity
}

drawBarriers(i)
}

for-loop in the render() method``````

The third thing is that finally here we have to draw the barriers. We gonna do it in the drawBarriers() method. As the only argument it will take over the number of the barrier.

``````fun drawBarriers(numberOfBarrier: Int)
{
when(birdsFlapState)
{
0 -> {
batch!!.draw(
downFlapBirdsAndStones[randomBarrier[numberOfBarrier]],
barrierX[numberOfBarrier],
barrierY[numberOfBarrier],
size*1.2f,
size)
}
1 -> {
batch!!.draw(
upFlapBirdsAndStones[randomBarrier[numberOfBarrier]],
barrierX[numberOfBarrier],
barrierY[numberOfBarrier],
size*1.2f,
size)
}
}
}

for-loop in the render() method``````

As you see, we will have here a when-statement, which will check the number of the birdsFlapState

#### Step 3 – The birdsFlapState

In addition, as we have already defined, the birds flap during the game. In other words, the state of the birds will be changed every second. If the birdsFlapState is 0, then the wings are down, of 1, then they are up.

This few lines of code will be in the startTimer() method and there in the run() method, where we count the scores.

birdsFlapState = if (birdsFlapState == 0) {
1
} else {
0
}

#### TekiTutorial::class

This chapter had lots of information. If you are lost, then you can check yourself now.

``````import com.badlogic.gdx.ApplicationAdapter
import java.util.*

{
var batch: SpriteBatch? = null

var screenWidth = 0
var screenHeight = 0

var gameState = 0

// Background
var backgrounds = mutableListOf()
val numberOfBackgrounds = 3
var backgroundX = FloatArray(numberOfBackgrounds)

// Teki
var tekisLegStates = mutableListOf()
var tekiX = 0f
var tekiY = 0f
var tekisStates = 0

//Timer
var timer: Timer = Timer()

var numbersTextures = mutableListOf()

//Score
var score = 0
var nextLevel = 20
var scoreTextTexture: Texture? = null

//Level
var level = 0
var levelTextTexture: Texture? = null

//Up and Down Arrow
var upArrowTexture: Texture? = null
var downArrowTexture: Texture? = null

//Jump and crawl
var jumpDistance = 0f
var jumpPushed = false
var jumpVelocity = 0f
var crawlPushed = false

//Barriers
var downFlapBirdsAndStones = mutableListOf()
var upFlapBirdsAndStones = mutableListOf()
var numberOfBarriers = 10
val barrierX = mutableListOf()
val barrierY = mutableListOf()
val barrierYPositions = mutableListOf()
var randomBarrier = mutableListOf()
var constOfJumpCrawlDist = 0
var minBarrierOffset = 0f
var birdsFlapState = 0
var random = 0

var gravity = 0.0f

var velocity = 12
var distance = 0

var size: Float = 0f

override fun create()
{
batch = SpriteBatch()

screenWidth = Gdx.graphics.width
screenHeight = Gdx.graphics.height

size = (screenWidth*0.06).toFloat()
gravity = (size*0.01).toFloat()
constOfJumpCrawlDist = (size*8).toInt()
minBarrierOffset = size*2

//Background
for(i in 1..numberOfBackgrounds)
{
}

//Teki
tekiX = screenWidth*0.35f
tekiY = screenHeight*0.22f

for (i in 0 until numberOfBackgrounds)
{
backgroundX[i] = screenWidth.toFloat() * i
}

// Numbers
for(i in 0..9)
{
}

//Scoring
scoreTextTexture = Texture("score.png")

//Level
levelTextTexture = Texture("level.png")

//Up and Down Arrow
upArrowTexture = Texture("upArrow.png")
downArrowTexture = Texture("downArrow.png")

//Up and down flap Bird & Stones
barrierX.clear()
barrierY.clear()
randomBarrier.clear()
for(i in 0 until numberOfBarriers)
{
val rand = Random().nextInt(10)
if(i == 0)
{
random = Random().nextInt(3)
}
else
{
random = Random().nextInt(3)
barrierX.add(barrierX.max()!! + constOfJumpCrawlDist + minBarrierOffset + random*size)
}

if(rand in 6..9)
{
}
else
{
}
}

jumpVelocity = (size*0.29).toFloat()
}

override fun render()
{
batch!!.begin()

for(i in 0 until numberOfBackgrounds)
{
drawBackground(i)
}

distance += velocity

if (gameState == 0) // Main Menu screen
{
drawTeki(0)

if(Gdx.input.justTouched())
{
gameState = 1
startTimer()
}
}
else if (gameState == 1) //Running game screen
{
for(i in 0 until numberOfBackgrounds)
{
if (backgroundX[i] <= -screenWidth)
{
if (i == 0)
{
backgroundX[i] = backgroundX.max()!!.plus(screenWidth) - velocity
}
else
{
backgroundX[i] = backgroundX.max()!!.plus(screenWidth)
}
}
else
{
backgroundX[i] = backgroundX[i] - velocity
}
}

//Teki
if(distance % 20 == 0)
{
when(tekisStates)
{
0 -> tekisStates = 1
1 -> tekisStates = 2
2 -> tekisStates = 1
3 -> tekisStates = 0
}
}

if(jumpPushed)
{
handleJump()
}
else if(crawlPushed)
{
handleCrawl()
}

drawTeki(tekisStates)

touchUpAndDownArrow()

//Barriers
for ( i in 0 until numberOfBarriers)
{
val rand = Random().nextInt(10)
if(barrierX[i] < -size*1.2f)
{
random = Random().nextInt(3)
barrierX[i] = barrierX.max()!! + constOfJumpCrawlDist + minBarrierOffset + size*random
randomBarrier[i] = rand

if(rand in 6..9)
{
barrierY[i] = barrierYPositions[0]
}
else
{
barrierY[i] = barrierYPositions[Random().nextInt(4)]
}
}
else
{
barrierX[i] = barrierX[i] - velocity
}

drawBarriers(i)
}

drawUpArrow()
drawDownArrow()

scoring()
leveling()
}
else if (gameState == 2) //Game Over screen
{
stopTime()

scoring()
leveling()
}
else if (gameState == 3) //High Score screen
{

}

batch!!.end()
}

fun startTimer()
{
timer = Timer()

{
override fun run()
{
if(score == nextLevel)
{
level++
nextLevel += 20
velocity += 2
}

score++
Gdx.app.log("score", "\$score")
Gdx.app.log("level", "\$level")

birdsFlapState = if (birdsFlapState == 0) {
1
} else {
0
}
}
}, 0, 1000)
}
fun stopTime()
{
timer.cancel()
}

fun handleJump()
{
tekisStates = 3
jumpDistance += jumpVelocity
if(jumpDistance in 0f..(size*4))
{
jumpVelocity -= gravity
tekiY += jumpVelocity
}
else if(jumpDistance in (size*4 + 1)..(size*8))
{
jumpVelocity += gravity
tekiY += -jumpVelocity
if(jumpDistance >= (size*8).toInt())
{
jumpPushed = false
jumpDistance = 0f
tekiY = screenHeight*0.22f
}
}
else
{
if(jumpDistance >= (size*8))
{
jumpPushed = false
jumpDistance = 0f
tekiY = screenHeight*0.22f
}
}
}
fun handleCrawl()
{
tekisStates = 3
jumpDistance += jumpVelocity
if(jumpDistance >= size*9)
{
crawlPushed = false
jumpDistance = 0f
tekiY = screenHeight*0.22f
}
}

fun drawBackground(number: Int)
{
// Background
batch!!.draw(
backgrounds[number],
backgroundX[number],
0f,
screenWidth.toFloat(),
screenHeight.toFloat())
}
fun drawTeki(number: Int)
{
//Teki
batch!!.draw(
tekisLegStates[number],
tekiX,
tekiY,
size*1.2f,
size)
}
fun drawBarriers(numberOfBarrier: Int)
{
when(birdsFlapState)
{
0 -> {
batch!!.draw(
downFlapBirdsAndStones[randomBarrier[numberOfBarrier]],
barrierX[numberOfBarrier],
barrierY[numberOfBarrier],
size*1.2f,
size)
}
1 -> {
batch!!.draw(
upFlapBirdsAndStones[randomBarrier[numberOfBarrier]],
barrierX[numberOfBarrier],
barrierY[numberOfBarrier],
size*1.2f,
size)
}
}
}
fun scoring()
{
batch!!.draw(
scoreTextTexture,
size,
screenHeight - size*1.2f,
size*2,
size*0.8f)

val scoreDigits = mutableListOf()
var _score = score
if (_score == 0)
{
batch!!.draw(
numbersTextures[0],
size*3 + size*0.5f,
screenHeight - size*1.2f,
size*0.5f,
size*0.8f)
}
else
{
while (_score > 0)
{
_score /= 10
}
scoreDigits.reverse()

for (i in 0 until scoreDigits.count())
{
batch!!.draw(
numbersTextures[scoreDigits[i]],
size*3 + size*0.5f + (size*0.5f)*i,
screenHeight - size*1.2f,
size*0.5f,
size*0.8f)
}
}
}
fun leveling()
{
batch!!.draw(
levelTextTexture,
size,
screenHeight - size*1.2f - size,
size*2*0.93f, //*0.93 - to don't be stretched
size*0.8f)

val scoreDigits = mutableListOf()
var _level = level
if (_level == 0)
{
batch!!.draw(
numbersTextures[0],
size + size*2*0.93f + size*0.5f,
screenHeight - size*1.2f - size,
size*0.5f,
size*0.8f)
}
else
{
while (_level > 0)
{
_level /= 10
}
scoreDigits.reverse()

for (i in 0 until scoreDigits.count())
{
batch!!.draw(
numbersTextures[scoreDigits[i]],
size + size*2*0.93f + size*0.5f + (size*0.5f)*i,
screenHeight - size*1.2f - size,
size*0.5f,
size*0.8f)
}
}
}
fun drawUpArrow()
{
batch!!.draw(
upArrowTexture,
size,
size*3 + size*0.5f,
size*2,
size*2)
}
fun drawDownArrow()
{
batch!!.draw(
downArrowTexture,
size,
size,
size*2,
size*2)
}

fun touchUpAndDownArrow()
{
val upArrowCircle = Circle(
size*2,
screenHeight - (size*4 + size*0.5f),
size)
val downArrowCircle = Circle(
size*2,
screenHeight - (size*2),
size)
if(Gdx.input.justTouched())
{
//Touch of the upArrow
if(upArrowCircle.contains(Gdx.input.getX().toFloat(), Gdx.input.getY().toFloat()))
{
Gdx.app.log("justTouched", "upArrow")
if(!crawlPushed && !jumpPushed)
{
jumpPushed = true
}
}
//Touch of the downArrow
if(downArrowCircle.contains(Gdx.input.getX().toFloat(), Gdx.input.getY().toFloat()))
{
Gdx.app.log("justTouched", "downArrow")
if(!crawlPushed && !jumpPushed)
{
crawlPushed = true
tekiY -= (size*0.55).toFloat()
}
}
}
}
}

for-loop in the render() method``````

#### Questions

I hope the description was understandable and clear. But if you have still questions, then leave me comments below! 😉

Have a nice a day! 🙂

Click to rate this post!
[Total: 0 Average: 0]