Getting a NullPointerException on UpdateThread when adding a Sprite
I'm creating my first game in AndEngine and I am simply trying to add a Sprite to my GameScene class. I've been tinkering with it for hours now as my application kept crashing after my splash screen, which is supposed to load my GameScene afterwards. I've narrowed it down to these of code in my drawPanel() method:
selectPanel[0] = new Sprite(0, 0, resourceManager.ballTextureRegionArray[0], vbom) {
@Override
protected void preDraw(GLState pGLState, Camera pCamera) {
super.preDraw(pGLState, pCamera);
pGLState.enableDither();
}
};
selectPanel[0].setPosition(240, 400);
attachChild(selectPanel[0]);
Here is my ResourceManager class where I loaded the ball texture:
ballTexture = new BitmapTextureAtlas(act.getTextureManager(), 64, 576);
ballTextureRegionArray[0] = BitmapTextureAtlasTextureRegionFactory
.createFromAsset(ballTexture, act, "red_ball.png", 0, 0);
ballTextureRegionArray[1] = BitmapTextureAtlasTextureRegionFactory
.createFromAsset(ballTexture, act, "blue_ball.png", 0, 64);
ballTextureRegionArray[2] = BitmapTextureAtlasTextureRegionFactory
.createFromAsset(ballTexture, act, "green_ball.png", 0, 128);
ballTextureRegionArray[3] = BitmapTextureAtlasTextureRegionFactory
.createFromAsset(ballTexture, act, "purple_ball.png", 0, 192);
ballTextureRegionArray[4] = BitmapTextureAtlasTextureRegionFactory
.createFromAsset(ballTexture, act, "yellow_ball.png", 0, 256);
ballTextureRegionArray[5] = BitmapTextureAtlasTextureRegionFactory
.createFromAsset(ballTexture, act, "orange_ball.png", 0, 320);
ballTextureRegionArray[6] = BitmapTextureAtlasTextureRegionFactory
.createFromAsset(ballTexture, act, "black_ball.png", 0, 384);
ballTextureRegionArray[7] = BitmapTextureAtlasTextureRegionFactory
.createFromAsset(ballTexture, act, "white_ball.png", 0, 448);
ballTextureRegionArray[8] = BitmapTextureAtlasTextureRegionFactory
.createFromAsset(ballTexture, act, "select_ball.png", 0, 512);
ballTexture.load(); // load ballTexture to the scene
... and of course the error.
11-28 17:44:44.750: E/AndroidRuntime(2119): FATAL EXCEPTION: UpdateThread
11-28 17:44:44.750: E/AndroidRuntime(2119): java.lang.NullPointerException
11-28 17:44:44.750: E/AndroidRuntime(2119): at com.eklypze.android.mastermdhd.GameScene.drawPanel(GameScene.java:188)
11-28 17:44:44.750: E/AndroidRuntime(2119): at com.eklypze.android.mastermdhd.GameScene.createScene(GameScene.java:68)
11-28 17:44:44.750: E/AndroidRuntime(2119): at com.eklypze.android.mastermdhd.BaseScene.<init>(BaseScene.java:38)
11-28 17:44:44.750: E/AndroidRuntime(2119): at com.eklypze.android.mastermdhd.GameScene.<init>(GameScene.java:28)
11-28 17:44:44.750: E/AndroidRuntime(2119): at com.eklypze.android.mastermdhd.SceneManager.createGameScene(SceneManager.java:120)
11-28 17:44:44.750: E/AndroidRuntime(2119): at com.eklypze.android.mastermdhd.BaseActivity$1.onTimePassed(BaseActivity.java:84)
11-28 17:44:44.750: E/AndroidRuntime(2119): at org.andengine.engine.handler.timer.TimerHandler.onUpdate(TimerHandler.java:94)
11-28 17:44:44.750: E/AndroidRuntime(2119): at org.andengine.engine.handler.UpdateHandlerList.onUpdate(UpdateHandlerList.java:47)
11-28 17:44:44.750: E/AndroidRuntime(2119): at org.andengine.engine.Engine.onUpdateUpdateHandlers(Engine.java:618)
11-28 17:44:44.750: E/AndroidRuntime(2119): at org.andengine.engine.Engine.onUpdate(Engine.java:605)
11-28 17:44:44.750: E/AndroidRuntime(2119): at org.andengine.engine.Engine.onTickUpdate(Engine.java:568)
11-28 17:44:44.750: E/AndroidRuntime(2119): at org.andengine.engine.Engine$UpdateThread.run(Engine.java:858)
Here is my GameScene.java class:
package com.eklypze.android.mastermdhd;
import java.util.Random;
import javax.microedition.khronos.opengles.GL10;
import org.andengine.engine.camera.Camera;
import org.andengine.entity.modifier.AlphaModifier;
import org.andengine.entity.modifier.LoopEntityModifier;
import org.andengine.entity.scene.background.SpriteBackground;
import org.andengine.entity.sprite.Sprite;
import org.andengine.input.touch.TouchEvent;
import org.andengine.opengl.util.GLState;
import android.util.Log;
import com.eklypze.android.mastermdhd.SceneManager.SceneType;
public class GameScene extends BaseScene {
/*** DECLARATIONS ***/
/* Settings */
protected static final int CAMERA_WIDTH = 480;
protected static final int CAMERA_HEIGHT = 800;
/* Sprites */
Sprite[] selectPanel = new Sprite[8];
Sprite boardPieces[] = new Sprite[40];
Sprite bwPegs[] = new Sprite[10];
Sprite nextSpot; // "next spot" cursor
Sprite gameoverLose, gameoverWin; // REPLACE with scenes
/* Game Options */
private int turn = 0;
private int turnCounter = 0; // per line turn counter
private int currentX = 1;
private int currentY = 13;
private int[] code = new int[4]; // array to store generated code
private int[] codeCopy = new int[4]; // for black&white peg use
private int blackPegs = 0, whitePegs = 0;
// remember to take currentX-1 as the array indexes
private int[] currentXValues = new int[4];
// dummy variable when drawing selectPanel for touch *don't delete*
private int z = 0;
Boolean gameOver = false;
Boolean doublesAllowed = false;
/************************************
* ------------INHERITED------------
************************************/
@Override
/********************************
* createScene()
********************************/
public void createScene() {
// create scene with bgSprite background
setBackground(new SpriteBackground(resourceManager.bgSprite));
// STEP 1: Start a New Game
newGame();
// STEP 2: Draw selectPanel
drawPanel(); // debugging: game seems to work up until this point
}
@Override
/********************************
* onBackKeyPressed()
********************************/
public void onBackKeyPressed() {
System.exit(0);
}
@Override
/********************************
* getSceneType()
********************************/
public SceneType getSceneType() {
return SceneType.SCENE_GAME;
}
@Override
/********************************
* disposeScene()
********************************/
public void disposeScene() {
this.detachSelf();
this.dispose();
}
/************************************
* -----------GAME METHODS-----------
************************************/
/********************************
* newGame()
* Description: Initialize game
* settings for a new session.
********************************/
private void newGame() {
/* [START] Generate New Code Combination
for (int x = 0; x < 4; x++) {
Random r = new Random();
// if doubles is not allowed check if new generated number is
// a double, if yes, generate another number. NOTE: doubles are
// defaulted to 'OFF' until feature is added.
int randomNumber = r.nextInt(8); // why (7-0)+0?
Log.v("randomR", "Number generated is " + randomNumber);
code[x] = randomNumber;
// write to log (debugging)
Log.v("theCode", "Number generated for " + x + " is: " + code[x]
+ " (" + resourceManager.ballColours[randomNumber] + ")");
// if doubles is not allowed check if new generated number is
// a double, if yes, generate another number. NOTE: doubles are
// defaulted to 'OFF' until feature is added.
if (!doublesAllowed && x > 0) {
for (int y = x - 1; y >= 0; y--) {
// Log.v("theY", "y is "+y);
if (code[y] == randomNumber) {
x--;
}
}
}
} [END] Generate New Code Combination */
code = new int[] { 7, 1, 2, 3 };
Log.v("theCode", "The Code Is: " + code[0] + "," + code[1] + ","
+ code[2] + "," + code[3] + ".");
codeCopy = code.clone(); // copies code array for white/black peg use
}
/********************************
* drawPanel()
* Description: Draw the panels
* required for user selection.
********************************/
private void drawPanel() {
int column = 7; // constant?
int rowStart = 2;
/* [START] Draw Selection selectPanel
for (int i = 0; i < 8; i++) {
final int j = i;
selectPanel[i] = new Sprite(grid_xPixel(column),
grid_yPixel(rowStart),
resourceManager.ballTextureRegionArray[i], vbom) {
@Override
/* [START] Touch Detection
public boolean onAreaTouched(TouchEvent pSceneTouchEvent,
float pTouchAreaLocalX, float pTouchAreaLocalY) {
switch (pSceneTouchEvent.getAction()) {
// On Touch
case TouchEvent.ACTION_DOWN:
this.setScale(2.0f); // enlarge effect
z = j;
Log.v("thisIsZ", "Z: " + z);
break;
// On Move/Drag
case TouchEvent.ACTION_MOVE: {
/* to be implemented in the future
// this.setPosition(pSceneTouchEvent.getX() -
// this.getWidth()/2, pSceneTouchEvent.getY() -
// this.getHeight()/2);
break;
}
// On Release
case TouchEvent.ACTION_UP:
// z = j; // not needed
makeMove(z);
this.setScale(1.0f); // normal size
break;
}
return super.onAreaTouched(pSceneTouchEvent,
pTouchAreaLocalX, pTouchAreaLocalY);
}
[END] Touch Detection
}; */
// selectPanel[0] = new Sprite(200, 400,
// resourceManager.ballTextureRegionArray[0], vbom);
//attachChild(selectPanel[0]);
//registerTouchArea(selectPanel[i]);
selectPanel[0] = new Sprite(0, 0, resourceManager.ballTextureRegionArray[0], vbom) {
@Override
protected void preDraw(GLState pGLState, Camera pCamera) {
super.preDraw(pGLState, pCamera);
pGLState.enableDither();
}
};
selectPanel[0].setPosition(240, 400);
attachChild(selectPanel[0]);
//} /* [END] Draw Selection selectPanel */
// setTouchAreaBindingOnActionDownEnabled(true);
}
/********************************
* makeMove()
* Description: Allow the player
* to make their selection and
* display pegs as a result.
********************************/
private void makeMove(int inColor) {
boardPieces[turn] = new Sprite(grid_xPixel(currentX),
grid_yPixelBoard(currentY),
resourceManager.ballTextureRegionArray[inColor], vbom);
boardPieces[turn].setScale(0.75f); // set 75% size on board
// store current line, compare values to code and generate B/W pegs
currentXValues[currentX - 1] = inColor;
if (currentXValues[currentX - 1] == codeCopy[currentX - 1]) {
blackPegs++;
// dummy variable so this isn't counted again as a white peg
codeCopy[currentX - 1] = 999;
}
for (int i = 0; i < 4; i++) {
if ((currentXValues[currentX - 1] == codeCopy[i])) {
whitePegs++;
// dummy variable so this isn't counted again as a white peg
codeCopy[i] = 999;
}
}
/* log for debugging */
Log.v("pegs", "blackPegs: " + blackPegs);
Log.v("pegs", "whitePegs: " + whitePegs);
// Draw pieces to scene and advance to next turn & column
attachChild(boardPieces[turn]);
currentX++;
turn++;
// advance to next row, draw B/W pegs
if (currentX > 4) {
currentX = 1;
currentY--;
// Draw Pegs
drawBWPegs(blackPegs, whitePegs);
turnCounter++;
// Reset pegs for next line
blackPegs = 0;
whitePegs = 0;
// codeCopy is only used for counting black and white
// pegs per line to ensure all cases work
codeCopy = code.clone();
}
/* [START] Draw Blinking Cursor in Next Spot */
nextSpot = new Sprite(grid_xPixel(currentX),
grid_yPixelBoard(currentY),
resourceManager.ballTextureRegionArray[8], vbom);
nextSpot.setScale(0.75f);
nextSpot.setBlendFunction(GL10.GL_SRC_ALPHA,
GL10.GL_ONE_MINUS_SRC_ALPHA);
nextSpot.registerEntityModifier(new LoopEntityModifier(
new AlphaModifier(2, 0f, 1.0f)));
attachChild(nextSpot);
/* [END] Draw Blinking Cursor in Next Spot */
/* *
* GAME OVER (LOSE)
* If player reaches turn 40 and still has not received
* correct code, go to Game Over (Lose) scene.
* */
if (turn == 40) {
// NOTE: I will replace this with a Game Over scene.
GameOverWin(false);
Log.v("Game Over", "You Lose");
gameoverLose = new Sprite(CAMERA_WIDTH / 2 - 256,
CAMERA_HEIGHT / 2 - 64, resourceManager.loseTextureRegion,
vbom);
attachChild(gameoverLose);
}
}
/********************************
* GameOverWin()
* Description: Display GameOver
* image as a result of the user
* winning the game.
********************************/
private void GameOverWin(boolean win) {
// clear game
detachChildren();
turn = 0;
}
/********************************
* drawBWPegs()
* Description: Draw the black
* and white pegs to the scene
* based on game results.
********************************/
private void drawBWPegs(int numBlack, int numWhite) {
/* [START] if */
// do not display if no pegs were counted
if (numBlack > 0 || numWhite > 0) {
int pegScore = 0;
// determine pegScore
if (numBlack == 1 && numWhite == 0) {
pegScore = 0;
} else if (numBlack == 1 && numWhite == 2) {
pegScore = 1;
} else if (numBlack == 1 && numWhite == 3) {
pegScore = 2;
} else if (numBlack == 0 && numWhite == 1) {
pegScore = 3;
} else if (numBlack == 2 && numWhite == 0) {
pegScore = 4;
} else if (numBlack == 2 && numWhite == 2) {
pegScore = 5;
} else if (numBlack == 0 && numWhite == 2) {
pegScore = 6;
} else if (numBlack == 3 && numWhite == 0) {
pegScore = 7;
} else if (numBlack == 3 && numWhite == 1) {
pegScore = 8;
} else if (numBlack == 0 && numWhite == 3) {
pegScore = 9;
} else if (numBlack == 4 && numWhite == 0) {
pegScore = 10;
} else if (numBlack == 0 && numWhite == 4) {
pegScore = 11;
} /* [END] if */
// use pegScore to display corresponding image
bwPegs[turnCounter] = new Sprite(grid_xPixel(5),
grid_yPixelBoard(currentY + 1),
resourceManager.pegTextureRegionArray[pegScore], vbom);
bwPegs[turnCounter].setScale(0.80f);
attachChild(bwPegs[turnCounter]);
}
}
/********************************
* ---------GRID SYSTEM---------
********************************/
/************************************
* grid_xPixel()
* Description: Converts grid
* coordinates to pixel coordinates
* based on a 480 by 800 resolution
* screen. Needs to be updated.
************************************/
private int grid_xPixel(int x) {
int pixel = 0;
pixel = x * (CAMERA_WIDTH / 8 + 2) - 32;
return pixel;
}
/************************************
* grid_yPixel()
* Description: Y-grid for user
* selection panel.
************************************/
private int grid_yPixel(int y) {
int pixel = 0;
pixel = y * (CAMERA_HEIGHT / 10) - 32;
return pixel;
}
/************************************
* grid_yPixelBoard()
* Description: Y-grid for the main
* game board.
************************************/
private int grid_yPixelBoard(int y) {
int pixel = 0;
pixel = y * (CAMERA_HEIGHT / 15) - 32;
return pixel;
}
}
I apologize as I'm also new to StackOverflow and don't quite know how to format code properly. Also, if I'm missing important areas of code that are relevant to the question please let me know as I have so many lines of code and don't quite know where to start.
Thanks in advance!
Looking at your code I'd say that ballTextureRegionArray[0] was the null pointer, probably because it wasn't loaded in your resourceManager initialisation.
If your .png files are resources ie in the "res" directory not the "asset" directory you need to load with .createFromResource not .createFromAsset.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.