You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android开发:实现小球弹跳高度-时间曲线及弹跳次数统计

Fixing the Bouncing Ball Height-Time Graph for Your Android App

Hey there! I see you're working on an Android app to visualize a bouncing ball's height over time, and you want to add support for custom initial height, bounce coefficient, and track the total bounce count. Let's fix up your current code to properly model the physics and meet all your requirements.

First, let's address the issues in your current code:

  • Your loop doesn't model the actual physics of falling and bouncing—right now it just decrements height by 10% every 0.1 seconds, which doesn't reflect how a ball accelerates downward or decelerates upward.
  • Time calculation is disconnected from the physical motion (you're just adding 0.1 each iteration instead of calculating how long each fall/rise takes).
  • There's no way for users to input initial height or adjust the bounce coefficient, and no tracking of total bounces.

Here's the complete solution:

First, update your layout (activity_main.xml) to add UI controls for user input and bounce count display:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="16dp">

    <!-- User Input Fields -->
    <EditText
        android:id="@+id/et_initial_height"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="Enter Initial Height (m)"
        android:inputType="numberDecimal"/>

    <EditText
        android:id="@+id/et_bounce_coeff"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="Enter Bounce Coefficient (0-1)"
        android:inputType="numberDecimal"/>

    <Button
        android:id="@+id/btn_generate_graph"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Generate Graph"/>

    <!-- Bounce Count Display -->
    <TextView
        android:id="@+id/tv_bounce_count"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="16dp"
        android:textSize="18sp"/>

    <!-- Graph View -->
    <com.jjoe64.graphview.GraphView
        android:id="@+id/graphView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginTop="16dp"/>

</LinearLayout>

Now, update your MainActivity.java to handle the physics, user input, and graph rendering:

import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
import com.jjoe64.graphview.GraphView;
import com.jjoe64.graphview.series.DataPoint;
import com.jjoe64.graphview.series.LineGraphSeries;

public class MainActivity extends AppCompatActivity {
    private EditText etInitialHeight;
    private EditText etBounceCoeff;
    private TextView tvBounceCount;
    private GraphView graphView;
    private LineGraphSeries<DataPoint> series;

    // Physics constants
    private final double GRAVITY = 10.0; // m/s²
    private final double TIME_STEP = 0.01; // Smaller step for smoother curve
    private final double MIN_HEIGHT = 0.1; // Stop when bounce height is below this

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Initialize UI elements
        etInitialHeight = findViewById(R.id.et_initial_height);
        etBounceCoeff = findViewById(R.id.et_bounce_coeff);
        tvBounceCount = findViewById(R.id.tv_bounce_count);
        graphView = findViewById(R.id.graphView);
        Button btnGenerate = findViewById(R.id.btn_generate_graph);

        // Set default values for input fields
        etInitialHeight.setText("20.0");
        etBounceCoeff.setText("0.8");

        // Generate graph on button click
        btnGenerate.setOnClickListener(v -> generateBounceGraph());
    }

    private void generateBounceGraph() {
        // Get user input values
        double initialHeight;
        double bounceCoeff;
        try {
            initialHeight = Double.parseDouble(etInitialHeight.getText().toString());
            bounceCoeff = Double.parseDouble(etBounceCoeff.getText().toString());

            // Validate input
            if (initialHeight <= 0 || bounceCoeff <= 0 || bounceCoeff >= 1) {
                tvBounceCount.setText("Please enter valid values: Height >0, Coeff 0-1");
                return;
            }
        } catch (NumberFormatException e) {
            tvBounceCount.setText("Please enter valid decimal numbers");
            return;
        }

        // Reset graph and bounce count
        graphView.removeAllSeries();
        series = new LineGraphSeries<>();
        double currentTime = 0.0;
        double currentHeight = initialHeight;
        int bounceCount = 0;

        // Add initial point (time=0, initial height)
        series.appendData(new DataPoint(currentTime, currentHeight), true, Integer.MAX_VALUE);

        while (currentHeight > MIN_HEIGHT) {
            // Phase 1: Ball falls from currentHeight to ground
            // Calculate time to fall: h = 0.5*g*t² → t = sqrt(2h/g)
            double timeToFall = Math.sqrt(2 * currentHeight / GRAVITY);
            // Simulate each time step during fall
            double fallStartTime = currentTime;
            while (currentTime < fallStartTime + timeToFall) {
                currentTime += TIME_STEP;
                // Height during fall: h(t) = currentHeight - 0.5*g*(t - fallStartTime)²
                double timeElapsedInFall = currentTime - fallStartTime;
                double fallHeight = currentHeight - 0.5 * GRAVITY * Math.pow(timeElapsedInFall, 2);
                // Ensure we don't go below ground level
                fallHeight = Math.max(fallHeight, 0.0);
                series.appendData(new DataPoint(currentTime, fallHeight), true, Integer.MAX_VALUE);
            }

            // Ball hits ground, increment bounce count
            bounceCount++;

            // Phase 2: Ball bounces up to new height
            currentHeight *= bounceCoeff;
            // Calculate time to reach peak: v = u - g*t → t = u/g, where u = sqrt(2*g*currentHeight)
            double timeToPeak = Math.sqrt(2 * currentHeight / GRAVITY);
            // Simulate each time step during rise
            double riseStartTime = currentTime;
            while (currentTime < riseStartTime + timeToPeak) {
                currentTime += TIME_STEP;
                // Height during rise: h(t) = sqrt(2*g*currentHeight)*(t - riseStartTime) - 0.5*g*(t - riseStartTime)²
                double timeElapsedInRise = currentTime - riseStartTime;
                double riseHeight = Math.sqrt(2 * GRAVITY * currentHeight) * timeElapsedInRise - 0.5 * GRAVITY * Math.pow(timeElapsedInRise, 2);
                series.appendData(new DataPoint(currentTime, riseHeight), true, Integer.MAX_VALUE);
            }
        }

        // Add the final point at ground level
        series.appendData(new DataPoint(currentTime, 0.0), true, Integer.MAX_VALUE);

        // Configure graph
        graphView.addSeries(series);
        graphView.setTitle("Height vs Time Graph");
        graphView.getGridLabelRenderer().setHorizontalAxisTitle("Time (s)");
        graphView.getGridLabelRenderer().setVerticalAxisTitle("Height (m)");

        // Display bounce count
        tvBounceCount.setText("Total Bounces: " + bounceCount);
    }
}

Key improvements explained:

  • Accurate Physics Simulation: We split each bounce into two phases—falling to the ground and rising to the new bounce height—using the correct kinematic equations. This gives a realistic curve that matches the expected bouncing ball motion.
  • User Input Support: Added EditText fields for initial height and bounce coefficient, with input validation to ensure valid values.
  • Bounce Count Tracking: We increment the count each time the ball hits the ground, then display it in a TextView.
  • Smoother Curve: Used a smaller TIME_STEP (0.01s) to make the graph line smoother, and ensured we don't plot values below ground level.
  • Reusable Graph Generation: The generateBounceGraph() method handles all logic, so users can adjust inputs and regenerate the graph anytime.

Just make sure you have the GraphView library added to your build.gradle (Module level):

dependencies {
    implementation 'com.jjoe64:graphview:4.2.2'
}

内容的提问来源于stack exchange,提问作者Alton Dsouza

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 00:09:06