Multiple sprites and animation problems - java

I'm trying to add multiple sprites to android game using an Array but at the minute only one will display and when I click it rather than it changing to the new sprite animation it freezes on the screen here is the code within my GameView.java and Sprite.java.
GameView.java:
/**
* This class takes care of surface for drawing and touches
*
*/
public class GameView extends SurfaceView implements SurfaceHolder.Callback {
/* Member (state) fields */
private GameLoopThread gameLoopThread;
private Paint paint; // Reference a paint object
/** The drawable to use as the background of the animation canvas */
private Bitmap mBackgroundImage;
private Sprite sprite;
private ArrayList<Sprite> spritesArrayList;
int SpriteAmount = 3;
private int hitCount;
private boolean GameOver = false;
/* For the countdown timer */
private long startTime; // Timer to count down from
private final long interval = 1 * 1000; // 1 sec interval
private CountDownTimer countDownTimer; // Reference to class
private boolean timerRunning = false;
private String displayTime; // To display time on the screen
public GameView(Context context) {
super(context);
spritesArrayList = new ArrayList<Sprite>();
// Focus must be on GameView so that events can be handled.
this.setFocusable(true);
// For intercepting events on the surface.
this.getHolder().addCallback(this);
mBackgroundImage = BitmapFactory.decodeResource(this.getResources(),
R.drawable.dbz);
}
/* Called immediately after the surface created */
public void surfaceCreated(SurfaceHolder holder) {
mBackgroundImage = Bitmap.createScaledBitmap(mBackgroundImage,
getWidth(), getHeight(), true);
// We can now safely setup the game start the game loop.
ResetGame();// Set up a new game up - could be called by a 'play again
// option'
gameLoopThread = new GameLoopThread(this.getHolder(), this);
gameLoopThread.running = true;
gameLoopThread.start();
}
// Sprite List
// To initialise/reset game
private void ResetGame() {
//sprite = new Sprite(this);
for (int P = 0; P < SpriteAmount; P++) {
spritesArrayList.add(sprite = new Sprite(this));
}
hitCount = 0;
GameOver = false;
/* Set paint details */
paint = new Paint();
paint.setColor(Color.WHITE);
paint.setTextSize(20);
// Set timer
startTime = 10;// Start at 10s to count down
// Create new object - convert startTime to milliseconds
countDownTimer = new MyCountDownTimer(startTime * 1000, interval);
countDownTimer.start();// Start it running
timerRunning = true;
}
// This class updates and manages the assets prior to drawing - called from
// the Thread
public void update() {
for (int P = 0; P < SpriteAmount; P++) {
GameOver = false;
spritesArrayList.get(P).update();
}
}
/**
* To draw the game to the screen This is called from Thread, so
* synchronisation can be done
*/
public void doDraw(Canvas canvas) {
canvas.drawBitmap(mBackgroundImage, 0, 0, null);
if (GameOver == false) {
sprite.draw(canvas);
} else if (GameOver == true) {
}
// Draw all the objects on the canvas
canvas.drawText("Hits Obtained =" + hitCount, 5, 25, paint);
canvas.drawText("Time Remaining =" + displayTime, 5, 40, paint);
if (GameOver == true) {
canvas.drawText("Return To Main Menu using return button", 5, 60,
paint);
}
}
// To be used if we need to find where screen was touched
public boolean onTouchEvent(MotionEvent event) {
for (int P = 0; P < SpriteAmount; P++) {
if (spritesArrayList.get(P).wasItTouched(event.getX(), event.getY())) {
/* For now, just renew the Sprite */
spritesArrayList.add(sprite = new Sprite(this));
hitCount++;
}
}
return true;
}
public void surfaceDestroyed(SurfaceHolder holder) {
gameLoopThread.running = false;
// Shut down the game loop thread cleanly.
boolean retry = true;
while (retry) {
try {
gameLoopThread.join();
retry = false;
} catch (InterruptedException e) {
}
}
}
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
}
/* Countdown Timer - private class */
private class MyCountDownTimer extends CountDownTimer {
public MyCountDownTimer(long startTime, long interval) {
super(startTime, interval);
}
public void onFinish() {
displayTime = "Times Over!";
timerRunning = false;
countDownTimer.cancel();
GameOver = true;
}
public void onTick(long millisUntilFinished) {
displayTime = " " + millisUntilFinished / 1000;
}
}// End of MyCountDownTimer
public int getHitCount() {
// TODO Auto-generated method stub
return hitCount;
}
}
Sprite.java:
public class Sprite {
// Needed for new random coordinates.
private Random random = new Random();
// x,y position of sprite - initial position (0,50)
int x = random.nextInt(500);
int X = random.nextInt(500);
int y = random.nextInt(1000);
int Y = random.nextInt(1000);
private int xSpeed = 10;// Horizontal increment of position (speed)
// apply at later date random.nextInt(10)
private int ySpeed = 10;// Vertical increment of position (speed)
// apply at later date random.nextInt(10)
private GameView gameView;
private Bitmap spritebmp;
// Width and Height of the Sprite image
private int bmp_width;
private int bmp_height;
private Integer[] imgid = { R.drawable.kidbuu, R.drawable.guko,
R.drawable.guko_ssj1
};
// Calculation for reverse direction
// x = x - (x - x)
// y = y - (y - y)
public Sprite(GameView gameView) {
this.gameView = gameView;
spritebmp = BitmapFactory.decodeResource(gameView.getResources(),
R.drawable.guko);
this.bmp_width = spritebmp.getWidth();
this.bmp_height = spritebmp.getHeight();
}
// update the position of the sprite
public void update() {
x = x + xSpeed;
y = y + ySpeed;
wrapAround(); // Adjust motion of sprite.
}
public void ReverseRandom() {
X = (x - (x - x));
Y = (y - (y - y));
}
public void draw(Canvas canvas) {
// Draw sprite image
// y = random.nextInt(500);
// x = random.nextInt(500);
canvas.drawBitmap(spritebmp, x, y, null);
}
public int calcX(int value) {
return random.nextInt(value);
}
public int calcY(int value) {
return random.nextInt(value);
}
public void wrapAround() {
ReverseRandom();
// Code to wrap around
if (x < 0)
x = X; // increment x whilst not off screen
if (x >= gameView.getWidth() - spritebmp.getWidth() - xSpeed) { // if
// gone
// of
// the
// right
// sides
// of
// screen
xSpeed = -5;
}
if (x + xSpeed <= 0) {
xSpeed = 5;
}
x = x + xSpeed;
if (y < 0)
y = Y;// increment y whilst not off screen
if (y >= gameView.getHeight() - spritebmp.getWidth() - ySpeed) {// if
// gone
// of
// the
// bottom
// of
// screen
ySpeed = -5;
}
if (y + ySpeed <= 0) {
ySpeed = 5;
}
y = y + ySpeed;
}
/* Checks if the Sprite was touched. */
public boolean wasItTouched(float ex, float ey) {
boolean touched = false;
if ((x <= ex) && (ex < x + bmp_width) && (y <= ey)
&& (ey < y + bmp_height)) {
touched = true;
}
return touched;
}// End of wasItTouched
public void change(Integer[] P) {
imgid = P;
spritebmp = BitmapFactory.decodeResource(gameView.getResources(),
R.drawable.guko_ssj1);
}
}

Related

Can't implement toggle button function outside of one screen

Hi I've implemented a toggle button for sound on my SettingsMenu, it works within this screen however when I go back to my main menu the functionality is lost and it resets back to its initial state. Any ideas how I can make it so that once it is clicked, it keeps this selection throughout every screen. I will show you the toggle button class and the settings class in which it is implemented. Thanks.
package uk.ac.qub.eeecs.game.cardDemo;
public class ToggleButtonSound extends GameObject {
protected enum ButtonState {
ON, OFF
}
private ButtonState mButtonState = ButtonState.OFF;
private SoundManager sm;
protected Bitmap mOffBitmap;
protected Bitmap mOnBitmap;
protected Bitmap mOnHoverBitmap;
protected Bitmap mOffHoverBitmap;
private Game mGame;
public boolean mMusicMuted = false;
public boolean mSoundMuted = false;
private MusicManager mMusicManager;
public ToggleButtonSound(float x, float y, float width, float height,
String offBitmap,
String onBitmap,
// String OffHoverBitmap,
//String OnHoverBitmap,
GameScreen gameScreen,
Game game) {
super(x, y, width, height,
gameScreen.getGame().getAssetManager().getBitmap(offBitmap), gameScreen);
mGame = game;
AssetStore assetStore = gameScreen.getGame().getAssetManager();
mOffBitmap = assetStore.getBitmap(offBitmap);
// mOffHoverBitmap = assetStore.getBitmap(offBitmap);
mOnBitmap = assetStore.getBitmap(onBitmap);
//mOnHoverBitmap = assetStore.getBitmap(onBitmap);
sm = new SoundManager(mGame);
mMusicManager = new MusicManager(mGame);
}
private boolean mPushTriggered;
private boolean mIsPushed;
/**
* Update the button
*
* #param elapsedTime Elapsed time information
*/
public void update(ElapsedTime elapsedTime) {
// Consider any touch events occurring in this update
Input input = mGame.getInput();
BoundingBox bound = getBound();
// Check for a press release on this button
for (TouchEvent touchEvent : input.getTouchEvents()) {
if (touchEvent.type == TouchEvent.TOUCH_UP
&& bound.contains(touchEvent.x, touchEvent.y)) {
// A touch up has occured in this control
if (mButtonState == ButtonState.OFF) {
setToggled(true);
} else {
setToggled(false);
}
return;
}
}
for (int idx = 0; idx < TouchHandler.MAX_TOUCHPOINTS; idx++) {
if (input.existsTouch(idx)) {
if (bound.contains(input.getTouchX(idx), input.getTouchY(idx))) {
if (!mIsPushed) {
mPushTriggered = true;
if (mOnHoverBitmap != null && mOffHoverBitmap != null)
mBitmap = mButtonState == ButtonState.ON ? mOnHoverBitmap : mOffHoverBitmap;
mIsPushed = true;
}
return;
}
}
}
if (mIsPushed) {
mBitmap = mButtonState == ButtonState.ON ? mOnBitmap : mOffBitmap;
mIsPushed = false;
mPushTriggered = false;
}
}
public boolean isToggledOn() {
return mButtonState == ButtonState.ON;
}
public void setToggled(boolean on) {
if (on) {
mButtonState = ButtonState.ON;
mBitmap = mOnBitmap;
} else {
mButtonState = ButtonState.OFF;
mBitmap = mOffBitmap;
}
}
#Override
public void draw(ElapsedTime elapsedTime, IGraphics2D graphics2D,
LayerViewport layerViewport, ScreenViewport screenViewport) {
// Assumed to be in screen space so just draw the whole thing
drawScreenRect.set((int) (position.x - mBound.halfWidth),
(int) (position.y - mBound.halfWidth),
(int) (position.x + mBound.halfWidth),
(int) (position.y + mBound.halfHeight));
graphics2D.drawBitmap(mBitmap, null, drawScreenRect, null);
}
}
Settings menu
public class SettingsMenu extends GameScreen {
private ToggleButtonSound mToggleButtonSound;
public SettingsMenu(Game game) {
super("Settings Menu", game);
mSoundManager = new SoundManager(game);
mMenuScreen = new MenuScreen(game);
music = new MusicManager(game);
AssetStore assetManager = mGame.getAssetManager();
assetManager.loadAndAddBitmap("offswitch", "img/offswitch.png");
assetManager.loadAndAddBitmap("onswitch", "img/onswitch.png");
assetManager.loadAndAddBitmap("SoundOn", "img/Soundon.png");
assetManager.loadAndAddBitmap("SoundOff", "img/Soundoff.png");
assetManager.loadAndAddBitmap("SettingsBackground", "img/settingsbackground.png");
//Load in sound
assetManager.loadAndAddSound("mouseClick", "Sounds/clicksound.wav");
assetManager.loadAndAddMusic("BackgroundMusic", "Sounds/MenuScreenBackgroundMusic.mp3");
//initialise sound
int spacingX = mGame.getScreenWidth() / 3;
int spacingY = mGame.getScreenHeight() / 9;
mPlayButtonBound = new Rect(spacingX, 3 * spacingY, 2 * spacingX, 4 * spacingY);
mInventoryButtonBound = new Rect(spacingX, 5 * spacingY, 2 * spacingX, 6 * spacingY);
soundButtonBound = new Rect(game.getScreenWidth() / 100, game.getScreenWidth() / 100, game.getScreenWidth() / 10, game.getScreenWidth() / 10);
mSettingsBackground = new Rect(1, 1, game.getScreenWidth(), game.getScreenHeight());
mLayerViewport = new LayerViewport(0, 0, game.getScreenWidth(), game.getScreenHeight());
mScreenViewport = new ScreenViewport(0, 0, game.getScreenWidth(), game.getScreenHeight());
int toggleHeight = mGame.getScreenHeight()/3;
mToggleButtonMusic = new ToggleButtonMusic(game.getScreenWidth() / 100, game.getScreenWidth() / 200, game.getScreenWidth() / 10, game.getScreenWidth() / 20, "onswitch","offswitch","onswitch","offswitch", this, mGame);
mToggleButtonSound = new ToggleButtonSound(game.getScreenWidth() / 100, game.getScreenWidth() / 200, game.getScreenWidth() / 10, game.getScreenWidth() / 20, "onswitch","offswitch", this, mGame);
mToggleButtonMusic.setPosition(game.getScreenWidth()/2,game.getScreenHeight()/3);
mToggleButtonSound.setPosition(game.getScreenWidth()/2, toggleHeight*2);
//toggleB.getBitmap();
//toggleB.getBound();
}
private boolean mIsPushed;
#Override
public void update(ElapsedTime elapsedTime) {
music.isPlaying1();
//mToggleButtonSound.setToggled(soundMuted);
mToggleButtonMusic.update(elapsedTime);
mToggleButtonSound.update(elapsedTime);
Input input = mGame.getInput();
List<TouchEvent> touchEvents = input.getTouchEvents();
if (touchEvents.size() > 0) {
TouchEvent touchEvent = touchEvents.get(0);
if (touchEvent.type == TouchEvent.TOUCH_UP) {
if ((soundButtonBound.contains((int) touchEvent.x, (int) touchEvent.y))) {
mGame.getScreenManager().removeScreen("Settings Menu");
mMenuScreen = new MenuScreen(mGame);
mGame.getScreenManager().addScreen(mMenuScreen);
}
}
}
}
#Override
public void draw(ElapsedTime elapsedTime, IGraphics2D graphics2D) {
graphics2D.drawBitmap(mGame.getAssetManager().getBitmap("SettingsBackground"), null, mSettingsBackground, null);
mToggleButtonMusic.draw(elapsedTime,graphics2D,mLayerViewport, mScreenViewport);
mToggleButtonSound.draw(elapsedTime,graphics2D,mLayerViewport, mScreenViewport);
graphics2D.drawBitmap(mGame.getAssetManager().getBitmap("SoundOn"), null, soundButtonBound, null);
}
#Override
public boolean onBackPressed() {
return true;
}
}

