Last active
April 26, 2021 10:08
-
-
Save antonkudin/b05f6df189424c1af2406a6d645dfbb3 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class treeThing { | |
// tree design: all the changable variables in one place! | |
struct treeStyle { | |
// skipping stuff like how many branches per tree, sticks per branch.. | |
// sticks | |
Vector2 stickAngleJagMM; // how jaggy the branches are (min-max) | |
Vector2 stickLengthMM; // how long the sticks are (min-max) | |
sprite[] sprites; // sprites to be assigned to sticks, can be assigned based on seed or using | |
// stick's branch position to get the 'leaf' shape if you have arrange this array | |
// [0-5] small leaf > [6-10] big leaf > [11-20] small leaf, or similar | |
// spring parameters to be assigned to sticks, from root of branch to its tip | |
float springFreqRoot; | |
float springFreqTip; | |
float springDampRoot; | |
float springDampTip; | |
// branches | |
Vector2 branchAngleMM; // branch angles (min-max) | |
int maxSubBranches; // how many sub-branches can branch have? | |
float subBrachChance; // chance a stick will have a sub branch growing on it (0-1) | |
} | |
class tree { | |
float tSeed; // seed (0-1) | |
branch[] branches; | |
} | |
class branch { | |
float bSeed; // seed (0-1) | |
float bAngle; // if you want branch to be at an angle | |
stick[] sticks; | |
void init(ref int subLeft, treeStyle style){ // subLeft is how many sub-branches this branch can have. | |
foreach(var stick in sticks){ | |
stick.sAngle = style.stickAngleJagMM.lerp(stick.seed); // Vector2.lerp here is just lerp(v.x, v.y, t); | |
stick.length = style.stickLengthMM.lerp(stick.seed); | |
stick.posOnBranch = sticks.indexOf(stick)/(sticks.length-1); | |
stick.freq = style.springFreqRoot.lerp(stick.posOnBranch); | |
stick.damp = style.springDampRoot.lerp(stick.posOnBranch); | |
stick.mySR.sprite = style.sprites[ style.sprites.length * stick.seed ]; // dont forget to limit this index. | |
// potentially can set other properties of the sprite, like color: | |
// stick.mySR.color = gradient.evaluate(stick.posOnBranch); - to get nice gradient along the branch | |
if(subLeft>0){ | |
subLeft--; | |
stick.subBranch = new branch(); | |
stick.subBranch.init(ref subLeft); // init the branch here, but remember | |
// to pass subLeft so not to run into infinite sub-branches | |
} | |
} | |
} | |
void updateBranch(Vector2 walkPosition, float walkAngle, float gravity, float deltaTime){ | |
// starting calculating branch | |
float mass = 0; | |
foreach(var stick in sticks) | |
stick.update(ref walkPosition, ref walkAngle, ref mass, gravity, deltaTime); | |
} | |
} | |
class stick { | |
float sSeed; // seed (0-1) | |
float posOnBranch; // where on branch it lays (root=0, tip=1) | |
Vector2 sPosition; // world position of this stick | |
Vector2 velocity; // stick velocity last frame | |
float sAngle; // default angle | |
float length; // length, obv | |
float freq, damp; // spring variables | |
renderer mySR; // however youre rendering your stick | |
branch subBranch; // if you want sub-branches, you'd have it here | |
void update(ref Vector2 walkPosition, ref float walkAngle, ref float mass, float gravity, float deltaTime){ | |
mass += length; | |
walkAngle += sAngle; | |
Vector2 stickDir = new Vector2(0,length).rotate(sAngle); | |
Vector2 stickEndPos = walkPosition + stickDir + new Vector2(0, mass*gravity); // where does this stick end? | |
// using Vector2 spring here, like this: http://allenchou.net/2015/04/game-math-numeric-springing-examples/ | |
sPosition = spring( | |
sPosition, // current position | |
stickEndPos, // target position | |
ref velocity, // get and record back velocity of this stick spring | |
damp, // damping | |
freq, // freq | |
deltaTime | |
); | |
// this bit is important to keep sticks never change 'length' | |
Vector2 newDir = sPosition - rootPos; | |
sPosition = rootPos + newDir.normalized * length; // .normalized makes vector be length of 1 | |
walkPosition = sPosition; | |
// update stick's renderer | |
mySR.position = walkPosition; | |
mySR.rotation = walkAngle; // or you can just newDir.angle() or similar | |
if(subBranch!=null){ // stick has sub-branch, lets update it recursively | |
Vector2 subWalkPosition = walkPosition; // new starting position for this branch | |
float subWalkAngle = sAngle + walkAngle + subBranch.bAngle; // and angle | |
subBranch.updateBranch(subWalkPosition, subWalkAngle, gravity, deltaTime); | |
} | |
} | |
} | |
void init( | |
treeStyle style, // contains your tree design | |
float seed // main seed from which every other should be derived from (0-1) | |
){ | |
// skipping init of tree, branches, seeds, arrays, renderer here.. | |
foreach(var branch in tree.branches){ | |
int subLeft = style.maxSubBranches; // how many sub-branches this branch can have? | |
// potentially. could be randomized. | |
branch.bAngle = branchAngleMM.lerp(branch.bSeed); | |
branch.init(ref subLeft, style); | |
} | |
} | |
void update( | |
Vector2 rootPos, // current world position | |
float rootAngle, // current tree angle | |
float gravity, // will be used to pull down the branches | |
float deltaTime // frame duration | |
){ | |
foreach(var branch in tree.branches){ | |
float walkAngle = rootAngle + bAngle; | |
Vector2 walkPosition = rootPos; // this can be offset using branch's seed, | |
// if you want several branches in an area instead of one root position | |
branch.updateBranch(walkPosition, walkAngle, gravity, deltaTime); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment