diff --git a/Makefile b/Makefile index 44ac215e655a16160c2e93f1028444dd58fc4fee..d0fa38820b1ece8c01c2690dd1fbbe628e170c60 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ all: out/Leitfaden.pdf -out/Leitfaden.pdf: leitfaden.typ template.typ +out/Leitfaden.pdf: leitfaden.typ template.typ sections/* mkdir -p out typst compile leitfaden.typ $@ diff --git a/leitfaden.typ b/leitfaden.typ index 35b4a03f390be0e7588a88c854ed889b9caa17bf..723117d0e1bc2334e9aed494ebf1ef1f2b75166a 100644 --- a/leitfaden.typ +++ b/leitfaden.typ @@ -14,21 +14,20 @@ #box(fill: yellow, stroke: black, width: 100%, inset: 1em)[*Warning:* #content] ] -#todo_outline +// #todo_outline = Organisation - The GameJam starts on 05.07.2024 at 18:30. The final version has to be submitted until 07.07.2024 18:30. -- The participants are divided into groups of $4$ people. - The games are presented by you to the jury on 10.07.2024 from 10:00 to 12:00. The jury will then chose the winner. - During the presentation, you will show the games on your own devices. You shall further upload a compiled version, that is distributed to all participants. = Technical Requirements -- The game has to support either Windows (10+) or Ubuntu (24.04.). If possible (your engine supports this, and you used no OS-specific APIs), you shall submit versions for Windows, MacOS, and GNU/Linux. -- If your game is intended for gamepads, it must also be possible to play it with keyboard and mouse. +- The game has to support either Windows (10+) or Ubuntu (24.04). If possible (your engine supports this, and you used no OS-specific APIs), you shall submit versions for Windows, MacOS, and GNU/Linux. +- If your game is intended for gamepads, it must also be possible to play one user with keyboard and mouse. - There will be repositories in the RWTH Gitlab. You also submit your final version there. - We do not mandate a specific engine, though we do recommend to use Godot or Unity. We also recommend you to get familiar with the engine you would like to use beforehand. -- You may only use assets that are available free of charge, and only if the license permits you and us to distribute your unmodified binaries. To keep track of the licensing, we recommend creating a list of all used assets, including assets that don't require attribution. +- You may only use assets and libraries that are available free of charge, and only if the license permits you and us to distribute your unmodified binaries to the other participants. To keep track of the licensing, we recommend creating a list of all used assets, including assets that don't require attribution. = Introduction: How to develop games? @@ -91,8 +90,8 @@ If the relative position between bones is fixed, the connection is called a _joi ), caption: [Typical components of a 3D model]) <3dmodel> *Sound*#h(1em) -Other assets almost always used are sounds. -These are divided into music (in minecraft that would be the constant background music or the menu music) +Other assets needed are sounds. +These are divided into music (in minecraft that would be the background music or the menu music) and sound effects (short: _SFX_) (f.e. the placing of a block, the opening of a door, the click on a menu button). There is usually one music played concurrently, while sound effects are triggered by events and may overlap without being faded into each other. @@ -107,7 +106,7 @@ A physics engine simulates in every frame the physical changes to all entities w It applies forces, moves objects, determines collisions, resolves collisions by calculating impulses, and sends collision events to the object's scripts. Kinds of physics other than rigid body physics (f.e. soft body physics or fluid simulation) are more difficult to use games. In both Godot and Unity, colliders can be generated from arbitrary meshes. -However, it is much more efficient and recommended to use one or multiple simple shapes (spheres, cubes, capsules or other built-in shapes) as colliders for your entities. +However, it is much more efficient to use one or multiple simple shapes (spheres, cubes, capsules or other built-in shapes) as colliders for your entities. Even games that have no physics interaction can need colliders, f.e. to determine which object is selected on a mouse click. The task of determining what colliders a ray (a line going from a point in one direction) will intersect is called _Ray Casting_. @@ -122,12 +121,12 @@ During rendering, the engine might also perform post-processing steps like anti- *Networking*#h(1em) For a $2$-day game jam you should probably stick to the default networking method of your game engine. -However, if you want to scale and have to consider latencies in a highly dynamic game, you would have to put a lot of thought and work into networking. +However, if you want to scale and have to consider latencies in a fast-paced game, you would have to put a lot of thought and work into networking. Some considerations are collected #link("https://github.com/bevyengine/bevy/discussions/8675")[here]. -If you want to do your own networking, I also recommend the networking section of #link("https://youtu.be/ueEmiDM94IE?t=1802")[the GDC presentation from the rocket league developers] on how to design physic-based games. +If you want to do your own networking, I also recommend the networking section of #link("https://youtu.be/ueEmiDM94IE?t=1802")[the GDC presentation from the RocketLeague developers] on how to design physic-based games. == Entity-Component-System (ECS) <ecs> -#info[This section does not apply to Godot. Godot does not use ECS, but uses an object-oriented class hierachy.] +#info[This section does not apply to Godot, which uses an object-oriented class hierachy and not ECS.] Game engines sometimes use a design pattern named entity-component-system (ECS)#footnote[Strictly speaking Unity does not use ECS either, but only the EC-pattern. The systems part is not used in Unity.]. An entity is like an object. It could be a physical object in the game, f.e. the player character, the camera, a light source, a spawn point, or a projectile. @@ -145,6 +144,16 @@ For example, an arrow projectile could have the following components: Screenshot from Unity with the hierachy of entities to the left (the red box) and the components of a PlayerArmature to the right (the blue box). ]) +== Modularization +Like in almost every programming language, it is helpful to group functionality into modules. +For entities, you might have a player entity with several colliders as children, an item in the hand, +a nameplate on top and components for animation, physics, remaining powerup durations, or input processing. +To avoid recreating this for every player from scratch, you should instead make a scene for the player figure, +and instantiate it for every player. +In Godot you just create a regular scene and instantiate it in another scene. +In Unity this not possible. +Instead there are special scenes called _Prefabs_ that can be instantiated in regular scenes. + == Where can I obtain free assets? === Blendswap @@ -180,17 +189,9 @@ A difficulty when using OpenGameArt, are the different artistic styles used betw link("https://opengameart.org/content/fantasy-icon-pack-by-ravenmore-0", image("images/sources/OGA/ravenmore.png")), ), caption: [Examples for scenes created with OpenGameArt assets]) -=== ambientCG -#link("https://ambientcg.com/")[ambientCG] is a collection of public domain high-resolution physically-based materials created by Lennart Demes. -It also contains a few 3D models with textures. - -#figure(grid( - columns: (1fr, 1fr, 1fr), - align: horizon, - link("https://ambientcg.com/view?id=Planks037A", image("images/sources/ambientCG/Planks037A.jpg")), - link("https://ambientcg.com/view?id=Tiles131", image("images/sources/ambientCG/Tiles131.jpg")), - link("https://ambientcg.com/view?id=3DBread002", image("images/sources/ambientCG/3DBread002.jpg")), -), caption: [2 materials and a model from ambientCG]) +=== freesound.org +#link("https://freesound.org/")[freesound.org] is a platform, +containing over $600,000$ sound effects and ambient sounds under (mostly) free licenses. === Polyhaven #link("https://polyhaven.com/")[Polyhaven] is a collection of high-resolution textures and high-poly 3D models. @@ -248,10 +249,6 @@ To lower hardware requirements and computation effort, you might want to apply t // caption: [#link("https://polyhaven.com/a/wooden_picnic_table")[Picnic Table] from polyhaven with different decimate settings], // ) -=== freesound.org -#link("https://freesound.org/")[freesound.org] is a platform, -containing over $600,000$ sound effects and ambient sounds under (mostly) free licenses. - === 0.A.D. There are many 3D models of ancient buildings, animals with animations, and plants, developed for the open-source game #link("https://play0ad.com/media/screenshots/")[0.A.D.], @@ -264,5 +261,17 @@ However, while high-quality and made for games, the animations can be difficult A screenshot from #link("https://play0ad.com/media/screenshots/")[0.A.D.] showing the 3D assets in action. ]) +=== ambientCG +#link("https://ambientcg.com/")[ambientCG] is a collection of public domain high-resolution physically-based materials created by Lennart Demes. +It also contains a few 3D models with textures. + +#figure(grid( + columns: (1fr, 1fr, 1fr), + align: horizon, + link("https://ambientcg.com/view?id=Planks037A", image("images/sources/ambientCG/Planks037A.jpg")), + link("https://ambientcg.com/view?id=Tiles131", image("images/sources/ambientCG/Tiles131.jpg")), + link("https://ambientcg.com/view?id=3DBread002", image("images/sources/ambientCG/3DBread002.jpg")), +), caption: [2 materials and a model from ambientCG]) + #include "sections/godot.typ" #include "sections/unity.typ" \ No newline at end of file diff --git a/sections/godot.typ b/sections/godot.typ index ff7bd92b57c4d58897d509c619b9079b2ff386ab..653b9335b269f8f3949535db50ad02640ccfda40 100644 --- a/sections/godot.typ +++ b/sections/godot.typ @@ -1,13 +1,59 @@ #import "/global.typ": * -= How to Godot +#pagebreak() -== Hints += How to Godot +#link("https://godotengine.org/features/")[Godot] is an open-source game engine under the MIT license. +It uses an object-oriented programming model and has its own scripting language #link("https://docs.godotengine.org/en/stable/tutorials/scripting/gdscript/index.html")[GDScript] with optional typing and python-like syntax. +It also supports #link("https://docs.godotengine.org/en/stable/tutorials/scripting/c_sharp/index.html")[C\#/.NET] +and has native bindings called GDExtensions for C and C++. +There are also several community-maintained language bindings like #link("https://github.com/utopia-rise/godot-kotlin-jvm")[Kotlin] +or #link("https://github.com/Geequlim/ECMAScript")[JavaScript/TypeScript] with a modified base engine or #link("https://docs.godotengine.org/en/stable/tutorials/scripting/gdextension/what_is_gdextension.html#supported-languages")[Rust, Go, and Swift] for GDExtensions. +However, I advise to use GDScript or C\# as they have the best support, have a programming model fitting the engine, and are mainted by the Godot project itself. + +Some general hints for Godot: - All fields accepting numbers also accept math expressions like `sqrt(2) - 1`. +- You navigate in the 3D panel, by pressing the right mouse button and move around with WASD. + Press `Shift` to fly faster. + +== UI +UI components all inherit from the `Control` class. +As simple but powerful layout containers, I recommend using `BoxContainer`s or `FlowContainer`s, +which work conceptually similar to #link("https://css-tricks.com/snippets/css/a-guide-to-flexbox/")[flexbox] in the HTML document model. +`HBoxContainer` and `VBoxContainer` stretch elements along the cross axis and cannot wrap in main direction. +`HFlowContainer` and `VFlowContainer` don't stretch elements along the cross axis and do wrap in main direction. +Elements whose position and size is not determined by the parent container, can use either absolute positions or anchors. + +#figure(image("/images/godot/Anchors.png"), caption: [ + The `VBoxContainer` named `ButtonContainer` in this example is anchored to be in a rectangle with $0.45 dot mono("width")$ as its left border. + The anchor point rectangle is shown by the green pins in the main view. + The rectangle after adding the absolute anchor offsets to each border is shown as orange box in the main view. +]) + +Text colors of `Label`s, space between of container elements, and similar properties are defined by the theme and can be overwritten by individual elements. +To theme your UI, set the theme in the topmost UI node. +#figure(image("/images/godot/Theme.png"), caption: [ + In the right box, you set the theme for a node and all it's children. + On the bottom panel, you have a preview on the left and a panel to edit the properties (f.e. the text color) of UI types on the right. +]) -== 3D Navigation -You navigate in the 3D panel, by pressing the right mouse button and move around with WASD. -Press `Shift` to fly faster. +== Input processing +Godot can handle keyboard, mouse, touchscreen, controllers, joystick, and gamepad inputs. +Controllers, joysticks or gamepads are modelled the same and named _Joypads_ in #link("https://docs.godotengine.org/en/stable/tutorials/inputs/inputevent.html")[the Godot docs]. +Touch devices are processed as mouse events with the `device` property set to $-1$. + +There are two ways to process inputs. +One method is, to handle inputs by setting actions in #path(("Projects", "Project Settings...", "Input Map (Tab)")), +and then question in `_process` whether `is_action_pressed` or `is_action_just_pressed` on the #link("https://docs.godotengine.org/en/stable/classes/class_input.html")[`Input`] singleton is true. +If you have multiple input devices the action map does not distinguish between them, +so instead you have to check for keys with #link("https://docs.godotengine.org/en/stable/classes/class_input.html#class-input-method-is-key-label-pressed")[`is_key_label_pressed`] or #link("https://docs.godotengine.org/en/stable/classes/class_input.html#class-input-method-is-physical-key-pressed")[`is_physical_key_pressed`], or joypad inputs with #link("https://docs.godotengine.org/en/stable/classes/class_input.html#class-input-method-get-axis")[`get_joy_axis`] or #link("https://docs.godotengine.org/en/stable/classes/class_input.html#class-input-method-is-joy-button-pressed")[`is_joy_button_pressed`]. + +To know what gamepads are connected you can either query for them with #link("hhttps://docs.godotengine.org/en/stable/classes/class_input.html#class-input-method-get-connected-joypads")[`get_connected_joypads`] or observe the #link("https://docs.godotengine.org/en/stable/classes/class_input.html#signals")[`joy_connection_changed` signal]. + +As a second method, instead of querying input state, you can also process input events as shown in #link("https://docs.godotengine.org/en/stable/tutorials/inputs/inputevent.html")[the Godot docs]. + +To change a rigid body's velocity directly (not via impulse or force) based on user input, override `state.linear_velocity` in +#link("https://docs.godotengine.org/en/stable/classes/class_rigidbody3d.html#class-rigidbody3d-private-method-integrate-forces")[`_integrate_forces`], don't change physics state in `_process` or `_physics_process`. == Physics You can generate a collider from a `MeshInstance3D` by selecting it, then open the `Mesh` options as shown in @godot-create-mesh. @@ -28,28 +74,16 @@ You can generate a collider from a `MeshInstance3D` by selecting it, then open t ] #wrap-content(simple_mesh_figure, body, align: top + left) -== UI -UI components all inherit from the `Control` class. -As simple but powerful layout containers, I recommend using `BoxContainer`s or `FlowContainer`s, -which work conceptually similar to #link("https://css-tricks.com/snippets/css/a-guide-to-flexbox/")[flexbox] in the HTML document model. -`HBoxContainer` and `VBoxContainer` stretch elements along the cross axis and cannot wrap in main direction. -`HFlowContainer` and `VFlowContainer` don't stretch elements along the cross axis and do wrap in main direction. -Elements whose position and size is not determined by the parent container, can use either absolute positions or anchors. +== Networking +See #link("https://docs.godotengine.org/en/stable/tutorials/networking/high_level_multiplayer.html")[the docs] for an introduction to Godot's high-level networking and sample code to build a client-server based lobby. +The `multiplayer` variable is global, and assigning a client or server peer object to it enables multiplayer via the high-level API. -#figure(image("/images/godot/Anchors.png"), caption: [ - The `VBoxContainer` named `ButtonContainer` in this example is anchored to be in a rectangle with $0.45 dot mono("width")$ as its left border. - The anchor point rectangle is shown by the green pins in the main view. - The rectangle after adding the absolute anchor offsets to each border is shown as orange box in the main view. -]) +If want spawned scenes to replicate on spawn accross the network, you will need #link("https://docs.godotengine.org/en/stable/classes/class_multiplayerspawner.html")[`MultiplayerSpawner`]. +To sync state continuously, you will need a #link("https://docs.godotengine.org/en/stable/classes/class_multiplayersynchronizer.html#class-multiplayersynchronizer")[`MultiplayerSynchronizer`] child for the synchronized node, which has a script, that sets the properties, that should be synced, in the #link("https://docs.godotengine.org/en/stable/classes/class_multiplayersynchronizer.html#class-multiplayersynchronizer-property-replication-config")[`replication_config`]. -Text colors of `Label`s, space between of container elements, and similar properties are defined by the theme and can be overwritten by individual elements. -To theme your UI, set the theme in the topmost UI node. -#figure(image("/images/godot/Theme.png"), caption: [ - In the right box, you set the theme for a node and all it's children. - On the bottom panel, you have a preview on the left and a panel to edit the properties (f.e. the text color) of UI types on the right. -]) +If you sync the positions of rigid bodies, you should #link("https://docs.godotengine.org/en/latest/classes/class_rigidbody2d.html#class-rigidbody2d-property-freeze")[`freeze`] them in #link("https://docs.godotengine.org/en/latest/classes/class_rigidbody2d.html#enum-rigidbody2d-freezemode")[`FREEZE_MODE_KINEMATIC`] on peers that don't control the body. -== Global state / Keep state accross scenes +== Global state / Keep state across scenes https://docs.godotengine.org/en/stable/tutorials/scripting/singletons_autoload.html == How to cross-compile? diff --git a/sections/unity.typ b/sections/unity.typ index 0993d5b8ba98b8fbbb08c4a75e3bf5da15b4f15c..ea455bd17264ab1199dbd6190d1b793d7c7f11e1 100644 --- a/sections/unity.typ +++ b/sections/unity.typ @@ -1,18 +1,17 @@ #import "/global.typ": * +#pagebreak() = How To Unity +Unity is proprietary engine that might be used at no cost for small projects (see the #link("https://unity.com/legal/eula")[EULA] and whatever you have to consent, when downloading a license key). +It only officially supports C\# as scripting language. +Other .NET language might work, but I discourage using them, +and recommend stick to the only language that is well tested, where bugs are fixed, +and that is used in all Unity documentation. -== Obtain Unity and setup a project -Use #link("https://docs.unity3d.com/hub/manual/InstallHub.html")[UnityHub]. +T obtain Unity, use #link("https://docs.unity3d.com/hub/manual/InstallHub.html")[UnityHub]. You will also need to #link("https://unity.com/products")[register as student or personal user]. -== Networking -Use #link("https://github.com/Unity-Technologies/com.unity.netcode.gameobjects/tree/develop")[NetCode GameObjects]. -You can see it in use #link("https://github.com/UnityTechnologies/GalacticKittens/tree/main")[in GalacticKittens]. -See especially the `NetworkManager` component in the `Scenes/Bootstrap`, which has a list of Prefabs that need synchronization over the network. -See also the `Network Object`, `Client Network Transform`, and `Network RigidBody` components in `Prefabs/Net/Player/PlayerShipBase`, which are needed to determine what properties should be synchronized. - -== UI Overlay +== UI The GalacticKittens sample project still uses the old UI system. It is simple to start with, but inflexible and unresponsive. The new system #link("https://docs.unity3d.com/Manual/UIElements.html")[UI Toolkit] builds UIs from XML and CSS with #link("https://css-tricks.com/snippets/css/a-guide-to-flexbox/")[flexbox] for layouts. @@ -88,7 +87,13 @@ UnityEngine.InputSystem.InputSystem.onEvent -= OnInputEvent; that can be triggered on keyboard by WASD keys or with on gamepad with the left stick. ]) -== Global state / Keep state accross scenes +== Networking +Use #link("https://github.com/Unity-Technologies/com.unity.netcode.gameobjects/tree/develop")[NetCode GameObjects]. +You can see it in use #link("https://github.com/UnityTechnologies/GalacticKittens/tree/main")[in GalacticKittens]. +See especially the `NetworkManager` component in the `Scenes/Bootstrap`, which has a list of Prefabs that need synchronization over the network. +See also the `Network Object`, `Client Network Transform`, and `Network RigidBody` components in `Prefabs/Net/Player/PlayerShipBase`, which are needed to determine what properties should be synchronized. + +== Global state / Keep state across scenes Keep entities with `DontDestroyOnLoad` after scene and initialize them in a bootstrapping scene. Again, see #link("https://github.com/UnityTechnologies/GalacticKittens/blob/main/Assets/Scripts/Utility/Singleton.cs")[GalacticKittens].