Temporary Sprite in Android App

I have an android game where there are sprites moving about the screen. When one is hit, it adds or takes away from the score and then disappears.
What I would like it to do is create a blood splatter when it is hit which will also disappear.
I have actually achieved this but the blood splatter doesn't appear where the sprite was hit. It always goes to the bottom right-hand corner. I was wondering if there is anyone out there that can see where my problem is.
I have a TempSprite class just for the blood splatter and this is below:
public class TempSprite {
private float x;
private float y;
private Bitmap bmp;
private int life = 12;
private List<TempSprite> temps;
public TempSprite(List<TempSprite> temps, GameView gameView, float x,
float y, Bitmap bmp) {
this.x = Math.min(Math.max(x - bmp.getWidth() / 2, 0),
gameView.getWidth() - bmp.getWidth());
this.y = Math.min(Math.max(y - bmp.getHeight() / 2, 0),
gameView.getHeight() - bmp.getHeight());
this.bmp = bmp;
this.temps = temps;
}
public void onDraw(Canvas canvas) {
update();
canvas.drawBitmap(bmp, x, y, null);
}
private void update() {
if (--life < 1) {
temps.remove(this);
}
}
}
All the other code is in the GameView class, specifically in the doDraw and GameView methods:
public class GameView extends SurfaceView implements SurfaceHolder.Callback {
private final Bitmap bmpBlood;
/* Member (state) fields */
private GameLoopThread gameLoopThread;
private Paint paint; //Reference a paint object
/** The drawable to use as the background of the animation canvas */
private Bitmap mBackgroundImage;
// For creating the game Sprite
private Sprite sprite;
private BadSprite badSprite;
// For recording the number of hits
private int hitCount;
// For displaying the highest score
private int highScore;
// To track if a game is over
private boolean gameOver;
// To play sound
private SoundPool mySound;
private int zapSoundId;
private int screamSoundId;
// For multiple sprites
private ArrayList<Sprite> spritesArrayList;
private ArrayList<BadSprite> badSpriteArrayList;
// For the temp blood image
private List<TempSprite> temps = new ArrayList<TempSprite>();
//int backButtonCount = 0;
private void createSprites() {
// Initialise sprite object
spritesArrayList = new ArrayList<>();
badSpriteArrayList = new ArrayList<>();
for (int i = 0; i < 20; i++) {
spritesArrayList.add(new Sprite(this));
badSpriteArrayList.add(new BadSprite(this));
}
}
public GameView(Context context) {
super(context);
// Focus must be on GameView so that events can be handled.
this.setFocusable(true);
// For intercepting events on the surface.
this.getHolder().addCallback(this);
// Background image added
mBackgroundImage = BitmapFactory.decodeResource(this.getResources(), R.drawable.castle);
// Populate multiple sprites
//createSprites();
//Vibrator vibe = (Vibrator) sprite.getSystemService(Context.VIBRATOR_SERVICE);
//vibe.vibrate(500);
// For the temp blood splatter
bmpBlood = BitmapFactory.decodeResource(getResources(), R.drawable.blood1);
//Sound effects for the sprite touch
mySound = new SoundPool(10, AudioManager.STREAM_MUSIC, 0);
screamSoundId = mySound.load(context, R.raw.scream, 1);
zapSoundId = mySound.load(context, R.raw.zap, 1);
}
/* Called immediately after the surface created */
public void surfaceCreated(SurfaceHolder holder) {
createSprites();
// We can now safely setup the game start the game loop.
ResetGame();//Set up a new game up - could be called by a 'play again option'
mBackgroundImage = Bitmap.createScaledBitmap(mBackgroundImage, getWidth(), getHeight(), true);
gameLoopThread = new GameLoopThread(this.getHolder(), this);
gameLoopThread.running = true;
gameLoopThread.start();
}
// For the countdown timer
private long startTime; // Timer to count down from
private final long interval = 1 * 1000; // 1 sec interval
private CountDownTimer countDownTimer; // Reference to the class
private boolean timerRunning = false;
private String displayTime; // To display the time on the screen
//To initialise/reset game
private void ResetGame(){
/* Set paint details */
paint = new Paint();
paint.setColor(Color.WHITE);
paint.setTextSize(20);
sprite = new Sprite(this);
hitCount = 0;
// Set timer
startTime = 10; // Start at 10s to count down
// Create new object - convert startTime to milliseconds
countDownTimer = new MyCountDownTimer(startTime*1000, interval);
countDownTimer.start(); // Start the time running
timerRunning = true;
gameOver = false;
}
// Countdown Timer - private class
private class MyCountDownTimer extends CountDownTimer {
public MyCountDownTimer (long startTime, long interval) {
super(startTime, interval);
}
public void onFinish() {
//displayTime = "Time is up!";
timerRunning = false;
countDownTimer.cancel();
gameOver = true;
}
public void onTick (long millisUntilFinished) {
displayTime = " " + millisUntilFinished / 1000;
}
}
//This class updates and manages the assets prior to drawing - called from the Thread
public void update(){
}
/**
* To draw the game to the screen
* This is called from Thread, so synchronisation can be done
*/
#SuppressWarnings("ResourceAsColor")
public void doDraw(Canvas canvas) {
canvas.drawBitmap(mBackgroundImage, 0, 0, null);
if (!gameOver) {
sprite.draw(canvas);
//paint.setColor(R.color.red);
canvas.drawText("Time Remaining: " + displayTime, 35, 50, paint);
canvas.drawText("Number of hits: " + hitCount, 35, 85, paint);
// Draw the blood splatter
for (int i = temps.size() - 1; i >= 0; i--) {
temps.get(i).onDraw(canvas);
}
// Draw all the objects on the canvas
for (int i = 0; i < spritesArrayList.size(); i++) {
Sprite sprite = spritesArrayList.get(i);
sprite.draw(canvas);
}
for (int i = 0; i < badSpriteArrayList.size(); i++) {
BadSprite badSprite = badSpriteArrayList.get(i);
badSprite.draw(canvas);
}
} else {
canvas.drawText("Game Over!", 35, 50, paint);
canvas.drawText("Your score was: " + hitCount, 35, 80, paint);
canvas.drawText("To go back home,", 280, 50, paint);
canvas.drawText("press the 'back' key", 280, 70, paint);
}
}
//To be used if we need to find where screen was touched
public boolean onTouchEvent(MotionEvent event) {
for (int i = spritesArrayList.size()-1; i>=0; i--) {
Sprite sprite = spritesArrayList.get(i);
if (sprite.wasItTouched(event.getX(), event.getY())) {
mySound.play(zapSoundId, 1.0f, 1.0f, 0,0, 1.5f);
spritesArrayList.remove(sprite);
//temps.add(new TempSprite(temps, this, x, y, bmpBlood));
hitCount--;
return super.onTouchEvent(event);
}
for (int i1 = badSpriteArrayList.size()-1; i1>=0; i1--) {
BadSprite badSprite = badSpriteArrayList.get(i1);
if (badSprite.wasItTouched(event.getX(), event.getY())) {
mySound.play(screamSoundId, 1.0f, 1.0f, 0, 0, 1.5f);
badSpriteArrayList.remove(badSprite);
temps.add(new TempSprite(temps, this, x, y, bmpBlood));
hitCount++;
return super.onTouchEvent(event);
}
}
}
//else {
return true;
// }
}
public void surfaceDestroyed(SurfaceHolder holder) {
gameLoopThread.running = false;
// Shut down the game loop thread cleanly.
boolean retry = true;
while(retry) {
try {
gameLoopThread.join();
retry = false;
} catch (InterruptedException e) {}
}
}
public int getHitCount() {
return hitCount;
}
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
}
As always, any help greatly appreciated.
Thanks
This was solved with the following code:
public class TempSprite {
private float x;
private float y;
private Bitmap bmp;
private int life = 12;
private List<TempSprite> temps;
public TempSprite(List<TempSprite> temps, GameView gameView, float x,
float y, Bitmap bmp) {
/*this.x = Math.min(Math.max(x - bmp.getWidth() / 2, 0),
gameView.getWidth() - bmp.getWidth());
this.y = Math.min(Math.max(y - bmp.getHeight() / 2, 0),
gameView.getHeight() - bmp.getHeight());*/
this.x = x;
this.y = y;
this.bmp = bmp;
this.temps = temps;
}
public void onDraw(Canvas canvas) {
update();
canvas.drawBitmap(bmp, x, y, null);
}
private void update() {
if (--life < 1) {
temps.remove(this);
}
}
}
You can see where the commented out sections are and below are what they were replaced with. I was trying to make things a little too complicated.

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.
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. In this specific example you (bitmap) tried to allocate 360KB though you could only allocate 78KB more. 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.
I'd recommend you to create a method in Obstacle like recycle or something along this way. Then every time you remove Obstacle from obstacles in ObstacleManager call that method. 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 would be meant to call recycle on every one of your frames.)

