Xây dựng ứng dụng chụp hình:
1. AndroidManifest.xml:

<uses-feature android:name="android.hardware.camera2"/>
<
uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<
uses-permission android:name="android.permission.RECORD_AUDIO"/>

2. activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:context="camerademo.hkh.com.camera_demo.MainActivity"
    android:orientation="vertical">

    <LinearLayout
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="89dp">
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Take a picture"
            android:id="@+id/btnCapturePicture"
            android:layout_gravity="center_horizontal" />
    </LinearLayout>

    <LinearLayout
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="1">
        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/imgPreview"
            android:visibility="gone"/>
    </LinearLayout>
</LinearLayout>

3. MainActivity.java:
package camerademo.hkh.com.camera_demo;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;import android.os.Environment;import android.provider.MediaStore;import android.support.v7.app.AppCompatActivity;import android.util.Log;import android.view.View;import android.widget.Button;import android.widget.ImageView;import android.widget.Toast;import java.io.File;import java.text.SimpleDateFormat;import java.util.Date;import java.util.Locale;

public class MainActivity extends AppCompatActivity implements View.OnClickListener{
    private static final int CAMERA_CAPTURE_IMAGE_REQUEST_CODE = 100;
    public static final int MEDIA_TYPE_IMAGE = 1;
    private static final String IMAGE_DIRECTORY_NAME = "CameraImage";
    private Uri fileUri; //store image
    private ImageView imgPreview;
    private Button btnCapturePicture;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        imgPreview = (ImageView) findViewById(R.id.imgPreview);
        btnCapturePicture = (Button) findViewById(R.id.btnCapturePicture);
        btnCapturePicture.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.btnCapturePicture:
                CaptureImage();
                break;
        }
    }

    private void CaptureImage() {
        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        fileUri = getOutputMediaFileUri(MEDIA_TYPE_IMAGE);
        intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);
        startActivityForResult(intent, CAMERA_CAPTURE_IMAGE_REQUEST_CODE);
    }

    public Uri getOutputMediaFileUri(int type) {
        return Uri.fromFile(getOutputMediaFile(type));
    }

    public File getOutputMediaFile (int type) {
        File mediaStorageDir = new File( Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
                                         IMAGE_DIRECTORY_NAME);
        if (!mediaStorageDir.exists()) {
            if (!mediaStorageDir.mkdir()) {
                Log.i(IMAGE_DIRECTORY_NAME, "create failed !!!!");
                return null;
            }
        }

        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(new Date());
        File mediaFile;

        if (type == MEDIA_TYPE_IMAGE) {
            mediaFile = new File(mediaStorageDir.getPath() + File.separator + "IMG_" + timeStamp + ".jpg");
        } else {
            return null;
        }
        return mediaFile;
    }

    @Override

    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == CAMERA_CAPTURE_IMAGE_REQUEST_CODE) {
            if (resultCode == RESULT_OK) {
                previewCapturedImage();
            } else  if (resultCode == RESULT_CANCELED) {
                Toast.makeText(getApplicationContext(), "User cancelled image capture", Toast.LENGTH_SHORT).show();
            } else {
                Toast.makeText(getApplicationContext(), "Failed to capture image", Toast.LENGTH_SHORT).show();
            }
        }
    }

    private void previewCapturedImage() {
        try {
            imgPreview.setVisibility(View.VISIBLE);
            BitmapFactory.Options options = new BitmapFactory.Options();
            options.inSampleSize = 1;
            final Bitmap bitmap = BitmapFactory.decodeFile(fileUri.getPath(), options);
            imgPreview.setImageBitmap(bitmap);
        } catch (NullPointerException e) {
            e.printStackTrace();
            Toast.makeText(getApplicationContext(), "Error ---------", Toast.LENGTH_SHORT).show();
        }
    }

}

Download sourcode demo link:


test
compile 'org.jbundle.util.osgi.wrapped:org.jbundle.util.osgi.wrapped.org.apache.http.client:4.1.2'
Bước 1. Tạo đối tượng Quad:
- Vào GameObject --> 3D Object --> chọn Quad: lúc này tạo ra được đối tượng Quad - đối tượng này sau này chính là background chuyển động lặp lại.

Bước 2. Kéo thả vào một hình background cần làm lặp lại, nhớ sét sang dạng Texture, cụ thể sét như sau:
   . Texture type: Texture
   . Wrap Mode: Repeat
   . Filter Mode: Bilinear
   . Max size: 2048

Bước 3: click vào background texute và kéo thả vào đối tượng Quad ở trên

Bước 4. Tạo mã script chẳng hạn đặt tên: ScrollBackground.cs, viết code:
using UnityEngine;
using System.Collections;

