Created
April 16, 2015 10:12
-
-
Save KeyMaster-/9d6898d686c24f6f5f62 to your computer and use it in GitHub Desktop.
Code sample for doing wave spring physics
This file contains 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
//Note: This does _not_ compile, it's just to demonstrate the relevant physics bits | |
class Main extends luxe.Game { | |
var fieldWidth:Int = 60; | |
var fieldDepth:Int = 60; | |
var physTimeStep:Float = 1 / 60; | |
var physTimeCounter:Float = 0; | |
var springK:Float = 100; | |
var springDampening:Float = 0.00; | |
var springSpread:Float = 600; | |
var startHeight:Float = -1500; | |
var heightTintRange:Float = 10; | |
var physStepCounter:Int = 0; | |
var maxPhysSteps:Int = 20; | |
var fieldVertices:Array<Vertex>; | |
var springVelocities:Array<Float>; | |
override function update(dt:Float) { | |
if (dt > 1) { | |
return; | |
} | |
physTimeCounter += dt; | |
physStepCounter = 0; | |
while (physTimeCounter >= physTimeStep && physStepCounter < maxPhysSteps) { | |
updateSprings(physTimeStep); | |
physTimeCounter -= physTimeStep; | |
physStepCounter++; | |
} | |
} //update | |
function updateSprings(dt:Float):Void { | |
for (x in 0...fieldWidth) { | |
for (y in 0...fieldDepth) { | |
runHooke(x, y, dt); | |
} | |
} | |
var avgHeight:Float = 0; | |
var heightDiff:Float = 0; | |
for (x in 0...fieldWidth) { | |
for (y in 0...fieldDepth) { | |
avgHeight = getNeighborAverage(x, y); | |
heightDiff = fieldVertices[x * fieldWidth + y].pos.z - avgHeight; | |
springVelocities[x * fieldWidth + y] += -springSpread * heightDiff * dt; //Effectively another hooke's law, springSpread is k | |
//springVelocities[x * fieldWidth + y] -= springDampening * springVelocities[x * fieldWidth + y]; | |
} | |
} | |
} | |
function runHooke(x:Int, y:Int, dt:Float):Void { | |
//0 represents rest height | |
springVelocities[x * fieldWidth + y] += -springK * (fieldVertices[x * fieldWidth + y].pos.z - 0) * dt; | |
springVelocities[x * fieldWidth + y] -= springDampening * springVelocities[x * fieldWidth + y]; | |
fieldVertices[x * fieldWidth + y].pos.z += springVelocities[x * fieldWidth + y] * dt; | |
} | |
function getNeighborAverage(x:Int, y:Int):Float { | |
var sum:Float = 0; | |
var springCounter:Int = 0; | |
var xStart:Int = x - 1; | |
var xEnd:Int = x + 1; | |
var yStart:Int = y - 1; | |
var yEnd:Int = y + 1; | |
if (xStart < 0) { | |
xStart = 0; | |
} | |
if (xEnd > fieldWidth - 1) { | |
xEnd = fieldWidth - 1; | |
} | |
if (yStart < 0) { | |
yStart = 0; | |
} | |
if (yEnd > fieldDepth - 1) { | |
yEnd = fieldDepth - 1; | |
} | |
var springCounter:Int = 0; | |
for (_x in xStart...xEnd + 1) { | |
for (_y in yStart...yEnd + 1) { | |
if (!(_x == x && _y == y)) { | |
if ((_x == xStart || _x == xEnd) && (_y == yStart || _y == yEnd)) { | |
sum += fieldVertices[_x * fieldWidth + _y].pos.z * 0.7071067811865475;// 1 / sqrt(2), adjusting distance to neighbour by dividing by sart(1^2 + 1^@) | |
} | |
else { | |
sum += fieldVertices[_x * fieldWidth + _y].pos.z; | |
} | |
springCounter++; | |
} | |
} | |
} | |
if (springCounter != 0) { | |
sum /= springCounter; | |
} | |
return sum; | |
} | |
} //Main |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment