Monthly Archives: December 2017

Creating a 3D Game With Three.js and WebGL

Prerequisites

  • A browser with WebGL – this game has been tested on Chrome and Firefox. IE still doesn’t support WebGL, unless you’re using Windows 8.1 with IE11.
  • Three.js library available for download from the Three.js website
  • The Keyboard.js helper library I used for this project, created by Arthur Schreiber at No Karma. Download it from my GitHub repository
  • A basic understanding of what Three.js does. Read this super simple, super quick tutorial by Paul Lewis. It’s basically a short-hand version of this article.

Setup

Get a base index.html running

Step one when making a web-based game is to create the host index.html file. In our case, it only needs to be a very simple set of elements, so we can bundle the CSS styling too.

Import Keyboard.js and Three.js

Three.js is a library contained in just one JavaScript file, so we can grab the minified version from the website.

For Keyboard input, we will need to referencethe aforementioned JavaScript file in our index.html as well.

Create setup() and draw() functions

The setup() function will be the start point for the game code. The draw() function will be run every frame and will handle all the rendering and game logic.

In order to loop the draw() function, we simply utilise the requestAnimationFrame() function call, and pass ‘draw’ as the parameter. Remember, not all browsers natively support the call, and you might have to use Paul Irish’s shim to gain maximum compatibility. Also, it is important to realise that requestAnimationFrame() does not guarantee a fixed frame-rate, so you need to use time-deltas to calculate realistic physics. For a basic game like Pong, we don’t really care about that.

Basic World

Set up the Three.js world and camera

Three.js includes these important elements:

  • Scene
  • Renderer
  • Camera
  • Mesh
  • Light
  • Material

Cameras, Meshes, and Lights need to be added to the scene using the scene.add() function.

Attach a WebGL Three.js Renderer to the DIV

The renderer is attached to whichever HTML DOM element you wish to render the scene to, and a render() call is made each frame to the renderer in order to draw the Three.js scene.

Add a camera to the scene

Three.js has the option to create Perspective and Orthographic cameras. For most uses, Perspective camera is the best choice. We can change position and rotation information of the camera like any other object in the scene.

Draw a sphere and light it

Meshes must be paired with Materials in order to give them a defined look and feel. Meshes can be of many types, include primitives such as Cube, Sphere, Plane and Torus. Materials can have different characteristics depending on their type. The basic Material types include Lambert, Phong, and Basic.

  • Basic renders an unlit Mesh with no shadows or dark shading. A sphere will look like a circle if rendered with Basic.
  • Lambert is a simple diffuse-like lighting that creates shading on sides facing away from a light source. It gives a basic 3D look of surfaces that are matte (non-shiny and non-reflective)
  • Phong is used for achieving a plastic-like look and feel, with the ability to gain highlights that give a much shinier appearance to the Mesh.

Show off your sphere with a Point Light. This is the most basic light, with no direction or rotation. Make sure you tweak the light’s intensity and distance to get it looking good.

Add Game Objects

Draw playing area plane

The playing area will be a Three.js Mesh object of type Plane. Make sure the plane matches the play area, giving a small buffer gap to indicate where the paddles can and can’t go.

Draw paddles

The paddles will be Mesh objects of type Cube. Position each of the paddles on opposite sides of the play area.

1234567891011121314151617181920212223242526272829303132333435363738394041
// set up the paddle vars
paddleWidth = 10;
paddleHeight = 30;
paddleDepth = 10;
paddleQuality = 1;
// set up paddle 1
paddle1 = new THREE.Mesh(
new THREE.CubeGeometry(
paddleWidth,
paddleHeight,
paddleDepth,
paddleQuality,
paddleQuality,
paddleQuality),
paddle1Material);
// add the paddle to the scene
scene.add(paddle1);
// Set up the second paddle
paddle2 = new THREE.Mesh(
new THREE.CubeGeometry(
paddleWidth,
paddleHeight,
paddleDepth,
paddleQuality,
paddleQuality,
paddleQuality),
paddle2Material);
// Add the second paddle to the scene
scene.add(paddle2);
// set paddles on each side of the table
paddle1.position.x = -fieldWidth/2 + paddleWidth;
paddle2.position.x = fieldWidth/2 – paddleWidth;
// lift paddles over playing surface
paddle1.position.z = paddleDepth;
paddle2.position.z = paddleDepth;
view rawBNG_Pong_paddlecreateThis Gist brought to you by GitHub.

If you manipulate the camera positions, as seen in the screenshot, you can give a different perspective to the player.

Basic Logic

Ball movement

The ball will have an X-direction and a Y-direction that determines the movement per frame.

// ball’s x-direction, y-direction and speed per frame
var ballDirX = 1, ballDirY = 1, ballSpeed = 2;

The ball will move at a constant speed in the X-plane every frame. To this end, we will specify a ballSpeed variable that acts as a multiplier for the direction values.

// update ball position over time
ball.position.x += ballDirX * ballSpeed;
ball.position.y += ballDirY * ballSpeed;

We want the ball to have some unpredictable characteristics (e.g. when it gets sliced quite hard) so we will allow the Y-direction to go up to a maximum of ballSpeed * 2. You can tweak the values until you’re happy with how the ball behaves.

// limit ball’s y-speed to 2x the x-speed
// this is so the ball doesn’t speed from left to right super fast
// keeps game playable for humans
if (ballDirY > ballSpeed * 2)
{
ballDirY = ballSpeed * 2;
}
else if (ballDirY < -ballSpeed * 2)
{
ballDirY = -ballSpeed * 2;
}

Ball wall bounce logic

Simple collision detection logic is required to check if the ball is touching each of the side ‘walls’. Using a series of ‘if-else’ statements, we check the ball positions against the predetermined wall positions. In the case of a collision, we simply switch the Y-direction of the ball, creating a bounce effect.

// if ball goes off the top side (side of table)
if (ball.position.y <= -fieldHeight/2)
{
ballDirY = -ballDirY;
}
// if ball goes off the bottom side (side of table)
if (ball.position.y >= fieldHeight/2)
{
ballDirY = -ballDirY;
}

Later, we will edit some of this code in order to implement scoring when the ball passes a paddle.

Keyboard input for paddles

We will utilise a very effective short-cut in order to easily get keyboard input working in this game. Using the Keyboard.js file provided, we simply have to include the reference to it in the index.html file and we are set. Only one function call is required, the Key.isDown() call. Given a parameter, the library checks if that particular key is current being pressed, and returns a boolean value.

// move left
if (Key.isDown(Key.A))
{
// code to move paddle left
}

We use the ‘A’ and ‘D’ keys to move the paddle left and right, but you can edit the Keyboard.js with additional values if you want to use your own control scheme.

var Key = {
_pressed: {},
A: 65,
W: 87,
D: 68,
S: 83,
// add your required key code (ASCII) along with the name here
// for example:
SPACE: 32,
};

While dealing with keyboard input, it is also important to ensure that the input is never blindly updated in game. We have to check that the paddle isn’t made to move off the play area, and we do that with some ‘if-else’ statements as well.

// move left
if (Key.isDown(Key.A))
{
// if paddle is not touching the side of table
// we move
if (paddle1.position.y < fieldHeight * 0.45)
{
paddle1DirY = paddleSpeed * 0.5;
}
// else we don’t move and stretch the paddle
// to indicate we can’t move
else
{
paddle1DirY = 0;
paddle1.scale.z += (10 – paddle1.scale.z) * 0.2;
}
}

Note that we use a paddle direction variable, rather than simply applying a change to the position values. This will come in handy when programming the ball to ‘slice’ when hit at an angle with a fast-moving paddle.

Opponent logic

When you code a game of this calibre, it is of utmost importance that you create a vivid, lush environment with a host of emotional, highly-relatable characters that showcase this generation’s strides forward in technology. Instead, we will code a Pong A.I. that blindly follows the ball, because that is even better.

We can update the opponent difficulty by using a variable instead of introducing magic numbers. This variable will affect the ‘reaction rate’ of the opponent by increasing the Lerp (Linear-Interpolation) time.

