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
Related
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.
Inside my gameplay screen I want to create a Pause Screen Menu which I can select the Retry button or Back to main screen if I click the pause button.I already draw the pause button inside my class.My problem is how can I draw the pause menu screen?
Here is my code
//pause
pause = new Texture("pause.png");
myTextureRegion = new TextureRegion(pause);
myTexRegionDrawable = new TextureRegionDrawable(myTextureRegion);
pause_btnDialog = new ImageButton(myTexRegionDrawable); //Set the button up
pause_btnDialog.setPosition(580,1150);
stage.addActor(pause_btnDialog); //Add the button to the stage to perform rendering and take input.
Gdx.input.setInputProcessor(stage);
pause_btnDialog.addListener(new ChangeListener() {
public void changed (ChangeEvent event, Actor actor) {
System.out.println("Pause Button Pressed");
//Show Pause Screen menu
//game.setScreen(new PauseGameday1(game));
}
});
stage.addActor(pause_btnDialog);
GameScreen
public class IngamedayOne implements Screen ,InputProcessor {
final MyGdxGame game;
// Constant rows and columns of the sprite sheet
private static final int FRAME_COLS = 5, FRAME_ROWS = 1;
private boolean peripheralAvailable;
private static final float ACCELERATION = 20f;
// Objects used
Animation<TextureRegion> walkAnimation; // Must declare frame type (TextureRegion)
Texture cat ,left_paw,right_paw,progressbar_background,progressbar_knob,pause,meter;
Texture carpet,desk,plants,square_carpet,shoes;
SpriteBatch spriteBatch;
Sprite sprite;
private Texture Background;
ImageButton left_paw_btn,right_paw_btn,pause_btnDialog;
Viewport viewport;
private Stage stage;
// A variable for tracking elapsed time for the animation
float stateTime;
private TextureRegion myTextureRegion;
private TextureRegionDrawable myTexRegionDrawable;
private boolean isPause;
private Group pauseGroup;
//Screen Size
OrthographicCamera camera;
float catSpeed = 50.0f; // 10 pixels per second.
float catX;
float catY;
public boolean paused = false;
public IngamedayOne(final MyGdxGame game) {
this.game = game;
Gdx.input.setCatchBackKey(true);
Gdx.graphics.setContinuousRendering(false);
Gdx.graphics.requestRendering();
stage = new Stage(new StretchViewport( 720, 1280));
camera = new OrthographicCamera();
camera.setToOrtho(false, 720, 1280);
camera.translate( 1280/2, 720/2 );
Gdx.input.setInputProcessor(stage);
spriteBatch = new SpriteBatch();
viewport = new StretchViewport(720, 1280);
Gdx.gl.glViewport(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
// Load the sprite sheet as a texture
cat = new Texture(Gdx.files.internal("cat.png"));
sprite = new Sprite(cat);
catX=300;
catY=0;
Gdx.input.setInputProcessor( this);
peripheralAvailable = Gdx.input.isPeripheralAvailable(Input.Peripheral.Accelerometer);
int orientation = Gdx.input.getRotation();
Input.Orientation nativeOrientation = Gdx.input.getNativeOrientation();
viewport = new StretchViewport(720, 1280);
Gdx.gl.glViewport(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
// Progressbar
progressbar_background = new Texture("progression_map.png");
progressbar_knob = new Texture("cat_head.png");
//pause
pause = new Texture("pause.png");
myTextureRegion = new TextureRegion(pause);
myTexRegionDrawable = new TextureRegionDrawable(myTextureRegion);
pause_btnDialog = new ImageButton(myTexRegionDrawable); //Set the button up
pause_btnDialog.setPosition(580,1150);
stage.addActor(pause_btnDialog); //Add the button to the stage to perform rendering and take input.
Gdx.input.setInputProcessor(stage);
pause_btnDialog.addListener(new ChangeListener() {
public void changed (ChangeEvent event, Actor actor) {
System.out.println("Pause Button Pressed");
//Show Pause Screen menu
game.setScreen(new PauseGameday1(game));
pause();
}
});
stage.addActor(pause_btnDialog);
meter = new Texture("meter.png");
//background
Background = new Texture(Gdx.files.internal("floor.png")); //File from assets folder
// Use the split utility method to create a 2D array of TextureRegions. This is
// possible because this sprite sheet contains frames of equal size and they are
// all aligned.
TextureRegion[][] tmp = TextureRegion.split(cat, cat.getWidth() / FRAME_COLS, cat.getHeight()/ FRAME_ROWS);
// Place the regions into a 1D array in the correct order, starting from the top
// left, going across first. The Animation constructor requires a 1D array.
TextureRegion[] walkFrames = new TextureRegion[FRAME_COLS * FRAME_ROWS];
int index = 0;
for (int i = 0; i < FRAME_ROWS; i++) {
for (int j = 0; j < FRAME_COLS; j++) {
walkFrames[index++] = tmp[i][j];
}
}
// Initialize the Animation with the frame interval and array of frames
walkAnimation = new Animation<TextureRegion>(0.200f, walkFrames);
// Instantiate a SpriteBatch for drawing and reset the elapsed animation
// time to 0
spriteBatch = new SpriteBatch();
stateTime = 0f;
//left_control
left_paw = new Texture(Gdx.files.internal("left_paw.png"));
myTextureRegion = new TextureRegion(left_paw);
myTexRegionDrawable = new TextureRegionDrawable(myTextureRegion);
left_paw_btn = new ImageButton(myTexRegionDrawable); //Set the button up
left_paw_btn.setPosition(10,25);
stage.addActor(left_paw_btn); //Add the button to the stage to perform rendering and take input.
Gdx.input.setInputProcessor(stage);
left_paw_btn.addListener(new InputListener(){
#Override
public void touchUp (InputEvent event, float x, float y, int pointer, int button) {
System.out.println("Left Button Pressed");
//Start Animation
}
#Override
public boolean touchDown (InputEvent event, float x, float y, int pointer, int button) {
return true;
}
});
stage.addActor(left_paw_btn);
//right_control
right_paw = new Texture(Gdx.files.internal("right_paw.png"));
myTextureRegion = new TextureRegion(right_paw);
myTexRegionDrawable = new TextureRegionDrawable(myTextureRegion);
right_paw_btn = new ImageButton(myTexRegionDrawable); //Set the button up
right_paw_btn.setPosition(517,25);
stage.addActor(right_paw_btn); //Add the button to the stage to perform rendering and take input.
Gdx.input.setInputProcessor(stage);
right_paw_btn.addListener(new InputListener(){
#Override
public void touchUp (InputEvent event, float x, float y, int pointer, int button) {
System.out.println("Right Button Pressed");
//Start Animation
stateTime += Gdx.graphics.getDeltaTime(); // Accumulate elapsed animation time
camera.update();
}
#Override
public boolean touchDown (InputEvent event, float x, float y, int pointer, int button) {
return true;
}
});
stage.addActor(right_paw_btn);
}
public enum State
{
PAUSE,
RUN,
RESUME,
STOPPED
}
private State state = State.RUN;
#Override
public void show() {
}
#Override
public void render(float delta) {
// clear previous frame
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); // Clear screen
stateTime += Gdx.graphics.getDeltaTime(); // Accumulate elapsed animation time
camera.update();
spriteBatch.begin();
TextureRegion currentFrame = walkAnimation.getKeyFrame(stateTime, true);
spriteBatch.setProjectionMatrix(camera.combined);
spriteBatch.draw(Background,0,0);
spriteBatch.draw(currentFrame,catX,catY); // Draw current frame at (50, 50)
spriteBatch.draw(meter,190,990);
spriteBatch.draw(progressbar_background,20,1170);
spriteBatch.draw(progressbar_knob,18,1170);
//Moving player on desktop
if(Gdx.input.isKeyPressed(Input.Keys.LEFT))
catX -= Gdx.graphics.getDeltaTime() * catSpeed;
if(Gdx.input.isKeyPressed(Input.Keys.RIGHT))
catX += Gdx.graphics.getDeltaTime() * catSpeed;
if(Gdx.input.isKeyPressed(Input.Keys.UP))
catY += Gdx.graphics.getDeltaTime() * catSpeed;
if(Gdx.input.isKeyPressed(Input.Keys.DOWN))
catY -= Gdx.graphics.getDeltaTime() * catSpeed;
//Mobile acceleration
if (Gdx.input.isPeripheralAvailable(Input.Peripheral.Accelerometer))
{
catX -= Gdx.input.getAccelerometerX();
catY += Gdx.input.getAccelerometerY();
}
if(catY<0) {
catY =0;
}
if(catY> Gdx.graphics.getWidth()-100) {
catY =Gdx.graphics.getWidth()-100;
}
if(catX<0){
catX =0;
}
if(catX> Gdx.graphics.getHeight()-250) {
catX =Gdx.graphics.getHeight()-250;
}
switch (state)
{
case RUN:
//do suff here
break;
case PAUSE:
break;
case RESUME:
break;
default:
break;
}
spriteBatch.end();
stage.act(); //acting a stage to calculate positions of actors etc
stage.draw(); //drawing it to render all
}
#Override
public void resize(int width, int height) {
viewport.update(width, height);
camera.position.set(camera.viewportWidth / 2, camera.viewportHeight / 2, 0);
}
#Override
public void pause() {
this.state = State.PAUSE;
}
#Override
public void resume() {
this.state = State.RESUME;
}
#Override
public boolean keyDown(int keycode) {
return true;
}
#Override
public boolean keyUp(int keycode) {
return false;
}
#Override
public boolean keyTyped(char character) {
return false;
}
#Override
public boolean touchDown(int screenX, int screenY, int pointer, int button) {
return false;
}
#Override
public boolean touchUp(int screenX, int screenY, int pointer, int button) {
return false;
}
#Override
public boolean touchDragged(int screenX, int screenY, int pointer) {
return false;
}
#Override
public boolean mouseMoved(int screenX, int screenY) {
return false;
}
#Override
public boolean scrolled(int amount) {
return false;
}
#Override
public void hide() {
}
#Override
public void dispose() { // SpriteBatches and Textures must always be disposed
spriteBatch.dispose();
cat.dispose();
left_paw.dispose();
right_paw.dispose();
stage.dispose();
Background.dispose();
progressbar_background.dispose();
progressbar_knob.dispose();
}
}
Pause Menu
public class PauseGameday1 implements Screen {
final MyGdxGame game;
private Texture Background,pauseImg;
private Stage stage;
SpriteBatch spriteBatch;
OrthographicCamera camera;
private static final int WIDTH= 720;
private static final int HEIGHT= 1280;
private TextureRegion myTextureRegion;
private TextureRegionDrawable myTexRegionDrawable;
Viewport viewport;
public PauseGameday1( MyGdxGame game) {
this.game = game;
stage = new Stage(new StretchViewport( 720, 1280));
camera = new OrthographicCamera();
camera.setToOrtho(false, 720, 1280);
camera.translate( 1280/2, 720/2 );
Gdx.input.setInputProcessor(stage);
spriteBatch = new SpriteBatch();
viewport = new StretchViewport(720, 1280);
Gdx.gl.glViewport(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
Background = new Texture(Gdx.files.internal("backgroundimage.png")); //background image
pauseImg = new Texture(Gdx.files.internal("pausemenu/pause_text.png"));
}
#Override
public void show() {
}
#Override
public void render(float delta) {
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); // Clear screen
camera.update();
spriteBatch.begin();
spriteBatch.setProjectionMatrix(camera.combined);
spriteBatch.draw(Background,0,0);
spriteBatch.draw(pauseImg,230,900);
stage.act(Gdx.graphics.getDeltaTime()); //Perform ui logic
spriteBatch.end();
stage.getViewport().apply();
stage.draw(); //Draw the ui
}
#Override
public void resize(int width, int height) {
viewport.update(width, height);
camera.position.set(camera.viewportWidth / 2, camera.viewportHeight / 2, 0);
}
#Override
public void pause() {
}
#Override
public void resume() {
}
#Override
public void hide() {
}
#Override
public void dispose() {
}
}
Can anyone correct my codes?
You only declared pauseGroup but never used in your game, Call pause() method from pause_button. It will create pauseGroup for you and add to your Stage. In pause() method, create Actor(UI) and add to pauseGroup. You can't use multiple screen at a time with your Game class because Game having reference of single Screen.
pause_btnDialog.addListener(new ChangeListener() {
public void changed (ChangeEvent event, Actor actor) {
pause();
}
});
#Override
public void render(float delta) {
// clear previous frame
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); // Clear screen
camera.update();
spriteBatch.begin();
spriteBatch.setProjectionMatrix(camera.combined);
if(this.state==State.RESUME)
stateTime += Gdx.graphics.getDeltaTime(); // Accumulate elapsed animation time
TextureRegion currentFrame = walkAnimation.getKeyFrame(stateTime, true);
spriteBatch.draw(Background,0,0);
spriteBatch.draw(currentFrame,catX,catY); // Draw current frame at (50, 50)
spriteBatch.draw(meter,190,990);
spriteBatch.draw(progressbar_background,20,1170);
spriteBatch.draw(progressbar_knob,18,1170);
if(this.state==State.RESUME){
//Moving player on desktop
if(Gdx.input.isKeyPressed(Input.Keys.LEFT))
catX -= Gdx.graphics.getDeltaTime() * catSpeed;
if(Gdx.input.isKeyPressed(Input.Keys.RIGHT))
catX += Gdx.graphics.getDeltaTime() * catSpeed;
if(Gdx.input.isKeyPressed(Input.Keys.UP))
catY += Gdx.graphics.getDeltaTime() * catSpeed;
if(Gdx.input.isKeyPressed(Input.Keys.DOWN))
catY -= Gdx.graphics.getDeltaTime() * catSpeed;
//Mobile acceleration
if (Gdx.input.isPeripheralAvailable(Input.Peripheral.Accelerometer))
{
catX -= Gdx.input.getAccelerometerX();
catY += Gdx.input.getAccelerometerY();
}
if(catY<0) {
catY =0;
}
if(catY> Gdx.graphics.getWidth()-100) {
catY =Gdx.graphics.getWidth()-100;
}
if(catX<0){
catX =0;
}
if(catX> Gdx.graphics.getHeight()-250) {
catX =Gdx.graphics.getHeight()-250;
}
}
switch (state)
{
case RUN:
//do suff here
break;
case PAUSE:
break;
case RESUME:
break;
default:
break;
}
spriteBatch.end();
stage.act(); //acting a stage to calculate positions of actors etc
stage.draw(); //drawing it to render all
}
public void pause(){
this.state = State.PAUSE;
pauseGroup = new Group;
Image semiTransparentBG= ......
// setSize(Size of screen) and make it semi transparent.
pauseGroup.addActor(semiTransparentBG);
//crate all other pause UI buttons with listener and add to pauseGroup
stage.addActor(pauseGroup);
}
public void resume() {
if(this.state = State.PAUSE){
this.state = State.RESUME;
pauseGroup.remove();
}
}
I know similar questions have been asked before but none of those solutions worked for me.
I'm trying to create a small 2D game for Android and I am having some problems using SurfaceView.
My main activity currently looks like this:
public class MainActivity extends Activity {
private static final String TAG = "MainActivity";
private DrawingSurface drawingsurface;
private Game game;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "onCreate()");
setFullscreen();
game = new Game();
drawingsurface = new DrawingSurface(this, game);
setContentView(drawingsurface);
}
private void setFullscreen() {
// ...
}
}
As you can see, I set my activity to fullscreen, create a new SurfaceView (called drawingSurface) and create a new game instance.
My SurfaceView (called DrawingSurface) looks like this:
public class DrawingSurface extends SurfaceView implements SurfaceHolder.Callback {
private GameThread thread;
private static final String TAG = "DrawingSurface";
public DrawingSurface(Context context, Game game) {
super(context);
getHolder().addCallback(this);
setFocusable(true);
// create a new game rendering thread and pass it game so it can call the update() and render() functions of game:
thread = new GameThread(getHolder(), this, game);
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
Log.v(TAG, "surfaceCreated()");
// start the rendering thread:
thread.setRunning(true);
thread.start();
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
Log.v(TAG, "surfaceChanged()");
// do I need to do anything in here?
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
// stop the rendering thread:
Log.v(TAG, "surfaceDestroyed()");
thread.setRunning(false);
boolean retry = true;
while (retry) {
try {
thread.join();
} catch (InterruptedException e) {
// try again shutting down the thread
}
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
// pass the touch event to the Game instance (to keep everything in on place)
thread.game.onTouchEvent(event);
return super.onTouchEvent(event);
}
#Override
protected void onDraw(Canvas canvas) {
// I don't use onDraw(), instead I have my own update() and render() functions in my game thread
super.onDraw(canvas);
}
}
This is my game thread:
public class GameThread extends Thread {
private boolean running;
private SurfaceHolder surfaceHolder;
private DrawingSurface drawingSurface;
private static final String TAG = GameThread.class.getSimpleName();
protected Game game;
public GameThread(SurfaceHolder surfaceHolder, DrawingSurface drawingSurface, Game game) {
super();
this.surfaceHolder = surfaceHolder;
this.drawingSurface = drawingSurface;
this.game = game;
}
public void setRunning(boolean running) {
this.running = running;
}
#SuppressLint("WrongCall")
#Override
public void run() {
Log.d(TAG, "Starting game loop");
long now;
long dt;
long last = System.currentTimeMillis();
Canvas canvas;
while (running) {
Log.v(TAG, "GameThread running");
canvas = null;
/* try locking the canvas for exclusive
pixel editing in the surface */
try {
canvas = this.surfaceHolder.lockCanvas();
synchronized (this.surfaceHolder) {
now = System.currentTimeMillis();
dt = (now - last);
this.game.update(dt);
if(canvas != null)
this.game.render(canvas, dt);
last = now;
}
} finally {
/*in case of an exception the surface
is not left in an inconsistent state */
if (canvas != null) {
this.surfaceHolder.unlockCanvasAndPost(canvas);
}
}
if (dt < 16) {
try {
Thread.sleep(16 - dt);
} catch (InterruptedException e) {
}
}
}
}
}
And this is the Game class:
public class Game {
private static final String TAG = "Game";
private static int playerRefPosX = 40;
private int playerY = 0;
private int playerVelY = 1;
public Game() {
Log.v(TAG, "Game instance created");
}
public void update(long dt) {
playerY += playerVelY * dt;
if (playerY > 1800) {
playerVelY = -playerVelY;
}
if (playerY < 0) {
playerVelY = -playerVelY;
}
}
public void render(Canvas canvas, long dt) {
canvas.drawColor(Color.BLACK);
// draw Player
Paint paint = new Paint();
paint.setTextSize(100);
paint.setColor(new Color().rgb(255, 0, 0));
canvas.drawRect(playerRefPosX, playerY + 100, playerRefPosX + 200, playerY - 100, paint);
canvas.drawText(String.valueOf(1000/dt), canvas.getWidth()/2, canvas.getWidth()/2, paint);
}
public void onTouchEvent(MotionEvent event) {
Log.v(TAG, "received touch event..");
}
}
The problems I am have right now:
When I press the home button and reenter the app OR rotate my device it calls surfaceDestroyed() but doesn't recreate it afterwards (the canvas doesn't get repainted)
The game rendering thread never stops (as indicated by the log messages)
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);
}
}
I am new in developing games, i trying to develop a simple shooting space game and everything works perfect. now, i want to create a Dialog popup when the user click on the back button and the game should pause until the user press resume. the game is paused but when i click the resume button the game still on pause here is my game Loop class:
public class Game extends SurfaceView implements Runnable , SurfaceHolder.Callback {
public static MyPreferences pref;
public static Levels level;
public static int SCREEN_W;
public static int SCREEN_H;
public static boolean running;
private static Thread thread = null;
private SurfaceHolder holder;
private Canvas canvas;
private Paint p = new Paint();
public static Handler handler = new Handler();
public static Resources res;
public static Timer timer;
public Game(Context context) {
super(context);
res = getResources();
holder = getHolder();
holder.addCallback(this);
level = new Levels();
timer = new Timer();
pref = new MyPreferences(context);
System.out.println("Create Game instance");
}
public void run() {
init();
long lastTime = System.nanoTime();
double delta = 0;
double ns = 1000000000.0 / 30.0;
System.out.println("Run method" + running);
while (running) {
System.out.println("+++++++++++++++++++++++++++++++++++");
long now = System.nanoTime();
delta+=(now - lastTime) / ns;
lastTime = now;
if(!holder.getSurface().isValid()){continue;}
canvas = holder.lockCanvas();
SCREEN_W = canvas.getWidth();
SCREEN_H= canvas.getHeight();
while (delta >-1) {
tick();
delta--;
}
level.level1();
render(canvas);
holder.unlockCanvasAndPost(canvas);
if(ControlPanel.PLAYER_POWER <=0){
System.out.println("Loose!");
ControlPanel.PLAYER_POWER = 100;
stop();
start();
}
}
}
private void render(Canvas c) {
handler.render(c);
textOnScreen(c);
}
public void tick(){
handler.tick();
}
public void init(){
System.out.println("Init game...");
ControlPanel.COINS = pref.getInt("coins");
MainActivity.music.backgroundMusic();
handler.addSpaceShip(new Player(500, 500, 10, 10, handler, Sprite.getSprite(0)));
// handler.addKing(new King(Game.SCREEN_W / 2, 100,
// 40, 40, handler, Sprite.getSprite(18), 0));
}
public void start() {
if(thread==null){
System.out.println("Start thread");
thread = new Thread(this);
thread.start();
timer.start();
}
if(!running) running = true;
System.out.println("Running = " + running);
}
public static void stop() {
System.out.println("Stop thread");
running = false;
timer.stop();
pref.putInt("coins", ControlPanel.COINS);
System.out.println("Running = " + running);
}
public void destroyed() {
System.out.println("Stop");
running = false;
try {
thread.join(300);
thread.interrupt();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void textOnScreen(Canvas c){
p = new Paint();
p.setColor(Color.YELLOW);
p.setTextSize(50);
c.drawText("POWER = " + ControlPanel.PLAYER_POWER, SCREEN_W / 2 ,50 , p);
c.drawText("Time = " + timer.timeFormat(), 100 ,50 , p);
c.drawText("Coins = " + ControlPanel.COINS, 10 ,SCREEN_H - 10 , p);
p.setColor(Color.WHITE);
c.drawText("Bullets = " +ControlPanel.BULLET, SCREEN_W - 390,SCREEN_H - 10 , p);
p.setColor(Color.WHITE);
c.drawText(ControlPanel.Distance + " km ", SCREEN_W /2 - 200,SCREEN_H - 10 , p);
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
System.out.println("###surface created!");
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
System.out.println("###surface Changed!");
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
System.out.println("###surface Destroid!");
}
}
and here is my Dialog class:
public class DialogPause extends Dialog implements android.view.View.OnClickListener{
Button btn;
public DialogPause(Context context) {
super(context);
setContentView(R.layout.pause_game);
Game.running = false;
btn = (Button) findViewById(R.id.resume);
btn.setOnClickListener(this);
}
#Override
public void onClick(View v) {
if(v.getId() == R.id.resume){
Game.running = true;
this.dismiss();
}
}
}
and my MainActivity class:
public class MainActivity extends Activity implements OnTouchListener {
public Game game;
public static Music music;
#SuppressLint("ClickableViewAccessibility")
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Full screen
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
music = new Music(this);
game = new Game(this);
game.setOnTouchListener(this);
setContentView(game);
}
protected void onStart() {
game.start();
super.onStart();
}
#Override
protected void onStop() {
music.StopBackgroundMusic();
game.destroyed();
super.onStop();
}
#Override
public void onBackPressed() {
new DialogPause(this).show();
}
#SuppressLint("ClickableViewAccessibility")
#Override
public boolean onTouch(View v, MotionEvent event) {
try {
//the x and y point
float x = event.getX();
float y = event.getY();
//The w and h of the space ship
int spaceShipW = Game.handler.spaceShip.get(0).getSprite().getWidth();
int spaceShipH = Game.handler.spaceShip.get(0).getSprite().getWidth();
//Moving
if( x > 10 || x > Game.SCREEN_W - spaceShipW ){
Game.handler.spaceShip.get(0).setX((int) x - (spaceShipW / 2) - 64);
Game.handler.spaceShip.get(0).setY((int) y - (spaceShipH +200) );
}
//Shooting
Bullet.shoot(y, x);
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN :
//Change sprite image when click
Game.handler.spaceShip.get(0).getSprite().setWhatColumnX(0);
Game.handler.spaceShip.get(0).getSprite().setFramesToAnimate(2);
case MotionEvent.ACTION_MOVE :
break;
case MotionEvent.ACTION_UP :
//Change sprite image when release
Game.handler.spaceShip.get(0).getSprite().setWhatColumnX(1);
Game.handler.spaceShip.get(0).getSprite().setFramesToAnimate(0);
break;
default:
break;
}
} catch (Exception e) {
}
return true;
}
}
By the way i will like to hear more opinions of my game loop code I created because I have sometimes crashes when I exit the game.
and how can i use some asyncTask when the game is finished to load because it's take a 4 sec until the game is load.
Thanks to all who help me I am very appreciate it!
Add a boolean value paused and whenever the back button is pressed toggle the value (paused = !paused;)
And in you loop before you call tick add a condition:
if(!paused) tick();
It's better to simply not mess with the thread.