Шаблон для создания 2D игр


Я использую следующий шаблон программы Мой 2D игр. Есть ли способ я могу улучшить его?

Заставка:

package com.dingle.template2d;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;



public class template2d extends Activity {

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    //set screen
    setContentView(R.layout.splash);

    // thread for displaying the SplashScreen
    Thread splashTread = new Thread() {
        @Override
        public void run() {
            try {
                int waited = 0;
                boolean _active;
                int _splashTime;
                 _active = true;
                 _splashTime = 500;
                while(_active && (waited < _splashTime)) {
                    sleep(100);
                    if(_active) {
                        waited += 100;
                    }
                }
                startActivity(new Intent("com.dingle.template2d.MENU"));
            } catch(InterruptedException e) {
                // do nothing
            } finally {
                finish();


            }
        }
    };
    splashTread.start();


   }

 }

Меню:

package com.dingle.template2d;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.Window;
import android.widget.Button;

public class menu extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    requestWindowFeature(Window.FEATURE_NO_TITLE);
    setContentView(R.layout.main);
    this.button();

}

private void button(){
       Button play_button = (Button)this.findViewById(R.id.play_button);
       play_button.setOnClickListener(
                  new Button.OnClickListener() {
                      public void onClick(View v) {
                    // parentButtonClicked(v);
                          startActivity(new      Intent("com.dingle.template2d.GAME"));
                     }
                  });
}
}

GameView класс: (это где я положил все код игры)

package com.dingle.template2d;

import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.os.Bundle;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.Window;

public class GameView extends Activity {

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    requestWindowFeature(Window.FEATURE_NO_TITLE);
    setContentView(new Panel(this));
}

public class Panel extends SurfaceView implements SurfaceHolder.Callback{

private MainThread _thread;

public Panel(Context context) {
    super(context);
    getHolder().addCallback(this);
    _thread = new MainThread(getHolder(), this);
    setFocusable(true);
}

final int windowHeight = getResources().getDisplayMetrics().heightPixels;
final int windowWidth = getResources().getDisplayMetrics().widthPixels;
final float tscale = getResources().getDisplayMetrics().density;
final int scale = (int) tscale;
public int _x = 0;
public int _y = 0;
Bitmap _scratch = BitmapFactory.decodeResource(getResources(), R.drawable.icon);
/**
*
*I Declare everything here
*
**/


@Override
public void onDraw(Canvas canvas) {
/**
*
*I run all my code here
*
**/
}

/*  @Override
public boolean onTouchEvent(MotionEvent event) {
    _x = (int) event.getX();
    _y = (int) event.getY();
    return true;
}*/

@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
    // TODO Auto-generated method stub

}

@Override
public void surfaceCreated(SurfaceHolder holder) {
    _thread.setRunning(true);
    _thread.start();
}

@Override
public void surfaceDestroyed(SurfaceHolder holder) {
    // simply copied from sample application LunarLander:
    // we have to tell thread to shut down & wait for it to finish, or else
    // it might touch the Surface after we return and explode
    boolean retry = true;
    _thread.setRunning(false);
    while (retry) {
        try {
            _thread.join();
            retry = false;
        } catch (InterruptedException e) {
            // we will try it again and again...
        }
    }
}
}
}

Основной Поток:

package com.dingle.template2d;

import com.dingle.template2d.GameView.Panel;

import android.graphics.Canvas;
import android.view.SurfaceHolder;

public class MainThread extends Thread {
private SurfaceHolder _surfaceHolder;
private Panel _panel;
private boolean _run = false;

public MainThread(SurfaceHolder surfaceHolder, Panel panel) {
    _surfaceHolder = surfaceHolder;
    _panel = panel;
}

public void setRunning(boolean run) {
    _run = run;
}

@Override
public void run() {
    Canvas c;
    while (_run) {
        c = null;
        try {
            c = _surfaceHolder.lockCanvas(null);
            synchronized (_surfaceHolder) {
                _panel.onDraw(c);
            }
        } finally {
            // do this in a finally so that if an exception is thrown
            // during the above, we don't leave the Surface in an
            // inconsistent state
            if (c != null) {
                _surfaceHolder.unlockCanvasAndPost(c);
            }
        }
    }
}
}


1377
6
задан 3 августа 2011 в 08:08 Источник Поделиться
Комментарии
1 ответ

И в частности, нет порядка, не вероятно, что вы будто ждала:

На inpredictability сна

В петле

