Я создаю мини-игру для Android, , доступную в игровом магазине , которую мы называем "Moon Buggy". Действие состоит в том, что вы управляете транспортным средством на Луне, и вы должны защитить себя от нападения НЛО.
Теперь я хочу улучшить движение машины. У меня есть код, чтобы он не выходил за пределы экрана, и можно было ускоряться, замедляться и прыгать. Но это не идеально. Я был вдохновлен классической игрой Moon Patrol , которая измеряет время на завершенный раздел, и моя игра тоже это делает. Поэтому желательно, чтобы вы могли ускоряться и завершать раздел быстрее, чем больше вы ускоряетесь, чем останавливаться в конце экрана, как сейчас делает мой автомобиль. Также, возможно, он должен ускоряться быстрее.
Соответствующий код:
ParallaxActivity.java
public class ParallaxActivity extends Activity implements View.OnClickListener {
long startTime;
long countUp;
TextView textGoesHere;
ParallaxView parallaxView;
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.button3:
ParallaxView parallaxView = findViewById(R.id.backgroundImage);
parallaxView.recent = false;
parallaxView.brake = false;
parallaxView.buggyXDistance = parallaxView.buggyXDistance + 3;
parallaxView.distanceDelta = parallaxView.distanceDelta + 0.2;
break;
case R.id.button4:
ParallaxView parallaxView2 = findViewById(R.id.backgroundImage);
parallaxView2.recent = false;
parallaxView2.buggyXDistance = parallaxView2.buggyXDistance - 7;
parallaxView2.retardation = parallaxView2.retardation + 0.2;
parallaxView2.brake = true;
break;
case R.id.button2:
ParallaxView parallaxView3 = findViewById(R.id.backgroundImage);
parallaxView3.numberOfshots++;
parallaxView3.recent = false;
parallaxView3.launchMissile();
parallaxView3.scoring = true;
break;
case R.id.button1:
ParallaxView parallaxView4 = findViewById(R.id.backgroundImage);
if(parallaxView4.distanceDelta<3) parallaxView4.distanceDelta = parallaxView4.distanceDelta + 0.2;
parallaxView4.jump = true;
parallaxView4.shoot = false;
parallaxView4.lastTurn3 = System.currentTimeMillis();
break;
default:
break;
}
}
}
ParallaxView.java
public class ParallaxView extends SurfaceView implements Runnable, SurfaceHolder.Callback {
static int bombed = 5;
boolean waitForTimer = false;
boolean waitForTimer2 = false;
boolean waitForTimer3 = false;
boolean recent = false;
Rect fromRect1;
Rect toRect1;
Rect fromRect2;
Rect toRect2;
boolean increment = false;
int numberOfshots = 0; // change to 0
int[] missiles = new int[200];
int alienBombYDelta = 0;
int alienBombYDelta2 = 0;
int alienBombXDelta = 20;
int alienBombXDelta2 = 30;
int p = 7;
int p2 = 13;
boolean once, once2 = true;
final int buggyXDisplacement = 450;
int jumpHeight = 0;
int xbuggy2 = 0;
boolean toggleDeltaY = true;
long lastTurn2 = System.currentTimeMillis();
long lastTurn3 = System.currentTimeMillis();
boolean toggleGround = true;
boolean jump = false;
boolean shoot = false;
int index = 0;
int missileOffSetY = 0;
static int score = 0;
double buggyXDistance = 0;
double distanceDelta = 1.15;
double retardation = 0.5;
boolean checkpointComplete = false;
boolean runOnce = true;
boolean passed = false;
List<Background> backgrounds;
int spacerocki, resID, explodeID, explodeID2, alienResID2;
boolean toggle = true;
private volatile boolean running;
private Thread gameThread = null;
Bitmap explode, buggy, alien, alien2, explode2, spacerock, spacerock2, hole;
boolean alienexplode = false;
TextView tvId;
TextView checkpointtextview;
TextView checkpointtextview2;
TextView checkpointtextview3;
TextView checkpointtextview4;
TextView checkpointtextview5;
TextView checkpointtextview6;
// For drawing
private Paint paint;
private Canvas canvas;
private SurfaceHolder ourHolder;
AttackingAlien alien3;
AttackingAlien alien4, alien5;
// Holds a reference to the Activity
Context context;
// Control the fps
long fps = 60;
// Screen resolution
int screenWidth;
int screenHeight;
boolean bexplode = false;
boolean brake = false;
boolean scoring = false;
// use Handler instead
// this runs for 4 seconds and not just once after a while
class BuggyExploded extends TimerTask {
public void run() {
distanceDelta = 1.15;
retardation = 0.5;
jumpHeight = 0;
bexplode=true;
}
}
// use Handler instead
class SetRecent extends TimerTask {
public void run() {
recent = false;
}
}
// use Handler instead
class ResetCheckpoint extends TimerTask {
public void run() {
Log.d("## sectionComplete", "sectionComplete " + sectionComplete);
if (sectionComplete == 0) Background.checkpoint = 'A';
if (sectionComplete == 1) Background.checkpoint = 'F';
if (sectionComplete == 2) Background.checkpoint = 'K';
if (sectionComplete == 3) Background.checkpoint = 'P';
if (sectionComplete == 4) Background.checkpoint = 'U';
//if (sectionComplete==5) Background.checkpoint = 'U';
}
}
private void update() {
// Update all the background positions
for (Background bg : backgrounds) {
bg.update(fps);
}
}
@Override
public void run() {
while (running) {
long startFrameTime = System.currentTimeMillis();
update();
if (alienBombXDelta > screenWidth - 250 || alienBombXDelta < 10) { // UFO change direction
p = -p;
}
if (alienBombXDelta2 > screenWidth - 250 || alienBombXDelta2 < 10) { // UFO2 change direction
p2 = -p2;
}
draw();
// Calculate the fps this frame
long timeThisFrame = System.currentTimeMillis() - startFrameTime;
if (timeThisFrame >= 1) {
fps = 1000 / timeThisFrame;
}
}
}
private void checkJump() {
if (System.currentTimeMillis() - lastTurn3 >= 650) { // 650 means how long the vehicle is in the air at a jump
// Change direction here
jump = false;
lastTurn3 = System.currentTimeMillis();
}
}
private void checkBuggyBombed() {
if (recent) {
// use handlers instead
new Timer().schedule(new BuggyExploded(), 4000);
new Timer().schedule(new SetRecent(), 10000);
new Timer().schedule(new ResetCheckpoint(), 1000);
}
}
private void makeShots(Bitmap b) {
for (int i1 = 0; i1 < numberOfshots; i1++) {
if (shoot) {
canvas.drawText("o", (float) (missiles[i1] + buggyXDistance + 450), (float) (screenHeight * 0.7) - jumpHeight, paint); // add to y the jump height
canvas.drawText("o", (float) (buggyXDistance + 185 + 400), screenHeight / 110 * 95 - missiles[i1] - xbuggy2, paint);
}
if (i1 == numberOfshots - 1 && missiles[i1] > screenWidth) {
if (numberOfshots > 0) numberOfshots--;
if (index > 0) index--;
}
}
}
private void updateDeltas() {
alienBombXDelta = alienBombXDelta + p;
//make sure alien does not move too low
if (alienBombYDelta + 1 > screenHeight / 2)
alienBombYDelta=alienBombYDelta-2;
if (!toggleDeltaY)
alienBombYDelta++;
else
alienBombYDelta--;
alienBombXDelta2 = alienBombXDelta2 + p2;
if (!toggleDeltaY)
alienBombYDelta2++;
else
alienBombYDelta2--;
}
//use a Handler instead
private void changeDirections() {
if (System.currentTimeMillis() - lastTurn2 >= 7000) {
// Change direction here
toggleDeltaY = !toggleDeltaY;
lastTurn2 = System.currentTimeMillis();
}
}
//try to improve this
private void controlVelocity() {
if (!brake && buggyXDistance > 0) buggyXDistance = buggyXDistance + distanceDelta;
else if (brake && buggyXDistance > 0) buggyXDistance = buggyXDistance - retardation;
}
TextView tvId1;
int sectionComplete = 0;
private void drawDetails() {
//draw a background color
}
private void makeShots() {
for (int n = 0; n < numberOfshots; n++)
missiles[n] = missiles[n] + 20;
}
public void changeText() {
if (scoring) {
((Activity) this.getContext()).runOnUiThread(new Runnable() {
@Override
public void run() {
String str = "Player 1 " + String.format("%06d", score);
tvId.setText(str);
scoring = false;
}
});
}
}
double lastTurn4 = System.currentTimeMillis();
//change to handler
private void checkFire() {
if (System.currentTimeMillis() - lastTurn4 >= 118500) { // 18500 means how often the alien fires
lastTurn4 = System.currentTimeMillis();
missileOffSetY = 0;
}
}
private void draw() {
if (retardation > 0.5)
distanceDelta = 0;
if (distanceDelta > 0)
retardation = 0.5;
if (ourHolder.getSurface().isValid()) {
//First we lock the area of memory we will be drawing to
canvas = ourHolder.lockCanvas();
if (checkpointComplete) {
((Activity) this.getContext()).runOnUiThread(new Runnable() {
@Override
public void run() {
//
}
});
canvas.drawColor(Color.BLACK);
((ParallaxActivity) getContext()).stopWatch.stop();
paint.setTextSize(60);
String s2 = "TIME TO REACH POINT \"" + Background.checkpoint + "\"\n";
if (runOnce) {
for (int q = 0; q < s2.length(); q++) {
final String s2f = s2;
final int r = q;
((Activity) this.getContext()).runOnUiThread(new Runnable() {
@Override
public void run() {
checkpointtextview.setTextColor(Color.RED);
checkpointtextview.append(Character.toString(s2f.charAt(r)));
}
});
try {
Thread.sleep(50);
} catch (InterruptedException ie) {
}
}
}
String str = String.format("%03d", ((ParallaxActivity) this.getContext()).countUp);
String s3 = "YOUR TIME : " + str;
if (runOnce) {
for (int q = 0; q < s3.length(); q++) {
final String s3f = s3;
final int r = q;
((Activity) this.getContext()).runOnUiThread(new Runnable() {
@Override
public void run() {
checkpointtextview2.setTextColor(Color.parseColor("#ADD8E6"));
checkpointtextview2.append(Character.toString(s3f.charAt(r)));
}
});
try {
Thread.sleep(50);
} catch (InterruptedException ie) {
}
}
}
String s4 = "THE AVERAGE TIME : 060";
if (runOnce) {
for (int q = 0; q < s4.length(); q++) {
final String s4f = s4;
final int r = q;
((Activity) this.getContext()).runOnUiThread(new Runnable() {
@Override
public void run() {
checkpointtextview3.setTextColor(Color.parseColor("#ADD8E6"));
checkpointtextview3.append(Character.toString(s4f.charAt(r)));
}
});
try {
Thread.sleep(50);
} catch (InterruptedException ie) {
}
}
}
String s5 = "TOP RECORD : 060";
if (runOnce) {
for (int q = 0; q < s5.length(); q++) {
final String s5f = s5;
final int r = q;
((Activity) this.getContext()).runOnUiThread(new Runnable() {
@Override
public void run() {
checkpointtextview4.setTextColor(Color.RED);
checkpointtextview4.append(Character.toString(s5f.charAt(r)));
}
});
try {
Thread.sleep(50);
} catch (InterruptedException ie) {
}
}
}
String s6 = "GOOD BONUS POINTS : 1000";
if (runOnce) {
for (int q = 0; q < s6.length(); q++) {
final String s6f = s6;
final int r = q;
((Activity) this.getContext()).runOnUiThread(new Runnable() {
@Override
public void run() {
checkpointtextview5.setTextColor(Color.RED);
checkpointtextview5.append(Character.toString(s6f.charAt(r)));
}
});
try {
Thread.sleep(50);
} catch (InterruptedException ie) {
}
}
}
if (runOnce) {
score = score + 1000;
sectionComplete++;
recent = true;
}
runOnce = false;
// canvas.drawText("CHECKPOINT COMPLETE", (float) (screenWidth * 0.35), (float) (screenHeight * 0.45), paint);
((Activity) this.getContext()).runOnUiThread(new Runnable() {
@Override
public void run() {
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
((ParallaxActivity) getContext()).startTime = SystemClock.elapsedRealtime();
((ParallaxActivity) getContext()).stopWatch.setBase(((ParallaxActivity) getContext()).startTime);
((ParallaxActivity) getContext()).stopWatch.start();
checkpointtextview.setText("");
checkpointtextview2.setText("");
checkpointtextview3.setText("");
checkpointtextview4.setText("");
checkpointtextview5.setText("");
checkpointtextview6.setText("");
String str = "Player 1 " + String.format("%06d", score);
tvId.setText(str);
scoring = false;
buggyXDistance = 0;
distanceDelta = 0;
retardation = 0;
checkpointComplete = false;
runOnce = true;
}
}, 3000);
}
});
} else {
if (bombed == 0) //GAME OVER
{
final int duration = Toast.LENGTH_SHORT;
((Activity) this.getContext()).runOnUiThread(new Runnable() {
@Override
public void run() {
final Toast toast = Toast.makeText(context, "GAME OVER!\nScore: " + score, duration);
toast.show();
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
toast.cancel();
bombed = 5;
score = 0;
Background.checkpoint = 'A';
String str = "Player 1 " + String.format("%06d", score);
tvId.setText(str);
}
}, 3000);
}
});
}
// adjust vehicle physics when jumping
if (jump && jumpHeight < 300) {
jumpHeight = jumpHeight + 7;
if (distanceDelta < 3) distanceDelta = distanceDelta + 0.55;
} else if (jumpHeight > 0) {
jumpHeight = jumpHeight - 4;
if (distanceDelta < 3) distanceDelta = distanceDelta + 0.55;
}
if (shoot) {
xbuggy2 = xbuggy2 + 4;
}
checkFire();
checkJump();
// drawDetails();
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));
checkBuggyBombed();
makeShots(alien);
changeDirections();
alien3.update(canvas, paint, toggleDeltaY, screenWidth, screenHeight);
recent=alien3.drawMissile(this, canvas, paint, buggyXDisplacement, buggyXDistance, buggy, jumpHeight, screenHeight);
if(recent) {
waitForTimer = true;
bexplode=true;
AttackingAlien.recent = true;
}
alien4.update(canvas, paint, toggleDeltaY, screenWidth, screenHeight);
boolean recent2=alien4.drawMissile(this, canvas, paint, buggyXDisplacement, buggyXDistance, buggy, jumpHeight, screenHeight);
if(recent || recent2) {
recent = true;
waitForTimer = true;
bexplode=true;
AttackingAlien.recent = true;
}
alien5.update(canvas, paint, toggleDeltaY, screenWidth, screenHeight);
boolean recent3=alien5.drawMissile(this, canvas, paint, buggyXDisplacement, buggyXDistance, buggy, jumpHeight, screenHeight);
if(recent || recent2 || recent3) {
recent = true;
waitForTimer = true;
bexplode=true;
AttackingAlien.recent = true;
Handler handler = new Handler(Looper.getMainLooper());
// this code runs after a while
handler.postDelayed(new Runnable() {
@Override
public void run() {
recent = false;
AttackingAlien.recent = false;
waitForTimer = false;
bexplode=false;
buggyXDistance = 0;
Log.d("postDelayed", "postDelayed ");
}
}, 5000);
}
checkBuggyBombed();
for (int i1 = 0; i1 < numberOfshots; i1++) {
alien3.checkBeingHit(missiles, buggyXDisplacement, buggyXDistance, canvas, explode2, paint, score, this, i1, xbuggy2);
alien4.checkBeingHit(missiles, buggyXDisplacement, buggyXDistance, canvas, explode2, paint, score, this, i1, xbuggy2);
alien5.checkBeingHit(missiles, buggyXDisplacement, buggyXDistance, canvas, explode2, paint, score, this, i1, xbuggy2);
}
drawBackground(1);
// canvas.drawText("X", (float) (50 + buggyXDistance)+buggy.getWidth()/2, (float) (screenHeight * 0.3) - jumpHeight+buggy.getHeight(), paint);
paint.setTextSize(60);
canvas.drawText("A E J O T Z", (float) (screenWidth * 0.7), (float) (screenHeight * 0.15), paint);
// Prevent buggy from moving outside horizontal screen
if (!brake && buggyXDisplacement + buggyXDistance > screenWidth - buggy.getWidth() - 200)
buggyXDistance = screenWidth - buggy.getWidth() - 200;
//Log.d("buggyXDistance", "buggyXDistance " + buggyXDistance);
if (!bexplode && !waitForTimer && !checkpointComplete)
canvas.drawBitmap(buggy, (float) (buggyXDisplacement + buggyXDistance), (float) (screenHeight * 0.5) - jumpHeight, paint);
else if (bexplode && !checkpointComplete) {
canvas.drawBitmap(explode, (float) (buggyXDisplacement + buggyXDistance), (float) (screenHeight * 0.5) - jumpHeight, paint);
distanceDelta = 0;
retardation = 0;
}
int inc = 0;
for (int i = 0; i < bombed; i++) {
canvas.drawBitmap(Bitmap.createScaledBitmap(buggy, (int) (0.50 * (buggy.getWidth() / 3)), (int) (0.50 * buggy.getHeight() / 3), false), inc, 100, paint);
inc = inc + buggy.getWidth() / 4;
}
makeShots();
updateDeltas();
controlVelocity();
}
ourHolder.unlockCanvasAndPost(canvas);
}
}
// Clean up our thread if the game is stopped
public void pause() {
running = false;
try {
gameThread.join();
} catch (InterruptedException e) {
// Error
//e.printStackTrace();
}
}
// Make a new thread and startMissile it
// Execution moves to our run method
public void resume() {
running = true;
gameThread = new Thread(this);
gameThread.start();
}
int craterX = -550;
}
Полный код доступен по запросу из-за ограничения SO в 30000 символов.