Add interaction through collision detection
-A standard feature of a game engine is collision detection. It is an +
A standard feature of a game engine is collision detection. It is an algorithmically complex calculation that determines if any two entities occupy the same part of the screen. If so, they have collided.
Yaeger differentiates between entities that need to be notified about a
-collision (a Collided
), and those that do not need to be notified (a
-Collider
). Think of this as a train and a fly. If they collide, the train
+collision (a Collided
), and those that do not need to be notified (a
+Collider
). Think of this as a train and a fly. If they collide, the train
doesn't even notice it; the fly does (and dies).
With this approach, it is possible to minimize the number of entities that need to be checked for collisions every GWU, and it also enables a good @@ -193,20 +193,20 @@
There are several algorithms for collision detection but Yaeger only supports
-the simplest implementation, which is based on the Bounding Box of an entity.
-This method is called Axis Aligned Bounding Box (AABB) collision detection and
+the simplest implementation, which is based on the Bounding Box of an entity.
+This method is called Axis Aligned Bounding Box (AABB) collision detection and
is implemented through the interfaces Collided
and Collider
.
Add the correct interface to Hanny and the swordfish.
You do not yet need to implement the event handler, but for testing purposes you
-should add a System.out.println("Collision!");
+should add a System.out.println("Collision!");
Start the game and test if the collision has been
detected. To get more insight into these collisions, it is possible to run
Yaeger with the commandline argument --showBB
, which makes all bounding boxes
visible.
-You might have noticed that because Yaeger uses the Bounding Box to check for
+
You might have noticed that because Yaeger uses the Bounding Box to check for
collisions, the collision detection is not as accurate as you might like it to
-be. This can be solved by using the notion of a hit box, a shape that defines
+be. This can be solved by using the notion of a hitbox, a shape that defines
the area that is being checked during a collision detection cycle.
We will first finish implementing what happens after a collision. In the next
chapter we will rework the swordfish to a version where only the sword causes
@@ -214,8 +214,8 @@
Let Hanny respawn after a collision with the swordfish
Because Hanny is the one who needs to know if she has collided with the
-swordfish, she will be the one who implements Collided
. We are going to
-use the event handler to let Hanny respawn at a different location, using
+swordfish, she will be the one who implements Collided
. We are going to
+use the event handler to let Hanny respawn at a different location, using
her setAnchorLocation()
method.
Use the following event handler to let Hanny respawn at
a random location:
@@ -229,7 +229,7 @@ Add health points and subtract one on a collision
The next step should be fairly simple, since we will use only features we have
@@ -240,27 +240,27 @@
public HealthText(Coordinate2D initialLocation){
super(initialLocation);
- setFont(Font.font("Roboto",FontWeight.NORMAL, 30));
+ setFont(Font.font("Roboto",FontWeight.NORMAL, 30));
setFill(Color.DARKBLUE);
}
public void setHealthText(int health){
- setText("Health: " + health);
+ setText("Health: " + health);
}
- Add this entity to GameLevel
, by using the
+
Add this entity to GameLevel
, by using the
setupEntities()
method, but also pass the instance to the constructor of
Hanny. This way, Hanny has access to the HealthText
entity and can call the
method setHealthText(int)
whenever her health changes.
Give Hanny a private instance field called health of
type int
and initialize it to 10. Also bind the constructor
-parameter HealthText
to an instance field. After this change, the
+parameter HealthText
to an instance field. After this change, the
constructor and instance fields of Hanny should look like:
private HealthText healthText;
private int health = 10;
public Hanny(Coordinate2D location, HealthText healthText){
- super("sprites/hanny.png", location, new Size(20,40), 2);
+ super("sprites/hanny.png", location, new Size(20,40), 2);
this.healthText = healthText;
healthText.setHealthText(health);
diff --git a/introduction.html b/introduction.html
index 7fd2070b..083eeea9 100644
--- a/introduction.html
+++ b/introduction.html
@@ -178,22 +178,22 @@ Yaeger Tutorial - Creating Waterworld
Introduction
In this tutorial you will create a simple game called Waterworld. We will start
-with an empty project. Only the assets and the project settings are provided.
-Step-by-step you will be guided in the creation of simple game, and in doing
+with an empty project. Only the assets and the project settings are provided.
+You will be guided Step-by-step in the creation of a simple game, and in doing
so, become familiar with many of the features of Yaeger.
What we will be building
-When this tutorial is completed, we will have a game in which a fish (called
+
When this tutorial is completed, we will have a game in which a fish (called
Hanny) has to navigate through the ocean and pop air bubbles. While doing so,
-she has to prevent being bitten by enemies that also prowl the ocean
+she has to prevent being bitten by enemies that also prowl the ocean.
Prerequisite
-Yaeger requires Java JDK21 or above to work. Although it can be used with any
+
Yaeger requires Java JDK21 or above to work. Although it can be used with any
modern IDE that supports Java, this tutorial will only include examples for
-JetBrains IntelliJ and
+JetBrains IntelliJ and
Eclipse.
This tutorial expects a basic understanding of the Java Programming language.
-From Java, we will only be using the basic constructs, such as Packages,
-classes, interfaces and methods. More "modern" parts of the language, such
+From Java, we will only be using the basic constructs, such as packages,
+classes, interfaces and methods. More "modern" parts of the language, such
as lambda's or generics are not required, nor used.
diff --git a/level.html b/level.html
index 513bc919..ec954d03 100644
--- a/level.html
+++ b/level.html
@@ -207,9 +207,9 @@ public StartButton(Coordinate2D initialLocation){
- super(initialLocation,"Play game");
+ super(initialLocation,"Play game");
setFill(Color.PURPLE);
- setFont(Font.font("Roboto", FontWeight.BOLD, 30));
+ setFont(Font.font("Roboto", FontWeight.BOLD, 30));
}
As you will notice we use the text Play Game, set the color to Purple and
@@ -220,8 +220,7 @@
Add behaviour to handle mouse clicks
In general, to expand the behaviour of an Entity
, you should add the
appropriate Interface to the Entity
. To let an Entity
listen to mouse button
-clicks, the Entity
should implement the Interface
-MouseButtonPressedListener
.
+clicks, the Entity
should implement the Interface MouseButtonPressedListener
.
Let StartButton
implement the interface
MouseButtonPressedListener
.
When the user clicks on the StartButton
the handler (onMouseButtonPressed()
)
diff --git a/more-entities.html b/more-entities.html
index 1108a80c..204f36d3 100644
--- a/more-entities.html
+++ b/more-entities.html
@@ -185,16 +185,16 @@
Add Sharky to GameLevel
, animate him and let him
-swim from left to right. After crossing the scene border, he should reappear
-at a random location left of the screen. After colliding with Sharky, Hanny
+swim from left to right. After crossing the scene border, he should reappear
+at a random location left of the screen. After colliding with Sharky, Hanny
loses a health point.
Start the game and test if Sharky behaves as expected.
Add air and poison bubbles
-We are now going to add the game objective: Hanny is going to pop air bubbles.
-They emerge from the depth of the ocean and float upwards at random speeds.
-Some are filled with air, and some are filled with a poisonous gas. When Hanny
-pops one of those, she loses a health point, but when she pops an air bubble,
-her bubbles popped score increases, and she earns eternal fame.
+We are now going to add the game objective: Hanny is going to pop air bubbles.
+They emerge from the depth of the ocean and float upwards at random speeds.
+Some are filled with air, and some are filled with a poisonous gas. When Hanny
+pops one of those, she loses a health point, but when she pops an air bubble,
+her bubbles popped score increases, and she earns eternal fame.
Create air and poison bubbles
For air- and poison bubbles we could provide two images of bubbles and use
a DynamicSpriteEntity
, but we'll use a different approach. Yaeger provides
@@ -211,8 +211,8 @@
API
-to figure out how to set the size and color (fill and stroke) of both
-bubbles. Note that the DynamicCircleEntity
inherits those methods from its
+to figure out how to set the size and color (fill and stroke) of both
+bubbles. Note that the DynamicCircleEntity
inherits those methods from its
parent ShapeEntity
, so look for the inherited methods in the JavaDoc.
Ensure you can differentiate between both bubbles.
Use
@@ -224,8 +224,8 @@
Create a bubble spawner
Because spawning entities into a level is a common feature of games, Yaeger
-supports this through the class EntitySpawner
. An EntitySpawner
should
-be extended and can then be added to a scene. The EntitySpawner
will
+supports this through the class EntitySpawner
. An EntitySpawner
should
+be extended and can then be added to a scene. The EntitySpawner
will
create new instances of YaegerEntity
and add them to the scene.
We are going to create a BubbleSpawner
that can create both instances
of AirBubble
and PoisonBubble
.
@@ -267,10 +267,10 @@ Add the bubble spawner to the game level
-A YaegerScene
does not support entity spawners by default, to enable it, the
+
A YaegerScene
does not support entity spawners by default. To enable it, the
scene needs to implement the interface EntitySpawnerContainer
, which requires
implementing the method setupEntitySpawners()
. From this method we can
-call addEntitySpawner(new BubbleSpawner(getWidth(), getHeight()));
, which
+call addEntitySpawner(new BubbleSpawner(getWidth(), getHeight()));
, which
adds the entity spawner to the scene and ensures the spawned entities appear on
the scene.
Add the BubbleSpawner
to the GameLevel
.
@@ -292,19 +292,19 @@ Make the bubbles pop if they collide with Hanny
Whenever a bubble collides with Hanny, a popping sound should be played, and
-they should be removed from the scene. We have already seen how to approach
+the bubble should disappear (by removing it from the scene). We have already seen how to approach
this. Apparently the bubble needs to be notified when something collides with
it. Remember the interface Collided
? But then, this is only applicable if the
-entity that collides with it, becomes an Collider
. So Hanny will not only be
-a Collided
, but also a Collider
.
- Add the interface Collider
to Hanny
+entity that collides with it, becomes a Collider
. So Hanny will not only be
+a Collided
, but also a Collider
!
+ Add the interface Collider
to Hanny.
Add the interface Collided
to the PoisonBubble
and AirBubble
(since this is shared behaviour, and we are doing proper object
orientation, we will add it to their superclass). Implement the event handler in
the following way:
@Override
public void onCollision(List<Collider> collidingObject){
- var popSound = new SoundClip("audio/pop.mp3");
+ var popSound = new SoundClip("audio/pop.mp3");
popSound.play();
remove();
@@ -321,20 +321,20 @@ Add the interface SceneBorderCrossingWatcher
to
the PoisonBubble
and AirBubble
, and call the method remove()
from the
event handler. Do make sure you call this method only when the top-border has
-been crossed.
+been crossed.
Run the game and use the debugger to see if the bubbles
that leave the top of the screen are actually removed (and garbage collected).
-Remove health point when Hanny collides with a PoisonBubble
+Remove a health point when Hanny collides with a PoisonBubble
Whenever Hanny collides with a PoisonBubble
, one health point should be
removed. Adding this shouldn't be too hard, since we have already seen
everything we need to accomplish this.
Make Hanny lose a health point whenever she collides
with a PoisonBubble
.
Add a Bubbles Popped counter and increase it whenever Hanny pops an AirBubble
-Just like the health counter, shown at the top of the screen, we are going
-to add a Bubbles Popped counter. Again, something we have done before, so it
-shouldn't be too hard. The main question will be which entity is responsible
-for changing the Bubbles Popped counter. Is it Hanny, or are the air bubbles
+
Just like the health counter, shown at the top of the screen, we are going
+to add a Bubbles Popped counter. Again, something we have done before, so it
+shouldn't be too hard. The main question will be which entity is responsible
+for changing the Bubbles Popped counter. Is it Hanny, or are the air bubbles
responsible for this?
In this case we are going to model it by letting Hanny know how many bubbles she
has popped. This way the implementation can mirror that of the HealthText
. The
diff --git a/player-controlled.html b/player-controlled.html
index 410cc467..a4ead6f9 100644
--- a/player-controlled.html
+++ b/player-controlled.html
@@ -194,16 +194,16 @@
With this in mind, the constructor of Hanny
should
look like:
public Hanny(Coordinate2D location){
- super("sprites/hanny.png", location, new Size(20,40), 1, 2);
+ super("sprites/hanny.png", location, new Size(20,40), 1, 2);
}
Now use the setupEntities()
from the GameLevel
to
add Hanny
. Place her in the top left corner of the screen.
Animate Hanny
To animate Hanny, we are going to let her listen to user input through the
-keyboard. As with the MouseButtonPressedListener
, we are going to add an
-interface. In its event handler, we are going to call setMotion()
, so we
-can change the direction based on the key being pressed. When no buttons are
+keyboard. As with the MouseButtonPressedListener
, we are going to add an
+interface. In its event handler, we are going to call setMotion()
, so we
+can change the direction based on the key being pressed. When no buttons are
pressed, we use setSpeed(0)
to make sure Hanny keeps her location.
Let Hanny
implement the interface KeyListener
and
implement the event handler in the following way:
@@ -226,18 +226,20 @@ Animate Hanny
all the keys that are currently being pressed. Depending on which keys are in
this Set
, we set the motion of Hanny.
Change the frame index depending on the direction of the Hanny
-
We must still change the frame index depending on the direction of Hanny. For
-this, a DynamicSpriteEntity
provides the method setCurrentFrameIndex(int)
.
+We must still change the frame index depending on the direction of Hanny.
+To select either the left facing or right facing part (sprite) of Hanny's bitmap
+and prevent that she swims backwars, but always looks in the direction she is swimming.
+For this, a DynamicSpriteEntity
provides the method setCurrentFrameIndex(int)
.
Set the correct frame index. Make sure only the left
and right buttons change the direction in which Hanny seems to be swimming.
Make sure Hanny doesn't leave the scene
-To ensure that Hanny remains on the screen, we can use the interface
-SceneBorderTouchingWatcher
, which provides an event handler that gets called
-whenever the entity touches the border of the scene. By implementing this
-interface, the entity needs to implement the method
-void notifyBoundaryTouching(SceneBorder)
, which receives which of the four
-borders was touched. We can use this the set either the x or
-y-coordinate of Hanny to ensure she remains within the screen. Besides that, we
+
To ensure that Hanny remains on the screen, we can use the interface
+SceneBorderTouchingWatcher
, which provides an event handler that gets called
+whenever the entity touches the border of the scene. By implementing this
+interface, the entity needs to implement the method
+void notifyBoundaryTouching(SceneBorder)
, which receives which of the four
+borders was touched. We can use this the set either the x
or
+y
-coordinate of Hanny to ensure she remains within the screen. Besides that, we
also set her speed to 0.
@Override
public void notifyBoundaryTouching(SceneBorder border){
@@ -266,9 +268,9 @@ Implement the interface SceneBorderTouchingWatcher
and use the event handler to ensure that Hanny doesn't leave the screen.
Make Hanny experience gravity and friction
-
Yaeger supports a simple approach to enable gravity and friction, which can be
-enabled by implementing the Newtonian
interface. With that interface the
-entity will continually experience gravitational pull and friction whenever
+
Yaeger supports a simple approach to enable gravity and friction, which can be
+enabled by implementing the Newtonian
interface. With this interface the
+entity will continually experience gravitational pull and friction whenever
it moves. To learn more about this interface, have a look at
the API
.
diff --git a/print.html b/print.html
index 1b72ea4f..278d7d44 100644
--- a/print.html
+++ b/print.html
@@ -179,22 +179,22 @@ Yaeger Tutorial - Creating Waterworld
Introduction
In this tutorial you will create a simple game called Waterworld. We will start
-with an empty project. Only the assets and the project settings are provided.
-Step-by-step you will be guided in the creation of simple game, and in doing
+with an empty project. Only the assets and the project settings are provided.
+You will be guided Step-by-step in the creation of a simple game, and in doing
so, become familiar with many of the features of Yaeger.
What we will be building
-When this tutorial is completed, we will have a game in which a fish (called
+
When this tutorial is completed, we will have a game in which a fish (called
Hanny) has to navigate through the ocean and pop air bubbles. While doing so,
-she has to prevent being bitten by enemies that also prowl the ocean
+she has to prevent being bitten by enemies that also prowl the ocean.
Prerequisite
-Yaeger requires Java JDK21 or above to work. Although it can be used with any
+
Yaeger requires Java JDK21 or above to work. Although it can be used with any
modern IDE that supports Java, this tutorial will only include examples for
-JetBrains IntelliJ and
+JetBrains IntelliJ and
Eclipse.
This tutorial expects a basic understanding of the Java Programming language.
-From Java, we will only be using the basic constructs, such as Packages,
-classes, interfaces and methods. More "modern" parts of the language, such
+From Java, we will only be using the basic constructs, such as packages,
+classes, interfaces and methods. More "modern" parts of the language, such
as lambda's or generics are not required, nor used.
Creating your first Yaeger game
We are going to create a game that consists of three scenes. A Title scene,
@@ -210,14 +210,14 @@
https://github.com/han-yaeger/yaeger-tutorial
The project is a Maven project, which will be
-recognized by all modern IDE's. Knowledge of Maven
-is therefore not required, but just to paint the full picture: you'll find a
-pom.xml
file at the root of the project. This file contains the full project
+recognized by all modern IDE's. Knowledge of Maven
+is therefore not required, but just to paint the full picture: you'll find a
+pom.xml
file at the root of the project. This file contains the full project
setup, and you will notice the dependency it has onYaeger
.
Importing the Maven project into your favourite IDE
Since all modern IDE's can import a Maven project,
it does not matter which you use. In this tutorial we focus on the two most
-popular amongst Java developers:
+popular amongst Java developers:
JetBrains IntelliJ and
Eclipse.
Importing the project in IntelliJ
@@ -227,7 +227,7 @@ Switch branch to look at the solution
-Whenever your stuck, you can switch to Branch implementation, to see the full
-implementation. For switching branches some knowledge of
+
Whenever you're stuck, you can switch to the Branch implementation, to see the full
+implementation. For switching branches some knowledge of
Git is required, so read the Git
documentation to figure out how to switch branches.
Setting up a new game
@@ -284,7 +284,7 @@ Add the following body to the setupGame()
method
@Override
protected void setupGame() {
- setGameTitle("Waterworld");
+ setGameTitle("Waterworld");
setSize(new Size(800, 600));
}
@@ -293,7 +293,7 @@
Collided
and Collider
.System.out.println("Collision!");
--showBB
, which makes all bounding boxes
visible.You might have noticed that because Yaeger uses the Bounding Box to check for +
You might have noticed that because Yaeger uses the Bounding Box to check for collisions, the collision detection is not as accurate as you might like it to -be. This can be solved by using the notion of a hit box, a shape that defines +be. This can be solved by using the notion of a hitbox, a shape that defines the area that is being checked during a collision detection cycle.
We will first finish implementing what happens after a collision. In the next chapter we will rework the swordfish to a version where only the sword causes @@ -214,8 +214,8 @@
Let Hanny respawn after a collision with the swordfish
Because Hanny is the one who needs to know if she has collided with the
-swordfish, she will be the one who implements Collided
. We are going to
-use the event handler to let Hanny respawn at a different location, using
+swordfish, she will be the one who implements Collided
. We are going to
+use the event handler to let Hanny respawn at a different location, using
her setAnchorLocation()
method.
Use the following event handler to let Hanny respawn at
a random location:
@@ -229,7 +229,7 @@ Add health points and subtract one on a collision
The next step should be fairly simple, since we will use only features we have
@@ -240,27 +240,27 @@
public HealthText(Coordinate2D initialLocation){
super(initialLocation);
- setFont(Font.font("Roboto",FontWeight.NORMAL, 30));
+ setFont(Font.font("Roboto",FontWeight.NORMAL, 30));
setFill(Color.DARKBLUE);
}
public void setHealthText(int health){
- setText("Health: " + health);
+ setText("Health: " + health);
}
- Add this entity to GameLevel
, by using the
+
Add this entity to GameLevel
, by using the
setupEntities()
method, but also pass the instance to the constructor of
Hanny. This way, Hanny has access to the HealthText
entity and can call the
method setHealthText(int)
whenever her health changes.
Give Hanny a private instance field called health of
type int
and initialize it to 10. Also bind the constructor
-parameter HealthText
to an instance field. After this change, the
+parameter HealthText
to an instance field. After this change, the
constructor and instance fields of Hanny should look like:
private HealthText healthText;
private int health = 10;
public Hanny(Coordinate2D location, HealthText healthText){
- super("sprites/hanny.png", location, new Size(20,40), 2);
+ super("sprites/hanny.png", location, new Size(20,40), 2);
this.healthText = healthText;
healthText.setHealthText(health);
diff --git a/introduction.html b/introduction.html
index 7fd2070b..083eeea9 100644
--- a/introduction.html
+++ b/introduction.html
@@ -178,22 +178,22 @@ Yaeger Tutorial - Creating Waterworld
Introduction
In this tutorial you will create a simple game called Waterworld. We will start
-with an empty project. Only the assets and the project settings are provided.
-Step-by-step you will be guided in the creation of simple game, and in doing
+with an empty project. Only the assets and the project settings are provided.
+You will be guided Step-by-step in the creation of a simple game, and in doing
so, become familiar with many of the features of Yaeger.
What we will be building
-When this tutorial is completed, we will have a game in which a fish (called
+
When this tutorial is completed, we will have a game in which a fish (called
Hanny) has to navigate through the ocean and pop air bubbles. While doing so,
-she has to prevent being bitten by enemies that also prowl the ocean
+she has to prevent being bitten by enemies that also prowl the ocean.
Prerequisite
-Yaeger requires Java JDK21 or above to work. Although it can be used with any
+
Yaeger requires Java JDK21 or above to work. Although it can be used with any
modern IDE that supports Java, this tutorial will only include examples for
-JetBrains IntelliJ and
+JetBrains IntelliJ and
Eclipse.
This tutorial expects a basic understanding of the Java Programming language.
-From Java, we will only be using the basic constructs, such as Packages,
-classes, interfaces and methods. More "modern" parts of the language, such
+From Java, we will only be using the basic constructs, such as packages,
+classes, interfaces and methods. More "modern" parts of the language, such
as lambda's or generics are not required, nor used.
diff --git a/level.html b/level.html
index 513bc919..ec954d03 100644
--- a/level.html
+++ b/level.html
@@ -207,9 +207,9 @@ public StartButton(Coordinate2D initialLocation){
- super(initialLocation,"Play game");
+ super(initialLocation,"Play game");
setFill(Color.PURPLE);
- setFont(Font.font("Roboto", FontWeight.BOLD, 30));
+ setFont(Font.font("Roboto", FontWeight.BOLD, 30));
}
As you will notice we use the text Play Game, set the color to Purple and
@@ -220,8 +220,7 @@
Add behaviour to handle mouse clicks
In general, to expand the behaviour of an Entity
, you should add the
appropriate Interface to the Entity
. To let an Entity
listen to mouse button
-clicks, the Entity
should implement the Interface
-MouseButtonPressedListener
.
+clicks, the Entity
should implement the Interface MouseButtonPressedListener
.
Let StartButton
implement the interface
MouseButtonPressedListener
.
When the user clicks on the StartButton
the handler (onMouseButtonPressed()
)
diff --git a/more-entities.html b/more-entities.html
index 1108a80c..204f36d3 100644
--- a/more-entities.html
+++ b/more-entities.html
@@ -185,16 +185,16 @@
Add Sharky to GameLevel
, animate him and let him
-swim from left to right. After crossing the scene border, he should reappear
-at a random location left of the screen. After colliding with Sharky, Hanny
+swim from left to right. After crossing the scene border, he should reappear
+at a random location left of the screen. After colliding with Sharky, Hanny
loses a health point.
Start the game and test if Sharky behaves as expected.
Add air and poison bubbles
-We are now going to add the game objective: Hanny is going to pop air bubbles.
-They emerge from the depth of the ocean and float upwards at random speeds.
-Some are filled with air, and some are filled with a poisonous gas. When Hanny
-pops one of those, she loses a health point, but when she pops an air bubble,
-her bubbles popped score increases, and she earns eternal fame.
+We are now going to add the game objective: Hanny is going to pop air bubbles.
+They emerge from the depth of the ocean and float upwards at random speeds.
+Some are filled with air, and some are filled with a poisonous gas. When Hanny
+pops one of those, she loses a health point, but when she pops an air bubble,
+her bubbles popped score increases, and she earns eternal fame.
Create air and poison bubbles
For air- and poison bubbles we could provide two images of bubbles and use
a DynamicSpriteEntity
, but we'll use a different approach. Yaeger provides
@@ -211,8 +211,8 @@
API
-to figure out how to set the size and color (fill and stroke) of both
-bubbles. Note that the DynamicCircleEntity
inherits those methods from its
+to figure out how to set the size and color (fill and stroke) of both
+bubbles. Note that the DynamicCircleEntity
inherits those methods from its
parent ShapeEntity
, so look for the inherited methods in the JavaDoc.
Ensure you can differentiate between both bubbles.
Use
@@ -224,8 +224,8 @@
Create a bubble spawner
Because spawning entities into a level is a common feature of games, Yaeger
-supports this through the class EntitySpawner
. An EntitySpawner
should
-be extended and can then be added to a scene. The EntitySpawner
will
+supports this through the class EntitySpawner
. An EntitySpawner
should
+be extended and can then be added to a scene. The EntitySpawner
will
create new instances of YaegerEntity
and add them to the scene.
We are going to create a BubbleSpawner
that can create both instances
of AirBubble
and PoisonBubble
.
@@ -267,10 +267,10 @@ Add the bubble spawner to the game level
-A YaegerScene
does not support entity spawners by default, to enable it, the
+
A YaegerScene
does not support entity spawners by default. To enable it, the
scene needs to implement the interface EntitySpawnerContainer
, which requires
implementing the method setupEntitySpawners()
. From this method we can
-call addEntitySpawner(new BubbleSpawner(getWidth(), getHeight()));
, which
+call addEntitySpawner(new BubbleSpawner(getWidth(), getHeight()));
, which
adds the entity spawner to the scene and ensures the spawned entities appear on
the scene.
Add the BubbleSpawner
to the GameLevel
.
@@ -292,19 +292,19 @@ Make the bubbles pop if they collide with Hanny
Whenever a bubble collides with Hanny, a popping sound should be played, and
-they should be removed from the scene. We have already seen how to approach
+the bubble should disappear (by removing it from the scene). We have already seen how to approach
this. Apparently the bubble needs to be notified when something collides with
it. Remember the interface Collided
? But then, this is only applicable if the
-entity that collides with it, becomes an Collider
. So Hanny will not only be
-a Collided
, but also a Collider
.
- Add the interface Collider
to Hanny
+entity that collides with it, becomes a Collider
. So Hanny will not only be
+a Collided
, but also a Collider
!
+ Add the interface Collider
to Hanny.
Add the interface Collided
to the PoisonBubble
and AirBubble
(since this is shared behaviour, and we are doing proper object
orientation, we will add it to their superclass). Implement the event handler in
the following way:
@Override
public void onCollision(List<Collider> collidingObject){
- var popSound = new SoundClip("audio/pop.mp3");
+ var popSound = new SoundClip("audio/pop.mp3");
popSound.play();
remove();
@@ -321,20 +321,20 @@ Add the interface SceneBorderCrossingWatcher
to
the PoisonBubble
and AirBubble
, and call the method remove()
from the
event handler. Do make sure you call this method only when the top-border has
-been crossed.
+been crossed.
Run the game and use the debugger to see if the bubbles
that leave the top of the screen are actually removed (and garbage collected).
-Remove health point when Hanny collides with a PoisonBubble
+Remove a health point when Hanny collides with a PoisonBubble
Whenever Hanny collides with a PoisonBubble
, one health point should be
removed. Adding this shouldn't be too hard, since we have already seen
everything we need to accomplish this.
Make Hanny lose a health point whenever she collides
with a PoisonBubble
.
Add a Bubbles Popped counter and increase it whenever Hanny pops an AirBubble
-Just like the health counter, shown at the top of the screen, we are going
-to add a Bubbles Popped counter. Again, something we have done before, so it
-shouldn't be too hard. The main question will be which entity is responsible
-for changing the Bubbles Popped counter. Is it Hanny, or are the air bubbles
+
Just like the health counter, shown at the top of the screen, we are going
+to add a Bubbles Popped counter. Again, something we have done before, so it
+shouldn't be too hard. The main question will be which entity is responsible
+for changing the Bubbles Popped counter. Is it Hanny, or are the air bubbles
responsible for this?
In this case we are going to model it by letting Hanny know how many bubbles she
has popped. This way the implementation can mirror that of the HealthText
. The
diff --git a/player-controlled.html b/player-controlled.html
index 410cc467..a4ead6f9 100644
--- a/player-controlled.html
+++ b/player-controlled.html
@@ -194,16 +194,16 @@
With this in mind, the constructor of Hanny
should
look like:
public Hanny(Coordinate2D location){
- super("sprites/hanny.png", location, new Size(20,40), 1, 2);
+ super("sprites/hanny.png", location, new Size(20,40), 1, 2);
}
Now use the setupEntities()
from the GameLevel
to
add Hanny
. Place her in the top left corner of the screen.
Animate Hanny
To animate Hanny, we are going to let her listen to user input through the
-keyboard. As with the MouseButtonPressedListener
, we are going to add an
-interface. In its event handler, we are going to call setMotion()
, so we
-can change the direction based on the key being pressed. When no buttons are
+keyboard. As with the MouseButtonPressedListener
, we are going to add an
+interface. In its event handler, we are going to call setMotion()
, so we
+can change the direction based on the key being pressed. When no buttons are
pressed, we use setSpeed(0)
to make sure Hanny keeps her location.
Let Hanny
implement the interface KeyListener
and
implement the event handler in the following way:
@@ -226,18 +226,20 @@ Animate Hanny
all the keys that are currently being pressed. Depending on which keys are in
this Set
, we set the motion of Hanny.
Change the frame index depending on the direction of the Hanny
-
We must still change the frame index depending on the direction of Hanny. For
-this, a DynamicSpriteEntity
provides the method setCurrentFrameIndex(int)
.
+We must still change the frame index depending on the direction of Hanny.
+To select either the left facing or right facing part (sprite) of Hanny's bitmap
+and prevent that she swims backwars, but always looks in the direction she is swimming.
+For this, a DynamicSpriteEntity
provides the method setCurrentFrameIndex(int)
.
Set the correct frame index. Make sure only the left
and right buttons change the direction in which Hanny seems to be swimming.
Make sure Hanny doesn't leave the scene
-To ensure that Hanny remains on the screen, we can use the interface
-SceneBorderTouchingWatcher
, which provides an event handler that gets called
-whenever the entity touches the border of the scene. By implementing this
-interface, the entity needs to implement the method
-void notifyBoundaryTouching(SceneBorder)
, which receives which of the four
-borders was touched. We can use this the set either the x or
-y-coordinate of Hanny to ensure she remains within the screen. Besides that, we
+
To ensure that Hanny remains on the screen, we can use the interface
+SceneBorderTouchingWatcher
, which provides an event handler that gets called
+whenever the entity touches the border of the scene. By implementing this
+interface, the entity needs to implement the method
+void notifyBoundaryTouching(SceneBorder)
, which receives which of the four
+borders was touched. We can use this the set either the x
or
+y
-coordinate of Hanny to ensure she remains within the screen. Besides that, we
also set her speed to 0.
@Override
public void notifyBoundaryTouching(SceneBorder border){
@@ -266,9 +268,9 @@ Implement the interface SceneBorderTouchingWatcher
and use the event handler to ensure that Hanny doesn't leave the screen.
Make Hanny experience gravity and friction
-
Yaeger supports a simple approach to enable gravity and friction, which can be
-enabled by implementing the Newtonian
interface. With that interface the
-entity will continually experience gravitational pull and friction whenever
+
Yaeger supports a simple approach to enable gravity and friction, which can be
+enabled by implementing the Newtonian
interface. With this interface the
+entity will continually experience gravitational pull and friction whenever
it moves. To learn more about this interface, have a look at
the API
.
diff --git a/print.html b/print.html
index 1b72ea4f..278d7d44 100644
--- a/print.html
+++ b/print.html
@@ -179,22 +179,22 @@ Yaeger Tutorial - Creating Waterworld
Introduction
In this tutorial you will create a simple game called Waterworld. We will start
-with an empty project. Only the assets and the project settings are provided.
-Step-by-step you will be guided in the creation of simple game, and in doing
+with an empty project. Only the assets and the project settings are provided.
+You will be guided Step-by-step in the creation of a simple game, and in doing
so, become familiar with many of the features of Yaeger.
What we will be building
-When this tutorial is completed, we will have a game in which a fish (called
+
When this tutorial is completed, we will have a game in which a fish (called
Hanny) has to navigate through the ocean and pop air bubbles. While doing so,
-she has to prevent being bitten by enemies that also prowl the ocean
+she has to prevent being bitten by enemies that also prowl the ocean.
Prerequisite
-Yaeger requires Java JDK21 or above to work. Although it can be used with any
+
Yaeger requires Java JDK21 or above to work. Although it can be used with any
modern IDE that supports Java, this tutorial will only include examples for
-JetBrains IntelliJ and
+JetBrains IntelliJ and
Eclipse.
This tutorial expects a basic understanding of the Java Programming language.
-From Java, we will only be using the basic constructs, such as Packages,
-classes, interfaces and methods. More "modern" parts of the language, such
+From Java, we will only be using the basic constructs, such as packages,
+classes, interfaces and methods. More "modern" parts of the language, such
as lambda's or generics are not required, nor used.
Creating your first Yaeger game
We are going to create a game that consists of three scenes. A Title scene,
@@ -210,14 +210,14 @@
https://github.com/han-yaeger/yaeger-tutorial
The project is a Maven project, which will be
-recognized by all modern IDE's. Knowledge of Maven
-is therefore not required, but just to paint the full picture: you'll find a
-pom.xml
file at the root of the project. This file contains the full project
+recognized by all modern IDE's. Knowledge of Maven
+is therefore not required, but just to paint the full picture: you'll find a
+pom.xml
file at the root of the project. This file contains the full project
setup, and you will notice the dependency it has onYaeger
.
Importing the Maven project into your favourite IDE
Since all modern IDE's can import a Maven project,
it does not matter which you use. In this tutorial we focus on the two most
-popular amongst Java developers:
+popular amongst Java developers:
JetBrains IntelliJ and
Eclipse.
Importing the project in IntelliJ
@@ -227,7 +227,7 @@ Switch branch to look at the solution
-Whenever your stuck, you can switch to Branch implementation, to see the full
-implementation. For switching branches some knowledge of
+
Whenever you're stuck, you can switch to the Branch implementation, to see the full
+implementation. For switching branches some knowledge of
Git is required, so read the Git
documentation to figure out how to switch branches.
Setting up a new game
@@ -284,7 +284,7 @@ Add the following body to the setupGame()
method
@Override
protected void setupGame() {
- setGameTitle("Waterworld");
+ setGameTitle("Waterworld");
setSize(new Size(800, 600));
}
@@ -293,7 +293,7 @@
Collided
. We are going to
-use the event handler to let Hanny respawn at a different location, using
+swordfish, she will be the one who implements Collided
. We are going to
+use the event handler to let Hanny respawn at a different location, using
her setAnchorLocation()
method.public HealthText(Coordinate2D initialLocation){
super(initialLocation);
- setFont(Font.font("Roboto",FontWeight.NORMAL, 30));
+ setFont(Font.font("Roboto",FontWeight.NORMAL, 30));
setFill(Color.DARKBLUE);
}
public void setHealthText(int health){
- setText("Health: " + health);
+ setText("Health: " + health);
}
- Add this entity to GameLevel
, by using the
+
Add this entity to GameLevel
, by using the
setupEntities()
method, but also pass the instance to the constructor of
Hanny. This way, Hanny has access to the HealthText
entity and can call the
method setHealthText(int)
whenever her health changes.
Give Hanny a private instance field called health of
type int
and initialize it to 10. Also bind the constructor
-parameter HealthText
to an instance field. After this change, the
+parameter HealthText
to an instance field. After this change, the
constructor and instance fields of Hanny should look like:
private HealthText healthText;
private int health = 10;
public Hanny(Coordinate2D location, HealthText healthText){
- super("sprites/hanny.png", location, new Size(20,40), 2);
+ super("sprites/hanny.png", location, new Size(20,40), 2);
this.healthText = healthText;
healthText.setHealthText(health);
diff --git a/introduction.html b/introduction.html
index 7fd2070b..083eeea9 100644
--- a/introduction.html
+++ b/introduction.html
@@ -178,22 +178,22 @@ Yaeger Tutorial - Creating Waterworld
Introduction
In this tutorial you will create a simple game called Waterworld. We will start
-with an empty project. Only the assets and the project settings are provided.
-Step-by-step you will be guided in the creation of simple game, and in doing
+with an empty project. Only the assets and the project settings are provided.
+You will be guided Step-by-step in the creation of a simple game, and in doing
so, become familiar with many of the features of Yaeger.
What we will be building
-When this tutorial is completed, we will have a game in which a fish (called
+
When this tutorial is completed, we will have a game in which a fish (called
Hanny) has to navigate through the ocean and pop air bubbles. While doing so,
-she has to prevent being bitten by enemies that also prowl the ocean
+she has to prevent being bitten by enemies that also prowl the ocean.
Prerequisite
-Yaeger requires Java JDK21 or above to work. Although it can be used with any
+
Yaeger requires Java JDK21 or above to work. Although it can be used with any
modern IDE that supports Java, this tutorial will only include examples for
-JetBrains IntelliJ and
+JetBrains IntelliJ and
Eclipse.
This tutorial expects a basic understanding of the Java Programming language.
-From Java, we will only be using the basic constructs, such as Packages,
-classes, interfaces and methods. More "modern" parts of the language, such
+From Java, we will only be using the basic constructs, such as packages,
+classes, interfaces and methods. More "modern" parts of the language, such
as lambda's or generics are not required, nor used.
diff --git a/level.html b/level.html
index 513bc919..ec954d03 100644
--- a/level.html
+++ b/level.html
@@ -207,9 +207,9 @@ public StartButton(Coordinate2D initialLocation){
- super(initialLocation,"Play game");
+ super(initialLocation,"Play game");
setFill(Color.PURPLE);
- setFont(Font.font("Roboto", FontWeight.BOLD, 30));
+ setFont(Font.font("Roboto", FontWeight.BOLD, 30));
}
As you will notice we use the text Play Game, set the color to Purple and @@ -220,8 +220,7 @@
Add behaviour to handle mouse clicks
In general, to expand the behaviour of an Entity
, you should add the
appropriate Interface to the Entity
. To let an Entity
listen to mouse button
-clicks, the Entity
should implement the Interface
-MouseButtonPressedListener
.
Entity
should implement the Interface MouseButtonPressedListener
.
Let StartButton
implement the interface
MouseButtonPressedListener
.
When the user clicks on the StartButton
the handler (onMouseButtonPressed()
)
diff --git a/more-entities.html b/more-entities.html
index 1108a80c..204f36d3 100644
--- a/more-entities.html
+++ b/more-entities.html
@@ -185,16 +185,16 @@
Add Sharky to GameLevel
, animate him and let him
-swim from left to right. After crossing the scene border, he should reappear
-at a random location left of the screen. After colliding with Sharky, Hanny
+swim from left to right. After crossing the scene border, he should reappear
+at a random location left of the screen. After colliding with Sharky, Hanny
loses a health point.
Start the game and test if Sharky behaves as expected.
Add air and poison bubbles
-We are now going to add the game objective: Hanny is going to pop air bubbles. -They emerge from the depth of the ocean and float upwards at random speeds. -Some are filled with air, and some are filled with a poisonous gas. When Hanny -pops one of those, she loses a health point, but when she pops an air bubble, -her bubbles popped score increases, and she earns eternal fame.
+We are now going to add the game objective: Hanny is going to pop air bubbles. +They emerge from the depth of the ocean and float upwards at random speeds. +Some are filled with air, and some are filled with a poisonous gas. When Hanny +pops one of those, she loses a health point, but when she pops an air bubble, +her bubbles popped score increases, and she earns eternal fame.
Create air and poison bubbles
For air- and poison bubbles we could provide two images of bubbles and use
a DynamicSpriteEntity
, but we'll use a different approach. Yaeger provides
@@ -211,8 +211,8 @@
API
-to figure out how to set the size and color (fill and stroke) of both
-bubbles. Note that the DynamicCircleEntity
inherits those methods from its
+to figure out how to set the size and color (fill and stroke) of both
+bubbles. Note that the DynamicCircleEntity
inherits those methods from its
parent ShapeEntity
, so look for the inherited methods in the JavaDoc.
Ensure you can differentiate between both bubbles.
Use @@ -224,8 +224,8 @@
Create a bubble spawner
Because spawning entities into a level is a common feature of games, Yaeger
-supports this through the class EntitySpawner
. An EntitySpawner
should
-be extended and can then be added to a scene. The EntitySpawner
will
+supports this through the class EntitySpawner
. An EntitySpawner
should
+be extended and can then be added to a scene. The EntitySpawner
will
create new instances of YaegerEntity
and add them to the scene.
We are going to create a BubbleSpawner
that can create both instances
of AirBubble
and PoisonBubble
.
Add the bubble spawner to the game level
-A YaegerScene
does not support entity spawners by default, to enable it, the
+
A YaegerScene
does not support entity spawners by default. To enable it, the
scene needs to implement the interface EntitySpawnerContainer
, which requires
implementing the method setupEntitySpawners()
. From this method we can
-call addEntitySpawner(new BubbleSpawner(getWidth(), getHeight()));
, which
+call addEntitySpawner(new BubbleSpawner(getWidth(), getHeight()));
, which
adds the entity spawner to the scene and ensures the spawned entities appear on
the scene.
Add the BubbleSpawner
to the GameLevel
.
Make the bubbles pop if they collide with Hanny
Whenever a bubble collides with Hanny, a popping sound should be played, and
-they should be removed from the scene. We have already seen how to approach
+the bubble should disappear (by removing it from the scene). We have already seen how to approach
this. Apparently the bubble needs to be notified when something collides with
it. Remember the interface Collided
? But then, this is only applicable if the
-entity that collides with it, becomes an Collider
. So Hanny will not only be
-a Collided
, but also a Collider
.
Add the interface Collider
to Hanny
Collider
. So Hanny will not only be
+a Collided
, but also a Collider
!
+ Add the interface Collider
to Hanny.
Add the interface Collided
to the PoisonBubble
and AirBubble
(since this is shared behaviour, and we are doing proper object
orientation, we will add it to their superclass). Implement the event handler in
the following way:
@Override
public void onCollision(List<Collider> collidingObject){
- var popSound = new SoundClip("audio/pop.mp3");
+ var popSound = new SoundClip("audio/pop.mp3");
popSound.play();
remove();
@@ -321,20 +321,20 @@ Add the interface SceneBorderCrossingWatcher
to
the PoisonBubble
and AirBubble
, and call the method remove()
from the
event handler. Do make sure you call this method only when the top-border has
-been crossed.
+been crossed.
Run the game and use the debugger to see if the bubbles
that leave the top of the screen are actually removed (and garbage collected).
-Remove health point when Hanny collides with a PoisonBubble
+Remove a health point when Hanny collides with a PoisonBubble
Whenever Hanny collides with a PoisonBubble
, one health point should be
removed. Adding this shouldn't be too hard, since we have already seen
everything we need to accomplish this.
Make Hanny lose a health point whenever she collides
with a PoisonBubble
.
Add a Bubbles Popped counter and increase it whenever Hanny pops an AirBubble
-Just like the health counter, shown at the top of the screen, we are going
-to add a Bubbles Popped counter. Again, something we have done before, so it
-shouldn't be too hard. The main question will be which entity is responsible
-for changing the Bubbles Popped counter. Is it Hanny, or are the air bubbles
+
Just like the health counter, shown at the top of the screen, we are going
+to add a Bubbles Popped counter. Again, something we have done before, so it
+shouldn't be too hard. The main question will be which entity is responsible
+for changing the Bubbles Popped counter. Is it Hanny, or are the air bubbles
responsible for this?
In this case we are going to model it by letting Hanny know how many bubbles she
has popped. This way the implementation can mirror that of the HealthText
. The
diff --git a/player-controlled.html b/player-controlled.html
index 410cc467..a4ead6f9 100644
--- a/player-controlled.html
+++ b/player-controlled.html
@@ -194,16 +194,16 @@
With this in mind, the constructor of Hanny
should
look like:
public Hanny(Coordinate2D location){
- super("sprites/hanny.png", location, new Size(20,40), 1, 2);
+ super("sprites/hanny.png", location, new Size(20,40), 1, 2);
}
Now use the setupEntities()
from the GameLevel
to
add Hanny
. Place her in the top left corner of the screen.
Animate Hanny
To animate Hanny, we are going to let her listen to user input through the
-keyboard. As with the MouseButtonPressedListener
, we are going to add an
-interface. In its event handler, we are going to call setMotion()
, so we
-can change the direction based on the key being pressed. When no buttons are
+keyboard. As with the MouseButtonPressedListener
, we are going to add an
+interface. In its event handler, we are going to call setMotion()
, so we
+can change the direction based on the key being pressed. When no buttons are
pressed, we use setSpeed(0)
to make sure Hanny keeps her location.
Let Hanny
implement the interface KeyListener
and
implement the event handler in the following way:
@@ -226,18 +226,20 @@ Animate Hanny
all the keys that are currently being pressed. Depending on which keys are in
this Set
, we set the motion of Hanny.
Change the frame index depending on the direction of the Hanny
-
We must still change the frame index depending on the direction of Hanny. For
-this, a DynamicSpriteEntity
provides the method setCurrentFrameIndex(int)
.
+We must still change the frame index depending on the direction of Hanny.
+To select either the left facing or right facing part (sprite) of Hanny's bitmap
+and prevent that she swims backwars, but always looks in the direction she is swimming.
+For this, a DynamicSpriteEntity
provides the method setCurrentFrameIndex(int)
.
Set the correct frame index. Make sure only the left
and right buttons change the direction in which Hanny seems to be swimming.
Make sure Hanny doesn't leave the scene
-To ensure that Hanny remains on the screen, we can use the interface
-SceneBorderTouchingWatcher
, which provides an event handler that gets called
-whenever the entity touches the border of the scene. By implementing this
-interface, the entity needs to implement the method
-void notifyBoundaryTouching(SceneBorder)
, which receives which of the four
-borders was touched. We can use this the set either the x or
-y-coordinate of Hanny to ensure she remains within the screen. Besides that, we
+
To ensure that Hanny remains on the screen, we can use the interface
+SceneBorderTouchingWatcher
, which provides an event handler that gets called
+whenever the entity touches the border of the scene. By implementing this
+interface, the entity needs to implement the method
+void notifyBoundaryTouching(SceneBorder)
, which receives which of the four
+borders was touched. We can use this the set either the x
or
+y
-coordinate of Hanny to ensure she remains within the screen. Besides that, we
also set her speed to 0.
@Override
public void notifyBoundaryTouching(SceneBorder border){
@@ -266,9 +268,9 @@ Implement the interface SceneBorderTouchingWatcher
and use the event handler to ensure that Hanny doesn't leave the screen.
Make Hanny experience gravity and friction
-
Yaeger supports a simple approach to enable gravity and friction, which can be
-enabled by implementing the Newtonian
interface. With that interface the
-entity will continually experience gravitational pull and friction whenever
+
Yaeger supports a simple approach to enable gravity and friction, which can be
+enabled by implementing the Newtonian
interface. With this interface the
+entity will continually experience gravitational pull and friction whenever
it moves. To learn more about this interface, have a look at
the API
.
diff --git a/print.html b/print.html
index 1b72ea4f..278d7d44 100644
--- a/print.html
+++ b/print.html
@@ -179,22 +179,22 @@ Yaeger Tutorial - Creating Waterworld
Introduction
In this tutorial you will create a simple game called Waterworld. We will start
-with an empty project. Only the assets and the project settings are provided.
-Step-by-step you will be guided in the creation of simple game, and in doing
+with an empty project. Only the assets and the project settings are provided.
+You will be guided Step-by-step in the creation of a simple game, and in doing
so, become familiar with many of the features of Yaeger.
What we will be building
-When this tutorial is completed, we will have a game in which a fish (called
+
When this tutorial is completed, we will have a game in which a fish (called
Hanny) has to navigate through the ocean and pop air bubbles. While doing so,
-she has to prevent being bitten by enemies that also prowl the ocean
+she has to prevent being bitten by enemies that also prowl the ocean.
Prerequisite
-Yaeger requires Java JDK21 or above to work. Although it can be used with any
+
Yaeger requires Java JDK21 or above to work. Although it can be used with any
modern IDE that supports Java, this tutorial will only include examples for
-JetBrains IntelliJ and
+JetBrains IntelliJ and
Eclipse.
This tutorial expects a basic understanding of the Java Programming language.
-From Java, we will only be using the basic constructs, such as Packages,
-classes, interfaces and methods. More "modern" parts of the language, such
+From Java, we will only be using the basic constructs, such as packages,
+classes, interfaces and methods. More "modern" parts of the language, such
as lambda's or generics are not required, nor used.
Creating your first Yaeger game
We are going to create a game that consists of three scenes. A Title scene,
@@ -210,14 +210,14 @@
https://github.com/han-yaeger/yaeger-tutorial
The project is a Maven project, which will be
-recognized by all modern IDE's. Knowledge of Maven
-is therefore not required, but just to paint the full picture: you'll find a
-pom.xml
file at the root of the project. This file contains the full project
+recognized by all modern IDE's. Knowledge of Maven
+is therefore not required, but just to paint the full picture: you'll find a
+pom.xml
file at the root of the project. This file contains the full project
setup, and you will notice the dependency it has onYaeger
.
Importing the Maven project into your favourite IDE
Since all modern IDE's can import a Maven project,
it does not matter which you use. In this tutorial we focus on the two most
-popular amongst Java developers:
+popular amongst Java developers:
JetBrains IntelliJ and
Eclipse.
Importing the project in IntelliJ
@@ -227,7 +227,7 @@ Switch branch to look at the solution
setupGame()
method
@Override
protected void setupGame() {
- setGameTitle("Waterworld");
+ setGameTitle("Waterworld");
setSize(new Size(800, 600));
}
@@ -293,7 +293,7 @@