Как реализовать и нарисовать пользовательскую кнопку на Android SurfaceView - PullRequest
0 голосов
/ 29 января 2019

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

Теперь я хочу разместить кнопку «Начать игру» в моем MainMenu, и мне интересно, как лучше всего это сделатьэтот.

Я мог бы объявить кнопку как private Bitmap button;, и на событии onTouch захватить пользователя Нажмите и выполните некоторые функции, если пользователь нажал координаты внутри кнопки.

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

Мне не нужен код (я учусь сам), просто объяснение того, как это сделать.Я думал о создании кнопки «Пуск», расширяющей сцену, или, возможно, о расширении растровых классов.

Я бы делал список объектов в классе MainManu для каждого GameObject, содержащий пользовательский интерфейс, и проверял бы список при каждом розыгрыше и при каждом касании.

Что вы думаете?

Основная активность

public class MainActivity extends Activity {
    private SceneHandler _sceneHandler;
    private DBCore database;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
            WindowManager.LayoutParams.FLAG_FULLSCREEN);
        this.requestWindowFeature(Window.FEATURE_NO_TITLE);

        database = new DBCore(this, getResources().getString(R.string.db_name),
                            null, 1);

        _sceneHandler = new SceneHandler(this);
        setContentView(_sceneHandler.getContentView());
    }
}

MainThread

public class MainThread extends Thread {
    private SurfaceHolder surfaceHolder;
    private GameView gameView;
    private boolean running;
    public static Canvas canvas;
    private int targetFPS = 60;
    private double averageFPS;

    public MainThread(SurfaceHolder surfaceHolder, GameView gameView) {

        super();
        this.surfaceHolder = surfaceHolder;
        this.gameView = gameView;

    }

    @Override
    public void run() {
        long startTime;
        long timeMillis;
        long waitTime;
        long totalTime = 0;
        int frameCount = 0;
        long targetTime = 1000 / targetFPS;

        while (running) {
            startTime = System.nanoTime();
            canvas = null;

            try {
                canvas = this.surfaceHolder.lockCanvas();
                synchronized(surfaceHolder) {
                    this.gameView.update();
                    this.gameView.draw(canvas);
                }
            } catch (Exception e) {       }
            finally {
                if (canvas != null)            {
                    try {
                        surfaceHolder.unlockCanvasAndPost(canvas);
                    }
                    catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }

            timeMillis = (System.nanoTime() - startTime) / 1000000;
            waitTime = targetTime - timeMillis;

            try {
                this.sleep(waitTime);
            } catch (Exception e) {}

            totalTime += System.nanoTime() - startTime;
            frameCount++;
            if (frameCount == targetFPS)        {
                averageFPS = 1000 / ((totalTime / frameCount) / 1000000);
                frameCount = 0;
                totalTime = 0;
                System.out.println(averageFPS);
            }
        }

    }

    public void setRunning(boolean isRunning) {
        running = isRunning;
    }
}

GameView (он же SurfaceView)

public class GameView extends SurfaceView implements SurfaceHolder.Callback {
    private MainThread thread;

    public GameView(Context context) {
        super(context);

        getHolder().addCallback(this);
        thread = new MainThread(getHolder(), this);
        setFocusable(true);
    }

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

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        boolean retry = true;
        while (retry) {
            try {
                thread.setRunning(false);
                thread.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            retry = false;
        }
    }

    @Override
    public void draw(Canvas canvas) {
        super.draw(canvas);
    }

    public void update() {

    }
}

SceneHandler (для переключения между сценами и внесения некоторой логики в изменения)

public class SceneHandler {
    private Canvas _canvas;

    private Scene _currentScene;
    private MainMenu _mainMenu;
    private LoadingBattle _loadingBattle;
    private Battlefield _battlefield;

    public SceneHandler(Context context) {
        this._mainMenu = new MainMenu(context);
        this._currentScene = this._mainMenu;
    }

    public void changeToScene(String newScene)
    {
        try {
            switch (newScene)
            {
                case "MainMenu":
                    this._currentScene = this._mainMenu;
                    break;
                case "LoadingBattle":
                    this._currentScene = this._loadingBattle;
                    break;
                case "Battlefield":
                    this._currentScene = this._battlefield;
                    break;
                default:
                    throw new Exception("Unrecongnized Scene");
            }
        } catch (Exception e) {
            //
        }
    }

    public Scene getContentView() {
        return _currentScene;
    }
}

Сцена (Основной класс для расширения)

public class Scene extends GameView implements View.OnTouchListener {
    private Scene _currentScene;
    private ArrayList<Scene> _gameScenes;

    public Scene(Context context) {
        super(context);
    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        return false;
    }
}

MainMenu (наконец, сцена, где я хочу поставить кнопку)

public class MainMenu extends Scene {
    private Bitmap background;
    private Context context;

    public MainMenu(Context context) {
        super(context);
        this.context = context;
        background = BitmapFactory.decodeResource(getContext().getResources(), R.drawable.varaldor_menu_background);
    }

    private Matrix getScaleTransformationMatrix() {
        float originalWidth = background.getWidth();
        float originalHeight = background.getHeight();
        float scale = this.getScreenSize().get("width") / originalWidth;

        float xTranslation = 0.0f;
        float yTranslation = (this.getScreenSize().get("height") - originalHeight * scale) / 2.0f;
        Matrix transformation = new Matrix();
        transformation.postTranslate(xTranslation, yTranslation);
        transformation.preScale(scale, scale);
        return transformation;
    }

    @Override
    public void draw(Canvas canvas) {
        super.draw(canvas);
        canvas.drawBitmap(background, 0, 0, null);
        Paint paint = new Paint();
        paint.setFilterBitmap(true);

        canvas.drawBitmap(background, getScaleTransformationMatrix(), paint);
    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:

                Toast.makeText(context,
                    "Toast por defecto", Toast.LENGTH_SHORT);
                break;
        }
        return true;
    }

    private Map<String, Integer> getScreenSize() {
        Display display = ((Activity)context).getWindowManager().getDefaultDisplay();
        Point size = new Point();
        display.getSize(size);
        Integer width = size.x;
        Integer height = size.y;
        Map<String, Integer> screenSizeArray = new HashMap<String, Integer>();
        screenSizeArray.put("width", width);
        screenSizeArray.put("height", height);
        return screenSizeArray;
    }
}
...