游戏开发锁画布错误

时间:2017-10-20 17:15:59

标签: java android game-engine

我不断将错误画到画布上 Error

当我尝试在用户移动操纵杆后向画布绘制画布时,错误仍然发生 它总是写我“无法锁定帆布,帆布已锁定”

我是游戏开发方面的初学者而且很抱歉,如果您需要更多详细信息,而且我会向您发送更多信息,那么问题有点不清楚

主要课程 - 主要活动

package app.shahardagan.Raven;

import android.graphics.Point;
import android.os.Bundle;
import android.app.Activity;
import android.view.Display;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.ImageView;
import android.widget.RelativeLayout;

public class Main extends Activity {
RelativeLayout layout_joystick;
ImageView image_joystick, image_border;
GameEngine gameEngine;

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // Get a Display object to access screen details
    Display display = getWindowManager().getDefaultDisplay();
    // Load the resolution into a Point object
    Point size = new Point();
    size.set(display.getWidth(),display.getHeight());
    layout_joystick = (RelativeLayout)findViewById(R.id.layout_joystick);
    gameEngine = new GameEngine(this,size.x,size.y);
    setContentView(gameEngine);
}

@Override
protected void onResume(){
    super.onResume();

    gameEngine.resume();
}

@Override
protected void onPause(){
    super.onPause();

    gameEngine.pause();
}
}

GameEngine类 - 负责绘制玩家并更新游戏

package app.shahardagan.Raven;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.drawable.Drawable;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.ImageView;
import android.widget.RelativeLayout;

public class GameEngine extends SurfaceView implements Runnable {
JoyStickClass js;
// This is our thread
private Thread gameThread = null;

// This is new. We need a SurfaceHolder
// When we use Paint and Canvas in a thread
// We will see it in action in the draw method soon.
private SurfaceHolder ourHolder;

// A boolean which we will set and unset
// when the game is running- or not.
private volatile boolean playing;

// Game is paused at the start
private boolean paused = true;

// A Canvas and a Paint object
private Canvas canvas;
private Paint paint;

// How wide and high is the screen?
private int screenX;
private int screenY;

// This variable tracks the game frame rate
private long fps;

// This is used to help calculate the fps
private long timeThisFrame;
private Context context;

private Player player;

private Drawable playerImage;


public GameEngine(Context context, int x, int y) {
    // This calls the default constructor to setup the rest of the object
    super(context);
    this.context = context;
    // Initialize ourHolder and paint objects
    ourHolder = getHolder();
    paint = new Paint();

    // Initialize screenX and screenY because x and y are local
    screenX = x;
    screenY = y;
    prepareLevel();
}
private void prepareLevel(){
    player = new Player(context,screenX,screenY);
}


public void PlayerControls(Context context,RelativeLayout layout_joystick, ImageView image_joystick, ImageView image_border){
    js = new JoyStickClass(context, layout_joystick, R.drawable.image_button);
    js.setStickSize(150, 150);
    js.setLayoutSize(500, 500);
    js.setLayoutAlpha(150);
    js.setStickAlpha(100);
    js.setOffset(90);
    js.setMinimumDistance(50);
    layout_joystick.setOnTouchListener(new View.OnTouchListener() {
        public boolean onTouch(View arg0, MotionEvent arg1) {
            js.drawStick(arg1);
            if(arg1.getAction() == MotionEvent.ACTION_DOWN || arg1.getAction() == MotionEvent.ACTION_MOVE) {
                int direction = js.get8Direction();
                if(direction == JoyStickClass.STICK_UP) {

                } else if(direction == JoyStickClass.STICK_UPRIGHT) {
                    player.setMovementState(Player.UP);
                } else if(direction == JoyStickClass.STICK_RIGHT) {

                } else if(direction == JoyStickClass.STICK_DOWNRIGHT) {

                } else if(direction == JoyStickClass.STICK_DOWN) {

                } else if(direction == JoyStickClass.STICK_DOWNLEFT) {

                } else if(direction == JoyStickClass.STICK_LEFT) {

                } else if(direction == JoyStickClass.STICK_UPLEFT) {

                } else if(direction == JoyStickClass.STICK_NONE) {

                }
            } else if(arg1.getAction() == MotionEvent.ACTION_UP) {

            }
            return true;
        }
    });
}

// Runs when the OS calls onPause on BreakoutActivity method
public void pause() {
    playing = false;
    try {
        gameThread.join();
    } catch (InterruptedException e) {
        Log.e("Error:", "joining thread");
    }
}

// Runs when the OS calls onResume on BreakoutActivity method
public void resume() {
    playing = true;
    gameThread = new Thread(this);
    gameThread.start();
}

@Override
public void run() {
    while (playing) {

        // Capture the current time in milliseconds in startFrameTime
        long startFrameTime = System.currentTimeMillis();

        // Update the frame
        // Update the frame
        if(!paused){
            update();
        }

        // Draw the frame
        draw();

        // Calculate the fps this frame
        // We can then use the result to
        // time animations and more.
        timeThisFrame = System.currentTimeMillis() - startFrameTime;
        if (timeThisFrame >= 1) {
            fps = 1000 / timeThisFrame;
        }

    }
}

private void draw() {
    // Make sure our drawing surface is valid or game will crash
    if (ourHolder.getSurface().isValid()) {
        // Lock the canvas ready to draw
        canvas = ourHolder.lockCanvas();
        // Draw the background color
        canvas.drawColor(Color.argb(255, 26, 128, 182));
        // Draw everything to the screen
        // Choose the brush color for drawing
        paint.setColor(Color.argb(255, 255, 255, 255));
        canvas.drawBitmap(player.getBitmap(),player.getX(),screenY - player.getHeight(),paint);

    }
}

private void update() {
    player.update(fps);

}
}

玩家类 - 玩家类方法

 package app.shahardagan.Raven;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.RectF;

public class Player {

// RectF is an object that holds four coordinates - just what we need
private RectF rect;
private Bitmap bitmap;
// How long will our paddle will be
private float length;
private float height;
// X is the far left of the rectangle which forms our paddle
private float x;
private float y;

// Which ways can the player move
final int STOPPED = 0;
public static final int UP = 1;
public static final int UPRIGHT = 2;
public static final int RIGHT = 3;
public static final int DOWNRIGHT = 4;
public static final int DOWN = 5;
public static final int DOWNLEFT = 6;
public static final int LEFT = 7;
public static final int UPLEFT = 8;
// Is the paddle moving and in which direction
private int playerMoving = STOPPED;
private int playerSpeed;

public Player(Context context,int screenX, int screenY){
    rect = new RectF();
    length =screenX/10;
    height = screenX/10;
    x = screenX;
    y= 0;
    bitmap = BitmapFactory.decodeResource(context.getResources(),R.drawable.eagle_fly);
    bitmap = Bitmap.createScaledBitmap(bitmap,(int)length,(int)height,false);
    playerSpeed = 350;
}

public RectF getRect(){
    return rect;
}

public Bitmap getBitmap(){
    return bitmap;
}
public float getX(){ return x; }
public float getHeight(){return height;}
private float getLength(){return length;}
public void setMovementState(int state){
    playerMoving = state;
}

void update(long fps){
    if(playerMoving == LEFT){
        x = x - playerSpeed / fps;
    }

    if(playerMoving == RIGHT){
        x = x + playerSpeed / fps;
    }
    rect.top = y;
    rect.bottom = y+ height;
    rect.left = x;
    rect.right = x + length;

}

}

欢乐棒课

 package app.shahardagan.Raven;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;

public class JoyStickClass {
  public static final int STICK_NONE = 0;
  public static final int STICK_UP = 1;
  public static final int STICK_UPRIGHT = 2;
  public static final int STICK_RIGHT = 3;
  public static final int STICK_DOWNRIGHT = 4;
  public static final int STICK_DOWN = 5;
  public static final int STICK_DOWNLEFT = 6;
  public static final int STICK_LEFT = 7;
  public static final int STICK_UPLEFT = 8; 

  private int STICK_ALPHA = 200;
  private int LAYOUT_ALPHA = 200;
  private int OFFSET = 0;

  private Context mContext;
  private ViewGroup mLayout;
  private LayoutParams params;
  private int stick_width, stick_height;

  private int position_x = 0, position_y = 0, min_distance = 0;
  private float distance = 0, angle = 0;

  private DrawCanvas draw;
  private Paint paint;
  private Bitmap stick;

  private boolean touch_state = false;

