I just want to ask how to create a button using java based program. I want to have a button on my official game like Next button that if the user clicked it, it will allow them to go to the next level of the game. It's like a pause/resume/stop/restart button inside the game.
This is the code of the Game I used. I can't see the declaration of button here but when I played this, it has a exit button(?) above that allows the user to go back to previous form.
public class NewGame extends Activity {
static MediaPlayer mp1;
MediaPlayer jump;
MediaPlayer takecoin;
GameLoopThread gameLoopThread;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// for no title
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(new GameView(this));
}
public class GameView extends SurfaceView {
Bitmap bmp;
Bitmap background, taya, note1;
Bitmap run1;
Bitmap run6;
Bitmap jump2;
Bitmap coin;
Bitmap exit;
// MediaPlayer mp1,jump,takecoin;
private SurfaceHolder holder;
// private gameloop gameLoopThread;
private int x = 0, y = 0, z = 0, delay = 0, getx, gety, sound = 1;
int show = 0, sx, sy = 0;
int cspeed = 0, kspeed = 0, gameover = 0;
int score = 0, health = 120, reset = 0;
private int min = 1, sec = 0;
private Handler mHandler = new Handler();
private Runnable mRunnable;
private boolean isStop = false;
#SuppressWarnings("deprecation")
#SuppressLint("NewApi")
public GameView(Context context) {
super(context);
mHandler.postDelayed(mRunnable = new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
if(sec <= 0){
if(min > 0){
sec = 59;
min--;
isStop = false;
}
else{
//stop timer here
Log.e("TIMER", "timer stop!");
mHandler.removeCallbacks(this);
isStop = true;
}
}
else{
sec--;
isStop = false;
}
Log.i("TIMER", "min: " + min + " sec: " + sec);
if(!isStop){
mHandler.postDelayed(this, 1000);
}
}
}, 1000);
gameLoopThread = new GameLoopThread(this);
holder = getHolder();
holder.addCallback(new SurfaceHolder.Callback() {
#SuppressWarnings("deprecation")
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
// for stoping the game
gameLoopThread.setRunning(false);
gameLoopThread.getThreadGroup().interrupt();
}
#SuppressLint("WrongCall")
#Override
public void surfaceCreated(SurfaceHolder holder) {
gameLoopThread.setRunning(true);
gameLoopThread.start();
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format,
int width, int height) {
}
});
// getting the screen size
Display display = getWindowManager().getDefaultDisplay();
sx = display.getWidth();
sy = display.getHeight();
;
cspeed = x / 4;
kspeed = x / 4;
background = BitmapFactory.decodeResource(getResources(),
R.drawable.imgluneta);
run1 = BitmapFactory
.decodeResource(getResources(), R.drawable.run1);
run6 = BitmapFactory
.decodeResource(getResources(), R.drawable.run6);
jump2 = BitmapFactory.decodeResource(getResources(),
R.drawable.run11);
coin = BitmapFactory
.decodeResource(getResources(), R.drawable.coin);
exit = BitmapFactory
.decodeResource(getResources(), R.drawable.exit);
taya = BitmapFactory
.decodeResource(getResources(), R.drawable.taya);
note1 = BitmapFactory.decodeResource(getResources(),
R.drawable.note1);
exit = Bitmap.createScaledBitmap(exit, 25, 25, true);
background = Bitmap
.createScaledBitmap(background, 2 * sx, sy, true);
// health dec
note1 = Bitmap.createScaledBitmap(note1, sx, sy, true);
mp1 = MediaPlayer.create(NewGame.this, R.raw.game);
jump = MediaPlayer.create(NewGame.this, R.raw.jump);
takecoin = MediaPlayer.create(NewGame.this, R.raw.cointake);
}
// on touch method
#Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_UP) {
show = 1;
getx = (int) event.getX();
gety = (int) event.getY();
// exit
if (getx < 25 && gety < 25) {
System.exit(0);
}
// sound off
if (getx > 25 && getx < 60) {
if (gety < 25) {
sound = 0;
mp1.stop();
}
}
// sound on
if (getx > 61 && getx < 90) {
if (gety < 25) {
sound = 1;
}
}
// restart game
if (getx > 91 && gety < 25) {
if (health <= 0) {
gameLoopThread.setPause(0);
health = 100;
score = 0;
}
}
}
return true;
}
#SuppressLint("WrongCall")
#Override
public void onDraw(Canvas canvas) {
canvas.drawColor(Color.BLACK);
// background moving
z = z - 10;
if (z == -sx) {
z = 0;
canvas.drawBitmap(background, z, 0, null);
} else {
canvas.drawBitmap(background, z, 0, null);
}
// running player
x += 5;
if (x == 20) {
x = 5;
}
if (show == 0) {
if (x % 2 == 0) {
int height = run1.getHeight();
canvas.drawBitmap(run1, sx / 16, (15 * sy / 18) - height / 2, null);
// kinfe hit
if (kspeed == 20) {
kspeed = sx;
health -= 25;
canvas.drawBitmap(note1, 0, 0, null);
}
} else {
int height = run6.getHeight();
canvas.drawBitmap(run6, sx / 16, (15 * sy / 18) - height / 2, null);
// kinfe hit
if (kspeed == 20) {
kspeed = sx / 2;
health -= 25;
canvas.drawBitmap(note1, 0, 0, null);
}
}
}
// for jump
if (show == 1) {
if (sound == 1) {
jump.start();
}
int height=jump2.getHeight();
canvas.drawBitmap(jump2, sx / 16, (3 * sy / 4)-height, null);
// score
if (cspeed <= (sx / 8)-height/2 && cspeed >= (sx / 16)-height/2) {
if (sound == 1) {
takecoin.start();
}
cspeed = sx / 2;
score += 10;
}
// jump-hold
delay += 1;
if (delay == 3) {
show = 0;
delay = 0;
}
}
// for coins
cspeed = cspeed - 5;
if (cspeed == -sx / 2) {
cspeed = sx / 2;
canvas.drawBitmap(coin, cspeed, 3 * sy / 4, null);
} else {
canvas.drawBitmap(coin, cspeed, 3 * sy / 4, null);
}
// kinfe
kspeed = kspeed - 20;
int height = taya.getHeight();
canvas.drawBitmap(taya, kspeed, (15 * sy / 18) - height / 2, null);
if (kspeed < 0) {
kspeed = sx;
health -= 25;
}
// score
Paint paint = new Paint();
paint.setColor(Color.BLUE);
paint.setAntiAlias(true);
paint.setFakeBoldText(true);
paint.setTextSize(15);
paint.setTextAlign(Align.LEFT);
canvas.drawText("Score :" + score, 3 * sx / 4, 20, paint);
// exit
canvas.drawBitmap(exit, 0, 0, null);
if (sound == 1) {
mp1.start();
mp1.setLooping(true);
}
// health
Paint myPaint = new Paint();
myPaint.setColor(Color.RED);
myPaint.setStrokeWidth(10);
canvas.drawText("Health :" + health, 0, (sy / 8) - 5, myPaint);
canvas.drawRect(0, sy / 8, health, sy / 8 + 10, myPaint);
// game over
if (health <= 0) {
gameover = 1;
mp1.stop();
canvas.drawText("GAMEOVER OVER", sx / 2, sy / 2, myPaint);
canvas.drawText("YOUR SCORE : " + score, sx / 2, sy / 4,
myPaint);
canvas.drawText("Restart", 91, 25, myPaint);
gameLoopThread.setPause(1);
}
// restart
if (reset == 1) {
gameLoopThread.setPause(0);
health = 100;
score = 0;
}
// timer
Paint mypaint = new Paint();
myPaint.setColor(Color.RED);
myPaint.setStrokeWidth(10);
mypaint.setTextSize(50);
canvas.drawText("Timer :" + min + sec,min, sec, mypaint);
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public void onResume() {
super.onResume();
NewGame.mp1.isPlaying();
}
#Override
public void onPause() {
super.onPause();
NewGame.mp1.pause();
}
}
You can create a button in Java code-
Button button = new Button(this);
where 'this' is context.
Related
I code a mini Android game scenario inspired by Space Invaders and Moon Patrol. It is possible to shoot an alien horizontally (see above).
It is also possible to shoot an alien vertically (see below).
But adding aliens doesn't "scale", it will be very difficult to add for instance 15 aliens moving with respect to all possible collisions. The original space invaders and moon patrol solved this, is it possible to develop a different strategy than the one I am using? The exact movement of aliens is not important, only that it is "fun".
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.support.v4.view.MotionEventCompat;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import java.util.ArrayList;
import java.util.List;
public class ParallaxView extends SurfaceView implements Runnable {
List<Background> backgrounds;
private volatile boolean running;
private Thread gameThread = null;
// For drawing
private Paint paint;
private Canvas canvas;
private SurfaceHolder ourHolder;
// Holds a reference to the Activity
Context context;
// Control the fps
long fps = 60;
// Screen resolution
int screenWidth;
int screenHeight;
private void update() {
// Update all the background positions
for (Background bg : backgrounds) {
bg.update(fps);
}
}
ParallaxView(Context context, int screenWidth, int screenHeight) {
super(context);
this.context = context;
this.screenWidth = screenWidth;
this.screenHeight = screenHeight;
// Initialize our drawing objects
ourHolder = getHolder();
paint = new Paint();
// Initialize our array list
backgrounds = new ArrayList<>();
//load the background data into the Background objects and
// place them in our GameObject arraylist
backgrounds.add(new Background(
this.context,
screenWidth,
screenHeight,
"bg", 0, 120, 50));
backgrounds.add(new Background(
this.context,
screenWidth,
screenHeight,
"grass", 70, 110, 200));
// Add more backgrounds here
}
#Override
public void run() {
while (running) {
long startFrameTime = System.currentTimeMillis();
update();
if (j > 2000) {
j = -50;
k = 0;
}
if (o > 2000) {
o = -50;
l = 0;
}
draw();
// Calculate the fps this frame
long timeThisFrame = System.currentTimeMillis() - startFrameTime;
if (timeThisFrame >= 1) {
fps = 1000 / timeThisFrame;
}
}
}
int numberOfshots = 1;
int[] i = new int[200];
int j = 0;
int k = 0;
int l = 0;
int m = 0;
int o = 0;
boolean down = true;
long lastTurn = System.currentTimeMillis();
int xbuggy = 0;
int xbuggy2 = 0;
boolean down2 = true;
long lastTurn2 = System.currentTimeMillis();
long lastTurn3 = System.currentTimeMillis();
boolean jump = false;
boolean shoot = false;
int ind = 0;
private void draw() {
if (ourHolder.getSurface().isValid()) {
//First we lock the area of memory we will be drawing to
canvas = ourHolder.lockCanvas();
if (jump) {
xbuggy = xbuggy + 4;
}
if (shoot) {
xbuggy2 = xbuggy2 + 4;
}
if (System.currentTimeMillis() - lastTurn3 >= 1000) {
// Change direction here
jump = false;
lastTurn3 = System.currentTimeMillis();
xbuggy = 0;
}
//draw a background color
canvas.drawColor(Color.argb(255, 0, 0, 0));
// Draw the background parallax
drawBackground(0);
// Draw the rest of the game
paint.setTextSize(60);
paint.setColor(Color.argb(255, 255, 255, 255));
//canvas.drawText("MOONPATROL3000", 350, screenHeight / 100 * 5, paint);
int resID = context.getResources().getIdentifier("vehicle",
"drawable", context.getPackageName());
int alienResID = context.getResources().getIdentifier("object3_hdpi",
"drawable", context.getPackageName());
int alienResID2 = context.getResources().getIdentifier("object2_hdpi",
"drawable", context.getPackageName());
int alienResID3 = context.getResources().getIdentifier("object1_hdpi",
"drawable", context.getPackageName());
// Load the bitmap using the id
Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), resID);
Bitmap alienbitmap = BitmapFactory.decodeResource(context.getResources(), alienResID);
Bitmap alienbitmap2 = BitmapFactory.decodeResource(context.getResources(), alienResID2);
Bitmap alienbitmap3 = BitmapFactory.decodeResource(context.getResources(), alienResID3);
//paint.setTextSize(220);
for (int i1 = 0; i1 < numberOfshots; i1++) {
// if horizontal missile hits alien 0
if (java.lang.Math.abs(j - i[i1]) * 2 < (alienbitmap.getWidth() + 60) && java.lang.Math.abs(k +150+ screenHeight / 100 * 45 - (float) (screenHeight * 0.61)) * 2 < (alienbitmap.getHeight() + 60)) {
//y1[i2] = -random.nextInt(1000); // reset to new vertical position
//score += 1;
//onScoreListener.onScore(score);
Log.d("missile", "missile hit! ");
j=-200;
}
// if vertical missile hits alien 0
if (java.lang.Math.abs(j - 185) * 2 < (alienbitmap.getWidth() + 60) && java.lang.Math.abs(j + 150 + screenHeight / 100 * 45 - (screenHeight / 100 * 95 - i[i1] - xbuggy2)) * 2 < (alienbitmap.getHeight() + 60)) {
//y1[i2] = -random.nextInt(1000); // reset to new vertical position
//score += 1;
//onScoreListener.onScore(score);
Log.d("missile", "missile hit! ");
j=-200;
}
// if horizontal missile hits alien 1, right now this won't happen
if (java.lang.Math.abs(j - i[i1]) * 2 < (alienbitmap.getWidth() + 60) && java.lang.Math.abs(k +150+ screenHeight / 100 * 45 - (float) (screenHeight * 0.61)) * 2 < (alienbitmap.getHeight() + 60)) {
//y1[i2] = -random.nextInt(1000); // reset to new vertical position
//score += 1;
//onScoreListener.onScore(score);
Log.d("missile", "missile hit! ");
j=-200;
}
// if vertical missile hits alien 1
if (java.lang.Math.abs(o + 10 - 185) * 2 < (alienbitmap.getWidth() + 60) && java.lang.Math.abs(l + screenHeight / 100 * 25 - (screenHeight / 100 * 95 - i[i1] - xbuggy2)) * 2 < (alienbitmap.getHeight() + 60)) {
//y1[i2] = -random.nextInt(1000); // reset to new vertical position
//score += 1;
//onScoreListener.onScore(score);
Log.d("missile", "missile hit! ");
o=-200;
}
canvas.drawText("o", i[i1], (float) (screenHeight * 0.61), paint);
canvas.drawText("o", 185, screenHeight / 100 * 95 - i[i1] - xbuggy2, paint);
if (i1 == numberOfshots - 1 && i[i1] > screenWidth) {
if (numberOfshots > 0) numberOfshots--;
if (ind > 0) ind--;
}
}
if (System.currentTimeMillis() - lastTurn >= 2000) {
// Change direction here
down = !down;
lastTurn = System.currentTimeMillis();
}
if (System.currentTimeMillis() - lastTurn2 >= 7000) {
// Change direction here
down2 = !down2;
lastTurn2 = System.currentTimeMillis();
}
canvas.drawBitmap(alienbitmap, j, k +150+ screenHeight / 100 * 45, paint);
canvas.drawBitmap(alienbitmap2, o + 10, l + screenHeight / 100 * 25, paint);
//canvas.drawBitmap(alienbitmap3, j+20, k+screenHeight / 100 * 5, paint);
drawBackground(1);
canvas.drawBitmap(bitmap, 50, (float) (screenHeight * 0.5) - xbuggy, paint);
// Draw the foreground parallax
for (int n = 0; n < numberOfshots; n++)
i[n] = i[n] + 20;
j = j + 10;
o = o + 7;
if (!down)
k=k+2;
else
k=k-2;
if (!down2)
l++;
else
l--;
// Unlock and draw the scene
ourHolder.unlockCanvasAndPost(canvas);
}
}
// Clean up our thread if the game is stopped
public void pause() {
running = false;
try {
gameThread.join();
} catch (InterruptedException e) {
// Error
}
}
// Make a new thread and start it
// Execution moves to our run method
public void resume() {
running = true;
gameThread = new Thread(this);
gameThread.start();
}
private void drawBackground(int position) {
// Make a copy of the relevant background
Background bg = backgrounds.get(position);
// define what portion of images to capture and
// what coordinates of screen to draw them at
// For the regular bitmap
Rect fromRect1 = new Rect(0, 0, bg.width - bg.xClip, bg.height);
Rect toRect1 = new Rect(bg.xClip, bg.startY, bg.width, bg.endY);
// For the reversed background
Rect fromRect2 = new Rect(bg.width - bg.xClip, 0, bg.width, bg.height);
Rect toRect2 = new Rect(0, bg.startY, bg.xClip, bg.endY);
//draw the two background bitmaps
if (!bg.reversedFirst) {
canvas.drawBitmap(bg.bitmap, fromRect1, toRect1, paint);
canvas.drawBitmap(bg.bitmapReversed, fromRect2, toRect2, paint);
} else {
canvas.drawBitmap(bg.bitmap, fromRect2, toRect2, paint);
canvas.drawBitmap(bg.bitmapReversed, fromRect1, toRect1, paint);
}
}
// Because we call this from onTouchEvent, this code will be executed for both
// normal touch events and for when the system calls this using Accessibility
#Override
public boolean performClick() {
super.performClick();
launchMissile();
return true;
}
private void launchMissile() {
i[ind] = 350;
ind++;
xbuggy2 = 0;
shoot = true;
}
// event listener for when the user touches the screen
#Override
public boolean onTouchEvent(MotionEvent event) {
boolean gameOver = false;
//if (paused) {
// paused = false;
//}
int action = MotionEventCompat.getActionMasked(event);
int coordX = (int) event.getX();
int coordY = (int) event.getY();
Log.d("coordY", "coordY " + coordY);
if (coordX < 220 && xbuggy == 0 && action == MotionEvent.ACTION_MOVE) {
jump = true;
shoot = false;
lastTurn3 = System.currentTimeMillis();
return true; // do nothing
}
if (coordX > 219 && action == MotionEvent.ACTION_DOWN) {
numberOfshots++;
performClick();
return true;
}
return true;
}
}
Update
I have started to encapsulate the logic for the aliens according to the following.
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
public class Alien {
public Alien(){}
public Alien(Context context, String name) {
setAlienResID(context.getResources().getIdentifier("object3_hdpi",
"drawable", context.getPackageName()));
setAlienbitmap(BitmapFactory.decodeResource(context.getResources(), this.getAlienResID()));
}
public int getAlienResID() {
return alienResID;
}
public void setAlienResID(int alienResID) {
this.alienResID = alienResID;
}
public Bitmap getAlienbitmap() {
return alienbitmap;
}
public void setAlienbitmap(Bitmap alienbitmap) {
this.alienbitmap = alienbitmap;
}
public int getWidth() {
return width;
}
public void setWidth(int width) {
this.width = width;
}
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
int alienResID;
Bitmap alienbitmap;
int width;
int height;
}
public class AttackingAlien extends Alien {
public AttackingAlien(Context context, String name) {
super(context, name);
}
}
Update 2
I have changed the strategy. Now I am drawing a spaceship which is going to bomb the moon buggy.
The relevant code is
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.support.v4.view.MotionEventCompat;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import java.util.ArrayList;
import java.util.List;
public class ParallaxView extends SurfaceView implements Runnable {
List<Background> backgrounds;
private volatile boolean running;
private Thread gameThread = null;
// For drawing
private Paint paint;
private Canvas canvas;
private SurfaceHolder ourHolder;
// Holds a reference to the Activity
Context context;
// Control the fps
long fps = 60;
// Screen resolution
int screenWidth;
int screenHeight;
private void update() {
// Update all the background positions
for (Background bg : backgrounds) {
bg.update(fps);
}
}
ParallaxView(Context context, int screenWidth, int screenHeight) {
super(context);
this.context = context;
this.screenWidth = screenWidth;
this.screenHeight = screenHeight;
// Initialize our drawing objects
ourHolder = getHolder();
paint = new Paint();
// Initialize our array list
backgrounds = new ArrayList<>();
//load the background data into the Background objects and
// place them in our GameObject arraylist
backgrounds.add(new Background(
this.context,
screenWidth,
screenHeight,
"bg", 0, 120, 50));
backgrounds.add(new Background(
this.context,
screenWidth,
screenHeight,
"grass", 70, 110, 200));
// Add more backgrounds here
}
#Override
public void run() {
while (running) {
long startFrameTime = System.currentTimeMillis();
update();
if (j > 2000) {
j = -50;
k = 0;
}
if (o > 2000) {
o = -50;
l = 0;
}
draw();
// Calculate the fps this frame
long timeThisFrame = System.currentTimeMillis() - startFrameTime;
if (timeThisFrame >= 1) {
fps = 1000 / timeThisFrame;
}
}
}
int numberOfshots = 1;
int[] i = new int[200];
int j = 0;
int k = 0;
int l = 0;
int m = 0;
int o = 0;
boolean down = true;
long lastTurn = System.currentTimeMillis();
int xbuggy = 0;
int xbuggy2 = 0;
boolean down2 = true;
long lastTurn2 = System.currentTimeMillis();
long lastTurn3 = System.currentTimeMillis();
long lastTurn4 = System.currentTimeMillis();
boolean jump = false;
boolean shoot = false;
int ind = 0;
int numberOfAlienshots = 1;
int missileOffSetY = 0;
private void draw() {
if (ourHolder.getSurface().isValid()) {
//First we lock the area of memory we will be drawing to
canvas = ourHolder.lockCanvas();
if (jump) {
xbuggy = xbuggy + 4;
}
if (shoot) {
xbuggy2 = xbuggy2 + 4;
}
if (System.currentTimeMillis() - lastTurn4 >= 2000) {
// Change direction here
//jump = false;
lastTurn4 = System.currentTimeMillis();
missileOffSetY = 0;
}
if (System.currentTimeMillis() - lastTurn3 >= 1000) {
// Change direction here
jump = false;
lastTurn3 = System.currentTimeMillis();
xbuggy = 0;
}
//draw a background color
canvas.drawColor(Color.argb(255, 0, 0, 0));
// Draw the background parallax
drawBackground(0);
// Draw the rest of the game
paint.setTextSize(60);
paint.setColor(Color.argb(255, 255, 255, 255));
//canvas.drawText("MOONPATROL3000", 350, screenHeight / 100 * 5, paint);
int resID = context.getResources().getIdentifier("vehicle",
"drawable", context.getPackageName());
Alien alien1 = new AttackingAlien(context, "right_side_hdpi");
Alien alien2 = new AttackingAlien(context, "object2_hdpi");
Alien alien3 = new AttackingAlien(context, "object1_hdpi");
int alienResID = context.getResources().getIdentifier("right_side_hdpi",
"drawable", context.getPackageName());
int alienResID2 = context.getResources().getIdentifier("right_side_hdpi",
"drawable", context.getPackageName());
int alienResID3 = context.getResources().getIdentifier("right_side_hdpi",
"drawable", context.getPackageName());
// Load the bitmap using the id
Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), resID);
Bitmap alienbitmap = BitmapFactory.decodeResource(context.getResources(), alienResID);
Bitmap alienbitmap2 = BitmapFactory.decodeResource(context.getResources(), alienResID2);
Bitmap alienbitmap3 = BitmapFactory.decodeResource(context.getResources(), alienResID3);
//paint.setTextSize(220);
//for (int i1 = 0; i1 < numberOfAlienshots; i1++) {
if (missileOffSetY < 300) {
canvas.drawText("|", o + 10 + alienbitmap2.getWidth() / 2, l + screenHeight / 100 * 25 + 75 + missileOffSetY, paint);
missileOffSetY = missileOffSetY + 10;
}
for (int i1 = 0; i1 < numberOfshots; i1++) {
// if horizontal missile hits alien 0
if (java.lang.Math.abs(j - i[i1]) * 2 < (alien1.getWidth() + 60) && java.lang.Math.abs(k +150+ screenHeight / 100 * 45 - (float) (screenHeight * 0.61)) * 2 < (alien1.getHeight() + 60)) {
//y1[i2] = -random.nextInt(1000); // reset to new vertical position
//score += 1;
//onScoreListener.onScore(score);
Log.d("missile", "missile hit! ");
j=-200;
}
// if vertical missile hits alien 0
if (java.lang.Math.abs(j - 185) * 2 < (alienbitmap.getWidth() + 60) && java.lang.Math.abs(j + 150 + screenHeight / 100 * 45 - (screenHeight / 100 * 95 - i[i1] - xbuggy2)) * 2 < (alienbitmap.getHeight() + 60)) {
j=-200;
}
// if horizontal missile hits alien 1, right now this won't happen
if (java.lang.Math.abs(j - i[i1]) * 2 < (alienbitmap.getWidth() + 60) && java.lang.Math.abs(k +150+ screenHeight / 100 * 45 - (float) (screenHeight * 0.61)) * 2 < (alienbitmap.getHeight() + 60)) {
j=-200;
}
// if vertical missile hits alien 1
if (java.lang.Math.abs(o + 10 - 185) * 2 < (alienbitmap.getWidth() + 60) && java.lang.Math.abs(l + screenHeight / 100 * 25 - (screenHeight / 100 * 95 - i[i1] - xbuggy2)) * 2 < (alienbitmap.getHeight() + 60)) {
o=-200;
}
canvas.drawText("o", i[i1], (float) (screenHeight * 0.61), paint);
canvas.drawText("o", 185, screenHeight / 100 * 95 - i[i1] - xbuggy2, paint);
if (i1 == numberOfshots - 1 && i[i1] > screenWidth) {
if (numberOfshots > 0) numberOfshots--;
if (ind > 0) ind--;
}
}
if (System.currentTimeMillis() - lastTurn >= 2000) {
// Change direction here
down = !down;
lastTurn = System.currentTimeMillis();
}
if (System.currentTimeMillis() - lastTurn2 >= 7000) {
// Change direction here
down2 = !down2;
lastTurn2 = System.currentTimeMillis();
}
// canvas.drawBitmap(alien1.getAlienbitmap(), j, k +150+ screenHeight / 100 * 45, paint);
canvas.drawBitmap(alienbitmap2, o + 10, l + screenHeight / 100 * 25, paint);
//canvas.drawBitmap(alienbitmap3, j+20, k+screenHeight / 100 * 5, paint);
drawBackground(1);
canvas.drawBitmap(bitmap, 50, (float) (screenHeight * 0.5) - xbuggy, paint);
// Draw the foreground parallax
for (int n = 0; n < numberOfshots; n++)
i[n] = i[n] + 20;
j = j + 10;
o = o + 7;
if (!down)
k=k+2;
else
k=k-2;
if (!down2)
l++;
else
l--;
// Unlock and draw the scene
ourHolder.unlockCanvasAndPost(canvas);
}
}
// Clean up our thread if the game is stopped
public void pause() {
running = false;
try {
gameThread.join();
} catch (InterruptedException e) {
// Error
}
}
// Make a new thread and start it
// Execution moves to our run method
public void resume() {
running = true;
gameThread = new Thread(this);
gameThread.start();
}
private void drawBackground(int position) {
// Make a copy of the relevant background
Background bg = backgrounds.get(position);
// define what portion of images to capture and
// what coordinates of screen to draw them at
// For the regular bitmap
Rect fromRect1 = new Rect(0, 0, bg.width - bg.xClip, bg.height);
Rect toRect1 = new Rect(bg.xClip, bg.startY, bg.width, bg.endY);
// For the reversed background
Rect fromRect2 = new Rect(bg.width - bg.xClip, 0, bg.width, bg.height);
Rect toRect2 = new Rect(0, bg.startY, bg.xClip, bg.endY);
//draw the two background bitmaps
if (!bg.reversedFirst) {
canvas.drawBitmap(bg.bitmap, fromRect1, toRect1, paint);
canvas.drawBitmap(bg.bitmapReversed, fromRect2, toRect2, paint);
} else {
canvas.drawBitmap(bg.bitmap, fromRect2, toRect2, paint);
canvas.drawBitmap(bg.bitmapReversed, fromRect1, toRect1, paint);
}
}
// Because we call this from onTouchEvent, this code will be executed for both
// normal touch events and for when the system calls this using Accessibility
#Override
public boolean performClick() {
super.performClick();
launchMissile();
return true;
}
private void launchMissile() {
i[ind] = 350; // what does it do?
ind++;
xbuggy2 = 0;
shoot = true;
}
// event listener for when the user touches the screen
#Override
public boolean onTouchEvent(MotionEvent event) {
boolean gameOver = false;
//if (paused) {
// paused = false;
//}
int action = MotionEventCompat.getActionMasked(event);
int coordX = (int) event.getX();
int coordY = (int) event.getY();
Log.d("coordY", "coordY " + coordY);
if (coordX < 220 && xbuggy == 0 && action == MotionEvent.ACTION_MOVE) {
jump = true;
shoot = false;
lastTurn3 = System.currentTimeMillis();
return true; // do nothing
}
if (coordX > 219 && action == MotionEvent.ACTION_DOWN) {
numberOfshots++;
performClick();
return true;
}
return true;
}
}
Your biggest error seems to be allocating 4 bitmaps in the draw routine. Allocate those bitmaps in the onCreate and simply call the global bitmaps, that you initialized onCreate(). That will fix your problem. You can draw them in their locations.
private void draw() {
Alien alien1 = new AttackingAlien(context, "right_side_hdpi");
Alien alien2 = new AttackingAlien(context, "object2_hdpi");
Alien alien3 = new AttackingAlien(context, "object1_hdpi");
You allocated a bunch of memory objects invoking the context and expanding the drawable and a bunch of other work. You could have just used the same aliens from last tick.
int alienResID = context.getResources().getIdentifier("right_side_hdpi",
"drawable", context.getPackageName());
int alienResID2 = context.getResources().getIdentifier("right_side_hdpi",
"drawable", context.getPackageName());
int alienResID3 = context.getResources().getIdentifier("right_side_hdpi",
"drawable", context.getPackageName());
The aliens IDs didn't change from the previous tick.
// Load the bitmap using the id
Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), resID);
Bitmap alienbitmap = BitmapFactory.decodeResource(context.getResources(), alienResID);
Bitmap alienbitmap2 = BitmapFactory.decodeResource(context.getResources(), alienResID2);
Bitmap alienbitmap3 = BitmapFactory.decodeResource(context.getResources(), alienResID3);
These are the same bitmaps from last tick and bitmaps are giant and getting them from resources is slow, and you are doing this EVERY tick.
}
}
Most of the other stuff is going to shave off half a ms here and there, but this here is going to maybe get you up to the right FPS ballpark.
Don't worry though you have others.
Much of your problem is solved by making the routines faster. This is a good time to say, you're doing it wrong. The typical and correct way to do this is to have a loop ticks every 17ms or so. And for the rest of the time is paused. Some errors are glaring.
Your biggest error seems to be allocating 4 bitmaps in the draw routine.
But, the draw routine only draws. You draw the stuff that needs to happen on your canvas and that's it. You don't allocate anything you don't inflate anything, you take the numbers you have for where stuff is, and draw the stuff you already have loaded in the memory in that location.
You are ticking and doing the collision detection, in the draw routine, and allocating a bunch of objects for this when they have to be thrown in the woodchipper in a split second anyway.
You should not create any objects outside your initialization or in those special cases when a new alien exists. You shouldn't ever use a "new" anywhere in a draw routine. Ever.
You are using brute force for collision detection, eventually don't. Find a nice acceleration structure you like and use that. For 1 object it won't matter though.
Don't call some alien class, while it looks prettier, you want raw numbers of the bounding boxes of the aliens. You want then to keep them in some sort of structure that allows referencing them very quickly (You need the frame in less than 17ms). Calling a bunch of width commands isn't really that helpful, even if they changed size just change the number for the hitbox. These methods allow you some nice structures for the data like having a sorted array of hitboxes you can binary search into them and find whether the moved object hits the object in a log(n) time with log(n) updates to the structure, or some various methods for traversing an Axis Aligned Bound Box Tree. This is something you eventually will need but it might work without this so long as you're keeping it simple. Though, truthfully it's just your bitmaps there doing most of the slowing.
There's a lot of other basic issues like putting the bounding box inside the if statement rather than making two additional rectangles. But there's other issues like making rectangles at all! You call the draw with the actual location rather than some allocate a big ass couple objects to call a function with. Just call the function with the numbers.
You should have a routine that does the drawing for you based on the locations of the stuff. It should be able to draw everything it needs to draw in less then 17ms. If it can't you won't ever hit the 60fps you need to hit. So in that case draw less stuff and do a better job of it. Does that space background need to be a bitmap? Could you just draw a bunch of points for the sky, and adjust the graphics accordingly. Your draw routine never allocates anything. Period. If you need to allocate something it should have been during the init. Allocations are the bane of your existence.
Your touches update the position of the stuff. The AI/Physics tick also updates the positions of things and checks for collusion. The draw only draws the stuff based on the positions and stuff in memory.
Run the update location tick in its own thread. You only need to cope with the concurrency bits where you would be reading and writing the same data. It just needs to synchronize the changing data reading of the data for the draw, so toss those sections (position update in touch, position update in tick, and getting the position for the draw routine itself) in a synchronized block with the same object.
I am currently coding a game with Android Studio in the style of FlappyBird. I have two Cooldowns that give the user the possibility to use extra abilities.
In the main game view you can see 2 images that are grey and a timer under them. The timer goes from 10 to 0 and when zero is reached the number disappears, the image gets colored and the user knows he is able to activate the ability in the pause screen.
The problem:
When the game is starting the timer starts also and goes down as i wanted. But if the user enters the Pause Menu the Timer should stop and if he leaves it the Timer should run again.
I have a
long startTime = 0;
and a
long elapsedTime = (System.currentTimeMillis() - startTime) / 1000;
It all works but I cannot save the current time in a long and can't find any function for it!
I know the code is very long but the important part is in the drawWorld()-method in the if statement GameState.Running.
public class PlaneGame extends ApplicationAdapter{
private static final float PLANE_JUMP_IMPULSE = 350;
private static final float GRAVITY = -20;
private static final float PLANE_VELOCITY_X = 200;
private static final float PLANE_START_Y = 240;
private static final float PLANE_START_X = 50;
private static final int STATE_START = 0;
private static final int STATE_RUNNING = 1;
private static final int STATE_OVER = 2;
SpriteBatch batch;
OrthographicCamera camera;
OrthographicCamera uiCamera;
Texture background;
TextureRegion ground;
float groundOffsetX = 0;
TextureRegion ceiling;
TextureRegion rock;
TextureRegion rockDown;
TextureRegion planeSmall;
TextureRegion planeSmallBlack;
Animation plane;
TextureRegion ready;
TextureRegion gameOver;
TextureRegion pause;
BitmapFont font;
Vector2 planePosition = new Vector2();
Vector2 planeVelocity = new Vector2();
float planeStateTime = 0;
Vector2 gravity = new Vector2();
Array<Rock> rocks = new Array<Rock>();
GameState gameState = GameState.Start; /*neeeeeeewwwww*/
int score = 0;
long startTime = 0;
long startTime2;
long elapsedTime;
long savedTime;
boolean wantToSeeTime = true;
boolean wantToSeeTimePause = true;
float timeCdRock = 0;
float timeCdPlane = 0;
Rectangle rect1 = new Rectangle();
Rectangle rect2 = new Rectangle();
Music music;
Sound point;
Sound explode;
//this gets called repeatedly to run the game
#Override
public void render () {
//clear the screen so we can draw the next one
Gdx.gl.glClearColor(1, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
long saveTime = elapsedTime;
//update the position of the plane and rocks
updateWorld();
elapsedTime = saveTime;
//now draw the updated screen
drawWorld();
}
//initialize objects and load assets when game starts
#Override
public void create () {
startTime = TimeUtils.nanoTime(); /*Neeeewwwwwwwww !!!*/
Gdx.input.setInputProcessor(new GestureDetector(new MyGestureListener()));
batch = new SpriteBatch();
camera = new OrthographicCamera();
camera.setToOrtho(false, 800, 480);
uiCamera = new OrthographicCamera();
uiCamera.setToOrtho(false, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
uiCamera.update();
font = new BitmapFont(Gdx.files.internal("arial.fnt"));
background = new Texture("background.png");
ground = new TextureRegion(new Texture("ground.png"));
ceiling = new TextureRegion(ground);
ceiling.flip(true, true);
rock = new TextureRegion(new Texture("rock.png"));
rockDown = new TextureRegion(rock);
rockDown.flip(false, true);
Texture frame1 = new Texture("plane1.png");
frame1.setFilter(TextureFilter.Linear, TextureFilter.Linear);
Texture frame2 = new Texture("plane2.png");
Texture frame3 = new Texture("plane3.png");
planeSmall = new TextureRegion(new Texture("planeSmall.png"));
planeSmallBlack = new TextureRegion(new Texture("planeSmallBlack.png"));
ready = new TextureRegion(new Texture("ready.png"));
gameOver = new TextureRegion(new Texture("gameover.png"));
pause = new TextureRegion(new Texture("pause.png"));
plane = new Animation(0.05f, new TextureRegion(frame1), new TextureRegion(frame2), new TextureRegion(frame3), new TextureRegion(frame2));
plane.setPlayMode(PlayMode.LOOP);
music = Gdx.audio.newMusic(Gdx.files.internal("music.mp3"));
music.setLooping(true);
music.play();
point = Gdx.audio.newSound(Gdx.files.internal("point.ogg"));
explode = Gdx.audio.newSound(Gdx.files.internal("explode.wav"));
resetWorld();
}
//reset the state of the game
private void resetWorld() {
score = 0;
startTime = 0;
groundOffsetX = 0;
planePosition.set(PLANE_START_X, PLANE_START_Y);
planeVelocity.set(0, 0);
gravity.set(0, GRAVITY);
camera.position.x = 400;
//randomize the position and direction of the rocks
rocks.clear();
for(int i = 0; i < 5; i++) {
boolean isDown = MathUtils.randomBoolean();
rocks.add(new Rock(700 + i * 200, isDown?480-rock.getRegionHeight(): 0, isDown? rockDown: rock));
}
}
//use the time elapsed since the last call to render() to determine how much to update the game
private void updateWorld() {
float deltaTime = Gdx.graphics.getDeltaTime();
planeStateTime += deltaTime;
/*if(Gdx.input.justTouched()) {
if(gameState == STATE_START) {
gameState = STATE_RUNNING;
}
if(gameState == STATE_RUNNING) {
planeVelocity.set(PLANE_VELOCITY_X, PLANE_JUMP_IMPULSE);
}
if(gameState == STATE_OVER) {
gameState = STATE_START;
resetWorld();
}
}*/
if(gameState != GameState.Start) planeVelocity.add(gravity);
planePosition.mulAdd(planeVelocity, deltaTime);
camera.position.x = planePosition.x + 350;
if(camera.position.x - groundOffsetX > ground.getRegionWidth() + 400) {
groundOffsetX += ground.getRegionWidth();
}
rect1.set(planePosition.x + 20, planePosition.y, plane.getKeyFrames()[0].getRegionWidth() - 20, plane.getKeyFrames()[0].getRegionHeight());
for(Rock r: rocks) {
//if the rock is off the screen, give it a new location in front of the plane
if(camera.position.x - r.position.x > 400 + r.image.getRegionWidth()) {
boolean isDown = MathUtils.randomBoolean();
r.position.x += 5 * 200;
r.position.y = isDown?480-rock.getRegionHeight(): 0;
r.image = isDown? rockDown: rock;
r.counted = false;
}
rect2.set(r.position.x + (r.image.getRegionWidth() - 30) / 2 + 20, r.position.y, 20, r.image.getRegionHeight() - 10);
//check if the plane crashed
if(rect1.overlaps(rect2)) {
if(gameState != GameState.GameOver) explode.play();
gameState = GameState.GameOver;
planeVelocity.x = 0;
}
//award a point for not crashing into a rock
if(r.position.x < planePosition.x && !r.counted) {
score++;
r.counted = true;
point.play();
}
}
//check if the plane crashed
if(planePosition.y < ground.getRegionHeight() - 20 ||
planePosition.y + plane.getKeyFrames()[0].getRegionHeight() > 480 - ground.getRegionHeight() + 20) {
if(gameState != GameState.GameOver) explode.play();
gameState = GameState.GameOver;
planeVelocity.x = 0;
}
}
//draw the background, rocks, and plane to the screen and possibly some ui text
private void drawWorld() {
elapsedTime = (System.currentTimeMillis() - startTime) / 1000;
camera.update();
batch.setProjectionMatrix(camera.combined);
batch.begin();
batch.draw(background, camera.position.x - background.getWidth() / 2, 0);
for(Rock rock: rocks) {
batch.draw(rock.image, rock.position.x, rock.position.y);
}
batch.draw(ground, groundOffsetX, 0);
batch.draw(ground, groundOffsetX + ground.getRegionWidth(), 0);
batch.draw(ceiling, groundOffsetX, 480 - ceiling.getRegionHeight());
batch.draw(ceiling, groundOffsetX + ceiling.getRegionWidth(), 480 - ceiling.getRegionHeight());
batch.draw(plane.getKeyFrame(planeStateTime), planePosition.x, planePosition.y);
batch.end();
batch.setProjectionMatrix(uiCamera.combined);
batch.begin();
if(gameState == GameState.Start) {
batch.draw(ready, Gdx.graphics.getWidth() / 2 - ready.getRegionWidth() / 2, Gdx.graphics.getHeight() / 2 - ready.getRegionHeight() / 2);
}
if(gameState == GameState.GameOver) {
batch.draw(gameOver, Gdx.graphics.getWidth() / 2 - gameOver.getRegionWidth() / 2, Gdx.graphics.getHeight() / 2 - gameOver.getRegionHeight() / 2);
}
if(gameState == GameState.GameOver || gameState == GameState.Running) {
font.draw(batch, "" + score, Gdx.graphics.getWidth() / 2, Gdx.graphics.getHeight() - 60);
}
if(gameState == GameState.Running || gameState == GameState.Pause) {
//font.draw(batch, "" + (10 - elapsedTime), (Gdx.graphics.getWidth() / 2) / 3, Gdx.graphics.getHeight() - 260);
if(wantToSeeTime){
font.draw(batch, "" + (5 - elapsedTime), (Gdx.graphics.getWidth() / 2) / 3, Gdx.graphics.getHeight() - 260);
}
if((5 -(elapsedTime) > 0)) {
batch.draw(planeSmallBlack, (Gdx.graphics.getWidth() / 2) / 3, Gdx.graphics.getHeight() - 250);
}else {
batch.draw(planeSmall, (Gdx.graphics.getWidth() / 2) / 3, Gdx.graphics.getHeight() - 250);
wantToSeeTime = false;
}
}
if(gameState == GameState.Pause){
batch.draw(pause, Gdx.graphics.getWidth() / 2 - pause.getRegionWidth() / 2, Gdx.graphics.getHeight() / 2 - pause.getRegionHeight() / 2);
if(wantToSeeTimePause){
font.draw(batch, "" + (savedTime), (Gdx.graphics.getWidth() / 2) / 3, Gdx.graphics.getHeight() - 260);
}
}
batch.end();
}
//object to hold all pertinent information for a rock
static class Rock {
Vector2 position = new Vector2();
TextureRegion image;
boolean counted;
public Rock(float x, float y, TextureRegion image) {
this.position.x = x;
this.position.y = y;
this.image = image;
}
}
// Neeeeeeeewwwww
static enum GameState {
Start, Running, GameOver, Pause
}
private class MyGestureListener implements GestureDetector.GestureListener {
#Override
public boolean touchDown(float x, float y, int pointer, int button) {
return false;
}
#Override
public boolean tap(float x, float y, int count, int button) {
if(gameState == GameState.Start) {
gameState = GameState.Running;
startTime = System.currentTimeMillis();
}
if(gameState == GameState.Running) {
planeVelocity.set(PLANE_VELOCITY_X, PLANE_JUMP_IMPULSE);
}
if(gameState == GameState.GameOver) {
gameState = GameState.Start;
resetWorld();
}
/*if((gameState == GameState.Pause) && (count == 2)) {
planeVelocity.set(PLANE_VELOCITY_X, PLANE_JUMP_IMPULSE);
gravity.set(0,GRAVITY);
gameState = GameState.Running;
}*/
return true;
}
#Override
public boolean longPress(float x, float y) {
return false;
}
#Override
public boolean fling(float velocityX, float velocityY, int button) {
if(gameState == GameState.Running) {
planePosition.set(planePosition.x, planePosition.y);
planeVelocity.set(0,0);
gravity.set(0, 0);
savedTime = System.currentTimeMillis() / 1000;
wantToSeeTime = false;
wantToSeeTimePause = true;
gameState = GameState.Pause;
} else {
planeVelocity.set(PLANE_VELOCITY_X, PLANE_JUMP_IMPULSE);
gravity.set(0,GRAVITY);
wantToSeeTime = true;
wantToSeeTimePause = false;
elapsedTime -= savedTime;
gameState = GameState.Running;
}
/*if(gameState == GameState.Pause) {
planeVelocity.set(PLANE_VELOCITY_X, PLANE_JUMP_IMPULSE);
gravity.set(0,GRAVITY);
gameState = GameState.Running;
}*/
return true;
}
#Override
public boolean pan(float x, float y, float deltaX, float deltaY) {
return false;
}
#Override
public boolean panStop(float x, float y, int pointer, int button) {
return false;
}
#Override
public boolean zoom(float initialDistance, float distance) {
return false;
}
#Override
public boolean pinch(Vector2 initialPointer1, Vector2 initialPointer2, Vector2 pointer1, Vector2 pointer2) {
return false;
}
public void pinchStop() {
}
}
}
Thanks for your help!
You can use joda time for advanced operations
Please check the link for your reference
http://www.joda.org/joda-time/userguide.html
I'm going to assume that your game runs as part of a loop. Ideally what you should have is a starting time when the ability is activated, which counts down during the cooldown based on how much time has elapsed since the last iteration of your loop. For example, for an ability with a 10 second cooldown:
final long abilityLength = 10 * 1000;
long cooldownRemaining = 0;
long lastTimestamp;
boolean isPaused = false;
private void doAbility() {
if (cooldownRemaining <= 0) {
cooldownRemaining = abilityLength;
}
}
public void main(int[] args) {
lastTimestamp = System.currentTimeMillis();
while(true) { // your main game loop
// Time (in ms) elapsed since the last iteration of this loop
long delta = System.currentTimeMillis() - lastTimestamp;
... // Other game code
if (cooldownRemaining > 0 && !isPaused) {
// Subtract the delta from the remaing cooldown time.
cooldownRemaining -= delta;
}
lastTimeStamp = System.currentTimeMillis();
}
}
I'm trying to reset my Countdown Timer with new variables (a new time), but nothing I do seems to work. Anyone know how to do this?
private long cdTime = 30000;
private long percentageTime = 30;
private void createCDTimer(){
mCountDownTimer = new CountDownTimer(cdTime, 1000) {
public void onTick(long millisUntilFinished) {
score = millisUntilFinished / 1000;
percentage = percentage - (100 / percentageTime);
cdTime = millisUntilFinished;
percentageTime = millisUntilFinished / 1000;
}
public void onFinish() {
score = 0;
percentage = 0;
}
}.start();
}
this code is in another class/void {
mCountDownTimer.cancel();
cdTime = cdTime + 20000;
percentageTime = percentageTime + 20;
mCountDownTimer.start();
}
Thanks in advance.
EDIT:
Here's the rest of my code for those who need it:
public class GameView extends SurfaceView implements Runnable {
Context context;
private Thread gameThread = null;
private SurfaceHolder ourHolder;
private volatile boolean playing;
private boolean paused = true;
private Canvas canvas;
private Paint paint;
private long fps;
private long thisTimeFrame;
private int screenX;
private int screenY;
private int column1;
private int column2;
private int column3;
private float enemyMDrop;
private float enemyMY;
private float enemyLDrop;
private float enemyLY;
private float enemyRDrop;
private float enemyRY;
private Random randomGen = new Random();
private int loadBarAnim;
private float loadBarTimer;
private float gameTimer;
private long percentage = 100;
private CountDownTimer mCountDownTimer;
private long cdTime;
private long percentageTime;
private Compressor compressor;
private loadingBar loadBar;
private loadingBarAnimation loadBarAnimation;
private EnemyMid enemyM;
private EnemyLeft enemyL;
private EnemyLeft enemyR;
private float mTimer;
private float lTimer;
private float rTimer;
private float enemyMWait;
private float enemyLWait;
private float enemyRWait;
private float enemyMTimer;
private float enemyLTimer;
private float enemyRTimer;
private boolean enemyMGo;
private boolean enemyLGo;
private boolean enemyRGo;
private SoundPool soundPool;
private int deathSound = -1;
private int liveSound = -1;
private int shootSound = -1;
private int gameMusic = -1;
private long score;
String scoreText = "Score: ";
//String scoreView = String.format("%.02f", score);
private int lives = 3;
public GameView (Context context, int x, int y){
super(context);
this.context = context;
ourHolder = getHolder();
paint = new Paint();
screenX = x;
screenY = y;
prepeareLevel();
}
private void createCDTimer(){
mCountDownTimer = new CountDownTimer(cdTime, 1000) {
public void onTick(long millisUntilFinished) {
score = millisUntilFinished / 1000;
percentage = percentage - (100 / percentageTime);
cdTime = millisUntilFinished;
percentageTime = millisUntilFinished / 1000;
}
public void onFinish() {
score = 0;
percentage = 0;
}
}.start();
}
private void prepeareLevel (){
cdTime = 30000;
percentageTime = 30;
createCDTimer();
loadBarAnim = 1;
column1 = screenX / 3;
column2 = (screenX / 3 ) * 2;
column3 = (screenX / 3 ) * 3;
compressor = new Compressor(context, screenX, screenY);
loadBar = new loadingBar(context, screenX, screenY);
loadBarAnimation = new loadingBarAnimation(context, screenX, screenY, 2);
enemyM = new EnemyMid(context, screenX, screenY);
enemyL = new EnemyLeft(context, screenX, screenY);
enemyR = new EnemyLeft(context, screenX, screenY);
mTimer = 0;
lTimer = 0;
rTimer = 0;
enemyMTimer = 2;
enemyLTimer = 0;
enemyRTimer = 5;
enemyMGo = false;
enemyLGo = false;
enemyRGo = false;
enemyMDrop = 0;
enemyLDrop = 0;
enemyRDrop = 0;
enemyMWait = randomGen.nextInt((5 - 1) + 1);
enemyLWait = randomGen.nextInt((5 - 1) + 1);
enemyRWait = randomGen.nextInt((5 - 1) + 1);
}
#Override
public void run(){
while (playing){
long startFrameTime = System.currentTimeMillis();
if(!paused){
update();
}
draw();
thisTimeFrame = System.currentTimeMillis() - startFrameTime;
if(thisTimeFrame >= 1){
fps = 1000/thisTimeFrame;
}
}
}
private void update(){
boolean finished = false;
if (finished){
}
}
private void draw(){
if(ourHolder.getSurface().isValid()){
canvas = ourHolder.lockCanvas();
if(rTimer < 30){
rTimer++;
}
else {
rTimer = 0;
if (enemyRTimer >= enemyRWait-1){
enemyRGo = true;
enemyRTimer = 0;
}
else if (!enemyRGo){
enemyRTimer++;
}
}
if(mTimer < 30){
mTimer++;
}
else {
mTimer = 0;
if (enemyMTimer >= enemyMWait-1){
enemyMGo = true;
enemyMTimer = 0;
}
else if (!enemyMGo){
enemyMTimer++;
}
}
if(lTimer < 30){
lTimer++;
}
else {
if (enemyLTimer >= enemyLWait-1){
enemyLGo = true;
enemyLTimer = 0;
}
else if (!enemyLGo){
enemyLTimer++;
}
}
canvas.drawColor(Color.WHITE);
paint.setColor(Color.BLACK);
if (enemyMGo){
enemyMDrop = enemyMDrop - 10;
enemyMY = enemyM.getY() - enemyMDrop;
}
if (enemyMY > 1200) {
enemyMDrop = 0;
enemyMY = 0;
enemyMGo = false;
enemyMTimer = 0;
enemyMWait = randomGen.nextInt((5 - 1) + 1);
mCountDownTimer.cancel();
cdTime = cdTime + 20000;
percentageTime = percentageTime + 20;
mCountDownTimer = new CountDownTimer(cdTime, 1000) {
public void onTick(long millisUntilFinished) {
score = millisUntilFinished / 1000;
percentage = percentage - (100 / percentageTime);
cdTime = millisUntilFinished;
percentageTime = millisUntilFinished / 1000;
}
public void onFinish() {
score = 0;
percentage = 0;
}
};
mCountDownTimer.start();
}
if (enemyLGo){
enemyLDrop = enemyLDrop - 10;
enemyLY = enemyL.getY() - enemyLDrop;
}
if (enemyLY > 1200) {
enemyLDrop = 0;
enemyLY = 0;
enemyLGo = false;
enemyLTimer = 0;
enemyLWait = randomGen.nextInt((5 - 1) + 1);
}
if (enemyRGo){
enemyRDrop = enemyRDrop - 10;
enemyRY = enemyR.getY() - enemyRDrop;
}
if (enemyRY > 1200) {
enemyRDrop = 0;
enemyRY = 0;
enemyRGo = false;
enemyRTimer = 0;
enemyRWait = randomGen.nextInt((5 - 1) + 1);
}
//Draw the invaders
canvas.drawBitmap(enemyL.getBitmap(), (column1 - enemyL.getX()) - (column1 / 4), enemyLY, paint);
canvas.drawBitmap(enemyM.getBitmap(), (column2 - enemyM.getX()) - (column1 / 4), enemyMY, paint);
canvas.drawBitmap(enemyR.getBitmap(), (column3 - enemyL.getX()) - (column1 / 4), enemyRY, paint);
//draw the compressor
canvas.drawBitmap(compressor.getBitmap(), 0, 0, paint);
//draw the animated loading bar
if (loadBarTimer > 2){
loadBarTimer = 0;
if (loadBarAnim == 1){
loadBarAnim = 2;
}
else if (loadBarAnim == 2){
loadBarAnim = 3;
}
else if (loadBarAnim == 3){
loadBarAnim = 4;
}
else {
loadBarAnim = 1;
}
}
else {
loadBarTimer++;
}
if (loadBarAnim == 1) {
canvas.drawBitmap(loadBarAnimation.getBitmap1(), 19, 1300, paint);
}
else if (loadBarAnim == 2){
canvas.drawBitmap(loadBarAnimation.getBitmap2(), 19, 1300, paint);
}
else if (loadBarAnim == 3) {
canvas.drawBitmap(loadBarAnimation.getBitmap3(), 19, 1300, paint);
}
else {
canvas.drawBitmap(loadBarAnimation.getBitmap4(), 19, 1300, paint);
}
//draw the loading bar
canvas.drawBitmap(loadBar.getBitmap(), 20, 1300, paint);
//Draw the Score
paint.setColor(Color.BLACK);
paint.setTextSize(40);
canvas.drawText("Time: " + score, 100, 1600, paint);
//Draw the Percentage
paint.setColor(Color.BLACK);
paint.setTextSize(40);
canvas.drawText("Percentage: " + percentage, 725, 1600, paint);
ourHolder.unlockCanvasAndPost(canvas);
}
}
//Paused or Stopped
public void pause(){
playing = false;
try{
gameThread.join();
}
catch (InterruptedException e){
Log.e("Error: ", "Error joining thread");
}
}
//Resume
public void resume(){
playing = true;
gameThread = new Thread(this);
gameThread.start();
}
public boolean onTouchEvent(MotionEvent motionEvent){
switch (motionEvent.getAction() & MotionEvent.ACTION_MASK){
//player touches the screen
case MotionEvent.ACTION_DOWN:
paused = false;
if (motionEvent.getX() > screenX - column1 && enemyRY > 200){
if (motionEvent.getY() < screenY) {
enemyRWait = randomGen.nextInt((5 - 1) + 1);
enemyRY = 0;
enemyRDrop = 0;
enemyRGo = false;
enemyRTimer = 0;
rTimer = 0;
canvas = ourHolder.lockCanvas();
canvas.drawColor(Color.WHITE);
paint.setColor(Color.BLACK);
//Draw the invaders
canvas.drawBitmap(enemyL.getBitmap(), (column1 - enemyL.getX()) - (column1 / 4), enemyLY, paint);
canvas.drawBitmap(enemyM.getBitmap(), (column2 - enemyM.getX()) - (column1 / 4), enemyMY, paint);
canvas.drawBitmap(enemyR.getBitmap(), (column3 - enemyL.getX()) - (column1 / 4), enemyRY, paint);
//draw the compressor
canvas.drawBitmap(compressor.getBitmap(), 0, 0, paint);
//draw the animated loading bar
if (loadBarTimer > 2){
loadBarTimer = 0;
if (loadBarAnim == 1){
loadBarAnim = 2;
}
else if (loadBarAnim == 2){
loadBarAnim = 3;
}
else if (loadBarAnim == 3){
loadBarAnim = 4;
}
else {
loadBarAnim = 1;
}
}
else {
loadBarTimer++;
}
if (loadBarAnim == 1) {
canvas.drawBitmap(loadBarAnimation.getBitmap1(), 19, 1300, paint);
}
else if (loadBarAnim == 2){
canvas.drawBitmap(loadBarAnimation.getBitmap2(), 19, 1300, paint);
}
else if (loadBarAnim == 3) {
canvas.drawBitmap(loadBarAnimation.getBitmap3(), 19, 1300, paint);
}
else {
canvas.drawBitmap(loadBarAnimation.getBitmap4(), 19, 1300, paint);
}
//draw the loading bar
canvas.drawBitmap(loadBar.getBitmap(), 20, 1300, paint);
//Draw the Score
paint.setColor(Color.BLACK);
paint.setTextSize(40);
canvas.drawText("Time: " + score, 100, 1600, paint);
//Draw the Percentage
paint.setColor(Color.BLACK);
paint.setTextSize(40);
canvas.drawText("Percentage: " + percentage, 725, 1600, paint);
ourHolder.unlockCanvasAndPost(canvas);
}
}
if (motionEvent.getX() > screenX - column2 && motionEvent.getX() < screenX - column1 && enemyMY > 200){
if (motionEvent.getY() < screenY) {
enemyMWait = randomGen.nextInt((5 - 1) + 1);
enemyMY = 0;
enemyMDrop = 0;
enemyMGo = false;
enemyMTimer = 0;
mTimer = 0;
canvas = ourHolder.lockCanvas();
canvas.drawColor(Color.WHITE);
paint.setColor(Color.BLACK);
//Draw the invaders
canvas.drawBitmap(enemyL.getBitmap(), (column1 - enemyL.getX()) - (column1 / 4), enemyLY, paint);
canvas.drawBitmap(enemyM.getBitmap(), (column2 - enemyM.getX()) - (column1 / 4), enemyMY, paint);
canvas.drawBitmap(enemyR.getBitmap(), (column3 - enemyL.getX()) - (column1 / 4), enemyRY, paint);
//draw the compressor
canvas.drawBitmap(compressor.getBitmap(), 0, 0, paint);
//draw the animated loading bar
if (loadBarTimer > 2){
loadBarTimer = 0;
if (loadBarAnim == 1){
loadBarAnim = 2;
}
else if (loadBarAnim == 2){
loadBarAnim = 3;
}
else if (loadBarAnim == 3){
loadBarAnim = 4;
}
else {
loadBarAnim = 1;
}
}
else {
loadBarTimer++;
}
if (loadBarAnim == 1) {
canvas.drawBitmap(loadBarAnimation.getBitmap1(), 19, 1300, paint);
}
else if (loadBarAnim == 2){
canvas.drawBitmap(loadBarAnimation.getBitmap2(), 19, 1300, paint);
}
else if (loadBarAnim == 3) {
canvas.drawBitmap(loadBarAnimation.getBitmap3(), 19, 1300, paint);
}
else {
canvas.drawBitmap(loadBarAnimation.getBitmap4(), 19, 1300, paint);
}
//draw the loading bar
canvas.drawBitmap(loadBar.getBitmap(), 20, 1300, paint);
//Draw the Score
paint.setColor(Color.BLACK);
paint.setTextSize(40);
canvas.drawText("Time: " + score, 100, 1600, paint);
//Draw the Percentage
paint.setColor(Color.BLACK);
paint.setTextSize(40);
canvas.drawText("Percentage: " + percentage, 725, 1600, paint);
ourHolder.unlockCanvasAndPost(canvas);
}
}
if (motionEvent.getX() > screenX - column3 && motionEvent.getX() < screenX - column2 && enemyLY > 200){
if (motionEvent.getY() < screenY) {
enemyLWait = randomGen.nextInt((5 - 1) + 1);
enemyLY = 0;
enemyLDrop = 0;
enemyLGo = false;
enemyLTimer = 0;
lTimer = 0;
canvas = ourHolder.lockCanvas();
canvas.drawColor(Color.WHITE);
paint.setColor(Color.BLACK);
//Draw the invaders
canvas.drawBitmap(enemyL.getBitmap(), (column1 - enemyL.getX()) - (column1 / 4), enemyLY, paint);
canvas.drawBitmap(enemyM.getBitmap(), (column2 - enemyM.getX()) - (column1 / 4), enemyMY, paint);
canvas.drawBitmap(enemyR.getBitmap(), (column3 - enemyL.getX()) - (column1 / 4), enemyRY, paint);
//draw the compressor
canvas.drawBitmap(compressor.getBitmap(), 0, 0, paint);
//draw the animated loading bar
if (loadBarTimer > 2){
loadBarTimer = 0;
if (loadBarAnim == 1){
loadBarAnim = 2;
}
else if (loadBarAnim == 2){
loadBarAnim = 3;
}
else if (loadBarAnim == 3){
loadBarAnim = 4;
}
else {
loadBarAnim = 1;
}
}
else {
loadBarTimer++;
}
if (loadBarAnim == 1) {
canvas.drawBitmap(loadBarAnimation.getBitmap1(), 19, 1300, paint);
}
else if (loadBarAnim == 2){
canvas.drawBitmap(loadBarAnimation.getBitmap2(), 19, 1300, paint);
}
else if (loadBarAnim == 3) {
canvas.drawBitmap(loadBarAnimation.getBitmap3(), 19, 1300, paint);
}
else {
canvas.drawBitmap(loadBarAnimation.getBitmap4(), 19, 1300, paint);
}
//draw the loading bar
canvas.drawBitmap(loadBar.getBitmap(), 20, 1300, paint);
//Draw the Score
paint.setColor(Color.BLACK);
paint.setTextSize(40);
canvas.drawText("Time: " + score, 100, 1600, paint);
//Draw the Percentage
paint.setColor(Color.BLACK);
paint.setTextSize(40);
canvas.drawText("Percentage: " + percentage, 725, 1600, paint);
ourHolder.unlockCanvasAndPost(canvas);
}
}
break;
}
return true;
}
}
Error codes:
11-22 06:41:46.164 9091-9146/au.com.webanddesignbros.loadingbarsimulator W/dalvikvm: threadid=12: thread exiting with uncaught exception (group=0xa65f7228)
11-22 06:41:46.174 9091-9146/au.com.webanddesignbros.loadingbarsimulator E/AndroidRuntime: FATAL EXCEPTION: Thread-206
java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
at android.os.Handler.(Handler.java:121)
at android.os.CountDownTimer$1.(CountDownTimer.java:109)
at android.os.CountDownTimer.(CountDownTimer.java:109)
at au.com.webanddesignbros.loadingbarsimulator.GameView$2.(GameView.java:0)
at au.com.webanddesignbros.loadingbarsimulator.GameView.draw(GameView.java:250)
at au.com.webanddesignbros.loadingbarsimulator.GameView.run(GameView.java:164)
at java.lang.Thread.run(Thread.java:856)
You are canceling the countdown and starting it again without every setting the new time values.
You are in fact only changing your cdTime and percentageTime variables. You should create a new countdown timer with these updated values.
mCountDownTimer.cancel();
cdTime = cdTime + 20000;
percentageTime = percentageTime + 20;
//Create a countdown timer with the updated time
mCountDownTimer = new CounDownTimer(cdTime, anInterval){
/* handle the countdown notifications as you wish, for example like you did in your question */
}
mCountDownTimer.start();
In order to validate that the code above should work a test app has been made. The code and apk are available at this repository : https://github.com/ySiggen/CDTimerTest
After the stack trace has been added to the question, this answer has been edited with the following:
The error you get means that you are calling code (the count down timer) from a background thread while it should be done from the main thread.
You can use a Handler to call the code from another thread like this:
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run() {
mCountDownTimer = new CountDownTimer(cdTime, 1000) {
/* handle the countdown notifications as you wish, for example like you did in your question */
}.start();
}
});
So I made Pong in a applet for a project in school but I realized that I can't hand in the project without creating an HTML file, so I'm attempting to change all my code from a applet to a JFrame. It all works, but my paint method isn't being called, any help will be great. Thanks for the help but to be honest im new to programming so if someone could make the changes to my code and then explain what you did, that would be great
package pong;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
class Main extends JPanel implements Runnable, KeyListener{//whatever class holds you main method
private static final long serialVersionUID = 1L;
int width = 600;
int height = width *9/16;
int Pwidth = 10, Pheight = 50, Px = 30, Py = height / 2-Pwidth, Pv = 3;
int Ewidth = 10, Eheight = 50, Ex = width - Ewidth - 30, Ey = height / 2-Ewidth - 50;
double Ev = 2.7;
int Bwidth = 10, Bheight = 10, Bx = width / 2 + 50, By = height / 2, Bvx = 3, Bvy = 3;
int TimeD = 0;
int Ms = 0, sec = 0, min = 0;
int Pscore = 0, Escore = 0, Pwinx = 800, Pwiny = height / 2, Ewinx = 800, Ewiny = height / 2;
boolean Bleft = true, Bright = false, Bup = true, Bdown = false;
boolean Pup = false, Pdown = false;
boolean Pa = false;
String string = new String();
public static JFrame frame;//public and static so other classes can access it. Might want to use a getter and setter here
public Main(){
frame=new JFrame("Pong, A game re-made by Camron Warren");// Create new JFrame
frame.setSize(width,height);//Set the size of the window
frame.setDefaultCloseOperation(frame.EXIT_ON_CLOSE);//Make sure all processes are closed when the window is closed
frame.setLocationRelativeTo(null);//Centers window
frame.setVisible(true);//Make the window visible
Thread th = new Thread(this);
addKeyListener(this);
th.start();
}
public static void main(String[] args){
new Main();//instantiate the Main class, this has to happen
}
#Override
public void run() {
while(true){
if(Pscore >= 5){
Pwinx = 100;
Py = height / 2 - Pheight / 2;
Bx = width / 2 - Bwidth;
By = height /2 - Bheight /2;
}
if(Escore >= 5){
Ewinx = 400;
Py = height / 2-Pwidth;
Bx = width / 2 - Bwidth;
By = height /2;
}
if(Escore >= 5 && Pa == true){
Pscore = 0;
Escore = 0;
Ewinx = 800;
Ms = 0;
sec = 0;
min = 0;
}
if(Pscore >= 5 && Pa == true){
Pscore = 0;
Escore = 0;
Pwinx = 800;
Ms = 0;
sec = 0;
min = 0;
}
//ball movement class
ballMovement();
//TIME COUNTER
Ms++;
if(Ms >= 60){
sec++;
Ms = 0;
}
if(sec >= 60){
min++;
sec = 0;
}
//BALLMOVEMENT
if(Bleft == true){
Bx-=Bvx;
}
if(Bright == true){
Bx+=Bvx;
}
if(Bup == true){
By-=Bvy;
}
if(Bdown == true){
By+=Bvy;
}
//BALLHITBOX
if(By <= 0){
Bup = false;
Bdown = true;
}
if(By + Bheight >= height){
Bdown = false;
Bup = true;
}
//SCORE SYSTEM
if(Bx <= 0){
Escore++;
Bx = width / 2 - Bwidth;
By = height / 2;
}
if(Bx+Bwidth >= width){
Pscore++;
Bx = width /2 - Bwidth;
By = height / 2;
}
//PHITBOX
if(Bx+Bwidth >= Px && Bx <= Px+Pwidth && By+Bheight >= Py && By <= Py+Pheight){
System.out.println("Phit");
Bleft = false;
Bright = true;
}
//EHITBOX
if(Bx+Bwidth >= Ex && Bx <= Ex + Ewidth && By+Bheight >= Ey && By <= Ey + Eheight){
System.out.println("Ehit");
Bright = false;
Bleft = true;
}
//PMOVEMENT
if(Pup == true){
Py-=Pv;
}
if(Pdown == true){
Py+=Pv;
}
//PHITBOX/APPLETHITBOX
if(Py <= 0){
Py = 0;
}
if(Py + Pheight >= height){
Py = height - Pheight;
}
//EHITBOX/APPLETHITBOX
if(Ey <= 0){
Ey = 0;
}
if(Ey + Eheight >= height){
Ey = height - Eheight;
}
//REPAINT
repaint();
try {
Thread.sleep(17);
} catch (InterruptedException e){
e.printStackTrace();
}
}
}
public void ballMovement()
{
if(By >= Ey)
{
Ey += Ev;
}
if(By <= Ey)
{
Ey -= Ev;
}
}
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
if(key == KeyEvent.VK_W){
Pup = true;
}
if(key == KeyEvent.VK_S){
Pdown = true;
}
if(key == KeyEvent.VK_UP){
Pup = true;
}
if(key == KeyEvent.VK_DOWN){
Pdown = true;
}
if(key == KeyEvent.VK_F1){
Pa = true;
}
}
public void keyReleased(KeyEvent e) {
int key = e.getKeyCode();
if(key == KeyEvent.VK_W){
Pup = false;
}
if(key == KeyEvent.VK_S){
Pdown = false;
}
if(key == KeyEvent.VK_UP){
Pup = false;
}
if(key == KeyEvent.VK_DOWN){
Pdown = false;
}
if(key == KeyEvent.VK_F1){
Pa = false;
}
}
#Override
public void keyTyped(KeyEvent arg0) {}
#SuppressWarnings("deprecation")
public void update(Graphics g) {
Graphics offgc;
Image offscreen = null;
Dimension d = size();
offscreen = createImage(d.width, d.height);
offgc = offscreen.getGraphics();
offgc.setColor(getBackground());
offgc.fillRect(0, 0, d.width, d.height);
offgc.setColor(getForeground());
paint(offgc);
g.drawImage(offscreen, 0, 0, this);
}
#Override
public void paint(Graphics g){
g.setColor(Color.green);
g.fillRect(Px, Py, Pwidth, Pheight);
g.setColor(Color.RED);
g.fillRect(Ex, Ey, Ewidth, Eheight);
g.setColor(Color.BLACK);
g.fillOval(Bx, By, Bwidth, Bheight);
g.setColor(Color.BLACK);
g.drawRect(0, 0, width - 1, height - 1);
g.drawString("Score: " + Pscore, 20, 20);
g.drawString("Score " + Escore , width - 60, 20);
g.drawString("Time played: " + min + ": " + sec, width / 2 - 50, 20);
g.setColor(Color.BLACK);
g.fillRect(width / 2, height, 1, height);
g.setColor(Color.BLACK);
g.drawLine(width / 2, 0, width / 2, height);
g.setColor(Color.BLACK);
g.drawString("Pong: a game re-made by Camron Warren", 10, height - 10);
g.drawString("Congrat's, you win!", Pwinx, Pwiny);
g.drawString("Press F1 to play again!", Pwinx, Pwiny + 10);
g.drawString("Enemy win's", Ewinx, Ewiny);
g.drawString("Press F1 to play again!", Ewinx, Ewiny + 10);
}
}
I am writing an Android game right now and I would need some help in the collision of the wall on screen. When I drag the ball in the top and right it able to collide in wall but when I drag it faster it was able to overlap in the wall
public boolean onTouchEvent(MotionEvent event) {
int x = (int) event.getX();
int y = (int) event.getY();
switch (event.getAction()) {
// if the player moves
case MotionEvent.ACTION_MOVE: {
if (playerTouchRect.contains(x, y)) {
boolean left = false;
boolean right = false;
boolean up = false;
boolean down = false;
boolean canMove = false;
boolean foundFinish = false;
if (x != pLastXPos) {
if (x < pLastXPos) {
left = true;
} else {
right = true;
}
pLastXPos = x;
}
if (y != pLastYPos) {
if (y < pLastYPos) {
up = true;
} else {
down = true;
}
pLastYPos = y;
}
plCellRect = getRectFromPos(x, y);
newplRect.set(playerRect);
newplRect.left = x - (int) (playerRect.width() / 2);
newplRect.right = x + (int) (playerRect.width() / 2);
newplRect.top = y - (int) (playerRect.height() / 2);
newplRect.bottom = y + (int) (playerRect.height() / 2);
int currentRow = 0;
int currentCol = 0;
currentRow = getRowFromYPos(newplRect.top);
currentCol = getColFromXPos(newplRect.right);
if(!canMove){
canMove = mapManager.getCurrentTile().pMaze[currentRow][currentCol] == Cell.wall;
canMove =true;
}
finishTest = mapManager.getCurrentTile().pMaze[currentRow][currentCol];
foundA = finishTest == Cell.valueOf(letterNotGet + "");
canMove = mapManager.getCurrentTile().pMaze[currentRow][currentCol] != Cell.wall;
canMove = (finishTest == Cell.floor || finishTest == Cell.pl) && canMove;
if (canMove) {
invalidate();
setTitle();
}
if (foundA) {
mapManager.getCurrentTile().pMaze[currentRow][currentCol] = Cell.floor;
// finishTest
letterGotten.add(letterNotGet);
playCurrentLetter();
/*sounds.play(sExplosion, 1.0f, 1.0f, 0, 0, 1.5f);*/
foundS = letterNotGet == 's';
letterNotGet++;
}if(foundS){
AlertDialog.Builder builder = new AlertDialog.Builder(mainActivity);
builder.setTitle(mainActivity.getText(R.string.finished_title));
LayoutInflater inflater = mainActivity.getLayoutInflater();
View view = inflater.inflate(R.layout.finish, null);
builder.setView(view);
View closeButton =view.findViewById(R.id.closeGame);
closeButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View clicked) {
if(clicked.getId() == R.id.closeGame) {
mainActivity.finish();
}
}
});
AlertDialog finishDialog = builder.create();
finishDialog.show();
}
else {
Log.d(TAG, "INFO: updated player position");
playerRect.set(newplRect);
setTouchZone();
updatePlayerCell();
}
} // end of (CASE) if playerTouch
break;
} // end of (SWITCH) Case motion
}//end of Switch
return true;
}//end of TouchEvent
private void finish() {
// TODO Auto-generated method stub
}
public int getColFromXPos(int xPos) {
val = xPos / (pvWidth / mapManager.getCurrentTile().pCols);
if (val == mapManager.getCurrentTile().pCols) {
val = mapManager.getCurrentTile().pCols - 1;
}
return val;
}
/**
* Given a y pixel position, return the row of the cell it is in This is
* used when determining the type of adjacent Cells.
*
* #param yPos
* y position in pixels
* #return The cell this position is in
*/
public int getRowFromYPos(int yPos) {
val = yPos / (pvHeight / mapManager.getCurrentTile().pRows);
if (val == mapManager.getCurrentTile().pRows) {
val = mapManager.getCurrentTile().pRows - 1;
}
return val;
}
/**
* When preserving the position we need to know which cell the player is in,
* so calculate it from the centre on its Rect
*/
public void updatePlayerCell() {
plCell.x = (playerRect.left + (playerRect.width() / 2))
/ (pvWidth / mapManager.getCurrentTile().pCols);
plCell.y = (playerRect.top + (playerRect.height() / 2))
/ (pvHeight / mapManager.getCurrentTile().pRows);
if (mapManager.getCurrentTile().pMaze[plCell.y][plCell.x] == Cell.floor) {
for (int row = 0; row < mapManager.getCurrentTile().pRows; row++) {
for (int col = 0; col < mapManager.getCurrentTile().pCols; col++) {
if (mapManager.getCurrentTile().pMaze[row][col] == Cell.pl) {
mapManager.getCurrentTile().pMaze[row][col] = Cell.floor;
break;
}
}
}
mapManager.getCurrentTile().pMaze[plCell.y][plCell.x] = Cell.pl;
}
}
public Rect getRectFromPos(int x, int y) {
calcCell.left = ((x / cellWidth) + 0) * cellWidth;
calcCell.right = calcCell.left + cellWidth;
calcCell.top = ((y / cellHeight) + 0) * cellHeight;
calcCell.bottom = calcCell.top + cellHeight;
Log.d(TAG, "Rect: " + calcCell + " Player: " + playerRect);
return calcCell;
}
public void setPlayerRect(Rect newplRect) {
playerRect.set(newplRect);
}
private void setTouchZone() {
playerTouchRect.set(
playerRect.left - playerRect.width() / TOUCH_ZONE,
playerRect.top - playerRect.height() / TOUCH_ZONE,
playerRect.right + playerRect.width() / TOUCH_ZONE,
playerRect.bottom + playerRect.height() / TOUCH_ZONE);
}
public Rect getPlayerRect() {
return playerRect;
}
public Point getPlayerCell() {
return plCell;
}
public void setPlayerCell(Point cell) {
plCell = cell;
}
}*
This is an architectural problem. You can read more about it here.
In essence, your physics simulation (as simple as might be) is coupled to your framerate (which is capped at 60fps). Any events occurring faster than 60Hz cannot be processed accurately hence your bug.
The solution is to run the collision detection on an independent thread and draw the state it calculates at 60fps.
Also, take a look at these gamedev questions that refer to the same article.