TYPE

From QB64 Phoenix Edition Wiki
(Redirected from END TYPE)
Jump to navigation Jump to search

TYPE definitions are used to create variables that can hold more than one value of a specific variable type and fixed byte length. Comparable to structures in C/C++.


Syntax

TYPE typename
.
. variable1 AS type1
. variable2 AS type2
.
. variableN AS typeN
.
END TYPE


Description

  • typename is an undefined type name holder as it can hold any variable types.
  • TYPE definitions should be placed in the main module before the program code.
  • TYPE definitions can be placed inside SUB or FUNCTION procedures in QB64(PE) only.
    • Note the typename still belongs to the global scope (main module) and hence must be unique in the program to avoid duplicate definition errors.
  • TYPE definitions can contain fixed and variable length STRINGs. (see Availability)
  • TYPE definitions can contain fixed-size array members. (see Availability)
  • Regular arrays can be dimensioned to hold TYPE variables (DIM arr(n) AS typename).
  • TYPE definitions cannot be nested, but a TYPE may contain variables defined as another TYPE (var AS typename, see Example 3).
  • TYPE definitions must be ended with END TYPE.
  • Any TYPE definition must always be assigned to a actual variable for use, you cannot use the typename directly. Array variables are allowed.
  • Type variables must be defined in every SUB or FUNCTION unless the variable is SHARED.
  • Type variables use the DOT notation to read or write specific member values. They do not use type suffixes as they can hold any variable type values. The part before the dot is the variable name you assigned your defined TYPE to, and the part after the dot is the variable name used inside of the TYPE definition which you wanna access.
  • The name of the assigned type variable itself is sufficient to PUT # or GET # the entire TYPE with all its data at once.
    • You may also PUT and GET single members using the DOT notation.
    • You cannot PUT or GET entire type variables containing variable length strings.
  • Once a type variable is assigned you can find its byte size by using LEN(typevariable). Note you cannot use the typename for that.
  • TYPE definitions can also be placed in $INCLUDE text files.
  • The _BIT variable type is currently not supported inside TYPE definitions.


Availability

  • Since QB64 v1.3 it is possible to use variable length strings inside definitions with the exception that you can't PUT # or GET # such type variables then.
  • Since QB64-PE v4.5.0 it is possible to use fixed-size arrays inside definitions.


Examples

Example 1
Creating a mouse INTERRUPT TYPE definition. Each INTEGER value is 2 bytes.
TYPE RegType
    AX AS INTEGER ' mouse function to use
    BX AS INTEGER ' mouse button
    CX AS INTEGER ' mouse graphic column position
    DX AS INTEGER ' mouse graphic row position
    BP AS INTEGER ' not used by mouse, but required *
    SI AS INTEGER ' not used by mouse, but required *
    DI AS INTEGER ' not used by mouse, but required *
    Flags AS INTEGER ' not used by mouse but required *
    DS AS INTEGER ' used by INTERRUPTX only
    ES AS INTEGER ' used by INTERRUPTX only
END TYPE

DIM SHARED InRegs AS RegType, OutRegs AS RegType ' create dot variables

InRegs.AX = 3 ' sets the mouse function to read the mouse buttons and position.

CALL INTERRUPT(&H33, InRegs, OutRegs)

column% = OutRegs.CX ' returns the current mouse column position
Explanation
 InRegs and OutRegs become the DOT variable prefix name for the TYPE
 definition's variables. Each TYPE variable is designated as the DOT
 variable's suffix.

Example 2
Creating an addressbook database for a RANDOM file.
TYPE ContactInfo
    First AS STRING * 10
    Last AS STRING * 15
    Address1 AS STRING * 30
    Address2 AS STRING * 30
    City AS STRING * 15
    State AS STRING * 2
    Zip AS LONG ' (4 bytes)
    Phone AS STRING * 12
END TYPE

DIM Contact AS ContactInfo 'create contact record variable for RANDOM file
RecordLEN% = LEN(Contact) ' 118 bytes
'define values
Contact.First = "Ted" ' the fixed string length value will contain 7 extra spaces
Contact.Zip = 15236 ' LONG value that can be used to search certain zip code numbers.

PUT #1, 5, Contact 'place contact info into fifth record position
Explanation
 Use the assigned type variable to find the RANDOM record length which
 is 118 bytes. The DOT variable names consist of Contact as the prefix.

Example 3
Defining a TYPE variable as another variable type from a previous TYPE definition in QB64.
TYPE bar
    b AS STRING * 10
END TYPE

TYPE foo
    a AS SINGLE
    c AS bar 'define variable as a bar type
END TYPE

DIM foobar AS foo 'create a variable to use the foo type
foobar.a = 15.5
foobar.c.b = "this is me"

PRINT foobar.a, foobar.c.b
END

Example 4
Nested fixed-size array members in TYPE definitions.
TYPE CellType
    Value(0 TO 2) AS INTEGER ' Three integer values
END TYPE

TYPE BoardType
    Cell(0 TO 1) AS CellType ' Two CellType members
END TYPE

DIM B AS BoardType

B.Cell(0).Value(0) = 10
B.Cell(0).Value(1) = 20
B.Cell(0).Value(2) = 30

PRINT B.Cell(0).Value(0)
PRINT B.Cell(0).Value(1)
PRINT B.Cell(0).Value(2)
Explanation
 TYPE definitions can now contain fixed-size array members. In this
 example, CellType contains an integer array member named Value.
 BoardType then contains an array of CellType members. This allows
 array elements to be accessed through nested TYPE members using DOT
 notation.

Example 5
Nested fixed-size array members in TYPE definitions.
TYPE TileType
    Grid(0 TO 1, 0 TO 1) AS INTEGER ' 2 by 2 integer grid
END TYPE

TYPE MapType
    Tile(0 TO 1) AS TileType ' Two TileType members
END TYPE

DIM M AS MapType

M.Tile(0).Grid(0, 0) = 1
M.Tile(0).Grid(1, 0) = 2
M.Tile(0).Grid(0, 1) = 3
M.Tile(0).Grid(1, 1) = 4

PRINT M.Tile(0).Grid(0, 0)
PRINT M.Tile(0).Grid(1, 0)
PRINT M.Tile(0).Grid(0, 1)
PRINT M.Tile(0).Grid(1, 1)
Explanation
 TYPE definitions can now contain fixed-size array members. In this
 example, TileType contains a two-dimensional integer array member
 named Grid. MapType then contains an array of TileType members.
 The array values are accessed through nested TYPE members using DOT
 notation.

Example 6
Screen saver, use nested fixed-size array members in TYPE definitions.
OPTION _EXPLICIT

CONST WORK_W = 320
CONST WORK_H = 180
CONST SCREEN_W = 1280
CONST SCREEN_H = 720
CONST GRADIENT_TOTAL = 6
CONST PARTICLE_TOTAL = 260

TYPE GradientStopType
    T AS SINGLE
    R AS INTEGER
    G AS INTEGER
    B AS INTEGER
END TYPE

TYPE GradientType
    StopCount AS INTEGER
    StopData(0 To 7) AS GradientStopType
    Lut(0 To 255, 0 To 2) AS _UNSIGNED _BYTE
END TYPE

TYPE FlowLayerType
    Amp(0 To 3) AS SINGLE
    FreqX(0 To 3) AS SINGLE
    FreqY(0 To 3) AS SINGLE
    Speed(0 To 3) AS SINGLE
END TYPE

TYPE SaverStateType
    Gradients(0 To 5) AS GradientType
    Layers(0 To 2) AS FlowLayerType
END TYPE

DIM SHARED saver AS SaverStateType
DIM SHARED imgScreen AS LONG
DIM SHARED imgWork AS LONG
DIM SHARED memWork AS _MEM
DIM SHARED memPixels AS _MEM

DIM SHARED gradientSpan AS SINGLE
DIM SHARED mouseStartX AS LONG
DIM SHARED mouseStartY AS LONG

