代码之家  ›  专栏  ›  技术社区  ›  Niklas Rosencrantz

改善月球车的运动

  •  1
  • Niklas Rosencrantz  · 技术社区  · 6 年前

    我正在为Android开发一款迷你游戏, available from the playstore ,我们称之为“月球车”。行动是你在月球上控制一辆汽车,你应该保护自己不受飞碟攻击。

    enter image description here

    现在我想改善车辆的运动。我有代码,这样它就不会在屏幕外移动,而且可以加速、减速和跳跃。但这并不完美。我的灵感来自经典的游戏 Moon Patrol 这是测量每个完成部分的时间,我的游戏也这么做。所以你最好能加速,加速越快完成这一部分,而不是像我的车现在这样停在屏幕的尽头。而且,或许它应该加速。

    相关代码为:

    视差活动.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;
            }
        }
    }
    

    视差视图.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;
    
    
    }
    

    由于限制为30000个字符,因此可根据要求提供完整的代码。

    1 回复  |  直到 6 年前
        1
  •  1
  •   Maxim Srour    6 年前

    不幸的是,我现在不能给你提供这个代码(因为我现在在工作),但是你可以做的一件事是根据是否按下了跳转按钮来修改你的下降速度(加速度)。

    即。

    // 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
    }
    

    这样做的目的是让你的跳跃感觉更灵敏,当你以一个很好的速度向上移动时,然后迅速地直接落在地上。它还提供了著名的踢踏低跳保持跳高的感觉,你发现在马里奥游戏等。

    除非我完全误解了你的问题,否则我相信这将有助于提高你的游戏感。我在其他项目中也实现了类似的功能,人们总是对这种变化做出积极的回应,经常声称这感觉更像是一个真正的“游戏”。

    更新:因为我注意到你实际上没有重力函数,这里有一个方法。单位2d是c,但是 this is how I learned to do it ,所以我知道这很好。