Array list for sprites in android game/app

I'm trying to get more than one sprite on screen (two for now to see if I can get it going) but all it does is just display the one still.
My code is as follows (it's all in one class:
public class GameView extends SurfaceView implements SurfaceHolder.Callback {
/* Member (state) fields */
private GameLoopThread gameLoopThread;
private Paint paint; //Reference a paint object
/** The drawable to use as the background of the animation canvas */
private Bitmap mBackgroundImage;
// For creating the game Sprite
private Sprite sprite;
//For multiple sprites
private ArrayList<Sprite> spritesArrayList;
// For recording the number of hits
private int hitCount;
// For displaying the highest score
//private int highScore;
// To track if a game is over
private boolean gameOver;
// To play sound
private SoundPool mySound;
// Zap sound when sprite hit
int zapSoundId;
int count = 2;
int arraySize;
public GameView(Context context) {
super(context);
// Focus must be on GameView so that events can be handled.
this.setFocusable(true);
// For intercepting events on the surface.
this.getHolder().addCallback(this);
// Background image added
mBackgroundImage = BitmapFactory.decodeResource(this.getResources(), R.drawable.castle);
// Initialise sprites object
spritesArrayList = new ArrayList<Sprite>();
}
/* Called immediately after the surface created */
public void surfaceCreated(SurfaceHolder holder) {
for (int i = 0; i < count; i++) {
spritesArrayList.add(sprite);
}
// We can now safely setup the game start the game loop.
ResetGame();//Set up a new game up - could be called by a 'play again option'
mBackgroundImage = Bitmap.createScaledBitmap(mBackgroundImage, getWidth(), getHeight(), true);
gameLoopThread = new GameLoopThread(this.getHolder(), this);
gameLoopThread.running = true;
gameLoopThread.start();
}
// For the countdown timer
private long startTime; // Timer to count down from
private final long interval = 1 * 1000; // 1 sec interval
private CountDownTimer countDownTimer; // Reference to the class
private boolean timerRunning = false;
private String displayTime; // To display the time on the screen
public void getArrayListSize() {
if (spritesArrayList.isEmpty()) {
// nothing
} else {
arraySize = spritesArrayList.size();
}
}
//To initialise/reset game
private void ResetGame() {
/* Set paint details */
paint = new Paint();
paint.setColor(Color.WHITE);
paint.setTextSize(20);
sprite = new Sprite(this);
hitCount = 0;
// Set timer
startTime = 10; // Start at 10s to count down
// Create new object - convert startTime to milliseconds
countDownTimer = new MyCountDownTimer(startTime * 1000, interval);
countDownTimer.start(); // Start the time running
timerRunning = true;
gameOver = false;
}
// Countdown Timer - private class
private class MyCountDownTimer extends CountDownTimer {
public MyCountDownTimer (long startTime, long interval) {
super(startTime, interval);
}
public void onFinish() {
//displayTime = "Time is up!";
timerRunning = false;
countDownTimer.cancel();
gameOver = true;
}
public void onTick (long millisUntilFinished) {
displayTime = " " + millisUntilFinished / 1000;
}
}
//This class updates and manages the assets prior to drawing - called from the Thread
public void update() {
if (gameOver != true) {
spritesArrayList.clear();
sprite.update();
}
for (int i = 0; i < spritesArrayList(); i++) {
sprite = new Sprite(this);
spritesArrayList.add(sprite);
}
}
private int spritesArrayList() {
return 0;
}
/*private void createSprites() {
sprites.add(createSprite(R.drawable.bad3));
sprites.add(createSprite(R.drawable.bad4));
sprites.add(createSprite(R.drawable.good2));
sprites.add(createSprite(R.drawable.good5));
}*/
/*private Sprite createSprite(int resource) {
Bitmap bmp = BitmapFactory.decodeResource(getResources(), resource);
return new Sprite(this, bmp);
}*/
/**
* To draw the game to the screen
* This is called from Thread, so synchronisation can be done
*/
#SuppressWarnings("ResourceAsColor")
public void doDraw(Canvas canvas) {
//Draw all the objects on the canvas
canvas.drawBitmap(mBackgroundImage, 0, 0, null);
getArrayListSize();
for (int i = 0; i < arraySize; i++)
{
Sprite sprite = spritesArrayList.get(i);
sprite.draw(canvas);
}
if (!gameOver) {
sprite.draw(canvas);
paint.setColor(R.color.red);
canvas.drawText("Time Remaining: " + displayTime, 35, 50, paint);
canvas.drawText("Number of hits: " + hitCount, 250, 50, paint);
} else {
canvas.drawText("Game Over!", 185, 100, paint);
canvas.drawText("To go back to the main menu, press the 'back' key", 15, 150, paint);
}
}
//To be used if we need to find where screen was touched
public boolean onTouchEvent(MotionEvent event) {
if (sprite.wasItTouched(event.getX(), event.getY())) {
sprite = new Sprite(this);
hitCount++;
return true;
} else {
return true;
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
gameLoopThread.running = false;
// Shut down the game loop thread cleanly.
boolean retry = true;
while(retry) {
try {
gameLoopThread.join();
retry = false;
} catch (InterruptedException e) {}
}
}
public int getHitCount() {
return hitCount;
}
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
}
If anyone would like me to clarify any of the code, please let me know.
Thanks

i am trying to make a pong game in android but i am stuck ,i dont know why ball isnt moving

here is the class which extends surface view , in its run method i've called the method to animate ball but the ball isnt animating
public class OurView extends SurfaceView implements Runnable
{
Canvas c;
Thread t = null;
SurfaceHolder holder;
boolean isItOk = false;
Rect racketTop,racketBottom;
int TopLeft ;
int TopRight ;
int TopTop ;
int TopBottom;
int bottomLeft;
int bottomRight;
int bottomTop;
int bottomBottom;
GameState state;
public OurView(Context context) {
super(context);
holder = getHolder();
state = new GameState();
}
#Override
public void run() {
while (isItOk == true) {
if (!holder.getSurface().isValid())
continue;
c = holder.lockCanvas();
c.drawARGB(0, 0, 0, 0);
TopLeft = ((c.getWidth() / 2) / 2) + 50;
TopRight = (c.getWidth() / 2) + ((c.getWidth() / 2) / 2) - 50;
TopTop = getTop();
TopBottom = 10;
bottomLeft = ((c.getWidth() / 2) / 2) + 50;
bottomRight = (c.getWidth() / 2) + ((c.getWidth() / 2) / 2) - 50;
bottomTop = getBottom() - 10;
bottomBottom = getBottom();
racketTop = new Rect(); // for top racket
racketTop.set(TopLeft, TopTop, TopRight, TopBottom); //left = ((c.getWidth()/2)/2)+50
//top = getTop()
//right = (c.getWidth()/2)+((c.getWidth()/2)/2)-50
//bottom = 10
racketBottom = new Rect(); // FOR BOTTOM RACKET
racketBottom.set(bottomLeft, bottomTop, bottomRight, bottomBottom); //left = ((c.getWidth()/2)/2)+50
// top = getBottom()-10
// right = (c.getWidth()/2)+((c.getWidth()/2)/2)-50
// bottom = getBottom()
Paint white = new Paint();
white.setColor(Color.WHITE);
white.setStyle(Paint.Style.FILL);
c.drawRect(racketTop, white);
c.drawRect(racketBottom, white);
here i called the method
state.update();
state.draw(c,white);
holder.unlockCanvasAndPost(c);
}
}
public void pause()
{
isItOk = false;
while(true)
{
try
{
t.join();
}
catch(InterruptedException e)
{
e.printStackTrace();
}
break;
}
t = null;
}
public void resume()
{
isItOk = true;
t = new Thread(this);
t.start();
}
here is the class where ball is defined
public class GameState {
int ballx,bally; //ball x and y position
int ball_size = 20; // size of ball
static int ballvelx = 3; // velocity x of ball
static int ballvely = 3; // velocity y of ball
public GameState() {
}
public void update()
{
ballx += ballvelx;
bally += ballvely;
}
public void draw(Canvas canvas, Paint paint)
{
//objects color
paint.setColor(Color.WHITE);
ballx = canvas.getWidth()/2;
bally = canvas.getHeight()/2;
//ball
canvas.drawCircle(ballx,bally,ball_size,paint);
}
}
help me this is my first android game
Without judging on the rest of your code:
ballx = canvas.getWidth()/2;
bally = canvas.getHeight()/2;
This resets the position of your ball every time you draw it.
No wonder it does not move, when you reset its position.
Call update() instead, so the ball is moved.

Categories

Resources