Get Flame Game Development: Your Guide to Creating Cross-Platform Games in 2D Using Flame Engine in Flutter 3 1st Edition Andrés Cruz Yoris PDF ebook with Full Chapters Now
Get Flame Game Development: Your Guide to Creating Cross-Platform Games in 2D Using Flame Engine in Flutter 3 1st Edition Andrés Cruz Yoris PDF ebook with Full Chapters Now
com
https://ebookmass.com/product/flame-game-development-your-
guide-to-creating-cross-platform-games-in-2d-using-flame-
engine-in-flutter-3-1st-edition-andres-cruz-yoris/
OR CLICK HERE
DOWLOAD NOW
https://ebookmass.com/product/firefighters-secret-flame-reign/
ebookmass.com
https://ebookmass.com/product/blossom-black-rose-helen-hardt/
ebookmass.com
Saving the Marquess: Book 1. A Steamy Regency Romance, I
Have A Secret, Happily Ever After book Mihwa Lee
https://ebookmass.com/product/saving-the-marquess-book-1-a-steamy-
regency-romance-i-have-a-secret-happily-ever-after-book-mihwa-lee/
ebookmass.com
Super Dad Jokes: Saving the World, One Bad Joke at a Time
Jimmy Niro
https://ebookmass.com/product/super-dad-jokes-saving-the-world-one-
bad-joke-at-a-time-jimmy-niro/
ebookmass.com
https://ebookmass.com/product/habitos-dos-milionarios-os-segredos-por-
tras-das-maiores-fortunas-do-mundo-napoleon-hill/
ebookmass.com
https://ebookmass.com/product/supreme-chess-understanding-statics-
dynamics-thinkers-publishing-2023-wojciech-moranda/
ebookmass.com
https://ebookmass.com/product/the-husband-heist-the-dainty-devils-
book-3-alyxandra-harvey/
ebookmass.com
Leo El Magnifico Pablo Cartaya
https://ebookmass.com/product/leo-el-magnifico-pablo-cartaya/
ebookmass.com
Flame Game
Development
Your Guide to Creating Cross-Platform
Games in 2D Using Flame Engine
in Flutter 3
—
Andrés Cruz Yoris
Flame Game Development
Your Guide to Creating
Cross-Platform Games in 2D Using
Flame Engine in Flutter 3
Introduction�����������������������������������������������������������������������������������������������������������xvii
iii
Table of Contents
iv
Table of Contents
v
Table of Contents
vi
Table of Contents
Animations�������������������������������������������������������������������������������������������������������������������������������� 284
Movement��������������������������������������������������������������������������������������������������������������������������������� 285
Changes in Movement��������������������������������������������������������������������������������������������������������� 290
Map and Initial Collidables�������������������������������������������������������������������������������������������������������� 292
Collisions Between the Player and Objects������������������������������������������������������������������������������� 294
Second Implementation������������������������������������������������������������������������������������������������������� 299
Third Implementation���������������������������������������������������������������������������������������������������������� 302
Fourth Implementation�������������������������������������������������������������������������������������������������������� 306
Fifth Implementation: Double Collision�������������������������������������������������������������������������������� 308
Limit Player Movement to the Map������������������������������������������������������������������������������������������� 313
Player Position�������������������������������������������������������������������������������������������������������������������������� 315
Hitbox Size�������������������������������������������������������������������������������������������������������������������������������� 317
Run�������������������������������������������������������������������������������������������������������������������������������������������� 317
vii
Table of Contents
viii
Table of Contents
ix
Table of Contents
Index��������������������������������������������������������������������������������������������������������������������� 559
x
About the Author
Andrés Cruz Yoris has more than ten years’ experience in the development of web
applications. He works with PHP, Python, and client-side technologies like HTML,
JavaScript, CSS, and Vue among others and server-side technologies like Laravel, Flask,
Django, and CodeIgniter. I am also a developer in Android Studio, Xcode, and Flutter
with which he creates native applications for Android and iOS.
xi
About the Technical Reviewer
Lukas Klingsbo (spydon) is part of the Blue Fire open
source collective and is the top contributor and maintainer
of the Flame game engine.
When not improving Flame, you can see him giving talks
and holding workshops on Flutter all over the world.
xiii
Acknowledgments
Thanks to everyone on my publishing team. Thanks to my father, who was always there
for me. And thanks to my mom for her support.
xv
Introduction
This book is intended to get you started with Flame using Flutter; with this, we are going
to clarify two things:
1. It is not a book which provides 100% knowledge of Flame or takes
you from being a beginner to an expert, since it would be too big
an objective for the scope of this book. What it offers is knowledge
about the main aspects of Flame, such as sprites, collision
systems, tiled inputs, and much more, and how to apply them to
2D game development.
This book applies a practical approach, from knowing the key aspects of the
technology to putting them into practice, gradually implementing small features and
functionalities that can be adapted to a real game.
To follow this book, you need to have a computer running Windows, Linux,
or MacOS.
xvii
CHAPTER 1
$ cd <ProjectName>
Finally, we open VSC or the editor you use to develop in Flutter; for this, you can
do the manual process (open the project we created earlier from VSC) or use the VSC
command (in case you have it configured):
$ code .
1
© Andrés Cruz Yoris 2024
A. Cruz Yoris, Flame Game Development, https://doi.org/10.1007/979-8-8688-0063-4_1
CHAPTER 2
Flame Basics
In this chapter we will know the key elements of Flame and its organization,
components, and key structures. This chapter purely acts as a reference; do not worry
if you do not understand all the terms explained. The following chapters offer a
more practical scheme in which we build an application step-by-step, and when you
encounter one of the classes and functions introduced in this chapter, you can return to
this chapter to review what was explained about it.
You can create a project called “testsflame” following the process shown in the
previous chapter.
1. The main class, which is the one that allows all the modules of the
application to communicate and uses Flame’s own processes such
as the collision and input system (keyboard, gestures, etc.)
2. The components, which are the elements of our game, such as a
background, a player, an enemy, etc.
To make the idea easier to understand, you can see Flame’s Game class as Flutter’s
MaterialApp and the Flame components as each of the pages that make up a Flutter
application.
3
© Andrés Cruz Yoris 2024
A. Cruz Yoris, Flame Game Development, https://doi.org/10.1007/979-8-8688-0063-4_2
Chapter 2 Flame Basics
Components
One of the great aspects of Flame is that we can use the different features of Flame with
the help of its component system. A component can be many things like a player, an
enemy, a background, particle effects, texts, or a joystick, among others, with which we
can incorporate more features such as the use of collisions, updates, and interactions
with keys, like drag and drop, tap, etc. As you can see, Flame has a very similar approach
to Flutter, but in this case with components instead of widgets and based on games.
In essence, a game entity, such as a player, is represented by a component, which
is a class. Through the Game class of our application, which is a Game-type class, the
components can communicate with each other, for example, in entries or collisions,
which gives us a very modular and scalable environment for the application.
We have many types of components. In this book, we will see some like
• SpriteComponent
• SpriteAnimationComponent
• PositionComponent
• TextComponent
4
Chapter 2 Flame Basics
import 'package:flame/components.dart';
import 'package:flame/game.dart';
import 'package:flutter/material.dart';
5
Chapter 2 Flame Basics
@override
void onLoad() async {
sprite = await Sprite.load('image.png');
}
}
main() {
runApp(GameWidget(game: MyGame()));
}
assets/images/image.png
pubspec.yaml
assets:
- assets/images/image.png
And the sprite will have a size of 16 pixels as specified in the class’s constructor:
size: Vector2.all(16)
add(MySprite());
Once an image is registered in your project, you will see a result like the following.
6
Chapter 2 Flame Basics
lib/main.dart
import 'package:flame/components.dart';
import 'package:flame/game.dart';
import 'package:flame/palette.dart';
import 'package:flutter/material.dart';
@override
void onLoad() async {}
@override
void render(Canvas canvas) {
canvas.drawCircle(const Offset(10, 10), 10, BasicPalette.red.paint());
main() {
runApp(GameWidget(game: MyGame()));
}
In this other example, we have the same application, but using the Game class
instead:
lib/main.dart
import 'package:flame/palette.dart';
import 'package:flutter/material.dart';
import 'package:flame/game.dart';
@override
void render(Canvas canvas) {
canvas.drawCircle(const Offset(10, 10), 10, BasicPalette.red.paint());
8
Chapter 2 Flame Basics
@override
void update(double deltaTime) {}
}
If you run either program with the Game or FlameGame class, you will see an output
like the following.
As you can conclude, this approach of organizing the code in classes allows us to
reuse the components more easily, as well as extend them or create others; therefore,
these examples reinforce the reason it is used. Apart from that, with the FlameGame
class, we have access to other features of the Flame API.
The FlameGame class maintains a list of all game components, and these can
be dynamically added to the game as needed; for example, we could add many
enemy SpriteComponents to the game and then remove them from the game as
the player kills the enemies. The FlameGame class will then iterate over these
components telling each component to update and render itself.
The GameWidget class represents the constructor we usually use to instantiate the
game in Flame and set it to the widget tree in Flutter.
As a recommendation, Ctrl/Command-click the FlameGame, Game,
PositionComponent, SpriteComponent, and the rest of the classes to see their details
and what properties they implement, as in the following:
9
Chapter 2 Flame Basics
ScaleProvider,
CoordinateTransform {
PositionComponent({
Vector2? position,
Vector2? size,
Vector2? scale,
double? angle,
this.nativeAngle = 0,
Anchor? anchor,
super.children,
***
You can also see the functions that you can implement and what parameters you can
send and their type, as in the case of Canvas, and test them and evaluate the result.
For example, to draw a rectangle, we can do it by defining two points on the screen:
import 'package:flame/components.dart';
import 'package:flame/game.dart';
import 'package:flame/palette.dart';
import 'package:flutter/material.dart';
10
Chapter 2 Flame Basics
@override
void onLoad() async {}
@override
void render(Canvas canvas) {
canvas.drawCircle(
Offset(circlePos, circlePos),
10,
_paint
);
@override
void update(double dt) {
super.update(dt);
circlePos++;
}
}
main() {
runApp(GameWidget(game: MyGame()));
}
11
Chapter 2 Flame Basics
import 'package:flame/palette.dart';
import 'package:flutter/material.dart';
import 'package:flame/game.dart';
@override
void onLoad() async {
super.onLoad();
// init
}
@override
void render(Canvas canvas) {
canvas.drawCircle(
Offset(circlePos, circlePos), 10, BasicPalette.red.paint());
@override
void update(double dt) {
circlePos++;
}
}
In the Game class, the game component, in this case the circle, is implemented
directly in the Game class, while for the implementation with the FlameGame class,
we can make use of a separate class (component) in which we handle all the logic of
said component, in this case moving the circle, which leaves us with a much cleaner
12
Chapter 2 Flame Basics
https://docs.flame-engine.org/latest/flame/components.html#circlecomponent
Or if you want to draw a rectangle, you can uncomment this code shown previously:
13
Chapter 2 Flame Basics
These two processes are known as the game loop, which is explained in the
following.
G
ame Loop
Flame’s module called GameLoop or the game loop is nothing more than a simple
abstraction of the game loop concept. Basically, most of the video games are based on
two methods:
• The render method takes the canvas to draw the current state of
the game.
• The update method receives the time (delta) since the last update
and allows the game to go to the next state, that is, updates the
game state.
That is, we have a method to initialize the game and another to perform updates.
Flame follows these principles, and we have a couple of methods that allow us to
perform such operations.
R
ender Method
The render() function receives an object-type parameter that refers to the canvas:
@override
void render(Canvas canvas) {
canvas.drawRect(squarePos, squarePaint);
}
This is just like with other technologies like HTML5; it’s nothing more than a blank
canvas to draw on. Here, we can draw anything, for example, a circle:
@override
void render(Canvas canvas) {
canvas.drawCircle(const Offset(10, 10), 10, BasicPalette.red.paint());
}
14
Chapter 2 Flame Basics
Update Method
The elements that are in the game need to be constantly redrawn according to the
current state of the game; to understand this more clearly, let’s see an example.
Suppose that a game element is represented by a sprite (an image), which in this
example we will call as a “player.” When the user clicks a button, then the player must
update its position; this update is applied in-game via a function called update().
As we saw in the example of the moving circle, it is this function that is responsible
for updating the position of the circle on the screen.
The update() method is, as its name indicates, an update function, which receives
a parameter called “delta time” (dt) that tells us the time that has elapsed since the
previous frame was drawn. You should use this variable to make your component move
at the same speed on all devices.
When updating any aspect of the game through the update() function, it is
automatically reflected through the render() function, and with this, the game updates
at a graphical level.
The game loop is used by all implementations of Game classes and their
components:
https://docs.flame-engine.org/latest/flame/game.html
15
Chapter 2 Flame Basics
16
CHAPTER 3
Flame Fundamentals
In this chapter, the main elements that we must know to work with Flame will be
discussed. We will see how to create the components, which are the key pieces or
elements of our game. We will look at the basic structure of a game with Flame and the
use of inputs (keyboard, joystick, etc.), which is the way in which the user can interact
with the application.
SpriteComponent: Components
for Rendering Images
One of the fundamental components that we have is the SpriteComponent. A sprite
sheet is a series of images joined in the same file next to each other.
Figure 3-1. Sprite sheet for the player, who can walk in all directions (https://
pipoya.itch.io/pipoya-free-rpg-character-sprites-nekonin)
17
© Andrés Cruz Yoris 2024
A. Cruz Yoris, Flame Game Development, https://doi.org/10.1007/979-8-8688-0063-4_3
Chapter 3 Flame Fundamentals
Figure 3-2. Sprite sheet for the player, who can move horizontally or up by
jumping (www.gameart2d.com/free-dino-sprites.html)
18
Chapter 3 Flame Fundamentals
pubspec.yaml
assets/images/tiger.png
pubspec.yaml
assets:
- assets/images/tiger.png
And we are going to create a new file to handle this image, which will have the
following structure:
lib/components/player_image_sprite_component.dart
import 'package:flame/components.dart';
import 'package:flutter/material.dart';
@override
void onLoad() async {
screenWidth = MediaQueryData.fromWindow(window).size.width;
screenHeight = MediaQueryData.fromWindow(window).size.height;
We obtain the size of the window, both its width and height. With this, we have all
the space that we can use to draw:
MediaQueryData.fromWindow(window).size
And we set the sizes, specifically the width and the height:
screenWidth = MediaQueryData.fromWindow(window).size.width;
screenHeight = MediaQueryData.fromWindow(window).size.height;
20
Chapter 3 Flame Fundamentals
Currently, getting the size this way is deprecated, which means that its use is
discouraged. In case you have access to the application context, you can get the window
size with
screenWidth = MediaQueryData.fromView(View.of(context)).size.width;
screenHeight = MediaQueryData.fromView(View.of(context)).size.height;
Or if you’re in a Flame component, where we don’t have access to the context, you
can use Flame’s game object that we can get as an import reference in the component,
for example:
game
game.size
screenWidth = game.size.x;
screenHeight = game.size.y;
We are going to want to place the image in the middle of the window. To do this, we
calculate the middle of the window:
(screenWidth/2)
(screenHeight/2)
Regardless of the scheme you want to use, we calculate the space occupied by the
image. Therefore, we subtract half the size of the image; with this, the image will appear
centered:
21
Chapter 3 Flame Fundamentals
And with this, we can calculate the position, to set it in the position property of the
SpriteComponent class. We need to indicate the position by means of a 2D vector in
which it is specified, the position that was previously calculated through the centerX and
centerY properties:
We indicate the total size of the image. As with the position, it is indicated by a two-
dimensional vector:
Remember that all the processes that require access to the storage memory of
the device are asynchronous processes; in this case, it is necessary to access the
storage memory, which is where the image we want to load is located.
To use the previously created component, we add it to the scene from main:
lib/main.dart
import 'package:flame/game.dart';
import 'package:flutter/material.dart';
import 'package:testsflame/components/player_image_sprite_component.dart';
22
Chapter 3 Flame Fundamentals
The image is in the specified size, which would be about 512 pixels; for a little
challenge, you can try resizing the image and placing it in different positions on
the screen.
This small example that we created is a base case that we must understand since any
Flame component has a logic similar to this; that is, create a component class with the
structure and logic and add it to the Game class to be able to use it in the application.
Going back to our application, we are going to update the position vector using the
update() function. For this example, we will not use the delta time:
23
Chapter 3 Flame Fundamentals
@override
void update(double dt) {
// TODO: implement update
super.update(dt);
}
This results in the constant movement of the image when executing the application.
With this, the next step that we have pending is to add interactivity with the user,
that is, the user can somehow interact with the application (the game) and something
happens, such as moving the sprite.
Here’s the code if we wanted to update the position of the sprite:
24
Chapter 3 Flame Fundamentals
25
Chapter 3 Flame Fundamentals
To avoid loading an image one by one in the project, managing them independently,
and, with this, increasing the consumption of resources (since, at the project level, each
image should be loaded individually), we are going to do all these steps at once; this
format is known as a “sprite sheet.” For this task, you can use any image editing program,
but, to facilitate the process, it is recommended to use programs such as the following:
www.codeandweb.com/texturepacker
The preceding program called TexturePacker allows us to create a sprite sheet
for the images; you can install the program on Linux, Windows, and MacOS. For this
process, you can download any image kit you want, although on the website www.
gameart2d.com/freebies.html, you will find several sprites that you can use for free.
Once the program is installed and your image kit has been downloaded, we are
going to create the sprite sheet. To do this, we drag and drop the images we want to work
with into the area shown in the following figure; in this book, they are the images shown
previously.
26
Random documents with unrelated
content Scribd suggests to you:
The Project Gutenberg eBook of The hounds of
Tindalos
This ebook is for the use of anyone anywhere in the United States
and most other parts of the world at no cost and with almost no
restrictions whatsoever. You may copy it, give it away or re-use it
under the terms of the Project Gutenberg License included with this
ebook or online at www.gutenberg.org. If you are not located in the
United States, you will have to check the laws of the country where
you are located before using this eBook.
Illustrator: C. C. Senf
Language: English
I rose quickly and moved toward him, but his eyes implored me not
to interfere. "The clock has stopped," he murmured. "The forces that
control it approve of my experiment. Time stopped, and I swallowed
the drug. I pray God that I shall not lose my way."
He closed his eyes and leaned back on the sofa. All of the blood had
left his face and he was breathing heavily. It was clear that the drug
was acting with extraordinary rapidity.
"It is beginning to get dark," he murmured. "Write that. It is
beginning to get dark and the familiar objects in the room are fading
out. I can discern them vaguely through my eyelids but they are
fading swiftly."
I shook my pen to make the ink come and wrote rapidly in shorthand
as he continued to dictate.
"I am leaving the room. The walls are vanishing and I can no longer
see any of the familiar objects. Your face, though, is still visible to
me. I hope that you are writing. I think that I am about to make a
great leap—a leap through space. Or perhaps it is through time that I
shall make the leap. I can not tell. Everything is dark, indistinct."
He sat for a while silent, with his head sunk upon his breast. Then
suddenly he stiffened and his eyelids fluttered open. "God in heaven!"
he cried. "I see!"
He was straining forward in his chair, staring at the opposite wall. But
I knew that he was looking beyond the wall and that the objects in
the room no longer existed for him. "Chalmers," I cried, "Chalmers,
shall I wake you?"
"Do not!" he shrieked. "I see everything. All of the billions of lives
that preceded me on this planet are before me at this moment. I see
men of all ages, all races, all colors. They are fighting, killing,
building, dancing, singing. They are sitting about rude fires on lonely
gray deserts, and flying through the air in monoplanes. They are
riding the seas in bark canoes and enormous steamships; they are
painting bison and mammoths on the walls of dismal caves and
covering huge canvases with queer futuristic designs. I watch the
migrations from Atlantis. I watch the migrations from Lemuria. I see
the elder races—a strange horde of black dwarfs overwhelming Asia
and the Neandertalers with lowered heads and bent knees ranging
obscenely across Europe. I watch the Achæans streaming into the
Greek islands, and the crude beginnings of Hellenic culture. I am in
Athens and Pericles is young. I am standing on the soil of Italy. I
assist in the rape of the Sabines; I march with the Imperial Legions. I
tremble with awe and wonder as the enormous standards go by and
the ground shakes with the tread of the victorious hastati. A
thousand naked slaves grovel before me as I pass in a litter of gold
and ivory drawn by night-black oxen from Thebes, and the flower-
girls scream 'Ave Cæsar' as I nod and smile. I am myself a slave on a
Moorish galley. I watch the erection of a great cathedral. Stone by
stone it rises, and through months and years I stand and watch each
stone as it falls into place. I am burned on a cross head downward in
the thyme-scented gardens of Nero, and I watch with amusement
and scorn the torturers at work in the chambers of the Inquisition.
"I walk in the holiest sanctuaries; I enter the temples of Venus. I
kneel in adoration before the Magna Mater, and I throw coins on the
bare knees of the sacred courtezans who sit with veiled faces in the
groves of Babylon. I creep into an Elizabethan theater and with the
stinking rabble about me I applaud The Merchant of Venice. I walk
with Dante through the narrow streets of Florence. I meet the young
Beatrice and the hem of her garment brushes my sandals as I stare
enraptured. I am a priest of Isis, and my magic astounds the nations.
Simon Magus kneels before me, imploring my assistance, and
Pharaoh trembles when I approach. In India I talk with the Masters
and run screaming from their presence, for their revelations are as
salt on wounds that bleed.
"I perceive everything simultaneously. I perceive everything from all
sides; I am a part of all the teeming billions about me. I exist in all
men and all men exist in me. I perceive the whole of human history
in a single instant, the past and the present.
"By simply straining I can see farther and farther back. Now I am
going back through strange curves and angles. Angles and curves
multiply about me. I perceive great segments of time through curves.
There is curved time, and angular time. The beings that exist in
angular time can not enter curved time. It is very strange.
"I am going back and back. Man has disappeared from the earth.
Gigantic reptiles crouch beneath enormous palms and swim through
the loathly black waters of dismal lakes. Now the reptiles have
disappeared. No animals remain upon the land, but beneath the
waters, plainly visible to me, dark forms move slowly over the rotting
vegetation.
"The forms are becoming simpler and simpler. Now they are single
cells. All about me there are angles—strange angles that have no
counterparts on the earth. I am desperately afraid.
"There is an abyss of being which man has never fathomed."
I stared. Chalmers had risen to his feet and he was gesticulating
helplessly with his arms. "I am passing through unearthly angles; I
am approaching—oh, the burning horror of it!"
"Chalmers!" I cried. "Do you wish me to interfere?"
He brought his right hand quickly before his face, as though to shut
out a vision unspeakable. "Not yet!" he cried; "I will go on. I will see
—what—lies—beyond——"
A cold sweat streamed from his forehead and his shoulders jerked
spasmodically. "Beyond life there are"—his face grew ashen with
terror—"things that I can not distinguish. They move slowly through
angles. They have no bodies, and they move slowly through
outrageous angles."
It was then that I became aware of the odor in the room. It was a
pungent, indescribable odor, so nauseous that I could scarcely endure
it. I stepped quickly to the window and threw it open. When I
returned to Chalmers and looked into his eyes I nearly fainted.
"I think they have scented me!" he shrieked. "They are slowly turning
toward me."
He was trembling horribly. For a moment he clawed at the air with his
hands. Then his legs gave way beneath him and he fell forward on
his face, slobbering and moaning.
I watched him in silence as he dragged himself across the floor. He
was no longer a man. His teeth were bared and saliva dripped from
the corners of his mouth.
"Chalmers," I cried. "Chalmers, stop it! Stop it, do you hear?"
As if in reply to my appeal he commenced to utter hoarse convulsive
sounds which resembled nothing so much as the barking of a dog,
and began a sort of hideous writhing in a circle about the room. I
bent and seized him by the shoulders. Violently, desperately, I shook
him. He turned his head and snapped at my wrist. I was sick with
horror, but I dared not release him for fear that he would destroy
himself in a paroxysm of rage.
"Chalmers," I muttered, "you must stop that. There is nothing in this
room that can harm you. Do you understand?"
I continued to shake and admonish him, and gradually the madness
died out of his face. Shivering convulsively, he crumpled into a
grotesque heap on the Chinese rug.
I carried him to the sofa and deposited him upon it. His features were
twisted in pain, and I knew that he was still struggling dumbly to
escape from abominable memories.
"Whisky," he muttered. "You'll find a flask in the cabinet by the
window—upper left-hand drawer."
When I handed him the flask his fingers tightened about it until the
knuckles showed blue. "They nearly got me," he gasped. He drained
the stimulant in immoderate gulps, and gradually the color crept back
into his face.
"That drug was the very devil!" I murmured.
"It wasn't the drug," he moaned.
His eyes no longer glared insanely, but he still wore the look of a lost
soul.
"They scented me in time," he moaned. "I went too far."
"What were they like?" I said, to humor him.
He leaned forward and gripped my arm. He was shivering horribly.
"No word in our language can describe them!" He spoke in a hoarse
whisper. "They are symbolized vaguely in the myth of the Fall, and in
an obscene form which is occasionally found engraven on ancient
tablets. The Greeks had a name for them, which veiled their essential
foulness. The tree, the snake and the apple—these are the vague
symbols of a most awful mystery."
His voice had risen to a scream. "Frank, Frank, a terrible and
unspeakable deed was done in the beginning. Before time, the deed,
and from the deed——"
He had risen and was hysterically pacing the room. "The seeds of the
deed move through angles in dim recesses of time. They are hungry
and athirst!"
"Chalmers," I pleaded to quiet him. "We are living in the third decade
of the Twentieth Century."
"They are lean and athirst!" he shrieked. "The Hounds of Tindalos!"
"Chalmers, shall I phone for a physician?"
"A physician can not help me now. They are horrors of the soul, and
yet"—he hid his face in his hands and groaned—"they are real, Frank.
I saw them for a ghastly moment. For a moment I stood on the other
side. I stood on the pale gray shores beyond time and space. In an
awful light that was not light, in a silence that shrieked, I saw them.
"All the evil in the universe was concentrated in their lean, hungry
bodies. Or had they bodies? I saw them only for a moment; I can not
be certain. But I heard them breathe. Indescribably for a moment I
felt their breath upon my face. They turned toward me and I fled
screaming. In a single moment I fled screaming through time. I fled
down quintillions of years.
"But they scented me. Men awake in them cosmic hungers. We have
escaped, momentarily, from the foulness that rings them round. They
thirst for that in us which is clean, which emerged from the deed
without stain. There is a part of us which did not partake in the deed,
and that they hate. But do not imagine that they are literally,
prosaically evil. They are beyond good and evil as we know it. They
are that which in the beginning fell away from cleanliness. Through
the deed they became bodies of death, receptacles of all foulness.
But they are not evil in our sense because in the spheres through
which they move there is no thought, no morals, no right or wrong as
we understand it. There is merely the pure and the foul. The foul
expresses itself through angles; the pure through curves. Man, the
pure part of him, is descended from a curve. Do not laugh. I mean
that literally."
I rose and searched for my hat. "I'm dreadfully sorry for you,
Chalmers," I said, as I walked toward the door. "But I don't intend to
stay and listen to such gibberish. I'll send my physician to see you.
He's an elderly, kindly chap and he won't be offended if you tell him
to go to the devil. But I hope you'll respect his advice. A week's rest
in a good sanitarium should benefit you immeasurably."
I heard him laughing as I descended the stairs, but his laughter was
so utterly mirthless that it moved me to tears.
Updated editions will replace the previous one—the old editions will
be renamed.
1.D. The copyright laws of the place where you are located also
govern what you can do with this work. Copyright laws in most
countries are in a constant state of change. If you are outside the
United States, check the laws of your country in addition to the
terms of this agreement before downloading, copying, displaying,
performing, distributing or creating derivative works based on this
work or any other Project Gutenberg™ work. The Foundation makes
no representations concerning the copyright status of any work in
any country other than the United States.
1.E.6. You may convert to and distribute this work in any binary,
compressed, marked up, nonproprietary or proprietary form,
including any word processing or hypertext form. However, if you
provide access to or distribute copies of a Project Gutenberg™ work
in a format other than “Plain Vanilla ASCII” or other format used in
the official version posted on the official Project Gutenberg™ website
(www.gutenberg.org), you must, at no additional cost, fee or
expense to the user, provide a copy, a means of exporting a copy, or
a means of obtaining a copy upon request, of the work in its original
“Plain Vanilla ASCII” or other form. Any alternate format must
include the full Project Gutenberg™ License as specified in
paragraph 1.E.1.
• You pay a royalty fee of 20% of the gross profits you derive
from the use of Project Gutenberg™ works calculated using the
method you already use to calculate your applicable taxes. The
fee is owed to the owner of the Project Gutenberg™ trademark,
but he has agreed to donate royalties under this paragraph to
the Project Gutenberg Literary Archive Foundation. Royalty
payments must be paid within 60 days following each date on
which you prepare (or are legally required to prepare) your
periodic tax returns. Royalty payments should be clearly marked
as such and sent to the Project Gutenberg Literary Archive
Foundation at the address specified in Section 4, “Information
Welcome to our website – the ideal destination for book lovers and
knowledge seekers. With a mission to inspire endlessly, we offer a
vast collection of books, ranging from classic literary works to
specialized publications, self-development books, and children's
literature. Each book is a new journey of discovery, expanding
knowledge and enriching the soul of the reade
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.
ebookmass.com