DIM SHARED activeLut(0 TO 255, 0 TO 2) AS INTEGER

REDIM SHARED pixelData(0) AS _UNSIGNED LONG
REDIM SHARED glowData(0) AS SINGLE
REDIM SHARED coordX(0) AS SINGLE
REDIM SHARED coordY(0) AS SINGLE
REDIM SHARED distData(0) AS SINGLE
REDIM SHARED angData(0) AS SINGLE
REDIM SHARED partX(0) AS SINGLE
REDIM SHARED partY(0) AS SINGLE
REDIM SHARED partVx(0) AS SINGLE
REDIM SHARED partVy(0) AS SINGLE

DIM done AS INTEGER
DIM tm AS SINGLE

RANDOMIZE TIMER

gradientSpan = 8.5

imgScreen = _NEWIMAGE(SCREEN_W, SCREEN_H, 32)
SCREEN imgScreen
_FULLSCREEN _SQUAREPIXELS
_TITLE "QB64PE Plasma Saver"

imgWork = _NEWIMAGE(WORK_W, WORK_H, 32)

InitScene

DO WHILE _MOUSEINPUT
LOOP
mouseStartX = _MOUSEX
mouseStartY = _MOUSEY
_MOUSEHIDE

DO
    tm = TIMER
    RenderFrame tm
    _DISPLAY
    _LIMIT 60

    done = 0
    HandleExit done
    _LIMIT 20
LOOP UNTIL done <> 0

_MOUSESHOW

_MEMFREE memWork
_MEMFREE memPixels

IF imgWork <= -2 THEN _FREEIMAGE imgWork: imgWork = 0
SCREEN 0
IF imgScreen <= -2 THEN _FREEIMAGE imgScreen: imgScreen = 0

END

SUB InitScene
    DIM workCount AS LONG
    DIM i AS LONG
    DIM x AS LONG
    DIM y AS LONG
    DIM idx AS LONG
    DIM nx AS SINGLE
    DIM ny AS SINGLE

    workCount = WORK_W * WORK_H

    REDIM pixelData(0 TO workCount - 1) AS _UNSIGNED LONG
    REDIM glowData(0 TO workCount - 1) AS SINGLE
    REDIM coordX(0 TO workCount - 1) AS SINGLE
    REDIM coordY(0 TO workCount - 1) AS SINGLE
    REDIM distData(0 TO workCount - 1) AS SINGLE
    REDIM angData(0 TO workCount - 1) AS SINGLE

    REDIM partX(0 TO PARTICLE_TOTAL - 1) AS SINGLE
    REDIM partY(0 TO PARTICLE_TOTAL - 1) AS SINGLE
    REDIM partVx(0 TO PARTICLE_TOTAL - 1) AS SINGLE
    REDIM partVy(0 TO PARTICLE_TOTAL - 1) AS SINGLE

    memPixels = _MEM(pixelData())
    memWork = _MEMIMAGE(imgWork)

    SeedLayers
    InitGradients

    idx = 0
    FOR y = 0 TO WORK_H - 1
        ny = (y - WORK_H * 0.5) / WORK_H
        FOR x = 0 TO WORK_W - 1
            nx = (x - WORK_W * 0.5) / WORK_H

            coordX(idx) = nx
            coordY(idx) = ny
            distData(idx) = SQR(nx * nx + ny * ny)
            angData(idx) = _ATAN2(ny, nx)

            idx = idx + 1
        NEXT x
    NEXT y

    FOR i = 0 TO PARTICLE_TOTAL - 1
        partX(i) = RND * (WORK_W - 1)
        partY(i) = RND * (WORK_H - 1)
        partVx(i) = (RND - 0.5) * 0.2
        partVy(i) = (RND - 0.5) * 0.2
    NEXT i
END SUB

