Created
February 20, 2023 18:54
-
-
Save pragdave/b07540972910e09b1fc959ab953305a7 to your computer and use it in GitHub Desktop.
Looking for feedback on my first Motion Canvas attempt
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
import {makeScene2D} from '@motion-canvas/2d/lib/scenes'; | |
import {Rect, View2D} from '@motion-canvas/2d/lib/components'; | |
import {createRef, Reference} from '@motion-canvas/core/lib/utils'; | |
import { Color, Vector2 } from '@motion-canvas/core/lib/types'; | |
const PoleLong = 201 | |
const PoleShort = 25 | |
const PoleBase = 150 | |
const DiskCount = 5 | |
const MinDiskWidth = 50 | |
const MaxDiskWidth = PoleLong - 20 | |
const DeltaWidth = (MaxDiskWidth - MinDiskWidth)/(DiskCount - 1) | |
const DiskHeight = 30 | |
const DiskGap = 4 | |
const BaseDiskColor = new Color("#c3e") | |
const EndDiskColor = new Color("#baf") | |
const VMoveTime = 0.5 | |
const HMoveTime = 1 | |
// ╭──────────────────────────────────────────────────────────╮ | |
// │ Each disk │ | |
// ╰──────────────────────────────────────────────────────────╯ | |
class Disk { | |
me: Reference<Rect>; | |
constructor(view: View2D, i: number) { | |
const width = MaxDiskWidth - i*DeltaWidth | |
const color = BaseDiskColor.lerp(EndDiskColor, i/(DiskCount-1)).name() | |
this.me = createRef<Rect>() | |
view.add(<Rect ref={this.me} width={width} height={DiskHeight} fill={color} x={0} y={0} />) | |
} | |
position(pos: Vector2) { | |
this.me().position(pos) | |
} | |
*moveUpDownTo(absY: number) { | |
return yield * this.me().position.y(absY, VMoveTime) | |
} | |
*moveAcrossTo(absX: number) { | |
return yield * this.me().position.x(absX, HMoveTime) | |
} | |
static heightOfStack(n: number) { | |
return (DiskHeight + DiskGap) * n | |
} | |
} | |
// ╭──────────────────────────────────────────────────────────╮ | |
// │ A Pole │ | |
// ╰──────────────────────────────────────────────────────────╯ | |
class Pole { | |
_base: Vector2 | |
disks: Disk[] = [] | |
constructor(view: View2D, public xpos: number) { | |
view.add([ | |
<Rect width={PoleLong} height={PoleShort} x={xpos} y={PoleBase+PoleShort/2} fill="brown" />, | |
<Rect width={PoleShort} height={PoleLong} x={xpos} y={PoleBase-PoleLong/2} fill="green" />, | |
]) | |
this._base = new Vector2(xpos, PoleBase) | |
} | |
push(disk: Disk) { | |
this.disks.push(disk) | |
// return the position of the newly pushed disk | |
return Disk.heightOfStack(this.disks.length) - DiskHeight/2 | |
} | |
pop() { | |
return this.disks.pop() | |
} | |
pushAndPosition(disk: Disk) { | |
const offset = this.push(disk) | |
disk.position(new Vector2([this.xpos, PoleBase - offset])) | |
} | |
} | |
// ╭──────────────────────────────────────────────────────────╮ | |
// │ Animate moving a disk from `from` to `to` │ | |
// ╰──────────────────────────────────────────────────────────╯ | |
function *moveFromTo(from: Pole, to: Pole) { | |
const disk = from.pop() | |
yield * disk.moveUpDownTo(-200) | |
yield * disk.moveAcrossTo(to.xpos) | |
const pos = to.push(disk) | |
yield * disk.moveUpDownTo(PoleBase - pos) | |
} | |
// ╭──────────────────────────────────────────────────────────╮ | |
// │ Keep dem monks busy │ | |
// ╰──────────────────────────────────────────────────────────╯ | |
function *hanoi(n: number, from: Pole, to: Pole, using: Pole): Generator<any> { | |
if (n > 0) { | |
yield * hanoi(n-1, from, using, to) | |
yield * moveFromTo(from, to) | |
yield * hanoi(n-1, using, to, from) | |
} | |
} | |
export default makeScene2D(function* (view) { | |
// drawGrid(view) | |
const Poles = [ | |
new Pole(view, -300), | |
new Pole(view, 0), | |
new Pole(view, +300) | |
] | |
for (let i = 0; i < DiskCount; i++) { | |
const d = new Disk(view, i) | |
Poles[0].pushAndPosition(d) | |
} | |
yield * hanoi(DiskCount, Poles[0], Poles[1], Poles[2]) | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment