Source     Discussion     Modifier     Historique     Forums     Salon IRC

Source:PureTetris.pb

Un article de Games Creators Network.

Adaptation pour PureBasic d'un code Darkbasic

;PB 4.0 
; Adaptation en 20 minutes du code d'Atreid 

If InitSprite() = 0 Or InitKeyboard() = 0
 MessageRequester( "Erreur" , "Impossible d'initialiser DirectX 7 Ou plus" , 0 )
 End
ElseIf OpenScreen( 800 , 600 , 32 , "Tetris" ) = 0
 MessageRequester( "Erreur" , "Impossible d'ouvrir l'écran " , 0 )
 End
EndIf

Declare fctAjoutePiece()
Declare fctBougeAGauche()
Declare fctBougeADroite()
Declare fctTourneAGauche()
Declare fctTourneADroite()
Declare goDown()
Declare dessineGrille(posx.l, posy.l, largeur.l, hauteur.l)
Declare dessinePiece(posx.l, posy.l, largeur.l, hauteur.l)
Declare ToucheLesBords()
Declare collision()

 
;déclaration des variables
;grille(x,y) contiendra un
;1 ou un 0, si la Case de la
;grille est remplie ou non
Global Dim grille(10, 26) 
;construction d'un sol
For t=1 To 10
	grille(t,26)=1
Next t
 
;ce tableau contiendra les pièces.
;pour le moment, on n'a que le T,
;il faudrait faire les autres
Global Dim piece(3,3)
 
;mettre toutes les variables globales
;dans un type rend le code plus propre
Structure t_glob
	pieceX.l
	pieceY.l
	ajoutPiece.l
	deplacePiece.l
EndStructure
Global glob.t_glob
;ajoutPiece : cette variable est incrémentée
;non-stop. Lorsqu'elle est égale à 0, on ajoute
;une pièce.
;lorsqu'on veut ajouter une nouvelle pièce, il
;suffit de lui donner une valeure inférieure à
;zéro. Avec -50, on a environ une seconde
;d'attente avant l'ajout de la pièce
glob\ajoutPiece = -50
;même principe qu'ajoutPiece, mais pour le
;déplacement de la pièce
glob\deplacePiece = -100
 
;gestion du clavier : ces variables stockent
;l'état précédent d'une touche. Comme ça, on
;peut faire des conditions du type de "si
;la touche est pressée mais ne l'était pas
;lors de la dernière boucle"
Define.l lastLeft, lastRight, lastUp ,lastDown 
 
;boucle principale
Repeat
	;comme je l'ai dit plus haut, on incrémente
	;ces variables
	glob\ajoutPiece + 1
	glob\deplacePiece + 1
 	;ajout d'une pièce
	If glob\ajoutPiece = 0
		fctAjoutePiece()
	EndIf
	
	;i glob.ajoutPiece est supérieur à 0, cela
	;signifie qu'il y a une pièce à déplacer, donc
	;on peut s'occupper de cette pièce
	ExamineKeyboard()
	If glob\ajoutPiece > 0
		;déplacement de la pièce
		If lastLeft=0 And KeyboardPushed(#PB_Key_Left)
			fctBougeAGauche()
		EndIf
		lastLeft = KeyboardPushed(#PB_Key_Left)
		If lastRight=0 And KeyboardPushed(#PB_Key_Right)
			fctBougeADroite()
		EndIf
		lastRight = KeyboardPushed(#PB_Key_Right)
		
		;rotation de la pièce
		If lastUp=0 And KeyboardPushed(#PB_Key_Up)
			fctTourneAGauche()
		EndIf
		lastUp = KeyboardPushed(#PB_Key_Up)
		If lastDOwn=0 And KeyboardPushed(#PB_Key_Down)
			fctTourneADroite()
		EndIf
		lastDown = KeyboardPushed(#PB_Key_Down)
	
		;si on presse espace, on descend la pièce
		;rapidement
		If KeyboardPushed(#PB_Key_Space) : glob\deplacePiece = 0 : EndIf
		;quand glob.deplacepiece est égal à 0, on
		;la déplace vers le bas et on met la variable
		;à -50
		If glob\deplacePiece = 0
			glob\deplacePiece = -50
			goDown()
		EndIf
	EndIf
	;affichage
	ClearScreen(0)
	StartDrawing(ScreenOutput())
	dessineGrille(10, 10, 232, 580)
	dessinePiece(10, 10, 232, 580)
	StopDrawing()
	FlipBuffers()
Until KeyboardPushed(#PB_Key_Escape)
 
Procedure dessineGrille(posx.l, posy.l, largeur.l, hauteur.l)
	Define.f w,	h
	;calcul de la largeur et de la hauteur d'une case
	w = (largeur / 10.0)
	h = (hauteur / 25.0)
	;couleur d'affichage de la grille et des boîtes placées
	
	For x=0 To 10
		For y=0 To 25
			;lignes verticales
			LineXY(posx + (w*x), posy, posx+(w*x), posy+hauteur,RGB(96,96,96))
			;lignes horizontales
			LineXY(posx, posy+(y*h), posx+largeur, posy+(y*h),RGB(96,96,96))
			If grille(x,y)=1
				Box(posx+(w*(x-1)), posy+(w*(y-1)), w, h, RGB(96,96,96))
			EndIf
		Next y
	Next x

EndProcedure
 
Procedure delLines()
	;cette commande supprime une ligne, si elle est complète.
	For y=25 To 1 Step -1
		;on compte le nombre de cases remplies
		nbr = 0
		For x=1 To 10
			 nbr + grille(x,y)
		Next x
		;s'il y en a 10...
		If nbr=10
			;... on descend toutes les cases se trouvant
			;en-dessus de la ligne :
			;grille(x,y) = grille(x,y-1)
			For y2=y To 1 Step -1
				For x=1 To 10
					grille(x,y2) = grille(x,y2-1)
				Next x
			Next y2
			y + 1
		EndIf
	Next y
EndProcedure
 
Procedure fctAjoutePiece()
	;cette fonction crée une nouvelle pièce en
	;haut de l'écran.
	
	;sélection aléatoire de la forme de la pièce
	num = Random(5)
	Select num
		Case 0
			Restore _piece_T
		Case 1
			Restore _piece_L
		Case 2
			Restore _piece_L2
		Case 3
			Restore _piece_Z
		Case 4
			Restore _piece_Z2
		Case 5
			Restore _piece_I
	EndSelect
	For x=1 To 3
		For y=1 To 3
			Read piece(x,y)
		Next y
	Next x
	;positionnement de la pièce : en haut et aléatoirement
	;le long de X (c'est plus marrant)
	glob\pieceX = 1+Random(6)
	glob\pieceY = 0
EndProcedure
 
Procedure fctTourneADroite()
	;cette commande effectue une rotation à la pièce. En gros,
	;je transforme
	;ABC    GDA
	;DEF en HEB
	;GHI    IFC
	Dim temporaire(3,3)
	For t=1 To 3
		temporaire(t, 1) = piece(1, (4-t))
		temporaire(3, t) = piece(t, 1)
		temporaire(t, 3) = piece(3, (4-t))
		temporaire(1, t) = piece(t, 3)
	Next t
	temporaire(2,2) = piece(2,2)
	For x=1 To 3
		For y=1 To 3
			piece(x,y) = temporaire(x,y)
		Next y
	Next x
	;je regarde si, à cause de la rotation, il faut décaler
	;la pièce
	ToucheLesBords()
EndProcedure
 
Procedure fctTourneAGauche()
	;idem à fctTourneADroite mais dans l'autre sens
	Dim temporaire(3,3)
	For t=1 To 3
		temporaire(1, t) = piece((4-t), 1)
		temporaire(t, 1) = piece(3, t)
		temporaire(3, (4-t)) = piece(t, 3)
		temporaire(t, 3) = piece(1, t)
	Next t
	temporaire(2,2) = piece(2,2)
	For x=1 To 3
		For y=1 To 3
			piece(x,y) = temporaire(x,y)
		Next y
	Next x
	ToucheLesBords()
EndProcedure
 
Procedure fctBougeAGauche()
	;déplace la pièce vers la gauche
	glob\pieceX - 1
	;elle dépasse le bord de l'écran ?
	If glob\pieceX < -1 : glob\pieceX = -1 : EndIf
	If glob\pieceX = -1
		;Regardons cette même pièce, dans deux orientations
		;différentes :
		;   010      000
		;1: 010   2: 111
		;   010      000
		;c'est une barre. Si elle est verticale, on peut la
		;mettre à la position X=-1, la barre sera alignée le
		;long du bord. Par contre, si elle est horizontale,
		;on ne peut pas la mettre plus à gauche que X=0.
		For t=1 To 3
			If piece(1, t)=1 : glob\pieceX = 0 : EndIf
		Next t
	EndIf
	;si la pièce est en collision avec une autre, on la remet
	;à la position X précédente.
	If collision()=1 : glob\pieceX + 1 : EndIf
EndProcedure
 
Procedure fctBougeADroite()
	;mêmes explications que fctBougeAGauche
	glob\pieceX + 1
	If glob\pieceX > 8 : glob\pieceX = 8 : EndIf
	If glob\pieceX = 8
		For t=1 To 3
			If piece(3, t)=1 : glob\pieceX = 7 : EndIf
		Next t
	EndIf
	If collision()=1 : glob\pieceX - 1 : EndIf
EndProcedure
 
Procedure ToucheLesBords()
	;en gros, cette fonction ne faut que
	;replacer la pièce si elle dépasse l'un
	;des bords
	If glob\pieceX > 8 : glob\pieceX = 8 : EndIf
	If glob\pieceX = 8
		For t=1 To 3
			If piece(3, t)=1 : glob\pieceX = 7 : EndIf
		Next t
	EndIf
	If glob\pieceX < -1 : glob\pieceX = -1 : EndIf
	If glob\pieceX = -1
		For t=1 To 3
			If piece(1, t)=1 : glob\pieceX = 0 : EndIf
		Next t
	EndIf
EndProcedure
 
Procedure dessinePiece(posx.l, posy.l, largeur.l, hauteur.l)
	;cette fonction affiche la pièce sur la grille. Ses paramètres doivent
	;être identiques à ceux de dessineGrille
	Define.f w,	h
	If glob\ajoutPiece > 0
		w = (largeur / 10.0)
		h = (hauteur / 25.0)

		For x=1 To 3
			For y=1 To 3
				If piece(x,y)=1
					Box(posx+(w*((x+glob\pieceX)-1)), posy+(w*((y+glob\pieceY)-1)), w, h, #White)
				EndIf
			Next y
		Next x

	EndIf
EndProcedure
 
Procedure auSol()
	;cette fonction regarde si la pièce est "posée" sur des cases remplies
	For x=1 To 3
		For y=3 To 1 Step -1
			If piece(x,y)=1
				;si une Case de la grille juste sous une Case de
				;la pièce est remplie, la fonction renvoie la
				;valeur 1
				If grille(x+glob\pieceX, y+glob\pieceY+1)=1 : ProcedureReturn #True : EndIf
			EndIf
		Next y
	Next x
	;si aucune Case de la grille n'était remplie, la fonction
	;renvoie la valeur 0
	ProcedureReturn #False
EndProcedure 
 
Procedure collision()
	;regarde si l'une des cases de la pièce est sur l'une
	;des cases remplies de la grille. Si c'est le cas, renvoie
	;1, sinon renvoie 0.
	For x=1 To 3
		For y=1 To 3
			If piece(x,y)=1
				If grille(x+glob\pieceX, y+glob\pieceY)=1 : ProcedureReturn #True : 	EndIf  
			EndIf
		Next y
	Next x
	ProcedureReturn 0
EndProcedure
 
Procedure goDown()
	;si la pièce est posée, on ne descend pas mais...
	If auSol()=1
		;... on "met la pièce dans la grille"
		For x=1 To 3
			For y=1 To 3
				If piece(x,y)=1
					grille(x+glob\pieceX, y+glob\pieceY)=1
				EndIf
			Next y
		Next x
		;on prépare l'ajout d'une nouvelle pièce
		glob\ajoutPiece = -50
		glob\deplacePiece = -100
		;on supprime éventuellement les lignes, s'il le faut
		delLines()
	Else
		;descente de la pièce, si elle n'était pas au sol
		glob\pieceY + 1
	EndIf
EndProcedure
 
;ces données servent à la construction des pièces. 0 indique
;une Case vide, 1 une Case pleine. Le tableau des pièces 
;est de dimension 3x3.
DataSection
_piece_T:
Data.l 0,1,0
Data.l 1,1,1
Data.l 0,0,0
 
_piece_L:
Data.l 1,1,1
Data.l 0,0,1
Data.l 0,0,0
 
_piece_L2:
Data.L 1,1,1
Data.L 1,0,0
Data.l 0,0,0
 
_piece_Z:
Data.l 1,1,0
Data.l 0,1,1
Data.l 0,0,0
 
_piece_Z2:
Data.l 0,1,1
Data.l 1,1,0
Data.l 0,0,0
 
_piece_I:
Data.l 0,1,0
Data.l 0,1,0
Data.l 0,1,0
EndDataSection

 

Rechercher
Installer l'extension de recherche Plus d'informations

 

Comprendre
Tu me dis, j'oublie. Tu m'enseignes, je me souviens. Tu m'impliques, j'apprends. - Benjamin Franklin

 

Partager
La connaissance est la seule chose qui s'accroit lorsqu'on la partage. - Sacha Boudjema

 

Créer
L'imagination est plus importante que la connaissance. - Albert Einstein

 

 

Le wiki en images Le wiki en images Image du mois: «Snowball: un prototype de jeu développé avec NeL.