36,59 €
Make your WebAssembly journey fun while making a game with it
Key Features
Book Description
Within the next few years, WebAssembly will change the web as we know it. It promises a world where you can write an application for the web in any language, and compile it for native platforms as well as the web.
This book is designed to introduce web developers and game developers to the world of WebAssembly by walking through the development of a retro arcade game. You will learn how to build a WebAssembly application using C++, Emscripten, JavaScript, WebGL, SDL, and HTML5.
This book covers a lot of ground in both game development and web application development. When creating a game or application that targets WebAssembly, developers need to learn a plethora of skills and tools. This book is a sample platter of those tools and skills. It covers topics including Emscripten, C/C++, WebGL, OpenGL, JavaScript, HTML5, and CSS. The reader will also learn basic techniques for game development, including 2D sprite animation, particle systems, 2D camera design, sound effects, 2D game physics, user interface design, shaders, debugging, and optimization. By the end of the book, you will be able to create simple web games and web applications targeting WebAssembly.
What you will learn
Who this book is for
Web developers and game developers interested in creating applications for the web using WebAssembly.
Game developers interested in deploying their games to the web
Web developers interested in creating applications that are potentially orders of magnitude faster than their existing JavaScript web apps
C/C++ developers interested in using their existing skills to deploy applications to the web
Das E-Book können Sie in Legimi-Apps oder einer beliebigen App lesen, die das folgende Format unterstützen:
Seitenzahl: 690
Veröffentlichungsjahr: 2019
Copyright © 2019 Packt Publishing
All rights reserved. No part of this book may be reproduced, stored in a retrieval system, or transmitted in any form or by any means, without the prior written permission of the publisher, except in the case of brief quotations embedded in critical articles or reviews.
Every effort has been made in the preparation of this book to ensure the accuracy of the information presented. However, the information contained in this book is sold without warranty, either express or implied. Neither the author, nor Packt Publishing or its dealers and distributors, will be held liable for any damages caused or alleged to have been caused directly or indirectly by this book.
Packt Publishing has endeavored to provide trademark information about all of the companies and products mentioned in this book by the appropriate use of capitals. However, Packt Publishing cannot guarantee the accuracy of this information.
Acquisition Editor:Ashitosh GuptaContent Development Editor:Smit CarvalhoTechnical Editor: Ralph Rosario, Jane D'souzaCopy Editor: Safis EditingProject Coordinator:Kinjal BariProofreader: Safis EditingIndexer: Tejal Daruwale SoniGraphics:Alishon MendonsaProduction Coordinator:Jayalaxmi Raja
First published: May 2019
Production reference: 1300519
Published by Packt Publishing Ltd. Livery Place 35 Livery Street Birmingham B3 2PB, UK.
ISBN 978-1-83864-465-9
www.packtpub.com
Mapt is an online digital library that gives you full access to over 5,000 books and videos, as well as industry leading tools to help you plan your personal development and advance your career. For more information, please visit our website.
Spend less time learning and more time coding with practical eBooks and Videos from over 4,000 industry professionals
Improve your learning with Skill Plans built especially for you
Get a free eBook or video every month
Mapt is fully searchable
Copy and paste, print, and bookmark content
Did you know that Packt offers eBook versions of every book published, with PDF and ePub files available? You can upgrade to the eBook version at www.packt.com and as a print book customer, you are entitled to a discount on the eBook copy. Get in touch with us at [email protected] for more details.
At www.packt.com, you can also read a collection of free technical articles, sign up for a range of free newsletters, and receive exclusive discounts and offers on Packt books and eBooks.
Rick Battagline is a game developer who has been working with web- and browser-based technologies since 1997. He wrote his first computer game in 1996 and, in 2006, he founded BattleLine Games LLC., an independent game studio where he works to this day. That same year, his game, Epoch Star, was nominated for an award at the Slamdance Guerrilla Games Competition, and was listed in Game Informer Magazine issue 156 as one of "The top ten games you've never heard of."
Since then, Rick has written hundreds of games for platforms including the web, Windows PC, iOS, Android, Wii U, and Nintendo Entertainment System emulators. He has developed games in web technologies including WebAssembly, HTML5, WebGL, JavaScript, TypeScript, Flash, and PHP.
Prasad Annadata is a senior technologist with experience ranging from mainframes to cloud computing. His foray into game development started when he adopted classic minesweeper game to Unix. Recruited right out of college into a major consulting firm his career spawned consulting and major financial institutions. Prasad Annadata has been an author of several peer-reviewed papers on privacy and security, a professional technology reviewer for a chapter on Cyber Law in the book Chitty on Contracts: Hong Kong and a sole inventor of a B2B technology patent.
He has a bachelors and masters degrees in Computer Science and currently serves as an SVP in a major financial institution and his interests include cloud computing and cloud security.
Steve Tack is a software developer with 28 years of experience. Since the 1980s, he's enjoyed making computers do fun things, from programming simple games in BASIC on a Sinclair ZX81 to creating real-time 3D graphics on modern hardware.
If you're interested in becoming an author for Packt, please visit authors.packtpub.com and apply today. We have worked with thousands of developers and tech professionals, just like you, to help them share their insight with the global tech community. You can make a general application, apply for a specific hot topic that we are recruiting an author for, or submit your own idea.
Title Page
Copyright and Credits
Hands-On Game Development with WebAssembly
Dedication
About Packt
Why subscribe?
Packt.com
Contributors
About the author
About the reviewers
Packt is searching for authors like you
Preface
Who this book is for
What this book covers
To get the most out of this book
Download the example code files
Download the color images
Conventions used
Conventions used
Get in touch
Reviews
Introduction to WebAssembly and Emscripten
What is WebAssembly?
Why do we need WebAssembly?
Why is WebAssembly faster than JavaScript?
Will WebAssembly replace JavaScript?
What is asm.js?
A brief introduction to LLVM
A brief introduction to WebAssembly text
Emscripten
Installing Emscripten on Windows
Installing Emscripten on Ubuntu
Using Emscripten
Additional installation resources
Summary
HTML5 and WebAssembly
The Emscripten minimal shell file
Creating a new HTML shell and C file
Defining the CSS
HTML5 and game development
Immediate mode versus retained mode
Adding a canvas to the Emscripten template
Summary
Introduction to WebGL
WebGL and canvas contexts
An introduction to WebGL shaders
WebGL and JavaScript
WebGL coordinate system versus 2D canvas
Vertex and UV data
2D canvas to WebGL
Minor tweaks to the head tag
Major JavaScript changes
WebGL global variables
The return of vertex and texture data
Buffer constants
Defining the shaders
The ModuleLoaded function
The ShipPosition function
The MoveShip function
Summary
Sprite Animations in WebAssembly with SDL
Using SDL in WebAssembly
Initializing SDL
Clearing the SDL renderer
Using the WebAssembly virtual filesystem
Rendering a texture to the HTML5 canvas
Cleaning up SDL
Compiling hello_sdl.html
Render a sprite to the canvas
Animating a sprite
Moving the sprite
Compiling sprite.html
Summary
Keyboard Input
JavaScript keyboard input
Adding SDL keyboard input to WebAssembly
Using keyboard input to move a sprite
Summary
Game Objects and the Game Loop
Understanding the game loop
Writing a basic game loop
Compiling gameloop.html
Game objects
The player's spaceship game object
Object pooling
Pooling the player's projectiles
Creating an enemy
Compiling game_objects.html
Summary
Collision Detection
Types of 2D collision detection
Circle collision detection
Rectangle collision detection
A short refresher on trigonometry
Line collision detection
Compound colliders
Implementing circle collision detection
Destroying a spaceship on collision
Pointers in memory
Implementing compound circle colliders
Compiling collider.html
Summary
Basic Particle System
Adding to the virtual file system
A brief introduction to SVG
Vector versus raster graphics
Trigonometry again?
Adding the JavaScript
The simple particle emitter tool
The Point class
The Particle class
The Emitter class
WebAssembly interface functions
C++ name mangling
Dead code elimination
Updating the emitter
The looping function
Initialization
Compiling and testing the particle emitter
Summary
Improved Particle Systems
Modifying our HTML shell file
Scaling values
Color-blending values
Particle burst
Looping the emitter
Aligning particle rotation
Emission time
Animation frames
Modifying the JavaScript
The JavaScript UpdateClick function
Coercing color values
Additional variable coercions
Modifying the handleFiles function
Modifying the Particle class
New attributes
Aligning rotation attributes
Color attributes
Animation attributes
Size and scale attributes
The source rectangle attribute
Additional constructor parameters
The Update function's parameters
The Spawn function's parameters
Changes to particle.cpp
Particle constructor logic
Particle Update logic
Particle Spawn function
Particle Move function
Particle Render function
Modifying the Emitter class
The Emitter constructor function
Emitter update logic
Emitter Move function
External functions
Random floating-point numbers
Adding an emitter
Updating an emitter
Configuring the particle emitter
HTML shell and WebAssembly module interaction
Compiling and running the new tool
Creating a particle emitter
Changes to game.hpp
Adding the Particle class definition
Emitter class definition
Changes to emitter.cpp
Changes to the constructor function
Changes to the Update function
Adding a Run function
Changes to the Move function
Changes to ship.cpp
The Ship class' constructor function
The Ship class' Acceleration function
The Ship class' Render function
Changes to projectile_pool.cpp
Changes to main.cpp
Compiling the new particle_system.html file
Taking it further
Summary
AI and Steering Behaviors
What is Game AI?
Autonomous agents versus top-down AI
What is an FSM?
Introducing steering behaviors
The seek behavior
The flee behavior
The arrival behavior
The pursuit behavior
The evade behavior
Obstacle avoidance
The wander behavior
Combining forces
Modifying game.hpp
Adding obstacles to our game
Adding force fields
More collision detection
Circle-line collision detection
Vector projection
The Vector2D class
Writing an FSM
The AvoidForce function
Compiling the ai.html file
Summary
Designing a 2D Camera
Creating a camera for our game
Camera for tracking player movement
Projected focus and camera attractors
Modifying our code
Modifying the game.hpp file
The Vector2D class definition
The Locator class definition
The Camera class definition
The RenderManager class definition
The camera.cpp file
The render_manager.cpp file
Modifying main.cpp
New global variables
Modifying the move function
Modifying the render function
Modifying the main function
Modifying asteroid.cpp
Modifying collider.cpp
Modifying enemy_ship.cpp
Modifying finite_state_machine.cpp
Modifying particle.cpp
Modifying player_ship.cpp
Modifying projectile.cpp
Modifying shield.cpp
Modifying ship.cpp
Modifying star.cpp
Modifying vector.cpp
Compiling and playing with a locked-on camera
A more advanced camera
Changes to games.hpp
Changes to camera.cpp
Compiling and playing with the advanced camera
Summary
Sound FX
Where to get sound effects
Simple audio with Emscripten
Adding sound to our game
Updating game.hpp
Updating main.cpp
Updating ship.cpp
The new audio.cpp file
Compiling and running
Summary
Game Physics
Newton's third law
Adding gravity
Improving collisions
Modifying the code
Changing the game.hpp file
Changing collider.cpp
Changes to star.cpp
Changing the main.cpp file
Changes to asteroid.cpp and projectile.cpp
Changes to the ship.cpp file
Compiling the physics.html file
Summary
UI and Mouse Input
UI requirements
Opening screen
Play screen
Game over screen
Mouse input
Creating a button
Screen states
Changes to games.hpp
Modifying the RenderManager class
New external variables
Changes to main.cpp
Adding global variables
Input functions
The end_input function
The render functions
The collisions function
The transition state
The game loop
Play and play again callbacks
Changes to the main function
ui_button.cpp
The MouseMove function
The MouseClick function
The MouseUp function
The KeyDown function
The RenderUI function
ui_sprite.cpp
Defining the constructor
The RenderUI function
Compile ui.html
Summary
Shaders and 2D Lighting
Using OpenGL with WebAssembly
More about shaders
GLSL ES 1.0 and 3.0
WebGL app redux
Shader code
OpenGL global variables
SDL global variables
The main function
The game loop
Compiling and running our code
Mixing textures for a glow effect
Fragment shader changes
OpenGL global variable changes
Other global variable changes
Changes to main()
Updating game_loop()
Compiling and running our code
3D lighting
Ambient light
Diffuse light
Specular light
Normal maps
Creating a 2D lighting demo app
Fragment shader updates
OpenGL global variables
SDL global variables
Function prototypes
The main function
The game_loop function
The input function
The draw_light_icon function
Compiling and running our lighting app
Summary
Debugging and Optimization
Debug macro and stack trace
Source maps
Browser debugging
Compiling your code for debugging
Using asm.js as an alternative for debugging
Debugging using Chrome
Debugging using Firefox
Firefox Developer Edition
Optimizing for WebAssembly
Optimization flags
Optimizing for performance
Optimizing for size
Unsafe flags
Profiling
Problems with try/catch blocks
Optimizing OpenGL for WebAssembly
Using WebGL 2.0 if possible
Minimizing the number of OpenGL calls
Emscripten OpenGL flags
Summary
This is the end
Other Books You May Enjoy
Leave a review - let other readers know what you think
WebAssembly is a technology that will change the web as we know it within the next few years. WebAssembly promises a world where web-based applications run at near-native speeds. It is a world where you can write an application for the web in any language you like, and compile it for native platforms as well as the web. It is early days for WebAssembly, but this technology is already taking off like a rocket. If you are interested in where the web is going, as much as where it is today, read on!
I wrote this book to reflect the way I like to learn new skills. I will walk you through the development of a game using WebAssembly and all of its related technologies. I am a long-time game and web developer, and I have always enjoyed learning new programming languages by writing games. In this book, we will be covering a lot of ground on a lot of topics using both web and game development tools that go hand in hand with WebAssembly. We will learn how to write games that target WebAssembly utilizing a plethora of programming languages and tools, including Emscripten, C/C++, WebGL, OpenGL, JavaScript, HTML5, and CSS. As a long-time owner of an independent game development studio that specializes in the development of web-based games, I have found that it is essential to have a broad understanding of web- and game-based technologies and I have stuffed this book full of them. You will be learning a sample platter of skills with a focus on getting your apps up and running with WebAssembly. If you want to learn how to develop games with WebAssembly, or if you would like to create web-based applications that are lightning fast, this book is for you.
This book is not an introduction to programming. It is intended for people who know how to code in at least one programming language. It would be helpful, but is not strictly necessary, to have at least a rudimentary understanding of some web-based technologies, such as HTML. This book contains instructions on how to install the required tools on Windows or Ubuntu Linux, and, out of the two, I would recommend using Ubuntu, as its installation process is much simpler.
Chapter 1, Introduction to WebAssembly and Emscripten, introduces WebAssembly, why the web needs it, and why it is so much faster than JavaScript. We will introduce Emscripten, why we need it for WebAssembly development, and how to install it. We will also discuss technologies related to WebAssembly, such as asm.js, LLVM, and WebAssembly Text.
Chapter 2, HTML5 and WebAssembly, discusses how WebAssembly modules integrate with HTML using the JavaScript "glue code". We will learn how to create our own Emscripten HTML shell file, and we will learn how to make calls to and from our WebAssembly module, which we will write in C. Finally, we will learn how to compile and run an HTML page that interacts with our WebAssembly module, and we will learn how to build a simple HTML5 Canvas app with Emscripten.
Chapter 3, Introduction to WebGL, introduces WebGL and the new canvas contexts that support it. We will learn about shaders, what they are, and how WebGL uses them to render geometry to the canvas. We will learn how to use WebGL and JavaScript to draw a sprite to the canvas. And finally, we will write an app that integrates WebAssembly, JavaScript, and WebGL that displays a sprite and moves it across the canvas.
Chapter 4, Sprite Animations in WebAssembly with SDL, teaches you about the SDL library and how we use it to simplify calls to WebGL from WebAssembly. We will learn how to use SDL to render, animate, and move sprites on the HTML5 canvas.
Chapter 5, Keyboard Input, looks at how to take input from the keyboard from JavaScript and make calls to the WebAssembly module. We will also learn how to accept keyboard input using SDL inside our WebAssembly module, and use the input to move a sprite around the HTML5 canvas.
Chapter 6, Game Objects and the Game Loop, explores some basic game design. We will learn about the game loop, and how a game loop in WebAssembly is different than in other games. We will also learn about game objects and how to create an object pool from within our game. We will end the chapter by coding the beginning of our game, with two spaceships that move about the canvas and shoot projectiles at each other.
Chapter 7, Collision Detection, introduces collision detection into our game. We will explore the types of 2D collision detection, implement a basic collision detection system, and learn a little about the trigonometry that makes it work. We will modify our game so that projectiles destroy the spaceships when they collide.
Chapter 8, Basic Particle System, introduces particle systems and discusses how they can visually improve our game. We will talk about the virtual filesystem, and we learn how to add files to it through a web page. We will briefly introduce SVG and Vector graphics, and how to use them for data visualization. We will further discuss trigonometry and how we will be using it in our particle systems. We will build a new HTML5 WebAssembly app that will help us to configure and test particle systems that we will later add to our game.
Chapter 9, Improved Particle Systems, goes into improving our particle system configuration tool by adding particle scaling, rotation, animation, and color transitions. We will modify the tool to allow the particle systems to loop, and add a burst effect. We will then update our game to support particle systems and add in particle system effects for our engine exhaust and explosions.
Chapter 10, AI and Steering Behaviors, introduces the concept of AI and game AI and discusses the difference between them. We will discuss the AI concepts of finite state machines, autonomous agents, and steering behaviors, and we will implement these behaviors in an enemy AI that will avoid obstacles and combat the player.
Chapter 11, Designing a 2D Camera, brings in the concept of 2D camera design. We will begin by adding a render manager to our game and creating a camera that locks on to the player's spaceship, following it around an expanded gameplay area. We will then add the advanced 2D camera features of projected focus and camera attractors.
Chapter 12, Sound FX, covers the use of SDL Audio in our game. We will discuss where we can get our sound effects online, and how to include those sounds in our WebAssembly module. We will then add sound effects to our game.
Chapter 13, Game Physics, introduces the concept of physics in computer games. We will be adding elastic collisions between our game objects. We will add Newton's third law to the physics of our game in the form of recoil when the spaceships launch projectiles. We will add a gravitational field to our star that will attract the spaceships.
Chapter 14, UI and Mouse Input, discusses adding a user interface to be managed and rendered within our WebAssembly module. We will gather requirements and translate them into new screens for our game. We will add a new button object and learn how we can manage mouse input from within our WebAssembly module using SDL.
Chapter 15, Shaders and 2D lighting, dives into how to create a new app that mixes OpenGL and SDL. We will create a new shader that loads and renders multiple textures to a quad. We will learn about normal maps, and how we can use normal maps to approximate the Phong lighting model in 2D, using OpenGL in our WebAssembly module.
Chapter 16, Debugging and Optimization, introduces the basic methods for debugging and optimizing WebAssembly modules. We will start with debug macros and stack traces from WebAssembly. We will introduce the concepts of source maps and how web browsers use them to debug WebAssembly modules. We will learn about optimizing WebAssembly code using optimization flags. We will discuss using a profiler to optimize our WebAssembly code.
You must understand the basics of computer programming.
It is helpful to have a basic understanding of web technologies such as HTML and CSS.
You can download the code bundle for this book from here: https://github.com/PacktPublishing/Hands-On-Game-Development-with-WebAssembly.
We also have other code bundles from our rich catalog of books and videos available at https://github.com/PacktPublishing/. Check them out!
We also provide a PDF file that has color images of the screenshots/diagrams used in this book. You can download it here: https://www.packtpub.com/sites/default/files/downloads/9781838644659_ColorImages.pdf.
You can download the example code files for this book from your account at www.packt.com. If you purchased this book elsewhere, you can visit www.packt.com/support and register to have the files emailed directly to you.
You can download the code files by following these steps:
Log in or register at
www.packt.com
.
Select the
SUPPORT
tab.
Click on
Code Downloads & Errata
.
Enter the name of the book in the
Search
box and follow the onscreen instructions.
Once the file is downloaded, please make sure that you unzip or extract the folder using the latest version of:
WinRAR/7-Zip for Windows
Zipeg/iZip/UnRarX for Mac
7-Zip/PeaZip for Linux
The code bundle for the book is also hosted on GitHub at https://github.com/PacktPublishing/Hands-On-Game-Development-with-WebAssembly. In case there's an update to the code, it will be updated on the existing GitHub repository.
We also have other code bundles from our rich catalog of books and videos available at https://github.com/PacktPublishing/. Check them out!
There are a number of text conventions used throughout this book.
CodeInText: Indicates code words in text, database table names, folder names, filenames, file extensions, pathnames, dummy URLs, user input, and Twitter handles. Here is an example: "We are going to copy the basic_particle_shell.html file to a new shell file that we will call advanced_particle_shell.html."
A block of code is set as follows:
<label class="ccontainer"><span class="label">loop:</span><input type="checkbox" id="loop" checked="checked"><span class="checkmark"></span></label><br/>
When we wish to draw your attention to a particular part of a code block, the relevant lines or items are set in bold:
<label class="ccontainer"><span class="label">loop:</span>
<input type="checkbox" id="loop" checked="checked">
<span class="checkmark"></span></label><br/>
Any command-line input or output is written as follows:
emrun --list_browsers
Bold: Indicates a new term, an important word, or words that you see on screen. For example, words in menus or dialog boxes appear in the text like this. Here is an example: "Select System info from the Administration panel."
Feedback from our readers is always welcome.
General feedback: If you have questions about any aspect of this book, mention the book title in the subject of your message and email us at [email protected].
Errata: Although we have taken every care to ensure the accuracy of our content, mistakes do happen. If you have found a mistake in this book, we would be grateful if you would report this to us. Please visit www.packt.com/submit-errata, selecting your book, clicking on the Errata Submission Form link, and entering the details.
Piracy: If you come across any illegal copies of our works in any form on the internet, we would be grateful if you would provide us with the location address or website name. Please contact us at [email protected] with a link to the material.
If you are interested in becoming an author: If there is a topic that you have expertise in, and you are interested in either writing or contributing to a book, please visitauthors.packtpub.com.
Please leave a review. Once you have read and used this book, why not leave a review on the site that you purchased it from? Potential readers can then see and use your unbiased opinion to make purchase decisions, we at Packt can understand what you think about our products, and our authors can see your feedback on their book. Thank you!
For more information about Packt, please visit packt.com.
Welcome to the exciting new world of WebAssembly! These are early days for WebAssembly, but the technology is currently taking off like a rocket, and by reading this book, you are in a position to get in on the ground floor. If you are interested in game development on the web, or you are interested in learning as much about this new technology as you can to position yourself for when it does reach maturity, you are in the right place. Even though WebAssembly is in its infancy, all major browser vendors have adopted it. These are early days and use cases are limited, but lucky for us, game development is one of them. So, if you want to be early to the party for the next generation of application development on the web, read on, adventurer!
In this chapter, I will introduce you to WebAssembly, Emscripten, and some of the underlying technologies around WebAssembly. I will teach you the basics of the Emscripten toolchain, and how you can use Emscripten to compile C++ code into WebAssembly. We will discuss what LLVM is and how it fits into the Emscripten toolchain. We will talk about WebAssembly's Minimum Viable Product (MVP), the best use cases for WebAssembly in its current MVP form, and what will soon be coming to WebAssembly. I will introduce WebAssembly text (.wat), how we can use it to understand the design of WebAssembly bytecode, and how it differs from other machine bytecodes. We will also briefly discuss asm.js, and its historical significance in the design of WebAssembly. Finally, I will show you how to install and run Emscripten on Windows and Linux.
In this chapter, we will cover the following topics:
What is WebAssembly?
Why do we need WebAssembly?
Why is WebAssembly faster than JavaScript?
Will WebAssembly replace JavaScript?
What is asm.js?
A brief introduction to LLVM
A brief introduction to WebAssembly text
What is Emscripten and how do we use it?
WebAssembly is not a high-level programming language like JavaScript, but a compiled binary format thatall major browsersare currently able to execute. WebAssembly is a kind of machine bytecode that was not designed to run directly on any real machine hardware, but runs in the JavaScript engine built into every browser. In some ways, it is similar to the old Java Virtual Machine (JVM); for example, it is a platform-independent compiled bytecode. One major problem with JavaScript bytecode is its requirement for a plugin to be downloaded and installed in the browser for the bytecode to run. Not only is WebAssembly designed to be run directly in a browser without a plugin, but it is also intended to produce a compact binary format that executes efficiently inside a web browser. The MVP version of the specification leverages existing work by the browser makers designing their JavaScript just-in-time (JIT) compiler. WebAssembly is currently a young technology and many improvements are planned. However, developers using the current version of WebAssembly have already seen performance improvements over JavaScript of 10–800%.
JavaScript has been around for a long time. It has evolved from a little scripting language that allowed bells and whistles to be added to a web page, to a sprawling JIT compiled language with a massive ecosystem that can be used to write fully fledged applications. Today, JavaScript is doing a lot of things that were probably never imagined when it was created by Netscape in 1995. JavaScript is an interpreted language, meaning that it must be parsed, compiled, and optimized on the fly. JavaScript is also a dynamically typed language, which creates headaches for an optimizer.
WebAssembly solves a lot of the problems created by JavaScript and its long history in the browser. Because the JavaScript engine is already in bytecode format, it does not need to run a parser, which removes a significant bottleneck in the execution of our application. This design also allows the JavaScript engine to know what data types it is dealing with at all times. The bytecode makes optimization a lot easier. The format allows multiple threads in the browsers to work on compiling and optimizing different parts of the code at the same time.
WebAssembly is not a high-level programming language, but a binary file with opcodes for a virtual machine. Currently, it is considered to be in an MVP stage of development. The technology is still in its infancy, but even now it offers notable performance and file size benefits for many use cases, such as game development. Because of the current limitations of WebAssembly, we have only two choices for languages to use for its development—C/C++ or Rust. The long-term plan for WebAssembly is to support a wide selection of programming languages for its development. If I wanted to write at the lowest level of abstraction, I could write everything in Web Assembly Text (WAT), but WAT was developed as a language to support debugging and testing and was not intended to be used by developers for writing applications.
The short answer to this question is not anytime soon. At present, WebAssembly is still in its MVP stage. At this stage, the number of use cases is limited to applications where WebAssembly has limited back and forth with the JavaScript and the Document Object Model (DOM). WebAssembly is not currently able to directly interact with the DOM, and Emscripten uses JavaScript "glue code" to make that interaction work. That interaction will probably change soon, possibly by the time you are reading this, but in the next few years, WebAssembly will need additional features to increase the number of possible use cases.
WebAssembly is not a "feature complete" platform. Currently, it cannot be used with any languages that require GC. That will change and, eventually, almost all strongly typed languages will target WebAssembly. In addition, WebAssembly will soon become tightly integrated with JavaScript, allowing frameworks such as React, Vue, and Angular to begin replacing significant amounts of their JavaScript code with WebAssembly without impacting the application programming interface (API). The React team is currently working on this to improve the performance of React.
In the long run, it is possible that JavaScript may compile into WebAssembly. For technical reasons, this is a very long way off. Not only does JavaScript require a GC (not currently supported), but because of its dynamic nature, JavaScript also requires a runtime profiler to optimize. Therefore, JavaScript would produce very poorly optimized code, or significant modifications would be needed to support strict typing. It is more likely that a language, such as TypeScript, will add features that allow it to compile into WebAssembly.
JavaScript is currently ubiquitous on the web; there are a tremendous number of libraries and frameworks developed in JavaScript. Even if there were an army of developers eager to rewrite the entire web in C++ or Rust, WebAssembly is not yet ready to replace these JavaScript libraries and frameworks. The browser makers have put immense efforts into making JavaScript run (relatively) fast, so JavaScript will probably remain as the standard scripting language for the web. The web will always need a scripting language, and countless developers have already put in the work to make JavaScript that scripting language, so it seems unlikely that JavaScript will ever go away.
There is, however, a need for a compiled format for the web that WebAssembly is likely to fulfill. Compiled code may be a niche on the web at the moment, but it is a standard just about everywhere else. As WebAssembly approaches feature-complete status, it will offer more choices and better performance than JavaScript, and businesses, frameworks, and libraries will gradually migrate toward it.
One early attempt to achieve native-like speed in the web browser using JavaScript was asm.js. Although that goal was reached and asm.js was adopted by all the major browser vendors, it never achieved widespread adoption by developers. The beauty of asm.js is that it still runs in most browsers, even in those that do not optimize for it. The idea behind asm.js was that typed arrays could be used in JavaScript to fake a C++ memory heap. The browser simulates pointers and memory allocation in C++, as well as types. A well-designed JavaScript engine can avoid dynamic type checking. Using asm.js, browser makers could get around many of the optimization problems created by the dynamic nature of JavaScript, by just pretending that this version of JavaScript is not dynamically typed. Emscripten, designed as a C++-to-JavaScript compiler, quickly adopted asm.js as the subset of JavaScript that it would compile to because of its improved performance in most browsers. The performance improvements driven by asm.js lead the way to WebAssembly. The same engine modifications used to make asm.js perform well could be used to bootstrap the WebAssembly MVP. Only the addition of a bytecode-to-bytecode compiler was required to take the WebAssembly bytecode and directly convert it into the IR bytecode used by the browser.
Emscripten is the tool we will be using to compile C++ into WebAssembly. Before I discuss Emscripten, I need to explain a technology called LLVM and its relationship to Emscripten.
First, take a moment to think of airlines (stay with me here). Airlines want to get passengers from one airport to another airport. But it's challenging to offer a direct flight from every single airport to every other airport on Earth. That would mean that airlines would have to provide a vast number of direct flights, such as Akron, Ohio to Mumbai, India. Let's travel back in time to the 1990s—that was the state of the compiler world. If you wanted to compile from C++ to ARM, you needed a compiler capable of compiling C++ to ARM. If you needed to compile from Pascal to x86, you needed a compiler that could compile from Pascal to x86. These are like having only direct flights between any two cities: a compiler for every combination of language and hardware. The result is either that you have to limit the number of languages you write compilers for, limit the number of platforms you can support with that language, or more likely, both.
In 2003, a student at the University of Illinois named Chris Lattner wondered, "What if we created a hub-and-spoke model for programming languages?" His idea led to LLVM, which originally stood for "Low-Level Virtual Machine." The idea was that, instead of compiling your source code for any possible distribution, you compile it for LLVM. There are then compilers between the intermediate language and your final output language. In theory, this means that if you develop a new target platform on the right side of the following diagram, you get all languages on the left side right away:
WebAssembly binary is not a language, but a build target similar to building for ARM or x86. The bytecode, however, is structured differently than other hardware-specific build targets. The designers of the WebAssembly bytecode had the web in mind. The aim was to create a bytecode that was compact and streamable. Another goal was that the user should be able to do a "view/source" on the WebAssembly binary to see what is going on. WebAssembly text is a companion code to the WebAssembly binary that allows the user to view the bytecode instructions in a human-readable form, similar to the way an assembly language would let you see what opcodes execute in a machine-readable form.
WebAssembly text may initially look unfamiliar to someone used to writing assembly for hardware such as ARM, x86, or 6502 (if you're old school). You write WebAssembly text in S-expressions, which has a parentheses-heavy tree structure. Some of the operations are also strikingly high level for an assembly language, such as if/else and loop opcodes. That makes a lot more sense if you remember that WebAssembly was not designed to run directly on computer hardware, but to download and translate into machine code quickly.
Another thing that will seem a little alien at first when you are dealing with WebAssembly text is the lack of registers. WebAssembly is designed to be a virtual stack machine, which is an alternative to a register machine, such as x86 and ARM, with which you might be familiar. A stack machine has the advantage of producing significantly smaller bytecode than a register machine, which is one good reason to choose a stack machine for WebAssembly. Instead of using a series of registers to store and manipulate numbers, every opcode in a stack machine pushes values on or off a stack (and sometimes does both). For example, a call to i32.add in WebAssembly pulls two 32-bit integers off the stack, adds them together, then pushes their value back on to the stack. The computer hardware can make the best use of whichever registers are available to perform this operation.
Now that we know what LLVM is, we can discuss Emscripten. Emscripten was developed to compile LLVM IR into JavaScript, but has recently been updated to compile LLVM into WebAssembly. The idea is that, when you get the LLVM compiler working, you can have the benefit of all the languages that compile to LLVM IR. In practice, the WebAssembly specification is still in its early days and does not support common language features such as GC. Therefore, only non-GC languages such as C/C++ and Rust are currently supported. WebAssembly is still in the early MVP phase of its development, but the addition of GC and other common language features are coming soon. When that happens, there should be an explosion of programming languages that will compile to WebAssembly.
When Emscripten was released in 2012, it was intended to be an LLVM-to-JavaScript compiler. In 2013, support was added for asm.js, which is a faster, easily optimized subset of the JavaScript language. In 2015, Emscripten began to add support for LLVM-to-WebAssembly compiling. Emscripten also provides a Software Development Kit (SDK) for both C++ and JavaScript that provides glue code to give users better tools for interaction between JavaScript and WebAssembly than those currently offered by the WebAssembly MVP alone. Emscripten also integrates with a C/C++-to-LLVM compiler called Clang, so that you can compile your C++ into WebAssembly. In addition, Emscripten will generate the HTML and JavaScript glue code you need to get your project started.
I am going to keep this section brief because these instructions are subject to change. You can supplement these instructions with the official Emscripten download and install instructions found on the Emscripten website:https://emscripten.org/docs/getting_started/downloads.html.
We will need to download and build Emscripten from the emsdk source files on GitHub. First, we will walk through what to do on Windows.
Python 2.7.12 or higher is a prerequisite. If you do not have a version of Python higher than 2.7.12 installed, you will need to get the windows installer from python.org and install that first: https://www.python.org/downloads/windows/.
If you have Git installed already, cloning the repository is relatively simple:
Run the following command to clone the repository:
git
clone
https
:
//
github
.
com
/
emscripten
-
core
/
emsdk
.
git
Wherever you run this command, it will create an
emsdk
directory. Enter that directory using the following:
cd emsdk
You may not have Git installed, in which case, the following steps will bring you up to speed:
Go to the following URL in a web browser:
https://github.com/emscripten-core/emsdk
.
You will see a green button on the right-hand side that says
Clone or download
. Download the ZIP file:
Unzip the downloaded file to the
c:\emsdk
directory.
Open up a Windows Command Prompt by typing
cmd
into the start menu and pressing
Enter
.
From there, you can change to the
c:\emsdk\emsdk-master
directory by typing the following:
cd \emsdk\emsdk-master
At this point, it does not matter whether you had Git installed or not. Let's move forward:
Install
emsdk
from the source code running the following command:
emsdk install latest
Then activate the latest
emsdk
:
emsdk activate latest
Finally, set up our path and environment variables:
emsdk_env.bat
If you are installing on Ubuntu, you should be able to use the apt-get package manager and git for the complete install. Let's move forward:
Python is required, so if you do not have Python installed, be sure to run the following:
sudo apt-get install python
If you do not already have Git installed, run the following:
sudo apt-get install git
Now you will need to clone the Git repository for
emsdk
:
git
clone
https
:
//
github
.
com
/
emscripten
-
core
/
emsdk
.
git
Change your directory to move into the
emsdk
directory:
cd emsdk
From here, you need to install the latest version of the SDK tools, activate it, and set your environment variables:
./emsdk install latest
./emsdk activate latest
source ./emsdk_env.sh
To make sure everything was installed correctly, run the following command:
emcc --version
We run Emscripten from the command line; therefore, you can use any text editor you choose to write your C/C++ code. Personally,I am partial to Visual Studio Code, which you can download here: https://code.visualstudio.com/download.
One beautiful thing about Visual Studio Code is that it has a built-in command-line terminal, which lets you compile your code without switching windows. It also has an excellent C/C++ extension that you can install. Just search for C/C++ from the extensions menu and install the Microsoft C/C++ Intellisense extension.
Whatever you choose for your text editor or integrated development environment, you need a simple piece of C code to test out the emcc compiler.
Create a new text file and name it
hello.c
.
Type the following code into
hello.c
:
#include <emscripten.h>
#include <stdlib.h>#
include
<
stdio.h
>
int main() {
printf("hello wasm\n");
}
Now I can compile the
hello.c
file into WebAssembly and generate a
hello.html
file:
emcc hello.c --emrun -o hello.html
The
--emrun
flag is necessary if you want to run the HTML page from
emrun
. This flag adds code that will capture
stdout
,
stderr
, and exit in the C code and
emrun
will not work without it:
emrun --browser firefox hello.html
Running emrun with the --browser flag will pick the browser where you would like to run the script. The behavior of emrun seems to be different between browsers. Chrome will close the window when the C program exits. That can be annoying because we are just trying to display a simple print message. If you have Firefox, I would suggest running emrun using the --browser flag.
To find out what browsers are available to you, run the following:
emrun --list_browsers
emrun should open an Emscripten-templated HTML file in a browser.
Make sure you have a browser capable of running WebAssembly. The following versions of the major browsers should work with WebAssembly:
Edge 16
Firefox 52
Chrome 57
Safari 11
Opera 44
Creating an installation guide for Emscripten is going to be somewhat problematic. The WebAssembly technology changes frequently and the installation process for Emscripten may be different by the time you read this. I would recommend consulting the download and install instructions on the Emscripten website if you have any problems: https://emscripten.org/docs/getting_started/downloads.html.
You may also want to consult the Emscripten page on GitHub: https://github.com/emscripten-core/emsdk.
Google Groups has an Emscripten discussion forum where you may ask questions if you are having installation problems: https://groups.google.com/forum/?nomobile=true#!forum/emscripten-discuss.
You can also contact me on Twitter (@battagline), and I will do my best to help you: https://twitter.com/battagline.
In this chapter, we learned what WebAssembly is and why it will be the future of application development on the web. We learned why we need WebAssembly, even though we already have a robust language like JavaScript. We learned why WebAssembly is so much faster than JavaScript, and how it has the potential to increase its performance lead. We have also discussed the possibility of WebAssembly replacing JavaScript as the de facto standard for application development on the web.
We have discussed the practical side of creating a WebAssembly module as it is done today using Emscripten and LLVM. We have talked about WebAssembly text and how it is structured. We have also discussed using Emscripten to compile our first WebAssembly module, as well as using it to create the HTML and JavaScript glue code to run that module.
