Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
5439a19
mech: initial work on ScoreMotorComponent
jsm174 Aug 14, 2022
28ef484
misc: rework score motor into score reel display. issue #421
jsm174 Aug 21, 2022
f70fad7
displays: added display type and add score functionality
jsm174 Aug 23, 2022
038d97c
displays: implement score motor
jsm174 Aug 25, 2022
d7d4b28
misc: code cleanup. Add support for score motor block points.
jsm174 Aug 25, 2022
08101cd
misc: add single points log message
jsm174 Aug 25, 2022
0dfda60
misc: move score motor back to separate component
jsm174 Aug 26, 2022
c97a594
misc: move score motor cleanup. add display reset support
jsm174 Aug 26, 2022
55d6ded
misc: move score from score reel to score motor
jsm174 Aug 27, 2022
96a5b16
misc: cleanup order of display attachment.
jsm174 Aug 27, 2022
cda71e6
misc: remove extra score truncation
jsm174 Aug 27, 2022
5d8031a
misc: revert removal of score reel display from icons
jsm174 Aug 27, 2022
5be75d1
misc: remove DisplayAddPoints in favor of using UpdateFrame
jsm174 Aug 28, 2022
9146610
misc: rename DisplayScoreEvent to DisplayUpdateEvent. More cleanup.
jsm174 Aug 28, 2022
53e4fd5
misc: add alphanumeric support to DisplayUpdateEvent. Add DisplayUpda…
jsm174 Aug 28, 2022
aabed91
misc: more cleanup
jsm174 Aug 28, 2022
e61d57a
misc: address code review comments.
jsm174 Aug 30, 2022
9c6ccd0
misc: rename ScoreMotorActions to ScoreMotorTiming
jsm174 Aug 30, 2022
a5a9a9c
cleanup: move most logic from score motor api to component
jsm174 Aug 30, 2022
0ca9e46
misc: remove display player from Displays. Replace DisplayUpdateEvent…
jsm174 Aug 30, 2022
2afa893
misc: simplify increase calculation
jsm174 Aug 30, 2022
5eaf19d
fix: Use math instead of switches.
freezy Aug 30, 2022
eb37ee4
reel: Better math.
freezy Aug 30, 2022
96923e2
fix: Refactor reel component to take frame skips into consideration.
freezy Sep 1, 2022
8a17568
fix: More reel component refactoring to support both rotation directi…
freezy Sep 1, 2022
8ad2340
fix: Reel direction should now work properly.
freezy Sep 1, 2022
dee1040
misc: optimize score reel display update frame
jsm174 Sep 2, 2022
29d76dc
docs: stub score motor mechanism page
jsm174 Sep 2, 2022
e320ae2
chore: Clean up debug prints.
freezy Sep 2, 2022
70501eb
refactor: Rename SetDisplay to DisplayChanged
freezy Sep 2, 2022
5aa57ee
refactor: More renaming.
freezy Sep 2, 2022
c3b8889
chore: Minor renamings.
freezy Sep 2, 2022
eeb736a
docs: add score motor and uvs display documentation
jsm174 Sep 5, 2022
6ddc987
misc: fix score motor help url
jsm174 Sep 5, 2022
a1c7663
doc: Clean up score motor schema.
freezy Sep 10, 2022
6be3848
misc: remove degrees to simplify score motor config
jsm174 Sep 11, 2022
bda5c75
Update score-motors.md
Scottacus64 Sep 12, 2022
143b033
misc: updated images to match @Scottacus64 doc updates
jsm174 Sep 12, 2022
bf8c01c
doc: Update score motor doc.
freezy Sep 13, 2022
1d49601
doc: Minor tweaks.
freezy Sep 13, 2022
3114960
doc: Add page about score reels.
freezy Sep 13, 2022
748854f
reels: Properly name components.
freezy Sep 13, 2022
47cee16
reels: Add inspector for the reel component.
freezy Sep 13, 2022
42522a6
doc: Update score reel and score motor doc.
freezy Sep 13, 2022
d82e3df
doc: Add missing link.
freezy Sep 14, 2022
9bf3b11
doc: Spelling.
freezy Sep 14, 2022
d4a5b26
doc: More minor fixes.
freezy Sep 14, 2022
b8a7539
doc: Update CHANGELOG.
freezy Sep 14, 2022
40a4681
doc: Swap score motor shot.
freezy Sep 14, 2022
3e23783
doc: More clarification in the score motors doc.
freezy Sep 14, 2022
ecc5e84
doc: Comma and formatting.
freezy Sep 14, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
Built with Unity 2021.3.0