SUB SeedLayers
    saver.Layers(0).Amp(0) = 0.42
    saver.Layers(0).Amp(1) = 0.36
    saver.Layers(0).Amp(2) = 0.28
    saver.Layers(0).Amp(3) = 0.21

    saver.Layers(0).FreqX(0) = 2.2
    saver.Layers(0).FreqX(1) = 3.7
    saver.Layers(0).FreqX(2) = 5.5
    saver.Layers(0).FreqX(3) = 7.8

    saver.Layers(0).FreqY(0) = 1.7
    saver.Layers(0).FreqY(1) = 2.8
    saver.Layers(0).FreqY(2) = 4.4
    saver.Layers(0).FreqY(3) = 6.1

    saver.Layers(0).Speed(0) = 0.38
    saver.Layers(0).Speed(1) = 0.57
    saver.Layers(0).Speed(2) = 0.83
    saver.Layers(0).Speed(3) = 1.10

    saver.Layers(1).Amp(0) = 0.35
    saver.Layers(1).Amp(1) = 0.29
    saver.Layers(1).Amp(2) = 0.23
    saver.Layers(1).Amp(3) = 0.18

    saver.Layers(1).FreqX(0) = 1.9
    saver.Layers(1).FreqX(1) = 3.2
    saver.Layers(1).FreqX(2) = 4.9
    saver.Layers(1).FreqX(3) = 6.7

    saver.Layers(1).FreqY(0) = 2.4
    saver.Layers(1).FreqY(1) = 3.8
    saver.Layers(1).FreqY(2) = 5.3
    saver.Layers(1).FreqY(3) = 7.5

    saver.Layers(1).Speed(0) = 0.31
    saver.Layers(1).Speed(1) = 0.49
    saver.Layers(1).Speed(2) = 0.74
    saver.Layers(1).Speed(3) = 0.96

    saver.Layers(2).Amp(0) = 0.26
    saver.Layers(2).Amp(1) = 0.21
    saver.Layers(2).Amp(2) = 0.17
    saver.Layers(2).Amp(3) = 0.13

    saver.Layers(2).FreqX(0) = 2.8
    saver.Layers(2).FreqX(1) = 4.5
    saver.Layers(2).FreqX(2) = 6.3
    saver.Layers(2).FreqX(3) = 8.4

    saver.Layers(2).FreqY(0) = 2.1
    saver.Layers(2).FreqY(1) = 3.5
    saver.Layers(2).FreqY(2) = 5.8
    saver.Layers(2).FreqY(3) = 7.9

    saver.Layers(2).Speed(0) = 0.27
    saver.Layers(2).Speed(1) = 0.44
    saver.Layers(2).Speed(2) = 0.68
    saver.Layers(2).Speed(3) = 0.89
END SUB

SUB InitGradients
    DIM i AS LONG
    DIM c AS INTEGER

    saver.Gradients(0).StopCount = 6
    saver.Gradients(0).StopData(0).T = 0.00: saver.Gradients(0).StopData(0).R = 5: saver.Gradients(0).StopData(0).G = 2: saver.Gradients(0).StopData(0).B = 18
    saver.Gradients(0).StopData(1).T = 0.18: saver.Gradients(0).StopData(1).R = 40: saver.Gradients(0).StopData(1).G = 0: saver.Gradients(0).StopData(1).B = 98
    saver.Gradients(0).StopData(2).T = 0.38: saver.Gradients(0).StopData(2).R = 0: saver.Gradients(0).StopData(2).G = 92: saver.Gradients(0).StopData(2).B = 188
    saver.Gradients(0).StopData(3).T = 0.60: saver.Gradients(0).StopData(3).R = 0: saver.Gradients(0).StopData(3).G = 220: saver.Gradients(0).StopData(3).B = 180
    saver.Gradients(0).StopData(4).T = 0.82: saver.Gradients(0).StopData(4).R = 255: saver.Gradients(0).StopData(4).G = 210: saver.Gradients(0).StopData(4).B = 70
    saver.Gradients(0).StopData(5).T = 1.00: saver.Gradients(0).StopData(5).R = 255: saver.Gradients(0).StopData(5).G = 255: saver.Gradients(0).StopData(5).B = 255

    saver.Gradients(1).StopCount = 6
    saver.Gradients(1).StopData(0).T = 0.00: saver.Gradients(1).StopData(0).R = 2: saver.Gradients(1).StopData(0).G = 8: saver.Gradients(1).StopData(0).B = 20
    saver.Gradients(1).StopData(1).T = 0.16: saver.Gradients(1).StopData(1).R = 0: saver.Gradients(1).StopData(1).G = 45: saver.Gradients(1).StopData(1).B = 130
    saver.Gradients(1).StopData(2).T = 0.37: saver.Gradients(1).StopData(2).R = 0: saver.Gradients(1).StopData(2).G = 180: saver.Gradients(1).StopData(2).B = 235
    saver.Gradients(1).StopData(3).T = 0.58: saver.Gradients(1).StopData(3).R = 90: saver.Gradients(1).StopData(3).G = 255: saver.Gradients(1).StopData(3).B = 180
    saver.Gradients(1).StopData(4).T = 0.80: saver.Gradients(1).StopData(4).R = 240: saver.Gradients(1).StopData(4).G = 255: saver.Gradients(1).StopData(4).B = 120
    saver.Gradients(1).StopData(5).T = 1.00: saver.Gradients(1).StopData(5).R = 255: saver.Gradients(1).StopData(5).G = 255: saver.Gradients(1).StopData(5).B = 255

    saver.Gradients(2).StopCount = 6
    saver.Gradients(2).StopData(0).T = 0.00: saver.Gradients(2).StopData(0).R = 8: saver.Gradients(2).StopData(0).G = 0: saver.Gradients(2).StopData(0).B = 10
    saver.Gradients(2).StopData(1).T = 0.18: saver.Gradients(2).StopData(1).R = 70: saver.Gradients(2).StopData(1).G = 0: saver.Gradients(2).StopData(1).B = 50
    saver.Gradients(2).StopData(2).T = 0.38: saver.Gradients(2).StopData(2).R = 180: saver.Gradients(2).StopData(2).G = 0: saver.Gradients(2).StopData(2).B = 120
    saver.Gradients(2).StopData(3).T = 0.60: saver.Gradients(2).StopData(3).R = 255: saver.Gradients(2).StopData(3).G = 70: saver.Gradients(2).StopData(3).B = 60
    saver.Gradients(2).StopData(4).T = 0.82: saver.Gradients(2).StopData(4).R = 255: saver.Gradients(2).StopData(4).G = 190: saver.Gradients(2).StopData(4).B = 40
    saver.Gradients(2).StopData(5).T = 1.00: saver.Gradients(2).StopData(5).R = 255: saver.Gradients(2).StopData(5).G = 255: saver.Gradients(2).StopData(5).B = 230

    saver.Gradients(3).StopCount = 6
    saver.Gradients(3).StopData(0).T = 0.00: saver.Gradients(3).StopData(0).R = 3: saver.Gradients(3).StopData(0).G = 0: saver.Gradients(3).StopData(0).B = 25
    saver.Gradients(3).StopData(1).T = 0.18: saver.Gradients(3).StopData(1).R = 0: saver.Gradients(3).StopData(1).G = 20: saver.Gradients(3).StopData(1).B = 95
    saver.Gradients(3).StopData(2).T = 0.38: saver.Gradients(3).StopData(2).R = 70: saver.Gradients(3).StopData(2).G = 0: saver.Gradients(3).StopData(2).B = 160
    saver.Gradients(3).StopData(3).T = 0.60: saver.Gradients(3).StopData(3).R = 255: saver.Gradients(3).StopData(3).G = 0: saver.Gradients(3).StopData(3).B = 170
    saver.Gradients(3).StopData(4).T = 0.82: saver.Gradients(3).StopData(4).R = 0: saver.Gradients(3).StopData(4).G = 220: saver.Gradients(3).StopData(4).B = 255
    saver.Gradients(3).StopData(5).T = 1.00: saver.Gradients(3).StopData(5).R = 255: saver.Gradients(3).StopData(5).G = 255: saver.Gradients(3).StopData(5).B = 255

    saver.Gradients(4).StopCount = 6
    saver.Gradients(4).StopData(0).T = 0.00: saver.Gradients(4).StopData(0).R = 0: saver.Gradients(4).StopData(0).G = 8: saver.Gradients(4).StopData(0).B = 16
    saver.Gradients(4).StopData(1).T = 0.16: saver.Gradients(4).StopData(1).R = 0: saver.Gradients(4).StopData(1).G = 80: saver.Gradients(4).StopData(1).B = 55
    saver.Gradients(4).StopData(2).T = 0.37: saver.Gradients(4).StopData(2).R = 80: saver.Gradients(4).StopData(2).G = 200: saver.Gradients(4).StopData(2).B = 70
    saver.Gradients(4).StopData(3).T = 0.58: saver.Gradients(4).StopData(3).R = 255: saver.Gradients(4).StopData(3).G = 245: saver.Gradients(4).StopData(3).B = 110
    saver.Gradients(4).StopData(4).T = 0.82: saver.Gradients(4).StopData(4).R = 255: saver.Gradients(4).StopData(4).G = 110: saver.Gradients(4).StopData(4).B = 20
    saver.Gradients(4).StopData(5).T = 1.00: saver.Gradients(4).StopData(5).R = 255: saver.Gradients(4).StopData(5).G = 255: saver.Gradients(4).StopData(5).B = 255

    saver.Gradients(5).StopCount = 6
    saver.Gradients(5).StopData(0).T = 0.00: saver.Gradients(5).StopData(0).R = 6: saver.Gradients(5).StopData(0).G = 4: saver.Gradients(5).StopData(0).B = 12
    saver.Gradients(5).StopData(1).T = 0.16: saver.Gradients(5).StopData(1).R = 38: saver.Gradients(5).StopData(1).G = 0: saver.Gradients(5).StopData(1).B = 92
    saver.Gradients(5).StopData(2).T = 0.37: saver.Gradients(5).StopData(2).R = 155: saver.Gradients(5).StopData(2).G = 0: saver.Gradients(5).StopData(2).B = 165
    saver.Gradients(5).StopData(3).T = 0.58: saver.Gradients(5).StopData(3).R = 255: saver.Gradients(5).StopData(3).G = 70: saver.Gradients(5).StopData(3).B = 140
    saver.Gradients(5).StopData(4).T = 0.82: saver.Gradients(5).StopData(4).R = 255: saver.Gradients(5).StopData(4).G = 210: saver.Gradients(5).StopData(4).B = 110
    saver.Gradients(5).StopData(5).T = 1.00: saver.Gradients(5).StopData(5).R = 255: saver.Gradients(5).StopData(5).G = 255: saver.Gradients(5).StopData(5).B = 255

    FOR i = 0 TO GRADIENT_TOTAL - 1
        BuildGradientLut saver.Gradients(i)
    NEXT i

    FOR i = 0 TO 255
        FOR c = 0 TO 2
            activeLut(i, c) = saver.Gradients(0).Lut(i, c)
        NEXT c
    NEXT i
END SUB

SUB BuildGradientLut (g AS GradientType)
    DIM i AS INTEGER
    DIM s AS INTEGER
    DIM t AS SINGLE
    DIM leftT AS SINGLE
    DIM rightT AS SINGLE
    DIM k AS SINGLE
    DIM r AS INTEGER
    DIM gg AS INTEGER
    DIM b AS INTEGER

    FOR i = 0 TO 255
        t = i / 255

        s = 0
        DO WHILE s < g.StopCount - 2
            IF t <= g.StopData(s + 1).t THEN EXIT DO
            s = s + 1
        LOOP

        leftT = g.StopData(s).t
        rightT = g.StopData(s + 1).t

        IF rightT > leftT THEN
            k = (t - leftT) / (rightT - leftT)
        ELSE
            k = 0
        END IF

        r = g.StopData(s).r + (g.StopData(s + 1).r - g.StopData(s).r) * k
        gg = g.StopData(s).g + (g.StopData(s + 1).g - g.StopData(s).g) * k
        b = g.StopData(s).b + (g.StopData(s + 1).b - g.StopData(s).b) * k

        IF r < 0 THEN r = 0 ELSE IF r > 255 THEN r = 255
        IF gg < 0 THEN gg = 0 ELSE IF gg > 255 THEN gg = 255
        IF b < 0 THEN b = 0 ELSE IF b > 255 THEN b = 255

        g.Lut(i, 0) = r
        g.Lut(i, 1) = gg
        g.Lut(i, 2) = b
    NEXT i
END SUB

SUB BlendPalette (ga AS INTEGER, gb AS INTEGER, k AS SINGLE)
    DIM i AS INTEGER
    DIM c AS INTEGER
    DIM v AS INTEGER

    FOR i = 0 TO 255
        FOR c = 0 TO 2
            v = saver.Gradients(ga).Lut(i, c) + (saver.Gradients(gb).Lut(i, c) - saver.Gradients(ga).Lut(i, c)) * k
            IF v < 0 THEN v = 0 ELSE IF v > 255 THEN v = 255
            activeLut(i, c) = v
        NEXT c
    NEXT i
END SUB

SUB FadeGlow
    DIM i AS LONG
    DIM workCount AS LONG

    workCount = WORK_W * WORK_H

    FOR i = 0 TO workCount - 1
        glowData(i) = glowData(i) * 0.945
        IF glowData(i) < 0.002 THEN glowData(i) = 0
    NEXT i
END SUB

SUB UpdateParticles (tm AS SINGLE)
    DIM i AS LONG
    DIM k AS INTEGER
    DIM nx AS SINGLE
    DIM ny AS SINGLE
    DIM ax AS SINGLE
    DIM ay AS SINGLE
    DIM speedMul AS SINGLE
    DIM power AS SINGLE

    FOR i = 0 TO PARTICLE_TOTAL - 1
        nx = (partX(i) - WORK_W * 0.5) / WORK_H
        ny = (partY(i) - WORK_H * 0.5) / WORK_H

        ax = 0
        ay = 0

        FOR k = 0 TO 3
            ax = ax + SIN(nx * saver.Layers(0).FreqX(k) + ny * saver.Layers(1).FreqY(k) + tm * saver.Layers(0).Speed(k)) * saver.Layers(0).Amp(k)
            ay = ay + COS(ny * saver.Layers(1).FreqX(k) - nx * saver.Layers(2).FreqY(k) - tm * saver.Layers(1).Speed(k)) * saver.Layers(1).Amp(k)
        NEXT k

        partVx(i) = partVx(i) * 0.92 + ax * 0.11
        partVy(i) = partVy(i) * 0.92 + ay * 0.11

        speedMul = 0.55 + 0.22 * SIN(tm * 0.70 + i * 0.11)

        partX(i) = partX(i) + partVx(i) * speedMul + SIN(tm * 0.17 + i * 0.07) * 0.15
        partY(i) = partY(i) + partVy(i) * speedMul + COS(tm * 0.19 + i * 0.09) * 0.15

        IF partX(i) < 0 THEN partX(i) = partX(i) + WORK_W
        IF partX(i) >= WORK_W THEN partX(i) = partX(i) - WORK_W
        IF partY(i) < 0 THEN partY(i) = partY(i) + WORK_H
        IF partY(i) >= WORK_H THEN partY(i) = partY(i) - WORK_H

        power = 0.55 + 0.75 * (0.5 + 0.5 * SIN(tm * 1.45 + i * 0.37))
        StampGlow partX(i), partY(i), power
    NEXT i
END SUB

SUB StampGlow (cx AS SINGLE, cy AS SINGLE, power AS SINGLE)
    DIM ix AS LONG
    DIM iy AS LONG
    DIM x AS LONG
    DIM y AS LONG
    DIM dx AS LONG
    DIM dy AS LONG
    DIM idx AS LONG
    DIM weight AS SINGLE

    ix = INT(cx)
    iy = INT(cy)

    FOR dy = -2 TO 2
        y = iy + dy
        IF y >= 0 AND y < WORK_H THEN
            FOR dx = -2 TO 2
                x = ix + dx
                IF x >= 0 AND x < WORK_W THEN
                    idx = y * WORK_W + x
                    weight = (3 - ABS(dx)) * (3 - ABS(dy)) * 0.030 * power
                    glowData(idx) = glowData(idx) + weight
                    IF glowData(idx) > 2.6 THEN glowData(idx) = 2.6
                END IF
            NEXT dx
        END IF
    NEXT dy
END SUB

SUB RenderFrame (tm AS SINGLE)
    DIM workCount AS LONG
    DIM i AS LONG
    DIM phase AS SINGLE
    DIM wholePhase AS LONG
    DIM ga AS INTEGER
    DIM gb AS INTEGER
    DIM mixK AS SINGLE
    DIM plasma AS SINGLE
    DIM shadeIndex AS INTEGER
    DIM shine AS SINGLE
    DIM r AS INTEGER
    DIM g AS INTEGER
    DIM b AS INTEGER

    workCount = WORK_W * WORK_H

    FadeGlow
    UpdateParticles tm

    phase = tm / gradientSpan
    wholePhase = INT(phase)
    ga = wholePhase MOD GRADIENT_TOTAL
    gb = (ga + 1) MOD GRADIENT_TOTAL
    mixK = phase - wholePhase

    BlendPalette ga, gb, mixK

    FOR i = 0 TO workCount - 1
        plasma = 128
        plasma = plasma + 62 * SIN(distData(i) * 15.0 - tm * 1.70 + SIN(angData(i) * 4.0 + tm * 0.72) * 1.8)
        plasma = plasma + 40 * SIN(coordX(i) * 12.0 + tm * 1.15)
        plasma = plasma + 36 * COS(coordY(i) * 14.0 - tm * 0.96)
        plasma = plasma + 28 * SIN((coordX(i) + coordY(i)) * 16.0 + tm * 0.43)
        plasma = plasma + 18 * COS((coordX(i) * coordX(i) + coordY(i) * coordY(i)) * 40.0 - tm * 0.81)
        plasma = plasma + glowData(i) * 48.0

        shadeIndex = INT(plasma)
        IF shadeIndex < 0 THEN shadeIndex = 0 ELSE IF shadeIndex > 255 THEN shadeIndex = 255

        shine = glowData(i)

        r = activeLut(shadeIndex, 0) + shine * 70
        g = activeLut(shadeIndex, 1) + shine * 55
        b = activeLut(shadeIndex, 2) + shine * 88

        IF r < 0 THEN r = 0 ELSE IF r > 255 THEN r = 255
        IF g < 0 THEN g = 0 ELSE IF g > 255 THEN g = 255
        IF b < 0 THEN b = 0 ELSE IF b > 255 THEN b = 255

        pixelData(i) = _RGB32(r, g, b)
    NEXT i

    _MEMCOPY memPixels, memPixels.OFFSET, memPixels.SIZE TO memWork, memWork.OFFSET
    _PUTIMAGE (0, 0)-(SCREEN_W - 1, SCREEN_H - 1), imgWork, 0
END SUB

SUB HandleExit (done AS INTEGER)
    IF _KEYHIT <> 0 THEN
        done = -1
        EXIT SUB
    END IF
END SUB
Note
 Nested static arrays must be declared with numeric bounds or constants
 only. Variable-based bounds are not allowed, because static arrays
 must have a fixed size that cannot change during program execution. 
All array usage examples by Petr

See also



Navigation:
Main Page with Articles and Tutorials
Keyword Reference - Alphabetical
Keyword Reference - By usage
Report a broken link