 public JoyStickClass (Context context, ViewGroup layout, int stick_res_id) {
    mContext = context;

    stick = BitmapFactory.decodeResource(mContext.getResources(),
            stick_res_id);

    stick_width = stick.getWidth();
    stick_height = stick.getHeight();

    draw = new DrawCanvas(mContext);
    paint = new Paint();
    mLayout = layout;
    params = mLayout.getLayoutParams();
}

public void drawStick(MotionEvent arg1) {
    position_x = (int) (arg1.getX() - (params.width / 2));
    position_y = (int) (arg1.getY() - (params.height / 2));
    distance = (float) Math.sqrt(Math.pow(position_x, 2) + Math.pow(position_y, 2));
    angle = (float) cal_angle(position_x, position_y);


    if(arg1.getAction() == MotionEvent.ACTION_DOWN) {
        if(distance <= (params.width / 2) - OFFSET) {
            draw.position(arg1.getX(), arg1.getY());
            draw();
            touch_state = true;
        }
    } else if(arg1.getAction() == MotionEvent.ACTION_MOVE && touch_state) {
        if(distance <= (params.width / 2) - OFFSET) {
            draw.position(arg1.getX(), arg1.getY());
            draw();
        } else if(distance > (params.width / 2) - OFFSET){
            float x = (float) (Math.cos(Math.toRadians(cal_angle(position_x, position_y))) * ((params.width / 2) - OFFSET));
            float y = (float) (Math.sin(Math.toRadians(cal_angle(position_x, position_y))) * ((params.height / 2) - OFFSET));
            x += (params.width / 2);
            y += (params.height / 2);
            draw.position(x, y);
            draw();
        } else {
            mLayout.removeView(draw);
        }
    } else if(arg1.getAction() == MotionEvent.ACTION_UP) {
        mLayout.removeView(draw);
        touch_state = false;
    }
}

public int[] getPosition() {
    if(distance > min_distance && touch_state) {
        return new int[] { position_x, position_y };
    }
    return new int[] { 0, 0 };
}

public int getX() {
    if(distance > min_distance && touch_state) {
        return position_x;
    }
    return 0;
}

public int getY() {
    if(distance > min_distance && touch_state) {
        return position_y;
    }
    return 0;
}

public float getAngle() {
    if(distance > min_distance && touch_state) {
        return angle;
    }
    return 0;
}

public float getDistance() {
    if(distance > min_distance && touch_state) {
        return distance;
    }
    return 0;
}

public void setMinimumDistance(int minDistance) {
    min_distance = minDistance;
}

public int getMinimumDistance() {
    return min_distance;
}

public int get8Direction() {
    if(distance > min_distance && touch_state) {
        if(angle >= 247.5 && angle < 292.5 ) {
            return STICK_UP;
        } else if(angle >= 292.5 && angle < 337.5 ) {
            return STICK_UPRIGHT;
        } else if(angle >= 337.5 || angle < 22.5 ) {
            return STICK_RIGHT;
        } else if(angle >= 22.5 && angle < 67.5 ) {
            return STICK_DOWNRIGHT;
        } else if(angle >= 67.5 && angle < 112.5 ) {
            return STICK_DOWN;
        } else if(angle >= 112.5 && angle < 157.5 ) {
            return STICK_DOWNLEFT;
        } else if(angle >= 157.5 && angle < 202.5 ) {
            return STICK_LEFT;
        } else if(angle >= 202.5 && angle < 247.5 ) {
            return STICK_UPLEFT;
        }
    } else if(distance <= min_distance && touch_state) {
        return STICK_NONE;
    }
    return 0;
}

public int get4Direction() {
    if(distance > min_distance && touch_state) {
        if(angle >= 225 && angle < 315 ) {
            return STICK_UP;
        } else if(angle >= 315 || angle < 45 ) {
            return STICK_RIGHT;
        } else if(angle >= 45 && angle < 135 ) {
            return STICK_DOWN;
        } else if(angle >= 135 && angle < 225 ) {
            return STICK_LEFT;
        }
    } else if(distance <= min_distance && touch_state) {
        return STICK_NONE;
    }
    return 0;
}

public void setOffset(int offset) {
    OFFSET = offset;
}

public int getOffset() {
    return OFFSET;
}

public void setStickAlpha(int alpha) {
    STICK_ALPHA = alpha;
    paint.setAlpha(alpha);
}

public int getStickAlpha() {
    return STICK_ALPHA;
}

public void setLayoutAlpha(int alpha) {
    LAYOUT_ALPHA = alpha;
    mLayout.getBackground().setAlpha(alpha);
}

public int getLayoutAlpha() {
    return LAYOUT_ALPHA;
}

public void setStickSize(int width, int height) {
    stick = Bitmap.createScaledBitmap(stick, width, height, false);
    stick_width = stick.getWidth();
    stick_height = stick.getHeight();
}

public void setStickWidth(int width) {
    stick = Bitmap.createScaledBitmap(stick, width, stick_height, false);
    stick_width = stick.getWidth();
}

public void setStickHeight(int height) {
    stick = Bitmap.createScaledBitmap(stick, stick_width, height, false);
    stick_height = stick.getHeight();
}

public int getStickWidth() {
    return stick_width;
}

public int getStickHeight() {
    return stick_height;
}

public void setLayoutSize(int width, int height) {
    params.width = width;
    params.height = height;
}

public int getLayoutWidth() {
    return params.width;
}

public int getLayoutHeight() {
    return params.height;
}

private double cal_angle(float x, float y) {
    if(x >= 0 && y >= 0)
        return Math.toDegrees(Math.atan(y / x));
    else if(x < 0 && y >= 0)
        return Math.toDegrees(Math.atan(y / x)) + 180;
    else if(x < 0 && y < 0)
        return Math.toDegrees(Math.atan(y / x)) + 180;
    else if(x >= 0 && y < 0) 
        return Math.toDegrees(Math.atan(y / x)) + 360;
    return 0;
}

private void draw() {
    try {
        mLayout.removeView(draw);
    } catch (Exception e) { }
    mLayout.addView(draw);
}

private class DrawCanvas extends View{
    float x, y;

    private DrawCanvas(Context mContext) {
         super(mContext);
     }

     public void onDraw(Canvas canvas) {
         canvas.drawBitmap(stick, x, y, paint);
     }

     private void position(float pos_x, float pos_y) {
        x = pos_x - (stick_width / 2);
        y = pos_y - (stick_height / 2);
     }
 }
}

1 个答案:

答案 0 :(得分:0)

在draw()方法中,您将锁定Canvas,但在完成绘制后不会解锁Canvas。因此,当您重新进入draw方法时,Canvas仍然会锁定前一次调用。

完成绘图后,您可能需要添加unlockCanvasAndPost(Canvas canvas)。请参阅完整文档here