4) Drawing, Camera, and Buffers
Goal: build a small scene that demonstrates primitive drawing, local transforms, clipping, and reusable off-screen content.
Step 1: Learn the Primitive Toolkit
SetDrawColor(80, 180, 255)
DrawLine(40, 80, 220, 80)
DrawRect(40, 100, 180, 80)
DrawFilledRect(260, 100, 180, 80)
DrawCircle(560, 140, 64, 48)
SetDrawColor affects lines, outlined and filled rectangles, and circles. The last DrawCircle argument is the segment count: small values make polygons, while larger values make a smoother outline.
Step 2: Draw in Local Coordinates
PushDrawState()
SetDrawOffset(400, 300)
SetDrawRotation(30.0)
SetDrawColor(255, 190, 70)
DrawFilledRect(-60, -20, 120, 40)
DrawLine(0, 0, 90, 0)
PopDrawState()
The shape is defined around local origin 0, 0, rotated, then moved to 400, 300. PushDrawState/PopDrawState contain the transform so later UI drawing is unaffected.
Step 3: Treat the Offset as a Camera
If the player is at world position playerX, playerY, center the camera by translating the world in the opposite direction:
PushDrawState()
SetDrawOffset( _
(ScreenWidth() / 2) - playerX, _
(ScreenHeight() / 2) - playerY _
)
' Draw all world objects here using world coordinates.
DrawFilledRect(playerX - 16, playerY - 16, 32, 32)
PopDrawState()
Draw the HUD after PopDrawState so it stays anchored to screen coordinates.
Step 4: Clip a Viewport
SetClipRegion(40, 40, 300, 180)
SetDrawColor(40, 100, 180)
DrawFilledRect(0, 0, 500, 300)
SetDrawColor(255, 255, 255)
DrawCircle(330, 130, 90, 48)
ClearClipRegion()
Only pixels inside the 300 × 180 region are rendered. Always clear or restore the clip before drawing unrelated content.
Step 5: Pre-render a Reusable Buffer
Dim panel As Integer
panel = CreateBuffer(220, 80)
If panel <> 0 Then
SetBufferTarget(panel)
Cls()
SetDrawColor(24, 34, 60, 230)
DrawFilledRect(0, 0, 220, 80)
SetDrawColor(100, 210, 255)
DrawRect(0, 0, 220, 80)
ClearBufferTarget()
End If
Render content that changes rarely into a buffer once, then reuse it with DrawBuffer. This is useful for UI panels, minimaps, and composed effects.
Checkpoint: Transform Playground
Graphics(800, 600, False)
SetClsColor(10, 14, 25)
Dim fontRef As Integer
Dim panel As Integer
Dim angle As Double
Dim running As Boolean
fontRef = LoadFont("", 18)
panel = CreateBuffer(240, 72)
running = True
If panel <> 0 Then
SetBufferTarget(panel)
Cls()
SetDrawColor(25, 38, 68, 235)
DrawFilledRect(0, 0, 240, 72)
SetDrawColor(80, 200, 255)
DrawRect(0, 0, 240, 72)
ClearBufferTarget()
End If
Do
angle = angle + (60.0 * FrameDelta())
Cls()
SetClipRegion(40, 80, 720, 420)
SetDrawColor(28, 45, 72)
DrawFilledRect(40, 80, 720, 420)
PushDrawState()
SetDrawOffset(400, 290)
SetDrawRotation(angle)
SetDrawColor(255, 185, 65)
DrawFilledRect(-90, -25, 180, 50)
SetDrawColor(255, 255, 255)
DrawCircle(0, 0, 110, 64)
PopDrawState()
ClearClipRegion()
If panel <> 0 Then
DrawBuffer(panel, 24, 16)
End If
SetTextColor(235, 240, 255)
DrawText(fontRef, 40, 530, "ESC exits. The scene is clipped; the HUD is not.")
Flip()
If KeyHit(KEY_ESC) Then
running = False
End If
Loop Until Not running
FreeBuffer(panel)
FreeFont(fontRef)
Choosing the Right State Tool
- Use
PushDrawState/PopDrawStatearound a camera, rotated object, clipped panel, or alternate target. - Use
ClearClipRegionwhen only the clip must be removed. - Use
ClearBufferTargetwhen only off-screen targeting must end. - Use
ResetDrawStateas an explicit return to screen defaults. It does not discard saved stack entries.
Try It Yourself
Turn the rotating rectangle into a clock hand, create a second clipped viewport, and compare circles drawn with 3, 6, 16, and 64 segments.
Functions Introduced
SetDrawColor, DrawCircle, PushDrawState, PopDrawState, SetDrawOffset, SetDrawRotation, SetClipRegion, and CreateBuffer.
Navigation: Previous | Course outline | Next: Input, Assets, and Audio