Улучшить движение лунной машины - PullRequest
0 голосов
/ 04 июля 2018

Я создаю мини-игру для Android, , доступную в игровом магазине , которую мы называем "Moon Buggy". Действие состоит в том, что вы управляете транспортным средством на Луне, и вы должны защитить себя от нападения НЛО.

enter image description here

Теперь я хочу улучшить движение машины. У меня есть код, чтобы он не выходил за пределы экрана, и можно было ускоряться, замедляться и прыгать. Но это не идеально. Я был вдохновлен классической игрой 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 символов.

1 Ответ

0 голосов
/ 04 июля 2018

Я, к сожалению, не могу предоставить вам код для этого прямо сейчас (так как я в данный момент на работе), но одну вещь, которую вы можете сделать, это изменить скорость падения (ускорение) в зависимости от того, удерживается ли кнопка прыжка.

т.

// Put this into your constant gravity function
// Or whatever you have that makes the player fall
// This should be altering a local gravity modifier in the player
if(jumpKeyHeld) {
    locaGravAccel = 0.5
} else {
    locaGravAccel = 1.0
}

Это делает ваш прыжок более чувствительным, когда вы двигаетесь вверх с хорошей скоростью, а затем быстро падаете прямо на землю. Это также дает известное чувство «нажми для низкого прыжка, удерживай для высокого прыжка», которое можно найти в играх Mario и т. П.

Если я не очень неправильно понял ваш вопрос, я верю, что это поможет вам почувствовать игру. Я реализовал подобные функции в других проектах, и люди всегда положительно реагировали на это изменение, часто утверждая, что это больше похоже на настоящую «игру».

ОБНОВЛЕНИЕ: Поскольку я заметил, что у вас нет гравитационной функции, вот один из способов сделать это. Это в C # для unity2D, но так я научился это делать , поэтому я знаю, что это хорошо.

...