User Tools

Site Tools


4rpl:commands:signalgenerator

Index
Math Utility

SignalGenerator

SignalGenerator(<-time <-frequency <-phaseShift <-invert <-signalType) ->sigValue

Description

Computes the value for a given signal waveform and pushes it to the stack.

A function to derive the y-coordinate for a given x-coordinate on a graph line following one of the indicated wave patterns.

Useful to animate an object or to produce a pattern over time. For instance, could be used to vary the strength of an emitter over time, or to “pulse” (oscillate) the brightness of light source or beacon.

Arguments and type in order:

  • time: (float) Current step in the waveform. For a wave duration of 10.0, a step of 2.5 is a quarter of the way into a pattern.
  • frequency: (float) The frequency dictates the duration of each repeating pattern. A duration of 10.0 must set the frequency to 0.1 (1/10.0)
  • phaseShift: (float) A starting offset, between 0 and 1, where 0 will start the pattern at the beginning, and 1 will start it at the end. For sine wave, 0.25 will begin the wave at the peak, and 0.75 will begin at the valley.
  • invert: (0/1) inverts the waveform
  • signalType: (0 to 6)
    • 0 = NONE
    • 1 = SINE
    • 2 = SQUARE
    • 3 = TRIANGLE
    • 4 = SAW-TOOTH
    • 5 = RANDOM
    • 6 = CONSTANT

The resulting variable sigValue contains a float value between -1 and 1 which represents the current state of the wave at the provided step (time) given its provided frequency and other factors.

Example

To create a sine wave that should start at its peak and run for 80 frames until it repeats, we should set the frequency to (1.0/80.0), phase shift to 0.25, start the time value at 0 and add 1 to it every frame.

Play the following example in the editor console to spawn a continuous stream of creeper using the sine wave at the bottom of the map.

$time:0
$duration:80.0
$phaseShift:0.25
$invert:0
$signalType:1
 
SignalGenerator(<-time <-frequency <-phaseShift <-invert <-signalType) ->sigValue
<-time 1 add ->time
 
#Let's use the result to spawn some creeper in a range of cells:
AddCreeper(<-time <-mapX mod, <-sigValue 20.0 mul 20 add, 1)
 
:Once
   1.0 <-duration div ->frequency
   GetMapSize ->mapZ ->mapX

Patterns

1 - SINE, Pattern repeated every 60 cells


2 - SQUARE, Pattern repeated every 60 cells
3 - TRIANGLE, Pattern repeated every 60 cells


4 - SAW-TOOTH, Pattern repeated every 60 cells
5 - RANDOM, Pattern repeated every 5 cells


Extra Notes

This is how each wave is produced in the game's source code:

Sine wave function

float t = frequency * time + phase;
value = (float)Mathf.Sin(2f * Mathf.PI * t);

Square wave function

value = Mathf.Sign(Mathf.Sin(2f * Mathf.PI * t)); 

For triangle wave function

value = 1f - 4f * (float)Mathf.Abs(Mathf.Round(t - 0.25f) - (t - 0.25f));

Saw-tooth wave function

value = 2f * (t - (float)Mathf.Floor(t + 0.5f));

Random wave function

The function will output the same number for a given interval. Interval is 1/frequency. It only changes to a new value on the next interval. Hence a random number per interval, or a random number at a given frequency. Otherwise, just use the rand functions to get a new value on each call.

float interval = 1 / frequency;
int slot = (int)(time / interval) ;
slot = (slot * 1431655781) + (slot * 1183186591) + (slot * 622729787) + (slot * 338294347);
if (slot < 0) slot = -slot;
value = (float)GameSpace.instance.RandDoubleInput(randSeed + slot)*2-1;

Extra examples

Sine Wave Creeper on Terrain

# On a map with terrain of 200 in X direction and at least 150 in Z direction (3D coordinates)
# generate a sine wave of creeper across the map.
# On a map with terrain of 200 in X direction and at least 150 in Z direction (3D coordinates)
# generate a sine wave of creeper across the map.
 
180 ->numFrames 			# at 30 frames a sec, cycle every 6 seconds.
1 <-numFrames asFloat div ->frequency	#stepsize
0 ->phaseShift
false ->invert
1 ->signalType 				#sine
 
do (<-numFrames 0)
    SignalGenerator(I <-frequency <-phaseShift <-invert <-signalType) ->sigValue
    Round(<-sigValue 2) ->sigValue
    TraceAllSp (I " : " <-sigValue)
    SetCreeper(I 75 add(<-sigValue mul(50)) 15 true)
loop

The above command generated this sinusoidal creeper pattern on a map

Make a Unit Move or "Float" Above Terrain

# Oscillate
$UID:1
 
GetUnitMoveCell(<-UID) ->cellZ ->cellX
if (<-cellz  -1 EQ)
	SignalGenerator(<-time , <-frequency , <-phaseShift , <-invert , <-signaltype) ->sigValue
	<-time 1 + ->time
	<-sigvalue 1 + <-scale * ->sigvalue
	GetUnitPosition(<-UID) ->pos
	GetExactTerrain(<-pos.X <-pos.Z false) ->exactTerrainHeight
	SetUnitPosition(<-UID V3(<-pos.x , <-exactTerrainHeight <-sigvalue + , <-pos.z))	# Buil-in unit	
	# SetObjPosition(2  "" V3(0 <-sigValue 0) false)          							# for custom unit
else
	0 ->time
endIf
 
:Once
	# Parameters for SignalGenerator
	1.0  180 / ->frequency  		# we cycle over 180 frames
	0.0 ->phaseShift 			# offset from zero-time
	false ->invert 				# Invert the waveform
	1 ->signalType				# type of signal generated
	0.5 ->scale				# control the maximum size of movement

Index

4rpl/commands/signalgenerator.txt · Last modified: 2024/05/29 15:57 by Grabz