0
\$\begingroup\$

I want to create a 2d board game that involve a spinning wheel that has 1 - 6 numbers that pick in random then it will animate in the wheel. how can i code the physics of a spinning wheel while generating an random number 1 - 6??

\$\endgroup\$
1
  • \$\begingroup\$ i want physics based wheel simulation to pick a random 1 to 6 number then use the wheel spinning animation to show it by user push button i was struggling with the physics \$\endgroup\$ Aug 16, 2021 at 13:01

1 Answer 1

0
\$\begingroup\$

Since you want a physics simulation, in 2D, in Godot, for a wheel spinning...

We will make the wheel as a RigidBody2D. It will have a a Sprite child for visual representation.

A couple options for fixing it in place come to mind:

  • You can set its gravity_scale to 0, so it does not fall. In theory something else could knock it off.
  • You can use a PinJoint2D to fix it an StaticBody2D. Make sure the PinJoint2D has Node A and Node B connected to the StaticBody2D and RigidBody2D.

I'll also suggest to have a Node2D to contain the whole arrangement (that way you can position the parent Node2D instead of moving its children nodes). It is also convenient to put our code there, in particular if we want to save this as a scene and instance it somewhere else.

CollisionShapes are NOT strictly necessary in this case, but you may add them too.


For the rotation the simplest solution is to give it a random angular_velocity.

I'll be writing the code for the parent Node2D. For example:

func spin() -> void:
    $RigidBody2D.angular_velocity = rand_range(500.0, 10000.0)

And it will slow down and stop according to its angular_damp.


We also need to know when it stopped. For that we can add a custom signal:

signal stopped_spinning

And check the angular velocity in _physics_process to know when it stopped.

By the way, we cannot rely on the angular velocity hitting 0. Instead we will consider it stopped when it is close to zero.

I will take advantage of set_physics_process to enable when spinning, and disable it is when done:

extends Node2D

signal stopped_spinning

func _ready() -> void:
    set_physics_process(false)

func spin() -> void:
    $RigidBody2D.angular_velocity = rand_range(500.0, 10000.0)
    set_physics_process(true)
    
func _physics_process(_delta: float) -> void:
    if abs($RigidBody2D.angular_velocity) < 0.02:
        $RigidBody2D.angular_velocity = 0.0
        emit_signal("stopped_spinning")
        set_physics_process(false)

In my test, the angular velocity gets down to 0.010584. So I picked 0.02 as threshold. If that gives you problems, experiment with the value.

Even though I only put positive angular velocities, I decided to use abs so the code can handle a negative value.


You can then create a button, and make it call spin when pressed. You can also handle the custom "stopped_spinning" signal to get the result. For that, you may use $RigidBody2D.rotation_degrees and some arithmetic, for example:

func get_value() -> int:
    var offset_degrees = 90
    var options = 6
    var option_degrees = 360 / options
    return int(fposmod($RigidBody2D.rotation_degrees + offset_degrees, 360) / option_degrees) + 1

The fposmod will give you a value between 0 and the second parameter (360 in this case).

I added offset_degrees to account for the fact that I don't know at what angle the first option is. Also, I added 1 at the end because it would give you values in the range [0, options), but you probably want a value on the range [1, options]. Tweak that as needed.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .