Re: [2D] Kanoid : Un casse brique dans un CanvasGadget
Publié : mar. 09/oct./2012 10:19
Sobre, marche nickel, merci pour le partage. 

Forums PureBasic - Français
https://www.purebasic.fr/french/
Bonjour Kwai chang caine. Sobre oui ..... mais ce n'est que le début j’espère.Kwai chang caine a écrit :Sobre, marche nickel, merci pour le partage.
Bonjour Golfy. C'est l'inconvéniant du mode fenetré. j'avoue que je n'ai pas encore de solution à ce souci. A force de jouer on finit par s'habituer à bien laisser la souris sur la canvas.Golfy a écrit :si je devais cependant faire une seule doléance, c'est la disparition du pointeur de la souris... à un moment, elle finit hors de Canvas et le temps de s'en apercevoir, on perd une vie.
Code : Tout sélectionner
;Vitesse Minimum et maximum
MinSpeed = 1
MaxSpeed = 4
Code : Tout sélectionner
;Kanoid Version 1.10 - Falsam
;
EnableExplicit
Enumeration
#ScoreFont
#BrickFont
#BigFont
#BigFontOutLine
#NormalFont
#Mainform
#Grid
;Pour environnement OSX
#VK_N = 78
#VK_PAUSE = 19
#VK_ESCAPE = 27
EndEnumeration
Structure DefBrick
Actif.b ;La brique n'est pas détruite
Col.i ;Position X
Lig.i ;Position Y
life.i ;Nombre de vie de la brique
Color.l ;Couleur : Depend du nombre de vie restant
BonusMalus.i ;Bonus ou Malus (Exemple: Ajout d'une vie, Augmentation de la vitesse de la balle)
Point.i ;Nombre de points ajouté au score quand la brique est détruite
EndStructure
Global NewList Brick.DefBrick()
Define.l Event, WEvent, MEvent, GEvent, TEvent, ActualTime, PreviousTime.d
Global WindowStyle.i = #PB_Window_ScreenCentered|#PB_Window_SystemMenu
;Grid
Global GridW.i, GridH.i
;Raquette : Position X,Y, Largeur/hauteur de la raquette, Vitesse
Global RacquetX.i, RacquetY.i, RacquetW.i, RacquetH.i
;Balle :Position X,Y, Largeur et hauteur de la balle
Global BallX.i, BallY.i, BallR.i, SpeedH.i, SpeedV.i, MinSpeed.i, MaxSpeed.i
Global OldBallX.i, OldBallY.i, OldSpeedV.i, OldSpeedH.i
;Affichage Score : Points obtenus et vie restante, Message
Global Score.i, life.i, Message.s
;Compteurs : Nombre de briques restantes, maximum de scenes , Maximum Random
Global Brick.i, MaxStage.i, MaxRnd.i
;Indicateurs : Brique en mouvement vers le bas, Scene en cours, Glue, Balle inactive, Balle perdu
Global BrickDown.b, Stage.i, Glue.b, Inactif.i, LostBall.i
Procedure Open_MainForm()
OpenWindow(#Mainform, 0, 0, GridW, GridH, "Kanoid", WindowStyle)
CanvasGadget(#Grid, 0, 0, GridW, GridH, #PB_Canvas_Keyboard)
SetActiveGadget(#Grid)
EndProcedure
Procedure MessageBox(Message.s)
DrawingMode(#PB_2DDrawing_AlphaBlend) ;Fond
RoundBox(50, 150, GridW-100, GridH-300, 8, 8, RGBA(245, 245, 245, 155))
DrawingMode(#PB_2DDrawing_Outlined) ;Contour
RoundBox(50, 150, GridW-100, GridH-300, 8, 8, RGB(254, 244, 253))
DrawingMode(#PB_2DDrawing_Transparent)
DrawingFont(FontID(#BigFont))
DrawText((GridW-TextWidth(Message))/2, (GridH-TextHeight(Message))/2, Message, RGB(189, 19, 172))
EndProcedure
Procedure SetDefault()
RacquetW = 101
RacquetH = 10
BallR = 7
SpeedH = 0
SpeedV = 0
Inactif = 0
Glue = #False
LostBall = #False
EndProcedure
Procedure SetBrickColor(life)
Select life
Case 1
ProcedureReturn RGB(204, 205, 242)
Case 2
ProcedureReturn RGB(204, 120, 242)
Case 3
ProcedureReturn RGB(248, 120, 43)
Case 4
ProcedureReturn RGB(255, 199, 64)
EndSelect
EndProcedure
;Correction de la vitesse
Procedure SetSpeed(Value1.i, Value2.i)
Protected Result
If Value1 = 0 And Value2 = 0 ;La balle est stoppée
SpeedH = 0
SpeedV = 0
Result = #True
Else
If Abs(SpeedH + Value1) >= MinSpeed And Abs(SpeedH + Value1) <= MaxSpeed And Value1 <> 0
SpeedH + Value1
Result = #True
Else
Result = #False
EndIf
If Abs(SpeedV + Value2) >= MinSpeed And Abs(SpeedV + Value2) <= MaxSpeed And Value2 <> 0
SpeedV + Value2
Result = #True
Else
Result = #True
EndIf
;La vitesse ne peut pas etre nul
If Abs(SpeedH) = 0
SpeedH = MinSpeed
EndIf
If Abs(SpeedV) = 0
SpeedV = MinSpeed
EndIf
EndIf
ProcedureReturn Result
EndProcedure
Procedure NewStage(Value.i)
Protected Lig.i, Col.i, N.i
ClearList(Brick())
Select Value
Case 1 ;Niveau 1
For Lig = 80 To 200 Step 25
For Col = 50 To 700 Step 50
AddElement(Brick())
Brick()\Actif = #True
Brick()\Col = Col
Brick()\Lig = Lig
Brick()\life = Random(3)+1
Brick()\Color = SetBrickColor(Brick()\life)
Brick()\Point = Brick()\life * 100
Brick()\BonusMalus = Random(MaxRnd)
Next
Next
Case 2 ;Niveau 2
N = 0
For Lig = 50 To 425 Step 25
For Col = 5 To N Step 50
AddElement(Brick())
Brick()\Actif = #True
Brick()\Col = Col
Brick()\Lig = Lig
Brick()\life = Random(3)+1
Brick()\Color = SetBrickColor(Brick()\life)
Brick()\Point = Brick()\life * 100
Brick()\BonusMalus = Random(MaxRnd)
Next
N+50
Next
Case 3 ;Niveau 3
For Lig = 150 To 375 Step 25
If Lig = 150 Or Lig = 375
For Col = 80 To 700 Step 50
AddElement(Brick())
Brick()\Actif = #True
Brick()\Col = Col
Brick()\Lig = Lig
Brick()\life = 4
Brick()\Color = SetBrickColor(Brick()\life)
Brick()\Point = Brick()\life * 100
Brick()\BonusMalus = Random(MaxRnd)
Next
Else
Col=80
AddElement(Brick())
Brick()\Actif = #True
Brick()\Col = Col
Brick()\Lig = Lig
Brick()\life = 4
Brick()\Color = SetBrickColor(Brick()\life)
Brick()\Point = Brick()\life * 100
Brick()\BonusMalus = Random(MaxRnd)
Col=680
AddElement(Brick())
Brick()\Actif = #True
Brick()\Col = Col
Brick()\Lig = Lig
Brick()\life = 4
Brick()\Color = SetBrickColor(Brick()\life)
Brick()\Point = Brick()\life * 100
Brick()\BonusMalus = Random(MaxRnd)
EndIf
Next
For Lig = 175 To 355 Step 25
For Col = 130 To 630 Step 50
AddElement(Brick())
Brick()\Actif = #True
Brick()\Col = Col
Brick()\Lig = Lig
Brick()\life = 2
Brick()\Color = SetBrickColor(Brick()\life)
Brick()\Point = Brick()\life * 100
Brick()\BonusMalus = Random(MaxRnd)
Next
Next
EndSelect
;Nombre de briques à détruire pour le niveau en cours
Brick = ListSize(Brick())
;Initialisation raquette et ball
SetDefault()
EndProcedure
;la raquette renvoie la ball
Procedure BrickCollision()
If Brick()\life = 0
Brick()\Actif = #False
Score + Brick()\Point
Brick - 1
Select Brick()\BonusMalus
Case 0, 1
Message = ""
Case 2 ;Balle plus grande
If BallR < 10
BallR + 1
Message = "Ball + "
EndIf
Case 3;Balle plus petite
If BallR >5
BallR-1
Message = "Ball -"
EndIf
Case 4 ;Augmentation de la vitesse verticale
If SetSpeed(0, 1)
Message = "Speed + 1"
EndIf
Case 5 ;Diminution de la vitesse verticale
If SetSpeed(0, -1)
Message = "Speed - 1"
EndIf
Case 6 ;Les briques commence à descendre
BrickDown = #True
Message = "Bricks down"
Case 7 ;Les briques arretent leurs progressions vers le bas
If BrickDown = #True
BrickDown = #False
Message = "Brick down stop"
EndIf
Case 8 ;Ajout d'une vie
life + 1
Glue = #False
Message = "Life + 1"
Case 9 ;Une vie en moins
If life >3 ;On laisse au moins trois vie
life -1
Message = "Life - 1"
EndIf
Case 10 ;Diminution de la raquette
If RacquetW > 100
RacquetW - 50
Message = "Racquet -"
EndIf
Case 11 ;Augmentation de la raquette
If RacquetW < 401
RacquetW + 50
Glue = #False
Message = "Racquet +"
EndIf
Case 12 ;Colle active
Glue = #True
Message = "Glue Actif"
Case 13 ;Colle inactive
If Glue = #True
Glue = #False
Message = "Glue Inactif"
EndIf
EndSelect
EndIf
Inactif = 0
;Toutes les briques sont détruites
If Brick=0
Stage+1
NewStage(Stage)
Message = "Stage " + Str(Stage) +"/"+ Str(MaxStage)
EndIf
EndProcedure
Procedure Game_Refresh()
If IsGadget(#Grid)
If SpeedH = 0 And SpeedV = 0
;La vitesse de la balle est nulle : Elle est positionnée sur la raquette
If Glue = #False
BallX = RacquetX + RacquetW/2
BallY = RacquetY - BallR
Else
BallX = RacquetX + OldBallX
BallY = RacquetY - BallR
EndIf
Else
;-La balle en cours de déplacement
BallX = BallX-SpeedH
BallY = BallY-SpeedV
EndIf
;-La balle atteint le cotes gauche ou droit du canvas
If BallX <= 0 + BallR Or BallX+BallR >= GridW
SpeedH * -1 ;Inversion de la direction de la balle
Inactif + 1 ;Aucune brique est touché
EndIf
;-La balle atteint le haut du canvas
If BallY <= 40 + BallR
SpeedV * -1 ;Inversion de la direction de la balle
Inactif + 1 ;Aucune brique est touché
EndIf
;-La balle percute une brique
ForEach(Brick())
If Brick()\Actif = #True
;La balle touche le cotes bas ou haut de la brique
If BallX >= Brick()\Col And BallX <= Brick()\Col+40
If BallY <= Brick()\Lig + 25 And BallY > Brick()\Lig
Brick()\life-1 ;La brique perd une vie
Brick()\Color = SetBrickColor(Brick()\life)
SpeedV * -1 ;Inversion de la direction de la balle
BrickCollision()
EndIf
Else
;La balle touche le cotes gauche ou droit de la brique
If BallY >= Brick()\Lig And BallY <= Brick()\Lig+25
If BallX <= Brick()\Col And BallX > Brick()\Col+40
Brick()\life-1 ;La brique perd une vie
Brick()\Color = SetBrickColor(Brick()\life)
SpeedH * -1 ;Inversion de la direction de la balle
BrickCollision()
EndIf
EndIf
EndIf
EndIf
Next
;-La balle atteint le bas du canvas
If (BallY + BallR) >= RacquetY And SpeedH <> 0
Inactif + 1 ;Aucune brique est touché
Message = ""
;Mémorisation des vitesses atteintes
OldSpeedH = SpeedH
OldSpeedV = SpeedV
;Si le malus BrickDown est actif, chaque brique descend de 5 pixels
If BrickDown = #True And LostBall = #False
ForEach(Brick())
If Brick()\Actif
Brick()\Lig = Brick()\Lig + 5
If Brick()\Lig > RacquetY - 25
Message = "The bricks have reached the bottom of the screen !"
Stage + 1
SetDefault()
NewStage(Stage)
EndIf
EndIf
Next
EndIf
;-La balle arrive sur la raquette
If (BallX + BallR) >= RacquetX And BallX < (RacquetX + RacquetW/3) And LostBall = #False
;Extemité gauche de la raquette
If Glue = #False
SpeedV * -1 ;Inversion de la direction de la balle
If SpeedH < 0
SpeedH * -1
EndIf
SetSpeed(2 , 0)
Else
SetSpeed(0, 0)
OldBallX = BallX - RacquetX
EndIf
ElseIf (BallX + BallR) >= RacquetX And BallX <= (RacquetX + RacquetW/2) And LostBall = #False
;Moitié gauche de la raquette
If Glue = #False
SpeedV * -1 ;Inversion de la direction de la balle
If SpeedH < 0
SpeedH * -1
EndIf
Else
SetSpeed(0, 0)
OldBallX = BallX - RacquetX
EndIf
ElseIf BallX > (RacquetX + RacquetW - RacquetW/3) And (BallX - BallR) <= (RacquetX + RacquetW) And LostBall = #False
;Extrémité droite de la raquette
If Glue = #False
SpeedV * -1 ;Inversion de la direction de la balle
If SpeedH > 0
SpeedH * -1
EndIf
SetSpeed(-2, 0)
Else
SetSpeed(0, 0)
OldBallX = BallX - RacquetX
EndIf
ElseIf BallX >=(RacquetX + RacquetW/2) And (BallX - BallR) <= (RacquetX + RacquetW) And LostBall = #False
;Moitié Droite de la raquette
If Glue = #False
SpeedV * -1 ;Inversion de la direction de la balle
If SpeedH > 0
SpeedH * -1
EndIf
Else
SetSpeed(0, 0)
OldBallX = BallX - RacquetX
EndIf
Else
;-La balle est perdu
LostBall = #True
SpeedV = 0 ;On evite le déplacement verticale
SpeedH = 1 ;La balle repart vers le cotes gauche
BallY = GridH - 2*BallR
If BallX = 0
SpeedH = 0
life-1
Message = "Ooooops : Life - 1"
SetDefault()
EndIf
EndIf
EndIf ;End Grid actif
If Inactif > 10 And SpeedV <> 0
Glue = #False
Inactif = 0
SetSpeed(0, 1)
Message = "No broken bricks for a long time : Speed +"
EndIf
;-Mise à jour du canvas
StartDrawing(CanvasOutput(#Grid))
;Efface l'image précédente
Box(0, 0, GridW, GridH, RGB(128, 128, 128))
;Affichage de l'entete
Box(0, 0, GridW, 40, RGB(241, 215, 221))
;Affichage des briques
ForEach Brick()
If Brick()\Actif = #True
DrawingMode(#PB_2DDrawing_Default)
RoundBox(Brick()\Col, Brick()\Lig, 45, 20, 5, 5, Brick()\Color)
DrawingMode(#PB_2DDrawing_Outlined)
RoundBox(Brick()\Col, Brick()\Lig, 45, 20, 5, 5, RGB(0, 0, 0))
DrawingMode(#PB_2DDrawing_Transparent)
DrawingFont(FontID(#NormalFont))
DrawText(Brick()\Col+(45-TextWidth(Str(Brick()\life)))/2, Brick()\Lig+2, Str(Brick()\life), RGB(0, 0, 0))
EndIf
Next
;Affichage de la raquette
DrawingMode(#PB_2DDrawing_Default)
If Glue = #True
DrawingMode(#PB_2DDrawing_AlphaBlend)
RoundBox(RacquetX-5, RacquetY-5, RacquetW+10, RacquetH+5, 4, 4, RGBA(242, 161, 239, 155))
EndIf
DrawingMode(#PB_2DDrawing_Default)
RoundBox(RacquetX, RacquetY, RacquetW, RacquetH, 4, 4, RGB(169, 169, 169))
DrawingMode(#PB_2DDrawing_Outlined)
RoundBox(RacquetX, RacquetY, RacquetW, RacquetH, 4, 4, RGB(0, 0, 0))
;Affichage de la balle
DrawingMode(#PB_2DDrawing_Default)
Circle(BallX, BallY, BallR, RGB(255, 140, 0))
DrawingMode(#PB_2DDrawing_Outlined)
Circle(BallX, BallY, BallR, RGB(0, 0, 0))
;Affichage du bandeau (Score, Message, Vie)
DrawingMode(#PB_2DDrawing_Transparent)
DrawingFont(FontID(#ScoreFont))
DrawText(10, 10, "Score : " + Str(Score), RGB(0,0,0))
DrawText(150, 10, Message, RGB(0,0,0))
DrawText(GridW-80, 10, "Life : " + Str(life), RGB(0,0,0))
;**Debug Vitesse et position de la balle ***
;DrawText(10, GridH-100, "Speed : " + Str(Abs(SpeedH))+"/"+Str(Abs(SpeedV))+" X/Y : "+Str(BallX)+"/"+Str(BallY), RGB(0,0,0))
;Message
If life = 0
BallR = 0
MessageBox("Game Over !")
EndIf
If Stage > MaxStage
MessageBox("Winner")
EndIf
StopDrawing()
EndIf
EndProcedure
Procedure Game_Start()
;Fonts
LoadFont(#NormalFont, "Arial", 10)
LoadFont(#ScoreFont, "Arial", 12)
LoadFont(#BigFont, "Arial", 70)
LoadFont(#BigFontOutLine, "Arial", 75)
;Affichage fenetre & canvas
GridW = 800
GridH = 700
If Not IsWindow(#Mainform)
Open_MainForm()
EndIf
SetDefault()
;Positionnement de la raquette (Px)
RacquetX = (GridW-RacquetW)/2
RacquetY = GridH-50
;Score
Score = 0
life = 3
;Bonus Malus
MaxRnd = 14
;Vitesse Minimum et maximum
MinSpeed = 1
MaxSpeed = 4
;Scene
Stage = 1
MaxStage =3
;Premiere scene
NewStage(1)
EndProcedure
Procedure Game_Stop()
End
EndProcedure
Game_Start()
PreviousTime = ElapsedMilliseconds()
Repeat
Event = WindowEvent()
WEvent = EventWindow()
MEvent = EventMenu()
GEvent = EventGadget()
TEvent = EventType()
ActualTime = ElapsedMilliseconds()
If ActualTime - PreviousTime > (1000 / 60) ; Rafraichissement à 60Hz
Game_Refresh()
PreviousTime + (1000 / 60)
ElseIf Event = 0
Delay(1)
EndIf
Select Event
Case #PB_Event_Gadget
Select GEvent
Case #Grid
Select TEvent
Case #PB_EventType_LeftButtonDown
If SpeedH = 0 And life > 0 And Brick > 0
;La balle n'est pas encore lancé
If Glue = #True
;La colle est actif (Glue = #True)
SpeedH = -OldSpeedH
SpeedV = -OldSpeedV
Else
;La colle est pas active (Glue = #False)
SetSpeed(MinSpeed, MinSpeed+2)
If BallX > GridW/2
If SpeedH > 0
SpeedH * -1
EndIf
EndIf
EndIf
;Je force la glue pour test
;Glue=#True
EndIf
Case #PB_EventType_RightButtonDown
SpeedH * -1
Case #PB_EventType_MouseMove
;Cache le cursor
SetGadgetAttribute(#Grid, #PB_Canvas_Cursor, #PB_Cursor_Invisible)
;Récupération de la position horizontale (Cotes gauche) de la raquette
RacquetX = GetGadgetAttribute(#Grid, #PB_Canvas_MouseX)
If RacquetX + RacquetW > GridW
RacquetX = GridW-RacquetW
EndIf
Case #PB_EventType_KeyDown
Select GetGadgetAttribute(#Grid, #PB_Canvas_Key)
Case #VK_N ;Nouvelle partie
Game_Start()
Case #VK_PAUSE ;Partie en pause
SetSpeed(0,0)
Case #VK_ESCAPE ;Fin du jeu
Game_Stop()
EndSelect
EndSelect ;End TEvent
EndSelect ;End Gevent
Case #PB_Event_CloseWindow
Game_Stop()
EndSelect ;End Event
ForEver
Oui ouifalsam a écrit : @MindPhaser : Dans ta signature tu as deux types d'environnement. Tu fais des tests sous OSx ?