Skip to content
Snippets Groups Projects
Verified Commit e8ed2426 authored by Lars Frost's avatar Lars Frost
Browse files

First draft

parents
No related branches found
No related tags found
No related merge requests found
Showing
with 377 additions and 0 deletions
images/sources/ambientCG/3DBread002.jpg

163 KiB

images/sources/ambientCG/Planks037A.jpg

257 KiB

images/sources/ambientCG/Tiles131.jpg

457 KiB

images/sources/blendswap.png

1.16 MiB

images/sources/decimate/collapse-0.05.png

801 KiB

images/sources/decimate/original.png

804 KiB

images/sources/decimate/planar-80°.png

802 KiB

images/sources/polyhaven/chess_set.png

868 KiB

images/sources/polyhaven/chess_set.webp

113 KiB

images/sources/polyhaven/island_tree_02.png

1.04 MiB

images/sources/polyhaven/island_tree_02.webp

281 KiB

images/sources/polyhaven/ship_pinnace.png

378 KiB

images/sources/polyhaven/ship_pinnace.webp

74.7 KiB

#import "template.typ": *
#import "@preview/big-todo:0.2.0": *
#import "@preview/cetz:0.2.2": canvas, draw, tree
#import "@preview/wrap-it:0.1.0": wrap-content
#let title = "Guideline for the RWTH GameJam 2024\nof Fachschaft Mathematik/Physik/Informatik"
#show: doc => apply-template(title, "en", doc)
#outline(indent: auto, depth: 2)
#let add(s) = todo(inline: true, s)
#let info(content) = align(center)[
#box(fill: teal, stroke: black, width: 100%, inset: 1em, content)
]
#let warning(content) = align(center)[
#box(fill: yellow, stroke: black, width: 100%, inset: 1em)[*Warning:* #content]
]
#todo_outline
#todo("Add License CC-BY-SA")
= Organisation
- The GameJam starts on 05.07.2024 at #add("Startuhrzeit").
The final version has to be submitted until 07.07.2024 #add("Enduhrzeit").
- The participants are divided into groups of $4$ people.
- The games are presented by you to the jury on 10.07.2024 from #add("Jury Presentation Time"). 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 to 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.
- 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.
= Introduction: How to develop games?
== What does a game consist of?
To create a game several components are usually needed:
*Graphics*#h(1em)
To show something in the game, you will need graphical assets.
In 2D games, the graphics consist of 2D UI Overlay elements like the menu, buttons, or the score.
The rest of the game graphics are also 2D images and are usually called sprites.
Often, many sprites are stored together in the same file called spritesheet or texture atlas.
#figure(image("images/Characters_SpriteSheet.png"), caption: [
Example character sprites from #link("https://opengameart.org/content/top-down-pokemon-esque-sprites")[Corey Archer]
])
In 3D games, the UI overlay is done the same way as in 2D games, but the the 3D world is more complicated.
#figure(image("images/0AD_example_colored.png"), caption: [
A screenshot from #link("https://play0ad.com/media/screenshots/")[0.A.D.]. The 2D UI Overlay is marked green. Buildings, People, Animals, Ground, Trees, and everything else are 3D models.
])
3D models are usually created in dedicated 3D modelling software like #link("https://www.blender.org/features/")[Blender].
The components are shown in @3dmodel.
The basis is a mesh (usually consisting only of triangles).
Next we need textures:
Each vertex (point) in the mesh has an UV-map attribute,
that tells to which point in the 2D texture it corresponds.
There can be several textures.
The most common textures are
_diffuse_ texture (what color does the point have),
_normal_ map (in which direction is light emitted),
_specular_ map (how much does the reflection use the light color instead of the diffuse color),
but there are several other types.
Models also have a material, with many more properties to change its appearance.
You can see the influence of many common properties in #link("https://docs.blender.org/manual/en/4.0/render/shader_nodes/shader/principled.html")[the blender documentation for physically based rendering (PBR)].
Note, that advanced shadered materials from 3D software are usually not exportable to game engines.
This is in part because lack of standardized formats, but also because games require real-time rendering,
which heavily restricts how complex graphics can be.
For unanimated objects, this is sufficient.
For animated objects we need some more components.
First, we add bones to the model.
Then we say for each combination of bone and vertex,
how much a change in the bone position should influence the position of that vertex (this process is called skinning).
Then for each point and each keyframe, we say what position the bone is in that frame.
This way of animation is called skeletal animation.
#let subpipe(filename) = [#image("images/pipeline/" + filename + ".png", height: 10em, width: 10em, fit: "contain")]
#figure(grid(columns: (1fr, auto, 1fr, auto, 1fr),
align: center + horizon,
row-gutter: (5pt, 15pt, 5pt, 15pt),
rows: (auto, auto, auto, auto),
subpipe("mesh"), [#text("+", size: 70pt)], subpipe("texture"), [#text("=", size: 70pt)], subpipe("textured"),
[*Mesh*], [], [*Texture*], [], [*Textured Model*],
subpipe("bones"), [#text("+", size: 70pt)], subpipe("skinned"), [#text("=", size: 70pt)], subpipe("animated"),
[*Bones*], [], [*Weights per Bone*], [], [*Animatable Model*],
[], [], [], [], [],
), caption: [Typical components of a 3D model]) <3dmodel>
*Sound*#h(1em)
Other assets usually used are sounds.
These are divided into music (in minecraft that would be the constant background music or the menu music)
and sound effects (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.
*Physics*#h(1em)
Most games need some form of physic simulation.
For this, each entity that should be influenced by physics,
gets a component (most commonly a rigid body component).
The components tells the weight of the object, whether its position or rotation is fixed,
how much it bounces (_bounciness_) or is affected by friction (_roughness_).
A physics engine simulates in every frame the physical changes to all entities with physical components.
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.
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_.
*Game engine*#h(1em)
The game engine loads required assets on startup and then enters the main loop.
In every frame, the loop will go through several stages (usually this includes `PreUpdate`, `Update`, and `PostUpdate`),
giving scripts the opportunity to act in these stage.
There is also a special stage called `FixedUpdate`, that is called with a fixed interval between all invocations, independently of the game's frame rate.
After each iteration of the main loop, the engine will render the world to the screen.
During rendering, the engine might also perform post-processing steps like anti-aliasing#footnote[See https://docs.godotengine.org/en/stable/tutorials/3d/3d_antialiasing.html for Godot's options].
== 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.]
Game engines usually use the 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, or a projectile.
But it could also be something more abstract, f.e. an animation or #add("entities without spatial components").
Entities have components, that define the entities functionality.
For example, an arrow projectile could have the following components:
- a transform component, that tells where the entity is located in the world and how it is rotated
- a mesh component with the mesh that should be rendered at the entities position
- a collider, that is used by the physics engine to determine whether the arrow hit some other entity
- a rigid body component, that tells the physics engine to move the entity according to rigid body physics
- a script component, to process events (f.e. the event that the arrow hit another entity)
#add("Godot oder Unity Screenshot: Links ist die Hierachy der Entities zu sehen. Rechts die Components des ausgewählten Entities.")
== Where can I obtain free assets?
=== Blendswap
#link("https://blendswap.com")[Blendswap] is a public exchange platform for blender files,
containing over $25,000$ blender files under (mostly) free licenses.
It is mainly useful to obtain meshes.
Sometimes the materials and textures are useful too,
but not every blend has textures and not all materials are usable in game engines.
#figure(image("images/sources/blendswap.png"), caption: [Blendswap search results when searching the term "arena"])
=== Kenney
#link("https://www.kenney.nl")[Kenney] creates low-poly 3D assets, simple 2D assets and UI elements, and a few sound effects,
and gives them to the public domain.
#figure(grid(
columns: (1fr, 1fr, 1fr),
link("https://www.kenney.nl/assets/pico-8-city", image("images/sources/Kenney/kenney2d.png")),
link("https://www.kenney.nl/assets/fantasy-town-kit", image("images/sources/Kenney/kenney3d.png")),
link("https://www.kenney.nl/assets/game-icons", image("images/sources/Kenney/kenneyUI.png")),
), caption: [Examples for scenes created with Kenney's graphics])
=== OpenGameArt
#link("https://opengameart.org")[OpenGameArt] is a public exchange platform for game assets with free licenses.
It contains 2D and 3D assets, particle effects, music, and sound effects.
A difficulty when using OpenGameArt are the different artistic styles used between the many graphics.
#figure(grid(
columns: (1fr, 1fr, 1fr),
align: horizon,
link("https://opengameart.org/content/modular-terrain", image("images/sources/OGA/hilly_terrain_cliffs_4.png")),
link("https://opengameart.org/content/mage-city-arcanos", image("images/sources/OGA/Arkanos_0.png")),
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])
=== Polyhaven
#link("https://polyhaven.com/")[Polyhaven] is a collection of high-resolution textures and high-poly 3D models.
#figure(grid(
columns: (1fr, 1fr, 1fr),
align: horizon,
link("https://polyhaven.com/a/ship_pinnace", image("images/sources/polyhaven/ship_pinnace.png")),
link("https://polyhaven.com/a/chess_set", image("images/sources/polyhaven/chess_set.png")),
link("https://polyhaven.com/a/island_tree_02", image("images/sources/polyhaven/island_tree_02.png")),
), caption: [Models from polyhaven])
The assets from polyhaven usually have many polygons.
To lower hardware requirements and computation effort, you might want to apply the #link("https://docs.blender.org/manual/nb/4.3/modeling/modifiers/generate/decimate.html")[decimate modifier in blender] to reduce polygon count with minimal distortion.
#figure(grid(
columns: (1fr, 1fr, 1fr),
row-gutter: 5pt,
align: horizon,
image("images/sources/decimate/collapse-0.05.png"),
image("images/sources/decimate/original.png"),
image("images/sources/decimate/planar-80°.png"),
[
*Collapse (ratio = 0.05)\
510 faces*
], [
*Original\
10210 faces*
], [*
Planar (angle limit = 80°)\
394 faces*
]
), caption: [#link("https://polyhaven.com/a/wooden_picnic_table")[Picnic Table] from polyhaven with different decimate settings])
// #figure(
// table(
// columns: (auto, 1fr),
// align: horizon,
// [
// *Collapse (ratio = 0.05)\
// 510 faces*
// ],
// image("images/sources/decimate/collapse-0.05.png"),
// [
// *Original\
// 10210 faces*
// ],
// image("images/sources/decimate/original.png"),
// [*
// Planar (angle limit = 80°)\
// 394 faces*
// ],
// image("images/sources/decimate/planar-80°.png"),
// ),
// 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.],
available under #link("https://creativecommons.org/licenses/by-sa/3.0/")[CC-BY-SA 3.0],
and downloadable from #link("https://github.com/0ad/0ad")#footnote[See files under `binaries/data/mods/*/art`].
However, while high-quality and made for games, the animations can be difficult to integrate technically.
#figure(image("images/sources/0AD_EgyptianPyramids.jpg"), caption: [
A screenshot from #link("https://play0ad.com/media/screenshots/")[0.A.D.] showing the 3D assets in action.
])
= How to Godot
== 3D Navigation
You navigate in the 3D panel, by pressing the right mouse button and move around with WASD.
Press `Shift` to fly faster.
== Physics
You can generate a collider from a `MeshInstance3D` by selecting it, then open the `Mesh` options as seen in @godot-create-mesh.
#figure(image("images/godot/create_mesh.png"), caption: [
"`Create Trimesh Static Body`" creates a static body (position and rotation are locked) with a complex collider.
The other options create dynamic rigid bodies with colliders of varying complexity for this mesh.
]) <godot-create-mesh>
#let simple_mesh_figure = figure(image("images/godot/simple_collider.png"), caption: [
Inspector view, with a simple shape (here a sphere) selected
])
<godot-simple-collider>
#let body = [
Instead of generating colliders, you can also add a child of type `CollisionShape3D` and select a simple shape in its shape attribute.
This is preferable performance-wise.
]
#wrap-content(simple_mesh_figure, body, align: top + left)
== UI
UI components all inherit from the `Control` class.
The simplest layouting is to use `BoxContainer`s or `FlowContainer`s.
They work conceptually similar to flexbox#footnote[https://css-tricks.com/snippets/css/a-guide-to-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.
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.
#add("Image with anchor example")
To theme your UI, set the theme in the topmost UI node.
#add("Theme example")
== How to cross-compile?
= How To Unity
== Obtain Unity and setup a project
- UnityHub
- download a unity version in UnityHub
== Objekte übers Netzwerk synchronisieren
== UI Overlay
== Music und Soundeffekte abspielen
#add("Unity sound manager den ich in Bubbleball hatte ins Template. Schauen wegen Galactic Kittens Lizenz falls noch anwendbar.")
== Input processing
== How to cross-compile?
#let apply-template(title, lang, doc) = {
import "@preview/codly:0.2.0": *
set document(title: title.replace("\n", " - "), author: "Lars Frost")
set page(
paper: "a4",
numbering: "1",
)
set par(leading: 0.6em, justify: true)
show par: set block(spacing: 1.2em)
show heading: set block(above: 2.2em, below: 1em)
show link: it => {
set text(fill: blue)
underline(it)
}
set heading(numbering: "1.1")
show: codly-init.with()
codly()
show table.header: strong
show figure.caption: it => block({
let content = align(left, {
strong[#it.supplement #context(it.counter.display(it.numbering))#it.separator]
it.body
})
let size = measure(content)
// Add borders, so the caption is better distinguishable from the below paragraph.
grid(columns: (0.02 * size.width, auto, 0.02 * size.width),
[],
align(center, {
block({
content
})
}),
[],
)
})
set text(lang: lang)
align(center, [
#text(17pt)[
*#title*
]\
#text(13pt)[
#datetime.today().display()
]
])
doc
}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment