1. Intro
A practical overview of using Castle Game Engine to create 3D and 2D games, and building them for various platforms. The talk is directed at both FPC/Lazarus and Delphi users.
Lost? Contact me:
Example project I made: https://github.com/michaliskambi/salamanca2
2. Monday: Overview - objects, classes, designing 3D levels and 2D UI
What we have covered:
-
Overview of CGE editor,
-
Overview of initial skeleton - code, views, data, ui
-
Views: Example: main menu, play, options - options on top of play, paused or not
-
How to react to event - button click
-
Generate log from code
-
Change objects from code, change any property of published: Add box, change box Translation from code
Basic reaction to button press:
procedure TViewPlay.Start;
begin
....
MyButton.OnClick := {$ifdef FPC}@{$endif} MyButtonClick;
end;
procedure TViewPlay.MyButtonClick(Sender: TObject);
begin
WritelnLog('Button clicked');
// translation is 3D vector, TVector3
Box1.Translation := Box1.Translation + Vector3(0, 1 , 0);
end;
Homework if you want:
-
Learn how to change views from code. Read how to:
-
read https://castle-engine.io/view_events, https://castle-engine.io/views ,
-
examples: e.g. examples/platformer/ , examples/fps_game/ in CGE.
-
3. Tuesday: Designing a level, playing with physics
-
Using Castle Game Engine to design 3D environment from ready pieces
-
Add rigid body physics for environment interactions
Homework if you want:
-
Learn Blender :)
-
Learn how to export from Blender to CGE: https://castle-engine.io/blender
4. Wednesday: Coding, behaviors
What we have covered:
-
Sketchfab ( https://castle-engine.io/sketchfab )
-
Designs ( https://www.youtube.com/watch?v=peiWjieZpbM )
-
Bulllet collisions using physics
Shooting bullets:
function TViewSomething.Press(const Event: TInputPressRelease): Boolean;
var
SphereWithStuff: TCastleTransform;
Pos, Dir, Up: TVector3;
Body: TCastleRigidBody;
begin
Result := inherited;
if Result then Exit;
if Event.IsKey(keyEnter) then
begin
{ Executed when user presses space key. }
WritelnLog('Space key pressed');
//Sphere := TCastleSphere.Create(Self);
//Sphere.Radius := 0.1;
SphereWithStuff := TransformLoad('castle-data:/bullet.castle-transform', Self);
MichalisViewport.Items.Add(SphereWithStuff);
MichalisViewport.Camera.GetWorldView(Pos, Dir, Up);
SphereWithStuff.Translation := Pos + Dir * 10.0;
Body := SphereWithStuff.FindBehavior(TCastleRigidBody) as TCastleRigidBody;
Body.LinearVelocity := Dir * 100.0;
Body.OnCollisionEnter := @CollisionEnter;
Result := true;
end;
end;
Make enemies disappear when bullet hits them:
procedure TViewSomething.CollisionEnter(const CollisionDetails: TPhysicsCollisionDetails);
begin
{ TODO: put enemies in a list (e.g. TCastleTransformList)
to make this code less error-prone. }
if CollisionDetails.OtherTransform = DesignMouseWithHat1 then
DesignMouseWithHat1.Exists := false;
if CollisionDetails.OtherTransform = DesignMouseWithHat2 then
DesignMouseWithHat2.Exists := false;
if CollisionDetails.OtherTransform = DesignMouseWithHat3 then
DesignMouseWithHat3.Exists := false;
end;
Homework if you want:
-
Learn about CGE behaviors, https://castle-engine.io/behaviors , to attach information (like life points) and actions to enemies, and to detect enemies better.
-
See also "3D FPS Game" template for example of using behaviors with enemies.
-
Rework above code to use 1 behavior for each enemy.
5. Thursday: Sound, savegames, using GitHub actions
-
Using spatial and non-spatial sound effects
-
music - OggVorbis (.ogg) or wav
-
sound - emitted by some object in 3d
-
sound - emitted by some object in 3d, from time to time, when user pressed key "keyP"
if Event.IsKey(keyP) then begin SoundSourceManual.Play(SoundAlien); end;
-
-
Saving persistent data (savegames)
-
Windows:
c:/Users/<YOU>/AppData/Local/<name of your project>/<name of your project>.conf
-
Linux:
~/.config/<name of your project>/<name of your project>.conf
procedure TViewSomething.SaveGame(Sender: TObject); var Pos, Dir, Up: TVector3; begin MichalisViewport.Camera.GetWorldView(Pos, Dir, Up); UserConfig.SetVector3('player_position', Pos); UserConfig.SetVector3('player_direction', Dir); UserConfig.SetVector3('player_up', Up); UserConfig.SetValue('player_saved', true); UserConfig.Save; end; procedure TViewSomething.LoadGame(Sender: TObject); var Pos, Dir, Up: TVector3; begin UserConfig.Load; if UserConfig.GetValue('player_saved', false) then begin Pos := UserConfig.GetVector3('player_position', Vector3(0, 0, 0)); Dir := UserConfig.GetVector3('player_direction', Vector3(0, 0, -1)); Up := UserConfig.GetVector3('player_up', Vector3(0, 1, 0)); MichalisViewport.Camera.SetWorldView(Pos, Dir, Up); end; end;
-
Using GitHub Actions ( https://castle-engine.io/github_actions )
Example project I made: https://github.com/michaliskambi/salamanca2
Homework if you want:
-
Deploying the game to Android, integration with Google Play Games
-
Building and testing the game on Android
-
Using CGE services to manage a leaderboard and achievements in Google Play Games
-
Using CGE services to send analytics to GameAnalytics
-
https://castle-engine.io/android, https://castle-engine.io/android_services .
-
-
Pickup items - inventory UI if you want, at least log
-
Shoot instant (see "3D FPS Game template")