Download ebooks file Building a 2D Game Physics Engine Using HTML5 and JavaScript Tanaya all chapters
Download ebooks file Building a 2D Game Physics Engine Using HTML5 and JavaScript Tanaya all chapters
com
https://textbookfull.com/product/building-a-2d-game-physics-
engine-using-html5-and-javascript-tanaya/
OR CLICK BUTTON
DOWNLOAD NOW
https://textbookfull.com/product/monogame-mastery-build-a-multi-
platform-2d-game-and-reusable-game-engine-jarred-capellman/
textboxfull.com
https://textbookfull.com/product/introducing-javascript-game-
development-build-a-2d-game-from-the-ground-up-1st-edition-graeme-
stuart/
textboxfull.com
https://textbookfull.com/product/introducing-javascript-game-
development-build-a-2d-game-from-the-ground-up-1st-edition-graeme-
stuart-2/
textboxfull.com
Pro HTML5 Games. Learn to build your own Games using HTML5
and JavaScript Aditya Ravi Shankar
https://textbookfull.com/product/pro-html5-games-learn-to-build-your-
own-games-using-html5-and-javascript-aditya-ravi-shankar/
textboxfull.com
Learn PHP 8: Using MySQL, JavaScript, CSS3, and HTML5
Second Edition Steve Prettyman
https://textbookfull.com/product/learn-php-8-using-mysql-javascript-
css3-and-html5-second-edition-steve-prettyman/
textboxfull.com
https://textbookfull.com/product/game-engine-architecture-jason-
gregory/
textboxfull.com
https://textbookfull.com/product/new-perspectives-on-html5-css3-and-
javascript-6th-edition-patric-carey/
textboxfull.com
Building a 2D Game
Physics Engine
Using HTML5 and JavaScript
—
Michael Tanaya
Huaming Chen
Jebediah Pavleas
Kelvin Sung
Building a 2D Game
Physics Engine
Using HTML5 and JavaScript
Michael Tanaya
Huaming Chen
Jebediah Pavleas
Kelvin Sung
Building a 2D Game Physics Engine: Using HTML5 and JavaScript
Michael Tanaya Huaming Chen
Bothell, Washington, USA Bothell, Washington, USA
Jebediah Pavleas Kelvin Sung
Kenmore, Washington, USA Woodinville, Washington, USA
ISBN-13 (pbk): 978-1-4842-2582-0 ISBN-13 (electronic): 978-1-4842-2583-7
DOI 10.1007/978-1-4842-2583-7
Library of Congress Control Number: 2017930129
Copyright © 2017 by Michael Tanaya, Huaming Chen, Jebediah Pavleas and Kelvin Sung
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.
Cover image designed by Freepik
Managing Director: Welmoed Spahr
Lead Editor: Steve Anglin
Development Editor: Matthew Moodie
Technical Reviewer: Jason Sturges
Coordinating Editor: Mark Powers
Copy Editor: Larissa Shmailo
Compositor: SPi Global
Indexer: SPi Global
Artist: SPi Global
Distributed to the book trade worldwide by Springer Science+Business Media New York, 233 Spring
Street, 6th Floor, New York, NY 10013. 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], or visit http://www.apress.com/us/
services/rights-permission.
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/us/services/bulk-sales.
Any source code or other supplementary material referenced by the author in this book is available
to readers for download via the book's product page, located at www.apress.com/9781484225820.
For more detailed information, please visit http://www.apress.com/us/services/source-code.
Printed on acid-free paper
To my love, Josephine Janice, for her companionship through many long
nights of writing, and my parents, Hendi and Ros,
for their support, advice, and love.
—Michael Tanaya
To my Mother, Diana, for the love and support she has given me
throughout my life.
—Jebediah Pavleas
To my wife, Clover, and our girls, Jean and Ruth, for completing my life.
—Kelvin Sung
Contents at a Glance
Index���������������������������������������������������������������������������������������������� 113
v
Contents
User Control������������������������������������������������������������������������������������������� 12
Creating User Control Script����������������������������������������������������������������������������������� 12
Using the User Control Script��������������������������������������������������������������������������������� 13
Summary����������������������������������������������������������������������������������������������� 14
vii
■ CONTENTS
■
■Chapter 2: Implementing the 2D Physics Engine Core����������������� 15
Vector Calculation Library��������������������������������������������������������������������� 16
Creating the Library������������������������������������������������������������������������������������������������ 16
Summary����������������������������������������������������������������������������������������������� 36
■
■Chapter 3: Incorporating Collision Detection������������������������������� 37
Interpenetration of Colliding Objects����������������������������������������������������� 38
Collision Detection��������������������������������������������������������������������������������� 40
Broad Phase Method����������������������������������������������������������������������������� 40
The Broad Phase Method Project��������������������������������������������������������������������������� 40
Observation������������������������������������������������������������������������������������������������������������ 45
Collision Information����������������������������������������������������������������������������� 45
The Circle Collision Detection Project��������������������������������������������������������������������� 46
Observation������������������������������������������������������������������������������������������������������������ 52
viii
CONTENTS ■
Summary����������������������������������������������������������������������������������������������� 69
■■Chapter 4: Completing the Physics Engine and Rigid Shape
Component����������������������������������������������������������������������������������� 71
Movement��������������������������������������������������������������������������������������������� 72
Explicit Euler Integration���������������������������������������������������������������������������������������� 73
Symplectic Euler Integration���������������������������������������������������������������������������������� 74
Resolving Interpenetrations������������������������������������������������������������������ 83
The Positional Correction Project��������������������������������������������������������������������������� 84
Observation������������������������������������������������������������������������������������������������������������ 87
Resolving Collisions������������������������������������������������������������������������������ 87
Formulating the Impulse Method��������������������������������������������������������������������������� 88
The Steps for Resolving Collisions������������������������������������������������������������������������� 92
The Collision Impulse Project��������������������������������������������������������������������������������� 93
Observation������������������������������������������������������������������������������������������������������������ 96
Supporting Rotation in Collision Response������������������������������������������� 96
Integrating Newtonian Mechanics for Rotation������������������������������������������������������ 97
Formulating Impulse Method with Rotation����������������������������������������������������������� 97
The Angular Impulse Project��������������������������������������������������������������������������������� 100
Observation���������������������������������������������������������������������������������������������������������� 102
Summary��������������������������������������������������������������������������������������������� 103
ix
■ CONTENTS
■
■Chapter 5: Summarizing the Physics Engine����������������������������� 105
The Concepts and Theories ���������������������������������������������������������������� 105
The Engine Source Code��������������������������������������������������������������������� 106
The Cool Demo Project������������������������������������������������������������������������ 108
Modifying Simulation Scene��������������������������������������������������������������������������������� 108
Observation���������������������������������������������������������������������������������������������������������� 109
Reference�������������������������������������������������������������������������������������������� 112
Index���������������������������������������������������������������������������������������������� 113
x
About the Authors
Huaming Chen is an international graduate student from China in the Computer Science
and Software Engineering program at the University of Washington Bothell (UWB). He
received dual undergraduate degrees, in Computer Science and Economics, from Xiamen
University in 2015. During his time as an undergraduate, he was interested in data mining
and videogame design. His project includes a structure of website groups that related to
each other and a software system that recommends useful information based on the
website groups. He also developed a mobile game based on Unity3D. Currently, Huaming
is working on a project that focuses on designing videogames that simplify vision therapy
for children. He will be graduating in Spring 2017.
xi
■ ABOUT THE AUTHORS
Kelvin Sung is a professor with the Computing and Software Systems division at
University of Washington Bothell (UWB). He received his Ph.D. in Computer Science
from the University of Illinois at Urbana-Champaign. Kelvin's background is in computer
graphics, hardware, and machine architecture. He came to UWB from Alias|Wavefront
(now part of Autodesk), where he played a key role in designing and implementing the
Maya Renderer, an Academy Award-winning image generation system. Funded by
Microsoft Research and the National Science Foundation, Kelvin’s recent work focused
on the intersection of video game mechanics, solutions to real-world problems, and
mobile technologies. Together with his students, Kelvin has co-authored three recent
books: one in computer graphics (Essentials of Interactive Computer Graphics: Concepts
and Implementations, A.K. Peters, 2008), and the others in 2D game engines (Learn 2D
Game Development with C#, APress, December 2013; and Build Your Own 2D Game
Engine and Create Great Web Games, Apress, October 2015).
xii
About the Technical
Reviewer
Jason Sturges is a cutting edge technologist focused on ubiquitous delivery of immersive
user experiences. Coming from a visualization background, he’s always pushing the
boundaries of computer graphics to the widest reach across platforms while maintaining
natural and intuitive usability per device. From interactivity, motion, and animation to
creative design, he has worked with numerous creative agencies on projects from kiosks
to video walls to Microsoft Kinect games. Most recently, the core of his work has been
mobile apps. Committed to the open source community, he is also a frequent contributor
at GitHub and Stack Overflow as a community resource leveraging modern standards,
solid design patterns, and best practices in multiple developer tool chains for web,
mobile, desktop, and beyond.
xiii
Acknowledgments
This and our prior books on Games and Game Engine development are the direct result
of the authors learning from building games for the Game-Themed CS1/2: Empowering
the Faculty project, funded by the Transforming Undergraduate Education in Science
Technology, Engineering, and Mathematics (TUES) Program, National Science
Foundation (NSF) (award number DUE-1140410). We would like to thank NSF officers
Suzanne Westbrook for believing in our project and Jane Prey, Valerie Bar, and Paul
Tymann for their encouragement.
The invaluable collaboration between the technical team in the Game-Themed
Research Group (https://depts.washington.edu/cmmr/GTCS/) and the design team
in the Digital Future Lab (http://www.bothell.washington.edu/digitalfuture) at
the University of Washington Bothell (where much of our learning occurred during
the production of the many casual games for teaching introductory programming
concepts) formed the foundation that allowed the development of this book. Thank
you to all the participants of this research undertaking. The authors would also like
to thank the students at the University of Washington Bothell for the games they built
from the course CSS385: Introduction to Game Development (see http://courses.
washington.edu/css385). Their interest and passion for games has provided us with the
ideal deployment vehicle and are a source of continuous inspiration. They have tested,
retested, contributed to, and assisted in the formation and organization of the contents of
this book.
Jebediah Pavleas would like to thank the Computing and Software Systems Division
at the University of Washington Bothell for the generous tuition scholarships that funded
his education throughout his participation with this book project.
Thanks to Clover Wai, for once again helping us with the figures and illustrations in
this book.
We also want to thank Steve Anglin at Apress for believing in this project, to our
editor Mark Powers for his patience and toleration with our constantly behind-schedule
frenzy. Finally, we would like to thank Jason Sturges for his insightful technical feedback.
All opinions, findings, conclusions, and recommendations in this work are those of
the authors and do not necessarily reflect the views of the sponsors.
xv
Introduction
Welcome to Building a 2D Game Physics Engine: Using HTML5 and JavaScript. Because you
have picked up this book, you are likely interested in the details of a game physics engine
and the creation of your own games to be played over the Internet. This book teaches
you how to build a 2D game physics engine by covering the involved technical concepts,
and providing detailed implementations for you to follow. The source code in this book
is provided in HTML5 and JavaScript, which are technologies that are freely available and
supported by virtually all web browsers. After reading this book, the game physics engine
you develop will be playable through a web browser from anywhere on the Internet.
This book focuses only on the relevant concepts and implementation details for
building a 2D game physics engine. The presentations are tightly integrated with the
analysis and development of source code. Much of the book guides you in implementing
related concepts and building blocks while the actual functioning engine only becomes
available towards the end. Some of the algorithms and mathematics can be challenging.
Be patient. It will all pay off by the end of Chapter 4. By Chapter 5, you will be familiar
with the concepts and technical details of 2D game physics engines, and feel competent
in implementing the associated functionality.
Assumptions
You should have some basic background in Newtonian Mechanics and be experienced
with programming in an object-oriented programming language, such as Java or C#.
Knowledge and expertise in JavaScript would be a plus but is not necessary. The examples
in this book were created with the assumption that you understand data encapsulation
and inheritance. In addition, you should be familiar with basic data structures such as
linked lists and dictionaries, and be comfortable working with the fundamentals of algebra
and geometry, particularly linear equations and coordinate systems.
xvii
■ INTRODUCTION
Code Samples
Every chapter in this book includes examples that let you interactively experiment with
and learn the new materials. You can download the source code for all the projects,
including the associated assets (images, audio clips, or fonts), from the following page:
www.apress.com/9781484225820.
Follow the instructions to download the 9781484225820.zip file. To install the code
samples, unzip the 9781484225820.zip file. You should see a folder structure that is
organized by chapter numbers. Within each folder are subfolders containing NetBeans
projects that correspond to sections of this book.
xviii
CHAPTER 1
Introduction to 2D Game
Physics Engine Development
Physics engines play an important part in many types of games. A believable physics
interaction between game objects has become a key element of most modern PC and
console games as well as, more recently, browser and smartphone games. The range of
topics within physics for games is broad and includes, but is not limited to, areas such
as rigid body, fluid dynamics, soft-body, vehicle physics, and particle physics. This book
will cover the fundamental topics needed for you to get started in understanding and
building a general purpose, rigid body physics engine in two dimensions. The book also
aims to provide you with a reusable game physics engine, which can be used for your
own games, by guiding you through the process of building a physics engine step-by-step
from scratch. This way you will gain a foundational understanding of the concepts and
components required for a typical 2D rigid body system.
While you can just download a physics engine library and continue on with your
game or engine development, building your own game engine from scratch has its own
advantages. Besides giving you an underlying understanding of how the physics engine
operates, it gives you more control over the flexibility, performance, functionality, and
usability of the engine itself.
As stated, this book will cover the foundation of 2D rigid body physics. The topics will
include properties and behavior of rigid bodies, collision detection, collision information
encoding, and collision response. The goal is to obtain a fundamental understanding of
these concepts which are required to build a usable physics engine.
The book approaches physics engine development from three important avenues:
practicality, approachability, and reusability. While reading the book, we want you to get
involved and experience the process of building the game engine. The step-by-step guide
should facilitate the practicality of this book. The theories and practices introduced in this
book are based on research and investigation from many sources which cover the topics in
varying detail. The information is presented in a way that is approachable, by allowing you
to follow along as each code snippet is explained in parallel to the overall concepts behind
© Michael Tanaya, Huaming Chen, Jebediah Pavleas and Kelvin Sung 2017 1
M. Tanaya et al., Building a 2D Game Physics Engine, DOI 10.1007/978-1-4842-2583-7_1
Chapter 1 ■ Introduction to 2D Game Physics Engine Development
each component of the engine. After following along and creating your own engine, you
will be able to extend and reuse the finished product by adding your own features.
This chapter describes the implementation technology and organization of the
book. The discussion then leads you through the steps of downloading, installing, and
setting up the development environment; guides you through building your first HTML5
application; and extends this first application with the JavaScript programming language
to run your first simulation.
2
Chapter 1 ■ Introduction to 2D Game Physics Engine Development
3
Chapter 1 ■ Introduction to 2D Game Physics Engine Development
■■Note If you cannot see a window in the IDE, you can click the Window menu and select
the name of the missing window to cause it to appear. For example, if you cannot see the
Projects window in the IDE, you can select Window ➤ Projects to open it.
4
Chapter 1 ■ Introduction to 2D Game Physics Engine Development
5
Chapter 1 ■ Introduction to 2D Game Physics Engine Development
NetBeans will generate the template of a simple and complete HTML5 application
project for you. Your IDE should look similar to Figure 1-5.
6
Chapter 1 ■ Introduction to 2D Game Physics Engine Development
By selecting and double-clicking the index.html file in the Projects window, you
can open it in the Editor window and observe the content of the file. The contents are as
follows:
<!DOCTYPE html>
<!--
To change this license header, choose License Headers in Project Properties.
To change this template file, choose Tools | Templates
and open the template in the editor.
-->
<html>
<head>
<title>TODO supply a title</title>
</head>
<body>
<div>TODO write content</div>
</body>
</html>
The first line declares the file to be an HTML file. The block that follows within the
<!-- and --> tags is a comment block. The complementary <html></html> tags contain
all the HTML code. In this case, the template defines the head and body sections. The
head sets the title of the web page, and the body is where all the content for the web page
will be located.
You can run this project by selecting Run ➤ Run Project or by pressing the F6 key.
Figure 1-6 shows an example of what the default project looks like when you run it.
To stop the program, either close the web page or click the Cancel button in the
browser to stop NetBeans from tracking the web page. You have successfully run your first
HTML5 project. You can use this project to understand the IDE environment.
7
Chapter 1 ■ Introduction to 2D Game Physics Engine Development
8
Chapter 1 ■ Introduction to 2D Game Physics Engine Development
Figure 1-7. Running the HTML5 project with drawing core and user control
Drawing Core
This engine will use simple drawing code for the sole purpose of simulating the physics
engine code. After all, the only thing the simulation needs to show is how simple objects
interact after the physics engine code is implemented. Thus, advanced graphical
functionalities such as illumination, texturing, or shadow rendering will only serve to
further complicate the code base. For that reason, a simple HTML5 canvas with primitive
drawing support will serve the purpose of rendering the physics simulation during
creation and debugging.
9
Chapter 1 ■ Introduction to 2D Game Physics Engine Development
The code defines a canvas element with an id of canvas. An id is the name of the
element and can be used to retrieve the corresponding element when the web page is
loaded. Notice that no width and height is specified in the code. This is because you will
specify those attributes in the next step. You will use the canvas id to retrieve the reference
to the actual canvas drawing area where you will draw into.
10
Chapter 1 ■ Introduction to 2D Game Physics Engine Development
■■Note All global variable names begin with a “g” and are followed by a capital letter, as
in gEngine.
■■Note All instance variable names begin with an “m” and are followed by a capital letter,
as in mCanvas.
var mPublic = {
mWidth: mWidth,
mHeight: mHeight,
mContext: mContext
};
return mPublic;
11
Chapter 1 ■ Introduction to 2D Game Physics Engine Development
User Control
In this section, you will be introduced to basic user control event handlers using
JavaScript. This is to enable you to test your implementation in every step of the physics
engine’s incremental development. For this chapter, the user control script will be used
to test if you have correctly initialized the canvas and implemented drawing functionality
properly.
function userControl(event) {
var keycode;
}
if (window.event) { // IE
keycode = event.keyCode;
}
else if (event.which) { // Netscape/Firefox/Opera
keycode = event.which;
}
This script will enable you to handle keyboard input events from the browser as well
as process the input and response accordingly. In this case, you want to test the canvas
you just created in the last section. This testing can be achieved by drawing rectangles
and circles when keyboard inputs are received, as detailed in the next section.
12
Chapter 1 ■ Introduction to 2D Game Physics Engine Development
■■Note The UserControl.js will evolve over the development to handle more keyboard
inputs and more complex responses.
13
Chapter 1 ■ Introduction to 2D Game Physics Engine Development
// radius
context.closePath();
context.stroke();
}
Now if you run the project and press the key F or G, the simulation will draw either
a circle or rectangle at a random position with random sizes as shown in Figure 1-7 above.
Summary
By this point the physics engine’s basic drawing function has been initialized, and
should be able to draw a rectangle and a circle onto the canvas with basic input required
from the user. In this chapter, you have structured the source code that supports future
increase in complexity with a simple way to draw rigid bodies. You are now ready to
extend the functionalities and features of your project into a physics engine. The next
chapter will focus on the core functionalities needed for any game or physics engine
(engine loops, vector calculation), as well as evolving rectangles and circles into rigid
body object-oriented objects to encapsulate their drawing and behaviors.
14
Another Random Scribd Document
with Unrelated Content
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.6. You may convert to and distribute this work in any binary,
compressed, marked up, nonproprietary or proprietary form,
including any word processing or hypertext form. However, if you
provide access to or distribute copies of a Project Gutenberg™ work
in a format other than “Plain Vanilla ASCII” or other format used in
the official version posted on the official Project Gutenberg™ website
(www.gutenberg.org), you must, at no additional cost, fee or
expense to the user, provide a copy, a means of exporting a copy, or
a means of obtaining a copy upon request, of the work in its original
“Plain Vanilla ASCII” or other form. Any alternate format must
include the full Project Gutenberg™ License as specified in
paragraph 1.E.1.
• You pay a royalty fee of 20% of the gross profits you derive
from the use of Project Gutenberg™ works calculated using the
method you already use to calculate your applicable taxes. The
fee is owed to the owner of the Project Gutenberg™ trademark,
but he has agreed to donate royalties under this paragraph to
the Project Gutenberg Literary Archive Foundation. Royalty
payments must be paid within 60 days following each date on
which you prepare (or are legally required to prepare) your
periodic tax returns. Royalty payments should be clearly marked
as such and sent to the Project Gutenberg Literary Archive
Foundation at the address specified in Section 4, “Information
about donations to the Project Gutenberg Literary Archive
Foundation.”
• You comply with all other terms of this agreement for free
distribution of Project Gutenberg™ works.
1.F.
1.F.4. Except for the limited right of replacement or refund set forth
in paragraph 1.F.3, this work is provided to you ‘AS-IS’, WITH NO
OTHER WARRANTIES OF ANY KIND, EXPRESS OR IMPLIED,
INCLUDING BUT NOT LIMITED TO WARRANTIES OF
MERCHANTABILITY OR FITNESS FOR ANY PURPOSE.
Please check the Project Gutenberg web pages for current donation
methods and addresses. Donations are accepted in a number of
other ways including checks, online payments and credit card
donations. To donate, please visit: www.gutenberg.org/donate.
Most people start at our website which has the main PG search
facility: www.gutenberg.org.
Our website is not just a platform for buying books, but a bridge
connecting readers to the timeless values of culture and wisdom. With
an elegant, user-friendly interface and an intelligent search system,
we are committed to providing a quick and convenient shopping
experience. Additionally, our special promotions and home delivery
services ensure that you save time and fully enjoy the joy of reading.
textbookfull.com