Merhaba,


Bu yazı serisinde Android Studio, Socket.io ve Mysql ile online oyun yapımından bahsediyorum.


Videolu anlatım için buraya tıklayınız.
Serinin ilk yazısı için buraya tıklayınız.
Serinin ikinci yazısı için buraya tıklayınız.
Serinin üçüncü yazısı için buraya tıklayınız.
Serinin dördüncü yazısı için buraya tıklayınız.


Serinin bu beşinci ve son yazısında sıralama ekranını tasarlayıp dinamik olarak çalıştırıyoruz.


Android Studio projesi üzerinde;


activity_leaderboard.xml dosyasını açarak bir RecyclerView yerleştiriyoruz:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".ui.activity.LeaderboardActivity">


    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/rvLeaderboard"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_margin="10dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />


</androidx.constraintlayout.widget.ConstraintLayout>


list_item_leaderboard.xml dosyası oluşturarak sıralama ekranındaki her bir eleman (item) için şöyle bir tasarım yapıyoruz:

<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="10dp">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:padding="10dp">

        <TextView
            android:id="@+id/tvRank"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/text_rank"
            android:fontFamily="@font/arbutus"
            android:textSize="18sp"
            android:background="@drawable/bg_circle"
            android:gravity="center"
            android:textColor="@color/white"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintBottom_toBottomOf="parent"/>

        <TextView
            android:id="@+id/tvUserName"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/text_player"
            android:textSize="20sp"
            android:fontFamily="@font/arbutus_slab"
            android:textColor="@color/colorPrimary"
            android:layout_marginStart="10dp"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintStart_toEndOf="@id/tvRank"/>

        <TextView
            android:id="@+id/tvScore"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/text_score"
            android:textSize="20sp"
            android:fontFamily="@font/arbutus_slab"
            android:layout_marginEnd="10dp"
            android:textColor="@color/colorPrimary"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"/>

    </androidx.constraintlayout.widget.ConstraintLayout>

</androidx.cardview.widget.CardView>


Leader.kt dosyası açarak veri modelini oluşturuyoruz:

package com.yusufborucu.onlinemathgame.model

data class Leader (
    val rank: Int = 0,
    val username: String = "",
    val score: Int = 0
)


LeaderAdapter.kt dosyası açarak verileri her bir eleman için yaptığımız tasarımdaki öğelere yerleştiriyoruz:

package com.yusufborucu.onlinemathgame.ui.adapter

import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.yusufborucu.onlinemathgame.R
import com.yusufborucu.onlinemathgame.model.Leader
import kotlinx.android.synthetic.main.list_item_leaderboard.view.*

class LeaderAdapter(private val leaders: MutableList<Leader>): RecyclerView.Adapter<LeaderAdapter.LeaderViewHolder>()
{
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): LeaderViewHolder {
        val view = LayoutInflater.from(parent.context).inflate(R.layout.list_item_leaderboard, parent, false)
        return LeaderViewHolder(view)
    }

    override fun getItemCount(): Int {
        return leaders.size
    }

    override fun onBindViewHolder(holder: LeaderViewHolder, position: Int) {
        val leader = leaders[position]
        holder.itemView.tvRank.text = leader.rank.toString()
        holder.itemView.tvUserName.text = leader.username
        holder.itemView.tvScore.text = leader.score.toString()
    }

    class LeaderViewHolder(itemView: View): RecyclerView.ViewHolder(itemView)
}


LeaderboardActivity.kt dosyası açarak server tarafına leaderboard şeklinde bir emit yapıp gelen leaders emit'ini karşılıyoruz. Verileri ekranda bulunan listemize adapter aracılığıyla bağlıyoruz:

package com.yusufborucu.onlinemathgame.ui.activity

import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.recyclerview.widget.LinearLayoutManager
import com.github.nkzawa.socketio.client.Socket
import com.yusufborucu.onlinemathgame.App
import com.yusufborucu.onlinemathgame.R
import com.yusufborucu.onlinemathgame.model.Leader
import com.yusufborucu.onlinemathgame.ui.adapter.LeaderAdapter
import kotlinx.android.synthetic.main.activity_leaderboard.*
import org.json.JSONArray

class LeaderboardActivity : AppCompatActivity() {

    lateinit var socket: Socket

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_leaderboard)

        socket = App.socket

        socket.emit("leaderboard")

        socket
            .on("leaders") {
                runOnUiThread {
                    run {
                        val leaderList = mutableListOf<Leader>()
                        val leaders = JSONArray(it[0].toString())
                        for (i in 0 until leaders.length()) {
                            val item = leaders.getJSONObject(i)
                            leaderList.add(Leader(item.getInt("rank"), item.getString("username"), item.getInt("score")))
                        }
                        rvLeaderboard.layoutManager = LinearLayoutManager(applicationContext)
                        rvLeaderboard.adapter = LeaderAdapter(leaderList)
                    }
                }
            }
    }

    override fun onBackPressed() {
        super.onBackPressed()
        val intent = Intent(applicationContext, MainActivity::class.java)
        startActivity(intent)
        finish()
    }
}


Server tarafına gelen leaderboard emit'ini karşılayıp users tablosundaki skorları leaders emit'i olarak geriye döndürüyoruz:

socket.on('leaderboard', () => {
        connection.query("SELECT username, score FROM users ORDER BY score DESC", (error, users) => {
            let leaders = [];
            for (var i = 0; i < users.length; i++) {
                let obj = {
                    rank: i + 1,
                    username: users[i].username,
                    score: users[i].score
                }
                leaders.push(obj);
            }
            io.to(socket.id).emit('leaders', leaders);
        });
    });


Yazı serisi boyunca oyun ile alakalı bir resim paylaşmadım. Oyunun görsel haline ve işleyişine videolu anlatım üzerinden göz atabilirsiniz.


Umarım yararlı olmuştur.


İyi çalışmalar.