Made a “beating heart” pattern based on drawing a heart as the combination of a 45 degree tilted square and two semi-circles. Added simple anti-aliasing based on some tricks I’ve seen posted here. I’m happy with how it looks at higher resolution, though it’s definitely tricky to make defined shapes look good at lower resolution.
// Ratio of the height of the heart to the length of one side of the diamond inside it
// length of one side of the diamond is also the radius of the circle
var ratio = (0.5 + 3*sqrt(2)/4)
// Precompute
var sqr2_2 = sqrt(2)/2
export var delta = 0.06 // Max antialiasing distance
export var height = 0.8 // Height of heart in world units
export var xpos = 0.5 // x position of the point of the heart
export var ypos = (1-height)/2
export var L = height/ratio
export var Lv = L*sqr2_2
export function beforeRender(delta) {
t1 = time(.02)
t2 = time(.035)
t3 = time(.057)
height = 0.4 + 0.4*sin(t1*PI)
L = height/ratio
Lv = L*sqr2_2
ypos = 0.4 + height/2 + 0.15*wave(t3) // Position of the heart's "tip"
xpos = 0.3 + 0.2*wave(t2) + 0.2*wave(t3)
}
// The position of the bottom heart point is (x0,y0)
// Heart height and x0, y0 are given in world units
export function drawHeart(x, y, x0, y0, height) {
v = 0
h = 0.5
xn = abs(x - x0) // Take advantage of symmetry - only compute half of heart
yn = y0 - y // Remove y offset of heart for computations
if (yn < Lv) { // Straight portion of heart
if (xn < yn) { // Inside straight portion
v = 1
} else { // Check to see if we are close enough for anti aliasing
d = (xn - yn)*sqr2_2 // Perpendicular distance to line x = y (makes a (90,45,45) triangle)
if (d < delta) { // Inside anti-aliasing distance
h = 0
v = 1-d/delta
}
}
} else { // Inside the curved portion of the heart
xc = Lv/2 // (xc,yc) are coordinates of the center of the circular part of the heart
yc = 3*Lv/2
yd = abs(yn - yc) // Vertical distance from center of the circle
if (yn < 2*Lv) { // This portion of the heart is below the inverted point
if (xn < Lv/2 + sqrt(L*L/4 - yd*yd)) {
v = 1
}
} else { // This portion of the heart is above the inverted point
xd = abs(xn - xc) // Horizontal distance to center of the circular part of the heart
if (xd < sqrt(L*L/4 - yd*yd)) {
v = 1
}
}
// Anti alias the curved part of the heart
if (v == 0) {
d = hypot(xn - xc, yn - yc) - L/2
if (d < delta) {
v = 1-d/delta
h = 0
}
}
}
hsv(y/2+t1,1,v*v)
}
export function render2D(index, x, y) {
drawHeart(x,y,xpos, ypos,height)
}