User-Defined Types

A TYPE groups related fields into one record (like a struct in C):

14.1 Defining a TYPE

A TYPE groups related fields into one record (like a struct in C):

Fixed-length string fields are padded with spaces — use RTRIM$ when printing.

QB64-PE also allows variable-length STRING fields in TYPEs, but fixed-length strings are required if you want to store records in random-access files (Chapter 20).

TYPE blocks belong at module level (before the main code is cleanest).

TYPEs can contain other TYPEs; QB64 TYPEs cannot contain arrays.

TYPE Employee
    id AS LONG
    lastName AS STRING * 20       ' fixed-length string
    firstName AS STRING * 15
    salary AS DOUBLE
    active AS INTEGER             ' -1 or 0
END TYPE

DIM e AS Employee
e.id = 1001
e.lastName = "Lovelace"
e.firstName = "Ada"
e.salary = 85000
e.active = -1
PRINT RTRIM$(e.firstName); " "; RTRIM$(e.lastName); " earns"; e.salary

14.2 Arrays of TYPEs

TYPE Vec2
    x AS SINGLE
    y AS SINGLE
END TYPE

TYPE Enemy
    position AS Vec2               ' nested type
    vel AS Vec2
    hp AS INTEGER
    alive AS INTEGER
END TYPE

CONST MAX_ENEMIES = 50
DIM SHARED enemies(1 TO MAX_ENEMIES) AS Enemy

RANDOMIZE TIMER
FOR i = 1 TO MAX_ENEMIES
    enemies(i).position.x = RND * 640
    enemies(i).position.y = RND * 480
    enemies(i).vel.x = RND * 4 - 2
    enemies(i).vel.y = RND * 4 - 2
    enemies(i).hp = 3
    enemies(i).alive = -1
NEXT
UpdateEnemies
PRINT "Enemy 1 at"; enemies(1).position.x; enemies(1).position.y
END

SUB UpdateEnemies
    DIM i AS INTEGER
    FOR i = 1 TO MAX_ENEMIES
        IF enemies(i).alive THEN
            enemies(i).position.x = enemies(i).position.x + enemies(i).vel.x
            enemies(i).position.y = enemies(i).position.y + enemies(i).vel.y
        END IF
    NEXT
END SUB

14.3 Passing TYPEs to procedures

(A space followed by _ at the end of a line continues the statement on the next line in QB64.)

You can assign one TYPE variable to another of the same type (b = a copies all fields) and SWAP them; you cannot compare them with = or PRINT them directly.

Classic BASIC: no records at all — programmers used parallel arrays. FreeBASIC: Type ... End Type with any field types including dynamic strings, arrays, pointers, methods, constructors, and operators (Chapter 33). Union is also available. VB.NET: Structure Point ... End Structure (value type) or Class (reference type), with properties and methods.

TYPE Rect
    x AS SINGLE: y AS SINGLE: w AS SINGLE: h AS SINGLE
END TYPE

DIM a AS Rect, b AS Rect
a.x = 0: a.y = 0: a.w = 10: a.h = 10
b.x = 5: b.y = 5: b.w = 10: b.h = 10
IF Overlaps%(a, b) THEN PRINT "Collision!"
END

FUNCTION Overlaps% (r1 AS Rect, r2 AS Rect)
    Overlaps% = r1.x < r2.x + r2.w AND r2.x < r1.x + r1.w AND _
                r1.y < r2.y + r2.h AND r2.y < r1.y + r1.h
END FUNCTION