Android游戏崩溃了FATAL EXCEPTION主要版本

时间:2017-04-03 16:33:10

标签: java android

我的应用程序有2个活动主菜单和游戏活动。你点击播放开始玩游戏,当你死了你可以点击返回去主菜单。出于某种原因,当我第三次点击播放(意味着我已经死了并且两次返回主菜单)时,游戏因此错误而崩溃。

FATAL EXCEPTION: main
 Process: com.example.jordanschanzenbach.myapplication, PID: 1875
          java.lang.OutOfMemoryError: Failed to allocate a 360012 byte allocation with 79976 free bytes and 78KB until OOM
          at dalvik.system.VMRuntime.newNonMovableArray(Native Method)
          at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
          at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:700)
          at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:535)
          at android.graphics.BitmapFactory.decodeResource(BitmapFactory.java:558)
          at android.graphics.BitmapFactory.decodeResource(BitmapFactory.java:588)
          at com.example.jordanschanzenbach.myapplication.Obstacle.<init>(Obstacle.java:44)
          at com.example.jordanschanzenbach.myapplication.ObstacleManager.populateObstacles(ObstacleManager.java:57)
          at com.example.jordanschanzenbach.myapplication.ObstacleManager.<init>(ObstacleManager.java:38)
          at com.example.jordanschanzenbach.myapplication.GamePlayScene.<init>(GamePlayScene.java:41)
          at com.example.jordanschanzenbach.myapplication.GamePanel.<init>(GamePanel.java:29)
          at com.example.jordanschanzenbach.myapplication.MainActivity.onCreate(MainActivity.java:27)

这不是整个错误消息,但我想我给了你所需要的东西。现在我试图为障碍物制作动画,而不仅仅是黑色矩形,但由于某种原因,尖峰不会显示,我认为它可能与我收到的错误相对应。但我不明白为什么尖峰不会显示,因为我为我的播放器使用相同的动画代码。

这是我的障碍的代码

public class Obstacle implements GameObject
{

private Rect rectangle;
private Rect rectangle2;
private int color;

private Animation falling;
private Animation fallingStill;
private Animation fallingAgain;
private AnimationManagerObstacle animationManagerObstacle;

public Rect getRectangle()
{
    return rectangle;
}

public void IncrementY(float y )
{
    rectangle.top += y;
    rectangle.bottom += y;
    rectangle2.top += y;
    rectangle2.bottom += y;
}

public Obstacle(int rectHeight, int color, int startX, int startY, int playerGap)
{
    this.color = color;

    BitmapFactory bitfac = new BitmapFactory();
    Bitmap fallings = bitfac.decodeResource(GlobalVariables.CURRENT_CONTEXT.getResources(), R.drawable.spikesupsidedown);
    Bitmap fallingStills = bitfac.decodeResource(GlobalVariables.CURRENT_CONTEXT.getResources(), R.drawable.spikesupsidedown);
    Bitmap fallingAgains = bitfac.decodeResource(GlobalVariables.CURRENT_CONTEXT.getResources(), R.drawable.spikesupsidedown);

    falling = new Animation(new Bitmap[]{fallings}, 2);
    fallingStill = new Animation(new Bitmap[]{fallings, fallingStills}, 0.5f);
    fallingAgain = new Animation(new Bitmap[]{fallings, fallingAgains}, 0.5f);

    animationManagerObstacle = new AnimationManagerObstacle(new Animation[]{falling, fallingStill, fallingAgain});

    rectangle = new Rect(0, startY, startX, startY + rectHeight);
    rectangle2 = new Rect(startX + playerGap, startY, GlobalVariables.SCREEN_WIDTH, startY + rectHeight);
}

public boolean playerCollide(RectPlayer player)
{
    return Rect.intersects(rectangle, player.getRectangle()) || Rect.intersects(rectangle2, player.getRectangle());

}

@Override
public void draw(Canvas canvas)
{
    Paint paint = new Paint();
    paint.setColor(color);

    animationManagerObstacle.draw(canvas, rectangle);

    canvas.drawRect(rectangle, paint);
    canvas.drawRect(rectangle2, paint);
}

@Override
public void update()
{
    animationManagerObstacle.update();
}

public void update(Point point)
{
    float oldTop = rectangle.top;

    rectangle.set(point.x - rectangle.width() / 2,
            point.y - rectangle.height() / 2,
            point.x + rectangle.width() / 2,
            point.y + rectangle.height() / 2);

    int state = 0;
    if (rectangle.left - oldTop > 1)
    {
        state = 1;
    }
    else if (rectangle.left - oldTop < 2)
    {
        state = 2;
    }

    animationManagerObstacle.playAnim(state);
    animationManagerObstacle.update();

}

}

这是错误消息指向的行

Bitmap fallings = bitfac.decodeResource(GlobalVariables.CURRENT_CONTEXT.getResources(), R.drawable.spikesupsidedown);

这是我的障碍经理,我添加并显示障碍

public class ObstacleManager
{

private ArrayList<Obstacle> obstacles;
private int playerGap;
private int obstacleGap;
private int obstacleHeight;
private int color;

private long startTime;
private long initTime;

private int score = 0;

public ObstacleManager(int playerGap, int obstacleGap, int obstacleHeight, int color)
{
    this.playerGap = playerGap;
    this.obstacleGap = obstacleGap;
    this.obstacleHeight = obstacleHeight;
    this.color = color;

    startTime = initTime = System.currentTimeMillis();

    obstacles = new ArrayList<>();

    populateObstacles();
}

public boolean playerCollide(RectPlayer player)
{
    for(Obstacle ob : obstacles)
    {
        if(ob.playerCollide(player))
            return true;
    }
    return false;
}

private void populateObstacles()
{
    int currY = -5 * GlobalVariables.SCREEN_HEIGHT / 4;
    while(currY < 0)
    {
        int xStart = (int)(Math.random()*(GlobalVariables.SCREEN_WIDTH - playerGap));
        obstacles.add(new Obstacle(obstacleHeight, color, xStart, currY, playerGap));
        currY += obstacleHeight + obstacleGap;
    }
}

public void update()
{
    if (GlobalVariables.GAMEOVER)
    {
        for (int i = 0; i < 3; i++)
        {
            obstacles.remove(obstacles.size() - 2);
        }
    }

    int elapsedTime = (int)(System.currentTimeMillis() - startTime);
    startTime = System.currentTimeMillis();
    float speed = (float)(Math.sqrt((1 + startTime - initTime) / 1750.0)) * GlobalVariables.SCREEN_HEIGHT /17500.0f;
    for(Obstacle ob : obstacles)
    {
        ob.IncrementY(speed * elapsedTime);
    }
    if(obstacles.get(obstacles.size() - 1).getRectangle().top >= GlobalVariables.SCREEN_HEIGHT * 3/4)
    {
        int xStart = (int)(Math.random()*(GlobalVariables.SCREEN_WIDTH - playerGap));
        obstacles.add(0, new Obstacle(obstacleHeight, color, xStart,
                obstacles.get(0).getRectangle().top - obstacleHeight - obstacleGap, playerGap));
        obstacles.remove(obstacles.size() - 1);
        score++;

        if (score > GlobalVariables.HIGHSCORE)
            GlobalVariables.HIGHSCORE = score;
    }
}

public void draw(Canvas canvas)
{
    for(Obstacle ob : obstacles)
        ob.draw(canvas);

    Paint paint = new Paint();
    paint.setTextSize(100);
    paint.setColor(Color.RED);
    canvas.drawText("" + score, 50, 50 + paint.descent() - paint.ascent(), paint);
    canvas.drawText("HighScore: " + GlobalVariables.HIGHSCORE, GlobalVariables.SCREEN_WIDTH  / 2 + 50, 50 + paint.descent() - paint.ascent(), paint);
}
}

这是我的动画经理

public class AnimationManager
{
private Animation[] animations;
private int animationsIndex = 0;

public AnimationManager(Animation[] animations)
{
    this.animations = animations;
}

public void playAnim(int index)
{
    for (int i = 0; i < animations.length; i++)
    {
        if (i == index)
        {
            if (!animations[index].isPlaying())
            {
                animations[i].play();
            }
        }
        else
        {
            animations[i].stop();
        }
    }
    animationsIndex = index;
}

public void draw(Canvas canvas, Rect rect)
{
    if (animations[animationsIndex].isPlaying())
    {
        animations[animationsIndex].draw(canvas, rect);
    }
}

public void update()
{
    if (animations[animationsIndex].isPlaying())
    {
        animations[animationsIndex].update();
    }
}
}

最后是我的动画类

public class Animation
{
private Bitmap[] frames;
private int frameIndex;

private boolean isPlaying = false;
public boolean isPlaying()
{
    return isPlaying;
}

public void play()
{
    isPlaying = true;
    frameIndex = 0;
    lastFrame = System.currentTimeMillis();
}

public void stop()
{
    isPlaying = false;
}

private float frameTime;
private long lastFrame;

public Animation(Bitmap[] frames, float animTime)
{
    this.frames = frames;
    frameIndex = 0;

    frameTime = animTime / frames.length;

    lastFrame = System.currentTimeMillis();
}

public void draw(Canvas canvas, Rect destination)
{
    if (!isPlaying)
        return;

    scaleRect(destination);

    canvas.drawBitmap(frames[frameIndex], null, destination, new Paint());
}

private void scaleRect(Rect rect)
{
    float whRatio = (float)(frames[frameIndex].getWidth() / frames[frameIndex].getHeight());

    if (rect.width() > rect.height())
    {
        rect.left = rect.right - (int)(rect.height() * whRatio);
    }
    else
    {
        rect.top = rect.bottom - (int)(rect.width() * (1 / whRatio));
    }
}

public void update()
{
    if (!isPlaying)
        return;

    if (System.currentTimeMillis() - lastFrame > frameTime * 1000)
    {
        frameIndex++;

        if (frameIndex >= frames.length)
            frameIndex = 0;

        lastFrame = System.currentTimeMillis();
    }
}
}

我认为你不一定需要这一切,但以防万一:)。感谢任何改进或帮助的评论。

1 个答案:

答案 0 :(得分:0)

OutOfMemoryError基本上意味着你试图使用更多内存。在此特定示例中,您(位图)尝试分配360KB,但您只能分配78KB。您可能在某处出现内存泄漏,或者您的位图可能太大。我认为你的位图可能会泄漏内存。我不是Android专家。

我建议您在Obstacle中创建方法,例如recycle或类似的方式。然后,每次从Obstacle obstacles中删除ObstacleManager时,都会调用该方法。在该方法中,您应该旨在回收所有不再使用的位图。我是通过在您的每个动画上调用Animation#recycle或致电AnimationManagerObstacle#recycle来实现此目的的。 (Animation#recycle会在recycle的每一个上拨打frames