100% found this document useful (5 votes)
11 views

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

Cruz

Uploaded by

everoyobidah
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
100% found this document useful (5 votes)
11 views

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

Cruz

Uploaded by

everoyobidah
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 76

Download Full Version ebookmass - Visit ebookmass.

com

Flame Game Development: Your Guide to Creating


Cross-Platform Games in 2D Using Flame Engine in
Flutter 3 1st Edition Andrés Cruz Yoris

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

Discover More Ebook - Explore Now at ebookmass.com


Instant digital products (PDF, ePub, MOBI) ready for you
Download now and discover formats that fit your needs...

Flame Game Development: Your Guide to Creating Cross-


Platform Games in 2D Using Flame Engine in Flutter 3 1st
Edition Andrés Cruz Yoris
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/
ebookmass.com

Beginning Game Development with Godot (for John Malkovec):


Learn to Create and Publish Your First 2D Platform Game
Maithili Dhule
https://ebookmass.com/product/beginning-game-development-with-godot-
for-john-malkovec-learn-to-create-and-publish-your-first-2d-platform-
game-maithili-dhule/
ebookmass.com

Firefighter's Secret Flame Reign

https://ebookmass.com/product/firefighters-secret-flame-reign/

ebookmass.com

Blossom (Black Rose) Helen Hardt

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

Hábitos dos Milionários: Os segredos por trás das maiores


fortunas do mundo Napoleon Hill

https://ebookmass.com/product/habitos-dos-milionarios-os-segredos-por-
tras-das-maiores-fortunas-do-mundo-napoleon-hill/

ebookmass.com

Supreme Chess Understanding - Statics & Dynamics, Thinkers


Publishing 2023 Wojciech Moranda

https://ebookmass.com/product/supreme-chess-understanding-statics-
dynamics-thinkers-publishing-2023-wojciech-moranda/

ebookmass.com

The Husband Heist (The Dainty Devils Book 3) Alyxandra


Harvey

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

Andrés Cruz Yoris


Flame Game Development: Your Guide to Creating Cross-Platform Games in
2D Using Flame Engine in Flutter 3
Andrés Cruz Yoris
Caracas, Venezuela

ISBN-13 (pbk): 979-8-8688-0062-7 ISBN-13 (electronic): 979-8-8688-0063-4


https://doi.org/10.1007/979-8-8688-0063-4
Copyright © 2024 by Andrés Cruz Yoris
This work is subject to copyright. All rights are reserved by the Publisher, whether the whole or part of the
material is concerned, specifically the rights of translation, reprinting, reuse of illustrations, recitation,
broadcasting, reproduction on microfilms or in any other physical way, and transmission or information
storage and retrieval, electronic adaptation, computer software, or by similar or dissimilar methodology now
known or hereafter developed.
Trademarked names, logos, and images may appear in this book. Rather than use a trademark symbol with
every occurrence of a trademarked name, logo, or image we use the names, logos, and images only in an
editorial fashion and to the benefit of the trademark owner, with no intention of infringement of the
trademark.
The use in this publication of trade names, trademarks, service marks, and similar terms, even if they are not
identified as such, is not to be taken as an expression of opinion as to whether or not they are subject to
proprietary rights.
While the advice and information in this book are believed to be true and accurate at the date of publication,
neither the authors nor the editors nor the publisher can accept any legal responsibility for any errors or
omissions that may be made. The publisher makes no warranty, express or implied, with respect to the
material contained herein.
Managing Director, Apress Media LLC: Welmoed Spahr
Acquisitions Editor: Jessica Vakili
Development Editor: James Markham
Coordinating Editor: Spandana Chatterjee
Distributed to the book trade worldwide by Apress Media, LLC, 1 New York Plaza, New York, NY 10004,
U.S.A. Phone 1-800-SPRINGER, fax (201) 348-4505, e-mail [email protected], or visit
www.springeronline.com. Apress Media, LLC is a California LLC and the sole member (owner) is Springer
Science + Business Media Finance Inc (SSBM Finance Inc). SSBM Finance Inc is a Delaware corporation.
For information on translations, please e-mail [email protected]; for reprint,
paperback, or audio rights, please e-mail [email protected].
Apress titles may be purchased in bulk for academic, corporate, or promotional use. eBook versions and
licenses are also available for most titles. For more information, reference our Print and eBook Bulk Sales
web page at http://www.apress.com/bulk-sales.
Any source code or other supplementary material referenced by the author in this book is available to
readers on GitHub (https://github.com/Apress/Flame-Game-Development). For more detailed information,
please visit https://www.apress.com/gp/services/source-code.
Paper in this product is recyclable
Table of Contents
About the Author����������������������������������������������������������������������������������������������������� xi

About the Technical Reviewer������������������������������������������������������������������������������� xiii


Acknowledgments���������������������������������������������������������������������������������������������������xv

Introduction�����������������������������������������������������������������������������������������������������������xvii

Chapter 1: Create a Project in Flutter and Add Flame���������������������������������������������� 1

Chapter 2: Flame Basics������������������������������������������������������������������������������������������� 3


Game Class and Components������������������������������������������������������������������������������������������������������� 3
Components���������������������������������������������������������������������������������������������������������������������������� 4
Game Classes: Game and FlameGame������������������������������������������������������������������������������������ 5
Key Processes and Methods in Flame���������������������������������������������������������������������������������������� 13
Game Loop����������������������������������������������������������������������������������������������������������������������������� 14
Other Important Functions in Flame�������������������������������������������������������������������������������������� 16

Chapter 3: Flame Fundamentals����������������������������������������������������������������������������� 17


SpriteComponent: Components for Rendering Images��������������������������������������������������������������� 17
Practical Case: Single-Image Sprite�������������������������������������������������������������������������������������� 19
Practical Case: Sprite Sheet�������������������������������������������������������������������������������������������������� 24
Practical Case: Animate the Sprite Sheet������������������������������������������������������������������������������ 33
Practical Case: Multiple Animations�������������������������������������������������������������������������������������� 37
Input: Keyboard��������������������������������������������������������������������������������������������������������������������������� 40
Game Class Level������������������������������������������������������������������������������������������������������������������ 41
Component Level������������������������������������������������������������������������������������������������������������������� 43
Input: Tap������������������������������������������������������������������������������������������������������������������������������������� 45
Game Class level������������������������������������������������������������������������������������������������������������������� 45
Component Level������������������������������������������������������������������������������������������������������������������� 47

iii
Table of Contents

Challenge: Animations and Inputs (Keyboard) – Walk and Idle Animations�������������������������������� 49


Resolution for the Challenge������������������������������������������������������������������������������������������������� 50
Mirror or Flip the Sprite�������������������������������������������������������������������������������������������������������������� 51
Practical Case������������������������������������������������������������������������������������������������������������������������ 52
Constant Velocity������������������������������������������������������������������������������������������������������������������������� 56
Key Combination������������������������������������������������������������������������������������������������������������������������� 59
PositionComponent: Components to Render Objects������������������������������������������������������������������ 61
Practical Case������������������������������������������������������������������������������������������������������������������������ 62
Debug Mode�������������������������������������������������������������������������������������������������������������������������������� 66
Detect Collisions������������������������������������������������������������������������������������������������������������������������� 67
Practical Case������������������������������������������������������������������������������������������������������������������������ 67

Chapter 4: Game 1: Meteor Shower������������������������������������������������������������������������ 83


Offset Collision Circles on the Vertical Axis��������������������������������������������������������������������������������� 92
Add Collision Circles by Time������������������������������������������������������������������������������������������������������ 94
Remove Invisible Components (Collision Circles)����������������������������������������������������������������������� 96
Prevent the Player from Crossing the Screen����������������������������������������������������������������������������� 97
Player: Vary Animation When Detecting Screen Edge��������������������������������������������������������������� 102
Gravity for the Player���������������������������������������������������������������������������������������������������������������� 105
Player: Implement Jump����������������������������������������������������������������������������������������������������������� 107
Modularize the Player Class������������������������������������������������������������������������������������������������������ 111
Meteor Animated Sprite������������������������������������������������������������������������������������������������������������ 118
Impact Counter������������������������������������������������������������������������������������������������������������������������� 121

Chapter 5: Background Color and Image�������������������������������������������������������������� 125


Background Color��������������������������������������������������������������������������������������������������������������������� 125
Background Image�������������������������������������������������������������������������������������������������������������������� 128
Get Component Information from the Game Class�������������������������������������������������������������������� 130
Update the Player Component with Map Dimensions��������������������������������������������������������� 136
Set the Camera to Follow the Component��������������������������������������������������������������������������� 138
Update the Meteor Component with Map Dimensions�������������������������������������������������������� 144

iv
Table of Contents

Chapter 6: Tiled Background�������������������������������������������������������������������������������� 149


Creating Our First Map with Tiled Map Editor��������������������������������������������������������������������������� 150
Use the Tiled Map��������������������������������������������������������������������������������������������������������������������� 163
Create TiledComponent������������������������������������������������������������������������������������������������������� 165
Iterate the Object Layer and Define a PositionComponent������������������������������������������������������� 167
Update the Gravity Component������������������������������������������������������������������������������������������������� 170

Chapter 7: Game 2: Jump Between Tiles�������������������������������������������������������������� 175


Detect When the Player Is Jumping������������������������������������������������������������������������������������������ 175
Changes to the Jump and Move Component���������������������������������������������������������������������������� 179
Lock the Jump��������������������������������������������������������������������������������������������������������������������� 179
Arched Jump and Movement Modifications������������������������������������������������������������������������ 180
Movement of the Player in the Tiles������������������������������������������������������������������������������������ 184
Horizontal Movement with the Velocity Vector�������������������������������������������������������������������������� 186
Create Multiple Hitbox Components for the Player�������������������������������������������������������������� 189
Modify Movement���������������������������������������������������������������������������������������������������������������� 191
Player Position�������������������������������������������������������������������������������������������������������������������������� 194
Add the Meteorite Component�������������������������������������������������������������������������������������������������� 194
New Map����������������������������������������������������������������������������������������������������������������������������������� 195
Overlay�������������������������������������������������������������������������������������������������������������������������������������� 197
Overlay: Show the Number of Collisions����������������������������������������������������������������������������� 197
Overlay: Game Over������������������������������������������������������������������������������������������������������������� 199
Overlay Functions���������������������������������������������������������������������������������������������������������������� 202
Game Instance in Components and Communication with Overlays������������������������������������ 203
Game Instance in Overlays and Communication with Components������������������������������������ 205
Reset����������������������������������������������������������������������������������������������������������������������������������� 207
Lives������������������������������������������������������������������������������������������������������������������������������������ 211
Pause����������������������������������������������������������������������������������������������������������������������������������� 214
Restart Level Button������������������������������������������������������������������������������������������������������������ 216
Types of Collisions�������������������������������������������������������������������������������������������������������������������� 217
Use Case: Correct the Counter of Collisions with Meteorites���������������������������������������������� 217

v
Table of Contents

Update the position Property with Delta Time��������������������������������������������������������������������������� 220


Block Player Movement by Time����������������������������������������������������������������������������������������������� 224
Invincibility�������������������������������������������������������������������������������������������������������������������������������� 227
Consumables on the Map��������������������������������������������������������������������������������������������������������� 229
Render Consumables on the Map���������������������������������������������������������������������������������������� 230
Recover a Life���������������������������������������������������������������������������������������������������������������������� 234
Problem When Restarting the Game������������������������������������������������������������������������������������ 235
Overwrite Consumables at Reboot�������������������������������������������������������������������������������������� 236
Invincibility�������������������������������������������������������������������������������������������������������������������������� 238
Game Over��������������������������������������������������������������������������������������������������������������������������� 239

Chapter 8: Game 2: Many Experiments���������������������������������������������������������������� 241


Vary the Jump��������������������������������������������������������������������������������������������������������������������������� 241
Background Image�������������������������������������������������������������������������������������������������������������������� 246
Map Size and Player Movement������������������������������������������������������������������������������������������������ 247
Alternative 1������������������������������������������������������������������������������������������������������������������������ 247
Alternative 2������������������������������������������������������������������������������������������������������������������������ 249
Conclusion��������������������������������������������������������������������������������������������������������������������������� 251
Correct Unevenness Between Player Positioning and Tiles������������������������������������������������������ 252
Prevent the Player from Falling at a Very High Speed�������������������������������������������������������������� 254
Mathematical Formulas for Collision Detection������������������������������������������������������������������������ 255
Implementation������������������������������������������������������������������������������������������������������������������� 255
Implement the Game on Small Screens������������������������������������������������������������������������������������ 270

Chapter 9: Game 3: Move XY�������������������������������������������������������������������������������� 271


Creating the Bases of the Game����������������������������������������������������������������������������������������������� 272
Creating the Map���������������������������������������������������������������������������������������������������������������������� 273
Create���������������������������������������������������������������������������������������������������������������������������������� 274
Design��������������������������������������������������������������������������������������������������������������������������������� 274
Object Layer������������������������������������������������������������������������������������������������������������������������ 276
Import into the Project��������������������������������������������������������������������������������������������������������� 279
Base Class�������������������������������������������������������������������������������������������������������������������������������� 282

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

Chapter 10: Game 3: Enemies������������������������������������������������������������������������������� 319


Refresh the Sprite��������������������������������������������������������������������������������������������������������������������� 322
Collisions Between Objects and Boundaries for the Map��������������������������������������������������������� 324
Change the Position Based on a Pattern����������������������������������������������������������������������������������� 327
Set the Object Layer for Enemies���������������������������������������������������������������������������������������������� 333
Skeleton Class�������������������������������������������������������������������������������������������������������������������������� 333
Load Enemies Based on the Map���������������������������������������������������������������������������������������������� 337

Chapter 11: Game 4: Plants vs. Zombies�������������������������������������������������������������� 341


Map������������������������������������������������������������������������������������������������������������������������������������������� 341
Define the Map�������������������������������������������������������������������������������������������������������������������� 341
Load the Map����������������������������������������������������������������������������������������������������������������������� 345
Plants���������������������������������������������������������������������������������������������������������������������������������������� 345
Sprites��������������������������������������������������������������������������������������������������������������������������������� 346
Base Classes����������������������������������������������������������������������������������������������������������������������� 346
FlameGame: Add One Plant by Tap�������������������������������������������������������������������������������������� 351
Component: Add a Plant by Tap������������������������������������������������������������������������������������������� 352

vii
Table of Contents

Seed Size����������������������������������������������������������������������������������������������������������������������������� 355


Avoid Adding Several Plants in One Place��������������������������������������������������������������������������� 356
Zombies������������������������������������������������������������������������������������������������������������������������������������ 358
Base Classes����������������������������������������������������������������������������������������������������������������������� 358
Level Enemies/Zombies������������������������������������������������������������������������������������������������������� 361
Define Logic for Channels��������������������������������������������������������������������������������������������������� 365
Attacks�������������������������������������������������������������������������������������������������������������������������������������� 368
Change Animation of Plants in Attack Mode������������������������������������������������������������������������ 369
Projectile: Create Structure������������������������������������������������������������������������������������������������� 370
Projectile: Shoot������������������������������������������������������������������������������������������������������������������ 371
Projectile: Starting Position������������������������������������������������������������������������������������������������� 375
Life and Collisions��������������������������������������������������������������������������������������������������������������� 377

Chapter 12: Game 4: Many Experiments�������������������������������������������������������������� 389


Plant Overlay����������������������������������������������������������������������������������������������������������������������������� 389
Mark the Selected Option���������������������������������������������������������������������������������������������������� 393
Suns������������������������������������������������������������������������������������������������������������������������������������������ 395
Moving Suns in a Wavy Way������������������������������������������������������������������������������������������������ 398
Sun Counter������������������������������������������������������������������������������������������������������������������������� 400
Suns Overlay����������������������������������������������������������������������������������������������������������������������� 402
Cost per Plant���������������������������������������������������������������������������������������������������������������������� 406
Plant Overlay Transparency������������������������������������������������������������������������������������������������� 407
Generate Suns on Map Space��������������������������������������������������������������������������������������������� 409
Plant Recharge�������������������������������������������������������������������������������������������������������������������� 410
Pause���������������������������������������������������������������������������������������������������������������������������������������� 426
Reset����������������������������������������������������������������������������������������������������������������������������������������� 428
Move the Camera Using the Drag Event����������������������������������������������������������������������������������� 432
Implementation������������������������������������������������������������������������������������������������������������������� 434
Scale Components to Window Size������������������������������������������������������������������������������������������� 438

viii
Table of Contents

Chapter 13: Game 5: Parallax Backgrounds��������������������������������������������������������� 447


Configure the Project���������������������������������������������������������������������������������������������������������������� 447
Create the Parallax Effect��������������������������������������������������������������������������������������������������������� 448
Vary Speed in Layers����������������������������������������������������������������������������������������������������������� 450
Create a Component Class for the Parallax������������������������������������������������������������������������� 451
Player���������������������������������������������������������������������������������������������������������������������������������������� 452
Rotation������������������������������������������������������������������������������������������������������������������������������� 456
Foods (Sweets)������������������������������������������������������������������������������������������������������������������������� 460
Help Functions and Base Structure������������������������������������������������������������������������������������� 462
Food Component (Sweet)���������������������������������������������������������������������������������������������������� 465
Eat Food������������������������������������������������������������������������������������������������������������������������������������ 474
Play the Chewing Animation������������������������������������������������������������������������������������������������ 476
Do Not Eat Food While Chewing������������������������������������������������������������������������������������������ 477
Eating Food in One Position������������������������������������������������������������������������������������������������� 478
Show Statistics in an Overlay��������������������������������������������������������������������������������������������������� 479
Implement Ways of Gameplay��������������������������������������������������������������������������������������������������� 485
1: Losing a Candy���������������������������������������������������������������������������������������������������������������� 488
2: Get a Minimum of Points������������������������������������������������������������������������������������������������� 488
3: Only Consume One Type of Sweet����������������������������������������������������������������������������������� 489
4: Cannot Consume a Type of Sweet����������������������������������������������������������������������������������� 490
Test Previous Implementations������������������������������������������������������������������������������������������� 491
Define Multiple Levels��������������������������������������������������������������������������������������������������������������� 494
Function to Load Game Levels�������������������������������������������������������������������������������������������������� 497
Overlays������������������������������������������������������������������������������������������������������������������������������������ 499
Game Over��������������������������������������������������������������������������������������������������������������������������� 500
Game Actions����������������������������������������������������������������������������������������������������������������������� 502
Select a Level���������������������������������������������������������������������������������������������������������������������� 504
Select a Gameplay��������������������������������������������������������������������������������������������������������������� 509
Information About the Type of Game and Level������������������������������������������������������������������� 514

ix
Table of Contents

GameOver: Implement Game Types������������������������������������������������������������������������������������������ 517


Next Level��������������������������������������������������������������������������������������������������������������������������������� 519
Virtual Joystick�������������������������������������������������������������������������������������������������������������������������� 520
Button to Rotate the Player������������������������������������������������������������������������������������������������������� 525
Gamepad����������������������������������������������������������������������������������������������������������������������������������� 529
First Steps with the gamepads Plugin��������������������������������������������������������������������������������� 530
SharedPreferences: Set Game State����������������������������������������������������������������������������������������� 535
Adapt to Small Screens������������������������������������������������������������������������������������������������������������� 537

Chapter 14: Audio������������������������������������������������������������������������������������������������� 541


Dino Jump Project��������������������������������������������������������������������������������������������������������������������� 542
Background Music��������������������������������������������������������������������������������������������������������������� 543
Audios for Actions���������������������������������������������������������������������������������������������������������������� 544
Plants vs. Zombies�������������������������������������������������������������������������������������������������������������������� 549
Zombies: Base Sound���������������������������������������������������������������������������������������������������������� 550
Customize Sound for Each Zombie Component������������������������������������������������������������������ 551
Detect Game Over���������������������������������������������������������������������������������������������������������������� 552
Parallax������������������������������������������������������������������������������������������������������������������������������������� 556
Basic Sounds����������������������������������������������������������������������������������������������������������������������� 556
Implementation������������������������������������������������������������������������������������������������������������������� 557

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.

2. It is assumed that you have at least basic knowledge of Flutter and


its basic technologies such as Dart.

Flame is a very interesting package to create our first multiplatform 2D games.


Being implemented in Flutter, with a single project, we can have the same game
for mobile, desktop, and web without much problem. Flame contains all the basic
elements to create 2D games provided by similar game engines like collision
handling, events, sprite loading, sprite sheet, and of course interacting with all
these elements.

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

Create a Project in Flutter


and Add Flame
In this chapter, we are going to learn how to create a Flutter project and add the
necessary base library to develop our 2D games using Flutter; therefore, it is a chapter
that you should refer to every time we create a new project in later chapters.
Let’s start by creating the project that we will use to create the application:

$ flutter create <ProjectName>

Once the project is created in Flutter, we change to the project folder:

$ cd <ProjectName>

And we add the Flame library:

$ flutter pub add flame

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.

Game Class and Components


A project in Flame can be divided into two parts:

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

Figure 2-1. Widgets in Flutter vs. components in Flame

Let’s get to know each of these Flame elements in more detail.

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

You can see the complete list at ­https://docs.flame-engine.org/latest/flame/


components.html.

4
Chapter 2 Flame Basics

Game Classes: Game and FlameGame


As we do in any project, it is important to have a base structure that we can easily
maintain and scale. Flame is designed for modularity. Globally, we have a Game class
that gives us a lot of control over each of the components that make up the application.
This Game class is global to the entire application and can be represented by many
types of classes; FlameGame is the most widely used Game class in Flame, and it’s the
one we’ll mainly be looking at in this book. Any component we add in the FlameGame
class can be used for collision detection, providing an easy way for components to
communicate in Flame.
Thanks to the FlameGame class, which is a Game-type class of the application, it is
possible to divide our game into components (classes) that represent each entity in our
game, such as a player, a background, enemies, a setting, etc.
You can find more information in https://docs.flame-engine.org/latest/flame/
game.html.
Regarding the class itself called Game, it is a low-level class. Like the FlameGame
class, we can use it as the main class or the Game-type class for the game, but unlike
FlameGame, it offers a more basic approach with which to create the game; for
example, we do not have access to adding components in separate classes, and we must
implement the update() and render() methods, which we will talk about later.
In this book, when referring to the term “Game-type class,” it refers to any of this
type of classes, which allow the creation of a global instance of the game; as we indicated
before, the FlameGame class is the one that we are going to use throughout the book to
develop the applications, since it allows us to use the typical Flame functionalities, such
as collision handling and managing components in classes.

Example 1: Draw a Sprite


In the following code, you can see the basic structure of an application in Flame, in
which we have the FlameGame class with its definition and subsequent addition of a
component:

import 'package:flame/components.dart';
import 'package:flame/game.dart';
import 'package:flutter/material.dart';

5
Chapter 2 Flame Basics

class MySprite extends SpriteComponent {


  MySprite() : super(size: Vector2.all(16));

  @override
  void onLoad() async {
    sprite = await Sprite.load('image.png');
  }
}

class MyGame extends FlameGame {


  @override
  void onLoad() async {
    await add(MySprite());
  }
}

main() {
  runApp(GameWidget(game: MyGame()));
}

For the preceding implementation, we load an image:

sprite = await Sprite.load('image.png');

This image must exist in the following path:

assets/images/image.png

And register the image in the app:

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)

Then we add it from the global instance:

add(MySprite());

Once an image is registered in your project, you will see a result like the following.
6
Chapter 2 Flame Basics

Figure 2-2. Example sprite

Example 2: Draw a Circle


In this example, we’ll see how to draw a circle with the FlameGame class:

lib/main.dart

import 'package:flame/components.dart';
import 'package:flame/game.dart';
import 'package:flame/palette.dart';
import 'package:flutter/material.dart';

class MyCircle extends PositionComponent {


  MyCircle() : super();

  @override
  void onLoad() async {}

  @override
  void render(Canvas canvas) {
    canvas.drawCircle(const Offset(10, 10), 10, BasicPalette.red.paint());

    // canvas.drawRect(Rect.fromCircle(center: const Offset(0, 0),


radius: 20),
    //     BasicPalette.red.paint());
  }
}
7
Chapter 2 Flame Basics

class MyGame extends FlameGame {


  @override
  void onLoad() async {
    await add(MyCircle());
  }
}

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';

void main() async {


  runApp(GameWidget(game: MyCircle()));
}

class MyCircle with Game {


  @override
  void onLoad() async {
    super.onLoad();
    // init
  }

  @override
  void render(Canvas canvas) {
    canvas.drawCircle(const Offset(10, 10), 10, BasicPalette.red.paint());

    // canvas.drawRect(Rect.fromCircle(center: const Offset(0, 0),


radius: 20),
    //     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.

Figure 2-3. Circle drawn with Flame

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:

class PositionComponent extends Component


    implements
        AnchorProvider,
        AngleProvider,
        PositionProvider,

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:

canvas.drawRect(Rect.fromPoints(const Offset(10,10), const


Offset(500,500)), BasicPalette.purple.paint());

Or instead of drawing a circle with canvas.drawCircle(), we draw a rectangle using


a circle:

canvas.drawRect(Rect.fromCircle(center: const Offset(100, 100), radius:


50.0),BasicPalette.brown.paint());

Example 3: Update the Circle Position


Another example, a little more elaborate in which additional functions are used to
update the game, is creating a circle that we move from left to right until it disappears
from the screen in a few seconds. Let’s look at both implementations, first, with the
FlameGame class:

import 'package:flame/components.dart';
import 'package:flame/game.dart';
import 'package:flame/palette.dart';
import 'package:flutter/material.dart';

class MyCircle extends PositionComponent {


  MyCircle() : super();

10
Chapter 2 Flame Basics

  double circlePos = 10;


  final Paint _paint = BasicPalette.red.paint();

  @override
  void onLoad() async {}

  @override
  void render(Canvas canvas) {
    canvas.drawCircle(
      Offset(circlePos, circlePos),
      10,
      _paint
    );

    // canvas.drawRect(Rect.fromCircle(center: const Offset(0, 0),


radius: 20),
    //     _paint );
  }

  @override
  void update(double dt) {
    super.update(dt);
    circlePos++;
  }
}

class MyGame extends FlameGame {


  @override
  void onLoad() async {
    await add(MyCircle());
  }
}

main() {
  runApp(GameWidget(game: MyGame()));
}

11
Chapter 2 Flame Basics

And here’s with the Game class:

import 'package:flame/palette.dart';
import 'package:flutter/material.dart';
import 'package:flame/game.dart';

void main() async {


  runApp(GameWidget(game: MyCircle()));
}

class MyCircle with Game {


  double circlePos = 10;

  @override
  void onLoad() async {
    super.onLoad();
    // init
  }

  @override
  void render(Canvas canvas) {
    canvas.drawCircle(
        Offset(circlePos, circlePos), 10, BasicPalette.red.paint());

    // canvas.drawRect(Rect.fromCircle(center: const Offset(0, 0),


radius: 20),
    //     _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

implementation. Additionally, in the Game class, it is mandatory to implement the


render() method (to draw on the canvas, in this case, the circle) and update() method
(to make updates to the game), which we will explain in the next section.
At the moment we will not go into detail about what each of the lines of code allows
to carry out. The important thing is to note the implementations of both Game-type
classes and compare them. In the next chapter, we’ll go into detail and explain what each
line of code in the preceding examples carries out.
In the Flame API, there is also a component called CircleComponent that we could
also use in a similar way:

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:

canvas.drawRect(Rect.fromCircle(center: const Offset(0, 0), radius: 20,


_paint);

Key Processes and Methods in Flame


In this section, we will get to know the basic cycle of a game and, with this, its key
functions. Every existing game, regardless of the engine used to create it, consists of two
defined processes:

1. A process that allows us to draw on a canvas, that is, we can draw


figures and images on the canvas to display them on the screen.
Its use is very similar to what we can handle in the HTML API.

2. Another process that updates the elements of the game. For


example, suppose we have a player. Then, by clicking buttons
on the screen or pressing keys, the player moves; by receiving
damage from the enemy, the player moves. You can implement
this same logic in other types of components and scenarios. To
give another example, we can have a grass component, which,
when a character steps on it, becomes deformed, and this said
deformation in this case is done by the interaction between the
components: the grass and the player.

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.

Devices work at different speeds, depending on the processing power (i.e.,


depending on what processor the device has, specifically the frequency at which
the processor works), so if we ignore the delta value and just run everything
at the maximum speed the processor can run it, the game might have speed
issues to control your character properly as it would be too fast or too slow.
By using the deltaTime parameter in our motion calculation, we can guarantee
that our sprites will move at whatever speed we want on devices with different
processor speeds.

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

Other Important Functions in Flame


The preceding functions have an equivalent in the use of components. We have an
update() function to perform updates; like the one in Game-type classes, it receives the
delta time parameter. We also have a function to initialize the components; in this case,
it is called onLoad(), which is used to only initialize data and not to render as it is in the
case of the render() function. We can use this method to, for example, to draw figures or
sprites on the screen.
Of course, there are many more functions in Flame, which we will see as they are
necessary to advance in the different examples that we will see in this book; however,
the functions that we saw in this chapter are key and the most important in Flame.
Remember that this chapter acts as a reference, which you can consult later when you
see the implementations of our games.

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)

A sprite is nothing more than an image that graphically represents an object,


character, or element of the game (like the tiger sprite shown before).
A sprite sheet is nothing more than a collection of images put into a single image,
and they are widely used in any game engine such as Unity. In video game development,
a sprite sheet is an image where all the movements (states) of a character or object
are included; therefore, it is common for a 2D game to have multiple images for each
animable object.
In conclusion, a sprite sheet is an image, for example, a PNG image that we can
upload to render somewhere on the screen.
In Flutter with Flame, we can create our sprites using the SpriteComponent class
and, with this, implement all the necessary logic for some elements of our game, such as
a player, an enemy, non-playable characters, etc.
The SpriteComponent class implements the PositionComponent class that we will
discuss later, in which we must implement three mandatory properties:

18
Chapter 3 Flame Fundamentals

1. position: position is simply a Vector2 that represents the


position of the component relative to its parent; if the parent is a
FlameGame, it is relative to the viewport.
2. size: The size of the component when the camera zoom level is 1.0.

3. sprite: The sprite handled in the component.

You can see the full reference at https://docs.flame-engine.org/latest/flame/


components.html#positioncomponent.
In this book, we will use the properties we need; the preceding link refers to the
PositionComponent, which is implemented by the SpriteComponent class.

Practical Case: Single-Image Sprite


Let’s start by adding some images to our project to start learning how Flame works; to do
this, we will use an icon like the following:
www.flaticon.com/free-icon/tiger_6457888
We must download and incorporate this into our project:

pubspec.yaml

assets/images/tiger.png

We add the image asset:

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';

class PlayerImageSpriteComponent  extends SpriteComponent{

  late double screenWidth;


  late double screenHeight;
19
Chapter 3 Flame Fundamentals

  late double centerX;


  late double centerY;

  final double spriteWidth = 512.0;


  final double spriteHeight = 512.0;

  @override
  void onLoad() async {

    sprite = await Sprite.load('tiger.png');

    screenWidth = MediaQueryData.fromWindow(window).size.width;
    screenHeight = MediaQueryData.fromWindow(window).size.height;

    size = Vector2(spriteWidth, spriteHeight);

    centerX = (screenWidth/2) - (spriteWidth/2);


    centerY = (screenHeight/2) - (spriteHeight/2);

    position = Vector2(centerX, centerY);


  }
}

Explanation of the preceding code


We define the size of the image. In this example, it is a 512-pixel image, but you can
place a different scale, for example, 48 pixels:

final double spriteWidth = 512.0;


final double spriteHeight = 512.0;

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:

class PlayerImageSpriteComponent extends SpriteComponent with


HasGameReference {
}

And with this, we have access to an object game:

game

And with this object, we have the size:

game.size

Therefore, an equivalent to obtain the size would be

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:

centerX = (screenWidth/2) - (spriteWidth/2);


centerY = (screenHeight/2) - (spriteHeight/2);

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:

position = Vector2(centerX, centerY);

We indicate the total size of the image. As with the position, it is indicated by a two-
dimensional vector:

size = Vector2(spriteWidth, spriteHeight);

Finally, we load the image, the sprite:

sprite = await Sprite.load('tiger.png');

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';

class MyGame extends FlameGame with KeyboardEvents {


  @override
  void onLoad() {
    add(PlayerImageSpriteComponent());
  }
}

void main() async {


  runApp(GameWidget(game: MyGame()));
}

22
Chapter 3 Flame Fundamentals

Because we added the component called “PlayerImageSpriteComponent” in


the onLoad() function of the FlameGame class, FlameGame is now tracking that
component.
From the component, its own onLoad() function is called to initialize the sprite;
we could also use additional processes to render additional objects via the render()
function and update the sprite via the update() function as we’ll see later.
Finally, we will see the following on the screen.

Figure 3-3. Draw a sprite in Flame

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

  position = Vector2(centerX++, centerY);

  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:

class PlayerImageSpriteComponent extends SpriteComponent {


  ***
  @override
  void update(double dt) {
    position = Vector2(centerX++, centerY++);
    super.update(dt);
  }
}

Practical Case: Sprite Sheet


Now, we are interested in not only processing a single image but several of them. For
this, we will use an image that consists of several images, like the one presented in the
following.

24
Chapter 3 Flame Fundamentals

Figure 3-4. Player sprite

This sprite sheet simulates a walking motion for our player.


For this example, we have individual images for the walk.

Figure 3-5. Player sprite generated individually

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.

Figure 3-6. Drag-and-drop section for TexturePacker folders or sprites

And we will have the following.

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.

Title: The hounds of Tindalos

Author: Frank Belknap Long

Illustrator: C. C. Senf

Release date: May 8, 2024 [eBook #73575]

Language: English

Original publication: Indianapolois, IN: Popular Fiction Publishing


Company, 1929

Credits: Greg Weeks, Mary Meehan and the Online Distributed


Proofreading Team at http://www.pgdp.net

*** START OF THE PROJECT GUTENBERG EBOOK THE HOUNDS OF


TINDALOS ***
The HOUNDS of TINDALOS

By Frank Belknap Long, Jr.

[Transcriber's Note: This etext was produced from


Weird Tales March 1929.
Extensive research did not uncover any evidence that
the U.S. copyright on this publication was renewed.]
"I'm glad you came," said Chalmers. He was sitting by the window
and his face was very pale. Two tall candles guttered at his elbow
and cast a sickly amber light over his long nose and slightly receding
chin. Chalmers would have nothing modern about his apartment. He
had the soul of a mediæval ascetic, and he preferred illuminated
manuscripts to automobiles and leering stone gargoyles to radios and
adding-machines.
As I crossed the room to the settee he had cleared for me I glanced
at his desk and was surprized to discover that he had been studying
the mathematical formulæ of a celebrated contemporary physicist,
and that he had covered many sheets of thin yellow paper with
curious geometric designs.
"Einstein and John Dee are strange bedfellows," I said as my gaze
wandered from his mathematical charts to the sixty or seventy quaint
books that comprised his strange little library. Plotinus and Emanuel
Moscopulus, St. Thomas Aquinas and Frenicle de Bessy stood elbow
to elbow in the somber ebony bookcase, and chairs, table and desk
were littered with pamphlets about mediæval sorcery and witchcraft
and black magic, and all of the valiant glamorous things that the
modern world has repudiated.
Chalmers smiled engagingly, and passed me a Russian cigarette on a
curiously carved tray. "We are just discovering now," he said, "that
the old alchemists and sorcerers were two-thirds right, and that your
modern biologist and materialist is nine-tenths wrong."
"You have always scoffed at modern science," I said, a little
impatiently.
"Only at scientific dogmatism," he replied. "I have always been a
rebel, a champion of originality and lost causes; that is why I have
chosen to repudiate the conclusions of contemporary biologists."
"And Einstein?" I asked.
"A priest of transcendental mathematics!" he murmured reverently.
"A profound mystic and explorer of the great suspected."
"Then you do not entirely despise science."
"Of course not," he affirmed. "I merely distrust the scientific
positivism of the past fifty years, the positivism of Haeckel and
Darwin and of Mr. Bertrand Russell. I believe that biology has failed
pitifully to explain the mystery of man's origin and destiny."
"Give them time," I retorted.
Chalmers' eyes glowed. "My friend," he murmured, "your pun is
sublime. Give them time. That is precisely what I would do. But your
modern biologist scoffs at time. He has the key but he refuses to use
it. What do we know of time, really? Einstein believes that it is
relative, that it can be interpreted in terms of space, of curved space.
But must we stop there? When mathematics fails us can we not
advance by—insight?"
"You are treading on dangerous ground," I replied. "That is a pit-fall
that your true investigator avoids. That is why modern science has
advanced so slowly. It accepts nothing that it can not demonstrate.
But you——"
"I would take hashish, opium, all manner of drugs. I would emulate
the sages of the East. And then perhaps I would apprehend——"
"What?"
"The fourth dimension."
"Theosophical rubbish!"
"Perhaps. But I believe that drugs expand human consciousness.
William James agreed with me. And I have discovered a new one."
"A new drug?"
"It was used centuries ago by Chinese alchemists, but it is virtually
unknown in the West. Its occult properties are amazing. With its aid
and the aid of my mathematical knowledge I believe that I can go
back through time."
"I do not understand."
"Time is merely our imperfect perception of a new dimension of
space. Time and motion are both illusions. Everything that has
existed from the beginning of the world exists now. Events that
occurred centuries ago on this planet continue to exist in another
dimension of space. Events that will occur centuries from now exist
already. We can not perceive their existence because we can not
enter the dimension of space that contains them. Human beings as
we know them are merely fractions, infinitesimally small fractions of
one enormous whole. Every human being is linked with all the life
that has preceded him on this planet. All of his ancestors are parts of
him. Only time separates him from his forebears, and time is an
illusion and does not exist."
"I think I understand," I murmured.
"It will be sufficient for my purpose if you can form a vague idea of
what I wish to achieve. I wish to strip from my eyes the veils of
illusion that time has thrown over them, and see the beginning and
the end."
"And you think this new drug will help you?"
"I am sure that it will. And I want you to help me. I intend to take
the drug immediately. I can not wait. I must see." His eyes glittered
strangely. "I am going back, back through time."
He rose and strode to the mantel. When he faced me again he was
holding a small square box in the palm of his hand. "I have here five
pellets of the drug Liao. It was used by the Chinese philosopher Lao
Tze, and while under its influence he visioned Tao. Tao is the most
mysterious force in the world; it surrounds and pervades all things; it
contains the visible universe and everything that we call reality. He
who apprehends the mysteries of Tao sees clearly all that was and
will be."
"Rubbish!" I retorted.
"Tao resembles a great animal, recumbent, motionless, containing in
its enormous body all the worlds of our universe, the past, the
present and the future. We see portions of this great monster
through a slit, which we call time. With the aid of this drug I shall
enlarge the slit. I shall behold the great figure of life, the great
recumbent beast in its entirety."
"And what do you wish me to do?"
"Watch, my friend. Watch and take notes. And if I go back too far
you must recall me to reality. You can recall me by shaking me
violently. If I appear to be suffering acute physical pain you must
recall me at once."
"Chalmers," I said, "I wish you wouldn't make this experiment. You
are taking dreadful risks. I don't believe that there is any fourth
dimension and I emphatically do not believe in Tao. And I don't
approve of your experimenting with unknown drugs."
"I know the properties of this drug," he replied. "I know precisely
how it affects the human animal and I know its dangers. The risk
does not reside in the drug itself. My only fear is that I may become
lost in time. You see, I shall assist the drug. Before I swallow this
pellet I shall give my undivided attention to the geometric and
algebraic symbols that I have traced on this paper." He raised the
mathematical chart that rested on his knee. "I shall prepare my mind
for an excursion into time. I shall approach the fourth dimension with
my conscious mind before I take the drug which will enable me to
exercise occult powers of perception. Before I enter the dream world
of the Eastern mystics I shall acquire all of the mathematical help
that modern science can offer. This mathematical knowledge, this
conscious approach to an actual apprehension of the fourth
dimension of time will supplement the work of the drug. The drug will
open up stupendous new vistas—the mathematical preparation will
enable me to grasp them intellectually. I have often grasped the
fourth dimension in dreams, emotionally, intuitively, but I have never
been able to recall, in waking life, the occult splendors that were
momentarily revealed to me.
"But with your aid, I believe that I can recall them. You will take
down everything that I say while I am under the influence of the
drug. No matter how strange or incoherent my speech may become
you will omit nothing. When I awake I may be able to supply the key
to whatever is mysterious or incredible. I am not sure that I shall
succeed, but if I do succeed"—his eyes were strangely luminous
—"time will exist for me no longer!"
He sat down abruptly. "I shall make the experiment at once. Please
stand over there by the window and watch. Have you a fountain
pen?"
I nodded gloomily and removed a pale green Waterman from my
upper vest pocket.
"And a pad, Frank?"
I groaned and produced a memorandum book. "I emphatically
disapprove of this experiment," I muttered. "You're taking a frightful
risk."
"Don't be an asinine old woman!" he admonished. "Nothing that you
can say will induce me to stop now. I entreat you to remain silent
while I study these charts."
He raised the charts and studied them intently. I watched the clock
on the mantel as it ticked out the seconds, and a curious dread
clutched at my heart so that I choked.
Suddenly the clock stopped ticking, and exactly at that moment
Chalmers swallowed the drug.

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.

When Chalmers phoned the following morning my first impulse was


to hang up the receiver immediately. His request was so unusual and
his voice was so wildly hysterical that I feared any further association
with him would result in the impairment of my own sanity. But I could
not doubt the genuineness of his misery, and when he broke down
completely and I heard him sobbing over the wire I decided to
comply with his request.
"Very well," I said. "I will come over immediately and bring the
plaster."
En route to Chalmers' home I stopped at a hardware store and
purchased twenty pounds of plaster of Paris. When I entered my
friend's room he was crouching by the window watching the opposite
wall out of eyes that were feverish with fright. When he saw me he
rose and seized the parcel containing the plaster with an avidity that
amazed and horrified me. He had extruded all of the furniture and
the room presented a desolate appearance.
"It is just conceivable that we can thwart them!" he exclaimed. "But
we must work rapidly. Frank, there is a stepladder in the hall. Bring it
here immediately. And then fetch a pail of water."
"What for?" I murmured.
He turned sharply and there was a flush on his face. "To mix the
plaster, you fool!" he cried. "To mix the plaster that will save our
bodies and souls from a contamination unmentionable. To mix the
plaster that will save the world from—Frank, they must be kept out!"
"Who?" I murmured.
"The Hounds of Tindalos!" he muttered. "They can only reach us
through angles. We must eliminate all angles from this room. I shall
plaster up all of the corners, all of the crevices. We must make this
room resemble the interior of a sphere."
I knew that it would have been useless to argue with him. I fetched
the stepladder, Chalmers mixed the plaster, and for three hours we
labored. We filled in the four corners of the wall and the intersections
of the floor and wall and the wall and ceiling, and we rounded the
sharp angles of the window-seat.
"I shall remain in this room until they return in time," he affirmed
when our task was completed. "When they discover that the scent
leads through curves they will return. They will return ravenous and
snarling and unsatisfied to the foulness that was in the beginning,
before time, beyond space."
He nodded graciously and lit a cigarette. "It was good of you to
help," he said.
"Will you not see a physician, Chalmers?" I pleaded.
"Perhaps—tomorrow," he murmured. "But now I must watch and
wait."
"Wait for what?" I urged.
Chalmers smiled wanly. "I know that you think me insane," he said.
"You have a shrewd but prosaic mind, and you can not conceive of an
entity that does not depend for its existence on force and matter. But
did it ever occur to you, my friend, that force and matter are merely
the barriers to perception imposed by time and space? When one
knows, as I do, that time and space are identical and that they are
both deceptive because they are merely imperfect manifestations of a
higher reality, one no longer seeks in the visible world for an
explanation of the mystery and terror of being."
I rose and walked toward the door.
"Forgive me," he cried. "I did not mean to offend you. You have a
superlative intellect, but I—I have a superhuman one. It is only
natural that I should be aware of your limitations."
"Phone if you need me," I said, and descended the stairs two steps at
a time. "I'll send my physician over at once," I muttered, to myself.
"He's a hopeless maniac, and heaven knows what will happen if
someone doesn't take charge of him immediately."

The following is a condensation of two announcements which


appeared in the Partridgeville Gazette for July 3, 1928:
Earthquake Shakes Financial District

At 2 o'clock this morning an earth tremor of unusual severity broke


several plate-glass windows in Central Square and completely
disorganized the electric and street railway systems. The tremor was
felt in the outlying districts and the steeple of the First Baptist Church
on Angell Hill (designed by Christopher Wren in 1717) was entirely
demolished. Firemen are now attempting to put out a blaze which
threatens to destroy the Partridgeville Glue Works. An investigation is
promised by the mayor and an immediate attempt will be made to fix
responsibility for this disastrous occurrence.

OCCULT WRITER MURDERED BY UNKNOWN GUEST

Horrible Crime in Central Square


Mystery Surrounds Death of Halpin Chalmers

At 9 a.m. today the body of Halpin Chalmers, author and journalist,


was found in an empty room above the jewelry store of Smithwick
and Isaacs, 24 Central Square. The coroner's investigation revealed
that the room had been rented furnished to Mr. Chalmers on May 1,
and that he had himself disposed of the furniture a fortnight ago.
Chalmers was the author of several recondite books on occult
themes, and a member of the Bibliographic Guild. He formerly
resided in Brooklyn, New York.
At 7 a.m. Mr. L. E. Hancock, who occupies the apartment opposite
Chalmers' room in the Smithwick and Isaacs establishment, smelt a
peculiar odor when he opened his door to take in his cat and the
morning edition of the Partridgeville Gazette. The odor he describes
as extremely acrid and nauseous, and he affirms that it was so strong
in the vicinity of Chalmers' room that he was obliged to hold his nose
when he approached that section of the hall.
He was about to return to his own apartment when it occurred to him
that Chalmers might have accidentally forgotten to turn off the gas in
his kitchenette. Becoming considerably alarmed at the thought, he
decided to investigate, and when repeated tappings on Chalmers'
door brought no response he notified the superintendent. The latter
opened the door by means of a pass key, and the two men quickly
made their way into Chalmers' room. The room was utterly destitute
of furniture, and Hancock asserts that when he first glanced at the
floor his heart went cold within him, and that the superintendent,
without saying a word, walked to the open window and stared at the
building opposite for fully five minutes.
Chalmers lay stretched upon his back in the center of the room. He
was starkly nude, and his chest and arms were covered with a
peculiar bluish pus or ichor. His head lay grotesquely upon his chest.
It had been completely severed from his body, and the features were
twisted and torn and horribly mangled. Nowhere was there a trace of
blood.

"He was starkly nude, and twisted and torn."


The room presented a most astonishing appearance. The
intersections of the walls, ceiling and floor had been thickly smeared
with plaster of Paris, but at intervals fragments had cracked and
fallen off, and someone had grouped these upon the floor about the
murdered man so as to form a perfect triangle.
Beside the body were several sheets of charred yellow paper. These
bore fantastic geometric designs and symbols and several hastily
scrawled sentences. The sentences were almost illegible and so
absurd in context that they furnished no possible clue to the
perpetrator of the crime. "I am waiting and watching," Chalmers
wrote. "I sit by the window and watch walls and ceiling. I do not
believe they can reach me, but I must beware of the Doels. Perhaps
they can help them break through. The satyrs will help, and they can
advance through the scarlet circles. The Greeks knew a way of
preventing that. It is a great pity that we have forgotten so much."
On another sheet of paper, the most badly charred of the seven or
eight fragments found by Detective Sergeant Douglas (of the
Partridgeville Reserve), was scrawled the following:
"Good God, the plaster is falling! A terrific shock has loosened the
plaster and it is falling. An earthquake perhaps! I never could have
anticipated this. It is growing dark in the room. I must phone Frank.
But can he get here in time? I will try. I will recite the Einstein
formula. I will—God, they are breaking through! They are breaking
through! Smoke is pouring from the corners of the wall. Their
tongues—ahhhhh——"
In the opinion of Detective Sergeant Douglas, Chalmers was poisoned
by some obscure chemical. He has sent specimens of the strange
blue slime found on Chalmers' body to the Partridgeville Chemical
Laboratories; and he expects the report will shed new light on one of
the most mysterious crimes of recent years. That Chalmers
entertained a guest on the evening preceding the earthquake is
certain, for his neighbor distinctly heard a low murmur of
conversation in the former's room as he passed it on his way to the
stairs. Suspicion points strongly to this unknown visitor and the police
are diligently endeavoring to discover his identity.

Report of James Morton, chemist and bacteriologist:


My dear Mr. Douglas:
The fluid sent to me for analysis is the most peculiar that I have ever
examined. It resembles living protoplasm, but it lacks the peculiar
substances known as enzymes. Enzymes catalyze the chemical
reactions occurring in living cells, and when the cell dies they cause it
to disintegrate by hydrolyzation. Without enzymes protoplasm should
possess enduring vitality, i.e., immortality. Enzymes are the negative
components, so to speak, of unicellular organism, which is the basis
of all life. That living matter can exist without enzymes biologists
emphatically deny. And yet the substance that you have sent me is
alive and it lacks these "indispensable" bodies. Good God, sir, do you
realize what astounding new vistas this opens up?

Excerpt from The Secret Watchers by the late Halpin Chalmers:


What if, parallel to the life we know, there is another life that does
not die, which lacks the elements that destroy our life? Perhaps in
another dimension there is a different force from that which
generates our life. Perhaps this force emits energy, or something
similar to energy, which passes from the unknown dimension where it
is and creates a new form of cell life in our dimension. No one knows
that such new cell life does exist in our dimension. Ah, but I have
seen its manifestations. I have talked with them. In my room at night
I have talked with the Doels. And in dreams I have seen their maker.
I have stood on the dim shore beyond time and matter and seen it. It
moves through strange curves and outrageous angles. Some day I
shall travel in time and meet it face to face.
*** END OF THE PROJECT GUTENBERG EBOOK THE HOUNDS OF
TINDALOS ***

Updated editions will replace the previous one—the old editions will
be renamed.

Creating the works from print editions not protected by U.S.


copyright law means that no one owns a United States copyright in
these works, so the Foundation (and you!) can copy and distribute it
in the United States without permission and without paying
copyright royalties. Special rules, set forth in the General Terms of
Use part of this license, apply to copying and distributing Project
Gutenberg™ electronic works to protect the PROJECT GUTENBERG™
concept and trademark. Project Gutenberg is a registered trademark,
and may not be used if you charge for an eBook, except by following
the terms of the trademark license, including paying royalties for use
of the Project Gutenberg trademark. If you do not charge anything
for copies of this eBook, complying with the trademark license is
very easy. You may use this eBook for nearly any purpose such as
creation of derivative works, reports, performances and research.
Project Gutenberg eBooks may be modified and printed and given
away—you may do practically ANYTHING in the United States with
eBooks not protected by U.S. copyright law. Redistribution is subject
to the trademark license, especially commercial redistribution.

START: FULL LICENSE


THE FULL PROJECT GUTENBERG LICENSE
PLEASE READ THIS BEFORE YOU DISTRIBUTE OR USE THIS WORK

To protect the Project Gutenberg™ mission of promoting the free


distribution of electronic works, by using or distributing this work (or
any other work associated in any way with the phrase “Project
Gutenberg”), you agree to comply with all the terms of the Full
Project Gutenberg™ License available with this file or online at
www.gutenberg.org/license.

Section 1. General Terms of Use and


Redistributing Project Gutenberg™
electronic works
1.A. By reading or using any part of this Project Gutenberg™
electronic work, you indicate that you have read, understand, agree
to and accept all the terms of this license and intellectual property
(trademark/copyright) agreement. If you do not agree to abide by all
the terms of this agreement, you must cease using and return or
destroy all copies of Project Gutenberg™ electronic works in your
possession. If you paid a fee for obtaining a copy of or access to a
Project Gutenberg™ electronic work and you do not agree to be
bound by the terms of this agreement, you may obtain a refund
from the person or entity to whom you paid the fee as set forth in
paragraph 1.E.8.

1.B. “Project Gutenberg” is a registered trademark. It may only be


used on or associated in any way with an electronic work by people
who agree to be bound by the terms of this agreement. There are a
few things that you can do with most Project Gutenberg™ electronic
works even without complying with the full terms of this agreement.
See paragraph 1.C below. There are a lot of things you can do with
Project Gutenberg™ electronic works if you follow the terms of this
agreement and help preserve free future access to Project
Gutenberg™ electronic works. See paragraph 1.E below.
1.C. The Project Gutenberg Literary Archive Foundation (“the
Foundation” or PGLAF), owns a compilation copyright in the
collection of Project Gutenberg™ electronic works. Nearly all the
individual works in the collection are in the public domain in the
United States. If an individual work is unprotected by copyright law
in the United States and you are located in the United States, we do
not claim a right to prevent you from copying, distributing,
performing, displaying or creating derivative works based on the
work as long as all references to Project Gutenberg are removed. Of
course, we hope that you will support the Project Gutenberg™
mission of promoting free access to electronic works by freely
sharing Project Gutenberg™ works in compliance with the terms of
this agreement for keeping the Project Gutenberg™ name associated
with the work. You can easily comply with the terms of this
agreement by keeping this work in the same format with its attached
full Project Gutenberg™ License when you share it without charge
with others.

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. Unless you have removed all references to Project Gutenberg:

1.E.1. The following sentence, with active links to, or other


immediate access to, the full Project Gutenberg™ License must
appear prominently whenever any copy of a Project Gutenberg™
work (any work on which the phrase “Project Gutenberg” appears,
or with which the phrase “Project Gutenberg” is associated) is
accessed, displayed, performed, viewed, copied or distributed:
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.

1.E.2. If an individual Project Gutenberg™ electronic work is derived


from texts not protected by U.S. copyright law (does not contain a
notice indicating that it is posted with permission of the copyright
holder), the work can be copied and distributed to anyone in the
United States without paying any fees or charges. If you are
redistributing or providing access to a work with the phrase “Project
Gutenberg” associated with or appearing on the work, you must
comply either with the requirements of paragraphs 1.E.1 through
1.E.7 or obtain permission for the use of the work and the Project
Gutenberg™ trademark as set forth in paragraphs 1.E.8 or 1.E.9.

1.E.3. If an individual Project Gutenberg™ electronic work is posted


with the permission of the copyright holder, your use and distribution
must comply with both paragraphs 1.E.1 through 1.E.7 and any
additional terms imposed by the copyright holder. Additional terms
will be linked to the Project Gutenberg™ License for all works posted
with the permission of the copyright holder found at the beginning
of this work.

1.E.4. Do not unlink or detach or remove the full Project


Gutenberg™ License terms from this work, or any files containing a
part of this work or any other work associated with Project
Gutenberg™.

1.E.5. Do not copy, display, perform, distribute or redistribute this


electronic work, or any part of this electronic work, without
prominently displaying the sentence set forth in paragraph 1.E.1
with active links or immediate access to the full terms of the Project
Gutenberg™ License.

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.

1.E.7. Do not charge a fee for access to, viewing, displaying,


performing, copying or distributing any Project Gutenberg™ works
unless you comply with paragraph 1.E.8 or 1.E.9.

1.E.8. You may charge a reasonable fee for copies of or providing


access to or distributing Project Gutenberg™ electronic works
provided that:

• 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.

Let us accompany you on the journey of exploring knowledge and


personal growth!

ebookmass.com

You might also like