mvbg

VM_SIN_SCALE

VM_SIN_SCALE is a GBVM instruction used to calculate the sine of a given angle, scaled by a specified factor, and store the result in a variable.

Purpose: Trigonometric functions like sine are essential for many game mechanics, especially those involving circular motion, waves, or angles. VM_SIN_SCALE is particularly useful for:

This instruction takes an angle and a scale factor. The angle is typically represented in a Game Boy-specific format (0-255 for a full circle, where 64 units represent 90 degrees). The SCALE parameter affects the precision of the calculation.

Syntax:

VM_SIN_SCALE IDX, IDX_ANGLE, SCALE

Usage Example: Creating a Circular Orbiting Object

Imagine a small object (e.g., a fairy, a satellite) orbiting around a central point. You can use VM_SIN_SCALE (for Y-coordinate) and VM_COS_SCALE (for X-coordinate) to calculate its position based on a continuously increasing angle.

; In your orbiting object's update script:

; Assume ORBITING_ACTOR_ID is the actor ID for the orbiting object
ORBITING_ACTOR_ID:
  .R_INT8 70 ; Example Actor ID

; Variables for angle, radius, and center position
VAR_ORBIT_ANGLE:
  .R_INT8 0 ; Current angle for orbiting (0-255)
VAR_ORBIT_RADIUS:
  .R_INT8 32 ; Radius of the orbit (e.g., 32 pixels)
VAR_CENTER_X:
  .R_INT16 80 ; X-coordinate of the center of orbit
VAR_CENTER_Y:
  .R_INT16 72 ; Y-coordinate of the center of orbit
VAR_OFFSET_X:
  .R_INT16 0 ; Calculated X offset
VAR_OFFSET_Y:
  .R_INT16 0 ; Calculated Y offset
VAR_ORBIT_X:
  .R_INT16 0 ; Orbiting object's current X position
VAR_ORBIT_Y:
  .R_INT16 0 ; Orbiting object's current Y position

ORBIT_LOOP:
  ; Increment the angle for continuous motion
  VM_RPN
    .R_REF_MEM .R_INT8, VAR_ORBIT_ANGLE
    .R_INT8 1 ; Increment by 1 each frame (adjust for speed)
    .R_OPERATOR +
    .R_INT8
  VM_STOP
  VM_SET_INT8 VAR_ORBIT_ANGLE, 0

  ; Calculate X offset using cosine (scaled by radius)
  VM_SET_INT8 VAR_OFFSET_X, VAR_ORBIT_RADIUS ; Set IDX to radius
  VM_COS_SCALE VAR_OFFSET_X, VAR_ORBIT_ANGLE, 4 ; Calculate cosine, scale by radius, accuracy 4

  ; Calculate Y offset using sine (scaled by radius)
  VM_SET_INT8 VAR_OFFSET_Y, VAR_ORBIT_RADIUS ; Set IDX to radius
  VM_SIN_SCALE VAR_OFFSET_Y, VAR_ORBIT_ANGLE, 4 ; Calculate sine, scale by radius, accuracy 4

  ; Add offsets to center position to get new object position
  VM_RPN
    .R_REF_MEM .R_INT16, VAR_CENTER_X
    .R_REF_MEM .R_INT16, VAR_OFFSET_X
    .R_OPERATOR +
    .R_INT16
  VM_STOP
  VM_SET_INT16 VAR_ORBIT_X, 0

  VM_RPN
    .R_REF_MEM .R_INT16, VAR_CENTER_Y
    .R_REF_MEM .R_INT16, VAR_OFFSET_Y
    .R_OPERATOR +
    .R_INT16
  VM_STOP
  VM_SET_INT16 VAR_ORBIT_Y, 0

  ; Set the orbiting object's new position
  VM_ACTOR_SET_POS ORBITING_ACTOR_ID, VAR_ORBIT_X, VAR_ORBIT_Y

  VM_IDLE 1 ; Yield control for one frame
  VM_JUMP ORBIT_LOOP

In this example, VM_SIN_SCALE (for Y) and VM_COS_SCALE (for X) are used together to calculate the X and Y offsets from a central point. As VAR_ORBIT_ANGLE continuously increments, the sine and cosine values change, causing the ORBITING_ACTOR_ID to move in a smooth circular path around (VAR_CENTER_X, VAR_CENTER_Y). The VAR_ORBIT_RADIUS determines the size of the circle.

Analogy to other programming languages/game engines: This is analogous to using Math.sin() or sinf() in C/C++ or math.sin() in Python to calculate a value based on an angle, and then multiplying it by an amplitude (radius) to get a desired range. When combined with cosine, it’s the fundamental mathematical approach for simulating circular or elliptical motion in games.