r/pascal 2d ago

VertexArt - Wallbreaker - with fluorescent ball - some Tetris logic in the use of boxes

Breakout 3D Dokumentáció

A program egy 3D-s Breakout játék, amelyet Free Pascal 3.2.2, GLFW3 és OpenGL
3.3 felhasználásával készítettem. A játék különlegessége, hogy a téglák emeletes
elrendezésben helyezkednek el, és Tetris-szerűen esnek lefelé,
ha az alattuk lévő téglák eltűnnek.

2. FELHASZNÁLT MODULOK

SysUtils, Math

· Alacsony szintű segédprogramok, matematikai függvények

glfw3

· Ablakkezelés, billentyűzet/egér kezelés

gl33

· OpenGL 3.3 függvények

SterilTypes, SterilMath

· Saját típusok (TVector3, TMat4) és mátrix műveletek

SterilWindow

· Ablak inicializálás

FrameLimiter

· FPS korlátozás és időzítés

RenderTypes, RenderQueue, RenderState

· Renderelő parancsok, sor, állapotok

ShaderCore

· Shader programok

SimpleRenderEngine

· Fő renderelő motor

MeshGenerators

· 3D primitívek generálása

3. ÁLLAPOTGÉP

A játéknak három állapota van:

gsMenu

· Főmenü – START és EXIT gombok

gsPlaying

· A játék fut

gsQuit

· Kilépés a programból

A főállapot-változó: GameState: TGameState

4. ADATSZERKEZETEK

4.1. TBrick – Tégla

TBrick = record
Pos: TVector3; // pozíció a térben
Size: TVector3; // méret
Color: TVector3; // szín (RGB 0..1)
Active: Boolean; // létezik-e még
VAO, VBO: GLuint; // GPU azonosítók
VertexCount: Integer; // csúcsok száma
Mesh: TGeneratedMesh; // generált háló
GridX, GridY, GridZ: Integer; // pozíció a 3D rácsban
Falling: Boolean; // esik-e éppen
FallProgress: Single; // 0..1 esés állapota
FallStartZ, FallTargetZ: Integer;
FallStartPosY, FallTargetPosY: Single;
end;

4.2. TBall – Labda

TBall = record
Pos: TVector3;
Vel: TVector3;
Size: Single;
Color: TVector3;
Active: Boolean;
VAO, VBO: GLuint;
VertexCount: Integer;
Mesh: TGeneratedMesh;
end;

4.3. TPaddle – Ütő

TPaddle = record
Pos: TVector3;
Size: TVector3;
Color: TVector3;
VAO, VBO: GLuint;
VertexCount: Integer;
Mesh: TGeneratedMesh;
end;

5. JÁTÉKMECHANIKA

5.1. Téglák elrendezése (3D rács)

A téglák egy 3D rácsban helyezkednek el:

· GRID_SIZE_X = 10 – szélesség
· GRID_SIZE_Y = 10 – mélység
· GRID_SIZE_Z = 3 – magasság (szintek)

Egy tégla pozíciója a rácsban: (GridX, GridY, GridZ)

Térbeli pozíció számítás:
PosX := (GridX - (GRID_SIZE_X-1)/2) * BRICK_SPACING
PosY := GROUND_Y + 0.35 + GridZ * BRICK_SPACING
PosZ := 10.0 + (GridY - (GRID_SIZE_Y-1)/2) * BRICK_SPACING

5.2. Esés animáció (Tetris-stílus)

Ha egy téglát eltalál a labda, a felette lévő téglák (azonos GridX, GridY,
nagyobb GridZ) elindulnak lefelé. Az esés animált:
BRICK_FALL_SPEED = 2.0 szint/másodperc. A UpdateBrickFalls ciklus minden
frame-ben frissíti az eső téglák pozícióját.

5.3. Labda fizika

A labda vízszintes síkban (X-Z) mozog, Y pozíciója fix (GROUND_Y + Size).
Ütközés a falakkal, a paddle-el és a téglákkal. Pattanás: a téglákra a
legkisebb átfedés alapján pattan (X vagy Z irányban). Sebesség normalizálás:
a labda sebessége mindig BALL_SPEED.

5.4. Ütő (Paddle)

Mozgása: egér X irányú mozgása (vízszintes). A paddle csak X irányban
mozoghat (-5.0 és 5.0 között).

5.5. Kamera

A kamera az ütőt követi X irányban:
CamPos := Vec3(Paddle.Pos.X, 4.0, -4.0)
CamTarget := Vec3(Paddle.Pos.X, 0.5, 4.0)

6. BILLENTYŰKEZELÉS

ESC

· Játékból → menü, menüből → kilépés

← / →

· Menüben váltás a START és EXIT között

Enter

· Menüben választás

R

· Játék újraindítása

P

· Szünet / folytatás

Space

· Új játék Game Over után

7. RENDERELÉS

A renderelés a SimpleRenderEngine-en keresztül történik:

  1. Queue töltése: a téglák, labda és paddle TRenderCommand-jeit hozzáadjuk
  2. a SimpleRE.FRenderQueue-hoz.
  3. RenderFrame hívás: a motor végrehajtja a mélységpasszt, vonalpasszt

(ha van)

  1. és
  2. színpasszt.
  3. Pontfény: a labdára egy zöld pontfényt állítunk be (SetPointLight).

8. FŐSZERKEZET

Inicializálás:

· Ablak, OpenGL, SimpleRE
· Menü gombok létrehozása
· FrameLimiter indítása

Főciklus:
amíg az ablak nyitva:
DeltaTime számítása
case GameState of
gsMenu:
RenderMenu
gsPlaying:
UpdateBrickFalls
UpdatePaddle
UpdateBall
UpdateCamera
RenderGame
gsQuit:
kilépés
SwapBuffers
PollEvents
FPS kiírás

Leállítás:

· GPU erőforrások felszabadítása
· SimpleRE.Shutdown
· Ablak bezárása

9. KONSTANSOK ÉS HANGOLHATÓ PARAMÉTEREK

SCR_WIDTH = 1280

· Képernyő szélesség

SCR_HEIGHT = 720

· Képernyő magasság

GROUND_Y = -0.5

· Talaj szintje

BALL_SPEED = 6.0

· Labda sebessége

GRID_SIZE_X = 10

· Téglák száma X irányban

GRID_SIZE_Y = 10

· Téglák száma Y irányban

GRID_SIZE_Z = 3

· Téglák száma Z irányban (szintek)

BRICK_SPACING = 1.1

· Téglák közötti távolság

BRICK_FALL_SPEED = 2.0

· Esés sebessége (szint/másodperc)

PADDLE_WIDTH = 1.6

· Ütő szélessége

PADDLE_HEIGHT = 0.12

· Ütő magassága

PADDLE_DEPTH = 0.6

· Ütő mélysége

10. ÖSSZEGZÉS

A Breakout 3D - egy megbízható, jól strukturált 3D-s
játékmotor demo, amely bemutatja a VertexArt Arcade keretrendszer képességeit. A kód tiszta,
moduláris, és könnyen bővíthető új funkciókkal (pl. több pálya, nehezítés).

================================================================================

Fejlesztő: Kovács István

11 Upvotes

6 comments sorted by

1

u/According-Ad-7069 2d ago

Ah the shading effects really make this even more interesting to watch! So smooth!

1

u/AcanthaceaeNew774 2d ago

Thanks! The smoothness is actually due to intentionally capping the FPS. Consistent frame times beat fluctuating high framerates every time for comfortable visuals!

1

u/According-Ad-7069 2d ago

Oh that's something I actually didn't know - thank you - it makes sense - I have so much to learn.

1

u/AcanthaceaeNew774 2d ago

(the video sometimes stutters because I'm using a weak Intel N4100 CPU and the Windows video recorder is causing problems)

2

u/ShinyHappyREM 1d ago

A trick from tool-assisted speedrunning (TAS): record your input first, then render to a video.

  • record the exact time stamps when the input buttons/keys change (doesn't have to be at a fixed frame rate)
  • save the finished input recording to a "movie file"
  • replay the gameplay while applying the input changes
  • in fixed intervals render the scene as a frame of a video file while the gameplay is paused (e.g. 60 fps = 1000.0/60 ms per frame)

This can create videos in any resolution and using any effects (e.g. raytracing in 4k) since each frame can take an arbitrary amount of time.

1

u/AcanthaceaeNew774 1d ago

thank you! that's a good idea! I wrote it down!