Android SurfaceView - рисует пустой полноэкранный режим - PullRequest
0 голосов
/ 20 октября 2019

В настоящее время я учусь создавать простую игру для Android с использованием SurfaceView. В настоящее время я сталкиваюсь с двумя проблемами:

  1. SurfaceView обрабатывает весь экран, когда не должен, так как я применил к нему layout_weight.
  2. SurfaceViewничего не рендерит, просто огромный белый экран.

Вот мой код

GameFragment.java

package com.example.tubes_2.fragments;

import android.graphics.drawable.Drawable;
import android.os.Bundle;

import androidx.fragment.app.Fragment;

import android.view.LayoutInflater;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;

import com.example.tubes_2.R;
import com.example.tubes_2.fragments.surfaceView.GameView;
import com.example.tubes_2.model.Attack;
import com.example.tubes_2.model.Ship;
import com.example.tubes_2.presenter.GameStatus;
import com.example.tubes_2.template.DifficultyTemplate;

import java.util.List;

/**
 * A simple {@link Fragment} subclass.
 */
public class GameFragment extends Fragment {
    DrawerThread drawerThread;
    LogicThread logicThread;

    GameView gameView;

    ImageView playerView;
    ImageView enemyView;

    GameStatus gameStatus;

    public GameFragment() {
        // Required empty public constructor
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_game, container, false);

        // this.difficulty = this.getArguments().getParcelable("difficulty");

        this.gameStatus = new GameStatus(this, null);

        LinearLayout gameWrapper = view.findViewById(R.id.gameView);

        this.gameView = new GameView(this.getContext(), this);

        gameWrapper.addView(this.gameView);

        this.playerView = view.findViewById(R.id.playerView);
        this.enemyView = view.findViewById(R.id.enemyView);

        return view;
    }

    public void initializeGame() {
        this.gameStatus.initializeGame();
    }

    public void startGame() {
        this.drawerThread = new DrawerThread(this);

        this.drawerThread.run();
    }

    public void endGame() {
        this.gameStatus.endGame();
    }

    public static GameFragment newInstance(DifficultyTemplate difficulty) {
        GameFragment fragment = new GameFragment();

        Bundle args = new Bundle();
        args.putParcelable("difficulty", difficulty);
        fragment.setArguments(args);

        return fragment;
    }

    public GameView getGameView() {
        return gameView;
    }
}

фрагмент_игры.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:weightSum="7">

    <androidx.coordinatorlayout.widget.CoordinatorLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="6">

        <LinearLayout
            android:orientation="horizontal"
            android:id="@+id/gameView"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />

        <com.google.android.material.floatingactionbutton.FloatingActionButton
            android:id="@+id/fab"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="bottom|start"
            android:layout_margin="@dimen/medium_margin"
            android:backgroundTint="@color/flame_off"
            app:borderWidth="0dp"
            android:src="@drawable/ic_iconmonstr_whats_hot_2" />
    </androidx.coordinatorlayout.widget.CoordinatorLayout>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:orientation="horizontal"
        android:layout_weight="1"
        android:background="@color/bgSmoke"
        android:padding="@dimen/small_padding"
        android:weightSum="3">
        <LinearLayout
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:orientation="vertical"
            android:layout_weight="1">
            <TextView
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:gravity="center"
                android:textSize="@dimen/label_size"
                android:text="@string/player_label"/>
            <TextView
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:gravity="center"
                android:textSize="@dimen/label_size"
                android:text="@string/enemy_label" />
        </LinearLayout>
        <LinearLayout
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:orientation="vertical"
            android:layout_weight="2">
            <ImageView
                android:layout_width="match_parent"
                android:layout_height="0dp"
                android:layout_margin="@dimen/small_margin"
                android:id="@+id/playerView"
                android:layout_weight="1" />
            <ImageView
                android:layout_width="match_parent"
                android:layout_height="0dp"
                android:layout_margin="@dimen/small_padding"
                android:id="@+id/enemyView"
                android:layout_weight="1" />
        </LinearLayout>
    </LinearLayout>
</LinearLayout>

GameView.java

package com.example.tubes_2.fragments.surfaceView;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.util.AttributeSet;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

import com.example.tubes_2.fragments.GameFragment;

public class GameView extends SurfaceView implements SurfaceHolder.Callback {
    GameFragment gameFragment;

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

        this.setAlpha(0);
        this.setZOrderOnTop(true);

        this.getHolder().addCallback(this);
    }

    public GameView(Context context, AttributeSet attributeSet) {
        super(context, attributeSet);

        this.setAlpha(0);
        this.setZOrderOnTop(true);

        getHolder().addCallback(this);
    }

    public GameView(Context ctx, GameFragment fragment) {
        super(ctx);
        this.gameFragment = fragment;

        this.setAlpha(0);
        this.setZOrderOnTop(true);

        this.getHolder().addCallback(this);
    }

    @Override
    public void surfaceCreated(SurfaceHolder surfaceHolder) {
        this.gameFragment.initializeGame();
        this.gameFragment.startGame();
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder surfaceHolder) {

    }

    @Override
    public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {
        // do nothing atm
    }

    @Override
    protected void onDraw(Canvas canvas) {
        canvas.drawColor(Color.WHITE, PorterDuff.Mode.CLEAR);

        super.onDraw(canvas);
    }
}

И, наконец, DrawerThread.java

package com.example.tubes_2.fragments;

import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.widget.ImageView;

import com.example.tubes_2.R;
import com.example.tubes_2.fragments.surfaceView.GameView;
import com.example.tubes_2.model.Ship;
import com.example.tubes_2.presenter.GameStatus;

public class DrawerThread implements Runnable {
    GameFragment game;

    GameView gameView;
    ImageView playerView, enemyView;

    Bitmap playerBitmap, enemyBitmap;

    long previousTime, fps;

    public DrawerThread(GameFragment game) {
        this.previousTime = 0;
        this.fps = 60; // PC MASTER RACE, MOBILE PEASANTS!!!
        this.game = game;

        this.gameView = game.gameView;
        this.playerView = game.playerView;
        this.enemyView = game.enemyView;

        Resources res = game.getResources();

        this.playerBitmap = BitmapFactory.decodeResource(res, R.drawable.player_ship);
        this.enemyBitmap = BitmapFactory.decodeResource(res, R.drawable.enemy_ship);
    }

    @Override
    public void run() {
        GameStatus status = this.game.gameStatus;
        SurfaceHolder gameHolder = this.gameView.getHolder();

        while (status.getGameState()) {
            long currentTimeMillis = System.currentTimeMillis();
            long elapsedTimeMs = currentTimeMillis - previousTime;
            long sleepTimeMs = (long) (1000f/ fps - elapsedTimeMs);

            Canvas gameCanvas = gameHolder.lockCanvas();

            try {
                if (gameCanvas == null) {
                    Thread.sleep(1);

                    continue;
                } else if (status.getCountdown() > 0) {
                    Paint pt = new Paint();
                    pt.setColor(Color.BLACK);
                    pt.setTextSize(48);

                    int xPos = (gameCanvas.getWidth() / 2);
                    int yPos = (int) ((gameCanvas.getHeight() / 2) - ((pt.descent() + pt.ascent()) / 2));

                    gameCanvas.drawText(Integer.toString(status.getCountdown()), xPos, yPos, pt);

                    // just decrement here
                    status.reduceCountdown();

                    gameHolder.unlockCanvasAndPost(gameCanvas);

                    Thread.sleep(1000);

                    continue;
                } else if (sleepTimeMs > 0) {
                    Thread.sleep(sleepTimeMs);
                }

                synchronized (gameHolder) {
                    /*
                    gameCanvas.drawBitmap(this.playerBitmap, this.game.player.getPositionX(), this.game.player.getPositionY(), null);
                    gameCanvas.drawBitmap(this.enemyBitmap, this.game.enemy.getPositionX(), this.game.enemy.getPositionY(), null);
                    */
                }

                gameHolder.unlockCanvasAndPost(gameCanvas);
                this.previousTime = currentTimeMillis;
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    private double getPercentageWidth(Ship ship, SurfaceView view) {
        return (double)ship.getHealth() / (double)view.getWidth();
    }
}

Примечание. Я МОГУ проверить, что поток действительно запущен, я зарегистрировал его.

РЕДАКТИРОВАТЬ: Я МОГУ проверить, что я правильно позвонил GameFragment, проблема возникает, когда я запускаю DrawerThread.

Любая помощь будет оценена. Спасибо!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...