When using a Lerp (Linear-Interpolation) function, we must ensure the opponent plays fairly by limiting their maximum travel speed. We do that with a few more if-else statements.

// in case the Lerp function produces a value above max paddle speed, we clamp it
if (Math.abs(paddle2DirY) <= paddleSpeed)
{
paddle2.position.y += paddle2DirY;
}
// if the lerp value is too high, we have to limit speed to paddleSpeed
else
{
// if paddle is lerping in +ve direction
if (paddle2DirY > paddleSpeed)
{
paddle2.position.y += paddleSpeed;
}
// if paddle is lerping in -ve direction
else if (paddle2DirY < -paddleSpeed)
{
paddle2.position.y -= paddleSpeed;
}
}
If want to extend immersion, you could also using the paddle.scale property to stretch the paddle when it can’t be moved. This indicates an issue to the player which they can then address immediately. In order to accomplish this, we must ensure the paddle always Lerps back to the default scale size.
// We lerp the scale back to 1
// this is done because we stretch the paddle at some points
// stretching is done when paddle touches side of table and when paddle hits ball
// by doing this here, we ensure paddle always comes back to default size
paddle2.scale.y += (1 – paddle2.scale.y) * 0.2;

Adding Gameplay

Making the ball reset after missing a paddle

To get the main scoring gameplay working, we need to first remove the ball’s ability to bonce off the paddle-facing walls. To do this, we remove the bounce code from the two corresponding if-else statements.

// if ball goes off the top side (side of table)
if (ball.position.y <= -fieldHeight/2)
{
ballDirY = -ballDirY;
}
// if ball goes off the bottom side (side of table)
if (ball.position.y >= fieldHeight/2)
{
ballDirY = -ballDirY;
}
//// ——————————— ////
CHANGED CODE
//// ——————————— ////
// if ball goes off the ‘left’ side (Player’s side)
if (ball.position.x <= -fieldWidth/2)
{
// CPU scores a point
// update scoreboard
// and reset ball
}
// if ball goes off the ‘right’ side (CPU’s side)
if (ball.position.x >= fieldWidth/2)
{
// player scores a point
// update scoreboard
// and reset ball
}

We can handle scoring in many different ways. For a simple game like this, we can simply increment the corresponding score count variable.

// if ball goes off the ‘left’ side (Player’s side)
if (ball.position.x <= -fieldWidth/2)
{
// CPU scores
score2++;
// update scoreboard HTML
document.getElementById(“scores”).innerHTML = score1 + “-” + score2;
// reset ball to center
resetBall(2);
// check if match over (someone scored maxScore points)
matchScoreCheck();
}

We can then update the HUD element in the DOM by setting its innerHTML value. Finally, we have to reset the ball once someone has scored. A simple function can be written to reset the ball, with a parameter indicating which paddle just lost (so we know which paddle to send the ball to next time).

// resets the ball’s position to the centre of the play area
// also sets the ball direction speed towards the last point winner
function resetBall(loser)
{
// position the ball in the center of the table
ball.position.x = 0;
ball.position.y = 0;
// if player lost the last point, we send the ball to opponent
if (loser == 1)
{
ballDirX = -1;
}
// else if opponent lost, we send ball to player
else
{
ballDirX = 1;
}
// set the ball to move +ve in y plane (towards left from the camera)
ballDirY = 1;
}

Making the ball bounce off paddles

Alright, this is it. The big one. Literally the biggest feature of this game. It’s time to get the paddles hitting the ball. In a simple Pong game, paddle-ball physics are nothing more than a couple of if-else statements. We check the X-position and Y-position of the ball against the paddle’s rectangular bounds, and if they intersect, we bounce the ball away.

// if ball is aligned with paddle1 on x plane
// remember the position is the CENTER of the object
// we only check between the front and the middle of the paddle (one-way collision)
if (ball.position.x <= paddle1.position.x + paddleWidth
&& ball.position.x >= paddle1.position.x)
{
// and if ball is aligned with paddle1 on y plane
if (ball.position.y <= paddle1.position.y + paddleHeight/2
&& ball.position.y >= paddle1.position.y – paddleHeight/2)
{
// ball is intersecting with the front half of the paddle
}
}

It’s also important to check the direction of the ball’s travel, as we only want to check collisions in one direction (the direction towards the opponent.)

// and if ball is travelling towards player (-ve direction)
if (ballDirX < 0)
{
// stretch the paddle to indicate a hit
paddle1.scale.y = 15;
// switch direction of ball travel to create bounce
ballDirX = -ballDirX;
// we impact ball angle when hitting it
// this is not realistic physics, just spices up the gameplay
// allows you to ‘slice’ the ball to beat the opponent
ballDirY -= paddle1DirY * 0.7;
}

We will also affect the ball’s lateral movement depending on the relative speed of the paddle when hitting the ball. This is particularly useful in introducing the biggest variable in Pong: the slice. Slicing the ball is often the only way to confuse and outmaneuver the opponent, so it is vital in this game.

Remember to duplicate the code, but update the values to match the opponent’s paddle. You can use this opportunity to gimp your opponent’s ability somewhat, by reducing the hitbox size or decreasing the slice amount. It’s what we would all do.

Here is the final paddle-ball collision function:

// Handles paddle collision logic
function paddlePhysics()
{
// PLAYER PADDLE LOGIC
// if ball is aligned with paddle1 on x plane
// remember the position is the CENTER of the object
// we only check between the front and the middle of the paddle (one-way collision)
if (ball.position.x <= paddle1.position.x + paddleWidth
&& ball.position.x >= paddle1.position.x)
{
// and if ball is aligned with paddle1 on y plane
if (ball.position.y <= paddle1.position.y + paddleHeight/2
&& ball.position.y >= paddle1.position.y – paddleHeight/2)
{
// and if ball is travelling towards player (-ve direction)
if (ballDirX < 0)
{
// stretch the paddle to indicate a hit
paddle1.scale.y = 15;
// switch direction of ball travel to create bounce
ballDirX = -ballDirX;
// we impact ball angle when hitting it
// this is not realistic physics, just spices up the gameplay
// allows you to ‘slice’ the ball to beat the opponent
ballDirY -= paddle1DirY * 0.7;
}
}
}
// OPPONENT PADDLE LOGIC
// if ball is aligned with paddle2 on x plane
// remember the position is the CENTER of the object
// we only check between the front and the middle of the paddle (one-way collision)
if (ball.position.x <= paddle2.position.x + paddleWidth
&& ball.position.x >= paddle2.position.x)
{
// and if ball is aligned with paddle2 on y plane
if (ball.position.y <= paddle2.position.y + paddleHeight/2
&& ball.position.y >= paddle2.position.y – paddleHeight/2)
{
// and if ball is travelling towards opponent (+ve direction)
if (ballDirX > 0)
{
// stretch the paddle to indicate a hit
paddle2.scale.y = 15;
// switch direction of ball travel to create bounce
ballDirX = -ballDirX;
// we impact ball angle when hitting it
// this is not realistic physics, just spices up the gameplay
// allows you to ‘slice’ the ball to beat the opponent
ballDirY -= paddle2DirY * 0.7;
}
}
}
}
view rawBNG_Pong_paddlecollCompleteThis Gist brought to you by GitHub.

Scoring

In Pong, it is usually simplest to have a maximum score value, such that a game is won when either player reaches that score. To that end, we can easily create a maxScore variable and set it at the start of the match.

We then create a function to check if either player has scored equal or higher than the maximum. This function should be called only when a score has been changed (i.e. when someone scores a point.)

// checks if either player or opponent has reached 7 points
function matchScoreCheck()
{
// if player has 7 points
if (score1 >= maxScore)
{
// stop the ball
ballSpeed = 0;
// write to the banner
document.getElementById(“scores”).innerHTML = “Player wins!”;
document.getElementById(“winnerBoard”).innerHTML = “Refresh to play again”;
}
// else if opponent has 7 points
else if (score2 >= maxScore)
{
// stop the ball
ballSpeed = 0;
// write to the banner
document.getElementById(“scores”).innerHTML = “CPU wins!”;
document.getElementById(“winnerBoard”).innerHTML = “Refresh to play again”;
}
}

After a match is deemed complete, it is simplest to just return the ball to the centre and stop any movement, so that play doesnt inadvertently continue.

Prettifying the Game

HUD

It’s important to give feedback to the player so they know what’s going on. For Pong, the least we can do is keep a scoreboard ticking over. Instead of trying to draw the HUD on the same layer as the game, we can use the other DOM elements to provide the required feedback.

It’s also good to indicate the maximum score as well, so we have another element for that which we will update at match start.

// update the board to reflect the max score for match win
document.getElementById(“winnerBoard”).innerHTML = “First to ” + maxScore + ” wins!”;

Shadows

Finally, it is time to make things look a tad more polished. Three.js has the awesome ability to create shadows for primitive objects (Cube, Plane, Sphere, etc.) so we can utilise that to make the game look nicer.

Shadows can’t be created with just a Point light, so we have to add a DirectionalLight or a SpotLight. A SpotLight shines a circular beam of light onto surfaces, which DirectionalLight simply shines a light in a certain direction with no regard to positioning.

We will use a SpotLight because it clearly indicates where the light originates from and shines towards.

We can update the SpotLight to follow the ball around to give a more dynamic look and feel to the game, whilst showcasing the hard work we just put into the lighting.

// we can easily notice shadows if we dynamically move lights during the game
spotLight.position.x = ball.position.x;
spotLight.position.y = ball.position.y;

To make an object in the scene cast or receive shadows, we simply set their .receiveShadow and .castShadow variables to true. For example,

paddle1 = new THREE.Mesh(
new THREE.CubeGeometry(paddleWidth, paddleHeight, paddleDepth, paddleQuality, paddleQuality, paddleQuality),
paddle1Material);
// add the sphere to the scene
scene.add(paddle1);
paddle1.receiveShadow = true;
paddle1.castShadow = true;

Conclusion

This is but a basic introduction to the power of Three.js, which should allow you to create a basic Pong clone.

Play the latest build of this game here: LATEST BUILD*

Find the latest code at its GitHub page*

You can still do quite a number of things to polish your game, such as

  • Create animations for the paddles and ball
  • Update the HUD to look prettier
  • Import complex objects created in Modeling packages, to design a more immersive environment
  • Move HUD elements inside the game view to allow for full-screen gaming
  • Mess around with complex shaders to create reflections and other cool effects

Gigabyte Launches Latest Game Keyboard K7 FORCE Stealth with Anti-ghosting feature

Gamers can now obtain the latest gaming keyboard option in the shopping list. The new gaming keyboards come from Gigabyte called FORCE K7 Stealth. And as a gaming keyboard, FORCE Stealth K7 is also equipped with several features gaming supporters.

The main feature on the keyboard is the anti-ghosting. This feature allows players to be able to press 7 keys simultaneously without conflict. But not all of the support this feature. There are only seven buttons, namely the Q, W, A, S, D, left Shift and Spacebar.

In addition keyboard also comes with a three-color illumination that can be arranged. Three colors are blue, green and cyan. Not only that, the keyboard buttons also have a thin structure. With so each button is pressed, aktuasinya very close distance.

Twitter Sensor Feature Release Pornography

San Francisco – Twitter introduced reforms for iOS and Android application on July 17, 2013. The update was a method of censorship of sensitive content, such as pornography and violence, which appeared in the early post-twit.
If Twitter states that an image or a video containing sensitive issues, Twitter will display a label containing the message. Users must click if you want to see the media.
Message in the label reads, “Media in circulation could contain sensitive content. Twit media settings can be set to inform you if the media contains sensitive content.” Then the user can click “View,” or “Always show my sensitive media.”
New features began to appear in the July 2013. Users can also tag pictures or video as a medium sensitive to the setting. So, Twitter can give a warning to others before they click the image or video that you post.
This is a simple way to keep Twitter users more comfortable and not bothered with unwanted content. Especially for the user of Twitter among children and adolescents.

Infinite Skills’ “Adobe Acrobat XI Security Tutorial” Targets Advanced Capabilities for Encryption and Authentication In Adobe’s PDF Creation Tool

Software training firm Infinite Skills Inc. last week introduced its “Adobe Acrobat XI Security Tutorial,” a condensed course targeted specifically toward using Acrobat XI to create and exchange information-sensitive digital documents.

Advanced security features have long been a feature that sets Acrobat apart from other digital document applications. Acrobat XI has capabilities for password protection and certificate encryption, digital signatures, and many other advanced security features that make it a one-stop solution for document management.

Infinite Skills’ “Adobe Acrobat XI Security,” covers all these features in a quick, easy-to-understand guide that will allow users to begin creating and transferring secure documents in just a few short hours.

Adobe Acrobat XI Security Video Training – DVD

Course author Michael Hoffman is a career photographer, artist, and trainer, with Adobe certifications in Acrobat and Photoshop. After beginning his career creating technical illustrations and photographs for electronic equipment manufacturers, he has continued to combine technology, photography and education in a productive career.

This brief, highly focused course, covers password and certificate encryption, creating a digital ID, how to sign a .pdf file, how to certify a .pdf file, and using Adobe’s EchoSign feature.

Other chapters include working with actions and creating custom actions, using security features in print situations, problem correction, and compatibility issues, along with several other specialized security features including options for automating repetitive tasks.

“Acrobat XI Professional is far more than just a tool for viewing .pdf files,” Hoffman explains. “It is an incredibly complex program, and its security features are part of a complete package that provides a seamless automated collaborative solution for almost any document management need.”

Free demo videos and a full list of course contents can be found on the Adobe Acrobat XI Security Tutorial training page of the InfiniteSkills website:

http://www.infiniteskills.com/training/advanced-adobe-acrobat-xi-training.html

InfiniteSkills offers its Adobe Acrobat XI Security Tutorial either as a DVD or a direct download from the company website at a retail price of $24.95. All InfiniteSkills titles and formats are compatible with both Mac and Windows operating systems, and shipping is available around the globe. InfiniteSkills tutorials are supported by project files which correspond to examples in the videos.

About InfiniteSkills Inc.
A leader in the field of software training, InfiniteSkills strives to offer the highest quality training available at an affordable cost. InfiniteSkills tutorials are task-oriented instructional videos, teaching complex skills by providing hands-on examples, guiding users as they carry out critical objectives. InfiniteSkills offers a comprehensive range of software titles available as DVDs, digital downloads, and iPad editions, keeping with company aim of delivering professional training to customers anywhere they want to learn.

Asus Memo Pad HD 7 review: Vivid screen barely outshines slow performance

The good: The Asus Memo Pad HD 7 rocks an impressively colorful screen, features a bevy of useful customization options, and comes in at a budget price.

The bad: Its performance is mediocre and the touch screen is sometimes unresponsive. The plastic build gives it a toy-like feel and it isn’t very comfortable to hold. The dull design lacks panache.

The bottom line: For those looking to save a buck, for its low price, the Asus Memo Pad HD 7 has a bevy of useful features, though there are better performing options out there.

With the Asus Memo Pad HD 7, you really get what you pay for. The HD 7 earns its low price with a lackluster design and sluggish performance. It’s not very comfortable to hold for long periods of time, and aside from being offered in a variety of different colors, lacks a coolness other tablets try hard to aspire to.

Its performance is meekly mediocre, and consistent lagging combined with a sometimes unresponsive touch screen make the tablet best suited for simple tasks like browsing and reading.

That said, the HD 7 is a refreshing upgrade from its predecessor and its best feature is the 7-inch IPS screen that displays an impressively wide range of colors which facilitate a visually richer experience than the original Nexus 7.

If you’re on a strict budget, the Asus Memo Pad is an inexpensive and functional small tablet, but if you can spare the change, a new Nexus 7 is the better choice.

