Tuts+ Is Looking for a New Course Producer (Audio/Video Production)!
We’re looking for a new Course Producer to help instructors produce top-quality video and audio for their Tuts+ courses.
In this key role, you will primarily focus on working with new instructors, bringing them up to speed with Tuts+ course creation. You’ll be a friendly, knowledgeable member of our team, coaching them through their first few courses with Tuts+ and making sure that their audio, video, course assembly and overall presentation meets our standards. You will also help our existing instructors with setup, equipment, editing, post-production and presentation advice.
You'll work 40 hours a week, and you'll have the flexibility of working from home to your own schedule. As part of our global Tuts+ Course Production team, most of your interactions will be remote, meaning you’ll meet with colleagues and instructors on a regular basis via Google Hangouts and/or Skype. Your instructors will be spread predominantly across Europe, US and UK time zones, so ideally you’ll be from a location that makes communication with them easy to arrange and conduct.
What We're Looking For
With a minimum of three years experience in quality video and audio production, you will be excited about reviewing current standards and sourcing cost-effective ways to continuously improve the quality and educational value of Tuts+ course content.
The ideal person to fill this rewarding, flexible role would have:
3+ years proven experience in quality video/audio production
Excellent written and verbal communication skills (you’ll be explaining to instructors how to create/improve courses via video, not in person)
A background in education is preferable
A proven history of self-driven productivity and superior time management
Understanding and appreciation for remote, global working, including willingness to work outside of traditional hours and be flexible with the timing of meetings
The confidence to initiate conversations, and the tact to tailor advice to differing experience levels
Patience when working with individuals and groups to achieve a desired quality outcome
Comfortable when presenting on camera
A preparedness to become extensively familiar with Tuts+ standards and guides
A personable warmth, sense of humour and respect for individual team members
A clear sense of fairness and a consistency of set expectations
Familiarity with Basecamp and Trello (nice to have)
We're hoping to get the process moving fairly quickly with this role. So if you're thinking of applying, please do so as soon as possible. The deadline for applications is 20th February.
To apply, please submit a cover letter to jobs@envato.com with the subject line “I’m your ideal Course Producer because…” along with a current copy of your resume.
In your email application, along with why you're right for this role, please answer the following questions:
What is your current country of residence?
How many years experience do you have in a similar role?
When are you available to start?
What is your expected daily rate in USD?
Tell us in 100 words or less why you’d love to work at Envato.
There are lots of game genres that haven't really been explored, save for maybe the one or two games that pioneered them. Each underused genre offers a niche and a lot of
possibilities to developers experimenting with it—especially for
indie developers.
In this article, we'll take a look at some genres that some successful games belong to, but that never caught on in a major way and have never been fully explored. We'll go through some examples of games in each genre, then look at some of the major game design elements that make it up, to see what makes it tick.
Space Roguelike
Flotilla
FTL - Faster Than Light
Weird Worlds - Return to Infinite Space
The Space Roguelike is a rare genre, despite space games and roguelikes separately being well-known and popular.
A space-roguelike is made of almost equal parts space navigation, decision making, and battle sequences. You choose a destination from a starmap, have to make a decision with meaningful repercussions (you encounter pirates; do you pay them off or do you fight?), and then (possibly) fight battles.
The games given above each have their own approach to fighting mechanics. In Flotilla you decide how to move while the game is paused, after which the movements are executed. Weird Worlds presents a top-down 2D-shooter. In FTL you see a view of your ship and those of the enemies, and chose which sub-systems to target.
Most systems and mechanics of the space roguelike can also easily work in a pirate setting. A good example of a game like this is Pixel Piracy.
Pirate Overlord Simulator
Tropico 2: Pirate Cove
The Tropico series usually centers on managing a banana republic in a modern setting. Tropico 2 made a unique choice: it was about building and managing a pirate hideout.
In this genre, the gameplay centers mainly on city building. A vital part of gaining resources, however, is sending out pirate ships to gather plunder and captives. You can build and capture a variety of ships and crew them with pirates that live on your island, who are a bit like Sims, with wants and needs and certain skills that can be developed.
Over time, your secret pirate outpost grows in size and reputation, as does your fleet. You'll recruit more pirates to your town and train them in special schools to improve their skills.
Hacker Games
Uplink
Hacker Evolution
Hacker games are unique in that they are often presented as if inside a (fictional) operating system with a primarily functional user-interface. Thus, the "hacking" elements appear in a more authentic fashion.
This lack of "flashiness" is a vital element. The data is presented matter-of-factly, like it would be in an actual OS. This might even include boring and mundane tasks:
One action in Uplink, for example, is to search for a file with a
certain name while the connection timer runs down. This alone can add tension.
Parachuting Games
AaAaAA!!! - A Reckless Disregard for Gravity
Games about falling should be more prevalent, since they are generally easier to make than games of many other genres. AaAaAA!!! is the pioneer, styling itself as a base-jumping game.
You fall down an improbable landscape and gain points by moving close to buildings, through targets and narrow spots, activating your parachute as late as possible, and touching down on the landing zone.
Another element is finding the optimal route through the world presented. Many elements factor into that, like the placement of buildings and breakable glass plates, which give different bonuses depending on their color. With all these factors, levels can be created that offer interesting paths downwards.
Heist Games
Monaco
Payday
The Amazing Miss Take
These are similar to stealth games, but unlike Splinter Cell and Metal Gear Solid, these rely not on action-fueled battle (or avoiding it), but performing quiet and planned heists.
These are often set in a '70s Heist movie setting, with the levels being museums and art galleries. Gameplay is centered around avoiding security cameras and guards, and swiping the desired loot.
Even Payday, which is a shooter, offers tons of non-violent ways to complete missions, which often are more tense and interesting than just having to shoot enemies.
Focus the gameplay on avoiding guards and staying in the shadows. Alarm systems and lasers offer puzzles to work around. Loot strewn around the level, with various risks attached to it, offer meaningful decisions: do you risk the reward, or do you play it safe?
Payday 2 is wonderfully designed in that it actively fosters greed. You only get a payout if at least one person makes it out alive, but every person left behind carries also a penalty. If somebody is downed, your first instinct would be to save them, but that would risk the entire enterprise, and thus the reward.
Weapon Simulator Shooters
Receiver
Shooting in mainstream games has been streamlined to such a degree that players instinctively hammer the "reload" button all the time, regardless of whether it destroys the immersion in the scene.
Receiver is the prime example of a game that does the opposite. Instead of pressing R to reload, every action of operating a gun has a single button assigned. In order to reload a weapon you have to:
Activate the safety
Remove the current magazine
Chamber rounds into a new or the same magazine
Insert the magazine
Load the first bullet
Deactivate the safety
See the text in the right-hand side of these screenshots? Each action has an unique key assigned. Learning the keys is difficult. Operating a firearm is a puzzle, and mastering the many elements, especially while under pressure, is incredibly gratifying.
All this makes the game much more intense, without having to rely too much on surroundings or enemies.
Lemmings-like
Eets
Flockers
Your Doodles are Bugged!
Ever since its release in 1991, the original Lemmings has been a classic of video game history. Surprisingly, apart from the "official" sequels bearing the Lemmings name, games using its rules are few and far between, with Team 17's Flockers being the rare modern one.
The rules are centered around herding a group of (mostly mindless) beings through an environment filled with dangers. At the right moment, you have to intervene to adjust the "flow" of beings, by assigning roles to them or removing obstacles.
There are a lot of possibilities to create puzzles and obstacles. Another element is the necessary sacrifice of your herd of mindless animals. How many of them can become a stairwell to help others across? When you have to blow one up, can you try to keep it isolated from the rest to minimize losses? These are meaningful decisions presented by the gameplay.
Time Travel Games
Braid
Achron
The Misadventures of P.B. Winterbottom
In all fairness, modeling time-travel in games is fairly complicated, which might explain the lack of examples.
The unique nature of time travel allows many ways to include the theme. Braid allows you to rewind of the entire level and undo all of your actions, and adds elements that resist this reversal of time to create unique puzzles. In Achron you can see the battle in four dimensions, and view the past and the future. Interactions outside of the present require more resources, though.
Even simple gags are possible, like in Magicka, where you jump into the past and see your own selves moving about, like you yourself did a few levels ago.
Parkour Games
Mirror's Edge
inMomentum
These are distinct from the endless runners, like Canabalt or Jungle Run, which have a character that runs all the time, and gameplay that is about quick reflexes and avoiding obstacles. The rare first-person runner is about navigating a 3D-environment and choosing the most efficient route through it, all while maintaining high momentum.
A variety of jumps and slides are useful, to let the player move around in a cool fashion.
However, the important thing to get right in these games is the sense of speed. Notice the slight blurring at the edges of the screenshot above. This is a great way to create a movement effect: while running faster and faster, everything around the edges becomes more fuzzy, pulling your view towards the center.
Another way of accomplishing this is by fading in an "effect tunnel" around the player. This can be a tube with moving lines drawn on it, or particles around the player. The effect is similar to the blurring mentioned above.
Conclusion
There are a lot of unique genres that beg to be developed further. Within them hide unique mechanics and settings that could make new games more interesting. All these genres mentioned are woefully under-represented in today's gaming-space, despite having the potential to be fun and engaging. A skilled developer could easily pick up one of these and create a title that would not have to fight against other titles in an already saturated field.
In past posts in this series, we've focused on the concepts behind the artificial intelligence we've been learning about. In this part, we'll wrap all the implementation into an entirely playable hockey game. You'll learn how to add the missing pieces required to turn this into a game, such as score, power-ups, and a bit of game design.
Final Result
Below is the game that will be implemented using all the elements described in this tutorial.
In order to make a fully playable game, however, all those aspects must be wrapped into a core game mechanic. The most obvious choice would be to implement all the official rules of an official hockey match, but that would require a lot of work and time. Let's take a simpler fantasy approach instead.
All hockey rules will be replaced with a single one: if you are carrying the puck and are touched by an opponent, you freeze and shatter into a million pieces! It will make the game simpler to play and fun for both players: the one carrying the puck and the one trying to recover it.
In order to enhance this mechanic, we'll add a few power-ups. They will help the player to score and make the game a bit more dynamic.
Adding the Ability to Score
Let's begin with the scoring system, responsible for determining who wins or loses. A team scores every time the puck enters the opponent's goal.
The easiest way to implement this is by using two overlapped rectangles:
The green rectangle represents the area occupied by the goal structure (the frame and the net). It works like a solid block, so the puck and the athletes will not be able to move through it; they will bounce back.
The red rectangle represents the "score area". If the puck overlaps this rectangle, it means a team just scored.
The red rectangle is smaller than the green one, and placed in front of it, so if the puck touches the goal on any side but the front, it will bounce back and no score will be added:
Organizing Everything After Someone Scores
After a team scores, all athletes must return to their initial position and the puck must be placed at the rink center again. After this process, the match can continue.
Moving Athletes To Their Initial Position
As explained in the first part of this series, all athletes have an AI state called prepareForMatch that will move them towards the initial position, and cause them to smoothly come to a stop there.
When the puck overlaps one of the "score areas", any currently active AI state of all athlete is removed and prepareForMatch is pushed into the brain. Wherever the athletes are, they will return to their initial position after a few seconds:
Moving the Camera Towards the Rink Center
Since the camera always follows the puck, if it is directly teleported to the rink center after someone scores, the current view will abruptly change, which would be ugly and confusing.
A better way to do this is to move the puck smoothly towards the rink center; since the camera follows the puck, this will gracefully slide the view from the goal to the rink center.
This can be achieved by changing the puck's velocity vector after it hits any goal area. The new velocity vector must "push" the puck towards the rink center, so it can be calculated as:
var c :Vector3D = getRinkCenter();
var p :Vector3D = puck.position;
var v :Vector3D = c - p;
v = normalize(v) * 100;
puck.velocity = v;
By subtracting the rink center's position from the puck's current position, it is possible to calculate a vector that points directly towards the rink center.
After normalizing this vector, it can be scaled by any value, like 100, which controls how fast the puck moves towards the rink center.
Below is an image with a representation of the new velocity vector:
This vector V is used as the puck's velocity vector, so the puck will move towards the rink center as intended.
To prevent any weird behavior while the puck is moving towards the rink center, such as an interaction with an athlete, the puck is deactivated during the process. As a consequence, it stops interacting with athletes and is marked as invisible. The player will not see the puck moving, but the camera will still follow it.
In order to decide whether the puck is already in position, the distance between it and the rink center is calculated during the movement. If it is less than 10, for instance, the puck is close enough to be directly placed at the rink center and reactivated so that the match can continue.
Adding Power-Ups
The idea behind power-ups is to help the player achieve the game's primary objective, which is to score by carrying the puck to the opponent's goal.
For the sake of scope, our game will have only two power-ups: Ghost Help and Fear The Puck. The former adds three additional athletes to the player's team for some time, while the latter makes the opponents flee the puck for a few seconds.
Power-ups are added to both teams when anyone scores.
Implementing the "Ghost Help" Power-up
Since all athletes added by the Ghost Help power-up are temporary, the Athlete class must be modified to allow an athlete to be marked as a "ghost". If an athlete is a ghost, it will remove itself from the game after a few seconds.
Below is the Athlete class, highlighting only the additions made to accommodate the ghost functionality:
public class Athlete
{
// (...)
private var mGhost :Boolean; // tells if the athlete is a ghost (a powerup that adds new athletes to help steal the puck).
private var mGhostCounter :Number; // counts the time a ghost will remain active
public function Athlete(thePosX :Number, thePosY :Number, theTotalMass :Number) {
// (...)
mGhost = false;
mGhostCounter = 0;
// (...)
}
public function setGhost(theStatus :Boolean, theDuration :Number) :void {
mGhost = theStatus;
mGhostCounter = theDuration;
}
public function amIAGhost() :Boolean {
return mGhost;
}
public function update() :void {
// (...)
// Update powerup counters and stuff
updatePowerups();
// (...)
}
public function updatePowerups() :void {
// TODO.
}
}
The property mGhost is a boolean that tells if the athlete is a ghost or not, while mGhostCounter contains the amount of seconds the athlete should wait before removing himself from the game.
Those two properties are used by the updatePowerups() method:
private function updatePowerups():void {
// If the athlete is a ghost, it has a counter that controls
// when it must be removed.
if (amIAGhost()) {
mGhostCounter -= time_elapsed;
if (mGhostCounter <= 2) {
// Make athlete flicker when it is about to be removed.
flicker(0.5);
}
if (mGhostCounter <= 0) {
// Time to leave this world! (again)
kill();
}
}
}
The updatePowerups() method, called within the athlete's update() routine, will handle all power-up processing in the athlete. Right now all it does is check whether the current athlete is a ghost or not. If it is, then the mGhostCounter property is decremented by the amount of time elapsed since the last update.
When the value of mGhostCounter reaches zero, it means that the temporary athlete has been active for long enough, so it must remove itself from the game. To make the player aware of that, the athlete will start flickering its last two seconds before disappearing.
Finally, it is time to implement the process of adding the temporary athletes when the power-up is activated. That is performed in the powerupGhostHelp() method, available in the main game logic:
private function powerupGhostHelp() :void {
var aAthlete :Athlete;
for (var i:int = 0; i < 3; i++) {
// Add the new athlete to the list of athletes
aAthlete = addAthlete(RINK_WIDTH / 2, RINK_HEIGHT - 100);
// Mark the athlete as a ghost which will be removed after 10 seconds.
aAthlete.setGhost(true, 10);
}
}
This method iterates over a loop that corresponds to the amount of temporary athletes being added. Each new athlete is added to the bottom of the rink and marked as a ghost.
As previously described, ghost athletes will remove themselves from the game.
Implementing the "Fear The Puck" Power-Up
The Fear The Puck power-up makes all opponents flee the puck for a few seconds.
Just like the Ghost Help power-up, the Athlete class must be modified to accommodate that functionality:
public class Athlete
{
// (...)
private var mFearCounter :Number; // counts the time the athlete should evade from puck (when fear powerup is active).
public function Athlete(thePosX :Number, thePosY :Number, theTotalMass :Number) {
// (...)
mFearCounter = 0;
// (...)
}
public function fearPuck(theDuration: Number = 2) :void {
mFearCounter = theDuration;
}
// Returns true if the mFearCounter has a value and the athlete
// is not idle or preparing for a match.
private function shouldIEvadeFromPuck() :Boolean {
return mFearCounter > 0 && mBrain.getCurrentState() != idle && mBrain.getCurrentState() != prepareForMatch;
}
private function updatePowerups():void {
if(mFearCounter > 0) {
mFearCounter -= elapsed_time;
}
// (...)
}
public function update() :void {
// (...)
// Update powerup counters and stuff
updatePowerups();
// If the athlete is an AI-controlled opponent
if (amIAnAiControlledOpponent()) {
// Check if "fear of the puck" power-up is active.
// If that's true, evade from puck.
if(shouldIEvadeFromPuck()) {
evadeFromPuck();
}
}
// (...)
}
public function evadeFromPuck() :void {
// TODO
}
}
First the updatePowerups() method is changed to decrement the mFearCounter property, which contains the amount of time the athlete should avoid the puck. The mFearCounter property is changed every time the method fearPuck() is called.
In the Athlete's update() method, a test is added to check if the power-up should take place. If the athlete is an opponent controlled by the AI (amIAnAiControlledOpponent() returns true) and the athlete should evade the puck (shouldIEvadeFromPuck() returns true as well), the evadeFromPuck() method is invoked.
The evadeFromPuck() method uses the evade behavior, which makes an entity avoid any object and its trajectory altogether:
All the evadeFromPuck() method does is to add an evade force to the current athlete's steering force. It makes him evade the puck without ignoring the already added steering forces, such as the one created by the currently active AI state.
In order to be evadable, the puck must behave like a boid, as all athletes do (more information about that in the first part of the series). As a consequence, a boid property, which contains the puck's current position and velocity, must be added to the Puck class:
class Puck {
// (...)
private var mBoid :Boid;
// (...)
public function update() {
// (...)
mBoid.update();
}
public function getBoid() :Boid {
return mBoid;
}
// (...)
}
Finally, we update the main game logic to make opponents fear the puck when the power-up is activated:
private function powerupFearPuck() :void {
var i :uint,
athletes :Array = rightTeam.members,
size :uint = athletes.length;
for (i = 0; i < size; i++) {
if (athletes[i] != null) {
// Make athlete fear the puck for 3 seconds.
athletes[i].fearPuck(3);
}
}
}
The method iterates over all opponent athletes (the right team, in this case), calling the fearkPuck() method of each one of them. This will trigger the logic that makes the athletes fear the puck during a few seconds, as previously explained.
Freezing and Shattering
The last addition to the game is the freezing and shattering part. It is performed in the main game logic, where a routine checks whether the athletes of the left team are overlapping with the athletes of the right team.
This overlapping check is automatically performed by the Flixel game engine, which invokes a callback every time an overlap is found:
private function athletesOverlapped(theLeftAthlete :Athlete, theRightAthlete :Athlete) :void {
// Does the puck have an owner?
if (mPuck.owner != null) {
// Yes, it does.
if (mPuck.owner == theLeftAthlete) {
//Puck's owner is the left athlete
theLeftAthlete.shatter();
mPuck.setOwner(theRightAthlete);
} else if (mPuck.owner == theRightAthlete) {
//Puck's owner is the right athlete
theRightAthlete.shatter();
mPuck.setOwner(theLeftAthlete);
}
}
}
This callback receives as parameters the athletes of each team that overlapped. A test checks if the puck's owner is not null, which means it is being carried by someone.
In that case, the puck's owner is compared to the athletes that just overlapped. If one of them is carrying the puck (so he is the puck's owner), he is shattered and the puck's ownership passes to the other athlete.
The shatter() method in the Athlete class will mark the athlete as inactive and place it at the bottom of the rink after a few seconds. It will also emit several particles representing ice pieces, but this topic will be covered in another post.
Conclusion
In this tutorial, we implemented a few elements required to turn our hockey prototype into a fully playable game. I intentionally placed the focus on the concepts behind each of those elements, instead of how to actually implement them in game engine X or Y.
The freeze and shatter approach used for the game might sound too fantastical, but it helps keep the project manageable. Sports rules are very specific, and their implementation can be tricky.
By adding a few screens and some HUD elements, you can create your own full hockey game from this demo!
Are you a freelance writer? Are you looking to get more business? If so, our parent company Envato has an exciting opportunity for you.
Envato Studio is an online shopfront for freelance services, with dozens of categories including logo design, photo retouching and icon design. Soon there'll be a new category for "Content & Writing". And that's where you come in.
The
Opportunity
We're looking for people who can offer any of the following services:
Website Content
Copywriting
Blog and Article Writing
Press Releases
Product Descriptions
Proofreading and Editing
Technical Writing
Creative Writing
Resumes and Cover Letters
If you sign up at Envato Studio to offer some of those services, the benefits for you include:
Tapping
in to Envato’s existing community of over 4 million registered users. Every day they are
creating thousands of websites and digital products—and we know they need
content.
Getting in early on a less-crowded marketplace.
Fair
compensation for your skills. You are free to set your own price.
Helping
us shape and grow our content category.
How
Envato Studio Works
Freelancers
can set up profiles and offer a selection of services for a fixed price and scope. Clients can compare the services on offer and pick the one that’s right
for them. When someone orders your service, we provide the tools for you to work
together and ways to tackle more work beyond the scope of the original project—our most successful freelancers have lots of repeat clients.
This
all means that you spend your time doing the work that you love, rather than
chasing clients for work. You can find more info in the FAQ.
Next
Steps
Check
out the Envato Studio website, and if you are
keen to be a part of our community, simply leave your details on this form. If you meet our criteria, we'll be in contact soon!
Previously, we looked at rare and underused modern game genres, like parkour games and Lemmings-likes. This time, we'll take a look at some classic genres that were once popular, but are now rare to see.
Each of these genres offers a niche rich with possibilities for developers to find and create something interesting and engaging. This is true especially for indie developers, who are not bound by massive budgets and the accompanying need to reach a certain audience size.
Flight Sims
Microsoft Flight Simulator
Take on Helicopters
Pilotwings 64
Most people would think of Microsoft Flight Simulator as the classic flight sim, with its fairly linear gameplay. But
there are a lot more ways to create a game centred around
operating an aircraft, with a secondary focus on doing things in the
game world.
Classic flight sims simulated huge
worlds, but today creating sufficient level of detail proves a challenge. However, a huge world is not strictly necessary; Pilotwings 64 simulates an island to fly hang-gliders and small
aircraft around, and that was in 1996! Imagine what you could do with
today's technology focused on a small scale. Employing procedural
generation would also be a possibility.
There are many ways to create
interesting challenges within these confines. Stunt flying is a good
task. Transporting cargo can be easily integrated with
management aspects. Search and rescue could be exciting if well executed,
as could disaster evacuation.
There are already aspects of flight sim control in many action games, such as Battlefield 2, Tie Fighter and Armed Assault, where
control of an aircraft is complex and not easy to master. In Battlefield
2 (and the later titles), being a helicopter pilot and shuttling people
to the front lines is a valid and fun playstyle, which has its own
challenges.
Action Flight Sims
Tom Clancy's HAWX
Sky Rogue
War Thunder
Sky Rogue and HAWX are the latest examples of this genre in its classic form, with the AAA-game HAWX 2 already five years old. War Thunder is a rare free-to-play take on aerial battles.
Sky Rogue shows beautifully how the genre can be explored. You can choose between several markedly different planes, and scenarios include fighting against stationary targets, other aircraft, and massive airships, the latter of which often include sub-targets, such as turrets.
Weapons also offer a lot of ways to make your gameplay feel good. In addition to simple weapons, you could also include multi-stage missiles, lasers, or any kind of contraption you can think of.
Multiplayer games in this genre can be very engaging, especially locally.
These games don't have to feature aircraft, necessarily. Submarine games could utilize the same control scheme, and offer a different environment. Space fighting games are possible too. Anything goes!
Space Tactics
Homeworld
Star Wolves
I try to avoid the term "real time strategy" for space games, because the prominent examples is Star Trek Armada. In that game, space is treated as a flat world, and thus very similar to regular, earth-bound RTS games.
The rare space tactics game makes use of the third dimension for manoeuvring—and suddenly a lot of new options and choices open
up.
Battles involving three dimensions take on different characteristics, as you have to think about being attacked from above or below. This
works well with directional shields, as seen in Flotilla and Star Trek Online.
Another fun element is that of the mothership, or the "aircraft carrier in space". Your mothership is your mobile base, and can take a lot more damage than a regular ship. It can also launch and repair fighters, the latter being very resource-intensive during battles.
In Star Wolves tactics often include how to split up your ships. If you send in the mothership first, it can take the brunt of enemy fire while providing cover. If it is damaged and you are attacked from every side, you need to provide cover for it while it retreats, or you will lose your mission.
Rail Shooters
Rambo - The Game
Resident Evil: The Darkside Chronicles
The latest prominent rail-shooter was the disappointing Rambo - The Video Game. The mechanic itself appears in a similar form throughout many games, but works somewhat differently in each. The "on-rails section" concept shows up often and can be combined with many types of action games, like in Metal Gear Solid V: Ground Zeroes.
The genre usually presents you with a static, non-moving view, into which targets move. Once all have been destroyed, the view moves around and switches to a new perspective.
Additional challenges can be incorporated by letting the player target specific hotspots of enemies or shooting thrown projectiles. There is also a lot of potential for environmental triggers, like shooting pipes full of steam. Pick-ups and power-ups can be implemented by getting the player to shoot the items in question.
Theme Park Managers
Theme Park
Rollercoaster Tycoon
Parkitect
It really is a shame that few theme park games exist, because they are a blast.
A theme park manager can be described as similar to a city builder
(which also seem to have become somewhat rare recently). You create
attractions, hire staff to keep your park running, place food stands, and
try to keep your enterprise afloat.
Guests visit your park, and each has unique characteristics and preferences. Some prefer smooth, simple rides, while others only go for white-knuckle thrill rides. They also want food and souvenirs, so you need to place these in strategic locations. Don't forget toilets, or everyone will become unhappy very quickly.
Rollercoaster Tycoon and Theme Park also allow you to design your own rollercoasters and train-tracks. In Zoo Tycoon you create your own animal habitats, and fit them with the right plants and props. There are lots of possibilities to explore, like water parks, dinosaur parks, or period carnivals.
Pinball Games
3-D Ultra Pinball
Momonga - Pinball Adventures
There are more ways of implementing pinball games than a boring, rectangular pinball table. Momonga - Pinball Adventures, which I had the pleasure of working on, is a wonderful example. It is more of an action adventure, where movement through the levels is achieved via pinball flippers. In the environments you can bounce around, activating switches and unlocking new passages, and you must destroy certain elements to continue.
The hero of the game is a Japanese flying squirrel who can roll into a ball, and who interacts with other characters. Variety is also added with flying sections.
Sierra's 3-D Ultra Pinball also has a nice approach, as it took the table concept to extremes. The "table" is not locked to the rectangular dimensions of its real-life counterpart, but stretches to fill the entire screen. Level are set in castles, jungles and amusement Parks, and feature challenges and targets that would not be possible in a physical pinball game.
Another fun way Sierra extended the tables was with special ball statuses: multiball spawned dozens more, radically changing the feel of the game for a few moments. Similar things can be achieved by duplicating balls, or possibly giving them "health", and not having them take damage in certain regions of the level.
Tactical Shooters
Rainbow Six
Takedown: Red Sabre
While many modern first-person shooters try to appear more "tactical", they are mostly still run-and-gun affairs, with occasional cover-sticking.
Unlike other first-person shooters, tactical shooters focus first on planning and movement. Instead of running and gunning into situations, the games
are structured around careful movement. Firefights are deadly and over quickly, and should be approached carefully.
Earlier Rainbow Six titles even including planning phases, where you would plan out, in a 2D map, how each team is supposed to move through the environment. Later titles streamlined that approach and let the players decide directly within the game how to proceed.
In that way it becomes about solving the "puzzle" of the level. How do I clear that room? Throw in a flashbang grenade while I simultaneously order the other team to move in from the other side? Let's give it a try.
The games feature unique characters with strengths in different areas, such as sneaking or accuracy. They can be outfitted with different weapons and other gear, often including camouflage. Most importantly, when they die, they stay dead. Over time you grow attached to your people, and losses actually hurt.
Real-Time Tactics
Commandos
Robin Hood
Desperados
In real-time tactics games you control a handful of people with special skills. This often involves sneaking and staying out of sight.
In Commandos you command a group of operatives during WWII. The Green Beret can climb any wall and distract enemies with noise-makers; the Diver can swim underwater, and also throw knives; other archetypes fill other possible roles.
The gravely underrated Robin Hood offers similar characters: the titular hero can shoot exceptionally well with a bow, while Little John can take out several enemies at once in close combat. Between missions you visit your secret hideout in Sherwood Forest, where you can assign tasks to followers you recruited during your missions, like training skills or crafting ammunition to use during operations.
Having the skills be unique to each character and be meaningfully
different is an important part to the puzzles that the scenarios
present. Level itself can be sprawling affairs (similar to MGS V: Ground
Zeroes' "open world stealth"), allowing the players plenty of approaches.
Conclusion
There are a lot of genres that are ripe for exploration, currently unused and proven by former successes. Utilizing them well could give developers a leg up, especially indies. And even within those genres there are loads of unique angles and variants ripe for exploring.
Whether it's a simple game jam entry or a long-term passion project, your game needs to feel alive in the hands of players. In this tutorial, I'll share ideas for bringing your game to life, and demonstrate what happens when you apply every one of those ideas to a simple game demo.
Check Out the Demo
Click the demo to give it focus, and then use the arrow keys to move, X to shoot, C to jump, and N and P to switch between different iterations of the game.
Introduction
This tutorial will walk
you through the creation of a very basic game, showing the thought process
behind the additions and changes made across 10 iterations to make the
experience come to life.
What exactly do I mean when I talk about bringing your game
to life? This is one of those game design philosophies that varies greatly
across the industry, but I personally define game life as the combination of
control, feedback, variation, and permanence. Game life is not all about
complex AI and deep, character-driven stories. It’s about how the game
responds to your input and how it delivers specific feedback to stimulate your
senses and reflexes.
For this example, I’ve
decided to go with a basic 2D sidescrolling platformer-shooter. If you’re
developing a turn-based RPG, then the specific details aren’t going to
apply to your project. But that’s not the point. The importance of this article
lies in why certain decisions are made, not the technical implementations of each
iteration.
Each iteration of the game corresponds to a specific section
below. You can follow along in the provided game demo by switching between the
different iterations. This will illustrate how a game comes to life over time
through simple, incremental changes.
Iteration 1: Basic Core
Mechanics
Ladies and gentlemen, I present to you our hero: Skull Baby.
Our hero has been locked in an eternal feud against the evil Slug Boogers, an
intergalactic menace determined to take over the known universe. With Skull
Baby’s trusty Booger Buster 5000 and relatively average jumping ability, it’s
up to you to save the galaxy!
With that, we have our incredibly basic and cliché
game idea. Our core mechanics include left and right player movement, left and
right enemy movement, a simple jump, and a semi-automatic gun that shoots a
bullet that travels horizontally. If the bullet collides with the enemy, the
enemy is destroyed. For the sake of this demo, and for testing purposes, the enemy
respawns after being destroyed. We use a basic collision system to keep the
player and enemy enclosed in the playing area, and the enemy begins moving in
the opposite direction after colliding with a wall.
For this example, I won’t be adding a win/loss condition,
player health, or even player/enemy collision. Balancing this kind of game in
that regard would require an entirely separate article. Game balance is a crucial
element of design, but it varies so immensely across genres that it would be a
distraction from the main idea. And remember, you’re not playing a finished game in the
demo, you’re looking at the decision making process of a few select details.
So our game works, but it’s a horribly bland experience. Let’s start bringing this game to life!
Iteration 2: Adding Animation
It’s such an obvious addition, but just look at how much
life is added to the game with a few simple animations.
For the player, I’ve
added animations for idling, running, and jumping. For the enemy, I’ve added a
walk cycle. With names like Skull Baby and Slug Booger, it makes sense to take a
light-hearted approach to animation. Skull Baby bounces and bobs around with a
squishy mid-section, while the Slug Booger creeps along with wiggly antennae and
googly eyes. It’s important to maintain consistency with the tone of your
artwork so that entities in your game world feel as if they belong together.
Here’s where my game design philosophies are slightly
different than others. I prefer to create and polish my artwork as I develop
the basic prototype. Some designers prefer to use “programmer art” for as long
as possible while building the basics of a game. While these animations are not
exactly final, they are very close to what I would use in the final product. I
do this for two important reasons:
First, it allows me to see these animations
repeatedly over an extended period of time due to the all the testing I’ll be
doing. Eventually the flaws of an animation will become more and more obvious,
and I’ll feel more compelled to refine and improve it.
Second, this allows me
to build the game around how it looks rather than trying to draw a sprite to
fit into the confined spaces dictated by the code. It’s easier to change a few
lines of code than it is to redraw a sprite.
Iteration 3: Adding Basic
Sound Effects
I'm using this iteration to prove a point, and not necessarily as an example of what I would do while creating a game. By
implementing incredibly basic (and arguably bad) sound effects this early in
development, the value of good sound effects will become even more apparent in
a later iteration.
I've added three sounds: shooting, jumping, and bullet collision
/ enemy death. By repeating these sounds over the next few iterations, you will
better understand one of the most important yet often overlooked aspects of
game design: variation through randomization.
Much like adding animations, adding sound effects this early
in development gives you enough time to determine whether you like your assets or not.
Many developers add sound effects in the final steps of game development. This
can be dangerous, because the mere inclusion of sound after hours and hours of silent
game testing can artificially inflate your level of satisfaction with the
quality of the assets. Adding sounds early also ensures that your audio
triggers are in place before you add too many layers of complicated code that may
need to be rewritten to get audio working properly.
Iteration 4: Adding Stage
Tiles
Again, this isn’t a terribly important iteration at this
stage of development, but I was tired of looking at the boring black blocks
used to represent the floor and walls.
This is purely a cosmetic alteration of
the game because we’re still using the pre-existing functionality of the black
blocks. These tiles add nothing to the gameplay experience, yet the
game still somehow feels different. Instead of standing directly on top of a
2D block, the perspective has shifted slightly so you can see both the top and
side surface of the block.
The collision code is the same, but now the foundation
is in place to create layers of depth in the future. I’m using this as a way to
prove a concept that I’ll expand on in greater detail in a future iteration:
seemingly small cosmetic changes can greatly influence the feel of a game.
Iteration 5: Verticality and the Introduction of Variation
This is where things start to get interesting. In this
iteration, I’ve added one of the most widely-used platforming mechanics of all
time: the double jump.
Whether it’s available from the start or as an upgrade
you earn over time, the double jump is the perfect example of how a simple
change can help bring a game to life. But how? It’s just a way to make the
player jumper higher and farther, right? How is that anything other than a
simple mechanic? Allow me to explain.
Our basic jump has a fixed height and a fixed speed. Some
platformers allow you to hold down the jump button to extend the jump height.
With our original jump, the player was locked into a decision. Once the button was
pressed, the player no longer had a choice. There was no variation. By adding a
double jump, we've given the player a choice, and introduced variation to
the player’s jumping experience. I’m sure you’ve heard that “variety is the
spice of life”; this is also true for game design.
But you can’t just throw in a ton of choices and call it a
day. We could give our player a jetpack, spring shoes, a portal gun, and the
ability to fly. That would definitely open up the number of choices available,
but most of them would become redundant or meaningless. The choices have to be
useful in multiple situations, and our double jump passes that test. By adding
this basic double jump, we can add verticality to our stages and enemy
encounters without changing the core gameplay in the way that a jetpack would. For
instance, stage design could remain mostly horizontal for a while, and then the
double jump could become required in a section to expand verticality and introduce
variety and life to the experience.
And it’s not just about basic platforming. In fact, the
number of gameplay choices is immense with a simple double jump. The regular
enemy can be avoided with a regular jump. A larger enemy could require a double
jump. Maybe a boss encounter would require a combination of regular and double
jumps to dodge attacks and reach a higher enemy weak point. A room with spikes
on the ceiling could limit the usage of the double jump, while a sequence of
sizeable jumps could limit the usage of the regular jump. Throw in the
strategic ability of using precise double jump timing to dodge multiple enemy
projectiles, and you’ve created hours of gameplay possibilities with one small
and seemingly insignificant mechanic.
This demonstrates how bringing life to a game experience isn’t
about adding an insane level of polish or detail, but can be about using a
small change to create giant, sweeping changes to the core player experience
through variation.
And now that you’re thinking about variation, I want to
bring up one of the greatest tools at your disposal: randomization. This
iteration features a randomized jumping sound, which ensures that the player
isn’t hearing the same sound every time the jump button is pressed. It seems
like a small change, but the next iteration will expand on this idea to show
just how important randomization is when you’re trying to bring a game
experience to life.
Iteration 6: Improving the Feel of Gunplay Through Feedback and Randomization
This iteration features quite a few changes, all designed to
improve the gunplay, which is the main focus of the game. No matter what kind
of game you’re making, you should spend as much time as you possibly can
refining the main way your players interact with it. This iteration adds life
to the game through an improvement on visual feedback, audio feedback, risk vs. reward, and randomization.
Visual Feedback
Our previous iterations featured very
unsatisfying and underwhelming gunplay due to the virtually non-existent bullet
feedback. Pressing the fire button resulted in the creation of a bullet, but
that was it. By creating a simple muzzle flash and increasing the size of the
bullet, we’ve created a much more satisfying experience for the player. A
subtle screen shake is added to emphasize the power of our gun, which now feels
more like a shotgun than a pea shooter. Our bullets are becoming a main
character, which is incredibly important in a game driven by gunplay.
Audio Feedback
The boring, puny gunshot sound from earlier
has been replaced with a thick and meaty explosion that goes well with our new
visual feedback. It’s important to make sure your visuals and audio work well together
to breathe life into your game. In the same way that great audio can enhance
your game, bad audio can detract from the overall experience.
Risk vs. Reward
In a game that’s all about shooting, many
players prefer an auto-fire option. Why is this? Maybe it’s because their fingers
get tired, but I would argue that it’s because most shooting games offer no
risk for firing a weapon.
Hear me out. If the player is not penalized for
firing a weapon in the game, then why even require the player to press the button
at all? There has to be reason to press a button, and there has to be a reason
to not press that button. Variety is all about choices, right? So give the
player a reason to choose to press a button or not, and provide a risk and a
reward for both choices.
In this iteration, I’ve introduced gun recoil that
will propel the player backwards with every shot fired. Fire too quickly, and
you end up flying across the screen. In a stage with pitfalls, spikes, or other
hazards, this recoil mechanic creates interesting scenarios where players are
forced to choose when, where, and how to shoot. Yes, you can reap the rewards
of firing hundreds of bullets at your enemy, but you run the risk of being
killed by something you’re not even firing at.
Try to find ways to introduce this concept in your game, and
you will find that the number of possible gameplay scenarios get multiplied. For example, this recoil mechanic results in the player being
able to jump farther, so long as they are comfortable doing it while traveling
backwards. It’s an interesting layer of depth that can emerge over time,
adding yet more variation to the gameplay experience.
Randomization
This is easily the quickest and simplest way
to breathe life into your game. As with the jumping sounds from an earlier
iteration, the gunshot sound is also randomized. The player will be firing
hundreds of bullets at a time, so it’s incredibly important to make this as
varied as possible. The trajectory of each bullet is also randomized slightly.
We could introduce upgrades over time to make our bullets more accurate, but
this kind of game will not require pinpoint bullet accuracy, so this kind of
randomization works perfectly.
Iteration 7: Enemy Knockback
Fighting the enemies up to this point has been an uneventful
experience. This iteration introduces a form of visual feedback by giving
enemies actual hitpoints and introducing a bit of knockback.
When a bullet
collides with an enemy, the enemy flashes red temporarily and the enemy is
moved in the direction that the bullet was traveling. It now takes five hits to
kill an enemy, creating an actual challenge.
The starting animation frame and an enemy’s maximum movement
speed is randomized to create variation among the enemy force that has now increased
from one Slug Booger to four Slug Boogers. If you have the same sprite on the
screen, and the sprites are all instantiated at the same time, it’s important
to do this to ensure that there’s some differentiation between the entities.
While these changes make enemy encounters a bit more interesting, we still have
a way to go to make the overall experience satisfying.
Iteration 8: Particles!
Remember when we introduced stage tiles, a strictly cosmetic
change that added nothing to the gameplay yet still managed to change the feel
of the game? Well, adding particles is a sure-fire way to turn that idea up to
11.
Dust particles are emitted when the player jumps and when the player lands,
adding a bit of life to the movement of the main character. Fire and a bit of
smoke is emitted from the gun barrel every time a shot is fired, and the
bullets erupt into an array of white particles when colliding with a wall,
floor, or enemy object.
While I was working on this demo, I showed a few teaser GIFs
to some of my friends, and the first response was usually the same. Everyone
commented on the particle effects, proving just how valuable this kind of
visual feedback can be. But it’s not just about being “pretty”; particles can
make a game feel more alive by pushing a player’s imagination further into the
game world.
We all know there’s no dust on the ground in this game, but
the particles can cause you to suspend your disbelief. The same goes for the
gunfire. What was previously just a white sprite now feels more like a projectile
hurled out of a barrel by the combustion of gunpowder. And now, instead of just
disappearing, our bullets can logically disappear from the game world by
breaking up into tiny pieces. The starting and ending positions of our jumps
are now marked by dust. Everything is starting to have a beginning and an end.
Everything is beginning to have a purpose. When these individual objects begin
to live and breathe on their own, that’s when the game as a whole can begin to
feel more alive.
Iteration 9: Enemy Death
and the Value of Permanence
Since things are starting to feel more alive, we should
definitely make them feel more dead.
Defeating an enemy should be a satisfying
moment, since it’s the main point of our little game. In this iteration,
enemies explode into a burst of alien blood particles and body chunks. A white
flash and a heavy screen shake accompanies a squishy explosion sound, and the
body chunks make a squish noise when they collide with the floor.
These body chunks also bring up another important game
design element: permanence. The player can leave a definitive mark on the game
world. It’s like keeping a scrapbook of photos to mark the events of your life—except much more sinister. In a way, it’s proof that you were once alive. This
simple idea can mark areas that you’ve already been to, and it can be a
reminder of the battles you’ve won.
Permanence is incredibly important, and it’s
an idea that’s been around since the beginning of game development. Think back
to the original Super Mario Bros., where you can see which blocks you’ve already
broken. It’s such a simple concept, but it brings your game to life by showing
the lingering effects of your invested time.
Iteration 10: Final Touches
The final iteration introduces a few optional visual touches
and a simple soundtrack. Although I didn’t take the time to compose a song to
fit the visual style of the game, I don’t want to ignore the sheer importance
of audio’s role in bringing a game to life. Whether it’s an actual song or some
kind of ambient environmental noise, the power of audio to breathe life into
your game is immense.
As for the visual additions to this final iteration, I added
a scrolling parallax background and more permanence via shell casings expelled
from the gun. The parallax background doesn’t make logical sense in this
example because all the action takes place on one screen, but you can see that
the added layers of depth help to extend the game’s world further back into
territory that the player will never be able to traverse.
The industry can seem
obsessed with the idea of open world games and being able to reach every
visible area of a game’s map, but I say that it’s actually important to feature
inaccessible areas in a game. Will you ever step foot on every grain of sand in
the known universe in real life? Of course not, and that’s not a bad thing. The
vastness of the universe is an interesting concept, so thinking about the
unreachable areas of game can be just as intriguing.
A game’s life can be extended well beyond any playable,
visible, or audible boundary if you want. The world is at your
fingertips, so take advantage of it!
Conclusion
Compare the game in Iteration 10 to the game in Iteration 1.
These small, simple changes and additions added up to create a much
more satisfying experience. The game in Iteration 1 is boring,
lifeless, and uninteresting. The game in Iteration 10 leaves you wanting more,
and you can actually feel as though a full game is beginning to take
shape.
As I said before, this is just one example of
how you might add life to a game with this kind of gameplay and presentation
style. There are infinitely many ways to make your experience come to
life in the hands of your players, and it’s up to you to master that art.
The next
time you play a game, stop and ask yourself why it feels satisfying. Don’t just
think about how it looks, how it sounds, or how it plays. Think about the
choices you have, the possible permutations of events there are, and the
feedback you’re seeing and hearing as a result of your input. Think about how
that feedback influences your choices, and try to understand why those
decisions were made during development. The best way to learn about game design
is to ask questions that you may never find the answer to.
It’s like searching
for the meaning of life: you will never find the answer, but your knowledge of
the world and of yourself will undoubtedly grow along the way.
If you want the flexibility to learn new skills wherever you are, then take a look at our Tuts+ Courses Android app.
The free app lets you log in to your Tuts+ account and access all your favourite creative and technical video courses on the move.
Our development team created it as part of a recent hack week here at Tuts+, and it's already reached more than 500 downloads and received lots of positive feedback.
We already have a mobile-friendly website, of course, where you can access both our free tutorials and, if you're a subscriber, our in-depth video courses. But the app gives you an easier way of managing your courses, letting you:
log in to your current Tuts+ account
access all your Tuts+ courses
browse through all 450+ courses and bookmark your favourites
access your recently watched courses
view your video courses from the app on the go
To find out more about the app and how it makes your learning easier, and to read reviews from other users, head over to the Google Play page.
This week marks a huge milestone for Tuts+ learning as we celebrate the release of our 500th video course!
From our humble beginnings way back in 2007 we’ve grown to incorporate 10 different creative and technical topics including Code, Web Design, Design & Illustration and Photography. We now house an extensive library of more than 19,000 free tutorials to help you build real life skills, and more than 190 downloadable eBooks.
For those who love the hands on approach to learning, our most popular channel remains our short video courses. We’ve had 111 instructors, to date, from around the world contributing to the collection and taking you through their favourite programs and techniques, step by step.
Together they’ve produced 9213 individual lessons, 77,315 minutes or 53 days of content!
To honor the publication of our 500th video, Creative Vector Hair by Sharon Milne, we’ve made the 18 lessons in this course free for one week only. Which makes this the perfect opportunity for you to develop a new skill, or to experience our video course learning for the first time. For free!
Plus, as a special bonus, we’re also giving away three free files from some of our wonderful Envato Market authors to help you with your future design projects. Get in quick, because this offer is limited and will finish Sunday 29 March.
About the Course
In this course you will learn how to create five different hairstyles from scratch, and then go on to create a series of variations. In total, there are 19 end results to this course. The aim is to arm you with the skill set to be able to render your own hairstyle creations without needing a reference image. This course is ideal for all digital artists, although it's specifically aimed at those with an advanced knowledge of Adobe Illustrator.
Create quick hair styles with the use of a collection of Scatter and Art Brushes. They can be used to create silhouetted hair, black and white, grey scale, monochrome, colored and even realistic styled vector hair!.
This set of brushes, for Adobe Illustrator, includes 10 different media libraries with 168 unique art brushes. Add a hand drawn feel to your clean vector lines. These brushes were created by hand from actual media.
These seamless texture patterns are great for adding a roughened look to text, vector shapes and backgrounds. The non-colored part of each pattern is transparent so you can add your own background color.
Free files are available for download on the course page under the "source files" download button. Files and course are free until Sunday 29 March. If you don't already have a free Tuts+ account you will need to create one to view the course and download the files.
Making good artificial intelligence for computer opponents is difficult. Programming a game like draughts isn't terribly challenging; adding convincing AI, however, might take longer than making the game itself. But what are we doing when we make this AI? Is it important for it to examine every possible move on the board, or can we cheat and just make it move randomly? What does an AI need to do, and (most importantly) how can we ensure that the game is fun?
Good AI vs Fun AI
The term "AI" is a really broad concept, and the type of AI depends on the game. Asymmetric games, such as Space Invaders, Mario, or Tower Defence, allow the player to cut through swathes of enemies effortlessly. Since the "teams" (player vs everything else) are unbalanced, these games tend to use dumb AI. Symmetric games, such as Starcraft, Street Fighter or Civilisation, expect the player to beat opponents on equal footing, and so require more complex AI.
However, games have to be fun, first and foremost. Players enjoy a challenge, not losing repeatedly. In fact, some games such as Checkers have been "solved", meaning it is possible to build an AI which plays an unbeatable game.
When my team and I were working on our computer/board game Infected, we had to make the first level's AI intentionally awful so as not to scare players off. The game AI was initially rather simplistic, and the computer would play hyper aggressively, focusing entirely on high scoring plays with no thought of defence or board presence.
Even though the AI was poor, we found that new players would get crushed and lose interest. We revised the AI several times, although it still proved too much of a challenge for players. Eventually, we simply removed the AI, so the game would just make a random move every time. Although some players still managed to lose, this massively improved player retention, allowing us to reintroduce the "serious" AI at higher levels.
The problem of "too good" AI can be seen in a variety of games: FPS games with bots that have 360 degree vision, or beat-'em-ups against bots with perfect reflexes. Playing against these AIs doesn't actually teach the player to play the game well: it teaches them to "game" the bots, to try to find a flaw in the algorithm which allows easy kills.
This isn't to say that all AI should be poor, but rather that good AI is multi-faceted. It makes mistakes, but tries to avoid falling into the same predictable patterns. Giving the AI the ability to adapt—and, therefore, to provide variance in gameplay—will likely provide much more entertainment for the player than an AI that plays the same perfect game every time.
Making Them Human
After making Infected, we briefly toyed around with a sequel, Infected 2. It was the same premise, but on a larger scale, similar to the classic board game Risk. Because the game was larger, it was important to have drastically improved AI: something which could keep the player entertained over the course of a much longer game, and where multiple AIs could compete against each other.
We plugged in the old AI, and there were several issues with it. The AI was predictable, but that was something that could be improved with a little work. The larger issue was regarding the general attitude of the AI, and how it played.
There were three main problems:
Firstly, playing against the AIs wasn't particularly fun.
Secondly, beating the AI wasn't particularly rewarding.
Thirdly, the AI would "cheat" by deliberately throwing the game.
The game was fun against other players, but not against the AI. Although there was still the same level of challenge, why was there such a massive disparity between player against the AI and playing against another person, if the gameplay was the same?
We then remembered that humans have one thing computers don't: emotions.
Part of playing a game is getting emotional; we love a thrilling victory, we hate a crushing defeat. We love to rub our victories in our friends' faces, and we become petty and vengeful when they betray us. Games are intrinsically linked to our emotions, and it's something that an AI can never experience... but it is something that we developers can emulate.
The Vital Spark
Why wasn't playing the AI fun?
Because the artificial intelligence was so obviously artificial. All the bots played the same way; they all had the same approaches to the game; they were all equally predictable in their movement patterns.
We needed something to make them stand out from each other. So we introduced personalities: reckless, defensive, explorer. The AI would give an artificial weight to certain strategies, and then move in those attack patterns.
Even in a basic form, this was a massive improvement: no longer was every game the same, but it added unpredictability to enemy moves and made it harder to formulate a single "game winning" strategy. If the AIs were randomised when the game started, then the player wouldn't be able to predict how the game would unfold.
Personalities on AI is not a new idea. Civilisation gives personalities to its leaders (Gandhi famously loves to nuke people), Age of Mythology AIs determine how likely they are to use strategies such as turtling or rushing, and Unreal Tournament bots have favourite weapons.
Why Wasn't Beating the AI Rewarding?
The main issue was that the AI played what it viewed as a "best move" every round. It simply assessed the game board, with no regard to diplomacy. If it needed to attack you it would. If you attacked it back, it simply didn't care. It viewed the game as a mathematical puzzle to be solved, rather than a game against complex human players. Playing against our artificial intelligence resulted in an artificial game.
Our solution came from an Amiga game from 1989 called Nuclear War. In Nuclear War, you fought against various world leaders and tried to nuke their country from existence. Whoever managed to survive would win. Although simplistic, it was surprisingly fun watching your enemies get caught in personal vendettas and throw warheads at each other.
This "friends and enemies" system used a very simple metric: happiness. Each world leader had a variety of facial expressions which made it easy to judge their attitude towards you. Unsurprisingly, nuking people tended to make them unhappy very quickly. In addition, your enemies wouldn't just get upset with you, but with each other. This meant that a single wayward missile could escalate into a sustained fight to the death.
Once again, this system has been used in many games, including Civilisation. An enemy nation with a high level of "happiness" is more likely to ally with you and send you gifts, whereas an enemy that hates you might invest a lot of resources into crushing your cities.
By adding a rudimentary happiness meter into our game, we allowed friendships and rivalries to brew. A game is more exciting when you develop a nemesis, or when teams and alliances form. Suddenly, the game became personal, and actions felt like they had weight. We also found that a visible happiness meter was important, otherwise the player wouldn't understand what was happening. A simple happy face icon immediately conveys the idea that enemies can get "upset", and watching the face change upon taking certain actions made it clear what consequences these actions were having.
The prisoner's dilemma is a well known game theory concept, and many programmers have spent time trying to build the ultimate bot to compete in the iterated prisoner's dilemma. Curiously, the winning strategy for many years was also the simplest: known as tit-for-tat, it simply copied the opponent's move.
How Would the AI Cheat?
The problem in Infected 2 was often that the AI was simply looking at the short term perspective. The AI aims to maximise its score every turn: if this meant making an overall poor move, then it would do it anyway.
The easiest way to imagine it is this scenario:
Alice, Bob and Carol are playing war.
Alice has 100 soldiers. Bob has 75 soldiers. Carol has 150.
Neither Alice nor Bob can beat Carol.
However, Alice and Bob combined can beat Carol.
The problem was that the AI would do whatever would score it the most points. In the above scenario, that meant Alice would attack Bob: in the short term, an excellent move, but in the long term, disastrous. Not only is Alice making a move which dooms herself, she is condemning Bob to certain defeat as well. Bob is understandably upset.
This sort of situation is difficult to avoid, as seeing the bigger picture requires a complex reasoning beyond most simple AI. We tried to ensure "fairness" by making players less likely to be attacked if they were losing, or if they had been attacked recently. While not every game can apply a simple solution, its important to realise that players hate being attacked for no apparent reason.
While Infected 2 never made it past the alpha stage, it taught us some valuable lessons. Most importantly, that it's not enough to just play against enemy bots: you want to be involved in the game, develop rivalries, and crush all those who stand against you.
AI Done Right
Many years ago, a game was published that seemed leaps and bounds ahead of the competition. Although a multiplayer game by design, the bots were good enough that it could be enjoyed single player. And, although by today's standards it is poor, this game—Unreal Tournament—had AI which blew other games out the water.
We can look at an in-game screenshot to see some of what went into making a bot:
Skill was the main factor in determing bot behaviour: novice bots were slow, had to stand still to shoot, and were slow to turn around, while the higher level bots were faster, could dodge, had a bigger field of view and could use advanced weapon combo techniques.
Bots could then be futher modified with accuracy, alertness, camping, and strafing levels. "Personality" would be determined by combat style and favourite weapon, determining whether the bot liked to get up close and personal, or try and snipe from a distance. Bots would also taunt the player and seek revenge. Each of the 32 bots could be individually customised, meaning you could have 32 distinct personalities. Certain bots, such as Loque, became notorious amongst players.
All of these factors helped create bots which felt more human. While the game would still be good without this sophistication, it adds an extra, almost imperceptible layer of fun.
Conclusion
At the end of the day, you need to ask: what do you want from your AI? Are the enemies going to mindlessly rush the player and walk head-first into pits, or are you trying to develop something more, something that provides a more personal level of interaction with the player? Whatever you decide, remember three key points:
If bots make mistakes, then they feel more human, and less like a "pack of cards".
If they deliberately make plays based on individual personality (or emotion, like
revenge), then unpredictable and exciting gameplay is more likely to emerge.
If bots try to play cleverly, rather than short-sightedly, they are more likely to make
the game fair to our eyes.
In this video tutorial, I'll show you four easy ways to reduce your game file size and increase playback performance by using optimized audio. Following these steps may reduce the overall sonic data footprint by 50% or more! Best of all, you don't need to spend a penny on special editing software.
Sound files: All sound files in this tutorial are provided for illustrative use only, and remain the property of the instructor. They may not be redistributed or used in any other projects, either free or commercial, without explicit permission from Jordan Reed.
Once a relatively obscure sub-genre that appealed to a hardcore fan base, roguelikes have been enjoying a recent renaissance. Let’s take a closer look at their central design elements, and see how different games are making use of the same underlying architecture.
So What is a Roguelike?
Until very recently, the term "roguelike" narrowly referred to games that were likeRogue, a 1980 Unix dungeon crawler that became the archetype of the genre it named. "Roguelike" was used to indicate that a game incorporated the primary mechanical features that Rogue had. The aesthetic of Rogue (that of an adventurer attempting to reach the bottom of a dungeon) was widely copied as well.
Since Rogue and its direct descendants were hack-and-slash RPGs, the unique design elements of the games tended to be conflated with aspects of the RPG genre they otherwise belonged to. This was formalized with something called the Berlin Interpretation, which outlined the defining aspects of a roguelike. These include some of the most important features:
Procedurally generated environments
Permanent death
The randomization of item identities
The Berlin Interpretation also lists turn-based combat, grid-based environments, and killing monsters as key features, which are more closely aligned with the specific kind of RPG roguelikes originated as. As the structure of roguelike has expanded into genres beyond action RPGs, those RPG design elements have tended to be dropped or ignored.
The primary three features (procedural generation, permadeath, and randomization of items) have found use in a variety of different types of game, and are strongly associated with the term "roguelike". So, technically speaking, "roguelike" refers more to a shared set of mechanics
and design principles than a genre in and of itself (though
I'll continue to use 'genre' as a shorthand).
As a result, games from a huge variety of genres have made use of the roguelike design framework. It's a set of design elements that can be used equally
well in action platforming (like Spelunky), exploration and base-building (like Dwarf Fortress), tower defense (like Dungeon of the Endless), top-down strategy (like FTL), stealth (like Invisible, Inc), first person shooters (like Eldritch), and traditional dungeon-delving RPGs (like Dungeons of Dredmor).
Procedurally Generated Levels
Procedural generation indicates that elements of the game, especially the level design, are not hardcoded in advance by the designer, but instead are generated randomly from a template each game. As a result, it means the player cannot memorize beneficial locations or places to avoid, and so must play each game blind.
Though the specifics of the map are randomized, the general form of the map stay the same each game. So, in a traditional dungeon crawler like Cardinal Quest, the map is always rooms and corridors, and similarly in the sci-fi FTL, a sector map is comprised of beacons linked by lanes. It is the specific arrangement of these links and nodes that is randomized each game.
Procedural generation has two main benefits to the overall design:
First, since the field of play is different every time, it increases replayability as the map is always unknown. This frees the player from having to memorize a level’s specific challenges in and of themselves (as one might do in a challenging platformer like a Megaman game or Super Meat Boy), so the player must attempt to adapt to the pattern underlying the challenges. While you can’t ever know for sure what’s behind the next door, you can develop a sense of what might be behind it.
Second, it ensures that every playthrough is an exploration of a new space. Since the map is never the same, the player will always be plunging into the unknown, whether it is their first game or their fiftieth.
Exactly how random the levels should be requires substantial testing and care from the designer. If the placement is too random, the difficulty between games may vary too drastically, with some being very easy and others being unwinnable. Depending on the complexity of the game, it can be an intensive process to ensure all possible random maps are fun and able to be completed. The best designed roguelikes make the player feel punished when they make mistakes, not when the game itself makes mistakes or generates a map that's unfairly difficult.
The difficulty in perfecting the maps increases the larger the levels are. A famously complex example is Dwarf Fortress, where a vast and detailed three dimensional world
with biomes, minerals, creatures, civilizations and entire histories is
generated each game. (Replicating just a fraction of these with graphics
instead of ASCII was part of the inspiration for Minecraft.) Most games take a more limited approach by segmenting the map by level or area, so the generated areas are relatively smaller and thus easier to fully test.
Permanent Death
"Permadeath" generally means that the player must restart from the beginning upon their death, and that they can not reload a save to reattempt a failed challenge. It’s this feature that often intimidates players unfamiliar with the genre. Kicking the player back to the beginning after every death can seem unduly punishing, and contrary to the design principle of interactivity.
But a game designed with permadeath in mind is built
differently than one that assumes the use of saves or lives. A typical
game will be built with portions of the game the player might see only
once (like easy initial levels), and balanced to have difficulty spikes
intended to require several attempts. Conversely, a roguelike is built
with repetition in mind, and so while death is still a failure condition, restarting is much less onerous than it might be in another game.
While permanent death can seem jarring at first, it does bring some design benefits. It essentially redefines the failure state of the game; rather than expecting the player to play through the game once, while re-attempting challenges they fail at, instead the player is expected to play through the entire game without dying once (a tall order!). So "death" isn't a temporary setback, but rather part of the cycle of play. Since the vast majority of attempts will result in death, it's less "You Lose", and more an invitation to "Try Again", while hopefully applying what you learned.
Most importantly, permanent death gives visceral meaning to each and every playthrough. Without the safety net of reloading or lives, the action of a roguelike can become heart pounding as the player's position becomes precarious. The stakes that permadeath create is why it's the most iconic design element of a roguelike. Every decision made is given critical meaning, because, unlike in most games, the player can't simply have another go if they make a mistake. This can certainly be stressful and frustrating, but it also makes success feel much more meaningful and hard-won; few games can match the feeling of accomplishment that roguelikes offer.
Though the cliché environment for a roguelike is heroes delving into a dungeon, the gameplay of surviving on limited resources against the unknown lends itself very well to a horror setting. Survival is a natural partner for the roguelike architecture of real consequences and a world you can't memorize, and dying is scarier when it carries more weight. Don't Starve is a good example that fosters an atmosphere of horror with its roguelike mechanics acting in concert with its ominous Edward Gorey inspired art direction. The Binding of Isaac's dark thematic elements are similarly bolstered by the underlying roguelike mechanical architecture.
Discovery and Limited Retention
This is a feature that has the most substantial variation in use. In a traditional roguelike, the only thing retained between games is the skill of the player. In NetHack, death means not just losing all acquired equipment, weapons, and levels, and losing the current random dungeon layout, but even also losing knowledge of any discoveries made during play. For example, a bubbly potion might heal the player, but in the next game it might contain acid instead. The Sega Genesis classic ToeJam & Earl uses power-ups in randomized presents in a similar manner.
Modern games don't tend to strictly implement this (especially since not all games have item attributes that could be sensibly randomized), but do tend to adhere to the spirit of the design. The intent is that the only thing the player keeps from game to game is their own increasing skill and knowledge of the system. Always needing to identify potions in NetHack or Angband is just an expression of that design. This ensures every playthrough is meaningful and unique, which procedural generation and permadeath also support.
There's been substantial experimentation with this aspect of roguelikes. A popular variation is to include unlockable game elements, which can help the player track their progression. In Spelunky there are multiple
unlockable skins for the main character, but they confer no advantages besides different aesthetics. In FTL, though, there are 28 ships to pilot, each with different strengths and abilities, but only one is available to start with, and making incremental progress or achieving certain goals gradually unlocks the others. This would seem to violate the principle, as earlier runs have a demonstrable impact on latter ones (by making new things available), but it's really just a way of slowly unveiling the full feature set as the player becomes more engrossed. NetHack has 13 character classes available from the start, but it wouldn't dramatically change the game if some needed to be "unlocked" in some manner, since you can't play more than one per game anyway.
Some games may include more meaningful progression. In Risk of Rain, in addition to unlockable character classes, achieving certain goals unlocks the ability for items and powerups to appear in future playthroughs, and making them available can become necessary for continued progress. Systems like this may blur the line of not retaining any advantages, but their effect is generally small, and the main advantage the player gains is their own increased skill. This can make the challenges of a roguelike more palatable, because instead of one very difficult goal to achieve (beating the game in a single playthrough without dying), it gives the players some incremental challenges to beat as proof of their progress. Though this may dilute the premise slightly, it's a concession that gives players a tangible sense of progress they can visualize, since their increasing skill level is more subtle.
Some games may even ignore this entirely, however. Rogue Legacy features a progression system that allows you to purchase incremental skills and benefits (like higher HP) for each subsequent attempt. So while the game is otherwise very much a roguelike action platformer with procedurally generated levels and permanent death, the game requires repeated attempts to slowly build in-game advantages, in addition to building player skill. The upcoming title Temple of Yog takes a similar approach, wherein the player's success in the roguelike combat portion is rewarded with incremental advantages to the player's village and to subsequent runs in the dungeon. These games further stretch the definition of roguelike (Rogue Legacy identifies itself as a "Rogue-Lite" for this reason), but they still maintain the core familiar gameplay of repeated meaningful and unique attempts with gradual progression.
In Conclusion
The defining aspects of roguelikes are instructive not for their exact features, but the style of play they give rise to. The roguelike architecture brings out the best in games which require repeated and iterative attempts at success. They raise the stakes for such play through permanent death, and ensure each attempt is a new experience by randomizing the layout and having no (or limited) carryover of advantages from previous games. It's why such a diverse range of games can make good roguelikes, from puzzlers to platformers. And since roguelike mechanics can be rich additions to games of any type or genre, why not try making one yourself?
List of Games Mentioned
This is by no means an exhaustive list of roguelikes, but these are the games mentioned as examples above:
For a limited time only, and with thanks to our friends at PayPal, if you're a student you can grab a full year of learning on Tuts+ for just $45!
That's a full year of access to all 500+ video courses, 19,000+ ad free written tutorials and over 190 eBooks to download. Plus you'll also be able to claim special offers from our subscriber benefits partners.
How Do I Claim This Offer?
This offer is limited to the first 1111 students only paying via PayPal, and can be purchased here until 30 April or sold out.
Learning to write graphics shaders is learning to leverage the power of the GPU, with its thousands of cores all running in parallel. It's a kind of programming that requires a different mindset, but unlocking its potential is worth the initial trouble.
Virtually every modern graphics simulation you see is powered in some way by code written for the GPU, from the realistic lighting effects in cutting edge AAA games to 2D post-processing effects and fluid simulations.
The Aim of This Guide
Shader programming sometimes comes off as an enigmatic black magic and is often misunderstood. There are lots of code samples out there that show you how to create incredible effects, but offer little or no explanation. This guide aims to bridge that gap. I'll focus more on the basics of writing and understanding shader code, so you can easily tweak, combine, or write your own from scratch!
This is a general guide, so what you learn here will apply to anything that can run shaders.
So What is a Shader?
A shader is simply a program that runs in the graphics pipeline and tells the computer how to render each pixel. These programs are called shaders because they're often used to control lighting and shading effects, but there's no reason they can't handle other special effects.
Shaders are written in a special shading language. Don't worry, you don't have to go out and learn a completely new language; we will be using GLSL (OpenGL Shading Language) which is a C-like language. (There are a bunch of shading languages out there for different platforms, but since they're all adapted to run on the GPU, they're all very similar)
Let's Jump In!
We'll use ShaderToy for this tutorial. This lets you start programming shaders right in your browser, without the hassle of setting anything up! (It uses WebGL for rendering, so you'll need a browser that can support that.) Creating an account is optional, but handy for saving your code.
Note: ShaderToy is in beta at the time of writing this article. Some small UI/syntax details may be slightly different.
Upon clicking New Shader, you should see something like this:
The little black arrow at the bottom is what you click to compile your code.
What's Happening?
I'm about to explain how shaders work in one sentence. Are you ready? Here goes!
A shader's sole purpose is to return four numbers: r, g, b,and a.
That's all it ever does or can do. The function you see in front of you runs for every single pixel on screen. It returns those four color values, and that becomes the color of thie pixel. This is what's called a Pixel Shader(sometimes referred to as a Fragment Shader).
With that in mind, let's try turning our screen a solid red. The rgba (red, green, blue, and "alpha", which defines the transparency) values go from 0 to 1, so all we need to do is return r,g,b,a = 1,0,0,1. ShaderToy expects the final pixel color to be stored in fragColor.
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
fragColor = vec4(1.0,0.0,0.0,1.0);
}
Congratulations! This is your very first working shader!
Challenge: Can you change it to a solid grey color?
vec4 is just a data type, so we could have declared our color as a variable, like so:
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
vec4 solidRed = vec4(1.0,0.0,0.0,1.0);
fragColor = solidRed;
}
This isn't very exciting, though. We have the power to run code on hundreds of thousands of pixels in parallel and we're setting them all to the same color.
Let's try to render a gradient across the screen. Well, we can't do much without knowing a few things about the pixel we're affecting, such as its location on screen...
Shader Inputs
The pixel shader passes a few variables for you to use. The most useful one to us is fragCoord, which holds the pixel's x and y (and z, if you're working in 3D) coordinates. Let's try turning all the pixels on the left half of the screen black, and all those on the right half red:
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
vec2 xy = fragCoord.xy; //We obtain our coordinates for the current pixel
vec4 solidRed = vec4(0,0.0,0.0,1.0);//This is actually black right now
if(xy.x > 300.0){//Arbitrary number, we don't know how big our screen is!
solidRed.r = 1.0;//Set its red component to 1.0
}
fragColor = solidRed;
}
Note: For any vec4, you can access its components via obj.x, obj.y, obj.z and obj.worviaobj.r, obj.g, obj.b, obj.a. They're equivalent; it's just a convenient way of naming them to make your code more readable, so that when others see obj.r, they understand that obj represents a color.
Do you see a problem with the code above? Try clicking on the go fullscreen button in the bottom right of your preview window.
The proportion of the screen that is red will differ depending on the size of the screen. To ensure that exactly half of the screen is red, we need to know how big our screen is. Screen size is not a built in variable like pixel location was, because it's usually up to you, the programmer who built the app, to set that. In this case, it's the ShaderToy developers who set the screen size.
If something is not a built in variable, you can send that information from the CPU (your main program) to the GPU (your shader). ShaderToy handles that for us. You can see all the variables being passed to the shader in the Shader Inputs tab. Variables passed in this way from CPU to GPU are called uniform in GLSL.
Let's tweak our code above to correctly obtain the center of the screen. We'll need to use the shader input iResolution:
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
vec2 xy = fragCoord.xy; //We obtain our coordinates for the current pixel
xy.x = xy.x / iResolution.x; //We divide the coordinates by the screen size
xy.y = xy.y / iResolution.y;
// Now x is 0 for the leftmost pixel, and 1 for the rightmost pixel
vec4 solidRed = vec4(0,0.0,0.0,1.0); //This is actually black right now
if(xy.x > 0.5){
solidRed.r = 1.0; //Set its red component to 1.0
}
fragColor = solidRed;
}
If you try enlarging the preview window this time, the colors should still perfectly split the screen in half.
From a Split to a Gradient
Turning this into a gradient should be pretty easy. Our color values go from 0 to 1, and our coordinates now go from 0 to 1 as well.
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
vec2 xy = fragCoord.xy; //We obtain our coordinates for the current pixel
xy.x = xy.x / iResolution.x; //We divide the coordinates by the screen size
xy.y = xy.y / iResolution.y;
// Now x is 0 for the leftmost pixel, and 1 for the rightmost pixel
vec4 solidRed = vec4(0,0.0,0.0,1.0); //This is actually black right now
solidRed.r = xy.x; //Set its red component to the normalized x value
fragColor = solidRed;
}
And voila!
Challenge: Can you turn this into a vertical gradient? What about diagonal? What about a gradient with more than one color?
If you play around with this enough, you can tell that the top left corner has coordinates (0,1), not(0,0). This is important to keep in mind.
Drawing Images
Playing around with colors is fun, but if we want to do something impressive, our shader has to be able to take input from an image and alter it. This way we can make a shader that affects our entire game screen (like an underwater-fluid effect or color correction) or affect only certain objects in certain ways based on the inputs (like a realistic lighting system).
If we were programming on a normal platform, we would need to send our image (or texture) to the GPU as a uniform, the same way you would have sent the screen resolution. ShaderToy takes care of that for us. There are four input channels at the bottom:
Click on iChannel0 and select any texture (image) you like.
Once that's done, you now have an image that's being passed to your shader. There's one problem, however: there's noDrawImage() function. Remember, the only thing the pixel shader can ever do is change the color of each pixel.
So if we can only return a color, how do we draw our texture on screen? We need to somehow map the current pixel our shader is on, to the corresponding pixel on the texture:
We can do this by using the function texture2D(texture,coordinates), which takes a texture and an (x, y) coordinate pair as inputs, and returns the color of the texture at those coordinates as a vec4.
You can match the coordinates to the screen in any way you like. You could draw the entire texture on a quarter of the screen (by skipping pixels, effectively scaling it down) or just draw a portion of the texture.
For our purposes, we just want to see the image, so we'll match the pixels 1:1:
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
vec2 xy = fragCoord.xy / iResolution.xy;//Condensing this into one line
xy.y = 1.0 - xy.y;
vec4 texColor = texture2D(iChannel0,xy);//Get the pixel at xy from iChannel0
fragColor = texColor;//Set the screen pixel to that color
}
With that, we've got our first image!
Now that you're correctly pulling data from a texture, you can manipulate it however you like! You can stretch it and scale it, or play around with its colors.
Let's try modifying this with a gradient, similar to what we did above:
texColor.b = xy.x;
Congratulations, you've just made your first post-processing effect!
Challenge: Can you write a shader that will turn an image black and white?
Note that even though it's a static image, what you're seeing in front of you is happening in real time. You can see this for yourself by replacing the static image with a video: click on the iChannel0 input again and select one of the videos.
Adding Some Movement
So far all of our effects have been static. We can do a lot more interesting things by making use of the inputs that ShaderToy gives us. iGlobalTimeis a constantly increasing variable; we can use it as a seed to make periodic effects. Let's try playing around with colors a bit:
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
vec2 xy = fragCoord.xy / iResolution.xy; // Condensing this into one line
xy.y = 1.0-xy.y; // Flipping the y
vec4 texColor = texture2D(iChannel0,xy); // Get the pixel at xy from iChannel0
texColor.r *= abs(sin(iGlobalTime));
texColor.g *= abs(cos(iGlobalTime));
texColor.b *= abs(sin(iGlobalTime) * cos(iGlobalTime));
fragColor = texColor; // Set the screen pixel to that color
}
There are sine and cosine functions built into GLSL, as well as a lot of other useful functions, like getting the length of a vector or the distance between two vectors. Colors aren't supposed to be negative, so we make sure we get the absolute value by using the abs function.
Challenge: Can you make a shader that changes an image back and forth from black and white to full color?
A Note on Debugging Shaders
While you might be used to stepping through your code and printing out the values of everything to see what's going on, that's not really possible when writing shaders. You might find some debugging tools specific to your platform, but in general your best bet is to set the value you're testing to something graphical you can see instead.
Conclusion
These are only the basics of working with shaders, but getting comfortable with these fundamentals will allow you to do so much more. Browse through the effects on ShaderToy and see if you can understand or replicate some of them!
One thing I didn't mention in this tutorial is Vertex Shaders. They're still written in the same language, except they run on each vertex instead of each pixel, and they return a position as well as a color. Vertex Shaders are usually responsible for projecting a 3D scene onto the screen (something that's built into most graphics pipelines). Pixel shaders are responsible for many of the advanced effects we see, so that's why they are our focus.
Final challenge: Can you write a shader that removes the green screen in the videos on ShaderToy and adds another video as a background to the first?
That's all for this guide! I'd greatly appreciate your feedback and questions. If there's anything specific you want to learn more about, please leave a comment. Future guides could include topics like the basics of lighting systems, or how to make a fluid simulation, or setting up shaders for a specific platform.
We wanted to make you aware of some changes to our Privacy Policy. We’re committed to ensuring that our Privacy Policy clearly sets out how we manage your identifying information (“personal information”) while also reflecting some important aspects of Australian privacy (called “data protection” in Europe) and SPAM laws.
The new policy goes into effect on May 1, so this is a quick heads up. You can read the new Privacy Policy here: envato.com/privacy.
So what’s going to change?
We’ve re-written the Privacy Policy to make it easier to understand and have a consistent policy across all of Envato. You’ll see a clearer approach to explaining what type of information we collect, how we use that information, and how you can take control of the information we have.
Overall, it’s pretty much business as usual, but please take the time to read and understand how your personal information is used and how to best manage it!
Every indie developer or team has asked themselves how best to manage the development process. Is it obligatory to use detailed
documentation, such as the legendary game design document (GDD)? What are the most common mistakes, and how can they be avoided?
For those who have searched for answers to these questions, I want to share our team's experience of creating our GDD.
Why You Need a GDD
Good Documentation is a Must
Many game designers abstain from cultivating design documents and organizing ideas. I can't imagine how these developers get through those times that they are hampered by malfunctioning code, placeholder art, and clashing mechanics, all while trying to remember why it was that they first subjected yourself to making a game in the first place.
Having a well thought out game design document can act as your crutch in these times. It will let you see the awesome ideas and concepts that kept you up all night long when you first started on your game, and, perhaps more importantly, which ones need to be cut from the game to make your life easier, or reworked to make your efforts worthwhile.
A GDD Aids Game Design and Development
A game design document acts as a nexus
and hub to connect and list every aspect of a game. It consists of
written descriptions, images, graphs, charts and lists of information
pertinent to each segment of development, and is often organized by
what features will be in the game, and clearly lays out how they will
all fit together.
Creating a GDD will aid your team's designer in understanding
what the essence of the game is and the planned scope of its
overarching world and gameplay. Plus, having all the game elements in one
well-organized document will help the designer easily convey their
vision to the rest of the team, while also helping to pinpoint weaknesses or missing components that the game may
require.
The GDD should serve as your master checklist. It will be
the document you toss up in the air in celebration upon completing
all its sections and finishing your game.
A GDD Helps in Other Areas, Too
Since a GDD is full of descriptions, it
is an ideal resource for all PR and marketing fronts, with concepts that convey the game's aesthetic and appeal already written up and ready to copy and paste.
Prospective employees' skills can be
quickly assessed as qualified or not by looking at their credentials
alongside their positions' corresponding sections in the
document.
If fundraising is in the cards for your team, it will be
crucial to have a well put together GDD for investors to look over
and determine the risks of your development, as well as your ability to deliver on your promises.
A GDD Keeps Everyone on the Same Page
Creating and adhering to a game design document is like planting a seed and watching it grow into a tree over the course of development. You have your initial preparation, cultivation, and ultimately the gruesome and backbreaking toil of the harvest.
A common mistake is not handing all your team members the proper gardening tools to make your game a reality. The GDD will help make sure everyone is working together, so that you don't find your programmer and artist cutting off the branch they are standing on.
Common Mistakes
Trying to Describe Everything at Once
It is not necessary to list every
feature and mechanic in detail in the first draft. This is impossible when working on a complex game with a small
team. Outlining the major nodes of gameplay and core elements will
help give you perspective on what needs to get done, but you should expect to fill them in one by one, over time.
Not Setting Deadlines
Setting game goals with deadlines may
seem off-putting to some developers. Deadlines are a part of the boring 9-to-5 lifestyle, so many people have a natural aversion to them.
However, setting deadlines is how you
ensure that your game will get made and not sit forever unfinished in
a folder on your desktop. These types of goals are milestones on
the road to progress, and passing them one by one is a clear
indication that you are doing something right. Each is a cause for
celebration.
Deadlines are a basic component of scheduling that helps
you monitor the performance of your team and yourself. It aids
in decision making that is rooted in reality, and eventually builds up
a momentum and ethic that is healthy for the team as a whole and the
individuals within it.
Assuming Everyone Knows What to Add
There is room in the GDD for basic descriptions that
cover gameplay, storylines, and major coding tasks. As
development progresses, you add more details to these sections. While creating and testing the game, you should add or update specific technical details every time
a feature is implemented or changed. This way, you'll never have a build with
elements that you can't trace back to the GDD, creating missing
links of ideas, code or art. It can also be helpful to add
information about the difficulty of implementing certain tasks, and
whether they have been fully integrated into the game or may
require further revision.
Throughout this process, your initial
concepts should be trickling down into ever more detailed
descriptions of each facet your features contain. This helps make
concrete milestones that are easy to navigate and backtrack to see
where they originated and where they need to go.
As the GDD continues
to grow and become more finalized it is still important to keep it up to
date. This eliminates situations where team members do something
without being able to justify why they spent time doing them, which
is crucial come crunch time.
Printing the GDD
Personally, I have an unexplained primal fear of drowning in a heap of printed documentation. This would become a real nightmare if I had to keep all old versions of our GDD for every team member.
Why should we torture ourselves like this in the age of digital technology? There are plenty of free online services like Google Docs or Trello that let you save all changes and see all your team's comments in real time.
How to Write an Effective GDD
Write It in Stages
When starting the GDD, it is normal to get wrapped up in concepts. Backgrounds, introductions, and key descriptions help to flesh out the game and give it shape. As you begin to test and implement features, these concepts should become more refined, specified and detailed. Maintaining proper organization will become more and more critical as your GDD gains weight and density.
Start in the concept phase, where you brainstorm your ideas and get them all down on paper. This should be exciting! It will also serve as a roadmap so you don't lose track of your goals and vision along the way. When the appeal of certain game elements lose their lustre or lead you into a ditch, it may be time to rework your initial concept to make sure you reach a satisfying finish line.
Towards the middle of development, once you have a gung-ho team on board, discussions and game builds will help sculpt and organize the document into an easy to use and hefty guide for everyone. There's still room for experimenting with new concepts and ideas at this point, but they should be kept in check with some of your initial documentation.
The home stretch of development is where your game design document will save you hours of frustration and heartache. As you close in on release your GDD should slowly start turning into a stone tablet, with features and mechanics set in more permanent game builds all held together by art that was surely crafted over multiple iterations to match the document's specifications. The document should help keep all the team's wheels on the ground, with a good line of sight on realistic expectations on delivering the game.
It is not necessary to have an absolutely complete GDD before starting development. But the GDD must be complete for the next 10 days or two weeks beyond your team's current work—and the relevant parts of the document must be as detailed as possible.
Allow Changes During Your Game's Development
Parts of the GDD will have to be changed and modified throughout the entire development process, sometimes even in the final days before release. It can start to resemble a disaster zone if the content is not trimmed properly. If you are afraid of deleting text that is outdated, cut and paste it into an addendum or separate document. This will leave the main body of the GDD relevant to the current state of development, without all the distractions of previous iterations.
Don't ever stop team members submitting new ideas. Idea creation is one of the most rewarding parts of development, and should be encouraged at all times. Your team members should head into development knowing that many of these concepts will be cut and never make it into the game, but this shouldn't stop them from dreaming! No one knows what ideas will produce the best results at first, so generating new and innovative ideas should be a staple of your discussions and celebrated accordingly.
Put Just One Person in Control of It
Supervision of the GDD must be performed only by one team member. They will identify the key ideas that must be focused on, and cut the less important ideas.
Encouraging active feedback is important, then, because other team members do not have the chance to add their ideas to the document directly.
Most development issues are comprised of a hard outer shell of miscommunication and a soft interior of not knowing how to compensate and correct them. These barriers can be eliminated with vigilant maintenance of the GDD and clear, concise documentation, and this can best be achieved if one person takes on that responsibility.
Focus on Readability
Be consistent with font styles and using uniform headers and indentations, punctuation, and formatting. Creating a legend or key to explain what specific colored highlights mean can go a long way toward reducing confusion and cutting down on the time it takes to convey the stages of different features' implementation.
Keep the Language Clear
The simpler and clearer you keep the language in the GDD, the better your team will understand it.
It's important to keep the writing clear and concise, and your team should actively give you feedback about the presentation and clarity of the GDD. A back-and-forth dynamic will result in a more cohesive development experience, with overarching benefits including a defined art style, fewer communication errors, and less stressful documentation and office work.
But most importantly, the GDD should be a reflection of your team culture, created in whatever format you find works best and is most appealing to you and those you work with.
Use Visual Aids
No one should ever be able to say that they haven't understood something, or done something correctly, due to a lack of reference material in the GDD.
Visual materials and references play a key role in the process of conveying ideas. Some difficult concepts can be explained in less time with visual aids like graphs and concept art. This will help ensure every team member understands the information that is conveyed to them, which in return will help them to complete development tasks faster.
Put Some Passion Into It
You should not restrict yourself to dry text. (If you do, you'll be waiting a long time for everyone to get engaged and understand the main ideas!) Try to describe the players' emotions and the experiences that the game might cultivate.
Keeping a GDD may sound technical, but you shouldn't be afraid to tear your heart out and throw it at the document. Let your emotion and passion bleed into it. Imagine how you want to make the player feel, and write those aspirations down alongside the descriptions of your features. This helps to cultivate a collective consciousness in your team about what your game is trying to convey to the player—and, let's face it, feelings should have enthusiasm behind them if you want them to be understood by anyone else.
Use It to Keep People on Track
Set the priorities of tasks and features, document their deadlines, and control their execution. You can't develop absolutely all the ideas which your team and your mind will propose, so (after you've cut some of them), you need to set their priorities and at least approximate a schedule for their implementation.
A well-groomed GDD makes for an excellent, prioritized list of tasks that need to be completed by your team. Not all the features in a GDD will make it into the final game. With this in mind, you must decide which features take precedence over others, and you should schedule them for implementation and testing before those others.
Think hard about what is critical for your game, and what is possible given your team's skill level, and use that information to guide your production.
A solid GDD can also help ease new team members into the project, and get them just as excited about it as you are.
Since a fully outlined GDD may result in what seems like an excessively daunting game to make, it is good to remember that more than one person will be fleshing out its specifics. Assigning your team members tasks in the GDD will help it to become more robust while keeping everyone on the same page. Anyone can jump in to the document and see what has been completed, what tasks lay before them and the rest of the team, and why they are working on their current task.
Continue Having Design Discussions
Writing something in a shared GDD shouldn't minimize or eliminate discussion with the team, it should serve to increase team discussion and improve your communication dynamics. It's important that everyone clearly understands how you (and the other team members) imagine each feature of the game.
Cutting ideas can be difficult and unnerving, but it is a process innate to creating games. Making sure that open, free discussion is a part of development will help ease the inherent tensions here, without dissuading members from being creative.
Play the Game In Your Mind
I found many good ideas virtually playing the game in my mind, both before and during the game's creation. Of course, this doesn't give any guarantee that those ideas will take roots in the game during development and testing but, especially in the early stages, it's a good method of brainstorming.
Set Realistic Goals
While it is good to foster an air of excitement within a team, it is equally important to keep your game goals embedded in reality. Mechanics and complex enemy and level behaviors always look great on paper, but reality has a way of corroding the grandeur of certain game elements, and this should be expected.
Consequences of updates and changes are almost impossible to foresee ahead of time in some situations, so just remember it is your job to try and limit the amount of remodelling that needs to be done when changes arise. If you make it common practice to play through new ideas in your mind before putting them down on paper, you stand a greater chance of keeping development goals rooted in realistic expectations.
Make Use of Free Online Tools
Our team is multinational. We live around the world, in different time-zones, and this makes it impossible to use print versions of documents for everyone, and difficult to have real-time conversations. Using tools such as Skype (for conversations), Google Drive (for sharing files), Google Docs (for collaborating on documents, and sharing the GDD), and FlockDraw (for digital drawings) can really help with explanations and discussions.
Conclusion
If you find yourself on the fence about
whether maintaining a GDD is necessary for your game's
production, you should take a good, hard look at how you envision development.
There are almost certainly times where real life and full time jobs
will get in the way of game making, or your implementation of
features and mechanics simply does not work out.
On the stormy seas
of game development, a healthy GDD can serve as a sturdy and solid
vessel, and even a lifeboat at times. It is a detailed journal of
your struggles and triumphs, a collection of thoughts and ideas for
you to fall back on during hard times. You might find that improving
the quality of the GDD trickles down into the
rest of development as well, raising the bar across the board for
your team. It should serve as a sturdy hub to facilitate team
discussion and generate new, even greater ideas. At the same time, it
can keep these concepts in realistic check.
The benefits of this type
of efficiency may seem small when looked at individually, but over
the long course of development, it builds up a wonderful kind of
momentum. Ultimately, this type of document should propel, compel, and
inspire you and your team to finish what you started. It should show
you that your game has a plan that can be realized.
And after you
have finished your game, your GDD will
stand as a testament to all of your hard work and efforts, the behind-the-scenes of an elaborate experience to be enjoyed by all.
Mark is a seventeen-year-old guy; he gets up every morning in a hurry to get to school. He eats breakfast standing, drinking a quick coffee, then he grabs his backpack, house keys, and smartphone and runs to catch the bus.
When the bus arrives, Mark is one of the first to get on, and he always tries to find a place at the back, away from the doors and from the morning’s noise. There, among the people close to him, he does what all teenagers of this world do in the morning: check messages on WhatsApp, read a few posts on Facebook, put two or three stars on tweets of the girl that he likes, check out friends' photos on Instagram, and quickly scroll through some Tumblr posts.
Mark is absent-mindedly going through his morning routine, when suddenly he gets a Facebook notification on his smartphone: Lucas has defeated the Fanged Megabunny that threatened the city of Grayport.
Without thinking twice, Mark taps on the notification and immediately starts to play Dungeons and Rabbits with his friend Lucas.
How Social Games Work
Here we have seen the functioning of virality in a social game—a game based on the possibility of interaction between players through social networks.
These social games have a very particular structure and they are relatively new, so I will explain briefly key definitions relating to this type of game.
Retention indicates how many players remain attached to the title over a certain period of time. It usually indicates how much the game is liked, and how much success it is having.
Monetization indicates how many players spend money in the game.
Virality is the ability of the game to spread and to attract other players, using social network-based mechanics such as invitations or requests for help.
Virality is perhaps the most overlooked of these three elements, but I consider it the most important—even if some people dismiss it as a type of spam, something unethical to avoid. Let’s find out why it is the key to success for a social game.
What is Paid User Acquisition?
Usually, to attract the attention of players for a "traditional" title (such as a boxed console game), we use advertising, on TV, in magazines, or elsewhere.
With social games, we can use a similar system, buying ad space on social networks. This is called "paid user acquisition", because you are essentially attempting to buy users. Each social network has different tariffs depending on the target chosen; age, interests, gender, and nationality determine an estimated cost to advertise.
To give you an example: in order to bring a new American player to your game on Facebook, you have to spend about $2.00. To bring a new Indonesian player to your game, you'll spend, instead, about $0.20.
Why the difference in price? The cost is estimated based on the probability of monetization. An American player is, on average, more likely to spend money in your game than an Indonesian player. And therefore it costs more to target the American market, because there are a lot of companies that will try to acquire these users, so you will have to outbid them.
Why You Should Avoid Paid User Acquisition Via Social Ads
If you do a few calculations, you'll notice that the cost of hosting a large number of users in your game (for example: a million players) can really add up. And if you are not sure that your game will be enjoyed (and therefore that players will spend money), it can be a huge gamble to invest much money in user acquisition.
In addition, you'll have to be very good at selecting your target audience, because if you target users in the wrong audience, you’re essentially throwing away money. (If I create a football game and advertise to players who are basketball fans, I risk those users opening the game, seeing what it is, and immediately closing it.) And to become good at targeting requires either relying on an expert in the field (which costs a lot of money), or gaining experience through trial and error (which probably costs even more).
What's the solution, then?
Why Virality is So Important
The solution lies in virality. If each user that you have acquired is able to attract other users to the game, what you get is user acquisition for a much lower cost than ad-based paid user acquisition.
We can then give a new definition to virality: the ability to reduce the cost of user acquisition. Seen from this point of view, virality no longer seems like something to be underestimated...
Open Graph Stories
I learned all this myself while working on a roleplaying game for Facebook. Unfortunately the game was closed a few months ago and I can not share the link. I will not go into much detail about why the project was closed; I refer you to my previous articles to understand how difficult it is to try to make video games seriously in Italy.
But I will tell you how I discovered the importance of virality.
After keeping the game in closed beta for almost a year, we decided to officially launch it worldwide. Very soon after, we came across the problem of user acquisition, and we started to think about what mechanics to insert to push users to contact their friends.
Each feature had two flaws: first, it required the user to confirm his action to send requests (for example: the call for help when your character runs out of energy); second, it ended up in the Facebook Notification Center, hidden among a thousand reports of comments, groups, events, tags, pokes, and so on.
The percentage of virality was very low: we paid to acquire 1,000 users, and these users only attracted another 100 users from their posts. We had a virality of 0.1: perhaps the worst metric the world has ever seen!
(To calculate virality, the formula is VUsers / BUsers, where VUsers is the number of users who enter the game via a request from a friend, and BUsers is the number of users acquired via ads.)
Then Facebook invented Open Graph Stories, which are, perhaps, the most powerful feature for the games on the social network that has ever been introduced.
Here's an example of an Open Graph Story as it appears on Facebook:
As you can see, it looks in every way like a post by a user. And it will appear in the news feed of the user’s friends—the most visible place of all. And, most importantly, it will be published automatically.
How? Simple: when you create a game that relies on Facebook technology (this includes iOS and Android games, if you use the Facebook API), you can use an admin panel to define Stories that you want to publish, composed of a title, image, description, and link.
At this point you can just connect a Story to an action in the game, and you're done! Each time a player performs that action, a Story will be published on their wall.
What Open Graph Stories Did For Us
After implementing Open Graph Stories, the virality of our game improved a lot; we paid to acquire 1,000 users and this time they brought in 700 new users—the virality increased from 0.1 to 0.7!
Clearly this was just the beginning. We knew we had to improve that result: a really good virality is 1.0 or greater. However, with little effort, we had increased the weak point of the game in one shot, thanks to this one feature.
Improving the virality of your game by iterating on the Open Graph Stories is simple: you can do tests on images or messages published, trying to choose the most attractive or those that are more engaging. During our tests, for example, we discovered that one image in particular attracts more attention than an alternative.
We discovered this through an A/B test. In an A/B test, players are divided into two groups (the A group and the B group), and each group is given a slightly different version of the game. After a couple of days, we check the analytics to understand which of the two versions (if either) performs better.
In our case, we gave the groups two different images: one had a dark mood (a fighting scene, with blood and shadows) and the other had a light mood (a reward scene, with a treasure and a close-up on a heroine). One or other of the images was published in an Open Graph Story every time a player completed the first dungeon.
After a couple of days, the analytics showed that only 31% of friends of players from the A group had clicked on the image, but 58% of friends of players from the B group had clicked on the image. So, we discovered that our potential players preferred a positive mood to a dark mood (and this was quite a surprise, as the project was a roleplaying game).
Conclusion
In short, Open Graph Stories are a really powerful tool that no developer of Facebook games should underestimate. If you need more details about how you can use Open Graph, check the official documentation here: Open Graph Stories.
Now excuse me, but checking Facebook I discovered that the Black Farbunny attacked the empire of Melniboné, and I have to go!
Envato Bundles has just launched the massive Indie Font Bundle. It features over 70 handcrafted fonts from 36 independent authors. It's valued at over $1,300, but you can grab it today for just $29! That's a saving of over 97%. Hurry, because this offer is strictly limited and only on sale until the 18th of May.
A Few of Our Favorite Fonts
Againts
Inspired by ink, tints and brush strokes, Againts is a naturally messy font. With alternating glyphs in some characters and extra ligature, it's easily manipulated to suit your design project.
Optotypo
Optotypo was inspired by the eye charts used in ophthalmology to determine eyesight capacity. It features almost 400 glyphs including symbols, ligatures and alternative glyphs, and it also contains the open type Latin pro character set.
Wonderwall
Wonderwall was born from handcrafted typography and transparent watercolor paint. The result is a set of irregularly beautiful characters that harmonize together perfectly. Use the different ligatures to create something truly unique.
Falco
Falco is a clean, vintage, sans serif typeface. It has four styles: Black, Black inline, Black outline, and Black inline negative. This font loves to stand out in a crowd, so it looks great on headlines, in your T-shirt design, or overlaid on posters.
These are just a few of the 70+ fonts on offer. So don't miss out on your chance to create an epic font library for just $29.
Post-match mini-achievements are little trophies that are awarded after each match in a multiplayer game. They are similar in spirit to the awards such as "Double Kill" and "First Blood" awards that games like Unreal Tournament announce during a match.
Once a match is over, a screen displays what mini-achievements the player (or all players) have won. The Worm series has the most fun way of presenting them:
Here are some examples of the awards Worms gives out:
Most Useless: awarded to the character doing the least things during a match.
Most Boring: awarded to the character using only basic weapons.
Doctor Dolittle Award: awarded to the character using the most animal-based weaponry.
Most Entertaining Team: awarded to the team doing the most insane things during a match.
Sadly, only few games use mini-achievements. Besides the Worms games (which only included this feature for a few games themselves), the newer Call Of Duty and Battlefield shooters offer a few, but concentrate more on the awards the players earned individually (in contrast to Worms' team awards), and tally stats like "most knife kills".
What Can Mini-Achievements Do?
Mini-achievements can add humour, but they can be more than just fun little gags...
They Can Keep Players From Disconnecting
Suppose the awards are only given once a match is over. If you want to see them, and get potential rewards such as unlocks or XP, you have to finish the game and not irritate other players by quitting early. The overall quality of the match thus improves.
They Can Surprise the Player and Inspire Stories
"Remember when Anne's Worm got the "Longest distance flung by explosion" award? I didn't even know that existed!"
This works especially well with fun and unique challenges. If there are a lot of these, it might take some time to encounter all of them, and players can still be surprised.
(I still haven't figured out what the cockroach award is about. I'd speculate it's about surviving the most explosions or attacks.)
They Can Tie In to XP Progression
Getting a mini-achievement is an efficient way to give the player an XP bonus, if your game has such a system. Getting an XP reward for a certain unique action (like "threw most grenades in a match") is much more fun than having to rely on farming XP with ordinary actions, like winning rounds or defeating opponents.
They Can Be Tracked, and so Foster Competition
If tracked over all matches, mini-achievements can function similarly to high scores. You could potentially see who on your friends list has the most triple-kills.
They Can Keep the Player Motivated
Team Fortress 2 informs you, when you die, if you've beaten your own record in one of the many statistics it tracks, like staying alive for a long time, or dealing out damage. This can pick up your spirits after getting sniped or stabbed.
Post-match mini-achievements could also work this way, by reminding the player that, although they may have lost the match, they excelled in one or two categories, and will get rewarded accordingly.
They Can Count Towards Regular Achievements
While mini-achievements are distinct from regular achievements, they can be turned into some. "Unlock every post-match trophy at least once" provides a fun challenge. Other things like "Get 20 First-Blood-Trophies" do too.
Conclusion
Mini-achievements are gravely underused, despite being a lot of fun for players and relatively straightforward to implement. Including them could give your game a unique touch, and provide a lot of benefits in terms of gameplay and fun.
References
Preview Image: Worms Elite trophy (not itself a mini-achievement!) from Worms Wikia.
Until 31 May you'll receive a free yearly subscription to Tuts+ when you purchase a hosting plan from Siteground.
Starting from just $3.95 per month, Siteground offers three plans to get you on the way to hosting bliss.
The StartUp
The StartUp Plan gives you all the essential hosting features you need to accommodate a "just getting started" website or an existing average-size blog, personal, or business website. From $3.95 per month.
GrowBig
If you need more resources and premium features in addition to the essential features then the GrowBig Plan may be for you. This plan is designed to accommodate either a single more heavily-trafficked website or multiple average-size websites. From $7.95 per month.
GoGeek
If you have a really heavily-visited or resource-intensive website then the GoGeek plan may be suitable. The GoGeek Plan offers a completely different and more geeky server infrastructure with more powerful machines and fewer users. From $14.95 per month.
Your Free Year on Tuts+
Your free year on Tuts+ gives you access to all 19,000+ written tutorials ad-free, over 500 premium video courses, and 190 downloadable ebooks on a range of topics including web design, code, design & illustration and photography. With new content added weekly, you'll always have the latest lessons right at your fingertips.
Hurry don't miss out on this fantastic opportunity. Start something new today.
JavaFX is a cross platform GUI toolkit for Java, and is the successor to the Java Swing libraries. In this tutorial, we will explore the features of JavaFX that make it easy to use to get started programming games in Java.
If you already develop applications with Java, you probably don't need to download anything at all: JavaFX has been included with the standard JDK (Java Development Kit) bundle since JDK version 7u6 (August 2012). If you haven't updated your Java installation in a while, head to the Java download website for the latest version.
Basic Framework Classes
Creating a JavaFX program begins with the Application class, from which all JavaFX applications are extended. Your main class should call the launch() method, which will then call the init() method and then the start() method, wait for the application to finish, and then call the stop() method. Of these methods, only the start() method is abstract and must be overridden.
The Stage class is the top level JavaFX container. When an Application is launched, an initial Stage is created and passed to the Application's start method. Stages control basic window properties such as title, icon, visibility, resizability, fullscreen mode, and decorations; the latter is configured using StageStyle. Additional Stages may be constructed as necessary. After a Stage is configured and the content is added, the show() method is called.
Knowing all this, we can write a minimal example that launches a window in JavaFX:
import javafx.application.Application;
import javafx.stage.Stage;
public class Example1 extends Application
{
public static void main(String[] args)
{
launch(args);
}
public void start(Stage theStage)
{
theStage.setTitle("Hello, World!");
theStage.show();
}
}
Content in JavaFX (such as text, images, and UI controls) is organized using a tree-like data structure known as a scene graph, which groups and arranges the elements of a graphical scene.
A general element of a scene graph in JavaFX is called a Node. Every Node in a tree has a single "parent" node, with the exception of a special Node designated as the "root". A Group is a Node which can have many "child" Node elements. Graphical transformations (translation, rotation, and scale) and effects applied to a Group also apply to its children. Nodes can be styled using JavaFX Cascading Style Sheets (CSS), quite similar to the CSS used to format HTML documents.
The Scene class contains all content for a scene graph, and requires a root Node to be set (in practice, this is often a Group). You can set the size of a Scene specifically; otherwise, the size of a Scene will be automatically calculated based on its content. A Scene object must be passed to the Stage (by the setScene() method) in order to be displayed.
Rendering Graphics
Rendering graphics is particularly important to game programmers! In JavaFX, the Canvas object is an image on which we can draw text, shapes, and images, using its associated GraphicsContext object. (For those developers familiar with the Java Swing toolkit, this is similar to the Graphics object passed to the paint() method in the JFrame class.)
The GraphicsContext object contains a wealth of powerful customization abilities. To choose colors for drawing text and shapes, you can set the fill (interior) and stroke (border) colors, which are Paint objects: these can be a single solid Color, a user-defined gradient (either LinearGradient or RadialGradient), or even an ImagePattern. You can also apply one or more Effect style objects, such as Lighting, Shadow, or GaussianBlur, and change fonts from the default by using the Font class.
The Image class makes it easy to load images from a variety of formats from files and draw them via the GraphicsContext class. It's easy to construct procedurally generated images by using the WritableImage class together with the PixelReader and PixelWriter classes.
Using these classes, we can write a much more worthy "Hello, World"-style example as follows. For brevity, we'll just include the start() method here (we'll skip the import statements and main() method); however, complete working source code can be found in the GitHub repo that accompanies this tutorial.
public void start(Stage theStage)
{
theStage.setTitle( "Canvas Example" );
Group root = new Group();
Scene theScene = new Scene( root );
theStage.setScene( theScene );
Canvas canvas = new Canvas( 400, 200 );
root.getChildren().add( canvas );
GraphicsContext gc = canvas.getGraphicsContext2D();
gc.setFill( Color.RED );
gc.setStroke( Color.BLACK );
gc.setLineWidth(2);
Font theFont = Font.font( "Times New Roman", FontWeight.BOLD, 48 );
gc.setFont( theFont );
gc.fillText( "Hello, World!", 60, 50 );
gc.strokeText( "Hello, World!", 60, 50 );
Image earth = new Image( "earth.png" );
gc.drawImage( earth, 180, 100 );
theStage.show();
}
The Game Loop
Next, we need to make our programs dynamic, meaning that the game state changes over time. We'll implement a game loop: an infinite loop that updates the game objects and renders the scene to the screen, ideally at a rate of 60 times per second.
The easiest way to accomplish this in JavaFX is using the AnimationTimer class, where a method (named handle()) may be written that will be called at a rate of 60 times per second, or as close to that rate as is possible. (This class does not have to be used solely for animation purposes; it is capable of far more.)
Using the AnimationTimer class is a bit tricky: since it is an abstract class, it cannot be created directly—the class must be extended before an instance can be created. However, for our simple examples, we will extend the class by writing an anonymous inner class. This inner class must define the abstract method handle(), which will be passed a single argument: the current system time in nanoseconds. After defining the inner class, we immediately invoke the start() method, which begins the loop. (The loop can be stopped by calling the stop() method.)
With these classes, we can modify our "Hello, World" example, creating an animation consisting of the Earth orbiting around the Sun against a starry background image.
public void start(Stage theStage)
{
theStage.setTitle( "Timeline Example" );
Group root = new Group();
Scene theScene = new Scene( root );
theStage.setScene( theScene );
Canvas canvas = new Canvas( 512, 512 );
root.getChildren().add( canvas );
GraphicsContext gc = canvas.getGraphicsContext2D();
Image earth = new Image( "earth.png" );
Image sun = new Image( "sun.png" );
Image space = new Image( "space.png" );
final long startNanoTime = System.nanoTime();
new AnimationTimer()
{
public void handle(long currentNanoTime)
{
double t = (currentNanoTime - startNanoTime) / 1000000000.0;
double x = 232 + 128 * Math.cos(t);
double y = 232 + 128 * Math.sin(t);
// background image clears canvas
gc.drawImage( space, 0, 0 );
gc.drawImage( earth, x, y );
gc.drawImage( sun, 196, 196 );
}
}.start();
theStage.show();
}
There are alternative ways to implement a game loop in JavaFX. A slightly longer (but more flexible) approach involves the Timeline class, which is an animation sequence consisting of a set of KeyFrame objects. To create a game loop, the Timeline should be set to repeat indefinitely, and only a single KeyFrame is required, with its Duration set to 0.016 seconds (to attain 60 cycles per second). This implementation can be found in the Example3T.java file in the GitHub repo.
Frame-Based Animation
Another commonly needed game programming component is frame-based animation: displaying a sequence of images in rapid succession to create the illusion of movement.
Assuming that all animations loop and all frames display for the same number of seconds, a basic implementation could be as simple as follows:
public class AnimatedImage
{
public Image[] frames;
public double duration;
public Image getFrame(double time)
{
int index = (int)((time % (frames.length * duration)) / duration);
return frames[index];
}
}
To integrate this class into the previous example, we could create an animated UFO, initializing the object using the code:
AnimatedImage ufo = new AnimatedImage();
Image[] imageArray = new Image[6];
for (int i = 0; i < 6; i++)
imageArray[i] = new Image( "ufo_" + i + ".png" );
ufo.frames = imageArray;
ufo.duration = 0.100;
...and, within the AnimationTimer, adding the single line of code:
gc.drawImage( ufo.getFrame(t), 450, 25 );
...at the appropriate spot. For a complete working code example, see the file Example3AI.java in the GitHub repo.
Handling User Input
Detecting and processing user input in JavaFX is straightforward. User actions that can be detected by the system, such as key presses and mouse clicks, are called events. In JavaFX, these actions automatically cause the generation of objects (such as KeyEvent and MouseEvent) that store the associated data (such as the actual key pressed or the location of the mouse pointer). Any JavaFX class which implements the EventTarget class, such as a Scene, can "listen" for events and handle them; in the examples that follow, we'll show how to set up a Scene to process various events.
Glancing through the documentation for the Scene class, there are many methods that listen for handling different types of input from different sources. For instance, the method setOnKeyPressed() can assign an EventHandler that will activate when a key is pressed, the method setOnMouseClicked() can assign an EventHandler that activates when a mouse button is pressed, and so on. The EventHandler class serves one purpose: to encapsulate a method (called handle()) that is called when the corresponding event occurs.
When creating an EventHandler, you must specify the type of Event that it handles: you can declare an EventHandler<KeyEvent> or an EventHandler<MouseEvent>, for example. Also, EventHandlers are often created as anonymous inner classes, as they are typically only used once (when they are passed as an argument to one of the methods listed above).
Handling Keyboard Events
User input is often processed within the main game loop, and thus a record must be kept of which keys are currently active. One way to accomplish this is by creating an ArrayList of String objects. When a key is initially pressed, we add the String representation of the KeyEvent's KeyCode to the list; when the key is released, we remove it from the list.
In the example below, the canvas contains two images of arrow keys; whenever a key is pressed, the corresponding image becomes green.
The source code is contained in the file Example4K.java in the GitHub repo.
public void start(Stage theStage)
{
theStage.setTitle( "Keyboard Example" );
Group root = new Group();
Scene theScene = new Scene( root );
theStage.setScene( theScene );
Canvas canvas = new Canvas( 512 - 64, 256 );
root.getChildren().add( canvas );
ArrayList<String> input = new ArrayList<String>();
theScene.setOnKeyPressed(
new EventHandler<KeyEvent>()
{
public void handle(KeyEvent e)
{
String code = e.getCode().toString();
// only add once... prevent duplicates
if ( !input.contains(code) )
input.add( code );
}
});
theScene.setOnKeyReleased(
new EventHandler<KeyEvent>()
{
public void handle(KeyEvent e)
{
String code = e.getCode().toString();
input.remove( code );
}
});
GraphicsContext gc = canvas.getGraphicsContext2D();
Image left = new Image( "left.png" );
Image leftG = new Image( "leftG.png" );
Image right = new Image( "right.png" );
Image rightG = new Image( "rightG.png" );
new AnimationTimer()
{
public void handle(long currentNanoTime)
{
// Clear the canvas
gc.clearRect(0, 0, 512,512);
if (input.contains("LEFT"))
gc.drawImage( leftG, 64, 64 );
else
gc.drawImage( left, 64, 64 );
if (input.contains("RIGHT"))
gc.drawImage( rightG, 256, 64 );
else
gc.drawImage( right, 256, 64 );
}
}.start();
theStage.show();
}
Handling Mouse Events
Now let's look at an example that focuses on the MouseEvent class rather than the KeyEvent class. In this mini-game, the player earns a point every time the target is clicked.
Since the EventHandlers are inner classes, any variables they use must be final or "effectively final", meaning that the variables can not be reinitialized. In the previous example, the data was passed to the EventHandler by means of an ArrayList, whose values can be changed without reinitializing (via the add() and remove() methods).
However, in the case of basic data types, the values cannot be changed once initialized. If you would like the EventHandler to access basic data types that are changed elsewhere in the program, you can create a wrapper class that contains either public variables or getter/setter methods. (In the example below, IntValue is a class that contains a publicint variable called value.)
public void start(Stage theStage)
{
theStage.setTitle( "Click the Target!" );
Group root = new Group();
Scene theScene = new Scene( root );
theStage.setScene( theScene );
Canvas canvas = new Canvas( 500, 500 );
root.getChildren().add( canvas );
Circle targetData = new Circle(100,100,32);
IntValue points = new IntValue(0);
theScene.setOnMouseClicked(
new EventHandler<MouseEvent>()
{
public void handle(MouseEvent e)
{
if ( targetData.containsPoint( e.getX(), e.getY() ) )
{
double x = 50 + 400 * Math.random();
double y = 50 + 400 * Math.random();
targetData.setCenter(x,y);
points.value++;
}
else
points.value = 0;
}
});
GraphicsContext gc = canvas.getGraphicsContext2D();
Font theFont = Font.font( "Helvetica", FontWeight.BOLD, 24 );
gc.setFont( theFont );
gc.setStroke( Color.BLACK );
gc.setLineWidth(1);
Image bullseye = new Image( "bullseye.png" );
new AnimationTimer()
{
public void handle(long currentNanoTime)
{
// Clear the canvas
gc.setFill( new Color(0.85, 0.85, 1.0, 1.0) );
gc.fillRect(0,0, 512,512);
gc.drawImage( bullseye,
targetData.getX() - targetData.getRadius(),
targetData.getY() - targetData.getRadius() );
gc.setFill( Color.BLUE );
String pointsText = "Points: " + points.value;
gc.fillText( pointsText, 360, 36 );
gc.strokeText( pointsText, 360, 36 );
}
}.start();
theStage.show();
}
The full source code is contained in the GitHub repo; the main class is Example4M.java.
Creating a Basic Sprite Class With JavaFX
In video games, a sprite is the term for a single visual entity. Below is an example of a Sprite class that stores an image and position, as well as velocity information (for mobile entities) and width/height information to use when calculating bounding boxes for the purposes of collision detection. We also have the standard getter/setter methods for most of this data (omitted for brevity), and some standard methods needed in game development:
update(): calculates the new position based on the Sprite's velocity.
render(): draws the associate Image to the canvas (via the GraphicsContext class) using the position as coordinates.
getBoundary(): returns a JavaFX Rectangle2D object, useful in collision detection due to its intersects method.
intersects(): determines whether the bounding box of this Sprite intersects with that of another Sprite.
public class Sprite
{
private Image image;
private double positionX;
private double positionY;
private double velocityX;
private double velocityY;
private double width;
private double height;
// ...
// methods omitted for brevity
// ...
public void update(double time)
{
positionX += velocityX * time;
positionY += velocityY * time;
}
public void render(GraphicsContext gc)
{
gc.drawImage( image, positionX, positionY );
}
public Rectangle2D getBoundary()
{
return new Rectangle2D(positionX,positionY,width,height);
}
public boolean intersects(Sprite s)
{
return s.getBoundary().intersects( this.getBoundary() );
}
}
The full source code is included in Sprite.java in the GitHub repo.
Using the Sprite Class
With the assistance of the Sprite class, we can easily create a simple collecting game in JavaFX. In this game, you assume the role of a sentient briefcase whose goal is to collect the many money bags that have been left lying around by a careless previous owner. The arrow keys move the player around the screen.
This code borrows heavily from previous examples: setting up fonts to display the score, storing keyboard input with an ArrayList, implementing the game loop with an AnimationTimer, and creating wrapper classes for simple values that need to be modified during the game loop.
One code segment of particular interest involves creating a Sprite object for the player (briefcase) and an ArrayList of Sprite objects for the collectibles (money bags):
Sprite briefcase = new Sprite();
briefcase.setImage("briefcase.png");
briefcase.setPosition(200, 0);
ArrayList<Sprite> moneybagList = new ArrayList<Sprite>();
for (int i = 0; i < 15; i++)
{
Sprite moneybag = new Sprite();
moneybag.setImage("moneybag.png");
double px = 350 * Math.random() + 50;
double py = 350 * Math.random() + 50;
moneybag.setPosition(px,py);
moneybagList.add( moneybag );
}
Another code segment of interest is the creation of the AnimationTimer, which is tasked with:
calculating the time elapsed since the last update
setting the player velocity depending on the keys currently pressed
performing collision detection between the player and collectibles, and updating the score and list of collectibles when this occurs (an Iterator is used rather than the ArrayList directly to avoid a Concurrent Modification Exception when removing objects from the list)
rendering the sprites and text to the canvas
new AnimationTimer()
{
public void handle(long currentNanoTime)
{
// calculate time since last update.
double elapsedTime = (currentNanoTime - lastNanoTime.value) / 1000000000.0;
lastNanoTime.value = currentNanoTime;
// game logic
briefcase.setVelocity(0,0);
if (input.contains("LEFT"))
briefcase.addVelocity(-50,0);
if (input.contains("RIGHT"))
briefcase.addVelocity(50,0);
if (input.contains("UP"))
briefcase.addVelocity(0,-50);
if (input.contains("DOWN"))
briefcase.addVelocity(0,50);
briefcase.update(elapsedTime);
// collision detection
Iterator<Sprite> moneybagIter = moneybagList.iterator();
while ( moneybagIter.hasNext() )
{
Sprite moneybag = moneybagIter.next();
if ( briefcase.intersects(moneybag) )
{
moneybagIter.remove();
score.value++;
}
}
// render
gc.clearRect(0, 0, 512,512);
briefcase.render( gc );
for (Sprite moneybag : moneybagList )
moneybag.render( gc );
String pointsText = "Cash: $" + (100 * score.value);
gc.fillText( pointsText, 360, 36 );
gc.strokeText( pointsText, 360, 36 );
}
}.start();
As usual, complete code can be found in the attached code file (Example5.java) in the GitHub repo.
You may be interested in learning how to use Scene Builder, a visual layout environment for designing user interfaces. This program generates FXML, which is an XML-based language that can be used to define a user interface for a JavaFX program. For this, see JavaFX Scene Builder: Getting Started.
FX Experience is an excellent blog, updated regularly, that contains information and sample projects of interest to JavaFX developers. Many of the demos listed are quite inspirational!
The JFxtras project consists of a group of developers that have created extra JavaFX components which provide commonly needed functionality currently missing from JavaFX.
The JavaFXPorts project enables you to package your JavaFX application for deployment on iOS and Android.
In this tutorial, I've introduced you to JavaFX classes that are useful in game programming. We worked through a series of examples of increasing complexity, culminating in a sprite-based collection-style game. Now you're ready to either investigate some of the resources listed above, or to dive in and start creating your own game. The best of luck to you in your endeavors!