简体   繁体   English

Android游戏导致FAULT EXCEPTION主要崩溃

[英]Android game crashes FATAL EXCEPTION main

My app has 2 activities a main menu and a game play activity. 我的应用程序有两个活动,一个主菜单和一个游戏活动。 you click play to start the game play and when you die you can click back to go to the main menu. 单击播放即可开始游戏,死后可以单击返回主菜单。 For some reason when i click play for the third time (meaning ive died and went back to the main menu twice) the game crashes with this error. 由于某些原因,当我第三次单击播放时(意味着ive死了,两次回到主菜单),游戏因该错误而崩溃。

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)

that's not the entire error message but i think i gave you what you needed. 那不是全部错误信息,但我想我给了您您所需要的。 Now i tried to make an animation for the obstacles to be spikes instead of just black rectangles but for some reason the spikes will not display and i think it might correspond with the error i receive. 现在,我尝试制作一个动画,使障碍物成为尖峰而不只是黑色矩形,但由于某些原因,尖峰将不会显示,我认为这可能与我收到的错误相对应。 But i don't understand why the spikes wont display as i used the same code for the animation for my player. 但是我不明白为什么尖峰不会显示,因为我为播放器使用了相同的动画代码。

here is the code for my obstacle 这是我的障碍代码

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();

}

}

this is the line that the error message points to 这是错误消息指向的行

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

here is my obstacle manager where i add and display the obstacles 这是我的障碍管理器,我在其中添加和显示障碍

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);
}
}

here is my animation manager 这是我的动画经理

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();
    }
}
}

and finally my animation class 最后是我的动画课

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();
    }
}
}

i dont think you necessarily needed all that but just in case :). 我认为您不一定需要所有这些,但以防万一:)。 thanks for any comments to improve or help. 感谢您提出任何改进或帮助的意见。

OutOfMemoryError basically means that you tried to use more memory than you can. OutOfMemoryError基本上意味着您试图使用更多的内存。 In this specific example you (bitmap) tried to allocate 360KB though you could only allocate 78KB more. 在此特定示例中,您(位图)尝试分配360KB,尽管您只能再分配78KB。 You might have a memory leak somewhere or your bitmap might be too big. 您可能在某处内存泄漏,或者您的位图可能太大。 I think your Bitmaps might be leaking memory. 我认为您的位图可能正在泄漏内存。 I'm not an Android expert though. 我不是Android专家。

I'd recommend you to create a method in Obstacle like recycle or something along this way. 我建议您在Obstacle创建一种方法,例如recycle或类似的方式。 Then every time you remove Obstacle from obstacles in ObstacleManager call that method. 然后,每次你删除的时间ObstacleobstaclesObstacleManager调用该方法。 In that method you should aim to recycle all no longer used bitmaps. 在这种方法中,您应该致力于回收所有不再使用的位图。 I'd do it by calling either Animation#recycle on every of your animations or calling AnimationManagerObstacle#recycle . 我想通过调用做Animation#recycle在每次你的动画或致电AnimationManagerObstacle#recycle ( Animation#recycle would be meant to call recycle on every one of your frames .) Animation#recycle旨在在您的每一frames上调用recycle 。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM