فهرست منبع

Added snake game.

Brucey 5 سال پیش
والد
کامیت
38e925f211
1فایلهای تغییر یافته به همراه238 افزوده شده و 0 حذف شده
  1. 238 0
      lib.mod/games/snake.bmx

+ 238 - 0
lib.mod/games/snake.bmx

@@ -0,0 +1,238 @@
+SuperStrict
+
+Framework Ray.Lib
+
+Const SNAKE_LENGTH:Int = 256
+Const SQUARE_SIZE:Int = 31
+
+New TSnakeGame.Run()
+
+
+Type TSnakeGame
+
+	Const screenWidth:Int = 800
+	Const screenHeight:Int = 450
+
+	Field framesCounter:Int = 0
+	Field gameOver:Int = False
+	Field pause:Int = False
+
+	Field fruit:TFood = New TFood
+	Field snake:SSnake[SNAKE_LENGTH]
+	Field snakePosition:RVector2[SNAKE_LENGTH]
+	Field allowMove:Int = False
+	Field offset:RVector2
+	Field counterTail:Int = 0
+
+	Method Run()
+		' Initialization (Note windowTitle is unused on Android)
+		'---------------------------------------------------------
+		InitWindow(screenWidth, screenHeight, "sample game: snake")
+
+		InitGame()
+
+		SetTargetFPS(60)
+		'--------------------------------------------------------------------------------------
+
+		' Main game loop
+		While Not WindowShouldClose()    ' Detect window close button or ESC key
+			' Update and Draw
+			'----------------------------------------------------------------------------------
+			UpdateDrawFrame()
+			'----------------------------------------------------------------------------------
+		Wend
+
+		' De-Initialization
+		'--------------------------------------------------------------------------------------
+		UnloadGame()         ' Unload loaded data (textures, sounds, models...)
+
+		CloseWindow()        ' Close window and OpenGL context
+		'--------------------------------------------------------------------------------------
+	End Method
+
+
+	Method InitGame()
+		framesCounter = 0
+		gameOver = False
+		pause = False
+
+		counterTail = 1
+		allowMove = False
+
+		offset.x = screenWidth Mod SQUARE_SIZE
+		offset.y = screenHeight Mod SQUARE_SIZE
+
+		For Local i:Int = 0 Until SNAKE_LENGTH
+			snake[i].position = New RVector2(offset.x/2, offset.y/2)
+			snake[i].size = New RVector2(SQUARE_SIZE, SQUARE_SIZE)
+			snake[i].speed = New RVector2(SQUARE_SIZE, 0)
+
+			If Not i Then
+				snake[i].color = DARKBLUE
+			Else
+				snake[i].color = BLUE
+			End If
+		Next
+
+		For Local i:Int = 0 Until SNAKE_LENGTH
+			snakePosition[i] = New RVector2(0.0, 0.0)
+		Next
+
+		fruit.size = New RVector2(SQUARE_SIZE, SQUARE_SIZE)
+		fruit.color = SKYBLUE
+		fruit.active = False
+	End Method
+
+
+	Method UpdateGame()
+		If Not gameOver Then
+
+			If IsKeyPressed(KEY_P) Then
+				pause = Not pause
+			End If
+			
+			If Not pause Then
+				' Player control
+				If IsKeyPressed(KEY_RIGHT) And snake[0].speed.x = 0 And allowMove Then
+					snake[0].speed = New RVector2(SQUARE_SIZE, 0)
+					allowMove = False
+				End If
+				
+				If IsKeyPressed(KEY_LEFT) And snake[0].speed.x = 0 And allowMove Then
+					snake[0].speed = New RVector2(-SQUARE_SIZE, 0)
+					allowMove = False
+				End If
+				
+				If IsKeyPressed(KEY_UP) And snake[0].speed.y = 0 And allowMove Then
+					snake[0].speed = New RVector2(0, -SQUARE_SIZE)
+					allowMove = False
+				End If
+				
+				If IsKeyPressed(KEY_DOWN) And snake[0].speed.y = 0 And allowMove Then
+					snake[0].speed = New RVector2(0, SQUARE_SIZE)
+					allowMove = False
+				End If
+
+				' Snake movement
+				For Local i:Int = 0 Until counterTail
+					snakePosition[i] = snake[i].position
+				Next
+
+				If (framesCounter Mod 5) = 0 Then
+					For Local i:Int = 0 Until counterTail
+						If Not i Then
+							snake[0].position.x :+ snake[0].speed.x
+							snake[0].position.y :+ snake[0].speed.y
+							allowMove = True
+						Else
+							snake[i].position = snakePosition[i-1]
+						End If
+					Next
+				End If
+
+				' Wall behaviour
+				If ((snake[0].position.x) > (screenWidth - offset.x)) Or ..
+					((snake[0].position.y) > (screenHeight - offset.y)) Or ..
+						(snake[0].position.x < 0) Or (snake[0].position.y < 0) Then
+					gameOver = True
+				End If
+
+				' Collision with yourself
+				For Local i:Int = 1 Until counterTail
+					If (snake[0].position.x = snake[i].position.x) And (snake[0].position.y = snake[i].position.y) Then
+						gameOver = True
+					End If
+				Next
+
+				' Fruit position calculation
+				If Not fruit.active Then
+					fruit.active = True
+					fruit.position = New RVector2(GetRandomValue(0, (screenWidth/SQUARE_SIZE) - 1)*SQUARE_SIZE + offset.x/2, GetRandomValue(0, (screenHeight/SQUARE_SIZE) - 1)*SQUARE_SIZE + offset.y/2)
+
+					For Local i:Int = 0 Until counterTail
+						While (fruit.position.x = snake[i].position.x) And (fruit.position.y = snake[i].position.y)
+							fruit.position = New RVector2(GetRandomValue(0, (screenWidth/SQUARE_SIZE) - 1) * SQUARE_SIZE + offset.x/2, GetRandomValue(0, (screenHeight/SQUARE_SIZE) - 1)*SQUARE_SIZE + offset.y/2)
+							i = 0
+						Wend
+					Next
+				End If
+
+				' Collision
+				If (snake[0].position.x < (fruit.position.x + fruit.size.x) And (snake[0].position.x + snake[0].size.x) > fruit.position.x) And ..
+						(snake[0].position.y < (fruit.position.y + fruit.size.y) And (snake[0].position.y + snake[0].size.y) > fruit.position.y) Then
+					snake[counterTail].position = snakePosition[counterTail - 1]
+					counterTail :+ 1
+					fruit.active = False
+				End If
+
+				framesCounter :+ 1
+			End If
+		Else
+			If IsKeyPressed(KEY_ENTER) Then
+				InitGame()
+				gameOver = False
+			End If
+		End If
+	End Method
+
+
+	' Draw game (one frame)
+	Method DrawGame()
+		BeginDrawing()
+
+			ClearBackground(RAYWHITE)
+
+			If Not gameOver Then
+				' Draw grid lines
+				For Local i:Int = 0 Until screenWidth/SQUARE_SIZE + 1
+					DrawLineV(New RVector2(SQUARE_SIZE*i + offset.x/2, offset.y/2), New RVector2(SQUARE_SIZE*i + offset.x/2, screenHeight - offset.y/2), LIGHTGRAY)
+				Next
+				
+				For Local i:Int = 0 Until screenHeight/SQUARE_SIZE + 1
+					DrawLineV(New RVector2(offset.x/2, SQUARE_SIZE*i + offset.y/2), New RVector2(screenWidth - offset.x/2, SQUARE_SIZE*i + offset.y/2), LIGHTGRAY)
+				Next
+
+				' Draw snake
+				For Local i:Int = 0 Until counterTail
+					DrawRectangleV(snake[i].position, snake[i].size, snake[i].color)
+				Next
+
+				' Draw fruit to pick
+				DrawRectangleV(fruit.position, fruit.size, fruit.color)
+
+				If pause Then
+					DrawText("GAME PAUSED", screenWidth/2 - MeasureText("GAME PAUSED", 40)/2, screenHeight/2 - 40, 40, GRAY)
+				End If
+
+			Else
+				DrawText("PRESS [ENTER] TO PLAY AGAIN", GetScreenWidth()/2 - MeasureText("PRESS [ENTER] TO PLAY AGAIN", 20)/2, GetScreenHeight()/2 - 50, 20, GRAY)
+			End If
+
+		EndDrawing()
+	End Method
+
+	' Unload game variables
+	Method UnloadGame()
+		' TODO: Unload all dynamic loaded data (textures, sounds, models...)
+	End Method
+
+	' Update and Draw (one frame)
+	Method UpdateDrawFrame()
+		UpdateGame()
+		DrawGame()
+	End Method
+End Type
+
+Struct SSnake
+    Field position:RVector2
+    Field size:RVector2
+    Field speed:RVector2
+    Field color:RColor
+End Struct
+
+Type TFood
+    Field position:RVector2
+    Field size:RVector2
+    Field active:Int
+    Field color:RColor
+End Type