


















Study with the several resources on Docsity
Earn points by helping other students or get them with a premium plan
Prepare for your exams
Study with the several resources on Docsity
Earn points to download
Earn points by helping other students or get them with a premium plan
Community
Ask the community for help and clear up your study doubts
Discover the best universities in your country according to Docsity users
Free resources
Download our free guides on studying techniques, anxiety management strategies, and thesis advice from Docsity tutors
A detailed guide to developing a classic snake game for android using android studio. It covers the design, implementation, and testing phases of the project, including the creation of the game's interface, the implementation of game logic, and the testing of the game's functionality. Suitable for students learning android development and provides a practical example of game development principles.
Typology: Assignments
1 / 26
This page cannot be seen from the preview
Don't miss anything!
IV. Giải pháp thực hiện
V. Thiết kế giao diện
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
android:layout_height="match_parent" android:orientation="vertical" android:id="@+id/main" android:background="#6D9558" android:gravity="center">
android:textSize="48sp" />
public class SnakeSegments { private int positionX, positionY; public SnakeSegments(int positionX, int positionY) { this.positionX = positionX; this.positionY = positionY; } public int getPositionX() { return positionX; } public void setPositionX(int positionX) { this.positionX = positionX; } public int getPositionY() { return positionY; } public void setPositionY(int positionY) { this.positionY = positionY; } }
package com.example.snake01; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.util.AttributeSet; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.widget.Toast; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.Random; public class GameView extends SurfaceView implements Runnable { private Thread thread; private boolean isPlaying = true; private Paint paint; private SurfaceHolder surfaceHolder;
private ArrayList
if (newX == apple.getPositionX() && newY == apple.getPositionY()) { generateApple(); score++; if (score > highScore) { highScore = score; saveHighScore(); // Lưu điểm cao mới vào file } } else { // Remove the last segment if not eating snake.remove(snake.size() - 1 ); } } private void draw() { if (surfaceHolder.getSurface().isValid()) { Canvas canvas = surfaceHolder.lockCanvas(); canvas.drawColor(Color. BLACK ); //snake paint.setColor(Color. GREEN ); for (SnakeSegments segment : snake) { canvas.drawRect(segment.getPositionX() * unitSize, segment.getPositionY() * unitSize, (segment.getPositionX() + 1 ) * unitSize, (segment.getPositionY() + 1 ) * unitSize, paint); } //apple paint.setColor(Color. RED ); canvas.drawCircle( (apple.getPositionX() + 0.5f) * unitSize, (apple.getPositionY() + 0.5f) * unitSize, unitSize / 2 , paint ); //text: score, high score paint.setColor(Color. WHITE ); paint.setTextSize( 42 ); canvas.drawText("Score: " + score, 20 , 40 , paint); canvas.drawText("High Score: " + highScore, 20 , 80 , paint); surfaceHolder.unlockCanvasAndPost(canvas); } } private void sleep() { try { Thread. sleep (speed); // Sleep duration based on speed } catch (InterruptedException e) { e.printStackTrace(); } } public void resume() { isPlaying = true; thread = new Thread(this); thread.start(); } public void pause() { try { isPlaying = false;
thread.join(); } catch (InterruptedException e) { e.printStackTrace(); } } // Button to control snake use public void setDirection(int newDirection) { // Prevent the snake from turning 180 degrees if ((currentDirection == 1 && newDirection == 3 ) || // Up to Down (currentDirection == 3 && newDirection == 1 ) || // Down to Up (currentDirection == 2 && newDirection == 4 ) || // Right to Left (currentDirection == 4 && newDirection == 2 )) { // Left to Right return; } currentDirection = newDirection; } private void showGameOver() { post(new Runnable() { @Override public void run() { Toast. makeText (getContext(), "Game Over! Score: " + score + " | High Score: " + highScore, Toast. LENGTH_LONG ).show(); ((PlayActivity) getContext()).showGameOverDialog(score); } }); } public void resetGame() { snake.clear(); // Initialize the snake with 3 segments snake.add(new SnakeSegments( 7 , 12 )); // Head snake.add(new SnakeSegments( 6 , 12 )); // Body segment 1 snake.add(new SnakeSegments( 5 , 12 )); // Body segment 2 generateApple(); score = 0 ; currentDirection = 2 ; // Reset to initial direction highScore = loadHighScore(); } public void saveHighScore() { try { FileOutputStream fos = getContext().openFileOutput(highScoreFileName, Context. MODE_PRIVATE ); fos.write(String. valueOf (highScore).getBytes()); fos.close(); } catch (IOException e) { e.printStackTrace(); } } private int loadHighScore() { try { FileInputStream fis = getContext().openFileInput(highScoreFileName); byte[] data = new byte[fis.available()];
ImageButton btnPause = findViewById(R.id.btnPause); btnUp.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { gameView.setDirection( 1 ); } }); btnDown.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { gameView.setDirection( 3 ); } }); btnLeft.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { gameView.setDirection( 4 ); } }); btnRight.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { gameView.setDirection( 2 ); } }); btnPause.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { gameView.pause(); showPauseDialog(); } }); } @Override protected void onResume() { super.onResume(); gameView.resume(); } @Override protected void onPause() { super.onPause(); gameView.pause(); } public void showPauseDialog() { new AlertDialog.Builder(this) .setTitle("Game Paused") .setMessage("Would you like to resume?") .setPositiveButton("Resume", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { // đếm ngược 3 giây -> resume() TextView tvCountDown = findViewById(R.id.tvCountDown); countDownAndResume(tvCountDown);
.setNeutralButton("Restart", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialogInterface, int i) { // restart gameView.resetGame(); gameView.resume(); } }) .setNegativeButton("Main Menu", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { // Exit to main menu Intent intent = new Intent(PlayActivity.this, MainActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(intent); finish(); } }) .setIcon(android.R.drawable. ic_media_pause ) .setCancelable(false) .show(); } private void countDownAndResume(TextView tvCountDown) { tvCountDown.setVisibility(View. VISIBLE ); new CountDownTimer( 3000 , 1000 ) { // 3 giây (3000ms), đếm mỗi 1 giây (1000ms) @Override public void onTick(long millisUntilFinished) { tvCountDown.setText(String. valueOf ((int) millisUntilFinished / 1000 )); } @Override public void onFinish() { gameView.resume(); tvCountDown.setVisibility(View.GONE); } }.start(); } public void showGameOverDialog(int score) { int highScore = gameView.getHighScore(); // Lấy điểm cao từ GameView new AlertDialog.Builder(this) .setTitle("Game Over") .setMessage("Score: " + score + "\nHigh Score: " + highScore) .setPositiveButton("Replay", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { gameView.resetGame(); gameView.resume();
setSpeed("slow"); } }); btnMedium.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { setSpeed("medium"); } }); btnFast.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { setSpeed("fast"); } }); // Minh họa tốc độ rắn ImageView previewSlow = findViewById(R.id. previewSlow ); ImageView previewMedium = findViewById(R.id. previewMedium ); ImageView previewFast = findViewById(R.id. previewFast ); setupPreviewAnimation(previewSlow, 300 ); // Slow speed setupPreviewAnimation(previewMedium, 200 ); // Medium speed setupPreviewAnimation(previewFast, 100 ); // Fast speed } private void setupPreviewAnimation(final ImageView preview, final int duration) { final int distance = 300 ; //px final Runnable[] moveRight = new Runnable[ 1 ]; final Runnable[] moveLeft = new Runnable[ 1 ]; moveRight[ 0 ] = new Runnable() { @Override public void run() { preview.animate().translationXBy(distance).setDuration(duration).wi thEndAction(moveLeft[ 0 ]); } }; moveLeft[ 0 ] = new Runnable() { @Override public void run() { preview.animate().translationXBy(- distance).setDuration(duration).withEndAction(moveRight[ 0 ]); } }; // Bắt đầu chuyển động handler.post(moveRight[ 0 ]); } private void setSpeed(String speed) { // Lưu lại tốc độ đã chọn SharedPreferences.Editor editor = sharedPreferences.edit(); editor.putString("speed", speed); editor.apply(); // Trở về màn hình chính Intent intent = new Intent(); intent.putExtra("speed", speed); setResult( RESULT_OK , intent);
finish(); } }
package com.example.snake01; import android.app.AlertDialog; import android.content.DialogInterface; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.content.SharedPreferences; import androidx.appcompat.app.AppCompatActivity; import java.io.FileInputStream; import java.io.IOException; public class MainActivity extends AppCompatActivity { private static final int SPEED_REQUEST_CODE = 1 ; private SharedPreferences sharedPreferences; private String selectedSpeed = "medium"; // Default speed @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout. activity_main ); sharedPreferences = getSharedPreferences("game_prefs", MODE_PRIVATE ); selectedSpeed = sharedPreferences.getString("speed", "medium"); // Default speed Button playButton = findViewById(R.id. Play ); playButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(MainActivity.this, PlayActivity.class); intent.putExtra("speed", selectedSpeed); startActivity(intent); } }); Button speedButton = findViewById(R.id. Speed ); speedButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) {