Bienvenidos sean a este post, hoy les traigo el codigo completo de nuestro cuarto proyecto.
En este caso seran solamente los codigos (tal como hicimos con cada proyecto que terminamos) pero si necesitan una explicacion les dejo un listado de los posts donde explicamos cada uno de ellos:
- Nuestro cuarto proyecto
- Clase SnakeJuego
- Agregando otros idiomas al juego
- La clase Manzana
- La clase Snake
- Finalizando el juego
Tambien les dejo los dos archivos que deben descargar, el primero sera para los sonidos:
Y este es el archivo que contiene las imagenes que usaremos:
El proyecto deberan crearlo con las siguientes caracteristicas:
- Dispositivos: Phone and Tablet
- Actividad: Empty Activity
- Nombre: Snake
- Nombre de paquete: org.example.snake
- API Minimo: API 14 (Android 4.0)
Comencemos con los codigos de cada una de las clases:
SnakeActivity.java
package org.example.snake;
import android.app.Activity;
import android.graphics.Point;
import android.os.Bundle;
import android.view.Display;
public class SnakeActivity extends Activity {
SnakeJuego mSnakeJuego;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Display display = getWindowManager().getDefaultDisplay();
Point tamano = new Point();
display.getSize(tamano);
mSnakeJuego = new SnakeJuego(this, tamano);
setContentView(mSnakeJuego);
}
@Override
protected void onResume(){
super.onResume();
mSnakeJuego.retomar();
}
@Override
protected void onPause(){
super.onPause();
mSnakeJuego.pausar();
}
}
Snake.java
package org.example.snake;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Point;
import android.view.MotionEvent;
import java.util.ArrayList;
class Snake {
private ArrayList<Point> ubicacionSegmentos;
private int mTamanoSegmento;
private Point mRangoMov;
private int pointMitad;
private enum Cabeza{
ARRIBA,
ABAJO,
IZQUIERDA,
DERECHA
};
private Cabeza cabeza = Cabeza.DERECHA;
private Bitmap mCabezaArr;
private Bitmap mCabezaAbj;
private Bitmap mCabezaDer;
private Bitmap mCabezaIzq;
private Bitmap mCuerpo;
Snake(Context contexto, Point rm, int ss){
ubicacionSegmentos = new ArrayList<>();
mTamanoSegmento = ss;
mRangoMov = rm;
mCabezaIzq = BitmapFactory.decodeResource(
contexto.getResources(),
R.drawable.cabeza);
mCabezaIzq = Bitmap.createScaledBitmap(mCabezaIzq,
ss,ss,false);
mCabezaDer = BitmapFactory.decodeResource(
contexto.getResources(),
R.drawable.cabeza);
mCabezaArr = BitmapFactory.decodeResource(
contexto.getResources(),
R.drawable.cabeza);
mCabezaAbj = BitmapFactory.decodeResource(
contexto.getResources(),
R.drawable.cabeza);
Matrix matrix = new Matrix();
matrix.preScale(-1,1);
mCabezaDer = Bitmap.createBitmap(mCabezaIzq,
0,0,ss,ss,matrix,true);
matrix.preRotate(90);
mCabezaArr = Bitmap.createBitmap(mCabezaIzq,
0,0,ss,ss,matrix,true);
matrix.preRotate(180);
mCabezaAbj = Bitmap.createBitmap(mCabezaIzq,
0,0,ss,ss,matrix,true);
mCuerpo = BitmapFactory.decodeResource(
contexto.getResources(),R.drawable.cuerpo);
mCuerpo = Bitmap.createScaledBitmap(
mCuerpo,ss,ss,false);
pointMitad = rm.x * ss / 2;
}
void reset (int an, int al){
cabeza = cabeza.DERECHA;
ubicacionSegmentos.clear();
ubicacionSegmentos.add(new Point(an/2,al/2));
}
void mover(){
for(int i=ubicacionSegmentos.size()-1; i > 0; i--){
ubicacionSegmentos.get(i).x = ubicacionSegmentos.get(i-1).x;
ubicacionSegmentos.get(i).y = ubicacionSegmentos.get(i-1).y;
}
Point p = ubicacionSegmentos.get(0);
switch (cabeza){
case ARRIBA:
p.y--;
break;
case ABAJO:
p.y++;
break;
case DERECHA:
p.x++;
break;
case IZQUIERDA:
p.x--;
break;
}
ubicacionSegmentos.set(0,p);
}
boolean detectarMuerte(){
boolean muerto = false;
if (ubicacionSegmentos.get(0).x==-1 ||
ubicacionSegmentos.get(0).x >= mRangoMov.x ||
ubicacionSegmentos.get(0).y == -1 ||
ubicacionSegmentos.get(0).y >= mRangoMov.y){
muerto = true;
}
for(int i=ubicacionSegmentos.size()-1; i > 0; i--){
if (ubicacionSegmentos.get(0).x ==
ubicacionSegmentos.get(i).x &&
ubicacionSegmentos.get(0).y ==
ubicacionSegmentos.get(i).y){
muerto = true;
}
}
return muerto;
}
boolean chekaCena(Point l){
if (ubicacionSegmentos.get(0).x == l.x &&
ubicacionSegmentos.get(0).y == l.y){
ubicacionSegmentos.add(new Point(-10,-10));
return true;
}
return false;
}
void dibujar(Canvas canvas, Paint pincel){
if (!ubicacionSegmentos.isEmpty()){
switch (cabeza){
case DERECHA:
canvas.drawBitmap(mCabezaDer,
ubicacionSegmentos.get(0).x * mTamanoSegmento,
ubicacionSegmentos.get(0).y * mTamanoSegmento,
pincel);
break;
case IZQUIERDA:
canvas.drawBitmap(mCabezaIzq,
ubicacionSegmentos.get(0).x * mTamanoSegmento,
ubicacionSegmentos.get(0).y * mTamanoSegmento,
pincel);
break;
case ABAJO:
canvas.drawBitmap(mCabezaAbj,
ubicacionSegmentos.get(0).x * mTamanoSegmento,
ubicacionSegmentos.get(0).y * mTamanoSegmento,
pincel);
break;
case ARRIBA:
canvas.drawBitmap(mCabezaArr,
ubicacionSegmentos.get(0).x * mTamanoSegmento,
ubicacionSegmentos.get(0).y * mTamanoSegmento,
pincel);
break;
}
for(int i=1; i < ubicacionSegmentos.size(); i++){
canvas.drawBitmap(mCuerpo,
ubicacionSegmentos.get(i).x * mTamanoSegmento,
ubicacionSegmentos.get(i).y * mTamanoSegmento,
pincel);
}
}
}
void cambiarDireccion(MotionEvent evento){
if (evento.getX() >= pointMitad){
switch (cabeza){
case ARRIBA:
cabeza = cabeza.DERECHA;
break;
case ABAJO:
cabeza = cabeza.IZQUIERDA;
break;
case IZQUIERDA:
cabeza = cabeza.ARRIBA;
break;
case DERECHA:
cabeza = cabeza.ABAJO;
break;
}
} else {
switch (cabeza){
case ARRIBA:
cabeza = cabeza.IZQUIERDA;
break;
case ABAJO:
cabeza = cabeza.DERECHA;
break;
case IZQUIERDA:
cabeza = cabeza.ABAJO;
break;
case DERECHA:
cabeza = cabeza.ARRIBA;
break;
}
}
}
}
Manzana.java
package org.example.snake;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Point;
import java.util.Random;
class Manzana {
private Point mUbicacion = new Point();
private Point mRangoCreacion;
private int mTamano;
private Bitmap mBitmapManzana;
Manzana(Context contexto, Point rc, int t){
mRangoCreacion = rc;
mTamano = t;
mUbicacion.x = -10;
mBitmapManzana = BitmapFactory
.decodeResource(contexto.getResources()
,R.drawable.manzana);
mBitmapManzana = Bitmap
.createScaledBitmap(mBitmapManzana,t,t,false);
}
void generar(){
Random random = new Random();
mUbicacion.x = random.nextInt(mRangoCreacion.x) + 1;
mUbicacion.y = random.nextInt(mRangoCreacion.y - 1) + 1;
}
Point getUbicacion(){
return mUbicacion;
}
void dibujar(Canvas canvas, Paint pincel){
canvas.drawBitmap(mBitmapManzana,
mUbicacion.x * mTamano,mUbicacion.y * mTamano,pincel);
}
}
SnakeJuego.java
package org.example.snake;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;
import android.media.AudioAttributes;
import android.media.AudioManager;
import android.media.SoundPool;
import android.os.Build;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import java.io.IOException;
class SnakeJuego extends SurfaceView implements Runnable {
private Thread mThread = null;
private long mProxTiempoCuadro;
private volatile boolean mPausado = true;
private volatile boolean mJugando = false;
private SoundPool mSP;
private int mComer_ID = -1;
private int mMordida_ID = -1;
private final int ANCHO_NUM_BLOQUES = 30;
private int mNumeroBloquesAlto;
private int mPuntaje;
private Canvas mCanvas;
private SurfaceHolder mSurfaceHolder;
private Paint mPincel;
private Snake mSnake;
private Manzana mManzana;
public SnakeJuego(Context contexto, Point tamano) {
super(contexto);
int tamanoBloque = tamano.x / ANCHO_NUM_BLOQUES;
mNumeroBloquesAlto = tamano.y / tamanoBloque;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP){
AudioAttributes atributos = new AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_MEDIA)
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.build();
mSP = new SoundPool.Builder()
.setAudioAttributes(atributos)
.setMaxStreams(5)
.build();
} else {
mSP = new SoundPool(5, AudioManager.STREAM_MUSIC,0);
}
try {
mComer_ID = mSP.load(contexto,R.raw.apple,0);
mMordida_ID = mSP.load(contexto,R.raw.bitten,0);
} catch (Exception e){
Log.e("Error","Ha ocurrido un error con la carga de los archivos");
}
mSurfaceHolder=getHolder();
mPincel = new Paint();
mManzana = new Manzana(contexto,
new Point(ANCHO_NUM_BLOQUES,
mNumeroBloquesAlto),
tamanoBloque);
mSnake = new Snake(contexto,
new Point(ANCHO_NUM_BLOQUES,
mNumeroBloquesAlto),
tamanoBloque);
}
@Override
public void run(){
while(mJugando){
if(!mPausado){
if(requiereActualizar()){
actualizar();
}
}
dibujar();
}
}
public boolean requiereActualizar(){
final long BLANCO_FPS = 10;
final long MILES_POR_SEGUNDO = 1000;
if(mProxTiempoCuadro<=System.currentTimeMillis()){
mProxTiempoCuadro=System.currentTimeMillis()
+ MILES_POR_SEGUNDO / BLANCO_FPS;
return true;
}
return false;
}
public void actualizar(){
mSnake.mover();
if (mSnake.chekaCena(mManzana.getUbicacion())){
mManzana.generar();
mPuntaje++;
mSP.play(mComer_ID,1,1,0,0,1);
}
if (mSnake.detectarMuerte()){
mSP.play(mMordida_ID,1,1,0,0,1);
mPausado = true;
}
}
public void dibujar(){
if(mSurfaceHolder.getSurface().isValid()){
mCanvas = mSurfaceHolder.lockCanvas();
mCanvas.drawColor(Color.argb(255,26,128,182));
mPincel.setColor(Color.argb(255,255,255,255));
mPincel.setTextSize(120);
mCanvas.drawText("" + mPuntaje,20,120,mPincel);
mManzana.dibujar(mCanvas,mPincel);
mSnake.dibujar(mCanvas,mPincel);
if (mPausado){
mPincel.setColor(Color.argb(255,255,255,255));
mPincel.setTextSize(100);
mCanvas.drawText(getResources().getString(R.string.inicioTexto),
20,300,mPincel);
}
mSurfaceHolder.unlockCanvasAndPost(mCanvas);
}
}
@Override
public boolean onTouchEvent(MotionEvent evento){
switch (evento.getAction() & MotionEvent.ACTION_MASK){
case MotionEvent.ACTION_UP:
if (mPausado){
mPausado = false;
nuevoJuego();
return true;
}
mSnake.cambiarDireccion(evento);
break;
default:
break;
}
return true;
}
public void nuevoJuego(){
mSnake.reset(ANCHO_NUM_BLOQUES,mNumeroBloquesAlto);
mManzana.generar();
mPuntaje = 0;
mProxTiempoCuadro = System.currentTimeMillis();
}
public void pausar(){
mJugando=false;
try{
mThread.join();
} catch (InterruptedException e){
Log.e("Error", "no se pudo detener el thread.");
}
}
public void retomar(){
mJugando=true;
mThread = new Thread(this);
mThread.start();
}
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.example.snake">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".SnakeActivity"
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
android:screenOrientation="landscape">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Con esto ya tenemos completo nuestro juego deberan tener un resultado similar a este:
En resumen, hemos hecho nuestro cuarto proyecto y con un clasico como es el juego snake, hemos logrado como manejar varios elementos para nuestro cuerpo, hemos trabajado algunos elementos de manera muy avanzada pero para el proximo proyecto haremos una genialidad unica, espero les haya gustado o sido util sigueme en tumblr, Twitter o Facebook para recibir una notificacion cada vez que subo un nuevo post en este blog, nos vemos en el proximo post.
Tengo un Patreon donde podes acceder de manera exclusiva a material para este blog antes de ser publicado, sigue los pasos del link para saber como.

Tambien podes donar
Es para mantenimiento del sitio, gracias!
$1.00