Wecoc
Pinball Wizard
- Joined
- Dec 7, 2021
- Messages
- 79
- Reaction score
- 122
- Points
- 40
- Favorite Pinball Machine
- Cirqus Voltaire
I have some ideas of things you could do with BAM and I never posted.
Smooth flasher (or any other light), which turns on/off smoothly.
You could also upgrade this to make lights that only turn on "partially" in some cases. I've seen that in some real pinball, for example in Monster Bash. It could even be used for advanced light sequences.

Code:
Class SmoothLight
Public Light, LightExt
Public RampColors(), RampLength
Public LitColor, UnlitColor, CurrentState
Private bTurningOn, bTurningOff, RampIndex, BlinkPatternIndex
Public Function Define(ByVal obj, ByVal r)
' Set Lights and color parameters
Set Light = obj
Set LightExt = Eval(obj.name + "Ext")
LitColor = Light.LitColour
UnlitColor = Light.UnlitColour
RampLength = r
' Set default parameters
CurrentState = BulbOff
bTurningOn = False
bTurningOff = False
RampIndex = 0
BlinkPatternIndex = 0
Redim RampColors(RampLength)
' S_tart, E_nd, D_ifference and C_urrent variables of RBG values
Dim sR, sG, sB, eR, eG, eB, dR, dG, dB, cR, cB, cG
sR = UnlitColor Mod 256
sG = ((UnlitColor - sR) / 256) Mod 256
sB = ((((UnlitColor - sR) / 256) - sG) / 256) Mod 256
eR = LitColor Mod 256
eG = ((LitColor - eR) / 256) Mod 256
eB = ((((LitColor - eR) / 256) - eG) / 256) Mod 256
dR = eR - sR : dG = eG - sG : dB = eB - sB
RampColors(0) = UnlitColor
Dim i : For i = 1 To RampLength
cR = CInt(sR + (dR / RampLength) * i)
cG = CInt(sG + (dG / RampLength) * i)
cB = CInt(sB + (dB / RampLength) * i)
RampColors(i) = RGB(cR, cG, cB)
Next
End Function
Property Get State
State = CurrentState
End Property
Property Let State(ByVal Value)
If (CurrentState = Value) Then Exit Property
CurrentState = Value
BlinkPatternIndex = 1
If (Value > 0) Then
bTurningOn = True
Else
bTurningOff = True
End If
End Property
Public Function ForceState(ByVal Value)
Light.State = Value
If (Value > 0) Then
RampIndex = RampLength
CurrentState = BulbOn
Else
RampIndex = 0
CurrentState = BulbOff
End If
SetLitColorFromIndex()
bTurningOn = False
bTurningOff = False
End Function
Private Function SetLitColorFromIndex()
Dim color, cR, cG, cB
color = RampColors(RampIndex)
cR = color Mod 256
cG = ((color - cR) / 256) Mod 256
cB = ((((color - cR) / 256) - cG) / 256) Mod 256
LightExt.SetLitColor cR, cG, cB
End Function
Private Function AdvanceBlinkPattern()
If (CurrentState = BulbBlink) Then
BlinkPatternIndex = BlinkPatternIndex + 1
If (BlinkPatternIndex > Len(Light.BlinkPattern)) Then
BlinkPatternIndex = 1
End If
If (Mid(Light.BlinkPattern, BlinkPatternIndex, 1) = "1") Then
bTurningOn = True
Else
bTurningOff = True
End If
End If
End Function
Public Function Update()
If (bTurningOn = True) Then
If (RampIndex = RampLength) Then
bTurningOn = False
AdvanceBlinkPattern()
Exit Function
End If
RampIndex = RampIndex + 1
Light.State = BulbOn
SetLitColorFromIndex()
If (RampIndex = RampLength) Then
RampIndex = RampLength
bTurningOn = False
AdvanceBlinkPattern()
End If
Exit Function
End If
If (bTurningOff = True) Then
If (RampIndex = 0) Then
bTurningOff = False
AdvanceBlinkPattern()
Exit Function
End If
RampIndex = RampIndex - 1
Light.State = BulbOn
SetLitColorFromIndex()
If (RampIndex = 0) Then
Light.State = BulbOff
RampIndex = 0
bTurningOff = False
AdvanceBlinkPattern()
End If
Exit Function
End If
End Function
End Class
Dim SmoothFlasher1, SmoothFlasher2
Sub SmoothLightsDemo()
' Set smooth lights
Set SmoothFlasher1 = New SmoothLight
Set SmoothFlasher2 = New SmoothLight
SmoothFlasher1.Define Flasher1, 16
SmoothFlasher2.Define Flasher2, 16
SmoothFlasher1.State = BulbBlink
SmoothFlasher2.State = BulbBlink
Flasher1Ext.Brightness = 2
Flasher2Ext.Brightness = 2
End Sub
Sub SmoothLightTimer_Expired()
SmoothFlasher1.Update()
SmoothFlasher2.Update()
End Sub
You could also upgrade this to make lights that only turn on "partially" in some cases. I've seen that in some real pinball, for example in Monster Bash. It could even be used for advanced light sequences.
A Captive ball hitter would be similar to a Newton ball; something that has a captive ball behind which reacts to it being hit. In this case, though, it would be a target instead.

Code:
Dim CaptiveBall ' Captive balls
Sub CaptiveHitterDemo()
' Create captive balls
CaptiveBallKicker.CreateCaptiveBall
Set CaptiveBall = xBAM.BallCloseTo(CaptiveBallKicker.X, CaptiveBallKicker.Y, 0)
CaptiveBallKicker.SolenoidPulse()
End Sub
' Function to get the arctangent between two numbers
Function Atn2(y, x)
If (x > 0) Then
Atn2 = Atn(y / x)
Exit Function
End If
If (x < 0) And (y >= 0) Then
Atn2 = Atn(y / x) + 3.1415
Exit Function
End If
If (x < 0) And (y < 0) Then
Atn2 = Atn(y / x) - 3.1415
Exit Function
End If
If (x = 0) And (y > 0) Then
Atn2 = 3.1415 / 2
Exit Function
End If
If (x = 0) And (y < 0) Then
Atn2 = -3.1415 / 2
Exit Function
End If
Atn2 = Null
End Function
' Calculate the force returned by a Newton ball
' > ObjAngle - Newton ball's angle
' > ForceR - Force ratio of transmission, from 0.0 to 1.0
' > MinPrec - Minimum required precision, from 0.0 to 1.0
Function GetNewtonBallForce(ObjAngle, ForceR, MinPrec)
Dim x, y, theta, r
' Get the angle of the hit
x = xBAM.Ball.Velocity.X
y = xBAM.Ball.Velocity.Y
theta = (Atn2(x, y) * 360 / (3.1415 * 2))
theta = (theta + 180) Mod 360
theta = (ObjAngle + theta) Mod 360
' Get the force multiplier based on the angle
If (theta > 180) Then r = 360 - theta Else r = theta
r = Abs(1.0 - (theta / 180))
If (r <= MinPrec) Then
GetNewtonBallForce = 0
Exit Function
End If
' Return the force
GetNewtonBallForce = xBAM.Ball.Speed * r * ForceR
End Function
' Newton Ball
Sub CaptiveHitter_Hit()
' If Bam is not defined ignore the effect entirely
If (BAM_VERSION = 0) Then Exit Sub
' Play ball hit sound
Playsound "Bumper1"
' Get the force and the angle in which the ball will recede (polar coordinates)
' The more centered and fast the hit was, the stronger will be the effect
Dim r : r = GetNewtonBallForce(CaptiveHitter.Rotation, 1.0, 0.5) : If (r = 0) Then Exit Sub
Dim theta : theta = ((180 - CaptiveHitter.Rotation) * (3.1415 * 2) / 360)
' Convert to cartesian coordinates
CaptiveBall.SetVelocity r * Cos(theta), r * Sin(theta)
End Sub
A target either with a horizontal pole and string behind, or alternatively, a leaf target that can recede, with a drop target orn hole. I don't have a code for this one, but it may probably be done with an edit of the Bullseye target, but with an appearance similar to a Vari target.
(Yes, I drew the spring directly on the screenshot, ain't doing extra work for this one
)
The idea is simple, the stronger you hit it, the harder it pushes the ball back. Another version of this could include a kicker hole that could only be accessed if the string is pushed to its end. Even though it's a basic idea, applying the appropriate forces may be challenging.

(Yes, I drew the spring directly on the screenshot, ain't doing extra work for this one

The idea is simple, the stronger you hit it, the harder it pushes the ball back. Another version of this could include a kicker hole that could only be accessed if the string is pushed to its end. Even though it's a basic idea, applying the appropriate forces may be challenging.
A spinning disk with leaf targets (and maybe a bulb for each target) attached around, so they also spin.
Even though I made a version of extended spinning disks with BAM, this mechanism would probably require a rotating Mini-playfield.
Even though I made a version of extended spinning disks with BAM, this mechanism would probably require a rotating Mini-playfield.
The Wide EM Kicker (I don't know its name) from The Shadow Pinball could be achieved with BAM with a Mini-playfield that moves horizontally with the flippers. The mechanism reminds me of the Zipper Flippers, which may be used as a basis.