public class ScrollBackground : MonoBehaviour {
public float _Speed = 3f;
public Renderer rend;
// Use this for initialization

void Start() {
rend = GetComponent<Renderer>();
}
// Update is called once per frame
void Update () {
rend.material.mainTextureOffset = new Vector2 (Time.time * _Speed, 0f);
}
}

Bước 5: Gắn script (file ScrollBackground.cs) vào đối tượng Quad ở trên. Bấm và chạy thử kết quả như mong đợi.



Hướng dẫn clone game FlappyBird
Mô tả các thành phần trong game: ...

Bước 1: Download resource
Trong thư mục Asset lần lượt tạo các thư mục: right click vào Asset --> create --> chọn Folder
- Resources: lưu tài nguyên hình ảnh
- Scripts: lưu mã nguồn
- Animations: lưu các sprite động
- Scenes:
- Prefabs:

Bước 2: Tạo sprite
Kéo tệp tin *.psd vào thư mục Resources --> click chọn hình
Ở mục Inspector:
 - TextureType: chọn Sprite(2D and UI)
 - Sprite Mode: chọn Multiple
--> sau đó chọn Sprite Editor -->
 - Bấm vào mục Slice --> chỉnh sửa lại các sprite cho như ý sao đó nhớ chọn Apply trên cửa sổ Sprite Editor. Như vậy đã tạo ra được các sprite

Bước 3: Tạo hình nền BackGround - Viết Script di chuyển BG
- Tạo GameObject: background gồm 2 thành phần sky (set layer = 0) và đất (set layer = 2). Số layer lớn ở ngoài cùng.
- Tạo Prefabs: cho background --> Các đối tượng tạo ra từ Prefabs thì chỉ cần thay đổi một thuộc tính nào đó trong Prefabs thì tất cả các đối tượng khác cũng thay đổi theo.

  + Thêm tốc độ di chuyển backgroud (lưu ý đặt biến public float SPEED), chỉnh từ giao diện trên prefabs background.
- Viết Scripte cho background: để bg di chuyển
void Update () {
transform.Translate(Vector3.left * SPEED * Time.deltaTime);
}

Bước 4: Tạo BGLooper - để các bg khác đụng vào BGLooper thì sẽ quay lại phía sau
- add Component Box Collider 2D cho.
- add Component Rigidbody 2D, lưu ý: để thuộc tính: Gravity Scale = 0; --> ko có trọng lượng
- Thêm mã nguồn đụng cái BGLooper thì sẽ quay lại
void OnTriggerEnter2D(Collider2D collider) {
if (collider.name == "BGLooper") {
Vector3 pos = this.transform.position;
float widthOfBGObject =  ((BoxCollider2D) collider).size.x;
pos.x += widthOfBGObject * numBG;
this.transform.position = pos;
}
}

Bước 5: Tạo các ống nước
- Tạo GameObject Pipe
- Add 2 cái Box Collider 2D cho ống phía trên và ống phía dưới, set vùng va chạm
- Add component Rigidbody 2D, lưu ý: để thuộc tính: Gravity Scale = 0; --> ko có trọng lượng
- Add script: Pipe
- Tạo Prefads: cho ống nước --> Mục đích: ....
- Viết mã nguồn để ống nước di chuyển
        void Update () {
transform.Translate(Vector3.left * SPEED * Time.deltaTime);
}
- Code ống nước di chuyển gặp BGLooper thì set lại vị trí phía sau:
void OnTriggerEnter2D(Collider2D collider) {
if (collider.name == "BGLooper") {
Vector3 pos = this.transform.position;
pos.x += distancePipe * numBG;
pos.y = Random.Range(MinY, MaxY);
transform.position = pos;
}
}

Bước 6: Tạo animation cho chú chim
- Chọn 3 sprite chim sau đó kéo thả vào vùng Hierachy. Tạo đối tượng GameObject Bird, kéo clony_bird_sprite_12 thả vào Bird. --> chúng ta có gameobject Bird.
- Viết mã nguồn cho chú chim chuyển động
public float jumpVelocity = 3.0f;
float g = -9.8f;

void Update () {
//x = x0 + v0 * t + a * t * t /2
transform.position += Vector3.up * (jumpVelocity * Time.deltaTime + g * Time.deltaTime * Time.deltaTime / 2);
//vt = v0 + a * t
jumpVelocity += g * Time.deltaTime;

if (Input.GetMouseButtonDown(0)) {
jumpVelocity = 2.5f;
}
}
- Xét va chạm giữa chú chim và ống nước:
 + Đặt tag cho các ống nước là: Pipe  --> để sau này dễ tìm các đối tượng là loại ống nước
void OnTriggerEnter2D(Collider2D collider) {
if ( collider.gameObject.tag == "Pipe")
{
jumpVelocity = 0;
}
}

---Hướng dẫn cách debug trên Unity.