Creative Computer Programming: Lucifer Projects
My creative writing practice, which I mentioned in my artist's statement, involves a Heaven and Hell paradigm, somewhat inspired by Catholic iconography, but more taking a Dantean Divine Comedy approach. Since my practice has become almost solely merged with the work of my collaborator, we take different roles. She takes Heaven and I take Hell, and we meet in the middle for limbo and purgatory.
Many of my character designs, which will be featured later, are demon-esque in this way. I prefer the name Lucifer for the king of Hell as opposed to Satan mostly for aesthetic purposes. I created my design for Lucifer first a couple years ago:
I am not proficient in hand, from-scratch animation. As such, I use my coding skills to animate my drawings. I started with "Lucifer and the Demolition Man", a fusion of my own interpretation of Lucifer and My Chemical Romance's Three Cheers Demolition Man.
The basic story of the Three Cheers album is a man who makes a deal with the dark lord after death to be reunited with his (still living) wife, and is given the task to kill one thousand evil men. It is often surmised in fan theories that "I Never Told You What I Do for a Living", the final song on the album, implies that the Demolition Man's final evil man to kill is himself.
In the painting below, watercolor on canvas, the Demolition Man is on his knees in a cathedral, Lucifer's presence to reap his soul deeming the surroundings icy (as is the ninth circle of hell).
I decided to take bits of the flying feathers in the painting and animate them to create the appearance that they were swirling around, the wind at Lucifer's back. I first programmed it in Processing, but translated it into Visual Basic for the increased functionality and less drag. I believe the VB code is much easier to understand as well. Similar to the Ong screensaver, this utilizes a WinForms app build and use of trigonometric functions to create gentle, oscillating movement.
Public Class Form1
Private featherSpeed() As Single
Private featherLeftXPos() As Single
Private featherLeftYPos() As Single
Private featherRightXPos() As Single
Private featherRightYPos() As Single
Private featherTopXPos1() As Single
Private featherTopYPos1() As Single
Private featherTopXPos2() As Single
Private featherTopYPos2() As Single
Private diameter As Single = 24
Private curveSlowerDownerSide() As Single
Private curveSlowerDownerTop1() As Single
Private curveSlowerDownerTop2() As Single
Private frameCount As Single = 60
Private feather() As Image
Private featherWhite() As Image
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Timer1.Enabled = True
Timer1.Interval = 33
Timer1.Start()
ReDim feather(74)
ReDim featherWhite(49)
ReDim featherSpeed(74)
ReDim featherLeftXPos(74)
ReDim featherLeftYPos(74)
ReDim featherRightXPos(74)
ReDim featherRightYPos(74)
ReDim featherTopXPos1(49)
ReDim featherTopYPos1(49)
ReDim featherTopXPos2(49)
ReDim featherTopYPos2(49)
ReDim curveSlowerDownerSide(74)
ReDim curveSlowerDownerTop1(49)
ReDim curveSlowerDownerTop2(49)
For n = 0 To 74
featherLeftXPos(n) = 350
featherLeftYPos(n) = 743 * Rnd() + 777
featherRightXPos(n) = 1050
featherRightYPos(n) = 743 * Rnd() + 777
featherSpeed(n) = 2 * Rnd() - 2
curveSlowerDownerSide(n) = 51 * Rnd() + 25
feather(n) = Bitmap.FromFile("C:\Users\genev\Pictures\arts\stickers\feather small.png")
Next
For n = 0 To 49
featherTopXPos1(n) = 845
featherTopYPos1(n) = 615
featherTopXPos2(n) = 595
featherTopYPos2(n) = 630
featherSpeed(n) = 2 * Rnd() - 2
curveSlowerDownerTop1(n) = 10
curveSlowerDownerTop2(n) = 15
featherWhite(n) = Bitmap.FromFile("C:\Users\genev\Pictures\arts\stickers\feather small white.png")
Next
End Sub
Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
Label1.Invalidate()
End Sub
Private Sub Label1_Paint(sender As Object, e As PaintEventArgs) Handles Label1.Paint
frameCount += 1
Dim gr0 = e.Graphics
For n = 0 To 74
featherLeftXPos(n) = featherLeftXPos(n) + featherSpeed(n)
featherLeftYPos(n) = featherLeftYPos(n) + Math.Cos(frameCount / curveSlowerDownerSide(n))
featherRightXPos(n) = featherRightXPos(n) - featherSpeed(n)
featherRightYPos(n) = featherRightYPos(n) + Math.Cos((frameCount) / curveSlowerDownerSide(n))
If featherLeftXPos(n) < 0 Then
featherLeftXPos(n) = 350
End If
If featherRightXPos(n) > 1417 Then
featherRightXPos(n) = 1050
End If
gr0.DrawImage(feather(n), featherLeftXPos(n), featherLeftYPos(n), diameter, diameter)
gr0.DrawImage(feather(n), featherRightXPos(n), featherRightYPos(n), diameter, diameter)
Next
For n = 0 To 49
featherTopXPos1(n) = featherTopXPos1(n) + featherSpeed(n)
featherTopYPos1(n) = featherTopYPos1(n) + Math.Cos(frameCount / curveSlowerDownerTop1(n))
featherTopXPos2(n) = featherTopXPos2(n) - featherSpeed(n)
featherTopYPos2(n) = featherTopYPos2(n) + Math.Cos(frameCount / curveSlowerDownerTop2(n))
If featherTopXPos1(n) < 583 Then
featherTopXPos1(n) = 845
End If
If featherTopXPos2(n) > 833 Then
featherTopXPos2(n) = 595
End If
gr0.DrawImage(featherWhite(n), featherTopXPos1(n), featherTopYPos1(n), diameter, diameter)
gr0.DrawImage(featherWhite(n), featherTopXPos2(n), featherTopYPos2(n), diameter, diameter)
Next
End Sub
Private Sub Label1_DoubleClick(sender As Object, e As EventArgs) Handles Label1.DoubleClick
Me.Close()
End Sub
End Class
_______________________________
My most recent Lucifer animation, Lucifer and the Earth, utilizes similar functions in a different environment. I imagine his scepter head as detachable and expandable, this earth in the form of a shiny marble. Here is the still image I illustrated on Krita:
And, here is the animated program and code (VB):
Public Class Form1
Private luciferAndEarth As Image
Private earth1 As Image
Private earth2 As Image
Private earth3 As Image
Private bubbleLight() As Image
Private bubbleMedium() As Image
Private bubbleDark() As Image
Private bubbleLightSpeed() As Single
Private bubbleMediumSpeed() As Single
Private bubbleDarkSpeed() As Single
Private bubbleLightXPos() As Single
Private bubbleMediumXPos() As Single
Private bubbleDarkXPos() As Single
Private bubbleLightYPos() As Single
Private bubbleMediumYPos() As Single
Private bubbleDarkYPos() As Single
Private earthXPos1 As Single
Private earthYPos1 As Single
Private earthXPos2 As Single
Private earthYPos2 As Single
Private earthXPos3 As Single
Private earthYPos3 As Single
Private earthSpeed1 = 0.025
Private earthSpeed2 = -0.025
Private earthSpeed3 = 0.02
Private curveSlowerDowner() As Single
Private frameCount = 60
Private constant = 51 * Rnd() + 50
Private angle1 = 0.05
Private angle2 = 0.06
Private angle3 = 0.07
Private scalar = 51 * Rnd() + 50
Private flickerEarth1 As Boolean
Private flickerEarth2 As Boolean
Private flickerEarth3 As Boolean
Private earth1Translucent As Image
Private earth2Translucent As Image
Private earth3Translucent As Image
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Timer1.Enabled = True
Timer1.Interval = 33
Timer1.Start()
Timer2.Enabled = True
Timer3.Enabled = True
Timer4.Enabled = True
Timer2.Interval = 100
Timer3.Interval = 150
Timer4.Interval = 200
Timer2.Start()
Timer3.Start()
Timer4.Start()
ReDim bubbleLight(49)
ReDim bubbleMedium(49)
ReDim bubbleDark(49)
ReDim bubbleLightSpeed(49)
ReDim bubbleMediumSpeed(49)
ReDim bubbleDarkSpeed(49)
ReDim bubbleLightXPos(49)
ReDim bubbleMediumXPos(49)
ReDim bubbleDarkXPos(49)
ReDim bubbleLightYPos(49)
ReDim bubbleMediumYPos(49)
ReDim bubbleDarkYPos(49)
ReDim curveSlowerDowner(49)
luciferAndEarth = Bitmap.FromFile("C:\Users\genev\Pictures\arts\lucifer and the earth smaller.png")
For n = 0 To 49
bubbleLightXPos(n) = Rnd() * 1000
bubbleLightYPos(n) = 1005
bubbleLightSpeed(n) = 3 * Rnd() + 2
curveSlowerDowner(n) = (51 * Rnd() + 25)
bubbleLight(n) = Bitmap.FromFile("C:\Users\genev\Pictures\arts\lucifer bubble bright.png")
Next
For v = 0 To 49
bubbleMediumXPos(v) = Rnd() * 1000
bubbleMediumYPos(v) = 1005
bubbleMediumSpeed(v) = 3 * Rnd() + 2
curveSlowerDowner(v) = (51 * Rnd() + 25)
bubbleMedium(v) = Bitmap.FromFile("C:\Users\genev\Pictures\arts\lucifer bubble medium.png")
Next
For k = 0 To 49
bubbleDarkXPos(k) = Rnd() * 1000
bubbleDarkYPos(k) = 1005
bubbleDarkSpeed(k) = 3 * Rnd() + 2
curveSlowerDowner(k) = (51 * Rnd() + 25)
bubbleDark(k) = Bitmap.FromFile("C:\Users\genev\Pictures\arts\lucifer bubble dark.png")
Next
earthXPos1 = 366 * Rnd() + 85
earthYPos1 = 371 * Rnd() + 80
earthXPos2 = 366 * Rnd() + 85
earthYPos2 = 371 * Rnd() + 80
earthXPos3 = 366 * Rnd() + 85
earthYPos3 = 371 * Rnd() + 80
earth1 = Bitmap.FromFile("C:\Users\genev\Pictures\arts\earth.png")
earth2 = Bitmap.FromFile("C:\Users\genev\Pictures\arts\earth.png")
earth3 = Bitmap.FromFile("C:\Users\genev\Pictures\arts\earth.png")
earth1Translucent = Bitmap.FromFile("C:\Users\genev\Pictures\arts\earth translucent.png")
earth2Translucent = Bitmap.FromFile("C:\Users\genev\Pictures\arts\earth translucent.png")
earth3Translucent = Bitmap.FromFile("C:\Users\genev\Pictures\arts\earth translucent.png")
End Sub
Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
Label1.Invalidate()
End Sub
Private Sub Timer2_Tick(sender As Object, e As EventArgs) Handles Timer2.Tick
Label1.Invalidate()
flickerEarth1 = Not flickerEarth1
End Sub
Private Sub Timer3_Tick(sender As Object, e As EventArgs) Handles Timer3.Tick
Label1.Invalidate()
flickerEarth2 = Not flickerEarth2
End Sub
Private Sub Timer4_Tick(sender As Object, e As EventArgs) Handles Timer4.Tick
Label1.Invalidate()
flickerEarth3 = Not flickerEarth3
End Sub
Private Sub Label1_Paint(sender As Object, e As PaintEventArgs) Handles Label1.Paint
frameCount += 1
Dim gr0 = e.Graphics
gr0.DrawImage(luciferAndEarth, 0, 0, 1000, 1000)
For n = 0 To 49
bubbleLightXPos(n) = bubbleLightXPos(n) + Math.Sin(frameCount / curveSlowerDowner(n))
bubbleLightYPos(n) = bubbleLightYPos(n) - bubbleLightSpeed(n)
If bubbleLightYPos(n) < -5 Then
bubbleLightYPos(n) = 1005
End If
gr0.DrawImage(bubbleLight(n), bubbleLightXPos(n), bubbleLightYPos(n), 5, 5)
Next
For v = 0 To 49
bubbleMediumXPos(v) = bubbleMediumXPos(v) + Math.Sin(frameCount / curveSlowerDowner(v))
bubbleMediumYPos(v) = bubbleMediumYPos(v) - bubbleMediumSpeed(v)
If bubbleMediumYPos(v) < -5 Then
bubbleMediumYPos(v) = 1005
End If
gr0.DrawImage(bubbleMedium(v), bubbleMediumXPos(v), bubbleMediumYPos(v), 8, 8)
Next
For k = 0 To 49
bubbleDarkXPos(k) = bubbleDarkXPos(k) + Math.Sin(frameCount / curveSlowerDowner(k))
bubbleDarkYPos(k) = bubbleDarkYPos(k) - bubbleDarkSpeed(k)
If bubbleDarkYPos(k) < -5 Then
bubbleDarkYPos(k) = 1005
End If
gr0.DrawImage(bubbleDark(k), bubbleDarkXPos(k), bubbleDarkYPos(k), 9, 9)
Next
angle1 = angle1 + earthSpeed1
earthXPos1 = constant + Math.Sin(angle1) * scalar
earthYPos1 = constant + Math.Cos(angle1) * scalar
If flickerEarth1 = True Then
gr0.DrawImage(earth1, earthXPos1, earthYPos1, 342, 337)
Else
gr0.DrawImage(earth1Translucent, earthXPos1, earthYPos1, 342, 337)
End If
angle2 = angle2 + earthSpeed2
earthXPos2 = constant + Math.Sin(angle2) * scalar
earthYPos2 = constant + Math.Cos(angle2) * scalar
If flickerEarth2 = True Then
gr0.DrawImage(earth2, earthXPos2, earthYPos2, 342, 337)
Else
gr0.DrawImage(earth2Translucent, earthXPos2, earthYPos2, 342, 337)
End If
angle3 = angle3 + earthSpeed3
earthXPos3 = constant + Math.Sin(angle3) * scalar
earthYPos3 = constant + Math.Cos(angle3) * scalar
If flickerEarth3 = True Then
gr0.DrawImage(earth3, earthXPos3, earthYPos3, 342, 337)
Else
gr0.DrawImage(earth3Translucent, earthXPos3, earthYPos3, 342, 337)
End If
End Sub
Private Sub Label1_DoubleClick(sender As Object, e As EventArgs) Handles Label1.DoubleClick
Me.Close()
End Sub
End Class




