Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- program snake;
- {$mode objfpc}{$H+}
- uses
- {$IFDEF UNIX}
- cthreads,
- {$ENDIF}
- Classes, SysUtils, CustApp, RayLib;
- const
- SNAKE_LENGTH = 256; // максимальная длина змейки
- SQUARE_SIZE = 31; // размер поля
- screenWidth = 800; // задаём высоту и ширину окна
- screenHeight = 450;
- type
- TSnake = record // тело змейки
- position: TVector2;
- size: TVector2;
- speed: TVector2;
- color: TColorB;
- end;
- TFood = record
- position: TVector2;
- size: TVector2;
- active: Boolean;
- color: TColorB;
- end;
- type
- { TRayApplication }
- TRayApplication = class(TCustomApplication)
- protected
- procedure DoRun; override;
- public
- framesCounter: Integer;
- gameOver: Boolean;
- pause: Boolean;
- fruit: TFood;
- snake: array [0..SNAKE_LENGTH] of TSnake;
- snakePosition: array [0..SNAKE_LENGTH] of TVector2;
- allowMove: boolean;
- offset: TVector2;
- counterTail: Integer;
- score: Integer;
- constructor Create(TheOwner: TComponent); override;
- destructor Destroy; override;
- procedure InitGame(); // Initialize game
- procedure UpdateGame(); // Update game (one frame)
- procedure DrawGame(); // Draw game (one frame)
- procedure UnloadGame(); // Unload game
- procedure UpdateDrawFrame(); // Update and Draw (one frame)
- end;
- const AppTitle = 'classic game: snake';
- { TRayApplication }
- constructor TRayApplication.Create(TheOwner: TComponent);
- begin
- inherited Create(TheOwner);
- InitWindow(screenWidth, screenHeight, AppTitle); // for window settings, look at example - window flags
- InitGame();
- SetTargetFPS(60); // Set our game to run at 60 frames-per-second
- end;
- procedure TRayApplication.DoRun;
- begin
- while (not WindowShouldClose) do // Detect window close button or ESC key
- begin
- // Update your variables here
- UpdateDrawFrame();
- end;
- // Stop program loop
- Terminate;
- end;
- destructor TRayApplication.Destroy;
- begin
- UnloadGame(); // Unload loaded data (textures, sounds, models...)
- CloseWindow(); // Close window and OpenGL context
- inherited Destroy;
- end;
- procedure TRayApplication.InitGame();
- var i: Integer;
- begin
- framesCounter := 0;
- gameOver := false;
- pause := false;
- score := 0; //modify
- counterTail := 1;
- allowMove := false;
- offset.x := screenWidth mod SQUARE_SIZE;
- offset.y := screenHeight mod SQUARE_SIZE;
- for i:= 0 to SNAKE_LENGTH - 1 do
- begin
- snake[i].position := Vector2Create( offset.x/2, offset.y/2 );
- snake[i].size := Vector2Create( SQUARE_SIZE, SQUARE_SIZE );
- snake[i].speed := Vector2Create( SQUARE_SIZE, 0 );
- if i = 0 then snake[i].color := DARKBLUE // бошка
- else snake[i].color := BLUE; // тело
- end;
- // for i := 0 to SNAKE_LENGTH - 1 do
- // snakePosition[i] := Vector2Create(0,0);
- fruit.size := Vector2Create( SQUARE_SIZE, SQUARE_SIZE );
- fruit.color := SKYBLUE;
- fruit.active := false;
- end;
- procedure TRayApplication.UpdateGame();
- var i: integer;
- begin
- if (not gameOver) then
- begin
- if (IsKeyPressed(KEY_P)) then pause := not pause;
- if (not pause) then
- begin
- // Player control
- if (IsKeyPressed(KEY_RIGHT) and (snake[0].speed.x = 0) and allowMove) then
- begin
- snake[0].speed := Vector2Create (SQUARE_SIZE, 0 );
- allowMove := false;
- end;
- if (IsKeyPressed(KEY_LEFT) and (snake[0].speed.x = 0) and allowMove) then
- begin
- snake[0].speed := Vector2Create( -SQUARE_SIZE, 0 );
- allowMove := false;
- end;
- if (IsKeyPressed(KEY_UP) and (snake[0].speed.y = 0) and allowMove) then
- begin
- snake[0].speed := Vector2Create( 0, -SQUARE_SIZE );
- allowMove := false;
- end;
- if (IsKeyPressed(KEY_DOWN) and (snake[0].speed.y = 0) and allowMove) then
- begin
- snake[0].speed := Vector2Create( 0, SQUARE_SIZE );
- allowMove := false;
- end;
- // Snake movement
- for i:=0 to counterTail -1 do snakePosition[i] := snake[i].position;
- if ((framesCounter mod 10) = 0) then // speed
- begin
- for i := 0 to counterTail do
- begin
- if (i = 0) then
- begin
- snake[0].position.x += snake[0].speed.x;
- snake[0].position.y += snake[0].speed.y;
- allowMove := true;
- end
- else snake[i].position := snakePosition[i-1];
- end;
- end;
- // 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;
- // Collision with yourself Столкновение с самим собой
- for i := 1 to counterTail -1 do
- begin
- if ((snake[0].position.x = snake[i].position.x) and (snake[0].position.y = snake[i].position.y))
- then gameOver := true;
- end;
- // Fruit position calculation Расчет положения плода
- if (not fruit.active) then
- begin
- fruit.active := True;
- fruit.position := Vector2Create(GetRandomValue (0,(screenWidth div SQUARE_SIZE) - 1) * SQUARE_SIZE + offset.x/2,
- GetRandomValue(0, (screenHeight div SQUARE_SIZE) - 1) * SQUARE_SIZE + offset.y/2);
- i := 0;
- while i < counterTail do
- begin
- while (fruit.position.x = snake[i].position.x) and (fruit.position.y = snake[i].position.y) do
- begin
- fruit.position := Vector2Create( GetRandomValue(0, (screenWidth div SQUARE_SIZE) - 1)*SQUARE_SIZE + offset.x/2,
- GetRandomValue(0, (screenHeight div SQUARE_SIZE) - 1)*SQUARE_SIZE + offset.y/2);
- i := 0; /// Гемоор
- end;
- Inc(i);
- end;
- end;
- // 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
- begin
- snake[counterTail].position := snakePosition[counterTail - 1];
- counterTail += 1;
- fruit.active := false;
- Inc(Score); // mod score
- end;
- Inc(framesCounter);
- end;
- end
- else
- begin
- if (IsKeyPressed(KEY_ENTER)) then
- begin
- InitGame();
- gameOver := false;
- end;
- end;
- end;
- procedure TRayApplication.DrawGame();
- var i: integer;
- begin
- BeginDrawing();
- ClearBackground(RAYWHITE);
- if (not gameOver) then
- begin
- // Draw grid lines Vertical
- for i := 0 to screenWidth div SQUARE_SIZE + 1 do
- DrawLineV( Vector2Create(SQUARE_SIZE*i + offset.x/2, offset.y/2),
- Vector2Create(SQUARE_SIZE*i + offset.x/2, screenHeight - offset.y/2), LIGHTGRAY);
- // horizont
- for i := 0 to screenHeight div SQUARE_SIZE + 1 do
- DrawLineV( Vector2Create(offset.x/2, SQUARE_SIZE*i + offset.y/2),
- Vector2Create(screenWidth - offset.x/2, SQUARE_SIZE*i + offset.y/2), LIGHTGRAY);
- // Draw fruit to pick
- DrawRectangleV(fruit.position, fruit.size, fruit.color);
- // Draw snake
- for i := 0 to counterTail -1 do DrawRectangleV(snake[i].position, snake[i].size, snake[i].color);
- if (pause) then DrawText('GAME PAUSED', screenWidth div 2 - MeasureText('GAME PAUSED', 40) div 2,
- screenHeight div 2 - 40, 40, GRAY);
- end
- else
- begin // modify add score
- DrawText('PRESS [ENTER] TO PLAY AGAIN', GetScreenWidth() div 2 - MeasureText('PRESS [ENTER] TO PLAY AGAIN', 20) div 2,
- GetScreenHeight() div 2 - 50, 20, GRAY);
- // mod
- DrawText(PChar('YOUR SCORE:'+ IntToStr(score)), GetScreenWidth() div 2 - MeasureText(PChar('YOUR SCORE:'+ IntToStr(score)), 20) div 2,
- GetScreenHeight() div 2 - 80, 20, SKYBLUE);
- end;
- EndDrawing();
- end;
- procedure TRayApplication.UnloadGame();
- begin
- // TODO: Unload all dynamic loaded data (textures, sounds, models...)
- end;
- procedure TRayApplication.UpdateDrawFrame();
- begin
- UpdateGame();
- DrawGame();
- end;
- var
- Application: TRayApplication;
- begin
- Application:=TRayApplication.Create(nil);
- Application.Title:=AppTitle;
- Application.Run;
- Application.Free;
- end.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement