No Coding! Just Copy-Paste করেই তৈরি করো Android Snake Game
📌 Download this resources file.
🖥️ XML Code in activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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:background="#121212"
tools:context=".MainActivity" >
<!-- Score Display -->
<TextView
android:id="@+id/scoreTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:text="Score: 0"
android:textSize="24sp"
android:textColor="#4CAF50"
android:padding="16dp"
android:textStyle="bold"
android:fontFamily="sans-serif-medium" />
<!-- Game Over Text -->
<TextView
android:id="@+id/gameOverTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="Game Over!\nTap RESTART to play again"
android:textSize="24sp"
android:textColor="#FF5252"
android:textStyle="bold"
android:visibility="invisible"
android:gravity="center"
android:fontFamily="sans-serif-medium"
android:background="#CC000000"
android:padding="20dp"
android:elevation="8dp" />
<!-- Game View -->
<FrameLayout
android:id="@+id/gameContainer"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="@+id/controlsLayout"
android:layout_below="@+id/scoreTextView"
android:background="#1E1E1E" />
<!-- Control Buttons - Modern Joystick Style -->
<LinearLayout
android:id="@+id/controlsLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:orientation="vertical"
android:padding="16dp"
android:background="#1A1A1A">
<!-- Up Button -->
<ImageButton
android:id="@+id/upButton"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_gravity="center_horizontal"
android:background="@drawable/button_up_selector"
android:scaleType="center"
android:layout_marginBottom="8dp" />
<!-- Middle Row: Left, Right Buttons -->
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:orientation="horizontal">
<ImageButton
android:id="@+id/leftButton"
android:layout_width="60dp"
android:layout_height="60dp"
android:background="@drawable/button_left_selector"
android:scaleType="center"
android:layout_marginEnd="100dp" />
<ImageButton
android:id="@+id/rightButton"
android:layout_width="60dp"
android:layout_height="60dp"
android:background="@drawable/button_right_selector"
android:scaleType="center" />
</LinearLayout>
<!-- Down Button -->
<ImageButton
android:id="@+id/downButton"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_gravity="center_horizontal"
android:background="@drawable/button_down_selector"
android:scaleType="center"
android:layout_marginTop="8dp" />
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardCornerRadius="10dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:weightSum="2">
<!-- Restart Button -->
<Button
android:id="@+id/restartButton"
android:layout_width="150dp"
android:layout_height="48dp"
android:layout_weight="1"
android:text="RESTART"
android:shadowColor="#D9C514"
android:background="@drawable/button_restart_selector"
android:textColor="#FFFFFF"
android:textStyle="bold"
android:fontFamily="sans-serif-medium"
android:layout_margin="5dp" />
<!-- Speed Control Dropdown -->
<LinearLayout
android:id="@+id/speedControlLayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="horizontal"
android:padding="16dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Speed: "
android:textColor="#000000"
android:textStyle="bold"
android:textSize="16sp"
android:layout_gravity="center_vertical"
android:layout_marginEnd="8dp" />
<Spinner
android:id="@+id/speedSpinner"
android:layout_width="100dp"
android:layout_height="30dp"
android:background="@drawable/spinner_background"
android:popupBackground="#E7E9E9"
android:spinnerMode="dropdown" />
</LinearLayout>
</LinearLayout>
</androidx.cardview.widget.CardView>
</LinearLayout>
</RelativeLayout >
📌 Paste this code in MainActivity.java
package com.nahid.snakegame;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.ImageButton;
import android.widget.Spinner;
import android.widget.TextView;
import java.util.Arrays;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private SnakeView snakeView;
private TextView scoreTextView;
private TextView gameOverTextView;
private ImageButton upButton, downButton, leftButton, rightButton;
private Button restartButton;
private FrameLayout gameContainer;
private Spinner speedSpinner;
private int currentSpeed = 150; // Default medium speed
// Speed options in milliseconds (higher value = slower speed)
private final List speedValues = Arrays.asList(300, 150, 75);
private final List speedLabels = Arrays.asList("Easy", "Medium", "Hard");
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Initialize views
scoreTextView = findViewById(R.id.scoreTextView);
gameOverTextView = findViewById(R.id.gameOverTextView);
gameContainer = findViewById(R.id.gameContainer);
speedSpinner = findViewById(R.id.speedSpinner);
// Create SnakeView dynamically and add to container
snakeView = new SnakeView(this, null);
gameContainer.addView(snakeView);
// Initialize control buttons
upButton = findViewById(R.id.upButton);
downButton = findViewById(R.id.downButton);
leftButton = findViewById(R.id.leftButton);
rightButton = findViewById(R.id.rightButton);
restartButton = findViewById(R.id.restartButton);
// Set up speed spinner
setupSpeedSpinner();
// Set up button listeners with touch feedback
setupButton(upButton, Snake.Direction.UP);
setupButton(downButton, Snake.Direction.DOWN);
setupButton(leftButton, Snake.Direction.LEFT);
setupButton(rightButton, Snake.Direction.RIGHT);
restartButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
restartGame();
}
});
}
private void setupSpeedSpinner() {
// Create adapter for spinner
ArrayAdapter adapter = new ArrayAdapter<>(
this,
android.R.layout.simple_spinner_item,
speedLabels
);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
speedSpinner.setAdapter(adapter);
// Set default selection to Medium
speedSpinner.setSelection(1);
// Set spinner item selection listener
speedSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView parent, View view, int position, long id) {
currentSpeed = speedValues.get(position);
if (snakeView != null) {
snakeView.setGameSpeed(currentSpeed);
}
// Show speed change feedback
String speedName = speedLabels.get(position);
showSpeedChangeMessage(speedName + " speed selected");
}
@Override
public void onNothingSelected(AdapterView parent) {
// Do nothing
}
});
}
private void showSpeedChangeMessage(String message) {
// You can implement a toast or a small text display here
// For now, we'll just log it
System.out.println(message);
// Optional: Show a small toast message
// Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
}
private void setupButton(ImageButton button, final Snake.Direction direction) {
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (snakeView != null && !snakeView.isGameOver()) {
snakeView.setDirection(direction);
// Add button press animation
v.animate().scaleX(0.9f).scaleY(0.9f).setDuration(100)
.withEndAction(new Runnable() {
@Override
public void run() {
v.animate().scaleX(1f).scaleY(1f).setDuration(100);
}
});
}
}
});
}
public void updateScore(int score) {
runOnUiThread(new Runnable() {
@Override
public void run() {
scoreTextView.setText("Score: " + score);
// Add score update animation
scoreTextView.animate().scaleX(1.2f).scaleY(1.2f).setDuration(200)
.withEndAction(new Runnable() {
@Override
public void run() {
scoreTextView.animate().scaleX(1f).scaleY(1f).setDuration(200);
}
});
}
});
}
public void showGameOver() {
runOnUiThread(new Runnable() {
@Override
public void run() {
gameOverTextView.setVisibility(View.VISIBLE);
// Add game over animation
gameOverTextView.setScaleX(0.8f);
gameOverTextView.setScaleY(0.8f);
gameOverTextView.animate()
.scaleX(1f)
.scaleY(1f)
.setDuration(500)
.start();
}
});
}
private void restartGame() {
gameOverTextView.setVisibility(View.INVISIBLE);
if (snakeView != null) {
snakeView.startGame(currentSpeed);
}
updateScore(0);
}
@Override
protected void onPause() {
super.onPause();
if (snakeView != null) {
snakeView.pauseGame();
}
}
@Override
protected void onResume() {
super.onResume();
if (snakeView != null) {
snakeView.resumeGame(currentSpeed);
}
}
}
📌 Paste this code in Food.java
package com.nahid.snakegame;
import android.graphics.Point;
import java.util.Random;
public class Food {
private Point position;
private Random random;
private int blockSize;
private int width;
private int height;
private int foodType;
private int[] foodColors = {0xFFFF5252, 0xFFFFEB3B, 0xFF4CAF50, 0xFF2196F3, 0xFF9C27B0};
private int[] foodSizes = {35, 40, 45, 50, 55};
private int currentColor;
private int currentSize;
public Food(int blockSize, int width, int height) {
this.blockSize = blockSize;
this.width = width;
this.height = height;
random = new Random();
position = new Point();
currentColor = foodColors[0];
currentSize = foodSizes[0];
}
public void spawn() {
// Ensure we don't divide by zero and get positive bounds
if (width <= blockSize * 3 || height <= blockSize * 3) {
position.x = blockSize * 5;
position.y = blockSize * 5;
return;
}
// Generate random position within the game boundaries
int maxX = (width / blockSize) - 2;
int maxY = (height / blockSize) - 2;
if (maxX <= 1) maxX = 2;
if (maxY <= 1) maxY = 2;
position.x = (random.nextInt(maxX) + 1) * blockSize;
position.y = (random.nextInt(maxY) + 1) * blockSize;
// Random food type and properties
foodType = random.nextInt(5);
currentColor = foodColors[foodType];
currentSize = foodSizes[foodType];
}
public Point getPosition() {
return position;
}
public int getFoodColor() {
return currentColor;
}
public int getFoodSize() {
return currentSize;
}
public int getFoodType() {
return foodType;
}
public int getPoints() {
// Different food types give different points
return (foodType + 1) * 10;
}
}
📌 Paste this code in Snake.java
package com.nahid.snakegame;
import android.graphics.Point;
import java.util.ArrayList;
import java.util.List;
public class Snake {
public enum Direction {UP, DOWN, LEFT, RIGHT}
private List body;
private Direction direction;
private int blockSize;
private int width;
private int height;
private int snakeColor;
private boolean isGrowing;
private int growCounter;
public Snake(int blockSize, int width, int height) {
this.blockSize = blockSize;
this.width = width;
this.height = height;
// Initialize snake with gradient colors
snakeColor = 0xFF4CAF50;
// Initialize snake with 3 segments
body = new ArrayList<>();
body.add(new Point(width / 2, height / 2)); // Head
body.add(new Point(width / 2 - blockSize, height / 2));
body.add(new Point(width / 2 - 2 * blockSize, height / 2));
direction = Direction.RIGHT;
isGrowing = false;
growCounter = 0;
}
public void move() {
// Move the snake by adding a new head
Point newHead = new Point(getHead());
switch (direction) {
case UP:
newHead.y -= blockSize;
break;
case DOWN:
newHead.y += blockSize;
break;
case LEFT:
newHead.x -= blockSize;
break;
case RIGHT:
newHead.x += blockSize;
break;
}
body.add(0, newHead); // Add new head
// Handle growing animation
if (isGrowing) {
growCounter++;
if (growCounter >= 3) { // Grow after 3 moves
isGrowing = false;
growCounter = 0;
}
} else {
body.remove(body.size() - 1); // Remove tail
}
}
public void grow() {
isGrowing = true;
growCounter = 0;
// Change snake color slightly when growing
snakeColor = 0xFF66BB6A;
}
public boolean checkCollision() {
Point head = getHead();
// Check if snake hits the wall (with some tolerance)
if (head.x < 0 || head.y < 0 ||
head.x >= width - blockSize || head.y >= height - blockSize) {
return true;
}
// Check if snake hits itself (skip the head)
for (int i = 1; i < body.size(); i++) {
if (head.equals(body.get(i))) {
return true;
}
}
return false;
}
public boolean checkFoodCollision(Point foodPosition) {
Point head = getHead();
// Check if snake s head is within the food block with some tolerance
return (Math.abs(head.x - foodPosition.x) < blockSize / 2 &&
Math.abs(head.y - foodPosition.y) < blockSize / 2);
}
public void setDirection(Direction newDirection) {
// Prevent 180-degree turns
if ((direction == Direction.UP && newDirection == Direction.DOWN) ||
(direction == Direction.DOWN && newDirection == Direction.UP) ||
(direction == Direction.LEFT && newDirection == Direction.RIGHT) ||
(direction == Direction.RIGHT && newDirection == Direction.LEFT)) {
return;
}
direction = newDirection;
// Reset color after direction change
snakeColor = 0xFF4CAF50;
}
public Point getHead() {
return body.get(0);
}
public Point getTail() {
return body.get(body.size() - 1);
}
public List getBody() {
return body;
}
public Direction getDirection() {
return direction;
}
public int getSnakeColor() {
return snakeColor;
}
public boolean isGrowing() {
return isGrowing;
}
}
📌 Paste this code in SnakeView.java
package com.nahid.snakegame;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.RadialGradient;
import android.graphics.Shader;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.AccelerateDecelerateInterpolator;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
public class SnakeView extends View {
private Snake snake;
private Food food;
private int score = 0;
private boolean gameOver = false;
private Paint snakePaint;
private Paint foodPaint;
private Paint backgroundPaint;
private Paint eyePaint;
private Paint gridPaint;
private Paint textPaint;
private int blockSize = 40;
private Timer gameTimer;
private boolean isInitialized = false;
private ValueAnimator foodAnimator;
private float foodScale = 1.0f;
private int gameSpeed = 150; // Default speed in milliseconds (Medium)
// Speed levels
public static final int SPEED_EASY = 300;
public static final int SPEED_MEDIUM = 150;
public static final int SPEED_HARD = 75;
public SnakeView(Context context, AttributeSet attrs) {
super(context, attrs);
initPaints();
initFoodAnimation();
}
private void initPaints() {
// Snake paint with gradient
snakePaint = new Paint();
snakePaint.setAntiAlias(true);
snakePaint.setStyle(Paint.Style.FILL);
// Food paint
foodPaint = new Paint();
foodPaint.setAntiAlias(true);
foodPaint.setStyle(Paint.Style.FILL);
// Background paint
backgroundPaint = new Paint();
backgroundPaint.setColor(0xFF1E1E1E);
backgroundPaint.setStyle(Paint.Style.FILL);
// Grid paint
gridPaint = new Paint();
gridPaint.setColor(0x33FFFFFF);
gridPaint.setStrokeWidth(1);
// Eye paint
eyePaint = new Paint();
eyePaint.setColor(Color.WHITE);
eyePaint.setAntiAlias(true);
// Text paint for debug info
textPaint = new Paint();
textPaint.setColor(Color.WHITE);
textPaint.setTextSize(20);
textPaint.setAntiAlias(true);
}
private void initFoodAnimation() {
foodAnimator = ValueAnimator.ofFloat(0.8f, 1.2f);
foodAnimator.setDuration(1000);
foodAnimator.setRepeatMode(ValueAnimator.REVERSE);
foodAnimator.setRepeatCount(ValueAnimator.INFINITE);
foodAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
foodAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
foodScale = (float) animation.getAnimatedValue();
postInvalidate(); // শুধুমাত্র food অংশ redraw করবে
}
});
}
public void setGameSpeed(int speed) {
this.gameSpeed = speed;
restartGameWithNewSpeed();
}
public int getGameSpeed() {
return gameSpeed;
}
private void restartGameWithNewSpeed() {
boolean wasRunning = (gameTimer != null && !gameOver);
pauseGame();
if (wasRunning) {
resumeGame();
}
}
public void startGame(int speed) {
this.gameSpeed = speed;
startGame();
}
public void startGame() {
if (getWidth() <= 0 || getHeight() <= 0) {
return;
}
snake = new Snake(blockSize, getWidth(), getHeight());
food = new Food(blockSize, getWidth(), getHeight());
food.spawn();
score = 0;
gameOver = false;
isInitialized = true;
foodScale = 1.0f;
if (gameTimer != null) {
gameTimer.cancel();
}
gameTimer = new Timer();
gameTimer.schedule(new TimerTask() {
@Override
public void run() {
if (!gameOver && isInitialized) {
update();
postInvalidate();
}
}
}, 0, gameSpeed); // Use the current game speed
}
private void update() {
if (!isInitialized) return;
snake.move();
if (snake.checkFoodCollision(food.getPosition())) {
int points = food.getPoints();
snake.grow();
food.spawn();
score += points;
// Food collection effect - Main thread এ run করতে হবে
post(new Runnable() {
@Override
public void run() {
startFoodAnimation();
}
});
if (getContext() instanceof MainActivity) {
((MainActivity) getContext()).updateScore(score);
}
}
if (snake.checkCollision()) {
gameOver = true;
post(new Runnable() {
@Override
public void run() {
stopFoodAnimation();
}
});
if (getContext() instanceof MainActivity) {
((MainActivity) getContext()).showGameOver();
}
}
}
public void startFoodAnimation() {
if (foodAnimator != null && !foodAnimator.isStarted()) {
foodAnimator.start();
}
}
public void stopFoodAnimation() {
if (foodAnimator != null && foodAnimator.isRunning()) {
foodAnimator.cancel();
foodScale = 1.0f;
}
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// Draw background with grid pattern
drawBackground(canvas);
if (isInitialized && snake != null && food != null) {
// Draw food with glowing effect
drawFood(canvas);
// Draw snake with realistic appearance
drawSnake(canvas);
// Draw debug information
drawDebugInfo(canvas);
}
}
private void drawBackground(Canvas canvas) {
canvas.drawRect(0, 0, getWidth(), getHeight(), backgroundPaint);
// Draw grid lines
for (int x = blockSize; x < getWidth(); x += blockSize) {
canvas.drawLine(x, 0, x, getHeight(), gridPaint);
}
for (int y = blockSize; y < getHeight(); y += blockSize) {
canvas.drawLine(0, y, getWidth(), y, gridPaint);
}
}
private void drawFood(Canvas canvas) {
Point foodPos = food.getPosition();
int foodSize = food.getFoodSize();
int foodColor = food.getFoodColor();
// Calculate scaled food size
float scaledSize = foodSize * foodScale;
// Draw food with gradient and glow
RadialGradient gradient = new RadialGradient(
foodPos.x + foodSize/2f, foodPos.y + foodSize/2f, scaledSize/2f,
foodColor, darkenColor(foodColor), Shader.TileMode.CLAMP
);
foodPaint.setShader(gradient);
canvas.drawCircle(foodPos.x + foodSize/2f, foodPos.y + foodSize/2f,
scaledSize/2f, foodPaint);
// Draw food inner highlight
foodPaint.setShader(null);
foodPaint.setColor(lightenColor(foodColor));
canvas.drawCircle(foodPos.x + foodSize/3f, foodPos.y + foodSize/3f,
scaledSize/6f, foodPaint);
}
private void drawSnake(Canvas canvas) {
List body = snake.getBody();
int snakeColor = snake.getSnakeColor();
// Draw snake body with gradient
for (int i = 0; i < body.size(); i++) {
Point segment = body.get(i);
// Create gradient for each segment
float[] hsv = new float[3];
Color.colorToHSV(snakeColor, hsv);
hsv[2] *= 0.9f; // Darken based on position
int segmentColor = Color.HSVToColor(hsv);
RadialGradient gradient = new RadialGradient(
segment.x + blockSize/2f, segment.y + blockSize/2f, blockSize/2f,
lightenColor(segmentColor), darkenColor(segmentColor), Shader.TileMode.CLAMP
);
snakePaint.setShader(gradient);
canvas.drawRoundRect(
segment.x + 2, segment.y + 2,
segment.x + blockSize - 2, segment.y + blockSize - 2,
10, 10, snakePaint
);
}
// Draw snake eyes on head
Point head = snake.getHead();
drawSnakeEyes(canvas, head, snake.getDirection());
}
private void drawSnakeEyes(Canvas canvas, Point head, Snake.Direction direction) {
int eyeSize = blockSize / 4;
int pupilSize = eyeSize / 2;
int eyeX1, eyeY1, eyeX2, eyeY2;
switch (direction) {
case UP:
eyeX1 = head.x + blockSize/3;
eyeY1 = head.y + blockSize/3;
eyeX2 = head.x + 2*blockSize/3;
eyeY2 = head.y + blockSize/3;
break;
case DOWN:
eyeX1 = head.x + blockSize/3;
eyeY1 = head.y + 2*blockSize/3;
eyeX2 = head.x + 2*blockSize/3;
eyeY2 = head.y + 2*blockSize/3;
break;
case LEFT:
eyeX1 = head.x + blockSize/3;
eyeY1 = head.y + blockSize/3;
eyeX2 = head.x + blockSize/3;
eyeY2 = head.y + 2*blockSize/3;
break;
case RIGHT:
eyeX1 = head.x + 2*blockSize/3;
eyeY1 = head.y + blockSize/3;
eyeX2 = head.x + 2*blockSize/3;
eyeY2 = head.y + 2*blockSize/3;
break;
default:
return;
}
// Draw eyes
eyePaint.setColor(Color.WHITE);
canvas.drawCircle(eyeX1, eyeY1, eyeSize, eyePaint);
canvas.drawCircle(eyeX2, eyeY2, eyeSize, eyePaint);
// Draw pupils
eyePaint.setColor(Color.BLACK);
canvas.drawCircle(eyeX1, eyeY1, pupilSize, eyePaint);
canvas.drawCircle(eyeX2, eyeY2, pupilSize, eyePaint);
}
private void drawDebugInfo(Canvas canvas) {
// Draw current speed information
String speedText = "Speed: ";
if (gameSpeed == SPEED_EASY) {
speedText += "Easy (" + gameSpeed + "ms)";
} else if (gameSpeed == SPEED_MEDIUM) {
speedText += "Medium (" + gameSpeed + "ms)";
} else if (gameSpeed == SPEED_HARD) {
speedText += "Hard (" + gameSpeed + "ms)";
} else {
speedText += "Custom (" + gameSpeed + "ms)";
}
canvas.drawText(speedText, 10, 30, textPaint);
canvas.drawText("Score: " + score, 10, 60, textPaint);
canvas.drawText("Snake Size: " + snake.getBody().size(), 10, 90, textPaint);
}
private int darkenColor(int color) {
float[] hsv = new float[3];
Color.colorToHSV(color, hsv);
hsv[2] *= 0.7f; // value component
return Color.HSVToColor(hsv);
}
private int lightenColor(int color) {
float[] hsv = new float[3];
Color.colorToHSV(color, hsv);
hsv[2] = Math.min(1.0f, hsv[2] * 1.3f);
return Color.HSVToColor(hsv);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
if (w > 0 && h > 0) {
startGame();
}
}
public void setDirection(Snake.Direction direction) {
if (snake != null) {
snake.setDirection(direction);
}
}
public boolean isGameOver() {
return gameOver;
}
public void pauseGame() {
if (gameTimer != null) {
gameTimer.cancel();
gameTimer = null;
}
stopFoodAnimation();
}
public void resumeGame(int speed) {
this.gameSpeed = speed;
resumeGame();
}
public void resumeGame() {
if (!gameOver && isInitialized) {
if (gameTimer != null) {
gameTimer.cancel();
}
gameTimer = new Timer();
gameTimer.schedule(new TimerTask() {
@Override
public void run() {
if (!gameOver && isInitialized) {
update();
postInvalidate();
}
}
}, 0, gameSpeed);
}
}
public int getScore() {
return score;
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
pauseGame();
if (foodAnimator != null) {
foodAnimator.cancel();
}
}
}