I am trying to use one MainActivity.java class in Android Studio to control an RC car, I am still in the works as this is an early prototype code.
I am currently struggling on why my surfaceHolder.getSurface().isValid() is returning false every time. I cannot find any help besides implementing a Callback class, however, previously I have been able to use precisely the same lines of code mimicking my surfaceHolder and never needed a Callback class, the only exception was the class extended SurfaceView which this one does not because I can only extend one class. Below is my code:
package com.example.hughman.cccontrol;
import android.graphics.Point;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Display;
import android.view.MotionEvent;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.view.SurfaceView;
import android.view.SurfaceHolder;
import android.widget.ImageButton;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
public class MainActivity extends AppCompatActivity implements View.OnClickListener, Runnable{
private ImageButton breakButton, connectButton;
private Bitmap left_thumb, left_thumb_resized, right_thumb_resized;
private Context context;
private int screenW, screenH, thumb_x, thumb_y, drag_x, drag_y, current_thumb = -1;
private Canvas canvas;
private Paint paint = new Paint();
private SurfaceHolder surfaceHolder;
private Thread thread;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
SurfaceView surfaceView = new SurfaceView(this);
paint.setAntiAlias(true);
//puts the app in full screen mode
requestWindowFeature(Window.FEATURE_NO_TITLE);
this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.activity_main);
surfaceHolder = surfaceView.getHolder();
//initalize screen size
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
screenH = size.x;
screenW = size.x;
//initialize buttons
breakButton = findViewById(R.id.breakbutton);
connectButton = findViewById(R.id.connectbutton);
breakButton.setOnClickListener(this);
connectButton.setOnClickListener(this);
left_thumb = BitmapFactory.decodeResource(this.getResources(), R.drawable.thumbstick);
left_thumb_resized = Bitmap.createScaledBitmap(left_thumb, 500, 500, false);
right_thumb_resized = Bitmap.createScaledBitmap(left_thumb, 500, 500, false);
thread = new Thread(this);
thread.start();
}
#Override
public void run() {
if(current_thumb == -1) {
drawInitialBitmap();
}
else
{
reDraw(drag_x, drag_y);
}
System.out.println("Run Test");
setFPS();
}
public void drawInitialBitmap()
{
thumb_x = 800;
thumb_y = (screenH / 2) + 250;
if (surfaceHolder.getSurface().isValid()) {
System.out.println("Hello");
canvas = surfaceHolder.lockCanvas();
canvas.drawBitmap(left_thumb_resized, thumb_x, thumb_y, paint);
canvas.drawBitmap(right_thumb_resized, thumb_x * 2, thumb_y, paint);
surfaceHolder.unlockCanvasAndPost(canvas);
}
}
public void reDraw(int x, int y)
{
if (surfaceHolder.getSurface().isValid()) {
canvas = surfaceHolder.lockCanvas();
if (current_thumb == 1) {
canvas.drawBitmap(left_thumb_resized, x, y, paint);
} else if (current_thumb == 2) {
canvas.drawBitmap(right_thumb_resized, x, y, paint);
}
surfaceHolder.unlockCanvasAndPost(canvas);
}
}
//method for when user selects an xml button
public void onClick(View v) {
if (v == connectButton) {
//prompts to connect to Bluetooth
System.out.println("ConectButton");
}
else if(v == breakButton)
{
System.out.println("BreakButton");
//halt all motors
}
}
public boolean onTouchEvent(MotionEvent event){
int action = event.getAction();
int drag_x = (int) event.getX(); // or getRawX();
int drag_y = (int) event.getY();
switch(action){
case MotionEvent.ACTION_DOWN:
if (drag_x >= thumb_x && drag_x < (thumb_x + left_thumb_resized.getWidth())
&& drag_y >= thumb_y && drag_y < (thumb_y + left_thumb_resized.getHeight())) {
current_thumb = 1;
return true;
}
else if (drag_x >= thumb_x * 2 && drag_x < ((thumb_x * 2) + right_thumb_resized.getWidth())
&& drag_y >= thumb_y && drag_y < (thumb_y + right_thumb_resized.getHeight())) {
current_thumb = 2;
return true;
}
break;
case MotionEvent.ACTION_MOVE:
if(current_thumb != -1)
{
System.out.println(Math.sqrt(Math.pow(drag_x - thumb_x, 2) + Math.pow(drag_y - thumb_y, 2)));
System.out.println(Math.sqrt(Math.pow(drag_x - (thumb_x * 2), 2) + Math.pow(drag_y - thumb_y, 2)));
//move left thumb
return true;
}
break;
case MotionEvent.ACTION_UP:
current_thumb = -1;
drawInitialBitmap();
break;
default:
}
return false;
}
public void setFPS() {
try {
thread.sleep(17);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Everything runs fine and builds properly, but neither thumb sticks are being drawn. I haven't restricted the movement of the thumb sticks, but later on I will add that. As for now, I want to be able to drag them in the direction I want to move, using the distance function to simply figure out how far I ideally want to be able to drag them.
Is it possible to do this without extending SufaceView? Or making a Callback class? Why? Below I will add the code from my previous project where I did not use a Callback class, keep in mind the code is messy as we had multiple people working on the project and it had a required deadline of 24 hours.
package com.example.michael.doyouknowdeway;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.widget.ImageButton;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.media.MediaPlayer;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
/**
* Created by michael on 1/27/18.
* The big class that does most of the work for the code, sets the overall view of the game, getting
* the character, tiles, and player motions all together for a working game. Took us the most time
* to work on with many bugs occuring along de wae.
*/
public class GameView extends SurfaceView implements Runnable{
//
volatile boolean isPlaying = true, init = true, isPassOver = true;
private Thread gameThread = null;
private SurfaceHolder surfaceHolder;
private Canvas canvas;
private Context context;
private Activity activity;
private int screenWidth = 0, screenHeight = 0, move_const = 1;
private Player player;
private MediaPlayer jumpNoise, eatNoise;
private Bitmap backgroundImage;
private MediaPlayer backgroundMusic;
private MediaPlayer endGameSound;
private Bitmap backgroundImageResized;
Tile currentTile, nextTile;
private ScheduledExecutorService executorService;
private Paint paint = new Paint();
private Paint textPaint = new Paint();
private FireBall fireball;
private int scoreCount = 0, passOver;
private Bitmap endImage;
private Bitmap endImageResized;
private Bitmap run1, podCount;
private Bitmap run1Resized, podCountResized;
private Bitmap run2;
private Bitmap playerJumpImage;
private boolean isRun1 = false;
private ImageButton redoButton;
//starts of the program, creating the background for the game based on the dimensions of the
//phone being used
public GameView(Context context, int screenX, int screenY) {
super(context);
//load images into game
backgroundImage = BitmapFactory.decodeResource(context.getResources(), R.drawable.background_sky);
backgroundImageResized = Bitmap.createScaledBitmap(backgroundImage, screenX, screenY, false);
podCount = BitmapFactory.decodeResource(context.getResources(), R.drawable.detergent_pod);
run1 = BitmapFactory.decodeResource(context.getResources(), R.drawable.knuckles_run);
run1Resized = Bitmap.createScaledBitmap(run1, 200, 200, false);
podCountResized = Bitmap.createScaledBitmap(podCount, 100, 100, false);
run2 = BitmapFactory.decodeResource(context.getResources(), R.drawable.ugandan_knuckle);
playerJumpImage = BitmapFactory.decodeResource(context.getResources(), R.drawable.knucklesjump);
//load sounds into game
jumpNoise = MediaPlayer.create(context, R.raw.jump_takeoff);
eatNoise = MediaPlayer.create(context, R.raw.eat_1);
backgroundMusic = MediaPlayer.create(context, R.raw.music_baby);
endGameSound = MediaPlayer.create(context, R.raw.end_game);
//initialize other important stuff
textPaint.setColor(Color.WHITE);
textPaint.setTextSize(72);
textPaint.setStyle(Paint.Style.FILL);
paint.setAntiAlias(true);
screenWidth = screenX;
screenHeight = screenY;
activity = (Activity) context;
backgroundMusic.start();
this.context = context;
player = new Player(context, screenX, screenY);
fireball = new FireBall(context, screenX, screenY);
currentTile = new Tile(context, 3, screenWidth + 400, screenHeight);
currentTile.fillTile();
surfaceHolder = getHolder();
//controls "running" animation
executorService = Executors.newSingleThreadScheduledExecutor();
executorService.scheduleAtFixedRate(new Runnable() {
#Override
public void run() {
if(!player.isJumping) {
if (!isRun1) {
run1Resized = Bitmap.createScaledBitmap(run1, 200, 200, false);
isRun1 = true;
} else {
run1Resized = Bitmap.createScaledBitmap(run2, 200, 200, false);
isRun1 = false;
}
}
}
}, 0, 200, TimeUnit.MILLISECONDS); //can change "speed" of run by altering the second param
}
/**
* Main game loop
*/
public void run() {
while (isPlaying) {
update();
draw();
setFPS();
}
}
/**
* Redraws the screen in the new positions, creating continuous movement for the game
*/
public void draw() {
if (surfaceHolder.getSurface().isValid()) {
canvas = surfaceHolder.lockCanvas();
canvas.drawColor(Color.WHITE);
canvas.drawBitmap(backgroundImageResized, 0, 0, paint);
canvas.drawBitmap(podCountResized, 0, 0, paint);
String scoreCountStr = Integer.toString(scoreCount);
if(0 >= (currentTile.getLength() * 100) - move_const)
{
currentTile = new Tile(nextTile);
isPassOver = true;
nextTile = null;
move_const = 0;
}
if(init) {
init = false;
for (int i = 0; i < currentTile.getLength(); i++) {
for (int j = currentTile.getHeight() - 1; j >= 0; j--) {
if (currentTile.getBlock(i, j) != null) {
canvas.drawBitmap(currentTile.getBlock(i, j).getImage(), (i * 100), (j * 100) + 10, paint);
}
}
}
}
else
{
for (int i = 0; i < currentTile.getLength(); i++) {
for (int j = currentTile.getHeight() - 1; j >= 0; j--) {
if (currentTile.getBlock(i, j) != null) {
canvas.drawBitmap(currentTile.getBlock(i, j).getImage(), (i * 100) - move_const, (j * 100) + 10, paint);
}
if (nextTile != null) {
if (i < nextTile.getLength() && j < nextTile.getHeight()) {
if (nextTile.getBlock(i, j) != null) {
canvas.drawBitmap(nextTile.getBlock(i, j).getImage(), ((i + currentTile.getLength()) * 100) - move_const, (j * 100) + 10, paint);
}
}
}
}
}
move_const += 10;
}
if(fireball.isShooting) {
canvas.drawBitmap(fireball.getImage(), fireball.getXVal(), fireball.getYVal(), paint);
}
canvas.drawBitmap(run1Resized,player.getXVal(), player.getYVal(), paint);
canvas.drawText(scoreCountStr, 120, 80, textPaint);
//releases the canvas to be redrawn again
surfaceHolder.unlockCanvasAndPost(canvas);
}
}
/**
* updates the positions of everything on the screen if needed
*/
public void update() {
player.update();
if(fireball.isShooting) {
fireball.update(player);
}
if((((currentTile.getLength() - (screenWidth/100) )* 100) - move_const <= 200) && nextTile == null){
nextTile = currentTile.getNextTile();
}
if(player.getYVal() >= screenHeight || player.getXVal() <= 0){
gameOver();
}
detectCollisions();
}
//initially sets player to not be colliding - changed almost instantly
static boolean isColliding = false;
//
/**
* Detects collisions so the player can collect tide pods and jump off of surfaces.
*/
public void detectCollisions(){
int highestY = 9;
int currentX = (250 + move_const)/100;
if(currentX >= currentTile.getLength() && isPassOver)
{
passOver = -10;
isPassOver = false;
}
else
{
passOver= -25; //arbitrary
}
for(int i = 0; i < currentTile.getHeight(); i++)
{
if(currentX >= currentTile.getLength())
{
passOver += 10;
if(nextTile.getBlock(passOver/100, i) != null)
{
if(!nextTile.getBlock(passOver/100, i).isPod())
{
highestY = i;
break;
}
}
}
else if(currentTile.getBlock(currentX, i) != null)
{
if(!currentTile.getBlock(currentX, i).isPod())
{
highestY = i;
break;
}
}
else
{
highestY = -1;
}
}
checkGroundCollision(highestY);
checkTidePodCollision(currentTile, nextTile);
checkForwardCollision(nextTile, currentX, highestY, passOver);
}
/**
* Method used to check if the player has hit a wall in front of them.
* #param next - the next tile
* #param x - player x position
* #param y - player y position
* #param passOver - the location being passed over.
*/
public void checkForwardCollision(Tile next, int x, int y, int passOver)
{
boolean collision = false;
Rect rect = new Rect();
if(next != null && passOver >= 0)
{
rect.top = y * 100;
rect.bottom = screenHeight;
rect.left = passOver + (player.getBitmap().getWidth() / 2);
rect.right = passOver + (player.getBitmap().getWidth() / 2) + 100;
collision = Rect.intersects(player.getHitBox(), rect);
}
else
{
rect.top = y * 100;
rect.bottom = screenHeight;
rect.left = (x+1)* 100;
rect.right = (x+2) * 100;
collision = Rect.intersects(player.getHitBox(), rect);
}
//if collision is true, half player movement until its not true
}
/**
* Method that checks if a player has hit a tidepod, if so, adds to score count
* #param current - the current tile
* #param next - the next tile
*/
public void checkTidePodCollision(Tile current, Tile next)
{
if(next != null && !isPassOver)
{
for(double iter: next.getTidePods())
{
int x = (int) iter;
int y = (int) (iter - x)*10;
boolean hit = podCollision(x, y);
if(hit)
{
eatNoise.start();
scoreCount += 10;
System.out.println("Cur Next: " + x + " || " + y);
nextTile.setNullBlock(x, y);
return;
}
}
}
else
{
for(double iter: current.getTidePods())
{
int x = (int) iter;
double temp = x;
int y = (int) ((iter - temp)*10.00);
boolean hit = podCollision(x, y);
if(hit)
{
eatNoise.start();
scoreCount += 10;
System.out.println("Current: " + x + " || " + y);
currentTile.setNullBlock(x, y);
return;
}
}
}
}
//compliment to the previous method
private boolean podCollision(int x, int y) {
Rect tideRect = new Rect();
if(isPassOver && x < 3)
{
System.out.println("TEST: " + x + " || " + y);
tideRect.top = (y * 100);
tideRect.left = x * 100 + passOver + 10;
tideRect.right = (x + 2) * 100 + passOver;
tideRect.bottom = (y + 2) * 100 + 10;
}
else {
tideRect.top = y * 100;
tideRect.left = x * 100 - move_const + 10;
tideRect.right = (x + 2) * 100 - move_const;
tideRect.bottom = (y + 2) * 100 + 10;
}
return Rect.intersects(player.getHitBox(), tideRect);
}
/**
* Method used for jumping off of the ground.
* #param highestY
*/
private void checkGroundCollision(int highestY) {
Rect blockRect = new Rect();
boolean GroundCollision;
if(highestY >= 0) {
blockRect.top = (highestY) * 100 - 25;
blockRect.left = 200;
blockRect.right = 300;
//changed this valued -- this is to remind myself
blockRect.bottom = highestY * 100 + 25; //still needs work //make player hitbox just his feet
GroundCollision = Rect.intersects(player.getFeetBox(), blockRect);
System.out.println("WWWWWW : " + GroundCollision);
}
else
{
GroundCollision = false;
}
if(GroundCollision){
isColliding = true;
} else {
player.isFalling = true;
isColliding = false;
}
}
/**
* Sets the FPS to roughly 60 fps
*/
public void setFPS() {
try {
gameThread.sleep(17);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
/**
* Method that
*/
public void gameOver() {
//end image is not currently working
endImage = BitmapFactory.decodeResource(context.getResources(), R.drawable.end_game);
endImageResized = Bitmap.createScaledBitmap(endImage, 100, 200, false);
canvas.drawBitmap(endImageResized, screenWidth/2, screenHeight/2, paint);
//free up memory from bitmaps
backgroundImage.recycle();
backgroundImage = null;
backgroundImageResized.recycle();
backgroundImageResized = null;
podCount.recycle();
podCount = null;
podCountResized.recycle();
podCountResized = null;
backgroundImage.recycle();
backgroundImage = null;
run1.recycle();
run1 = null;
run1Resized.recycle();
run1Resized = null;
run2.recycle();
run2 = null;
playerJumpImage.recycle();
playerJumpImage = null;
backgroundMusic.stop();
Runtime.getRuntime().gc(); //manually run garbage collector
endGameSound.start();
context.startActivity(new Intent(context,MainActivity.class));
}
/**
* Method used to dictate what to do when the android screen is touched.
* #param event - the type of touch on the screen
* #return - true when screen is touched
*/
public boolean onTouchEvent(MotionEvent event){
int touchAction = event.getAction();
if(touchAction == MotionEvent.ACTION_DOWN){
if(event.getX() < (screenWidth / 2)) {
jumpNoise.start();
if(!player.isJumping && !player.isFalling) {
player.setYval(player.getYVal());
player.isJumping = true;
run1Resized = Bitmap.createScaledBitmap(playerJumpImage, 200, 200, false);
}
else if(player.getJumpCount() < 1)
{
player.setYval(player.getYVal());
player.incrJump();
player.isJumping = true;
run1Resized = Bitmap.createScaledBitmap(playerJumpImage, 200, 200, false);
}
} else {
fireball.setOnScreen(true);
}
}
return true;
}
/**
* Method that pauses the game when necessary (i.e when home button is pressed)
*/
public void pause() {
isPlaying = false;
backgroundMusic.pause();
try {
gameThread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
/**
* Resumes the game after a pause
*/
public void resume() {
isPlaying = true;
backgroundMusic.start();
gameThread = new Thread(this);
gameThread.start();
}
}
Thank you for your time & any help is appreciated!
EDIT: Also using bitmaps to redraw etc. as that is what I am used to.
Related
I am trying to edit this game code and call a second activity in //Show Result in order to go to another screen when the game is over.
There's an error "cannot resolve contructor".
enter image description here
I think the problem is with the intent but I am not really sure about where I can put it.
Can you help me?
Thank you
This is the GameView code
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Typeface;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.content.Intent;
public class GameView extends View {
// Canvas
private int canvasWidth;
private int canvasHeight;
// J
//private Bitmap j;
private Bitmap j[] = new Bitmap[2];
private int jX = 10;
private int jY;
private int jSpeed;
// Blue Ball
private int blueX;
private int blueY;
private int blueSpeed = 15;
private Paint bluePaint = new Paint();
// Black Ball
private int blackX;
private int blackY;
private int blackSpeed = 20;
private Paint blackPaint = new Paint();
// Background
private Bitmap bgImage;
// Score
private Paint scorePaint = new Paint();
private int score;
// Level
private Paint levelPaint = new Paint();
// Life
private Bitmap life[] = new Bitmap[2];
private int life_count;
// Status Check
private boolean touch_flg = false;
public GameView(Context context) {
super(context);
j[0] = BitmapFactory.decodeResource(getResources(), R.drawable.jun1);
j[1] = BitmapFactory.decodeResource(getResources(), R.drawable.jun2);
bgImage = BitmapFactory.decodeResource(getResources(), R.drawable.bg);
bluePaint.setColor(Color.BLUE);
bluePaint.setAntiAlias(false);
blackPaint.setColor(Color.BLACK);
blackPaint.setAntiAlias(false);
scorePaint.setColor(Color.BLACK);
scorePaint.setTextSize(32);
scorePaint.setTypeface(Typeface.DEFAULT_BOLD);
scorePaint.setAntiAlias(true);
levelPaint.setColor(Color.DKGRAY);
levelPaint.setTextSize(32);
levelPaint.setTypeface(Typeface.DEFAULT_BOLD);
levelPaint.setTextAlign(Paint.Align.CENTER);
levelPaint.setAntiAlias(true);
life[0] = BitmapFactory.decodeResource(getResources(), R.drawable.heart);
life[1] = BitmapFactory.decodeResource(getResources(), R.drawable.heart_g);
// First position.
jY = 500;
score = 0;
life_count = 3;
}
#Override
protected void onDraw(Canvas canvas) {
canvasWidth = canvas.getWidth();
canvasHeight = canvas.getHeight();
canvas.drawBitmap(bgImage, 0, 0, null);
// Bird
int minBirdY = j[0].getHeight();
int maxBirdY = canvasHeight - j[0].getHeight() * 3;
jY += jSpeed;
if (jY < minBirdY) jY = minBirdY;
if (jY > maxBirdY) jY = maxBirdY;
jSpeed += 2;
if (touch_flg) {
// Flap wings.
canvas.drawBitmap(j[1], jX, jY, null);
touch_flg = false;
} else {
canvas.drawBitmap(j[0], jX, jY, null);
}
// Blue
blueX -= blueSpeed;
if (hitCheck(blueX, blueY)) {
score += 10;
blueX = -100;
}
if (blueX < 0) {
blueX = canvasWidth + 20;
blueY = (int) Math.floor(Math.random() * (maxBirdY - minBirdY)) + minBirdY;
}
canvas.drawCircle(blueX, blueY, 10, bluePaint);
// Black
blackX -= blackSpeed;
if (hitCheck(blackX, blackY)) {
blackX = -100;
life_count--;
if (life_count == 0) {
// Show Result
Intent i = new Intent(this, result.class);
i.putExtra("SCORE", score);
}
}
if (blackX < 0) {
blackX = canvasWidth + 200;
blackY = (int) Math.floor(Math.random() * (maxBirdY - minBirdY)) + minBirdY;
}
canvas.drawCircle(blackX, blackY, 20, blackPaint);
// Score
canvas.drawText("Score : " + score, 20, 60, scorePaint);
// Level
canvas.drawText("Lv.1", canvasWidth / 2, 60, levelPaint);
// Life
for (int i = 0; i < 3; i++) {
int x = (int) (560 + life[0].getWidth() * 1.5 * i);
int y = 30;
if (i < life_count) {
canvas.drawBitmap(life[0], x, y, null);
} else {
canvas.drawBitmap(life[1], x, y, null);
}
}
}
public boolean hitCheck(int x, int y) {
if (jX < x && x < (jX + j[0].getWidth()) &&
jY < y && y < (jY + j[0].getHeight())) {
return true;
}
return false;
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
touch_flg = true;
jSpeed = -20;
}
return true;
}
}
View doesn't extend the Context class, which Intent's constructor needs for what you're doing.
Use
Intent i = new Intent(getContext(), result.class);
in your View class.
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;
}
}
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);
}
}
What is the best way drawing a hero and moving it? I just need the best code for doing that. Before writing this i found a way, but when i made the surface holder transparent, i realised that the code is drawing new bitmap in the front of the old one every milisecond. That way looks kind of laggy to me, but maymie i'm not right. Please help me. Actualy i'm kind of confused...
Anyway, here's the code that i think is laggy:
MainThread.java
/**
*
*/
package com.workspace.pockethero;
import android.graphics.Canvas;
import android.util.Log;
import android.view.SurfaceHolder;
/**
* #author impaler
*
* The Main thread which contains the game loop. The thread must have access to
* the surface view and holder to trigger events every game tick.
*/
public class MainThread extends Thread {
private static final String TAG = MainThread.class.getSimpleName();
// Surface holder that can access the physical surface
private SurfaceHolder surfaceHolder;
// The actual view that handles inputs
// and draws to the surface
private MainGamePanel gamePanel;
// flag to hold game state
private boolean running;
public void setRunning(boolean running) {
this.running = running;
}
public MainThread(SurfaceHolder surfaceHolder, MainGamePanel gamePanel) {
super();
this.surfaceHolder = surfaceHolder;
this.gamePanel = gamePanel;
}
#Override
public void run() {
Canvas canvas;
canvas = this.surfaceHolder.lockCanvas();
Log.d(TAG, "Starting game loop");
while (running) {
canvas = null;
// try locking the canvas for exclusive pixel editing
// in the surface
try {
synchronized (surfaceHolder) {
// update game state
this.gamePanel.update();
// render state to the screen
// draws the canvas on the panel
this.gamePanel.render(canvas);
}
} finally {
// in case of an exception the surface is not left in
// an inconsistent state
if (canvas != null) {
surfaceHolder.unlockCanvasAndPost(canvas);
}
} // end finally
}
}
}
MainGamePanel.java
/**
*
*/
package com.workspace.pockethero;
import com.workspace.pockethero.model.Droid;
import com.workspace.pockethero.buttons.*;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
/**
* #author impaler
* This is the main surface that handles the ontouch events and draws
* the image to the screen.
*/
public class MainGamePanel extends SurfaceView implements
SurfaceHolder.Callback {
private static final String TAG = MainGamePanel.class.getSimpleName();
private MainThread thread;
public Droid droid;
public Butt butt;
public Butt1 butt1;
public Butt2 butt2;
public Butt3 butt3;
public Buttz buttz;
public Buttz1 buttz1;
public Buttz2 buttz2;
public Buttz3 buttz3;
public Buttx buttx;
public Build build;
public int decentreX;
public int decentreY;
public int debottomA;
public boolean moved;
public boolean moved1;
public boolean moved2;
public boolean moved3;
public boolean moved4;
public boolean moved5;
public boolean moved6;
public boolean moved7;
private Drawable myImage;
public boolean mapPainted;
public MainGamePanel(Context context) {
super(context);
// adding the callback (this) to the surface holder to intercept events
getHolder().addCallback(this);
// create droid and load bitmap
decentreX = PocketHero.centreX;
decentreY = PocketHero.centreY;
debottomA = PocketHero.bottomA;
droid = new Droid(BitmapFactory.decodeResource(getResources(), R.drawable.herod), decentreX, decentreY);
butt = new Butt(BitmapFactory.decodeResource(getResources(), R.drawable.button), 110, debottomA - 70);
butt1 = new Butt1(BitmapFactory.decodeResource(getResources(), R.drawable.button1), 70, debottomA - 110);
butt2 = new Butt2(BitmapFactory.decodeResource(getResources(), R.drawable.button2), 30, debottomA - 70);
butt3 = new Butt3(BitmapFactory.decodeResource(getResources(), R.drawable.button3), 70, debottomA - 30);
buttz = new Buttz(BitmapFactory.decodeResource(getResources(), R.drawable.zbutton), 110, debottomA - 110);
buttz1 = new Buttz1(BitmapFactory.decodeResource(getResources(), R.drawable.zbutton1), 30, debottomA - 110);
buttz2 = new Buttz2(BitmapFactory.decodeResource(getResources(), R.drawable.zbutton2), 30, debottomA - 30);
buttz3 = new Buttz3(BitmapFactory.decodeResource(getResources(), R.drawable.zbutton3), 110, debottomA - 30);
buttx = new Buttx(BitmapFactory.decodeResource(getResources(), R.drawable.xbutton), 70, debottomA - 70);
build = new Build(BitmapFactory.decodeResource(getResources(), R.drawable.building), 500, 200);
// create the game loop thread
//300 indicates start position of bitmapfield on screen
thread = new MainThread(getHolder(), this);
// make the GamePanel focusable so it can handle events
setFocusable(true);
this.setOnTouchListener(new OnTouchListener() {
public boolean onTouch(View V, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
// delegating event handling to the droid
handleActionDown((int)event.getX(), (int)event.getY());
} if (event.getAction() == MotionEvent.ACTION_MOVE) {
handleActionDown((int)event.getX(), (int)event.getY());
// the gestures
} if (event.getAction() == MotionEvent.ACTION_UP) {
// touch was released
if (droid.touched) {
droid.setTouched(false);
}
if (droid.touched1) {
droid.setTouched1(false);
}
if (droid.touched2) {
droid.setTouched2(false);
}
if (droid.touched3) {
droid.setTouched3(false);
}
}
return true;
}
});
}
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
}
public void surfaceCreated(SurfaceHolder holder) {
// at this point the surface is created and
// we can safely start the game loop
thread.setRunning(true);
thread.start();
}
public void surfaceDestroyed(SurfaceHolder holder) {
Log.d(TAG, "Surface is being destroyed");
// tell the thread to shut down and wait for it to finish
// this is a clean shutdown
boolean retry = true;
while (retry) {
try {
thread.join();
retry = false;
} catch (InterruptedException e) {
// try again shutting down the thread
}
}
Log.d(TAG, "Thread was shut down cleanly");
}
public void render(Canvas canvas) {
canvas.drawColor(Color.TRANSPARENT);
droid.draw(canvas);
butt.draw(canvas);
butt1.draw(canvas);
butt2.draw(canvas);
butt3.draw(canvas);
buttz.draw(canvas);
buttz1.draw(canvas);
buttz2.draw(canvas);
buttz3.draw(canvas);
buttx.draw(canvas);
}
/**
* This is the game update method. It iterates through all the objects
* and calls their update method if they have one or calls specific
* engine's update method.
*/
public void update() {
droid.update();
}
public void handleActionDown(int eventX, int eventY) {
if (eventX >= (butt.x - butt.bitmap.getWidth() / 2) && (eventX <= (butt.x + butt.bitmap.getWidth()/2))) {
if (eventY >= (buttz.y - buttz.bitmap.getHeight() / 2) && (eventY <= (buttz3.y + buttz3.bitmap.getHeight() / 2))) {
// droid touched
droid.setTouched(true);
} else {
droid.setTouched(false);
}
} else {
droid.setTouched(false);
}
if (eventX >= (buttz1.x - buttz1.bitmap.getWidth() / 2) && (eventX <= (buttz.x + buttz.bitmap.getWidth()/2))) {
if (eventY >= (butt1.y - butt1.bitmap.getHeight() / 2) && (eventY <= (butt1.y + butt1.bitmap.getHeight() / 2))) {
// droid touched
droid.setTouched1(true);
} else {
droid.setTouched1(false);
}
}else {
droid.setTouched1(false);
}
if (eventX >= (butt2.x - butt2.bitmap.getWidth() / 2) && (eventX <= (butt2.x + butt2.bitmap.getWidth()/2))) {
if (eventY >= (buttz1.y - buttz1.bitmap.getHeight() / 2) && (eventY <= (buttz2.y + buttz2.bitmap.getHeight() / 2))) {
// droid touched
droid.setTouched2(true);
} else {
droid.setTouched2(false);
}
}else {
droid.setTouched2(false);
}
if (eventX >= (buttz2.x - buttz2.bitmap.getWidth() / 2) && (eventX <= (buttz3.x + buttz3.bitmap.getWidth()/2))) {
if (eventY >= (butt3.y - butt3.bitmap.getHeight() / 2) && (eventY <= (butt3.y + butt3.bitmap.getHeight() / 2))) {
// droid touched
droid.setTouched3(true);
} else {
droid.setTouched3(false);
}
}else {
droid.setTouched3(false);
}
if (droid.touched & !droid.touched1 & !droid.touched3) {
if (!moved) {
droid.bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.heror);
moved = true;
}
}else {
moved = false;
}if (droid.touched1 & !droid.touched & !droid.touched2){
if (!moved1) {
droid.bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.herou);
moved1 = true;
}
}else {
moved1 = false;
} if (droid.touched2 & !droid.touched1 & !droid.touched3){
if (!moved2) {
droid.bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.herol);
moved2 = true;
}
}else {
moved2 = false;
} if (droid.touched3 & !droid.touched2 & !droid.touched){
if (!moved7) {
droid.bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.herod);
moved7 = true;
}
}else {
moved7 = false;
} if (droid.touched & droid.touched1){
if (!moved3) {
droid.bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.herour);
moved3 = true;
}
}else {
moved3 = false;
} if (droid.touched1 & droid.touched2){
if (!moved4) {
droid.bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.heroul);
moved4 = true;
}
}else {
moved4 = false;
} if (droid.touched2 & droid.touched3){
if (!moved5) {
droid.bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.herodl);
moved5 = true;
}
}else {
moved5 = false;
} if (droid.touched3 & droid.touched){
if (!moved6) {
droid.bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.herodr);
moved6 = true;
}
}else {
moved6 = false;
}
}
}
and the Droid.java
/**
*
*/
package com.workspace.pockethero.model;
import android.graphics.Bitmap;
import android.graphics.Canvas;
/**
* This is a test droid that is dragged, dropped, moved, smashed against
* the wall and done other terrible things with.
* Wait till it gets a weapon!
*
* #author impaler
*
*/
public class Droid {
public Bitmap bitmap; // the actual bitmap
public int x; // the X coordinate
public int y; // the Y coordinate
public boolean touched; // if droid is touched/picked up
public boolean touched1; // if droid is touched/picked up
public boolean touched2; // if droid is touched/picked up
public boolean touched3; // if droid is touched/picked up
public Droid(Bitmap bitmap, int x, int y) {
this.bitmap = bitmap;
this.x = x;
this.y = y;
}
public Bitmap getBitmap() {
return bitmap;
}
public void setBitmap(Bitmap bitmap) {
this.bitmap = bitmap;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public void draw(Canvas canvas) {
canvas.drawBitmap(bitmap, x - (bitmap.getWidth() / 2), y - (bitmap.getHeight() / 2), null);
}
/**
* Method which updates the droid's internal state every tick
*/
public void setTouched(boolean touched) {
this.touched = touched;
}
public boolean isTouched() {
return touched;
}
public void setTouched1(boolean touched) {
this.touched1 = touched;
}
public boolean isTouched1() {
return touched1;
}
public void setTouched2(boolean touched) {
this.touched2 = touched;
}
public boolean isTouched2() {
return touched2;
}
public void setTouched3(boolean touched) {
this.touched3 = touched;
}
public boolean isTouched3() {
return touched3;
}
public void update() {
if (touched & !touched1 & !touched3) {
x += 1;
}else if (touched1 & !touched & !touched2){
y -= 1;
}else if (touched2 & !touched1 & !touched3){
x -= 1;
}else if (touched3 & !touched2 & !touched){
y += 1;
}else if (touched & touched1){
x += 1;
y -= 1;
}else if (touched1 & touched2){
x -= 1;
y -= 1;
}else if (touched2 & touched3){
x -= 1;
y += 1;
}else if (touched3 & touched){
x += 1;
y += 1;
}
}
/**
* Handles the {#link MotionEvent.ACTION_DOWN} event. If the event happens on the
* bitmap surface then the touched state is set to <code>true</code> otherwise to <code>false</code>
* #param eventX - the event's X coordinate
* #param eventY - the event's Y coordinate
*/
}
there are also other classes created for each button, but i didnt pasted them here, because the are practicly the same as droid.java
Re-drawing the whole frame each loop is the correct way to draw/move sprites and perform anything with canvas.
The buffer is cleared each frame and you need to re-draw the background and all objects at their specified position.
In your code render() and update() will not be called more frequently than approximately every 16milliseconds~ (60 frames per second), so all you have to think about is drawing the onscreen scene.
I'm not sure what you mean by 'laggy', maybe you have a performance issue related to the size of your Bitmaps or phone performance, but I hope this is close to what you were looking for.
Please help with the following code - I need a dialog box with a button to appear when the game puzzle is completed. Thank you!
Here's the code:
Sudoku.java
package org.example.sudoku;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
public class Sudoku extends Activity implements OnClickListener {
private static final String TAG = "Sudoku";
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// Set up click listeners for all the buttons
View continueButton = findViewById(R.id.continue_button);
continueButton.setOnClickListener(this);
View newButton = findViewById(R.id.new_button);
newButton.setOnClickListener(this);
View aboutButton = findViewById(R.id.about_button);
aboutButton.setOnClickListener(this);
View exitButton = findViewById(R.id.exit_button);
exitButton.setOnClickListener(this);
}
#Override
protected void onResume() {
super.onResume();
Music.play(this, R.raw.main);
}
#Override
protected void onPause() {
super.onPause();
Music.stop(this);
}
public void onClick(View v) {
switch (v.getId()) {
case R.id.continue_button:
startGame(Game.DIFFICULTY_CONTINUE);
break;
// ...
case R.id.about_button:
Intent i = new Intent(this, About.class);
startActivity(i);
break;
// More buttons go here (if any) ...
case R.id.new_button:
openNewGameDialog();
break;
case R.id.exit_button:
finish();
break;
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.settings:
startActivity(new Intent(this, Prefs.class));
return true;
// More items go here (if any) ...
}
return false;
}
/** Ask the user what difficulty level they want */
private void openNewGameDialog() {
new AlertDialog.Builder(this)
.setTitle(R.string.new_game_title)
.setItems(R.array.difficulty,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialoginterface,
int i) {
startGame(i);
}
})
.show();
}
/** Start a new game with the given difficulty level */
private void startGame(int i) {
Log.d(TAG, "clicked on " + i);
Intent intent = new Intent(Sudoku.this, Game.class);
intent.putExtra(Game.KEY_DIFFICULTY, i);
startActivity(intent);
}
}
Game.Java
package org.example.sudoku;
import android.app.Activity;
import android.app.Dialog;
import android.os.Bundle;
import android.util.Log;
import android.view.Gravity;
import android.widget.Toast;
public class Game extends Activity {
private static final String TAG = "Sudoku";
public static final String KEY_DIFFICULTY =
"org.example.sudoku.difficulty";
private static final String PREF_PUZZLE = "puzzle" ;
public static final int DIFFICULTY_EASY = 0;
public static final int DIFFICULTY_MEDIUM = 1;
public static final int DIFFICULTY_HARD = 2;
protected static final int DIFFICULTY_CONTINUE = -1;
private int puzzle[] = new int[9 * 9];
private final String easyPuzzle =
"360000000004230800000004200" +
"070460003820000014500013020" +
"001900000007048300000000045";
private final String mediumPuzzle =
"650000070000506000014000005" +
"007009000002314700000700800" +
"500000630000201000030000097";
private final String hardPuzzle =
"009000000080605020501078000" +
"000000700706040102004000000" +
"000720903090301080000000600";
private PuzzleView puzzleView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "onCreate");
int diff = getIntent().getIntExtra(KEY_DIFFICULTY,
DIFFICULTY_EASY);
puzzle = getPuzzle(diff);
calculateUsedTiles();
puzzleView = new PuzzleView(this);
setContentView(puzzleView);
puzzleView.requestFocus();
// ...
// If the activity is restarted, do a continue next time
getIntent().putExtra(KEY_DIFFICULTY, DIFFICULTY_CONTINUE);
}
#Override
protected void onResume() {
super.onResume();
Music.play(this, R.raw.game);
}
#Override
protected void onPause() {
super.onPause();
Log.d(TAG, "onPause");
Music.stop(this);
// Save the current puzzle
getPreferences(MODE_PRIVATE).edit().putString(PREF_PUZZLE,
toPuzzleString(puzzle)).commit();
}
/** Given a difficulty level, come up with a new puzzle */
private int[] getPuzzle(int diff) {
String puz;
switch (diff) {
case DIFFICULTY_CONTINUE:
puz = getPreferences(MODE_PRIVATE).getString(PREF_PUZZLE,
easyPuzzle);
break;
// ...
case DIFFICULTY_HARD:
puz = hardPuzzle;
break;
case DIFFICULTY_MEDIUM:
puz = mediumPuzzle;
break;
case DIFFICULTY_EASY:
default:
puz = easyPuzzle;
break;
}
return fromPuzzleString(puz);
}
/** Convert an array into a puzzle string */
static private String toPuzzleString(int[] puz) {
StringBuilder buf = new StringBuilder();
for (int element : puz) {
buf.append(element);
}
return buf.toString();
}
/** Convert a puzzle string into an array */
static protected int[] fromPuzzleString(String string) {
int[] puz = new int[string.length()];
for (int i = 0; i < puz.length; i++) {
puz[i] = string.charAt(i) - '0';
}
return puz;
}
/** Return the tile at the given coordinates */
private int getTile(int x, int y) {
return puzzle[y * 9 + x];
}
/** Change the tile at the given coordinates */
private void setTile(int x, int y, int value) {
puzzle[y * 9 + x] = value;
}
/** Return a string for the tile at the given coordinates */
protected String getTileString(int x, int y) {
int v = getTile(x, y);
if (v == 0)
return "";
else
return String.valueOf(v);
}
/** Change the tile only if it's a valid move */
protected boolean setTileIfValid(int x, int y, int value) {
int tiles[] = getUsedTiles(x, y);
if (value != 0) {
for (int tile : tiles) {
if (tile == value)
return false;
}
}
setTile(x, y, value);
calculateUsedTiles();
return true;
}
/** Open the keypad if there are any valid moves */
protected void showKeypadOrError(int x, int y) {
int tiles[] = getUsedTiles(x, y);
if (tiles.length == 9) {
Toast toast = Toast.makeText(this,
R.string.no_moves_label, Toast.LENGTH_SHORT);
toast.setGravity(Gravity.CENTER, 0, 0);
toast.show();
} else {
Log.d(TAG, "showKeypad: used=" + toPuzzleString(tiles));
Dialog v = new Keypad(this, tiles, puzzleView);
v.show();
}
}
/** Cache of used tiles */
private final int used[][][] = new int[9][9][];
/** Return cached used tiles visible from the given coords */
protected int[] getUsedTiles(int x, int y) {
return used[x][y];
}
/** Compute the two dimensional array of used tiles */
private void calculateUsedTiles() {
for (int x = 0; x < 9; x++) {
for (int y = 0; y < 9; y++) {
used[x][y] = calculateUsedTiles(x, y);
// Log.d(TAG, "used[" + x + "][" + y + "] = "
// + toPuzzleString(used[x][y]));
}
}
}
/** Compute the used tiles visible from this position */
private int[] calculateUsedTiles(int x, int y) {
int c[] = new int[9];
// horizontal
for (int i = 0; i < 9; i++) {
if (i == y)
continue;
int t = getTile(x, i);
if (t != 0)
c[t - 1] = t;
}
// vertical
for (int i = 0; i < 9; i++) {
if (i == x)
continue;
int t = getTile(i, y);
if (t != 0)
c[t - 1] = t;
}
// same cell block
int startx = (x / 3) * 3;
int starty = (y / 3) * 3;
for (int i = startx; i < startx + 3; i++) {
for (int j = starty; j < starty + 3; j++) {
if (i == x && j == y)
continue;
int t = getTile(i, j);
if (t != 0)
c[t - 1] = t;
}
}
// compress
int nused = 0;
for (int t : c) {
if (t != 0)
nused++;
}
int c1[] = new int[nused];
nused = 0;
for (int t : c) {
if (t != 0)
c1[nused++] = t;
}
return c1;
}
}
PuzzleView.java
package org.example.sudoku;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.Paint.FontMetrics;
import android.graphics.Paint.Style;
import android.os.Bundle;
import android.os.Parcelable;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.AnimationUtils;
public class PuzzleView extends View {
private static final String TAG = "Sudoku";
private static final String SELX = "selX";
private static final String SELY = "selY";
private static final String VIEW_STATE = "viewState";
private static final int ID = 42;
private float width; // width of one tile
private float height; // height of one tile
private int selX; // X index of selection
private int selY; // Y index of selection
private final Rect selRect = new Rect();
private final Game game;
public PuzzleView(Context context) {
super(context);
this.game = (Game) context;
setFocusable(true);
setFocusableInTouchMode(true);
// ...
setId(ID);
}
#Override
protected Parcelable onSaveInstanceState() {
Parcelable p = super.onSaveInstanceState();
Log.d(TAG, "onSaveInstanceState");
Bundle bundle = new Bundle();
bundle.putInt(SELX, selX);
bundle.putInt(SELY, selY);
bundle.putParcelable(VIEW_STATE, p);
return bundle;
}
#Override
protected void onRestoreInstanceState(Parcelable state) {
Log.d(TAG, "onRestoreInstanceState");
Bundle bundle = (Bundle) state;
select(bundle.getInt(SELX), bundle.getInt(SELY));
super.onRestoreInstanceState(bundle.getParcelable(VIEW_STATE));
return;
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
width = w / 9f;
height = h / 9f;
getRect(selX, selY, selRect);
Log.d(TAG, "onSizeChanged: width " + width + ", height "
+ height);
super.onSizeChanged(w, h, oldw, oldh);
}
#Override
protected void onDraw(Canvas canvas) {
// Draw the background...
Paint background = new Paint();
background.setColor(getResources().getColor(
R.color.puzzle_background));
canvas.drawRect(0, 0, getWidth(), getHeight(), background);
// Draw the board...
// Define colors for the grid lines
Paint dark = new Paint();
dark.setColor(getResources().getColor(R.color.puzzle_dark));
Paint hilite = new Paint();
hilite.setColor(getResources().getColor(R.color.puzzle_hilite));
Paint light = new Paint();
light.setColor(getResources().getColor(R.color.puzzle_light));
// Draw the minor grid lines
for (int i = 0; i < 9; i++) {
canvas.drawLine(0, i * height, getWidth(), i * height,
light);
canvas.drawLine(0, i * height + 1, getWidth(), i * height
+ 1, hilite);
canvas.drawLine(i * width, 0, i * width, getHeight(),
light);
canvas.drawLine(i * width + 1, 0, i * width + 1,
getHeight(), hilite);
}
// Draw the major grid lines
for (int i = 0; i < 9; i++) {
if (i % 3 != 0)
continue;
canvas.drawLine(0, i * height, getWidth(), i * height,
dark);
canvas.drawLine(0, i * height + 1, getWidth(), i * height
+ 1, hilite);
canvas.drawLine(i * width, 0, i * width, getHeight(), dark);
canvas.drawLine(i * width + 1, 0, i * width + 1,
getHeight(), hilite);
}
// Draw the numbers...
// Define color and style for numbers
Paint foreground = new Paint(Paint.ANTI_ALIAS_FLAG);
foreground.setColor(getResources().getColor(
R.color.puzzle_foreground));
foreground.setStyle(Style.FILL);
foreground.setTextSize(height * 0.75f);
foreground.setTextScaleX(width / height);
foreground.setTextAlign(Paint.Align.CENTER);
// Draw the number in the center of the tile
FontMetrics fm = foreground.getFontMetrics();
// Centering in X: use alignment (and X at midpoint)
float x = width / 2;
// Centering in Y: measure ascent/descent first
float y = height / 2 - (fm.ascent + fm.descent) / 2;
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
canvas.drawText(this.game.getTileString(i, j), i
* width + x, j * height + y, foreground);
}
}
if (Prefs.getHints(getContext())) {
// Draw the hints...
// Pick a hint color based on #moves left
Paint hint = new Paint();
int c[] = { getResources().getColor(R.color.puzzle_hint_0),
getResources().getColor(R.color.puzzle_hint_1),
getResources().getColor(R.color.puzzle_hint_2), };
Rect r = new Rect();
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
int movesleft = 9 - game.getUsedTiles(i, j).length;
if (movesleft < c.length) {
getRect(i, j, r);
hint.setColor(c[movesleft]);
canvas.drawRect(r, hint);
}
}
}
}
// Draw the selection...
Log.d(TAG, "selRect=" + selRect);
Paint selected = new Paint();
selected.setColor(getResources().getColor(
R.color.puzzle_selected));
canvas.drawRect(selRect, selected);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() != MotionEvent.ACTION_DOWN)
return super.onTouchEvent(event);
select((int) (event.getX() / width),
(int) (event.getY() / height));
game.showKeypadOrError(selX, selY);
Log.d(TAG, "onTouchEvent: x " + selX + ", y " + selY);
return true;
}
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
Log.d(TAG, "onKeyDown: keycode=" + keyCode + ", event="
+ event);
switch (keyCode) {
case KeyEvent.KEYCODE_DPAD_UP:
select(selX, selY - 1);
break;
case KeyEvent.KEYCODE_DPAD_DOWN:
select(selX, selY + 1);
break;
case KeyEvent.KEYCODE_DPAD_LEFT:
select(selX - 1, selY);
break;
case KeyEvent.KEYCODE_DPAD_RIGHT:
select(selX + 1, selY);
break;
case KeyEvent.KEYCODE_0:
case KeyEvent.KEYCODE_SPACE: setSelectedTile(0); break;
case KeyEvent.KEYCODE_1: setSelectedTile(1); break;
case KeyEvent.KEYCODE_2: setSelectedTile(2); break;
case KeyEvent.KEYCODE_3: setSelectedTile(3); break;
case KeyEvent.KEYCODE_4: setSelectedTile(4); break;
case KeyEvent.KEYCODE_5: setSelectedTile(5); break;
case KeyEvent.KEYCODE_6: setSelectedTile(6); break;
case KeyEvent.KEYCODE_7: setSelectedTile(7); break;
case KeyEvent.KEYCODE_8: setSelectedTile(8); break;
case KeyEvent.KEYCODE_9: setSelectedTile(9); break;
case KeyEvent.KEYCODE_ENTER:
case KeyEvent.KEYCODE_DPAD_CENTER:
game.showKeypadOrError(selX, selY);
break;
default:
return super.onKeyDown(keyCode, event);
}
return true;
}
public void setSelectedTile(int tile) {
if (game.setTileIfValid(selX, selY, tile)) {
invalidate();// may change hints
} else {
// Number is not valid for this tile
Log.d(TAG, "setSelectedTile: invalid: " + tile);
startAnimation(AnimationUtils.loadAnimation(game,
R.anim.shake));
}
}
private void select(int x, int y) {
invalidate(selRect);
selX = Math.min(Math.max(x, 0), 8);
selY = Math.min(Math.max(y, 0), 8);
getRect(selX, selY, selRect);
invalidate(selRect);
}
private void getRect(int x, int y, Rect rect) {
rect.set((int) (x * width), (int) (y * height), (int) (x
* width + width), (int) (y * height + height));
}
// ...
}
Maybe an AlertDialog?http://developer.android.com/guide/topics/ui/dialogs.html#AlertDialog