-
Notifications
You must be signed in to change notification settings - Fork 40
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add remaining Fish Pond tutorial steps
- Loading branch information
1 parent
cd53671
commit 4965624
Showing
14 changed files
with
826 additions
and
117 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,88 +1,30 @@ | ||
# Adding Water Surface | ||
# Adding Water Overlay | ||
|
||
What's a pond without the fishes, right? Let's use what we learn from the previous step to add some fish sprites to the scene as well. We will also animate them afterwards to give them life. | ||
At the point, the fishes look like they are floating on the rocks and pebbles. We will overlay what we have so far with a tiling sprite of a tiled water texture. Tiling sprite is essentially a sprite with the capabilities of transforming and rending an infinitely repeating grid of a single texture, preferably a tiled one where the edges seamlessly connect with each other when put together. We will use this to give an illusion of a forever moving water surface. | ||
|
||
## Create and Setup Fish Sprites | ||
## Create and Setup Tiling Sprite | ||
|
||
Let's encapsulate all the following setup within the `addFishes` function that has already been prepared for you. We begin by creating a container to hold all the fish sprites together and add it to the stage. This is a great practice for better separation. | ||
Here we create a tiling sprite, supplying a texture and dimensions as an option object, and add it to the stage. | ||
|
||
```javascript | ||
const fishContainer = new Container(); | ||
const texture = Texture.from('overlay'); | ||
|
||
app.stage.addChild(fishContainer); | ||
``` | ||
|
||
Then we declare some reference variables like how many fishes should there be in the pond and what are the fish types available. For the types, we refer to the 5 different fish assets we have preloaded earlier and made them into an array of aliases. | ||
|
||
```javascript | ||
const fishCount = 20; | ||
const fishAssets = ['fish1', 'fish2', 'fish3', 'fish4', 'fish5']; | ||
``` | ||
|
||
Instead of creating each of the fish individually, which will be super tedious, we will use a simple `for` loop to create each of the fish until it reaches our desire count, also cycling through the fish asset aliases array. In addition to the basic setup and applying initial transforms, we also assign them with custom properties like `direction`, `speed` and `turnSpeed` which will be used during the animation. We will store the fishes in a reference array defined outside of the IIFE. | ||
|
||
```javascript | ||
for (let i = 0; i < fishCount; i++) | ||
{ | ||
const fishAsset = fishAssets[i % fishAssets.length]; | ||
const fish = Sprite.from(fishAsset); | ||
|
||
fish.anchor.set(0.5); | ||
|
||
fish.direction = Math.random() * Math.PI * 2; | ||
fish.speed = 2 + Math.random() * 2; | ||
fish.turnSpeed = Math.random() - 0.8; | ||
|
||
fish.x = Math.random() * app.screen.width; | ||
fish.y = Math.random() * app.screen.height; | ||
fish.scale.set(0.8 + Math.random() * 0.3); | ||
|
||
this.fishContainer.addChild(fish); | ||
this.fishes.push(fish); | ||
} | ||
overlay = new TilingSprite({ | ||
texture, | ||
width: app.screen.width, | ||
height: app.screen.height, | ||
}); | ||
app.stage.addChild(overlay); | ||
``` | ||
|
||
## Animate Fishes | ||
|
||
It's time to give the fishes some movements! Another function `animateFishes` has been prepared and connected to the application's ticker which will be continuously called. It is supplied with a Ticker object which we can use to infer the amount of time passed between the calls. | ||
|
||
We will declare a few variables to help us with the animation. We extract `deltaTime` from the Ticker object which tells us the amount of time passed since last call, in seconds. We also define an imaginary bound that is larger than the stage itself to wrap the position of the fishes when they go off the screen. We use this bound instead of the actual screen size to avoid having the fishes disappear before they actually go off the edges, since the fish sprites' anchor is in the center so, eg. when a `fish.x = 0`, half of the fish's width is still apparent on the screen. | ||
|
||
```javascript | ||
const delta = time.deltaTime; | ||
|
||
const stagePadding = 100; | ||
const boundWidth = app.screen.width + stagePadding * 2; | ||
const boundHeight = app.screen.height + stagePadding * 2; | ||
``` | ||
## Animate Overlay | ||
|
||
We can then simply loop through individual fishes array and update them one by one. First by updating the fish's pseudo direction which dictates the changes in its sprite position and rotation. To keep the fish within the screen bound, we use the padded bound defined earlier to check and wrap the fish as soon as it goes off the bound. | ||
Similar to the previous step, we will now animate the water overlay using the application's ticker. The code has been modify to call both animation functions for the fish and this overlay so we only need to add the animation logic inside the `animateWaterOverlay` function. | ||
|
||
```javascript | ||
fishes.forEach((fish) => | ||
{ | ||
fish.direction += fish.turnSpeed * 0.01; | ||
fish.x += Math.sin(fish.direction) * fish.speed; | ||
fish.y += Math.cos(fish.direction) * fish.speed; | ||
fish.rotation = -fish.direction - Math.PI / 2; | ||
|
||
if (fish.x < -stagePadding) | ||
{ | ||
fish.x += boundWidth; | ||
} | ||
if (fish.x > app.screen.width + stagePadding) | ||
{ | ||
fish.x -= boundWidth; | ||
} | ||
if (fish.y < -stagePadding) | ||
{ | ||
fish.y += boundHeight; | ||
} | ||
if (fish.y > app.screen.height + stagePadding) | ||
{ | ||
fish.y -= boundHeight; | ||
} | ||
}); | ||
elapsed += time.deltaTime; | ||
overlay.tilePosition.x = elapsed * -1; | ||
overlay.tilePosition.y = elapsed * -1; | ||
``` | ||
|
||
They are beautiful aren't they! Next, let's add a water surface effect to make the pond feels more dynamic. | ||
Congratulations, we have now completed a beautiful pond! But we can take it a step further. Let's proceed to the final touch! |
Oops, something went wrong.