Wer, Wie, Was?
Spieleprogrammierung in Kotlin
Tobse Fritz
![](https://s3.amazonaws.com/media-p.slid.es/uploads/909801/images/6042155/Schwellwert_2.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/909801/images/8545791/mechanical-arm_1f9be.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/909801/images/8545792/smiling-face-with-sunglasses_1f60e.png)
ITscope GmbH
Java Entwickler
Kotlin Fanboy
Hobby Fotograf
Gaming Nerd
3D Printer
Daddy
Mit ITscope vereinfachen Systemhäuser
Ihre Verkaufsprozesse & IT Beschaffung
![](https://s3.amazonaws.com/media-p.slid.es/uploads/909801/images/9040169/pasted-from-clipboard.png)
WO
WO
![](https://s3.amazonaws.com/media-p.slid.es/uploads/909801/images/9040199/pasted-from-clipboard.png)
WO
![](https://s3.amazonaws.com/media-p.slid.es/uploads/909801/images/9040199/pasted-from-clipboard.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/909801/images/9040229/Außenansicht_ITscope_Büro.jpg)
WO
![](https://s3.amazonaws.com/media-p.slid.es/uploads/909801/images/9040229/Außenansicht_ITscope_Büro.jpg)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/909801/images/9040260/PSX_20200724_163308.jpg)
2003
Gründung
62
Mitarbeiter
7.800
Aktive Nutzer
420+
Distributoren
3 Mio
Produkte
Fakten
Tech Stack
Spieleprogrammierung in Kotlin
My Games
![](https://s3.amazonaws.com/media-p.slid.es/uploads/909801/images/8623000/Hospital_Game.gif)
Hospital
![](https://s3.amazonaws.com/media-p.slid.es/uploads/909801/images/8623001/Screensoht.jpg)
Kathis Kleiner Sattelit
My Games
Swing Plus Remake
![](https://s3.amazonaws.com/media-p.slid.es/uploads/909801/images/8623005/XSwingPlus.jpg)
My Games
Hit Klack Remake
![](https://s3.amazonaws.com/media-p.slid.es/uploads/909801/images/8623002/Hitclack_Game_Console_-_s.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/909801/images/8623003/Hitclack_Game_-s.png)
My Games
My Games
![](https://s3.amazonaws.com/media-p.slid.es/uploads/909801/images/8623312/MobilePreview.png)
Candy Crush Clone
Magic Maze Online Multiplayer
![](https://s3.amazonaws.com/media-p.slid.es/uploads/909801/images/8623007/MagicMaze.png)
My Games
K
or
G
E
K
or
otlin
G
E
K
or
otlin
C
outines
G
E
K
or
otlin
C
outines
G
E
ame
ngine
K
or
G
E
Kotlin Multiplatform
JVM
Win
Mac
Linux
JS
Browser
Native
Android
IOS
K
or
G
E
JVM
Win
Mac
Linux
JS
Browser
Win
Mac
Linux
Native
Android
IOS
Common
Code
Kotlin
Compiler
LLVM IR
Kotlin Multiplatform
K
or
G
E
Kotlin Multiplatform
JVM
Win
Mac
Linux
JS
Browser
Win
Mac
Linux
Native
Android
IOS
KorGE
Libs
Common
Code
Kotlin
Compiler
LLVM IR
K
or
G
E
Kotlin Multiplatform
JVM
Win
Mac
Linux
JS
Browser
Win
Mac
Linux
Native
Android
IOS
KorGE
Libs
Common
Code
![](https://s3.amazonaws.com/media-p.slid.es/uploads/909801/images/8623080/korau.png)
expect
expect fun play(file: Sound)
actual
actual
actual
actual
actual
K
or
G
E
.org
K
or
G
E
- 2D Game Engine
- Open Source
- Native Multiplatform
- Live Debugging
- IDE Integration
- Visual editor
- 100 % Kotlin
⭐Features
Kotlin
Spiele... warum in
Kotlin
- Prägnant
- Sicher
- Interoperabel
- Optimales Tooling
- Frei & OpenSource
Features
Kotlin
public class Person {
private final String firstName;
private final String lastName;
private final LocalDate birthDay;
public Person(String firstName, String lastName,
LocalDate birthDay) {
this.firstName = firstName;
this.lastName = lastName;
this.birthDay = birthDay;
}
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
public LocalDate getBirthDay() {
return birthDay;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
return Objects.equals(firstName, person.firstName) &&
Objects.equals(lastName, person.lastName) &&
Objects.equals(birthDay, person.birthDay);
}
@Override
public int hashCode() {
return Objects.hash(firstName, lastName, birthDay);
}
@Override
public String toString() {
return "Person{" +
"firstName='" + firstName + '\'' +
", lastName='" + lastName + '\'' +
", birthDay=" + birthDay +
'}';
}
}
data class PersonK(
val firstName: String,
val lastName: String,
val birthDay: LocalDate
)
Java
Kotlin
Prägnanz
Kotlin
public class RectangleJava {
private int x = 0;
private int y = 0;
private int width = 0;
private int height = 0;
public boolean contains(int x, int y) {
var inWidth = (x >= this.x) && (x <= this.x + width);
var inHeight = (y >= this.y) && (y <= this.y + height);
return inWidth && inHeight;
}
}
Java
Kotlin
public class RectangleKotlin {
private val x = 0;
private val y = 0;
private val width = 0;
private val height = 0;
public fun contains(x: Int, y: Int): Boolean {
val inWidth = (x >= this.x) && (x <= this.x + width);
val inHeight = (y >= this.y) && (y <= this.y + height);
return inWidth && inHeight;
}
}
Kotlin
public fun public private fun
new
;
Kotlin
class RectangleKotlinNice {
private val x = 0
private val y = 0
private val width = 0
private val height = 0
fun contains(x: Int, y: Int): Boolean {
val inWidth = x in (x .. this.x + width)
val inHeight = y in (y .. this.y + height)
return inWidth && inHeight
}
}
Kotlin
Kotlin
- Prägnant
- Sicher
- Interoperabel
- Optimales Tooling
- Frei & OpenSource
Features
Kotlin
Prägnant
Sicher
Interoperabel
Optimales Tooling
Frei & OpenSource
Inline Classes
Extensions
Contracts
Operator Overloading
Gradle DSL
Data Classes
Coroutines
KorGE
The Tree Game
![](https://s3.amazonaws.com/media-p.slid.es/uploads/909801/images/8642954/2021-06-04_21h40_26.png)
KorGE
The Tree Game
The Tree Game
Lesson learned
![](https://s3.amazonaws.com/media-p.slid.es/uploads/909801/images/8643036/background.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/909801/images/8643037/tree.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/909801/images/8643038/apple.png)
image(backgroundBitmap){
size(gameWidth, gameHeight)
}
image(treeBitmap).centerOnStage()
Image(appleBitmap).addTo(this)
container {
name = "Happy Sun"
circle(radius = 50.0, fill = YELLOW)
circle(radius = 8.0, fill = BLACK).position(60, 20)
circle(radius = 8.0, fill = BLACK).position(24, 20)
circle(radius = 10.0, fill = RED).position(50, 60)
position(50, 50)
}
The Tree Game
private suspend fun hit() {
tween(this::y[gameHeight],
time = 1.seconds, easing = EASE_IN)
tween(this::rotation[Random[-40, 40].degrees],
time = 100.milliseconds, easing = EASE_IN)
}
![](https://s3.amazonaws.com/media-p.slid.es/uploads/909801/images/8643420/pasted-from-clipboard.png)
EASE_IN_ELASTIC EASE_OUT_ELASTIC EASE_OUT_BOUNCE LINEAR EASE_IN EASE_OUT EASE_IN_OUT EASE_OUT_IN EASE_IN_BACK EASE_OUT_BACK
EASE_IN_OUT_BACK EASE_OUT_IN_BACK EASE_IN_OUT_ELASTIC EASE_OUT_IN_ELASTIC EASE_IN_BOUNCE EASE_IN_OUT_BOUNCE EASE_OUT_IN_BOUNCE EASE_IN_QUAD EASE_OUT_QUAD EASE_IN_OUT_QUAD
Lesson learned
The Tree Game
val bus = GlobalBus()
class GameOverEvent()
private fun eatApple() {
if (apples == 0) {
bus.send(GameOverEvent())
}
}
bus.register<GameOverEvent> {
text("Game Over", textSize = 64.0).centerOnStage()
}
private suspend fun hit() {
tween(this::y[gameHeight],
time = 1.seconds, easing = EASE_IN)
tween(this::rotation[Random[-40, 40].degrees],
time = 100.milliseconds, easing = EASE_IN)
}
Game Over
Lesson learned
The Tree Game
![](https://s3.amazonaws.com/media-p.slid.es/uploads/909801/images/8643038/apple.png)
class Bird(...){
init {
onClick {
hit()
}
}
class Bird(...){
init {
onCollision(filter = { it is Image}) {
if (it.name == "apple") {
it.removeFromParent()
eatApple()
}
}
}
}
Lesson learned
resourcesVfs["bird.mp3"].readSound().play()
The Tree Game
JS
Browser
runAndroidRelease
runJs
runJvm
runNativeRelease
Native
Android
Native
IOS
Win
Mac
Linux
Native
JVM
Win
Mac
Linux
Tasks > run
iosRunSimulatorDebug
Lesson learned
The Tree Game
Coming soon
🆕
Jetzt mit Hörnchen!
The Tree Game
gamepad.down(0, GameButton.LEFT) {
x -= 40
}
gamepad.down(0, GameButton.RIGHT) {
x += 40
}
gamepad.down(0, GameButton.BUTTON0) {
shoot()
}
keys {
down {
if (it.key == Key.LEFT) {
x -= 20
}
if (it.key == Key.RIGHT) {
x += 20
}
if (it.key == Key.SPACE) {
shoot()
}
}
}
Coming soon
Box2D
solidRect(50, 50, Colors.RED)
solidRect(50, 50, Colors.RED)
solidRect(50, 50, Colors.RED)
solidRect(600, 100, Colors.WHITE)
Box2D
solidRect(50, 50, Colors.RED)
.registerBodyWithFixture(type = BodyType.DYNAMIC, density = 2, friction = 0.01)
solidRect(50, 50, Colors.RED)
.registerBodyWithFixture(type = BodyType.DYNAMIC)
solidRect(50, 50, Colors.RED)
.registerBodyWithFixture(type = BodyType.DYNAMIC)
solidRect(600, 100, Colors.WHITE)
.registerBodyWithFixture(
type = BodyType.STATIC,
friction = 0.2
)
Box2D
solidRect(50, 50, Colors.RED)
.registerBodyWithFixture(type = BodyType.DYNAMIC, density = 2, friction = 0.01)
solidRect(50, 50, Colors.RED)
.registerBodyWithFixture(type = BodyType.DYNAMIC)
solidRect(50, 50, Colors.RED)
.registerBodyWithFixture(type = BodyType.DYNAMIC)
solidRect(600, 100, Colors.WHITE)
.registerBodyWithFixture(
type = BodyType.STATIC,
friction = 0.2
)
onClick {
val pos = it.currentPosLocal
solidRect(50, 50, Colors.RED).position(pos.x, pos.y).rotation(randomAngle())
.registerBodyWithFixture(type = BodyType.DYNAMIC)
}
fun randomAngle(): Angle = Random.nextInt(0, 90).degrees
Box2D
![](https://s3.amazonaws.com/media-p.slid.es/uploads/909801/images/8623081/korui.png)
Kor
UI
val container = fixedSizeContainer(width, height)
container.korui {
vertical {
layoutChildrenPadding = 2
horizontal {
preferredWidth = 100.percent
button("HELLO", {
preferredWidth = 70.percent
})
button("WORLD", {
preferredWidth = 30.percent
preferredHeight = 32.pt
})
}
button("TEST")
checkBox("CheckBox", checked = true)
comboBox("test", listOf("test", "demo"))
}
}
DSL
![](https://s3.amazonaws.com/media-p.slid.es/uploads/909801/images/8623081/korui.png)
Kor
UI
Absolute Positionierung
uiButton(256.0, 32.0) {
text = "Disabled Button"
position(128, 128)
}
val emitter = resourcesVfs["particle2.pex"].readParticleEmitter()
particleEmitter(emitter)
Particles
![](https://s3.amazonaws.com/media-p.slid.es/uploads/909801/images/8643289/2021-06-04_23h37_35.png)
Particles
Hiero
![](https://s3.amazonaws.com/media-p.slid.es/uploads/909801/images/8643349/Hiero_Bitamap_Font__Editpr.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/909801/images/8643312/pasted-from-clipboard.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/909801/images/8643313/pasted-from-clipboard.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/909801/images/8643314/pasted-from-clipboard.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/909801/images/8643316/pasted-from-clipboard.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/909801/images/8643327/pasted-from-clipboard.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/909801/images/8643334/pasted-from-clipboard.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/909801/images/8643327/pasted-from-clipboard.png)
Axiom Verge
Brigador
2016
2015
Edit Worlds
Performance
10K
Performance
10K
1Mio
100K
need
more?
Performance
![](https://s3.amazonaws.com/media-p.slid.es/uploads/909801/images/8623727/doom-eternal-3.jpg)
https://store.steampowered.com/app/379720/DOOM/
- 😁Weil es Spaß macht
- 💡 Programmier-Skills verbessern
- 🔭Neues ausprobieren
- 👨👦Für Entwicklung begeistern
- 😊Wertschätzung für eigene Arbeit
- 🤝Zusammenarbeit im Team
- 👾Kleine abgeschlossene Projekte
Warum ein Spiel programmieren?
![](https://s3.amazonaws.com/media-p.slid.es/uploads/909801/images/8623488/indie-game-jams-header.jpg)
https://produktivkeller.com/game-jams
29 - 31 Oktober 2021
![](https://s3.amazonaws.com/media-p.slid.es/uploads/909801/images/8623554/ggj-logo.png)
https://globalgamejam.org
28 - 30 Januar 2022
28 000 creators
104 Countries
6 000 Games
Warum ein Spiel programmieren?
Warum ein Spiel programmieren?
![](https://s3.amazonaws.com/media-p.slid.es/uploads/909801/images/8623488/indie-game-jams-header.jpg)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/909801/images/8623610/game_jam_poster10-art.jpg)
Jetzt bist Du dran!
https://globalgamejam.org/news/poster-showcase-2018-0
![](https://s3.amazonaws.com/media-p.slid.es/uploads/909801/images/8623610/game_jam_poster10-art.jpg)
git clone https://github.com/korlibs/korge-hello-world
![](https://s3.amazonaws.com/media-p.slid.es/uploads/909801/images/8623610/game_jam_poster10-art.jpg)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/909801/images/8623610/game_jam_poster10-art.jpg)
Tools
- Tiled (Level Editor)
- Spine (Paid, Character Animation)
- Free Sprite Sheet Packer (Web App)
- Texture Packer (Paid)
- Hiero (Bitmap Font Editor)
-
KorGE IDE Plugin
- Visual Editor
- Particle Editor
- Level Editor
![](https://s3.amazonaws.com/media-p.slid.es/uploads/909801/images/8623610/game_jam_poster10-art.jpg)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/909801/images/9047582/pasted-from-clipboard.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/909801/images/9046343/Team.jpg)
Werde Teil der ITscope Familie
Werde Teil der ITscope Familie
![](https://s3.amazonaws.com/media-p.slid.es/uploads/909801/images/9046343/Team.jpg)
Java Backend Developer (m/w/d)
Festanstellung, Vollzeit
Informatikstudenten (m/w/d)
Werkstudent, Teilzeit
Werkstudent (m/w/d) im Marketing
Werkstudent, Teilzeit
Werde Teil der ITscope Familie
![](https://s3.amazonaws.com/media-p.slid.es/uploads/909801/images/9046343/Team.jpg)
ITscope - Carrer Contacts
By Tobse Fritz
ITscope - Carrer Contacts
Spieleprogrammierung mit KorGE - Der Kotlin Multiplatform Game Engine
- 604