dnd Dice Roller Android App tutorial with source code
dnd Dice Roller Android App tutorial with source code

A dnd dice roller is Tutorial using android-studio. who want to learn and gain more knowledge in developing an android application.

This tutorial is not be a fancy 3D dice roller but it’ll be a simple Dice that roller with some animation effect and generate a random number from 1 – 6 and show similar image of dice roller to the user.

Demo of how the final Dice Roller dnd android app looks

android dice roller app tutorial
android dice roller app tutorial ( gif )

All the image given below are free to use .

one
 

dice vector images Download from tekeye.uk

 

The sound of a dice roll is stored in shake_dice.mp3. It is by Mike Koenig and is from SoundBilble.com.

dnd dice roller android studio tutorial mini project.

let’s start with creating a new project in android-studio

File > New > New Project

Give a proper name to project ( Dice Roller ) , Select a project storage destination , select minimum API : 22 ,Android 5.1 (Lollipop), all set android project will be get ready in several seconds.

Add the dice resources (from above) to the project by copying them to the res folder in android – studio.

Dice Roller app resources android studio
Dice Roller app resources android studio

Optional Changes

To set a icon from this dice roller app project go to AndroidManifest.xml file

android:icon="@drawable/dice3d" and android:roundIcon="@mipmap/dice3d_rounded".

Designing a UI Layout spin the dice roller

Designing a UI Layout spin the dice roller
main_activity.xml Layout Design

main_activity.xml

Copy the below code in main_activity.xml file

<?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=".MainActivity">


    <ImageView
        android:id="@+id/imageView"
        android:layout_width="131dp"
        android:layout_height="121dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:srcCompat="@drawable/dice3d160" />

    <TextView
        android:id="@+id/dice_no"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Dice Number : ? Spin it "
        android:textSize="25sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.498"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/imageView"
        app:layout_constraintVertical_bias="0.157" />

    <TextView
        android:id="@+id/textView2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textColor="#0184FC"
        android:textSize="25sp"
        android:textStyle="italic|bold"
        android:text="Click on the Dice to Spin it"
        app:layout_constraintBottom_toTopOf="@+id/imageView"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

Android Dice Roller Source Code

ActivityMain.java

package protocoderspoint.com.androiddicerollertutorial;

import android.media.AudioAttributes;
import android.media.SoundPool;
import android.os.Build;
import android.os.Handler;
import android.os.Message;
import android.os.Bundle;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.LinearInterpolator;
import android.view.animation.RotateAnimation;
import android.widget.ImageView;
import android.widget.TextView;

import androidx.appcompat.app.AppCompatActivity;

import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;

import protocoderspoint.PreLollipopSoundPool;

public class MainActivity extends AppCompatActivity {
    ImageView dice_picture;     //reference to dice picture
    Random rng=new Random();    //generate random numbers
    SoundPool dice_sound;       //For dice sound playing
    int sound_id;               //Used to control sound stream return by SoundPool
    Handler handler;            //Post message to start roll
    Timer timer=new Timer();    //Used to implement feedback to user
    boolean rolling=false;      //Is die rolling?
    RotateAnimation rotate;
    int soundplay;
    TextView dice_no;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //Our function to initialise sound playing

        dice_no=(TextView)findViewById(R.id.dice_no);
        InitSound();
        //Get a reference to image widget
        dice_picture = (ImageView) findViewById(R.id.imageView);
        dice_picture.setOnClickListener(new HandleClick());
         rotate = new RotateAnimation(0, 360, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
        rotate.setDuration(3000);
        rotate.setInterpolator(new LinearInterpolator());

        //link handler to callback
        handler=new Handler(callback);
    }

    //User pressed dice, lets start
    private class HandleClick implements View.OnClickListener {
        public void onClick(View arg0) {
            if (!rolling) {
                rolling = true;
                //Show rolling image
                dice_picture.setImageResource(R.drawable.dice3d160);
                //Start rolling sound
              soundplay=  dice_sound.play(sound_id, 1.0f, 1.0f, 0, 0, 1.0f);
                //Pause to allow image to update
                dice_picture.startAnimation(rotate);
                timer.schedule(new Roll(), 3000);
            }
        }
    }

    //New code to initialise sound playback
    void InitSound() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            //Use the newer SoundPool.Builder
            //Set the audio attributes, SONIFICATION is for interaction events
            //uses builder pattern
            AudioAttributes aa = new AudioAttributes.Builder()
                    .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
                    .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
                    .build();