### Added
- Documentation for score reels.
- Score Motor Component ([#435](https://github.com/freezy/VisualPinball.Engine/pull/435), [Documentation](https://docs.visualpinball.org/creators-guide/manual/mechanisms/score-motors.html)).
- Scale support for rubbers.
- Slingarm coil arms can now be any game objects, not just primitives ([#432](https://github.com/freezy/VisualPinball.Engine/pull/432)).
- Gate Lifter Component ([#418](https://github.com/freezy/VisualPinball.Engine/pull/418), [Documentation](https://docs.visualpinball.org/creators-guide/manual/mechanisms/lifting-gates.html)).
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
---
gui: displays
uid: displays
title: Displays
description: How VPE handles dot matrix and segment displays.
---
# Displays
Expand All @@ -24,12 +25,10 @@ For example, in [MPF](xref:mpf_index) you name your displays yourself in the mac

<img src="display-add-component.png" width="243" alt="Add display component" class="img-responsive pull-right" style="margin-left: 15px"/>

VPE provides two display components, one for segment displays and one for DMDs. Both components create the underlying geometry and apply a shader that renders the content of the display. In order to create one, make an empty game object in your scene and add the desired component under *Visual Pinball -> Display*.
VPE provides three display components, a [score reel](xref:score-reels), a segment display and a DMD. Both the segment display and the DMD component create the underlying geometry and apply a shader that renders the content of the display. In order to create one, make an empty game object in your scene and add the desired component under *Visual Pinball -> Display*.

You can also create the game object with a component already assigned by right-clicking in the hierarchy and choosing *Visual Pinball -> Dot Matrix Display*. This will place the display into your scene right behind your playfield.

Since score reels come with additional geometry and textures, VPE provides them as prefabs through the asset library.

<img src="display-dmd-inspector.png" width="354" alt="DMD Inspector" class="img-responsive pull-right" style="margin-left: 15px"/>

Selecting the game object will let you customize it in the inspector, and assign the ID that links it to the gamelogic engine.
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
---
uid: score-motors
title: Score Motors
description: Simulate EM reel timing during gameplay
---

# Score Motors

Score motors are used in electro-mechanical games to add points to a player's score. They consist of multiple cams that are stacked on top of each other. Each cam has different patterns around the edges, and switches sit at different positions in order to open or close at specific times when the motor runs and thus the cams rotate.

![Photo and schema of a score motor](score-motor-schema.jpg)
<small>*A typical score motor, found in Gottlieb and early Bally machines.*</small>

The score motor assembly sits typically at the bottom of the cabinet. The produced switch sequences are used when the game needs to do several things in a specific order. Although its main purpose is triggering the score reel relays, it is often used to drive other mechanisms as well.

## Scoring in an EM

There are two different modes of operation:

1. The player scores **single points**, e.g. one, ten, hundred, and so on. In this case, a pulse is directly sent to the coil driving the corresponding score wheel, which increases its position by one.
2. The player scores **multiple points**, like five, twenty, or 300. In this case, the score motor starts and the appropriate numbers of coil pulses are triggered by the switches around cams. For example, if a player scores fifty points, the score motor runs and enables the ten point relay to pulse five times. With each pulse of the ten point relay, the 10's score reel coil fires, which advances the score reel one position.

Another property of a score motor is that it has no state, i.e. it doesn't know the actual score. This means that while the motor is running and the player scores *multiple* points, they are ignored. For *single* points, it depends on the machine, some allow single-point scoring while the motor is running, some don't.

> [!NOTE]
> For an in-depth look at score motors, check out the fantastic article [Animated Score Motor circuits from EM Pinball Machines](https://www.funwithpinball.com/learn/animated-score-motor-circuits) at [Fun With Pinball](https://www.funwithpinball.com/).

## Player Experience

The way the scoring works results in a very particular timing of when exactly the score reels move during the game. Since in most games, chimes and bells are fired when the reel position changes, the player not only sees, but also hears these patterns. This means that accurate timing is essential for an authentic gaming experience.

# Setup

VPE provides a component that accurately simulates the behavior described above. It handles score resets and add points, all while performing accurate timing that can be specified by the table author.

To setup a score motor, select any game object, click on *Add Component* in the inspector and select *Visual Pinball -> Mechs -> Score Motor*.

Next, configure the score motor. The inspector shows the following options:

<img src="score-motor-inspector.png" width="363" class="img-responsive pull-right" style="margin-left: 15px">

- **Steps** defines how many steps the score motor pulses for one turn.
- **Duration** defines the length of time it takes the score motor to completely cycle.
- **Block Scoring** defines if single point scoring is blocked **while the score motor is running**. As mentioned before, multiple point scores are always blocked while the score motor is running.
- **Increase by #** defines the behavior of the score motor for all of its the possible outputs. This gives the table author control over the timing and execution of `Wait` (pause) or `Increase` (add points) actions. The example in the screenshot shows a motor where when the player scores 30 points, it pulses on the first three actions of the score motor.

> [!NOTE]
> The minimum amount of `Steps` for a score motor is `5`. `Increase by 5` will not be shown under `Reel timing by increase` if `Steps` is set to 5, as all actions would be `Increase`.

<img src="score-motor-gottlieb.png" width="335" class="img-responsive pull-right" style="margin-left: 15px">

By default, the score motor is configured to:

- 6 Steps
- 769 ms total run time

Next, associate the score motor with the [score reel display](xref:score-reels) by selecting it in [its inspector](xref:score-reels#score-reel-display).

# Usage

Score motors are primarily used in EMs, so we'll focus on how to use them in [Visual Scripting](xref:uvs_index). Programming a game with a score motor is a bit more complicated than with traditional displays for one reason: Scores might get blocked due to the motor being active, so you cannot solely rely on a score variable being updated.

To make this less cumbersome, we've added an [On Display Changed](xref:uvs_node_reference#on-display-changed) node that emits the actual value of the display when it has been updated (after potentially blocking scores).

Give you've already set up your [score reel display](xref:score-reels), the recommended approach is the following:

1. Add an *Add Score* [event](xref:uvs_setup#events) in the Visual Scripting GLE's inspector.
<img src="score-motor-score-event.png" width="357">
2. Add a *Score* [player variable](xref:uvs_variables#setup) in the same inspector.
<img src="score-motor-score-variable.png" width="357">
3. In your graph, whenever you do scoring, use a [Trigger Pinball Event](xref:uvs_node_reference#trigger-pinball-event) node and set the *Add Score* event to be emitted.
![Score Event](score-motor-uvs-score-event.png)
4. In your graph, at a centralized location, create an [On Pinball Event](xref:uvs_node_reference#on-pinball-event) node, select the *Add Score* event, and link it to an [Update Display](xref:uvs_node_reference#update-display) node.
![Update Display](score-motor-uvs-update-display.png)
5. Just beneath, add an [On Display Changed](xref:uvs_node_reference#on-display-changed) node, select your score reel, and link the node to [Set Player Variable](xref:uvs_node_reference#set-variable) node, with *Score* to be updated.
![Update Score](score-motor-uvs-update-score.png)
6. Use the [Clear Display](xref:uvs_node_reference#clear-display) node when the game starts, in order to reset the score reels to zero.
![Reset Score](score-motor-uvs-reset-score.png)

This setup allows you to:

- Easily add scores in your game logic by triggering an *Add Score* event.
- Subscribe to the *Score* variable in order to trigger score-dependent game logic, while taking into consideration eventually blocked scores by the motor.

> [!WARNING]
> If you're working on an original EM game, make sure to only emit scores that a score motor can actually handle. For example, it's impossible to score anything higher than five points (or 50, 500, ...) at once. It's also impossible to score a combination of multiple points at once, like 150.

Finally, you might want to hook up other events to the score motor's behavior. For example, in Gottlieb's Volley, some lamps are toggled off while the motor is running. In order to achieve that, the score motor component exposes two switches:

1. The **Motor Running** switch is activated when the motors starts and deactivated when it stops.
2. The **Motor Step Switch** pulses on each step.

In order to hook into those switches, you'll have to create them in the GLE inspector and link them to the corresponding switches in the [Switch Manager](xref:switch_manager).

<img src="score-motor-switch-manager.png" width="1044" class="img-responsive">

Then, in your graphs, add your logic behind the corresponding [On Switch Changed](xref:uvs_node_reference#on-switch-changed) node(s).
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
---
uid: score-reels
title: Score Reels
description: How to use EM-style reels to display the score.
---

# Score Reel Displays

<img src="score-reels.jpg" width="350" alt="Score Reels a of a Gottlieb Volley" class="img-responsive pull-right" style="margin-left: 15px"/>

In electro-mechanical games, score reels are very common for displaying the player score. Typically, four to six units are mounted behind the backglass. Each reel is driven by a coil that advances the reel by one position when pulsed. The coils are driven by the playfield elements in the game, often indirectly through a score motor for multi-point scoring.

VPE includes components that simulate the [score motor](xref:score-motors) and render the score reel animation. This page is about the score reel, which presents itself to the [GLE](xref:gamelogic_engine) as a [display](xref:displays) that takes in the "numerical" frame format (i.e. numbers only). The score motor is an optional component that provides accurate timing when animating the reels.

## Setup

Typically you would drop the desired score reel variant from the asset library into your scene. But you can also set it up manually:

A score reel display consists of two separate components.

1. The *Score Reel Display* component, which represents the logical display that takes in a number and then sets the reels to display that number.
2. The *Score Reel* component, which represents one single reel and handles the animation.

### Model

The best geometry for a score reel is a simple, open cylinder. Make sure the local origin is in the middle, and that it rotates around the Z-axis.

![Score reel geometry](score-reels-geometry.jpg)

The texture should contain the numbers 0-9, each taking up 36°. The order (and thus the direction of rotation) depends on the game, so both are valid, and can be configured later.

### Scene

In your scene, drop in your reel model and add the *Score Reel* component (not the *Score Reel Display* component) to the game object. You can find it under *Visual Pinball -> Display*. Since you'll need the same reel for each position, the best approach is to create a [prefab](https://docs.unity3d.com/Manual/Prefabs.html) for the reel and instance it for each position. Then, parent them under a game object that acts as your display. To this object, add the *Score Reel* component (also under *Visual Pinball -> Display*).

![Score reel scene](score-reels-scene.png)

### Components

#### Score Reel

<img src="score-reel-inspector.png" width="362" alt="Score Reel Inspector" class="img-responsive pull-right" style="margin-left: 15px"/>

The *Score Reel* component is quick to set up. There is only one option, which is the *rotation direction*. What the score reel component gets from the display component is "turn to position X", where X is between 0 and 9, and the component's job is to animate the reel to that position.

Internally, it also takes in the rotation speed, and how long it rests at the final position before it can advance to the next position. However, those parameters are not exposed in the inspector but retrieved from the display component described in the next section.

#### Score Reel Display

<img src="score-reel-display-inspector.png" width="362" alt="Score Reel Display Inspector" class="img-responsive pull-right" style="margin-left: 15px"/>

This is the component on the parent game object that receives score numbers from the game and tells the individual reels to which position they need to turn to.

- **ID** defines the display ID. Remember that displays are [connected at runtime](xref:displays#setup), so this is the identifier that the GLE uses to send data to it.
- **Speed** defines how quickly the reels should rotate.
- **Wait** indicates the time the reels stand still before they can go to the next position.
- Under **Reel Objects** you define your reels (they are not automatically retrieved from the children). The order is from largest to smallest, i.e. from left to right.
- The **Score Motor** is an optional reference to a [score motor component](xref:score-motors).


## Usage

### Gamelogic Engine

<img src="score-reel-uvs-display.png" width="362" alt="Score Reel Display Inspector" class="img-responsive pull-right" style="margin-left: 15px"/>

Score reels are primarily used in EMs, so they are typically driven by [Visual Scripting](xref:uvs_index). As with every display, the first step is to define the display in the GLE component.

Add a new display under *Displays* and set the same ID as you did in the display component. The *Width* and *Height* properties are ignored, since they are managed by the display component (contrarily to the other displays, where the size is given by the GLE).

Next, add *Numeric* under *Supported Formats*.

### Visual Scripting

In Visual Scripting, use the [Update Display](xref:uvs_node_reference#update-display) node to set a new score. It's up to you whether to use a separate [event](xref:uvs_setup#events) or to subscribe to a [player variable](xref:uvs_variables) directly.

If you're using a score motor, read how to set it up correctly [here](xref:score-motors#usage).
4 changes: 4 additions & 0 deletions VisualPinball.Unity/Documentation~/creators-guide/toc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,10 @@
href: manual/mechanisms/drop-target-banks.md
- name: Rotators
href: manual/mechanisms/rotators.md
- name: Score Reels
href: manual/mechanisms/score-reels.md
- name: Score Motors
href: manual/mechanisms/score-motors.md
- name: Collision Switches
href: manual/mechanisms/collision-switches.md
- name: Lifting Gates
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,12 @@ Creating original *graphical* content for displays is not yet supported by VPE.

Even if we have nothing that creates the graphical content, we've defined the APIs used to pass the data around. This allows us to already have a working system that supports number and text data.

### Clear Display

This node clears a [display defined in the GLE](xref:uvs_setup#displays).

![Clear Display](clear-display-example.png)

### Update Display

This node takes in some data and sends it to one of the [displays defined in the GLE](xref:uvs_setup#displays). VPE supports segment displays and score reels, so the data can be numeric (score reels and segment displays) or alphanumeric (segment displays).
Expand All @@ -275,4 +281,10 @@ This example shows how the display is updated for a simple one player EM machine

![Update Display](update-display-example.png)

The score reel animation is handled by the component driving the reel. It's also on component level where you can define the speed and delays of the score reel animation.
The score reel animation is handled by the component driving the reel. It's also on component level where you can define the speed and delays of the score reel animation and associate a [score motor](xref:score-motors).

### On Display Changed

This event is triggered when a [display defined in the GLE](xref:uvs_setup#displays) is updated by *Clear Display* or *Update Display*. It is useful for EM machines that use a [score motor](xref:score-motors) and need to capture the score in a player variable.

![On Display Changed](display-changed-example.png)
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading