问题
I'm creating a little game in Javascript, and I have trees that can hold a certain amount of max experience, and each tree have a varied amount of branches that also needs to be leveled up with experience, and they should total to the tree max experience.
If it was that easy, I would just divide them equally, like max / branches
, but since it's for a game, I need to make a formula where the first branch needs no experience, and then each branch experience needed steadily increase (while still totalling to the tree max experience).
Branch 1 0 XP
Branch 2 100 XP
Branch 3 200 XP
Branch 4 300 XP
Total Tree Experience Capacity: 600 XP
The amount of branches can be anything from 2 to 10, to 20 and so on, so it must therefor scale with the tree max experience capacity, I believe. How much I want each level to increase with must also depend on how many branches there are, but there should be some kind of pattern across all trees, I think (correct me if it's a bad idea).
The variables that we know are:
- The amount of branches we have per tree
- Max experience capacity for each tree
The rest is unknown.
How can a formula solve this issue? I also do not mind any functional formulas for specifically JS.
回答1:
What you seem to want is arithmetic progression. It's a sequence of numbers where there is a common difference between each, for example 1, 4, 7, 10
would be an arithmetic progression where the difference is 3
between each subsequent members.
The more generalised view of arithmetic progression is
a, a + d, a + 2d, a + 3d, ..., a + nd`
Where a
is your initial member, d
is the difference, and n
is the length of the series.
The formula for a sum of arithmetic series is as follows:
S = (n/2) * (2*a + (n - 1)*d)
Which looks complex let's just see it in action. Let's say we want to sum the series 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
. Or integers from 1 to 10. Substituting in the formula, we have a = 1
, d = 1
, n = 10
and we get
S = (10/2) * (2*1 + (10 - 1)*1)
= 5 * (2 + 9*1)
= 5 * (2 + 9)
= 5 * 11
= 55
And we can just write code to verify:
const sum = 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10;
console.log(sum);
So, the formula works.
Now, we want to shuffle things - we have S
, for the total tree experience capacity, we also have n
the number of branches, and we have a
which would be zero for the initial branch. We just need to find d
in order to get all the things we need. So, here it goes:
S = (n/2) * (2*a + (n - 1)*d)
S / (n/2) = 2*a + (n - 1)*d
(S / (n/2)) - 2*a = (n - 1)*d
((S / (n/2)) - 2*a) / (n - 1) = d
We can actually eliminate 2*a
since we know a = 0
, so we can slightly simplify the formula:
(S / (n/2)) / (n - 1) = d
And done. We can just encode it in a function now:
// S = totalExperience
// n = branches
function findArithmeticStep(totalExperience, branches) {
return (totalExperience / (branches/2)) / (branches - 1);
}
console.log(findArithmeticStep(600, 4));
You can even use a generator function that will supply you the next XP value:
// S = totalExperience
// n = branches
function findArithmeticStep(totalExperience, branches) {
return (totalExperience / (branches/2)) / (branches - 1);
}
function* nextXPCost(totalExperience, branches) {
const step = findArithmeticStep(totalExperience, branches);
let currentXPCost = 0;
for(let i = 0; i < branches; i++) {
yield currentXPCost;
currentXPCost += step;
}
}
const gen = nextXPCost(600, 4);
//1 - 0
let next = gen.next();
console.log(next.value, next.done);
//2 - 100
next = gen.next();
console.log(next.value, next.done);
//3 - 200
next = gen.next();
console.log(next.value, next.done);
//4 - 300
next = gen.next();
console.log(next.value, next.done);
//5 - getting after the end
next = gen.next();
console.log(next.value, next.done);
//generate an array of all costs
const allCostsTree1 = [...nextXPCost(600, 4)];
console.log(allCostsTree1);
//generate a different tree with higher total cost
const allCostsTree2 = [...nextXPCost(2000, 5)];
console.log(allCostsTree2)
回答2:
This is what you seek.
Your "rate" increment for each level is based on the summation of all the numbers between "1" and the BRANCH_COUNT-1. There's probably a name in mathematics for this summatation, but I forget it....
It's easily computed with a simple function that takes the total number of branches and the total XP.
// A function that determines the rate by which each branch reward should increment by
function getRate(branch_count, total_xp) {
if (branch_count <= 1) {
return 0;
}
let R = 0;
for (let i = 1; i < branch_count; i++) {
R += i;
}
return total_xp / R;
}
And by recalling some high school match as explained here. The above is can be simplified to just this:
function getRate(branch_count, total_xp) {
if (branch_count <= 1) {
return 0;
}
let R = ((branch_count-1) * (branch_count))/2;
return total_xp / R;
}
And then some sample code using that function to print out the reward structure for each branch
// sample function to print the reward count for each branch
function dumpBranches(branch_count, total_xp) {
let rate = getRate(branch_count, total_xp);
let reward = 0;
for (let i = 0; i < branch_count; i++) {
console.log("Branch ", i, reward);
reward += rate;
}
}
Example:
> dumpBranches(4, 600)
Branch 0 0
Branch 1 100
Branch 2 200
Branch 3 300
> dumpBranches(9, 2700)
Branch 0 0
Branch 1 75
Branch 2 150
Branch 3 225
Branch 4 300
Branch 5 375
Branch 6 450
Branch 7 525
Branch 8 600
来源:https://stackoverflow.com/questions/60904585/formula-in-js-to-create-experience-goals-for-different-branches-in-a-game