C# Game Programming Cookbook For Unity 3D 2nd Edition Jeff W. Murray PDF Download
C# Game Programming Cookbook For Unity 3D 2nd Edition Jeff W. Murray PDF Download
https://textbookfull.com/product/c-game-programming-cookbook-for-
unity-3d-2nd-edition-jeff-w-murray/
https://textbookfull.com/product/learning-c-programming-with-
unity-3d-alex-okita/
https://textbookfull.com/product/game-programming-in-c-
creating-3d-games-creating-3d-games-sanjay-madhav/
https://textbookfull.com/product/unity-game-development-
programming-c-in-unity-engine-a-guide-book-for-beginners-1nd-
edition-2020-kathleen-peterson/
https://textbookfull.com/product/unity-game-development-cookbook-
essentials-for-every-game-1-converted-edition-paris-buttfield-
addison/
3D Game Programming for Kids Create Interactive Worlds
with JavaScript 2nd Edition Chris Strom
https://textbookfull.com/product/3d-game-programming-for-kids-
create-interactive-worlds-with-javascript-2nd-edition-chris-
strom/
https://textbookfull.com/product/beginning-game-ai-with-unity-
programming-artificial-intelligence-with-c-sebastiano-m-cossu/
https://textbookfull.com/product/developing-2d-games-with-unity-
independent-game-programming-with-c-1st-edition-jared-halpern/
https://textbookfull.com/product/developing-2d-games-with-unity-
independent-game-programming-with-c-1st-edition-jared-halpern-2/
https://textbookfull.com/product/3d-game-programming-for-kids-
create-interactive-worlds-with-javascript-1st-edition-chris-
strom/
C# Game Programming
Cookbook for Unity 3D
C# Game Programming
Cookbook for Unity 3D
Second Edition
Jeff W. Murray
Second Edition published 2021
by CRC Press
6000 Broken Sound Parkway NW, Suite 300, Boca Raton, FL 33487-2742
and by CRC Press
2 Park Square, Milton Park, Abingdon, Oxon, OX14 4RN
First Edition published by CRC Press 2014
CRC Press is an imprint of Taylor & Francis Group, LLC
© 2021 Taylor & Francis Group, LLC
The right of Jeff W. Murray to be identified as author of this work has been asserted by
him/ in accordance with sections 77 and 78 of the Copyright, Designs and Patents Act
1988.
Reasonable efforts have been made to publish reliable data and information, but the
author and publisher cannot assume responsibility for the validity of all materials or the
consequences of their use. The authors and publishers have attempted to trace the copy-
right holders of all material reproduced in this publication and apologize to copyright
holders if permission to publish in this form has not been obtained. If any copyright
material has not been acknowledged please write and let us know so we may rectify in any
future reprint.
Except as permitted under U.S. Copyright Law, no part of this book may be reprinted,
reproduced, transmitted, or utilized in any form by any electronic, mechanical, or other
means, now known or hereafter invented, including photocopying, microfilming, and
recording, or in any information storage or retrieval system, without written permission
from the publishers.
For permission to photocopy or use material electronically from this work, access www.
copyright.com or contact the Copyright Clearance Center, Inc. (CCC), 222 Rosewood
Drive, Danvers, MA 01923, 978-750-8400. For works that are not available on CCC please
contact [email protected]
Trademark notice: Product or corporate names may be trademarks or registered trade-
marks and are used only for identification and explanation without intent to infringe.
ISBN: 978-0-367-32170-3 (hbk)
ISBN: 978-0-367-32164-2 (pbk)
ISBN: 978-0-429-31713-2 (ebk)
Typeset in Minion
by SPi Global, India
This book is dedicated to my
amazing wife, Tori, and to
my boys, Ethan and William.
Boys, be nice to the cat and
the cat will be nice to you!
Contents
Acknowledgments xiii
Introduction xv
Prerequisites xvii
vii
2. Making a 2D Infinite Runner Game 9
2.1 Anatomy of a Unity Project . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
2.2 Open Unity, Then the Example Project for This Chapter . . . . . . . . . . 10
2.2.1 A Few Notes on the Example Project . . . . . . . . . . . . . . . . . .12
2.2.2 Sprites . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
2.2.3 Animation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
2.3 Open the Main Game Scene . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
2.4 The Game Manager . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
2.5 Making Platforms to Run On . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
2.6 Building the Player, RunMan . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
2.6.1 Adding the RunMan Sprite . . . . . . . . . . . . . . . . . . . . . . . . . . 22
2.6.2 Adding Physics and Collisions to RunMan . . . . . . . . . . . . 23
2.6.3 Player Scripts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
2.6.4 RunMan Sounds . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
2.6.5 Animating RunMan . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
2.6.6 Scoring . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
2.7 The Game Loop and the Game Manager . . . . . . . . . . . . . . . . . . . . . . . 28
2.7.1 Game States . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
2.7.2 The Main Loop of RunMan_GameManager.cs . . . . . . . . . 29
2.7.3 Setting Up the RunMan_Game Manager
Component in the Editor . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
2.8 The Demise of RunMan . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
2.9 Adding the User Interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
2.9.1 Main Menu Setup . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
4. Player Structure 61
4.1 A Player Controller . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
4.2 Dealing with Input . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
4.3 User Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
4.3.1 The UserData Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
4.3.2 The BaseUserManager Class . . . . . . . . . . . . . . . . . . . . . . . . . 66
4.4 The BasePlayerStatsController Class . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
4.5 Managing Players . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73
viii Contents
5.3 Camera . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76
5.3.1 Third-Person Camera . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
5.3.2 Top-Down Camera . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80
5.4 Game Control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80
5.4.1 GlobalRaceManager . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80
5.4.2 RaceController . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80
5.5 Input . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
5.5.1 Mouse Input . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
5.6 Level Loading . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82
5.7 ScriptableObjects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
5.7.1 ProfileScriptableObject . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
5.8 Spawning . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
5.8.1 A Spawner Component . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
5.8.2 Trigger Spawning . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88
5.8.3 Timed Spawning . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89
5.9 User Interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91
5.9.1 CanvasManager . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91
5.9.2 ScreenandAudioFader . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91
5.9.3 MenuWithProfiles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91
5.10 Utility . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91
5.10.1 AlignToGround . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91
5.10.2 AutomaticDestroyObject . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93
5.10.3 AutoSpinObject . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93
5.10.4 FaceCamera . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94
5.10.5 LookAtCamera . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94
5.10.6 PretendFriction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94
5.10.7 TimerClass . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96
5.10.7.1 Modifying the Timer to Update
Automatically����������������������������������������������������100
5.10.8 WaypointsController . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100
5.11 Weapons . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100
Contents ix
9. Recipe: Sound and Audio 145
9.1 Audio Mixers and Mixing Audio in Unity . . . . . . . . . . . . . . . . . . . . . 145
9.1.1 Mixing Audio . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145
9.1.2 Exposing Mixer Properties to Modify Them with Scripts . . 146
9.1.3 Audio Effects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147
9.2 The BaseSoundManager Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147
9.3 Adding Sound to Weapons . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153
x Contents
14.4.5 Audio . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 259
14.4.5.1 Vehicle Audio����������������������������������������������������259
14.4.5.2 Incidental Sounds����������������������������������������������259
14.4.6 User Interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 260
Index 283
Contents xi
Acknowledgments
Thanks to all of my family, friends and everyone who has helped me with my
books, games and projects over the years: Brian Robbins, Chris Hanney,
Technicat, Molegato, NoiseCrime, Quantum Sheep, Mickael Laszlo, Juanita
Leatham, CoolPowers, Dave Brake, Sigurdur Gunnarsson, Kevin Godoy R.,
Lister, Wim Wouters, Edy (VehiclePhysics), IdeaFella, Liam Twose, RafaEnd,
Lynxie, Alistair Murphy, McFunkypants, Dani Moss, Malcolm Evans, Vinh,
Scott Wilson, Jon Keon, Dunky, Huck Z, Paradise Decay, Kryten, Silverware
Games, Pete Patterson, Dr. Not Oculus VR, Say Mistage, Andy Hatch, Lydia, RT
Warner, GermanRifter VR, Sylvain Demers, Kenneth Seward Jr, Dancer (Space
Dad), Steve Fulton, Paul Bettner, Derek Scottishgeeks, Jonny Gorden, Edward
Atkin, Ottawa Pete, Sam W., Dylan Stout, Shane McCafferty, Will Goldstone,
Sanborn VR, Gary Riches, J. Dakota Powell, Mayonnaise Boy, Stephen Parkes,
Ram Kanda, Alex Bethke, Itzik Goldman, Joachim Ante, Robert Scoble, Tony
Walsh, Andreas ‘BOLL’ Aronsson, Cat, Darrel Plant, Mike Baker, Rimsy, Cassie,
Christopher Brown, Phil Nolan, Pixel Hat Studio, Marcus Valles, Trev, Karyl,
Tami Quiring, Nadeem Rasool, Dwayne Dibley, Liz and Pete Smyth, Isaac and
Aiden, David Helgason, VR Martin, James Gamble, Vasanth Mohan, Simona
Ioffe, Alexander Kondratskiy, Tim and Paul, The Oliver Twins, Jeevan Aurol,
Rick King, Aldis Sipolins, Ric Lumb, Craig Taylor, Rob Hewson, Dani Moss,
Jayenkai (JNK), Matthew Kirubakaran, Elliot Mitchell, Ethan and William,
Pablo Rojo, Paul Bettner, AdrellaDev, Gordon Little, Ryan Evans, Sasha Boersma,
Matt Browning at Perfect Prototype, Hermit, Dirty Rectangles and the whole
Ottawa game dev community.
xiii
I would also like to sincerely thank Anya Hastwell, Thivya Vasudevan and
the team at SPI Global, the whole team at Routledge/CRC Press/AK Peters,
including Randi Cohen, Jessica Vega and Rick Adams, for making this book a
reality.
Thank you for buying this book and for wanting to do something as cool as
to make games. I wish I could tell you how awesome it feels to know that someone
else is reading this right now. I cannot wait to see your games and I sincerely hope
this book helps you in your game making adventures. Have fun making games!
xiv Acknowledgments
Introduction
The overall goal of this book is to provide a library of C# code with which to
jumpstart your projects and to help you with the overall structure of your games.
Many development cookbooks focus on only providing snippets of code, but,
here, we take a different approach. What you are holding in your hands right now
(or on your screen) is a cookbook for game development that has a highly flexible
core framework designed to speed up development of just about any type of Unity
project.
You might think of the framework as a base soup and the scripting compo-
nents as ingredients. We can mix and match script components and we can share
the same core scripts in many of them. The framework takes care of the essentials
and we add a little extra code to pull it all together the way we want it to work.
The framework is optional, however – you can use a lot the components indi-
vidually. If you intend on using the components in this book for your own games,
the framework could either serve as a base to build your games on or simply as a
tutorial test bed for you to rip apart and see how it all works. Perhaps you can
develop a better framework or maybe you already have a solid framework in
place. If you do find a way to develop your own framework, I say do it. The key to
game development is to do what works for you and your game projects – what-
ever it takes to cross the finish line.
I hope it helps you to make your games and tell your stories. I also hope you
remember to try to have fun doing it!
xv
Prerequisites
You can get up and running with the required software for the grand total of zero
dollars. Everything you need can be downloaded free of charge with no catches.
All you need is:
C# programming knowledge.
This is not a book about learning how to program. You will need to know
some C# and there are several other books out there for that purpose, even if I
have tried to make the examples as simple as possible!
xvii
1 Making Games in a
Modular Way
1.1.1.1 Managers
Managers deal with overall management, in a similar way to how a Manager
would work in a workplace situation.
1.1.1.2 Controllers
Controllers deal with systems that the managers need to do their jobs. For exam-
ple, in the racing game example game for this book, we have race controller
scripts and a global race manager script. The race controller scripts are attached
to the players and track their positions on the track, waypoints, and other rele-
vant player-specific race information. The global race manager script talks to all
1
the race controller scripts attached to the players to determine who is winning
and when the race starts or finishes.
1. Direct referencing scripts via variables set in the editor by the Inspector
window.
The easiest way to have script Components talk to each other (that is, scripts
attached to GameObjects in the Scene as Components) is to have direct refer-
ences, in the form of public variables within your code. They can then be popu-
lated in the Inspector window of the Unity editor with a direct link to another
Component on another GameObject.
Above, this would call the function DoSomething() on any of the script
Components attached to the GameObject referenced by someGameObject.
3. Static variables.
The static variable type makes a variable accessible to other scripts without a
direct reference to the GameObject it is attached to. This is particularly useful
behavior where several different scripts may want to manipulate a variable to do
things like adding points to a score or set the number of lives of a player, and so on.
An example declaration of a static variable might be:
public static GameManager aManager;
1.1.1.4 Public Static
A public static variable exists everywhere and may be accessed by any other
script.
For example, imagine a player script which needs to tell the Game Manager
to increase the current score by one:
2. In any other script, we can now access this static variable and alter the
score as needed:
GameController.gameScore++;
When a player script is first created, it uses the value of uniqueNum for itself
and increases uniqueNum by one:
myUniqueNum = uniqueNum;
uniqueNum++;
The value of uniqueNum will be shared across all player scripts. The next
player to be spawned will run the same start up function, getting uniqueNum
again – only this time it has been increased by one, thanks to the player spawned
earlier. This player again gets its own unique number and increases the static
variable ready for the next one.
1.1.2 The Singleton
A singleton is a commonly used method for allowing access to an instance of a
class, accessible to all other scripts. This pattern is ideal for code that needs to
communicate with the entire game, such as a Game Manager.
instance = this;
}
}
1.1.3 Inheritance
Inheritance is a complex concept, which calls for some explanation here because
of its key role within the scripts provided by this book. Have a read through this
section but don’t worry if you don’t pick up inheritance right away. Once we get
to the programming it will probably become clearer.
Car–
–Wheels
–Engine
Car class.
Wheels function
Engine function
If we were building a game with lots of cars in it, having to rewrite the car class for
each type of car would be silly. A far more efficient method might be to write a base
class and populate it with virtual functions. When we need to create a car, rather
than use this base class, we build a new class, which inherits the base class. Because
our new class is inherited, it is optional whether we choose to override wheels or
engine functions to make them behave in ways specific to our new class. That is, we
can build ‘default’ functions into the base class and if we only need to use a default
behavior for an engine, our new class doesn’t need to override the engine function.
A base class might look something like this:
public class BaseCar : MonoBehaviour {
There are two key things to notice in the above script. One is the class declara-
tion itself and the fact that this class derives from MonoBehaviour. MonoBehaviour
is itself a class – the Unity documentation describes it as “the base class every
script derives from” – this MonoBehaviour class contains many engine-specific
functions and methods such as Start(), Update(), FixedUpdate(), and more. If our
script didn’t derive from MonoBehaviour it would not inherit those functions and
the engine wouldn’t automatically call functions like Update() for us to be able to
work with. Another point to note is that MonoBehaviour is a class that is built into
the engine and not something we can access to edit or change.
The second point to note is that our functions are both declared as virtual
functions. Both are public, both are virtual. Making virtual functions means that
the behavior in our base class may be overridden by any scripts that derive from it.
The behavior we define in this base class could be thought of as its default behav-
ior. We will cover overriding in full a little further on in this section.
The first thing you may notice is that the OctoCar class derives from BaseCar
rather than MonoBehaviour. This means that OctoCar inherits functions and meth-
ods belonging to our BaseCar script. As the functions described by BaseCar were
virtual, they may be overridden. For OctoCar, we override Wheels with the line:
public override void Wheels () {
Let’s take a look at what this script actually does: In this case, if we were to
call the Engine() function on OctoCar, it would do the same as the BaseCar class;
it would write “Vroom” to the console. It would do this because we have inherited
the function but have not overridden it, which means we keep that default behav-
ior. In OctoCar, however, we have overridden the Wheels() function. The BaseCar
behavior of Wheels would print “Four wheels” to the console but if we call
Wheels() on OctoCar, the overridden behavior will write “Eight wheels,” instead.
Inheritance plays a huge part in how our core game framework is structured.
The idea is that we have basic object types and specific elaborated versions of
these objects inheriting the base methods, properties, and functions. By building
our games in this manner, the communication between the different game com-
ponents (such as game control scripts, weapon scripts, projectile controllers, etc.)
becomes universal without having to write out the same function declarations
over and over again for different variations of script. For the core framework, our
main goal is to make it as flexible and extensible as possible and this would be a
much more difficult if we were unable to use inheritance.
1.1.4 Coroutines
Unity lets you run a function known as a coroutine, outside of the regular built
in functions like Update, FixedUpdate, LateUpdate, and so on. A coroutine is
self-contained code that will just go off and do its own thing once you have told
it to run. As it is running on its own, you can do some cool stuff like pause it for
a set amount of time and then have it start again, and coroutines are ideally suited
to time-based actions like fade effects or animations.
Here is an example of a coroutine (this example code comes from the Unity
engine documentation):
IEnumerator Fade()
{
for (float ft = 1f; ft >= 0; ft -= 0.1f)
{
Color c = renderer.material.color;
c.a = ft;
renderer.material.color = c;
yield return null;
}
}
Do not be alarmed by this odd code above! All it does is tell the engine that,
at this point, the coroutine is ready to end this update and go on to the next one.
You need this in your code, but don’t worry too much about why at this stage.
I will go into some more detail below, but for now let us continue by looking at
how you would start this coroutine running:
StartCoroutine("Fade");
You can think of IEnumerator like a cursor making its way through your
code. When the cursor hits a yield statement, that tells the engine that this update
is done and to move the cursor on to the next block.
Another thing you can do with coroutines is to pause the code inline for a
certain amount of time, like this:
yield return new WaitForSeconds(1.0f);
Using WaitForSeconds(), you can quite literally pause the coroutine script
execution inline. For example:
IEnumerator DebugStuff()
{
Debug.Log("Start.");
yield return new WaitForSeconds(1.0f);
Debug.Log("Now, it’s one second later!");
Earlier in this section, I mentioned that the yield statement is used to tell
Unity the current update is done and to move on to the next. In the code above,
rather than just telling Unity to move on to the next bit of code, it tells Unity to
wait for the specified number of seconds first.
1.1.5 Namespaces
Namespaces compartmentalize chunks of code away from each other. You can
think of a namespace as a box to put your own scripts in, so that they can stay
separated from other code or code libraries. This helps to prevent possible
namespace MyNamespace
{
public class MyClass() : Monobehaviour
{
}
When you want to refer to the code from another class, you need to be either
wrapped in the same namespace or to have the using keyword at the top of the
script, like:
using MyNamespace;
Switch(currentGameState)
{
Case GameStates.GameLoaded:
GameLoaded();
Break;
Case GameStates.GameStarting:
GameStart();
Break;
Having code in each case statement can get unruly. To counter this, I like to
split all of the code out into individual functions. This keeps the code tidy, easier
to manage, and easier to debug when things do not go to plan.
"Oikein."
"Sano se."
61
"Valtion asia!"
"Niin, monsieur."
"Minä olen utelias kuin vanha akka. Tule hetkiseksi kadun puolelle,
niin vilkaisemme torille. Lyönpä vetoa, että tästä tulee erikoisempi
näky."
62.
Eläköön Colbert!
Kamalan näytelmän esitti Grève-tori katselijalle tänä hetkenä.
Kymmenettuhannet tältä matkalta yhteensulautuvat ihmispäät
kuvastuivat ikäänkuin laajana vainiotasankona, jonka tähkäpäitä tuuli
huojuttelee. Tuon tuostakin kuului etäältä jotakin käsittämätöntä
kohua, joka sai väkimeren aaltoilemaan entistä rajummin ja
tuhannet silmät siinä väläyttelemään salamoita, ja toisinaan
tungettiin ulkoreunoilta niin voimakkaasti keskelle päin, että
lainehtiva ahdinko valtameren hyökyjen tavoin hyrskehti
kaupunginvartion rivejä vasten, jotka olivat asettuneet hirsipuiden
ympärille. Silloin tapparakeihäiden varret mätkähtelivät etumaisten
tungeksijain päähän ja hartioihin, ja joskus käytettiin kärkiäkin,
jolloin vartion ympäri avautui laaja tyhjä kehä. Se ala vallattiin
reunimmaisten kustannuksella, jolloin nämä vuorostaan saivat kokea
äkillistä puristusta Seine-virran rintasuojuksia vasten. Ylhäältä
ikkunastaan d'Artagnan näki yli koko torin, ja hän havaitsi sisäiseksi
tyytyväisyydekseen, että ne muskettisoturit ja henkivartion miehet,
jotka olivat tulleet vedetyiksi tungokseen, kykenivät nyrkeillään ja
miekankahvoillaan raivaamaan itselleen tilaa. Huomasipa hän
myöskin, että heidän onnistui kaksinkertaisia voimia antavan
yhteishengen avulla liittyä koolle lähes viisikymmentä miestä
käsittäväksi ryhmäksi, joten joukon ydin oli saapuvilla ja hänen
äänensä ulottuvilla, ja ainoastaan kymmenisen eksynyttä näkyi enää
lentelehtivän edestakaisin tungosmainingeissa. Mutta eivät
ainoastaan muskettisoturit ja kaartilaiset kääntäneet puoleensa
d'Artagnanin huomiota. Hirsipuiden ja etenkin Saint-Jeanin
holvikäytävän lähistöllä liikehti rähisevä ja rauhaton pyörre, jossa
vilahteli rohkeita kasvoja ja päättäväisiä ilmeitä; yksinkertaisten
piirteiden ja välinpitämättömän ällistelyn keskeltä merkkejä
vaihdettiin ja toistensa käsiä puristeltiin. D'Artagnan keksi juuri
vilkkaimmissa ryhmissä liikuskelemassa sen ritarin, jonka oli nähnyt
tulevan puutarhansa veräjästä ja sitten pitävän puhetta krouvissa.
Hän jakoi nyt miehiä osastoiksi ja antoi heille määräyksiä.
"Hyvä juttu! Hiisi vieköön, oletpa reipas urho! Sinulla on isäsi pää
ja Portoksen käsivarsi. Ah, olisipa Portos ollutkin täällä, niin olisi
vasta saatu nähdä ihmeitä!"
63.
"Niinkuin jalopeurat."
"Monsieur!"
"Tottele!"
"Niin, teidän piti laahata heidät suoraa päätä roviolle", uudisti abbé
raakaluontoisesti.
"Heitä sinä silleen valtioviisaus, abbé; mene nyt vain äläkä toimita
minulle kuulumisia itsestäsi ennen kuin määrään toisin, — minusta
tuntuu, että meidän on nyt asetuttava hyvin hiljaisiksi ja varovaisiksi.
Sinulla on kamala esimerkki edessäsi. Ei mitään kostotoimia sinun ja
väkesi taholta; sen kiellän jyrkästi."
"Chevalier d'Artagnan."
"Niin, herra Fouquet", sanoi hän, "kyllä minä tiesinkin, ettei täällä
ole rahoja muskettisotureille. En tänne tullutkaan saamaan rahoja,
vaan ainoastaan kieltävän vastauksen. Se on nyt annettu; kiitos!
Sanon vain hyvästi ja menen nostamaan herra Colbertilta, mitä
muodon vuoksi pyysin teiltä."
Our website is not just a platform for buying books, but a bridge
connecting readers to the timeless values of culture and wisdom. With
an elegant, user-friendly interface and an intelligent search system,
we are committed to providing a quick and convenient shopping
experience. Additionally, our special promotions and home delivery
services ensure that you save time and fully enjoy the joy of reading.
textbookfull.com