int waited = 0;
while(_active && (waited < _splashTime)) {
sleep(100);
if(_active) {
waited += 100;
}
}

способ сна не может гарантировать, что время спал фактически 100 мс. Она может больше или может быть меньше в зависимости от контекста и точность часов и т. д. Было бы лучше, если бы вы опирались на системные часы, а не счетчик:

long started = System.currentTimeMillis();
while(_active && System.currentTimeMillis() - start < _splashTime) {
sleep(100);
}

Если вы в конечном итоге с помощью ждали счетчика, если(_active) условия может и не понадобиться.

На начальных значений

Если у вас нет особых причин для определения переменных исходных значений в отдельных строках, можно определить их в той же строке

int waited = 0;
boolean _active;
int _splashTime;
_active = true;
_splashTime = 500;

становится

int waited = 0;
boolean _active = true;
int _splashTime = 500;

О наименовании

Я видел подчеркивания для обозначения переменных экземпляра и я после скимминга я думал _activeи _splashTime были такие. Вместо этого они были локальные переменные. Возможно, не используя и подчеркивания могут быть больше обычных.

Можно использовать символ подчеркивания в переменных экземпляра, а также, что ок, хотя я не большой поклонник его.

Есть также некоторые несоответствия с переменным имена из нескольких слов: сравните surfaceHolder и play_button. В Java это convetional, что имена переменных в верблюда-чехол без пробелов; playButton будет лучше.

Имена классов начинаются с прописной буквы, например Template2d, меню.

На константы

Мне кажется, вы пытаетесь объявить константу _splashTime. Почему бы просто не сделать так с

public class template2d extends Activity {
private static final SPLASH_TIME_IN_MILLISECONDS = 500;
}

По видимости

Я бы предпочел, если все переменные экземпляра будет либо частная или окончательной.

Это по крайней мере не плохая идея, чтобы держать область переменных, как можно меньше. В

Canvas c;
while (_run) {
c = null;
try {
c = _surfaceHolder.lockCanvas(null);
synchronized (_surfaceHolder) {
_panel.onDraw(c);
}
} finally {
// do this in a finally so that if an exception is thrown
// during the above, we don't leave the Surface in an
// inconsistent state
if (c != null) {
_surfaceHolder.unlockCanvasAndPost(c);
}
}
}

Холст переменная c не существует вне покапетля в то время как он не используется нигде, кроме как в нем. Вы можете объявить переменную внутри цикла, чтобы ограничить его объем

while (_run) {
Canvas c = null;
try {
c = _surfaceHolder.lockCanvas(null);
synchronized (_surfaceHolder) {
_panel.onDraw(c);
}
} finally {
// do this in a finally so that if an exception is thrown
// during the above, we don't leave the Surface in an
// inconsistent state
if (c != null) {
_surfaceHolder.unlockCanvasAndPost(c);
}
}
}

На порядке вещей

Содержание класса, как правило, в порядке не unline следующие


  1. Подпись класс

  2. публичный статический constansts

  3. частная статические константы

  4. частная статические переменные

  5. частная константы

  6. частная переменных

  7. конструкторы

  8. публичных методов

  9. частные методы

Это делает код труднее уследить, если есть экземпляр переменной в более чем одном месте.

В последнее время я экспериментировал, как он чувствует, как когда все частные подвернут вниз на дно класс и мне нравится. Хотя конвенций кодирования козырь личных предпочтений.

Делать всего одну вещь

Каждый класс и объект желательно делать только одну вещь т. е. они должны иметь единую ответственность. По крайней мере, класса группа содержит функции для рисования поверхности и реагирования на события. Эти две вещи можно разделить на два разных класса, если это имеет смысл.

На разных способов написания одного и того же кода

В этом коде

retry = true;
while (retry) {
try {
_thread.join();
retry = false;
} catch (InterruptedException e) {
// we will try it again and again...
}
}

Вы могли бы достичь того же с перерывом заявление, чтобы избавится от лишней переменной

while (true) { // or for(;;)
try {
_thread.join();
break;
} catch (InterruptedException e) {
// we will try it again and again...
}
}

или определять логику в метод, чтобы описать свои намерения более четко

while(!hasThreadStopped) {
// Retry until thread stops
}
...

private boolean hasThreadStopped() {
try {
_thread.join();
return true;
} catch (InterruptedException e) {
return false;
}
}

11
ответ дан 3 августа 2011 в 10:08 Источник Поделиться