Design
Even though the tablet shares similar dimensions with the Nexus 7, it’s nowhere near as sleek or comfortable in design. The tablet fits fine in one hand, even for people with smaller hands like me, yet, despite its light weight, the design doesn’t lend itself to comfortable holding over lengthy periods of time.

The back panel protrudes slightly, and the corners slightly dig into your palms when holding it in both hands, instead of the flush, smoothly curved edges of the original Nexus 7. I often found myself wanting to put the device down after using it for awhile — not because I was done using it — but because holding it became tiresome.

The Asus Memo Pad HD 7 comes in navy blue, white, hot pink, and lime green. The navy blue version is the only one that has a back with a matte finish. The dark shade of blue attracts a minimal amount of fingerprints that are only highly visible from certain angles. The back panel is smooth and comfortable to the touch but can be a bit slippery without a tight grip.

In comparison, the reflective plastic backsides of the other colors looks less chic, but its texture helps one grip the device significantly better than the matte finish does. I personally prefer a back panel with a grippier texture, like the Nexus 7 (2012), because it enhances my comfort level in a way that extends the amount of time I can hold the device.

Since they’re both made by Asus, the Memo Pad HD 7 and the Nexus 7 (2012) share similar design elements. The power button and volume rocker on the right edge look almost identical in shape, while the rear speakers are similarly located towards the bottom edge of the tablet.

The front of the tablet is typically simple, with an Asus logo on the bottom bezel and a front-facing camera on the top. There is no ambient light sensor, therefore no automatic brightness setting.

The Memo Pad HD 7’s headphone jack, microphone pinhole, and Micro-USB port are all located on the top edge, with the microSD expansion slot — which is expandable up to 32GB — around the corner on the left edge. There are no ports on the bottom edge, but the speaker sits on the bottom of the tablet’s back, keeping the 5-megapixel rear camera on top company.

Asus Application Suite
The tablet comes loaded with the Asus Application Suite and features apps that range from useful to creative. The simple additions include a calendar, to-do list, and file manager, and it comes with 16GB of Asus WebStorage cloud service for one year.

Some of the apps that are geared towards family use include App Locker, which allows you to put passwords on specific apps; Asus Artists, where you can create “paintings” or greeting cards; and Asus Story, which helps you organize your photos into albums, or as they call them, “stories.”

The tablet comes with Power Saver, a battery saving feature that comes in handy if you’re trying to squeeze the most out of a low battery.

The custom mode lets you pick the specific functions that the power-saving option affects. For example, you can set a low screen brightness for listening to music, a higher one for watching video, and no power-saving function for reading books. When enabled, it significantly helped extend the battery life when it was low and the highly customizable options.

Floating apps
One of the most interesting and useful features on the tablet is the floating menu. On the Android navigation bar, there’s a button to the left of the back button that activates the floating menu.

When activated, a small menu pops up above the navigation bar that contains a selection of floating apps that you can quickly access without having to close whatever app you’re currently using. Since the apps “float” on the screen, on top of whatever is already open, it’s almost like a multiwindow option, but they can only perform simple tasks and can’t compare to the multiwindow functions that the Microsoft Surface or some of the Samsung Galaxy tablets provide.

Floating apps are an easy way to multitask, and I liked the ability to use the browser while watching video, but not all streaming video services continue to play while a floating app is open. With the exception of a few floating apps, including the calculator and compass, Netflix did not let me use most of the floating apps while simultaneously watching video, although YouTube did.

Despite providing an easy way to multitask, the floating apps don’t have the same functionality as the fullscreen app and are limited in their capabilities; the YouTube app only shows recommended videos — you can’t search — and the Twitter app displays only one tweet at a time. There is a limited amount of floating apps, and although the floating menu is customizable, not all downloaded apps have the ability to be floating ones.

Speaker features
The Memo Pad HD 7 houses stereo speakers with Asus SonicMaster audio technology and Audio Wizard software. Although the speakers aren’t great, the number of specific audio settings are. The tablet allows you to manually adjust separate volume settings for app audio, notifications, and alarms.