To solve this problem, we can formulate a linear programming model. The goal is to maximize the total points earned from hitting slow and fast balls, subject to the given constraints.

Let's define two decision variables:
- $x_s$: The number of slow balls hit.
- $x_f$: The number of fast balls hit.

The objective function to maximize is the total points earned: $3x_s + 5x_f$.

The constraints are as follows:
1. Hit at least 5 slow balls: $x_s \geq 5$.
2. Hit at least 3 fast balls: $x_f \geq 3$.
3. Hit at most 8 slow balls: $x_s \leq 8$.
4. Hit at most 8 fast balls: $x_f \leq 8$.
5. Hit no more than 12 balls in total: $x_s + x_f \leq 12$.

All decision variables are non-negative since you cannot hit a negative number of balls.

Now, let's translate this problem into Gurobi code using Python:

```python
from gurobipy import *

# Create a new model
m = Model("Ball_Hitting_Optimization")

# Define the decision variables
x_s = m.addVar(name='slow_balls', vtype=GRB.INTEGER, lb=5, ub=8)
x_f = m.addVar(name='fast_balls', vtype=GRB.INTEGER, lb=3, ub=8)

# Set the objective function to maximize
m.setObjective(3*x_s + 5*x_f, GRB.MAXIMIZE)

# Add constraints if necessary (Gurobi handles bounds directly)
# Since we've already set lower and upper bounds on our variables,
# the only constraint left to explicitly add is the total number of balls:
m.addConstr(x_s + x_f <= 12, name='total_balls')

# Optimize the model
m.optimize()

# Print out the results
if m.status == GRB.OPTIMAL:
    print(f"Optimal solution found: Hit {x_s.x} slow balls and {x_f.x} fast balls.")
    print(f"Total points earned: {3*x_s.x + 5*x_f.x}")
else:
    print("No optimal solution found")
```