            //default max streams is 1
            //also uses builder pattern
            dice_sound= new SoundPool.Builder().setAudioAttributes(aa).build();

        } else {
            //Running on device earlier than Lollipop
            //Use the older SoundPool constructor
            dice_sound= PreLollipopSoundPool.NewSoundPool();
        }
        //Load the dice sound
        sound_id=dice_sound.load(this,R.raw.shake_dice,1);
    }

    //When pause completed message sent to callback
    class Roll extends TimerTask {
        public void run() {
            handler.sendEmptyMessage(0);
        }
    }

    //Receives message from timer to start dice roll
    Handler.Callback callback = new Handler.Callback() {
        public boolean handleMessage(Message msg) {
            //Get roll result
            //Remember nextInt returns 0 to 5 for argument of 6
            //hence + 1
            switch(rng.nextInt(6)+1) {
                case 1:
                    rotate.cancel();
                    dice_no.setText("Dice Number : 1");
                    dice_picture.setImageResource(R.drawable.one);
                    break;
                case 2:
                    rotate.cancel();
                    dice_no.setText("Dice Number : 2");
                    dice_picture.setImageResource(R.drawable.two);
                    break;
                case 3:
                    rotate.cancel();
                    dice_no.setText("Dice Number : 3");
                    dice_picture.setImageResource(R.drawable.three);
                    break;
                case 4:
                    rotate.cancel();
                    dice_no.setText("Dice Number : 4");
                    dice_picture.setImageResource(R.drawable.four);
                    break;
                case 5:
                    rotate.cancel();
                    dice_no.setText("Dice Number : 5");
                    dice_picture.setImageResource(R.drawable.five);
                    break;
                case 6:
                    rotate.cancel();
                    dice_no.setText("Dice Number : 6");
                    dice_picture.setImageResource(R.drawable.six);
                    break;
                default:
            }
            rolling=false;  //user can press again
            return true;
        }
    };

    //Clean up
    protected void onPause() {
        super.onPause();
        dice_sound.pause(sound_id);
    }
    protected void onDestroy() {
        super.onDestroy();
        timer.cancel();
    }
}

To support APIs pre Lollipop add a new class called PreLollipopSoundPool,java

package protocoderspoint;

import android.media.AudioManager;
import android.media.SoundPool;

/**
 * Created a pre Lollipop SoundPool
 */
public final class PreLollipopSoundPool {
    @SuppressWarnings("deprecation")
    public static SoundPool NewSoundPool() {
        return new SoundPool(1, AudioManager.STREAM_MUSIC,0);
    }
}

Explanation of the above ActivityMain.java Code

Random number

Random java – user to generate a random number from 1 to 6

Random rng=new Random();

//Get roll result
//Remember nextInt returns 0 to 5 for argument of 6
//hence + 1
rng.nextInt(6)+1

Rotate a imageView in android-studio

RotateAnimation rotate = new RotateAnimation(0, 360, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);

Set Duration for the rotator in milli-sec like (1 sec = 1000milli sec )

rotate.setDuration(3000);
rotate.setInterpolator(new LinearInterpolator());

Learn more about setInterpolator ( new LinearInterpolator())

Soundpool

In Android-studio Java Soundpool is used to play a sound like in our project we have used a dice roller sound effect to feel like a real dice is spinning. Code below

  SoundPool dice_sound;       //For dice sound playing
 
int sound_id;               //Used to control sound stream return by SoundPool

New code to initialise sound playback

 //New code to initialise sound playback
    void InitSound() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            //Use the newer SoundPool.Builder
            //Set the audio attributes, SONIFICATION is for interaction events
            //uses builder pattern
            AudioAttributes aa = new AudioAttributes.Builder()
                    .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
                    .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
                    .build();

            //default max streams is 1
            //also uses builder pattern
            dice_sound= new SoundPool.Builder().setAudioAttributes(aa).build();

        } else {
            //Running on device earlier than Lollipop
            //Use the older SoundPool constructor
            dice_sound= PreLollipopSoundPool.NewSoundPool();
        }
        //Load the dice sound
        sound_id=dice_sound.load(this,R.raw.shake_dice,1);
    }

As java codes runs within a fraction of seconds, it will be hard to view the image is getting spinned or an real animation effect, i have made use of Timer method with will help programmer to show dice rolling effect.

Timer timer=new Timer();    //Used to implement Time to spin

Timer is used to provide a delay in roll.

timer.schedule(new Roll(), 3000);

above snippet code timer is set to 3 sec’s where the viewer will be above to see the animation effect for 3 sec.

Download source code Dice Roller android App

Downlaod from drive

LEAVE A REPLY

Please enter your comment!
Please enter your name here