Bombardier
Publié : jeu. 01/janv./2026 2:54
Voici le code du premier jeu vidéo que j'ai joué dans les années 80. Bon c'est une adaptation de mes souvenir et il manque les sons et quelque options.
Le but et de détruire les immeuble avant de les toucher.
Le but et de détruire les immeuble avant de les toucher.
Code : Tout sélectionner
; ============================================
; Jeu de Bombardement - Style Années 80
; By MetalOS
; ============================================
EnableExplicit
; Constantes
#SCREEN_WIDTH = 800
#SCREEN_HEIGHT = 600
#GROUND_HEIGHT = 50
#BUILDING_WIDTH = 30
#MAX_BUILDINGS = 25
#HELICOPTER_SIZE = 20
#BOMB_SIZE = 6
#MAX_BOMBS = 10
; Structures
Structure Building
x.i
height.i
width.i
currentHeight.i
fullyDestroyed.i
EndStructure
Structure Helicopter
x.d
y.d
row.i
speed.d
EndStructure
Structure Bomb
x.d
y.d
active.i
velocity.d
EndStructure
; Variables globales
Global Dim Buildings.Building(#MAX_BUILDINGS - 1)
Global Dim Bombs.Bomb(#MAX_BOMBS - 1)
Global Heli.Helicopter
Global Window.i, Canvas.i, Font.i, FontBig.i
Global Score.i, BestScore.i
Global GameOver.i, GameWon.i
Global RowHeight.i
Global BuildingsDestroyed.i
Global TotalBuildings.i
; ============================================
; Initialisation de l'hélicoptère
; ============================================
Procedure InitHelicopter()
Heli\x = #SCREEN_WIDTH - 50
Heli\y = 50
Heli\row = 0
Heli\speed = -3 ; Négatif pour aller de droite à gauche
RowHeight = 30
EndProcedure
; ============================================
; Initialisation des immeubles
; ============================================
Procedure InitBuildings()
Protected i.i, currentX.i = 100
For i = 0 To #MAX_BUILDINGS - 1
Buildings(i)\x = currentX
Buildings(i)\height = Random(150) + 100
Buildings(i)\currentHeight = Buildings(i)\height
Buildings(i)\width = Random(20) + 25
Buildings(i)\fullyDestroyed = #False
currentX + Buildings(i)\width + Random(20) + 20
Next i
BuildingsDestroyed = 0
TotalBuildings = #MAX_BUILDINGS
EndProcedure
; ============================================
; Initialisation des bombes
; ============================================
Procedure InitBombs()
Protected i.i
For i = 0 To #MAX_BOMBS - 1
Bombs(i)\active = #False
Next i
EndProcedure
; ============================================
; Dessiner un immeuble pixelisé
; ============================================
Procedure DrawBuilding(x.i, height.i, width.i, currentHeight.i, fullyDestroyed.i)
Protected i.i, j.i, windowSize.i = 6
If fullyDestroyed Or currentHeight <= 0
ProcedureReturn
EndIf
; Corps de l'immeuble (hauteur actuelle)
DrawingMode(#PB_2DDrawing_Default)
Box(x, #SCREEN_HEIGHT - #GROUND_HEIGHT - currentHeight, width, currentHeight, RGB(50, 50, 50))
; Fenàªtres
For i = 1 To (currentHeight / 18) - 1
For j = 1 To (width / 12) - 1
If Random(100) > 30
Box(x + j * 12 - 4, #SCREEN_HEIGHT - #GROUND_HEIGHT - currentHeight + i * 18, windowSize, windowSize, RGB(255, 255, 150))
Else
Box(x + j * 12 - 4, #SCREEN_HEIGHT - #GROUND_HEIGHT - currentHeight + i * 18, windowSize, windowSize, RGB(70, 70, 70))
EndIf
Next j
Next i
; Contour
DrawingMode(#PB_2DDrawing_Outlined)
Box(x, #SCREEN_HEIGHT - #GROUND_HEIGHT - currentHeight, width, currentHeight, RGB(0, 0, 0))
EndProcedure
; ============================================
; Dessiner l'hélicoptère pixelisé (orienté vers la gauche)
; ============================================
Procedure DrawHelicopter(x.i, y.i)
Protected size.i = #HELICOPTER_SIZE
; Corps principal
DrawingMode(#PB_2DDrawing_Default)
Box(x - size, y - size/2, size * 2, size, RGB(200, 50, 50))
; Cabine
Box(x - size, y - size/2 + 2, size, size - 4, RGB(120, 120, 180))
; Queue (à droite maintenant)
Box(x + size, y - 3, size, 6, RGB(180, 50, 50))
; Rotor principal (animation)
Protected rotorFrame.i = (ElapsedMilliseconds() / 40) % 4
DrawingMode(#PB_2DDrawing_Default)
Select rotorFrame
Case 0, 2
Line(x - size * 1.5, y - size - 3, size * 3, 2, RGB(100, 100, 100))
Case 1, 3
Line(x, y - size * 1.5 - 3, 2, size, RGB(100, 100, 100))
EndSelect
; Rotor de queue
Circle(x + size * 2, y, 4, RGB(100, 100, 100))
; Contour
DrawingMode(#PB_2DDrawing_Outlined)
Box(x - size, y - size/2, size * 2, size, RGB(0, 0, 0))
EndProcedure
; ============================================
; Lancer une bombe
; ============================================
Procedure DropBomb()
Protected i.i
; Vérifier qu'il n'y a pas déjà une bombe active
For i = 0 To #MAX_BOMBS - 1
If Bombs(i)\active
ProcedureReturn ; Ne pas autoriser une nouvelle bombe
EndIf
Next i
; Trouver un slot libre
For i = 0 To #MAX_BOMBS - 1
If Not Bombs(i)\active
Bombs(i)\x = Heli\x
Bombs(i)\y = Heli\y + #HELICOPTER_SIZE
Bombs(i)\velocity = 0
Bombs(i)\active = #True
ProcedureReturn
EndIf
Next i
EndProcedure
; ============================================
; Mise à jour des bombes
; ============================================
Procedure UpdateBombs()
Protected i.i, j.i
Protected gravity.d = 0.4
Protected bombLeft.i, bombRight.i, bombTop.i, bombBottom.i
Protected buildingLeft.i, buildingRight.i, buildingTop.i
Protected damageAmount.i = 30 ; Montant de dégà¢ts par bombe
For i = 0 To #MAX_BOMBS - 1
If Bombs(i)\active
; Appliquer la gravité
Bombs(i)\velocity + gravity
Bombs(i)\y + Bombs(i)\velocity
; Vérifier si la bombe touche le sol
If Bombs(i)\y >= #SCREEN_HEIGHT - #GROUND_HEIGHT
Bombs(i)\active = #False
Continue
EndIf
; Vérifier collision avec les immeubles
bombLeft = Bombs(i)\x - #BOMB_SIZE
bombRight = Bombs(i)\x + #BOMB_SIZE
bombTop = Bombs(i)\y - #BOMB_SIZE
bombBottom = Bombs(i)\y + #BOMB_SIZE
For j = 0 To #MAX_BUILDINGS - 1
If Not Buildings(j)\fullyDestroyed And Buildings(j)\currentHeight > 0
buildingLeft = Buildings(j)\x
buildingRight = Buildings(j)\x + Buildings(j)\width
buildingTop = #SCREEN_HEIGHT - #GROUND_HEIGHT - Buildings(j)\currentHeight
If bombRight >= buildingLeft And bombLeft <= buildingRight
If bombBottom >= buildingTop
; BOOM ! Réduire la hauteur de l'immeuble
Buildings(j)\currentHeight - damageAmount
Bombs(i)\active = #False
; Vérifier si l'immeuble est complètement détruit
If Buildings(j)\currentHeight <= 0
Buildings(j)\currentHeight = 0
Buildings(j)\fullyDestroyed = #True
BuildingsDestroyed + 1
Score + 100
Else
Score + 10 ; Petit bonus pour chaque hit
EndIf
If Score > BestScore
BestScore = Score
EndIf
Break
EndIf
EndIf
EndIf
Next j
EndIf
Next i
EndProcedure
; ============================================
; Mise à jour de l'hélicoptère
; ============================================
Procedure UpdateHelicopter()
; Déplacer l'hélicoptère
Heli\x + Heli\speed
; Si l'hélicoptère sort de l'écran à gauche
If Heli\x < -50
Heli\x = #SCREEN_WIDTH + 50
Heli\row + 1
Heli\y + RowHeight
; Augmenter légèrement la vitesse (en valeur absolue)
If Heli\speed > -6
Heli\speed - 0.2
EndIf
EndIf
EndProcedure
; ============================================
; Vérifier les collisions
; ============================================
Procedure CheckCollisions()
Protected i.i
Protected heliLeft.i = Heli\x - #HELICOPTER_SIZE
Protected heliRight.i = Heli\x + #HELICOPTER_SIZE
Protected heliTop.i = Heli\y - #HELICOPTER_SIZE/2
Protected heliBottom.i = Heli\y + #HELICOPTER_SIZE/2
; Collision avec le sol
If heliBottom >= #SCREEN_HEIGHT - #GROUND_HEIGHT
ProcedureReturn #True
EndIf
; Collision avec les immeubles
For i = 0 To #MAX_BUILDINGS - 1
If Not Buildings(i)\fullyDestroyed And Buildings(i)\currentHeight > 0
If heliRight > Buildings(i)\x And heliLeft < Buildings(i)\x + Buildings(i)\width
If heliBottom > #SCREEN_HEIGHT - #GROUND_HEIGHT - Buildings(i)\currentHeight
ProcedureReturn #True
EndIf
EndIf
EndIf
Next i
ProcedureReturn #False
EndProcedure
; ============================================
; Dessiner le jeu
; ============================================
Procedure DrawGame()
Protected i.i
If StartDrawing(CanvasOutput(Canvas))
; Ciel
DrawingMode(#PB_2DDrawing_Default)
Box(0, 0, #SCREEN_WIDTH, #SCREEN_HEIGHT - #GROUND_HEIGHT, RGB(135, 206, 235))
; Sol avec damier
For i = 0 To #SCREEN_WIDTH / 20
If (i % 2) = 0
Box(i * 20, #SCREEN_HEIGHT - #GROUND_HEIGHT, 20, #GROUND_HEIGHT, RGB(100, 200, 100))
Else
Box(i * 20, #SCREEN_HEIGHT - #GROUND_HEIGHT, 20, #GROUND_HEIGHT, RGB(80, 180, 80))
EndIf
Next i
; Dessiner les immeubles
For i = 0 To #MAX_BUILDINGS - 1
DrawBuilding(Buildings(i)\x, Buildings(i)\height, Buildings(i)\width, Buildings(i)\currentHeight, Buildings(i)\fullyDestroyed)
Next i
; Dessiner les bombes
DrawingMode(#PB_2DDrawing_Default)
For i = 0 To #MAX_BOMBS - 1
If Bombs(i)\active
; Bombe (cercle noir)
Circle(Bombs(i)\x, Bombs(i)\y, #BOMB_SIZE, RGB(0, 0, 0))
; Aileron
Line(Bombs(i)\x - 3, Bombs(i)\y - 8, 6, 0, RGB(50, 50, 50))
EndIf
Next i
; Dessiner l'hélicoptère
If Not GameOver And Not GameWon
DrawHelicopter(Heli\x, Heli\y)
ElseIf GameOver
; Explosion
DrawingMode(#PB_2DDrawing_Default)
Circle(Heli\x, Heli\y, 40, RGB(255, 100, 0))
Circle(Heli\x, Heli\y, 30, RGB(255, 200, 0))
Circle(Heli\x, Heli\y, 20, RGB(255, 255, 100))
EndIf
; Afficher le score et les stats
DrawingMode(#PB_2DDrawing_Transparent)
DrawingFont(FontID(Font))
DrawText(20, 20, "SCORE " + Str(Score), RGB(0, 0, 0))
DrawText(#SCREEN_WIDTH - 220, 20, "MEILLEUR " + Str(BestScore), RGB(0, 0, 0))
DrawText(20, 50, "BÂTIMENTS: " + Str(BuildingsDestroyed) + "/" + Str(TotalBuildings), RGB(0, 0, 0))
; Message Game Over
If GameOver
DrawingFont(FontID(FontBig))
Protected textWidth.i = TextWidth("GAME OVER")
DrawText((#SCREEN_WIDTH - textWidth) / 2, #SCREEN_HEIGHT / 2 - 60, "GAME OVER", RGB(255, 0, 0))
DrawingFont(FontID(Font))
Protected restartText.s = "Appuyez sur ESPACE pour redémarrer"
textWidth = TextWidth(restartText)
DrawText((#SCREEN_WIDTH - textWidth) / 2, #SCREEN_HEIGHT / 2, restartText, RGB(0, 0, 0))
EndIf
; Message Victory
If GameWon
DrawingFont(FontID(FontBig))
textWidth = TextWidth("VICTOIRE!")
DrawText((#SCREEN_WIDTH - textWidth) / 2, #SCREEN_HEIGHT / 2 - 60, "VICTOIRE!", RGB(0, 200, 0))
DrawingFont(FontID(Font))
restartText.s = "Tous les bâtiments sont détruits ! Appuyez sur ESPACE pour rejouer."
textWidth = TextWidth(restartText)
DrawText((#SCREEN_WIDTH - textWidth) / 2, #SCREEN_HEIGHT / 2, restartText, RGB(0, 0, 0))
EndIf
StopDrawing()
EndIf
EndProcedure
; ============================================
; Réinitialiser le jeu
; ============================================
Procedure ResetGame()
InitHelicopter()
InitBuildings()
InitBombs()
Score = 0
GameOver = #False
GameWon = #False
EndProcedure
; ============================================
; Programme principal
; ============================================
; Initialiser
BestScore = 0
; Créer la fenàªtre
Window = OpenWindow(#PB_Any, 0, 0, #SCREEN_WIDTH, #SCREEN_HEIGHT, "Bombardier - Années 80", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
If Window
Canvas = CanvasGadget(#PB_Any, 0, 0, #SCREEN_WIDTH, #SCREEN_HEIGHT)
; Charger les polices
Font = LoadFont(#PB_Any, "Courier New", 18, #PB_Font_Bold)
If Not Font
Font = LoadFont(#PB_Any, "", 18, #PB_Font_Bold)
EndIf
FontBig = LoadFont(#PB_Any, "Courier New", 40, #PB_Font_Bold)
If Not FontBig
FontBig = LoadFont(#PB_Any, "", 40, #PB_Font_Bold)
EndIf
; Ajouter les raccourcis clavier
AddKeyboardShortcut(Window, #PB_Shortcut_Escape, 1)
AddKeyboardShortcut(Window, #PB_Shortcut_Space, 2)
; Initialiser le jeu
ResetGame()
; Timer pour l'animation (60 FPS)
AddWindowTimer(Window, 1, 16)
; Boucle principale
Define Event.i, quit.i = 0
Define spacePressed.i = 0, lastSpaceState.i = 0
Define currentSpaceState.i
Repeat
Event = WaitWindowEvent(10)
Select Event
Case #PB_Event_CloseWindow
quit = 1
Case #PB_Event_Timer
If EventTimer() = 1
If Not GameOver And Not GameWon
UpdateHelicopter()
UpdateBombs()
; Vérifier les collisions
If CheckCollisions()
GameOver = #True
EndIf
; Vérifier la victoire
If BuildingsDestroyed >= TotalBuildings
GameWon = #True
EndIf
EndIf
DrawGame()
EndIf
Case #PB_Event_Menu
Select EventMenu()
Case 1 ; à‰chap
quit = 1
Case 2 ; Espace
If GameOver Or GameWon
ResetGame()
Else
; Larguer une bombe
spacePressed = 1
EndIf
EndSelect
EndSelect
; Détecter l'appui sur Espace pour larguer une bombe
If Not GameOver And Not GameWon
currentSpaceState = GetAsyncKeyState_(#VK_SPACE) & $8000
If currentSpaceState And Not lastSpaceState
DropBomb()
EndIf
lastSpaceState = currentSpaceState
If spacePressed
DropBomb()
spacePressed = 0
EndIf
EndIf
Until quit
; Nettoyage
RemoveWindowTimer(Window, 1)
If Font
FreeFont(Font)
EndIf
If FontBig
FreeFont(FontBig)
EndIf
EndIf
End