• The evolution of gamepad controllers through history

    The evolution of gamepad controllers through history

    While video game technology, whether for PC or gaming consoles, have certainly evolved over the years, little attention is paid to how gamepad controllers have evolved. In this article, we’re going to explore how the concept of the gamepad controller has been updated over the years, evolving right alongside things like stronger GPUs, more RAM, motion sensor technology, and everything else in the gaming industry.

    The earliest years (70s - 80s)

    The most iconic game controller in history is perhaps the Atari joystick. While not technically the very first game controller, previous designs were far more primitive, such as the Magnavox Odyssey in 1972. The Atari 2600 featured numerous popular games such as Pitfall!, Breakout, Pong, and more.

    The Atari joystick could be moved in four directions, not like the 360-rotation joysticks of later design. However, it was perfect for the 2D games featured on the Atari 2600, but improvements could be made.

    Thus Nintendo came along with the original Nintendo Entertainment System. However, the video game market was experiencing a crash in 1983, and retail stores were hesitant to stock the Nintendo Entertainment System, as the market was already flooded with low-quality games and consoles.

    Thus, Nintendo engineered a genius marketing ploy, by designing R.O.B - the Robotic Operating Buddy. This was a robotic toy companion for the NES, and was promised to “interact” with the player during compatible games, even acting as a second player.

    This positioned the Nintendo Entertainment System as a highly “futuristic” gaming console, and perhaps if not for the marketing plot of R.O.B, the NES would not have initially succeeded. In any case, along with bringing classic titles such as Excitebike, Kung Fu, and Mario, Nintendo revolutionized the gamepad industry with the classic NES controller.

    Pretty much all modern game controllers are descended from the original NES gamepad. With its D-Pad, 2 buttons, and buttons for Start / Select, it allowed a whole new style of gameplay, especially for sidescrollers. Players could easily jump and attack at the same time, or other simultaneous separate actions that were simply not possible on the Atari joystick.

    Nintendo soon met competition, however, as Sega released their home gaming console, the Sega Genesis. They weren’t able to improve much on the Nintendo gamepad’s design, so they added more buttons. The original Sega Genesis controller had 3 main buttons, but later added 3 more, for a total of 6 buttons.

    This allowed Sega to give a “superior” gaming experience for certain fighting games like Mortal Kombat, with easier to perform attacks and combos, since each button could correspond to different kicks and punches.

    The early to mid 90s: End of 2D, hello 3D

    Nintendo fought back with the Super Nintendo Entertainment System (SNES), and introduced another revolutionary concept - the shoulder buttons.

    While they didn’t go Sega’s route and add rows of buttons, only adding 2 more buttons to the original NES controller, they rounded the controller’s edges for a more comfortable grip, which are something used on controllers still today. The shoulder buttons, referred to typically as “L” and “R”, allows players to press them with their index finger, while the thumbs can still hit the D-Pad and face buttons, allowing for even greater freedom and complex gameplay.

    Sega and Nintendo battled it out for a while, with Sega released the Sega Saturn, a console that could be considered as displaying some of the first hi-res 3D polygon graphics on gaming consoles, but limited titles doomed the console.

    Nintendo then released the Nintendo 64, which saw yet another massive revolution in the gamepad controller.

    The N64 controller had a strange trident shape, which forced players to hold only two of the three prongs at a time, depending on the game. It kept the original D-Pad on the left side, and on the right side, and the B/A buttons on the right, while adding the C-buttons, which could be used like the D-Pad on same games, or as regular game buttons in others.

    They also added the “Z-Button” behind the joystick prong. As hideous and complicated as the N64 controller appeared, it actually turned out to be highly functional. At the time, playing first-person shooters like Goldeneye and Turok felt amazing with the joystick and C-button combination, with the joystick allowing players to move their character, and the C-buttons acting as camera controllers, as a pseudo D-Pad for the first-person perspective.

    The original Sony Playstation had already launched by this point, but the original Sony Playstation gamepad was pretty similar in design to the SNES / Sega Genesis controllers, with a D-Pad, 4 game buttons, and shoulder pads. However, they soon released the DualShock controller, to try and improve on Nintendo’s concept of the N64’s joystick.

    The DualShock controller contained built-in rumble motors, whereas the N64 controller needed an external Rumble Pak accessory. Sony also added a second joystick, and unlike N64’s joystick, Sony’s were actually analog sticks, with pressure sensitivity. This meant that in racing games, for example, the player’s would accelerate quickly or slowly, depending on how far they pushed the stick. Pushing the stick all the way up was analogous to “putting the pedal to the metal”, so to speak.

    While the N64 controller perhaps introduced the concept of the joystick for modern gaming, Sony’s DualShock controller really revolutionized the industry at this point, and pretty much all gaming consoles now feature built-in rumble motors and dual thumbsticks.

    The late 90s to early 00s

    Sega released the Sega Dreamcast in 1998, and while the console itself was a commercial failure, they did experiment with controller design. The Sega Dreamcast featured a single thumbstick, D-Pad, and 4 buttons, but they introduced the VMU screen.

    The VMU screen on the Dreamcast controller was simultaneously a memory card and LCD screen that could be plugged into the controller. The LCD screen would display additional game information, real-time clock, or graphics and logos depending on the game being played. The VMU could also be unplugged from the controller and function as a sort of pocket minigame device, sort of like a Tomagotchi (remember those?).

    Sony released the Playstation 2 in 2000, along with the DualShock 2 controller. This really didn’t innovate much, because it kept the original DualShock design, but Sony also made their analog sticks function as buttons. Known as the “analog buttons”, the player simply clicks in the sticks. This was fairly innovative, as it allows the player to access an extra pair of buttons where the player’s thumbs are already resting!

    Nintendo then released the Gamecube system in 2001, which again, showcased Nintendo’s preference for slightly bizarre controller design.

    The Gamecube controller utilized the dual-stick layout of Sony’s DualShock controllers, yet swapped the position of the D-Pad and the left joystick. The secondary analog stick was slightly smaller, and referred to as the “C-Stick”, which replaced the C-buttons on the original N64 controller. It maintained the shoulder buttons, while moving the Z-button found on the middle prong of the original N64 controller to the right side of the Gamecube controller, next to the right shoulder pad.

    Gamepad controllers in the modern era

    In any case, Nintendo and Sony battled it out for a long time, until Microsoft arrived on the scene with the original Xbox console. The original Xbox controller was a massive behemoth, and was criticized for its sheer bulky size. It also didn’t introduce anything really “new” to gamepad design. For a long time, nobody knew exactly why Microsoft made the original Xbox controller, nicknamed “The Duke”, such a massive size.

    However, just a few years ago, one of the co-creators of the original Xbox explained that their vendor couldn’t shrink the electronics inside the controller, so they had no choice but to go with such a massive design. Their solace was that the Sega Dreamcast controller was around the same size, because of the VMU screen.

    Microsoft released a smaller version, called the “S Controller”, and for the Xbox 360 controller, they introduced the “Guide” button, which could be used to turn the Xbox console on or off, as well as accessing the Xbox 360 menu.

    One awesome thing Microsoft did is make the Xbox 360 controller compatible with Windows through USB input, and many PC games can be played using the Xbox 360 controller. While previously, DirectInput was the standard for Microsoft API for gamepad devices on PC, it was replaced by XInput, and many game developers who port console games over to PC prefer using the XInput API.

    This also extends to browser games, like those found on CrazyGames. For example, browser games like Forge of Empires or powerline.io can be played with a gamepad, even through the browser.

    While Sony and Xbox have pretty much stuck to their main controller concepts throughout the years, Nintendo has continued to experiment with shapes and button placement, even until today. For better or for worse, Nintendo enjoys being an “innovator” in gamepad controller design, with the release of the Nintendo Wii in 2005.

    The Nintendo Wii introduced the “Wiimote”, which is literally shaped like a remote control. With a D-Pad and a trigger button, the Wii Remote has motion sensing capabilities, using accelerometer and optical sensor technology. A secondary “Nunchuk” controller can be plugged into the Wiimote for additional functions, or other peripherals such as the Wii Classic Controller, Wii Zapper (a light gun peripheral), and the Wii Wheel, for racing games.

    While the Wii outsold every other console on the market, due to a lower price and a wider market appeal (focusing on a younger demographic), the motion sensor technology of the Wiimote did face some accuracy issues.

    Xbox released their own motion sensor technology in 2010, known as Kinect for the Xbox 360. Sony also released Sony Move for the Playstation 3 in 2010, which utilized a motion controller very similar in design to the Wiimote, while Xbox Kinect requires no remote whatsoever, using infrared camera technology.

    In any case, the evolution of the console gamepad controller really peaked in the late 90s, as modern controller design really follows the foundations laid out by Nintendo and Sony in that era.

  • 4 Popular Zombie Survival Tactics (That Will Get You Killed)

    4 Popular Zombie Survival Tactics (That Will Get You Killed)

    The zombie uprising is a popular fictional trope that has spawned countless movies, books, video games, and online debates. Everyone likes to believe they’d be a survivor, prattling off their carefully calculated strategies to avoid becoming brainfood for the undead. And yet, a good majority of those same people would probably become brain food.

    It’s like this exercise we did in the 5th grade. The teacher asked us what supplies we would take if we were stranded at ocean on a raft. We could choose up to 5 supplies from a list provided by the teacher. About 90% of the class ended up dead. I didn’t. Because I’m smart, and bringing a CD-player and magazines instead of an umbrella and duct tape (for sun protection and plugging leaks, duh) is stupid. That’s why you should pay attention to the things I’m going to say.

    Now, prepare to be told why all those popular zombie survival tactics are totally wrong and will get you killed.

    Using martial arts against zombies

    Using martial arts against zombies

    For some reason (natural selection), there are people out there who believe deploying martial arts against the undead is a good idea. It’s not. In fact, it’s a terrible idea.

    For starters, striking a zombie with your hands and feet is entirely pointless. Zombies are generally immune to pain, cannot be knocked unconscious (unless we’re talking about UFC’s Chan Sung “The Korean Zombie Jung), and you’ll probably end up breaking your own hand.

    Yet there are internet users who seem to think that martial arts could be viable against the undead. See exhibitions A and B:

    Using martial arts against zombies 1

    Using martial arts against zombies 2

    “Hold on!” You might say. “What about grappling arts?”. Again, no. In fact, here’s an instructional video from BJJ black belt and martial arts practitioner for over 30 years, Stephan Kesting. He explains why most BJJ techniques would get you killed against zombies:

    The only martial arts techniques that could possibly be utilized against zombies, while saving your life, would be throws and sweeps, as found in martial arts like Judo. Hip tosses and leg sweeps would allow you to quickly drop a zombie onto its back and give you time to run away (or stomp on its head). And this is highly situational at best, such as if a zombie grabs you from behind, and your reflexes are fast enough to o-goshi that zombie on its head before it sinks its teeth into your neck.

    Using martial arts against zombies 3

    Also, it takes a long time of drilling techniques repetitively to execute them flawlessly without pause. When a zombie grabs you, you have around a second to A: not panic, and B: execute the proper throw based on your position and the zombie’s. Hesitate, and you’re (un)dead. So no, you cannot simply attend a Judo class for a couple of months and become a zombie-hip-tossing machine.

    Now, martial arts are great for staying in shape, absolutely. Anything that improves your cardio, flexibility and body strength is going to be highly beneficial during a zombie apocalypse. Parkour, while not technically a combat martial art, would be a fantastic candidate for this. But actually going all Wing Chun rolling punches on a zombie? Worst. Idea. Ever.

    Using video games as a training tool

    You might’ve played countless hours of Left 4 Dead, Dead Rising, Dying Light, Resident Evil, or any other number of the plethora of zombie games out there. You might think this has prepared you for the zombie apocalypse. It hasn’t.

    Using video games as a training tool

    Yes, video games have been proven to have a number of cognitive benefits, such as increased reaction time and split-second decision-making skills. You might’ve even picked up some viable flanking strategies from Call of Duty. How well is all this going to translate into real life, though?

    In video games, you have medikits that instantly recover health. Guns never jam. And while video games attempt to simulate gun recoil, they don’t prepare you for the sheer kinetic energy. Firing powerful rifles with improper positioning can dislocate your shoulder, handguns can smack you in the face. You can get messed up from behind a gun. Good luck finding a dentist during the zombie apocalypse.

    So yes, video games are educational. But they don’t teach you the muscle memory to properly handle a firearm. If you’re an avid firearms collector who attends the range often or have military training, this obviously doesn’t apply to you. I’m speaking specifically to you basement dwellers who thinks 5000 hours of Call of Duty on your Steam account has in any way prepared you for gun maintenance and safety protocols.

    Aiming for the head

    Aiming for the head

    It’s common knowledge that zombies are killed by cranial damage, which has led to hordes of movies and video games depicting characters blowing the heads off zombies with ease. Here’s a fun fact - headshots are freaking hard. So hard, in fact, infantry soldiers are typically trained to aim for the chest, AKA “center mass”.

    Aming for the head 1

    Another fun fact: Army basic marksmanship training is a 2 - 3 week course, and soldiers must only hit around 25 out of 40 pop-up targets, from a range of 5 to 300 meters. Yes, the Army considers a successful hit rate of around 57% to be a passing score for marksman qualification.

    So how exactly do you, Mr. Joe Average, expect to squeeze off those perfect headshots that trained Army soldiers cannot?

    The good news, however, is that you can cripple zombies without aiming for the head. Depending on your ammunition type, severing the zombie’s spinal cord while aiming for the chest is completely viable. In fact, gunshot wounds are the second leading cause of spinal cord injuries.

    Aming for the head 2

    The knees are also a potentially good target - they’re smaller than the head, but there’s two of them to hit. A quick burst aimed at a zombie’s legs could leave it crippled, giving you the opportunity to escape.

    Holing up in a fortress

    Holing up in a fortress

    During a zombie apocalypse, most people’s instinct will be to head for some type of fortified compound or other suitable area intended for disaster relief. Alternatively, you may be thinking of fortifying your own house. This is all wrong.

    During the zombie apocalypse, tensions are going to be high. People will be fighting over precious resources such as water, guns, sleeping bags, and any other type of survival gear. People will get killed over this, yo. In fact, it could be argued that other people will be a real threat during a zombie apocalypse. Don’t believe me? Just yell “FIRE!” in a crowded theatre and watch everyone trample each other to reach the exit. No, don’t do that, it’s illegal. But hopefully, you get my point.

    Holing up in a fortress 1

    Now, I could be totally wrong. Humanity could band together against a common threat, the government could maintain peace and order, and people could put aside their differences to kick some zombie ass. It’s idealistic, yet highly unlikely.

    “Humans are the real monsters”, and its sub-trope “Beware the Living” are extremely common fictional tropes, for good reason. When crap hits the fan, people generally look out for numero uno - themselves.

    All those disaster survival guides you’ve read; head for the nearest school, hospital, evacuation centers, the Superdome in New Orleans (on second thought…), all perfectly good ideas. During a natural disaster, where relief organizations can bring supplies, and celebrities tweet things like #HopeForHaiti. In a zombie apocalypse, all that goes right out the window. Our politicians will be secure in their underground bunkers, and West Hollywood is the 17th most densely populated city in the United States, so our celebrities will probably be tweeting #Braaaiiiins.

    Holing up in a fortress 2

    You could spend a couple of months on zombie-proofing your home, but will it be human proof? Probably not. Unless you already live in a fortified compound (who are you, Osama Bin Laden?), you won’t have the time or resources to start erecting barbed-wire trenches and 8-foot concrete walls around your house in the middle of the end of humanity.

    So where do you go during the zombie apocalypse? Well, here we have to get technical.

    Cornell University researcher Alex Alemi released an interactive model of a hypothetical zombie outbreak in the United States. Users can click anywhere on the map, and watch how fast a zombie outbreak would spread, based on starting location, population density, kill-to-bite ratio (zombies killed per infected humans), and average time for zombies to walk 1 mile.

    Holing up in a fortress 2

    Based on Alemi’s model, zombie outbreaks started in or near major urban cities would spread quite rapidly (obviously), yet infection rate decreases exponentially once it reaches more rural areas. Based on this model, we could suppose that the safest places to be during a zombie apocalypse would be rural areas, especially low-population, mountainous regions.

    Of course, many people might be aware of this, and those low-population areas might suddenly become not so low-population anymore. It’s a bit like waking up early to “beat the morning traffic”. Lots of people have the same idea, so the roads just end up being congested anyway.

    Thus, the absolute safest location would be out on the ocean, in a sailboat stocked with plenty of supplies and fishing gear.

  • Key Video Game Statistics for 2019

    The video game industry is predicted to experience rapid growth in the coming years. The industry as a whole generated around $135 billion throughout 2018. This is a 66% increase in global gaming revenue since 2015. (1)

    Asia Pacific leads as the largest gaming market, followed by North America, Europe, the Middle East, Africa, and Latin America, respectively. (2)

    Revenue & Trends by Top Countries

    China

    China alone accounts for about 28% of global game revenue, or around $37.9Bn. This is due to a massive gaming population (around 619.5 million). Mobile games accounted for $23Bn of the Chinese market, with PC and console games generating $14.4 and $0.6 billion respectively. The vast majority of Chinese gamers (94%) purchased virtual items throughout 2018, mostly cosmetics and character skins.

    The top mobile games in China are native MOBAs like Arena of Valor, which has a massive esport following, though only in China. Arena of Valor has not found much esport success outside of China. 72% of China’s gaming population watches esport tournaments. (3)

    One thing worth noting is that China’s esport scene mostly revolves around Chinese games – the government has blocked a large number of popular online games, including some of the most popular esport games on the global scene.

    U.S.

    The U.S. comes in second at $30.4Bn total gaming revenue. With a population of 178.7M gamers, 79% of gamers spent money on in-game items. Mobile gaming leads the market revenue, followed by PC games and consoles, respectively. It’s worth mentioning gender statistics in the U.S. – 60% / 58% of mobile games are male / female, 42% / 24% for consoles, and 46% / 36% for PC games.

    Esports are also popular in the U.S., with 63% of the gaming population viewing esports tournaments. The most popular esports game in the U.S. is Super Smash Bros. (4)

    Japan

    Japan remains in third, adding $19.2 billion to the global revenue. With a population of 67.6 million gamers, 77% spent money on in-game items. What’s worth noting here is that Japanese gamers spend more on mobile games than any other market, averaging 1.5x higher purchase-per-player overall.

    As with other countries, the gaming demographic leads towards male gamers. For mobile gamers, 41% are male, and 32% are female. For consoles, 30% are male and 15% are female. On PC, 28% are male, 15% are female.

    Of the top three countries, Japan has the largest ratio of esports viewers. 84% of Japanese gamers view esports tournaments, with the most popular franchise being Street Fighter. (5)

    Revenue by Platform

    Mobile Games

    Mobile is the largest gaming platform, accounting for 51% of global revenue in 2018. This is expected to climb to 54% in 2019, 57% in 2020, and 59% by 2021. Basically, this means that mobile gaming will be a $100Bn market by 2021. (6)

    It’s worth noting that the rise of mobile games has impacted, but not significantly gutted the console and PC industry, which also saw their own growth – just at a much smaller growth rate than mobile gaming.

    Console and PC Games

    PC and console games saw a 3.1% and 2.3% revenue growth in the past decade, respectively. PC games are expected to account for 24$ of the market in 2019, and consoles will take 22%. (6)

    PC game revenue in the esports market will likely not see significant growth, as most of the popular PC games are operating at their maximum monetization potential. Furthermore, it’s unlikely that any new PC games will sweep the market. There’s also been a decline in average price for pay-to-play PC titles, as well as significant backlash against the freemium model.

    Consoles, on the other hand, have the potential to significantly increase esport revenue, as live streaming console titles is becoming more popular. By 2021, the console market could reach $39Bn, in part thanks to console gamers embracing live streaming and esports.

    Browser Games

    An oft-ignored category are “browser games” (video games played in a web browser), which are usually lumped in with the PC game market. However, we will separate browser games from the PC game market, because browser games are highly cross-platform compatible.

    In 2017, browser games accounted for $4.5Bn of the overall market, or around 4% (7). However, browser games are expected to decline to around $2.5Bn by 2021, as many browser games (and browser game titles) transition to mobile. In fact, many popular mobile games are strongly based on browser titles, or mobile versions of games that were originally developed for PC browsers.

    Exact numbers for browser-based game revenue is a bit difficult to track, as only a very tiny percentage of browser games rely on a freemium model. It is mostly browser-based MMOs that offer in-app purchases. The majority of browser-based games rely on traffic and ad revenue.

    Esports Revenue & Player Incomes

    Next to mobile games, esports has seen the highest year-to-year revenue growth in recent years, expected to surpass the $1.1Bn revenue mark in 2019. (8)

    The total predicted revenue for esports depends on various revenue sources, which are as follows:

    The projected revenue for 2019 takes into account the growing esport audience, which is expected to surpass 201.2 million regular viewers, and 252.6 million casual viewers.

    As we mentioned earlier, China recently banned a large number of the most popular esport games including PubG and Fortnite. Other popular esport games like League of Legends and Overwatch were placed on a “watch list” for inappropriate content. These facts should be taken into account when considering the overall esport growth for 2019 on a global scale, as China is one of the largest gaming markets.

    As we noted earlier in the Console and PC Games section, the growing popularity of streaming will lead a growth in esport interest amongst console gamers. With the exception of a few notable console titles like Call of Duty, Halo 5, Mortal Kombat X, Super Smash Bros, and Street Fighter, PC games have typically dominated the esports market, thanks to the popularity of RTS games like StarCraft, and MOBAs like League of Legends.

    The most popular esport games in 2018 (ranked by prize pool) were (9):


    • Call of Duty: WWII ($4.17M)

    • StarCraft II ($4.53M)

    • Hearthstone ($4.95M)

    • Heroes of the Storm ($6.52M)

    • Overwatch ($6.7M)

    • PubG ($6.73M)

    • League of Legends ($14.12M)

    • Fortnite ($19.96M)

    • Counter-Strike ($22.47M)

    • Dota 2 ($41.26M)


    The games expected to become more popular in 2019 are:

    • Call of Duty: Black Ops 4

    • PubG

    • Super Smash Bros Ultimate

    • Clash Royale

    • Magic: The Gathering Arena


    Esport Player Earnings

    The average salary for an esports player ranges between $1,000 - $5,000 monthly throughout 2018.

    The top 5 earning players for console games were (10):


    • Damon Barlow: $728,222

    • Ian Porter: $703,851

    • Jordan Kaplan: $655,217

    • Tony Campbell: $639,125

    • Paul Duarte: $629,250


    The top 5 earning players for PC games were (11):

    • Kuro Takhasomi: $4,163,926.95

    • Johan Sundstein: $3,749,055.59

    • Amer Al-Barkawi: $3,728,337.28

    • Ivan Ivanov: $3,519,411.76

    • Lasse Urpalainen: $3,503,116.04



    It’s worth noting that the majority of top earners are Dota 2 players. In fact, the top 45 earners overall are Dota 2 players, followed by a few Counter-Strike and League of Legends players.

    The top 5 highest earnings by country (based on earnings of players):


    • United States: $95,016,301

    • China: $87,212,214

    • Korea: $72,126,497

    • Sweden: $30,379,428

    • Denmark: $25,167,864


    Twitch Streaming Stats and Streamer Incomes

    Twitch.tv has proved to be an inspired acquisition for Amazon, and the growth of the platform has truly been explosive in the past few years, building a massive economy for streamers and the opportunity to play professionally.

    Average Concurrent Viewers on Twitch since 2012

    Growth in Twitch Broadcasters Over Time

    We’ve since an explosive growth in the number of people broadcasting on Twitch, especially in the past 2 years. This has opened a gateway to a whole new generation who want to play and stream video games professionally. It’s a cultural phenomenon.

    Twitch Milestones for 2019

    Twitch streamers make roughly $2.50 per month per channel subscription, as the subscription cost of $4.99 is split either 50/50 or 60/40 between Twitch and the streamer. The split scales in favor of the streamer with viewership.

    Twitch streamers can also monetize their channels through donations (which go entirely to the donor), ad revenue, and sponsorships. There are many variables involved, so it is nigh impossible to calculate an “average” income for Twitch streamers. We can, however, offer a look at the approximate incomes of top Twitch streamers, based on the various metrics mentioned above. (12)


    • Ninja: $5,417,447/yr

    • Shroud: $3,193,097/yr

    • TimTheTatman: $2,770,287/yr

    • DrLupo: $1,963,700/yr

    • DrDisRespectLIVE: $1,791,453/yr

    • MOONMOON_OW: $1,726,966/yr

    • AdmiralBahroo: $1,688,351/yr

    • Sodapoppin: $1,666,707/yr

    • LIRIK: $1,545,598/yr

    • Tsm_Myth: $1,330,275/yr


    Most Streamed Games on Twitch as of February 2019



    • Apex Legends: 156,183 average viewers

    • League of Legends: 135,236 average viewers

    • Fortnite: 130,615 average viewers

    • CS: GO: 87,472 average viewers

    • Dota 2: 85,684 average viewers

    • Overwatch: 48,969 average viewers

    • PubG: 26,094 average viewers

    • Grand Theft Auto V: 24,346 average viewers


    (1)GamesIndustryBiz, Global games market value

    (2)WePC, 2019 Video Game Industry Statistics, Trends & Data

    (3)Newzoo, China Games Market 2018

    (4)Newzoo, U.S. Games Market 2018

    (5)Newzoo, Japan Games Market 2018

    (6)Newzoo, Mobile Revenues Account for More Than 50% of the Global Games Market

    (7)Newzoo, Global Games Market Report 2018.PDF

    (8)Newzoo, Global Esports Economy Will Top $1 Billion

    (9)EsportObserver, 10 Biggest Esports of 2018

    (10)EsportsEarnings, Top Console Players

    (11)EsportsEarnings, Highest Overall

    (12)MediaKix, How Much Do Twitch Streamers Make

  • Apex Legends Key Statistics

    Electronics Arts’ decision to launch Apex Legends, a free-to-play battle royale game, could be seen as a Hail Mary pass from the gaming giant. The game was released without any warning from EA, it literally came out of left field, during a downturn in EA’s finances. EA received huge amounts of criticism and gamer backlash in 2018, owing to loot box microtransactions in Battlefront 2. Battlefield V’s overall sales were disappointing, and FIFA 19 had disappointing digital sales.

    So for a company coming out of a difficult year with a strong final quarter slump, releasing a free-to-play battle royale game (with loot boxes) into a sea of battle royale games dominated by PubG and Fortnite, with absolutely no prior marketing, could seem almost positively ludicrous. So ludicrous, in fact, it worked.

    Player Stats

    It seems that the developers of Apex Legends, Respawn Entertainment, were highly aware that the words “EA”, “free-to-play”, and “loot boxes” would send red flags through the gaming industry, and intentionally released the game without any marketing. Lead producer Drew McCoy had the following to say about the strategy:

    “We’re doing a free-to-play game, with essentially loot boxes, after we were bought by EA, and it’s not ‘Titanfall 3.’ It’s the perfect recipe for a marketing plan to go awry […] So why have that? Let’s just ship the game and let players play.”

    It certainly worked better than anyone could have dreamed of. Within 3 days of launching, Apex Legends had a total of 10 million players (1 million concurrent), and rose to 25 million players in the first week.
    Not only did it far exceed expectations for amount of players, but it absolutely dominated livestreaming throughout February, on popular streaming portals Twitch and YouTube.

    Twitch Stats

    Within a few days of release, Apex Legends claimed 11.8% of Twitch’s entire audience, averaging 156,183 viewers in a 1-week timeframe. Apex Legends beat out long-time Twitch favorites League of Legends and Fortnite, which hold 10.2% and 9.8% of Twitch’s viewer audience respectively (1).

    Apex Legends highest average views mark came on February 10th, with 278,004 viewers. Its peak came on February 12th, with 674,070 viewers. These numbers could be expected for the amount of hype that surrounded Apex Legends’ release, but despite a gradual decline in average views between February 13 – February 28, Apex Legends still ended the month with an average 222,005 viewers. This edged it out over long-time Twitch favorite League of Legends, which had an average of 142,591 viewers for February.

    It’s worth noting that this isn’t simply gamers briefly watching Apex Legends to gauge its hype. In the final week of February, Apex Legends amassed 26,655,239 total hours viewed (combined total of all viewers in 7 days, obviously the game has not been streaming for 3042.83 years).

    In an increasingly common form of guerrilla advertising, EA paid several prominent Twitch streamers to play Apex Legends. Of course, the streamers must disclose that they are being sponsored by EA while streaming, and many of them carried an #ApexPartner hashtag on their Twitch profiles. (2)

    The interesting part about that, however, is that a number of streamers who were paid to stream Apex Legends, ended up praising the game, and continued streaming it when EA was no longer paying them. Some of the top Twitch streamers that have praised Apex Legends include Ninja, Dr. Disrespect, Tim the Tatman, and Shroud.

    1 Month In, Will Apex Stand The Test of Time?

    Clearly, with all the hype surrounding the game, it was always going to surge ahead of its peers during the first weeks of launch as something new and fresh.

    Now into March 2019, we wanted to check how it was comparing against key rivals now that the dust has settled.

    Here’s our findings on the daily average Twitch viewers, Feb 2019 vs. March 2019:

    Interesting points of note:


    • League of Legends remains very consistent and unaffected by the introduction of Apex Legends. We can reasonably guess this is because LoL isn’t a competing battle royale game, and attracts a very different kind of gamer.

    • Fortnite engagement was severely disrupted by the introduction of Apex Legends, since it’s a competing Battle Royale game and because many key Fortnite streamers switched over to Apex. However, Fortnite has recovered nicely in March and overtaken again.

    • PUBG, the 3rd most popular game in the Battle Royale genre right now (going off Twitch viewer count) took quite a significant hit in February 2019, and hasn’t yet managed to recover in March. This could be an indication that a good chunk of its player base has permanently migrated over to Apex.

    EA’s Share Price Before and After Apex Legends

    Apex Legends has also appeared to mark a turnaround in EA’s finances. After steadily climbing for several years, reaching an all-time high of $147.48 USD per share in July 2018, EA’s stock prices saw a sharp decline throughout the rest of 2018. Its lowest point came in late December, finishing the year at $79.30 USD per share – an overall 25% down.

    Apexlegendskeystatistics

    Part of this was due to a delayed release for Battlefield V, and disappointing FIFA 19 digital revenue. Since the release of Apex Legends, EA’s stock climbed up to $106.84 USD per share on February 15th, though has declined down to (average) $95 USD per share in the last half of February, remaining there. (3)


    References

    (1) TwitchTracker, Apex Legends

    (2) Barrons, How EA Used Twitch Gamers to Battle Fortnite

    (3) Nasdaq, Electronic Arts

  • Brain Games for the Elderly: Benefits & What to Play

    The older we get, the more prone we become to a variety of mental disabilities. The World Health Organization estimates that over 20% of adults aged 60 suffer from some type of mental or neurological disorder. The most common are dementia and depression. Dementia itself is an umbrella term for a range of symptoms that impair memory and thinking. The most well-known cause of dementia is Alzheimer’s, although other common causes include Parkinson’s Disease, Huntington’s Disease, and Creutzfeldt-Jakob disease.

    Brain Games for the Elderly

    We may think that these neurological disorders are the natural decline of a person’s mental faculties as they grow older, but there are many external influences as well. Life stress is a major contributor, and it can be easily overlooked how much stress the elderly need to cope with. Elderly persons often need to deal with the awareness of losing certain capacities and functions, as well as chronic pains and loss of mobility as the body natural ages.

    The very idea of “aging” can be a stress factor, but then you include things such as bereavement (41% of American women older than 65 are widowed), and a potential drop in socioeconomic status due to retirement. So overall, its important to remember that dementia symptoms are not simply a natural decline of the mental faculties, but can also be largely influenced by a number of stress factors that the elderly must cope with.

    Currently, there is no known cure for Alzheimer’s, and no way to slow its progression. Whether or not Alzheimer’s is preventable is up in the air – as we mentioned, dementia symptoms can be onset by stress factors, and there are numerous risk factors for Alzheimer’s. These include diabetes, mid-life hypertension, mid-life obesity, physical inactivity, depression, smoking, and low educational attainment. Thus, experts suggest that one in three Alzheimer’s cases may be preventable with certain lifestyle changes.

    “The two biggest misconceptions are “It’s just aging” and “It’s untreatable, so we should just leave the person alone.”
    -Murali Doraiswamy, MBBS, “Can Alzheimer’s Be Cured




    Why Scientists are Divided on Brain Games



    One common misconception is that brain-training games are a sure-fire method to combat dementia. This is partially true – there’s very little brain games can offer once dementia has set in. However, a large part of the battle against dementia is prevention. Thus, brain games are a great method to stimulate the mind, forming new neuro-connections, and benchmarking whether dementia is setting in. For example, if an elderly person notices their daily brain-game puzzles are becoming more difficult to solve (and not due to any sort of in-game difficulty), it’s a good sign that something should be checked out.

    There have been many studies into the subject, which we’ll dive into shortly. The main point to remember is that brain-training games are a preventative measure, not a treatment.

    Brain games can offer stress relief, and provide an outlet for creative mental energy. It’s the old adage that the brain is a muscle, and needs to be exercised like the rest of our body. Thus, when we keep our minds active on a daily basis, our cognitive abilities are far less likely to decline.

    This is really all a bit of a controversial subject, to be quite clear. There are studied that promote the validity of brain games as a way to reduce the risk of dementia, and studies that find no correlation whatsoever. Study results also appear to be influenced by the types of games being utilized.

    As an example, Lumos Labs, a well-known San Francisco based brain-game company, was fined $2 million USD by the US Federal Trade Commission, for false advertising. Lumos Labs had made the advertisement claims that their brain-training games could reduce the effects of dementia, and combat dementia-related diseases such as Alzheimer’s.

    One study at the University of Pennsylvania, with a research team led by Joseph Kable, put Lumos Labs various brain-training games to the test against a handful of regular computer games. They recruited 128 young adults for a controlled trial. The volunteers were split into three groups – one group using Lumos Labs brain games, the other group playing regular computer games, for a period of 10 weeks. The third group played nothing.

    Before the study began, all three groups were given standard cognitive tests. At the end of the study, it was found that all three groups performed better on a second round of cognitive tests – which means that playing Lumos Labs’ games, regular computer games, or no games at all had pretty much no bearing on the second round of test results. The study subjects most likely performed better on the second set of cognitive tests, due to having already done them before (practice makes perfect?).

    Of course, as we said, studies involving research into the effects of brain-training games on dementia symptoms pretty often have conflicting results. For example, two groups of scientists in 2014 published separate letters on the efficacy of brain-training games for dementia. The first group of 70 scientists claimed that there is no scientific basis for the belief that brain games will improve cognitive function, or combat cognitive decline.

    The second group of 133 scientists countered their letter. Of course, science is all about being able to prove theories, so its no surprise that two groups of scientists would have differing opinions. But one possible reason for this particular disagreement is the standards utilized when evaluating evidence.

    So, as you can see, the debate goes pretty deep. What we can gather from the available research, is that many brain-training games do not offer the proper type of “brain training” that is most effective in combatting the onset of dementia symptoms. To understand this, we need to understand the exact scientific causes of dementia.

    The Exact Science Behind Dementia in Alzheimer’s

    Our brains have trillions of neural synapses, which are connection points where information flows through our brains. Imagine entire spider webs of these neural connections in our brains, information flowing and crossing between them (at the synapse points) at the speed of light.

    We also produce a solitary molecule called amyloid beta – its life begins as a solitary molecule, but over time, these molecules begin to group together. These clusters of amyloid betas begin to travel freely through the brain, but over time, they become plaque that binds to receptors on nerve cells.

    We also produce glial cells, which are like janitors for our neural pathways. Their duty is to clean up injuries to our neuron pathways. However, amyloid beta seems to send these glial cells into overdrive, causing them to work much harder. The glial cells end up working so hard, they actually assist in the degradation of our neural synapses by overcleaning them, eventually eroding the neural synapses altogether. Microglia basically devours our neural synapses. It’s like a janitor that scrubs graffiti off a wall so hard, he ends up scrubbing a hole right through the wall.

    Now, even though amyloid beta production is fairly natural, there are ways we unwittingly speed up the production process and harm ourselves. For example, scientists found that a single night of sleep deprivation can lead to an increase in amyloid beta production. The increase is amyloid beta production in turn makes it harder to fall asleep the next night, which actually creates a positive feedback loop (which, in this case, is not actually positive at all, in a beneficial sense).

    Scientists also found a strong correlation between lack of cardiovascular-strengthening activity, and amyloid beta production. It’s been shown that a large percentage of Alzheimer’s patients also have some type of cardiovascular disease or deficiency. This is because our hearts are responsible for pumping blood through our circulatory system, which carries oxygen to the brain. Oxygen deprivation can have an enormous impact on the brain – for example, oxygen deprivation is the most common cause of mental retardation in newborn infants.

    Thus, when our cardiovascular system is unable to pump sufficient oxygen to our brains, it plays a significant role in the degradation of our cognitive functions. For this reason, many doctors and scientists recommend a healthy, active lifestyle as a way to prevent the onset of Alzheimer’s and other dementia-related diseases.

    As an additional note, while genetics can play a strong role in the development of Alzheimer’s – having just one parent with Alzheimer’s can significantly increase your risk for Alzheimer’s – it is not a guarantee. The specific gene that is thought to be responsible for late Alzheimer’s onset is APOE4, or Apolipoprotein E. However, while APOE4 can contribute to the onset of Alzheimer’s, it is not a direct cause.

    This is because APOE4 belongs to an entire group of proteins which are related to the metabolism of fats in our body. Thus, there is a correlation between cholesterol and Alzheimer’s as well. So, for example, while Nigerians in fact have the highest observed frequency of the APOE4 gene, Alzheimer’s disease is actually rather rare amongst Nigerians. This is thought to be due to their low cholesterol levels (Source: Genetic studies of human apolipoproteins. X. The effect of the apolipoprotein E polymorphism on quantitative levels of lipoproteins in Nigerian blacks).

    So, as you can see, there are a wide range of things that can contribute to the onset of Alzheimer’s and dementia symptoms.

    How Brain Games Can Help Prevent Dementia

    As we said earlier, the dementia symptoms in Alzheimer’s are caused by the erosion of neural synapses. However, we are able to create new neural pathways through cognitive exercise. This is a delicate subject however.

    The problem with many brain training games is that they do not target the proper cognitive developments needed to prevent the onset of dementia. We only form new neural synapses by learning new information – learning a new language, for example. Learning new ways to recall information. We do not form new neural synapses by studying or recalling information we already know.

    This is why doing Crossword or Sudoku puzzles are largely ineffective in brain training, at least for developing new neural synapses. Yes, you are exercising your brain, to a degree. But you’re hitting a plateau. Imagine it like exercising the body. If you do the same exercise every day, like a set of 20 pull-ups each morning, the exercise will quickly lose its efficiency for building new muscle. It may help you maintain the muscles your arms and chest have already developed, but you will not be building new muscle. Thus, bodybuilders will target different muscle groups on certain days, or target the same muscle groups but with different types of exercises.

    Brain workout

    The same exact thing is happening in brain training games. It’s not enough to exercise the brain and do, for example, trivia games where you recall information you have already learned in the past. You must be learning new information in order to form new neural synapses.

    One of the best examples of a particular study that concerns what we’re talking about is The Nun Study. It is a continuous study that began in 1986, led by David Snowdon at the University of Minnesota. The study was eventually moved to the University of Kentucky, but was moved back to the University of Minnesota with Snowdon’s retirement.

    This particular study has yielded many findings in the area of Alzheimer’s, as it focuses on nuns, who are the ideal population for studying Alzheimer’s development. Thus, the study focuses on a group of over 600 American Roman Catholic nuns from the School Sisters of Notre Dame. These nuns do not use drugs, alcohol, and various other elements that could confuse variables found during research.

    Researchers were able to find that over 80% of the nuns whose essays lacked linguistic density went on to develop Alzheimer’s. In the nuns with linguistic density in their writings, only 10% developed Alzheimer’s. One significant finding amongst this was that, while some of the nuns did in fact have all the prerequisites of Alzheimer’s, and they should have been suffering dementia symptoms, they in fact did not. This is attributed to having an excess of neural synapses.

    So, while the nuns were losing existing neural synapses due to the relationship between amyloid beta and microglia we talked about earlier, their constant learning of new information had created enough new neural synapses to create a buffer against dementia.

    What this basically means is that neural pathways are basically roads to retrieving information – when several roads become blocked due to neural synapse erosion, the information can take detours through other neural synapses, if we contain enough of them. Thus, constantly learning new information is of exceeding value when it comes to preventing dementia symptoms – even if we are already at risk for Alzheimer’s.

    This is an important consideration for the prevention of dementia. Because it basically means that, while we may develop Alzheimer’s at late stages in life, the dementia symptoms may not affect us particularly bad if we build up enough neural synapses to counter the erosive damage being done to them. It’s like having $10 million USD. Even if somebody breaks into your house and robs you of $500 thousand, you still have $9.5 million USD.

    The website Cognitive Training Data, maintained by Michael Merzenich, PhD, Professor Emeritus of Neurophysiology at the University of California San Francisco, and Chief Scientific Officer of Posit Science Corporation, is also worth researching. Cognitive Training Data attempts to help scientists, reporters, and consumers “navigate the many mixed messages on the field of computerized cognitive training”.

    Cognitive Training Data offers a tremendous list of published studies that directly demonstrate the effects of computerized cognitive training on cognitive function.

    So, when it comes to brain games, you should not focus on games that simply do memory exercises. You don’t want games that simply target the five cognitive functions: speed, memory, attention, flexibility, and problem-solving. Yes, it’s a good idea to supplement your brain training with those exercises, but it should not be the basis of your training. You need to focus on games that actively teach you new information.

    Therein lies a small problem – because we can’t look at simple puzzle-based apps for effective dementia prevention, we need to think a bit outside the box and dig deeper. We need to look at video games that offer educational benefits. Of course, recommending video games for seniors sounds a bit silly. Can you imagine Grandpa Bob playing Assassin’s Creed: Origins because it imparts tons of historically accurate knowledge? Unfortunately, that’s exactly what we need to imagine.

    Of course, it’s not entirely far-fetched. A report titled “Gamers Over 50 Study: You’re Never Too Old to Play”, released by the ESA (Entertainment Software Association), found that 48% of polled adults over the age of 50 said they play video games.

    Thus, we are going to attempt creating two categories of games for recommendation. Our first category will be brain training games that have cognitive benefits on the five cognitive functions. These are daily exercises that may have some benefit in exercising your brain. Our second category will be games that actually teach you new information – whether its historical, mathematical, creative, etc. Ideally, these two categories would be combined. Of course, this author is no scientist, so nothing I’m saying right now can be supported by research evidence, but I imagine that it would be most beneficial to perhaps spend 30 minutes a day on brain training puzzle games, and an hour or two a day on educational games.

    Brain Games That Have Cognitive Benefits


    Happy Neuron

    Happy NeuronHappy Neuron is another set of brain training games and activities. It also focuses on the 5 cognitive functions, a personalized training program based on your individual cognitive profile, and it has a wide range of available games. HAPPYneuron was founded by, and is based on the research of, a team of neurologists and neuroscientists, led by Chief Scientific Officer Bernard Croisile, M.D., PhD, who has published over 40 peer-reviewed papers in neuroscience and neurology.

    Crosswords

    Crosswords are a fun and challenging way of exercising your brain through verbal memory. Of course, crosswords come in all difficulties – for example, US (American) crosswords are infinitely easier than British-style crosswords. While American crosswords tend to focus on themes and simple questions (Tomato-based sauce put on hamburgers?), British crosswords can come in the fiendish ‘cryptic crosswords’ variety, which are true exercises in riddle and puzzle-solving.

    Brain Age: Concentration Training

    Brain AgeThe last title in the Brain Age series for Nintendo, Brain Age: Concentration Training was published on the Nintendo 3DS in 2013 for North America, but it took 5 years to be released for the European market. The Brain Age series of games are based on the works of Ryuta Kawashima (in fact, Brain Age in Japan is called Dr. Kawashima’s Brain Training), a Japanese neuroscientist. There’s a range of activity games available, such as math problems, card matching, and other games that require concentration or memory.

    Peak

    Peak is a phone-based app which contains over 35 brain games. The games focus on areas such as memory, attention, math, problem solving, mental agility, language, coordination, and emotional control. Some of the cognitive brain training games were developed by expert researchers at institutes such as Cambridge University and NYU.

    Elevate

    ElevateYet another bundle of over 35 brain games, Elevate was chosen as the Apple App of the Year in 2014, and Google Editors’ Choice. It’s been downloaded over 15 million times since it was released. It was originally intended to be an SAT prep and language learning app, but the designer Jesse Pickard wanted his app to “help everyone in the world”. Elevate receives regular updates, and its highly reviewed by numerous news sources (CNET, Wall Street Journal, Washington Post, etc.).

    Fit Brains Trainer

    Fit Brains Trainer is an award-winning brain training and fitness app, which was originally published by Vivity Labs, before being acquired by Rosetta Stone. Rosetta Stone of course is best known for their language-learning software. The scientific aspect of Fit Brains Trainer is led by Chief Scientific Officer, Dr. Paul Nussbaum, PhD, an American clinical neuropsychologist who has published numerous books and research papers on the brain and aging.

    Cognito

    CognitoCognito offers daily brain training missions that focus on memory, logic, puzzles, word games, and other cognitive functions. Like many of the apps on this list, Cognito offers a variety of brain training games and activities, but it ties them all together with a game-like storyline that involves secret agents and global spying missions. Cognito can also connect with Apple Health, to give you additional data on your performance results, such as how your daily exercise and sleeping patterns affect your cognitive scores.

    Bookworm

    Bookworm is like a cross between Scrabble and word search puzzles. You need to make words out of lettered tiles on a board – each time you clear letters, more drop in. Word scores are based on word length and difficulty, and there are several game modes to play.

    The Room

    The roomThe Room is a popular series of “escape the room” puzzle games, where you must piece together various clues and puzzles to move onto the next room. The games are literally just an almost endless progression of rooms, with each room becoming increasingly difficult. It requires sharp logic and memory to get through all the levels.

    Dissembler

    Dissembler is more of an abstract puzzle game, which focuses on flipping tiles to match color groups. Your task is to clear all the tiles from the board, and the puzzles become increasingly complex, to the point that strategic planning and lateral thinking becomes a must.

    Brain It On

    brain it onBrain It On is a fun series of physics-based puzzles which require you to draw on your screen to complete the puzzles. You’ll be given an objective like “flip the glass upside down”, and must draw an object that will fall down and set off the proper chain reaction of physics. There are numerous ways to approach and solve each puzzle, so it heightens your creative thinking as well as your strategic planning.

    Bejeweled

    The classic match-3 game is still one of the most addicting experiences, especially with its spin-offs Bejeweled Twist and Bejeweled Blitz. It offers numerous game modes, such as Lightning Mode where you must match as many gems as possible in a minute, or Zen Mode where the game simply plays relaxing, meditative music and just play as long as you like.

    Words with Friends 2

    Words with friendsIf you’d like to train your brain and be competitive with friends, Words with Friends 2 is a sure bet. Its basically an online Scrabble-like game, with numerous gameplay modes. Scrabble is one of the best games for brain flexibility, memory, and vocabulary expansion, so Words with Friends 2 brings all those brain-training benefits into an online platform.

    Mahjong Games

    These are classic games of an ancient Chinese origin, and have truly lasted the test of time! Mahjong games are brain-teasing tile based games, which were originally developed during the Chinese Xing dynasty. They required skill, strategy and patience.

    Games In a Box

    This is a wonderful collection of 14 different logic and puzzle based games aimed at improving logic, counting, memory and attention. They include some more classical brain game variations such as dominoes, spot the difference, sequences and more. There’s something basic and easy here for everyone to enjoy, and it doesn’t require a large commitment to get into.

    Games That Actively Teach New Information


    Civilization 5

    If you love strategy games and want to learn a great bit of history, Civilization 5 should be right up your alley. It is one of the most addictive turn-based strategy games, where you control one of 43 real-life civilizations, and compete on large maps for resources and global dominance. The educational benefits come from just how amazingly historically accurate and informative Civilization 5 is, with an in-game encyclopedia that offers huge amounts of information on each civilization.

    Crusader Kings II

    Another awesome strategy game with a strong focus on historical accuracy, Crusader Kings II takes you through the middle ages as you control a Medieval dynasty from 1066 to 1453 AD. The game is able to teach you a lot of geography, important historical dates, and has links to Wikipedia pages for many of the historical figures featured in the game.

    CodeMonkey

    If you want to learn how to code while playing online games, CodeMonkey offers a handful of educational courses designed as games. You will learn how to code in CoffeeScript, which basically compiles into JavaScript. From there, you can get into HTML5, and you’ll be basically learning how to create a wide range of web applications and games, while playing games!

    MindSnacks

    For learning new languages, you should have plenty of fun with MindSnacks series of games, which are offered in a variety of languages. MindSnacks games offer to teach you Spanish, French, Italian, Portuguese, German, Chinese, and Japanese. The games offer much more than just basic word memory similar to flashcard language learning. You will be playing a wide variety of games designed to build vocabulary, boost conversational skills, and teach useful little nuances of the various languages.

    Learn with Lingo Arcade

    Another great language-learning series of games, Learn with Lingo Arcade offers versions in Spanish, English, French, and German. Each version of the Learn with Lingo Arcade app comes with four games and five difficulty settings, all designed to help you improve beyond basic vocabulary in the chosen language.

    Influent

    Influent is a computer video game and language learning tool that offers a huge list of different languages to learn. Its not so much a “video game” per se in that is has a plot – basically, you can freely navigate a 3D environment, and click on pretty much every object in the various rooms throughout a large house.

    The objects will then be translated and spoken to you. For example, you can click on a cabinet in the kitchen to open it, then click on each household item in the cabinet to learn the appropriate word in the chosen language. Influent currently offers Japanese, European Portuguese, Finnish, Danish, Norwegian, Brazilian Portuguese, Italian, Russian, Latin, Bulgarian, Korean, German, Swedish, Spanish, French, English, Mandarin Chinese, and Hindi, with more languages being added in future updates.

    Flight Simulator

    Want to learn how to fly a plane? Of course you do! Flight Simulator can actually really teach you how to fly a plane. Well, sort of. You won’t exactly be able to hop into an airplane’s cockpit and take control of the craft after a few hours in Flight Simulator, but the software is used by numerous flight schools as a training supplement to real-life practice.

    Minecraft

    Minecraft may appear as a block-building game on the surface, but its so much deeper. Minecraft can actually teach you the very real fundamentals of engineering, and even a bit of scripting. There’s also a ton of game modifications available, some of which are used in real educational scenarios.

    A mod known as Polycraft World, for example, was designed by Professor Walter Voit of the mechanical engineering department of the University of Texas at Dallas, to teach his students about harvesting and mixing various chemical ingredients. Many classroom teachers also use Minecraft: Education Edition, which includes a huge range of topics including gravity, quantum mechanics, and coding.

    Rocksmith

    Listening to music has its own benefits on the brain, but learning how to play an instrument? That unleashes a whole new potential of brain creativity. Rocksmith is a video game that literally teaches you how to play guitar, using a real guitar. You connect a guitar to the game via a special cable, and the game has a huge library of licensed songs that you can learn to play in real-time. It’s a fantastic video game for beginner and expert guitarists alike.

    Kerbal Space Program

    Kerbal Space Program is a space flight simulation game, and it is incredibly realistic and educational. Your objective is to construct a fully functional spaceport, and launch rocket ships. Of course, building a rocket ship is no easy task, or aerospace engineers wouldn’t earn so much money in real life.
    So of course, you need to consider things like fuel usage, trajectory paths, sufficient thrust, gravity, orbital dynamics, Newtonian dynamics, and all the other little nuances that go into successful rocket ship launches. Kerbal Space Program has been highly praised for its realistic approach to physics, and thus its not only an incredibly fun game, it’s a wonderful educational tool for anyone interested in aerospace engineering.

    VR Games: Can They Be Used as Well?

    One interesting thing to think about, since we’ve mostly covered typical brain-training apps and computer games, is the applications of VR (virtual reality) in the fight against dementia. In fact, scientists and VR developers have already been hard at work on this exact topic, and it turns out that VR experiences can be used as a calming, distractive technique for altering the mood levels of patients suffering from dementia.

    Furthermore, a team of scientists in Germany published a study, where they used a virtual-reality based maze to help detect Alzheimer’s. Based on how the test subjects navigated through the maze, they were able to successfully identify which subjects had genetic markers for Alzheimer’s.

    The future of VR, brain-training, and dementia prevention could be closely linked together, if this is any indication.

  • Developer Portal off with a Crazy start!

    |

    On the first of October CrazyGames launched a public beta version of its developer portal. The goal was to increase and intensify cooperations with developers. Many new developers signed up for different reasons. In this blog, we’ll discuss the two main reasons and evaluate the first two months.

    The launch of the developer portal has been a great success. During the first two months, more than 50 new developers signed up bringing the total active developers to 95. Together they uploaded 175 games and earned over 30K euro. We see that developers publish their games for two main reasons.

    1. CrazyGames reaches a really big audience and high-quality games get a lot of plays. Monetizing these plays can earn developers a substantial amount. Most successful games have intuitive interfaces, crisp visuals, and a great gameplay.
    2. Developers use CrazyGames to get an initial audience for their games and get audience feedback. They use this feedback to learn what works and what doesn’t so that they can improve the game.

    High revenue during the first months

    Most of the published games were eligible for revenue share. Over the past two months, developers earned about 30K with their games. November has always been an excellent month for advertisers due to events like Black Friday and Cyber Monday. But this year CPM’s where 23% higher than November 2017. The main reason for this is the continuous development of our Smart Advertising Layer.

    CrazyGames worked hard to create an optimal setup for display advertising. We called this setup the Smart Advertising Layer. It enables competition between multiple of the world’s biggest advertising players like Google, Amazon, etc. Recently we also started a cooperation with two new video partners. This will increase the demand for video ads and therefore increase fill rates and revenues. We plan to implement the Smart Advertising Layer for video ads in the near future.

    Whether developers can enjoy this last benefit depends on them. To request video ads in games, developers must implement the CrazyGames SDK. It’s only a little effort knowing that it can increase the revenue of a game by 70%! What’s more is that the SDK also includes a sidelock to prevent dubious sites from stealing the games.

    Looking for an initial audience

    Many of the developers use the services of CrazyGames in search for an initial audience. About 30% of the games are prototypes. Creating a web prototype and uploading it on CrazyGames provides developers with an immediate test of how the audience perceives the game. Every new game is given a trial of 48 hours on the homepage and therefore seen by 10 million CrazyGames users. After a few days, the ranking is purely based on performance parameters like plays/day, retention rate,… This is what makes our ranking system very different from others. CrazyGames doesn’t offer “pay-to-feature” options. We firmly believe only our players know best.

    At the moment the developer portal offers some insights into the game statistics under the tap “game stats” like new players, playtime and total players. In 2019 we plan to include many other statistics that help developers improve their games and even give concrete tips on how to create better games.

    Conclusion

    The two main reasons developers upload games on the portal are first and foremost to use the CrazyGames monetization strategy. Other developers upload games to assemble audience feedback when testing ideas. The first two months have proven to be successful and with new features on the way in 2019, we hope to increase the value of the portal for our developers.

  • Sokoban Series: Part 5, Publishing your Game

    |

    After spending too many hours of your free time on creating a game you want people to play and enjoy it. Next to that, you also want to earn a bit of money from your game. CrazyGames has a Developer Portal that enables you to upload a game, and if there are no problems get it published within a couple of days.

    You automatically get part of the revenue that is made from advertisements on your game page, even without having any kind of advertisement in your game. You can increase the revenue share by letting CrazyGames have exclusive rights for the first couple of weeks of your game, by incorporating the logo in your game etc.
    The only minimum requirement for revenue share is that your game is not published anywhere else, and does not contain branding of a competing portal.

    It is also interesting for larger games that aim to release on Steam: you can submit an early version of your game, see what parts users like and dislike, while already earning some money. You can update your game after it has been released. And, you can choose to take down your game at any time; you remain the owner of your game.

    The upload process is fairly short. You fill in the basic information of your game, upload your game files, configure the revenue share options and you are done.

    game files

    revenue share

    You can immediately preview your game using using the Preview tool. This shows you what your game will approximately look like on CrazyGames. It also helps you to catch some final mistakes. You can update your game files at any point in time.

    preview

    Integrating Advertisements

    In case you want to increase the revenue from your game you can integrate advertisements into your game. CrazyGames provides an SDK that facilitates this process.

    The SDK comes with detailed instructions on how to install and use it.

    Installation

    Installing the SDK is done by including <script src="https://sdk.crazygames.com/crazygames-sdk-v1.js"></script> in your index.html. This installs the SDK under window.CrazyGames. The SDK requires that you use the game loader of CrazyGames: this is the loader that wraps your game, adds a full screen button, adds links to the Play store if your game is on it etc. It also contains the logic of requesting and displaying advertisements. The SDK comes with an HTML file that wraps your index.html. Just test your game by going to localhost/sdk.html instead of localhost/index.html.

    Setup of the SDK

    We instantiate the SDK in our init() function. The SDK is implemented using a singleton pattern, and you get an instance by calling getInstance().
    After this we make a call to sdk.init() which initializes the SDK. The SDK communicates through events to let you know the state of a requested advertisement.

    There are three kinds of events:

    • adStarted: fired when the advertisement starts playing. You should mute any music, and ensure that the game is not continuing playing
    • adFinished: fired when the advertisement finished playing. Resume your game.
    • adError: fired whenever some error occured, or when no advertisement is available. Continue with your game.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    class LevelScene extends Phaser.Scene {
    // ads
    private sdk: any;
    private adRequested: boolean;

    init() {
    const { SDK } = (window as any).CrazyGames;
    this.sdk = SDK.getInstance();
    this.sdk.init();
    this.installListeners();
    }

    private installListeners() {
    this.sdk.addEventListener('adStarted', this.adStarted);
    this.sdk.addEventListener('adError', this.adError);
    this.sdk.addEventListener('adFinished', this.adFinished);
    }

    private adStarted = () => {
    this.sound.mute = true;
    }

    private adError = () => {
    this.sound.mute = false;
    this.adRequested = false;
    }

    private adFinished = () => {
    this.sound.mute = false;
    this.adRequested = false;
    }
    }

    Requesting an Advertisement

    We have installed the necessary event listeners, but still need to request an advertisement. We want to do this at the time where it annoys the user the least. We do it whenever we start a level. The SDK will automatically limit the number of advertisements that are displayed, so even when a user quickly finishes a level he won’t see to many advertisements.

    We place the call to requestAd() in the preload() function, so that the ad plays while other assets are loaded in the background. An advertisement is played
    as an overlay, so your game still runs in the background. As long as an advertisement is requested or playing we disable user interaction, simply by returning early from the update loop.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    class LevelScene extends Phaser.Scene {
    preload() {
    this.requestAd();
    // load other assets if needed
    }

    update() {
    if (this.adRequested) {
    return;
    }
    // normal update logic here
    }

    private requestAd() {
    this.adRequested = true;
    this.sdk.requestAd();
    }
    }

    And that is all you need to do to get advertisements up and running.

    Sitelocking your Game

    Games can get copied and distributed to other platforms without your permission, and it is difficult to enforce to take down your game from a platform.
    What we can do is obfuscate our code and install a sitelock into the game that freezes your game when it runs on a disallowed domain.

    We will make use of obfuscator.io: they provide a specialized tool to obfuscate and sitelock your code, and there is no need to reinvent the wheel. They surely do a better job than we can do ourselves, and having an easy to remove sitelock check is almost useless. Don’t forget that people can always download your code, and just remove the sitelock code. We enable our game to run on the following domains: .crazygames.com, .gioca.re, .1001juegos.com, .onlinegame.co.id, .speelspelletjes.nl and localhost. These are all the domains affiliated with CrazyGames, and of course localhost so we can still test it locally.

    We install java-obfuscator as a dev-dependency (npm install -D javascript-obfuscator), and create a new build task in our package.json:

    1
    2
    3
    "scripts": {
    "obfuscate": "webpack --mode production && npx javascript-obfuscator build/bundle.js --output build/obfuscated.js --compact true --domain-lock '.crazygames.com, .gioca.re, .1001juegos.com, .onlinegame.co.id, .speelspelletjes.nl, localhost'"
    }

    This will build our game and then obfuscate our game bundle. One downside of obfuscating the code is that it can have an impact on performance. For sokoban this is not a problem as the game is not very resource intensive, but may be a problem for more complex games. We obfuscate everything: Phaser, React and our game. One solution would be to only obfuscate some of your game logic, and make a bundle using that code.

    You can always use the online interface on obfuscator.io to sitelock your game. Automating the task is easier though; you will surely update your game, apply some bug fixes or add new content. Automating the job costs a bit more time in the beginning, but quickly pays of. And of course make sure to upload the obfuscated code, and not the original file :).

    Conclusion

    We discussed how you can publish your game on CrazyGames, and how to integrate advertisement in between your levels to increase your revenue. Even if you do not do this last step you still get revenue from the advertisement on CrazyGames itself. Finally, we showed how you can protect your game from being stolen and being hosted without your permission.

    Here are the other parts of this series:

  • Sokoban Series: Part 4, Creating an Overlay in React

    |

    In this part of our Sokoban Series we will create an overlay for our game. The overlay contains our menu in which the user can select different levels, and a volume control. The end result looks like this:

    overlay

    We tried making a simple menu in Phaser, but we found that Phaser is not suited to do this in a straight-forward manner. It would take us a lot less work in simple HTML, so that’s what we did.

    Enter React and material-ui. React is a JS library to create user interfaces. Material-UI provide react components that implemnet Google’s Material Design, and that simply look a lot better than I can design myself. We will not explain React in this post, that could be a whole book on its own. We focus on how you can communicate with your Phaser game from outside of Phaser.

    So let’s hook React and Material-UI up to our Phaser game. Phaser itself is also just Javascript. So, we want to create a React app that renders a DOM, and in that DOM will be our Phaser game.

    We create a React Component that renders a container for our game, and that creates our game in componentDidMount(). componenDidMount is the earliest point in which we are sure that our game div exists.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    import * as React from 'react';
    import { createGame } from '../core/game';

    class GameContainer extends React.Component<{}> {
    constructor(props: {}) {
    super(props);
    }

    componentDidMount() {
    createGame();
    }

    render() {
    return (
    <div id="game" />
    )
    }
    }

    export default GameContainer;

    The function createGame() simply calls the constructor of our Game class.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    export class Game extends Phaser.Game {
    constructor(conf: GameConfig) {
    super(conf);
    }
    }

    let game: Game;
    export function createGame() {
    game = new Game(config);
    }

    export function getGame(): Game {
    return game;
    }

    That’s all we had to do. Of course we must be careful that our GameContainer is always present in our React application, if not it will be unmounted, and our game would get destroyed. To this end, we render the overlay on top of the game. The game will still be available in the DOM, it will just be hidden behind an overlay.

    What are the components our overlay and menu needs:

    • A way to open the menu
    • A way to select and load a level
    • A way to control the volume

    Let’s start with the volume control. We want to have a component that, when clicked opens a slider. The slider indicates the current volume, and when slidered (yes, that’s a word from now on) it changes the volume of our game. As Phaser is simple JS, we can also call function from “outside” Phaser. By accessing our game we can
    simple access the sound.volume and modify it:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    import * as React from 'react';
    import { getGame } from '../core/game';

    import VolumeMuteIcon from '@material-ui/icons/VolumeMute';
    import VolumeDownIcon from '@material-ui/icons/VolumeDown';
    import VolumeUpIcon from '@material-ui/icons/VolumeUp';
    import VolumeOffIcon from '@material-ui/icons/VolumeOff';
    import IconButton from '@material-ui/core/IconButton';
    import Slider from '@material-ui/lab/Slider';
    import { Grid, Icon, ClickAwayListener } from '@material-ui/core';

    export interface VolumeControlState {
    isOpen: boolean;
    volume: number;
    isMuted: boolean;
    }

    export interface VolumeControlProps {

    }

    class VolumeControl extends React.Component<VolumeControlProps, VolumeControlState> {
    constructor(props: VolumeControlProps) {
    super(props);
    this.state = {
    volume: getGame().sound.volume,
    isMuted: getGame().sound.mute,
    isOpen: false,
    }
    }

    render() {
    const { isOpen } = this.state;
    return (
    <Grid container alignItems="center" style={{ minWidth: '200px' }} alignContent="flex-end">
    <Grid item>
    <IconButton onClick={this.iconClicked}>
    {this.renderIcon()}
    </IconButton>
    </Grid>
    {
    isOpen &&
    <Grid item style={{ flex: 1 }}>
    {this.renderSlider()}
    </Grid>
    }
    </Grid>
    );
    }

    private iconClicked = (event: React.MouseEvent) => {
    this.setState({
    isOpen: !this.state.isOpen,
    })
    }

    private unMute() {
    this.setState({
    isMuted: false,
    });
    getGame().sound.mute = false;
    }

    private renderSlider() {
    const { volume } = this.state;
    return (
    <Slider value={volume * 100} onChange={this.volumeChange} />
    )
    }

    private volumeChange = (event: React.ChangeEvent, value: number) => {
    const actualVolume = value / 100;
    this.setState({
    volume: actualVolume
    });
    this.unMute();
    getGame().sound.volume = actualVolume;
    }

    private renderIcon() {
    const { isMuted, volume } = this.state;
    if (isMuted) {
    return this.renderMuted();
    }
    if (volume === 0) {
    return this.renderVolumeOff();
    }
    if (volume < 0.5) {
    return this.renderLowVolume();
    }
    return this.renderVolume();
    }

    private renderMuted() {
    return <VolumeMuteIcon />;
    }

    private renderLowVolume() {
    return <VolumeDownIcon />;
    }

    private renderVolumeOff() {
    return <VolumeOffIcon />;
    }

    private renderVolume() {
    return <VolumeUpIcon />
    }
    }

    export default VolumeControl;

    Next, let’s create a LoadLevel component that renders a thumbnail of each level, and that when clicks loads that level. All of our levels are stored in a JSON that is loaded inside Phaser. We can also access the cache of Phaser from outside. Simply get the intance of your game and call .cache, and you can get all your loaded resources.

    The following component renders a grid with LevelTiles. The LevelTile itself simply renders a thumbnail of the level, the name of the level etc. You can export a thumbnail of a map in the Tiled map editor.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    import * as React from 'react';
    import Grid from '@material-ui/core/Grid';
    import LevelTile from './LevelTile';
    import { getGame } from '../core/game';
    import sortLevels from '../core/utils/sortLevels';

    export interface LoadLevelProps {
    onSelected: (level: string) => void;
    }

    class LoadLevel extends React.Component<LoadLevelProps, {}> {
    constructor(props: LoadLevelProps) {
    super(props);
    }

    render() {
    return (
    <Grid container={true} spacing={8} justify="center">
    {this.renderLevelTiles()}
    </Grid>
    );
    }

    private renderLevelTiles() {
    const levels = getGame().cache.json.get('levels').levels;
    const sorted = sortLevels(levels);
    return sorted.map((level) => {
    return (
    <Grid item key={level.file}>
    <LevelTile level={level} onClick={this.onClick} />
    </Grid>
    );
    })
    }

    private onClick = (id: string) => {
    const { onSelected } = this.props;
    onSelected(id);
    }
    }

    export default LoadLevel;

    We now have the main components for our overlay. Let’s create our main menu that is rendered on top of our game:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    import * as React from 'react';
    import Toolbar from '@material-ui/core/Toolbar';
    import MenuIcon from '@material-ui/icons/Menu';
    import IconButton from '@material-ui/core/IconButton';
    import LoadLevel from './LoadLevel';
    import Dialog from '@material-ui/core/Dialog';
    import CloseIcon from '@material-ui/icons/Close';
    import Typography from '@material-ui/core/Typography';
    import { loadLevel, getGame } from '../core/game';
    import VolumeControl from './VolumeControl';
    import { Grid } from '@material-ui/core';

    export interface MenuState {
    isOpen: boolean;
    }

    class MainMenu extends React.Component<{}, MenuState> {
    constructor(props: {}) {
    super(props);
    this.state = {
    isOpen: false,
    }
    }

    render() {
    return (
    <div className="menu">
    <Toolbar>
    <Grid container alignItems="center">
    <Grid item xs={2}>
    {this.renderHamburger()}
    </Grid>
    <Grid item xs={10}>
    {this.renderVolume()}
    </Grid>
    </Grid>
    </Toolbar>
    {this.renderMenu()}
    </div>
    )
    }

    private renderHamburger() {
    return (
    <IconButton onClick={this.toggleOpen}>
    <MenuIcon />
    </IconButton>
    );
    }

    private renderVolume() {
    return <VolumeControl />;
    }

    private renderMenu() {
    const { isOpen } = this.state;
    return (
    <Dialog fullScreen={true} open={isOpen} onClose={this.close}>
    <Toolbar>
    <IconButton color="inherit" onClick={this.close} aria-label="Close">
    <CloseIcon />
    </IconButton>
    <Typography variant="title">Select Level</Typography>
    </Toolbar>
    <LoadLevel onSelected={this.levelSelected} />
    </Dialog>
    );
    }

    private toggleOpen = () => {
    this.setState({ isOpen: !this.state.isOpen });
    }

    private close = () => {
    this.setState({ isOpen: false });
    }

    private levelSelected = (level: string) => {
    this.close();
    loadLevel(level);
    }
    }

    export default MainMenu;

    The final part is ensuring that our Menu is rendered above the game. We use CSS to achieve this:

    1
    2
    3
    4
    5
    6
    .menu {
    position: absolute;
    top: 0;
    left: 0;
    z-index: 1;
    }

    We enforce that our overlay is always rendered on a fixed position, and by using a higher z-index than our game it is rendered above our game.

    Conclusion

    In my opinion Phaser is ill suited to render complex interactive user interfaces. The DOM-tree is made specifically to create such interfaces, so I prefer to use that. In this episode we combined React with Material-UI to render a menu on top of our game. As Phaser is, in the end, simply Javascript interacting with your game from ‘the outside world’ is not that hard.

    This completes our game. The only thing left to do is to publish our game. We will show you how to publish your game on CrazyGames in the next episode.

  • Sokoban Series: Part 3, Handling Input and Game Logic

    |

    In this episode we will handle keyboard and touch input to move our player through the world. We will add the game logic that checks for valid moves and that verifies whether the win condition was met.

    Input

    We want to add two kinds of input: keyboard input for desktop users, and touch input for mobile users.

    We will start with keyboard input:

    Keyboard Input

    There are two ways to control the player character: either you move him around using the arrow keys, or alternatively you move around using WASD. French keyboards have an azerty layout, and would move around using ZQSD. As far as I know, there is no way to know the keyboard layout of the player. Luckily, as we only need these four keys, we can just let the player move forward using either Z or W, and move left using either Q or A. For other games this approach may not be viable.

    We create a function getPlayerDirection() that returns either the direction our player’s character must move to, or null when no key was touched. Here is the code:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    export type PlayerDirection = 'playerLeft' | 'playerRight' | 'playerUp' | 'playerDown';

    class LevelScene extends Phaser.Scene {
    private leftKeys: Phaser.Input.Keyboard.Key[];
    private rightKeys: Phaser.Input.Keyboard.Key[];
    private upKeys: Phaser.Input.Keyboard.Key[];
    private downKeys: Phaser.Input.Keyboard.Key[];

    private createInputHandler() {
    this.leftKeys = [Phaser.Input.Keyboard.KeyCodes.LEFT, Phaser.Input.Keyboard.KeyCodes.A, Phaser.Input.Keyboard.KeyCodes.Q].map((key) => {
    return this.input.keyboard.addKey(key);
    });
    this.rightKeys = [Phaser.Input.Keyboard.KeyCodes.RIGHT, Phaser.Input.Keyboard.KeyCodes.D].map((key) => {
    return this.input.keyboard.addKey(key);
    });
    this.upKeys = [Phaser.Input.Keyboard.KeyCodes.UP, Phaser.Input.Keyboard.KeyCodes.W, Phaser.Input.Keyboard.KeyCodes.Z].map((key) => {
    return this.input.keyboard.addKey(key);
    });
    this.downKeys = [Phaser.Input.Keyboard.KeyCodes.DOWN, Phaser.Input.Keyboard.KeyCodes.S].map((key) => {
    return this.input.keyboard.addKey(key);
    });
    }

    private getPlayerDirection(): PlayerDirection | null {
    if (this.leftKeys.some((key) => key.isDown)) {
    return 'playerLeft';
    }
    if (this.rightKeys.some((key) => key.isDown)) {
    return 'playerRight';
    }

    if (this.upKeys.some((key) => key.isDown)) {
    return 'playerUp';
    }
    if (this.downKeys.some((key) => key.isDown)) {
    return 'playerDown';
    }
    return null;
    }
    }

    The handling of keyboard input is well documented in Phaser, and you can find plenty of examples on their example page. Mobile input is trickier, and will be discussed next.

    Touch Input

    For mobile we want the user to move the ingame character by tapping the screen. We have two options.

    • The first option is to move the character by tapping the sides of the scree. So when the user taps the top of the screen the player moves up, left to move left etc.
    • The second option was to have movement relative to the position of the player. So when the user taps to the left of the player’s character, he moves left.

    The first version of our game implemented the first option, but users preferred relative movement as it felt more natural. One of the parts that was difficult to get right with the first option was to find a cutoff that felt natural. What happens when a user presses the center of the screen? What happens when you press the topleft corner of the screen? In our opinion there is no correct answer, and it just shows that this option for movement is not the correct on. It was also hard to get the boundaries right for different screen sizes.

    This is the code for the first option:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    class LevelScene extends Phaser.Scene {
    private getDirectionFromInput(currentTime: number): PlayerDirection {
    const bounds = this.physics.world.bounds;
    const pointer = this.input.pointer1;
    const isHorizontalCentered = pointer.x > bounds.right / 4 && pointer.x < bounds.right * 3 / 4;
    const isLeft = pointer.x < bounds.left + WIDTH / 3;
    const isRight = pointer.x > bounds.right - WIDTH / 4;
    const isTop = pointer.y < bounds.top + HEIGHT / 2;
    const isBottom = pointer.y > bounds.bottom - HEIGHT / 2;
    if (isLeft && isVerticalCentered) {
    return 'playerLeft';
    }
    if (isRight && isVerticalCentered) {
    return 'playerRight';
    }
    if (isTop && isHorizontalCentered) {
    return 'playerUp';
    }
    if (isBottom && isHorizontalCentered) {
    return 'playerDown';
    }
    return null;
    }
    }

    The better way is to have movement relative to the player position. We just need to compute the angle between the location of the player and the location of the pointer. You can use Phaser.Math.Angle to compute the angle between two points. We then move the player right when the angle is between +45 degrees and -45 degrees, up when it is between +45 and +135 degrees etc. To ensure we get angles between 0 and Math.PI * 2 you can use Phaser.Math.Angle.Normalize.

    There is still one tricky part. Remember that we centered the playing field in our canvas. Thus, when we ask the coordinates of our player, we get the in-game coordinate, but not the one that is rendered on screen. The touch input on the other hand returns on-screen coordinates. Luckily, you can use
    camera.getWorldPoint(x,y) to convert screen coordinates to world coordinates. A second mistake we made is that in classic mathematics the y-axis goes upwards, while the in-game y-axis goes down. A simple mistake that did cost us a head scratch :)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    class LevelScene extends Phaser.Scene {
    private getDirectionFromInput(currentTime: number): PlayerDirection {
    const pointer = this.input.pointer1;

    if (!pointer.isDown) {
    return null;
    }

    // we want users to press for every movement, and not keep their finger down
    if (currentTime - pointer.downTime > 400) {
    return null;
    }

    const playerCenter = this.player.getCenter();
    const pointerWorld = this.cameras.main.getWorldPoint(pointer.x, pointer.y);
    const angle = Phaser.Math.Angle.Normalize(Phaser.Math.Angle.Between(playerCenter.x, playerCenter.y, pointerWorld.x, pointerWorld.y, ));
    const quarter = Math.PI / 4;
    if (angle < quarter || angle >= (Math.PI + quarter * 3)) {
    return 'playerRight';
    }
    if (angle >= quarter && angle < quarter * 3) {
    return 'playerDown';
    }
    if (angle >= quarter * 3 && angle < quarter * 5) {
    return 'playerLeft';
    }
    if (angle >= quarter * 5 && angle < Math.PI + quarter * 3) {
    return 'playerUp';
    }
    return null;
    }
    }

    Game Logic

    Now that we have input we need to define the game logic. In theory we could do this using the physics system of Phaser: we can define collisions between the player and a crate, and let the player move the crates in this manner. The downside of this approach is that players need pixel perfect precision to place their crates, or they will become stuck behind walls.

    Given that the gameplay of Sokoban is so simple we can just implement everything ourselves without using the physics system.

    What are the things we need to do?

    • We need to check whether a square is free. A square is free when it is within bounds, does not contain a wall and does not contain a crate.
      This is needed to check whether our player can move to that location, or whether a crate can be moved to that location.
    • We need to check whether a crate can be moved to the next tile, and what the next tile is.
    • Do the actual moving of the player and the crate.

    So first let’s write a helper function getCrateAt(tileX, tileY) that returns the crate at the given position, or null when no crate is on that location. Keep in mind that our crates are represented using coordinates, while a tilemap refers to tile numbers. Luckily, you can simply use tileToWorldXY() to convert coordinates to a tile.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    class LevelScene extends Phaser.Scene {
    private getCrateAt(tileX: number, tileY: number): Crate | null {
    const allCrates = this.crates.getChildren() as Crate[];
    const { x, y } = this.tileMap.tileToWorldXY(tileX, tileY);
    const crateAtLocation = allCrates.filter((crate) => {
    return crate.x === x && crate.y === y;
    });
    if (crateAtLocation.length === 0) {
    return null;
    }
    return crateAtLocation[0];
    }
    }

    Next, let’s write checkIfLocationIsFree(tileX, tileY):

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    class LevelScene extends Phaser.Scene {
    private checkIfLocationIsFree(tileX: number, tileY: number): boolean {
    if (tileX < 0 || tileX >= this.tileMap.width || tileY < 0 || tileY >= this.tileMap.height) {
    return false;
    }
    const hasWall = !!this.wallLayer.getTileAt(tileX, tileY);
    if (hasWall) {
    return false;
    }
    const crate = this.getCrateAt(tileX, tileY);
    return !crate;
    }
    }

    We need to check ‘the next tile’ at several loations:

    • Whenever a player moves we need to know what his target tile will be,
    • Whenever a crate is moved we need to to see whether the next location is free.

    To facilitate this we create getNextTile(startTile, direction, layer) that gets the next tile of startTile based on direction:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    class LevelScene extends Phaser.Scene {
    private getNextTile(
    start: Phaser.Tilemaps.Tile,
    direction: PlayerDirection,
    layer: Phaser.Tilemaps.DynamicTilemapLayer | Phaser.Tilemaps.StaticTilemapLayer,
    ): Phaser.Tilemaps.Tile {
    const { x, y } = start;
    switch (direction) {
    case 'playerDown':
    return layer.getTileAt(x, y + 1);
    case 'playerUp':
    return layer.getTileAt(x, y - 1);
    case 'playerLeft':
    return layer.getTileAt(x - 1, y);
    case 'playerRight':
    return layer.getTileAt(x + 1, y);
    default:
    throw new Error('Unexpected direction');
    }
    }
    }

    Let’s add everything together, and create our movement logic:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    class LevelScene extends Phaser.Scene {
    private updatePlayer(direction: PlayerDirection | null) {
    if (!direction) {
    return;
    }
    this.troToMovePlayer(direction);
    }

    private troToMovePlayer(direction: PlayerDirection) {
    const { x, y } = this.player;
    const currentTile = this.tileMap.getTileAtWorldXY(x, y, true);
    const wall = this.getNextTile(currentTile, direction, this.wallLayer, true);
    if (!wall) { // out of bounds
    return;
    }
    if (wall.index > -1) {
    return;
    }
    const floor = this.getNextTile(currentTile, direction, this.floorLayer);
    const crate = this.getCrateAt(wall.x, wall.y);

    if (crate) {
    const oneFurther = this.getNextTile(wall, direction, this.floorLayer);
    if (!oneFurther.index < 0) { // out of bounds
    return false;
    }
    if (!this.checkIfLocationIsFree(oneFurther.x, oneFurther.y)) {
    return false;
    }
    }
    this.movePlayer(wall.x, wall.y);
    }

    private checkIfLocationIsFree(tileX: number, tileY: number): boolean {
    if (tileX < 0 || tileX >= this.tileMap.width || tileY < 0 || tileY >= this.tileMap.height) {
    return false;
    }
    const hasWall = !!this.wallLayer.getTileAt(tileX, tileY);
    if (hasWall) {
    return false;
    }
    const crate = this.getCrateAt(tileX, tileY);
    return !crate;
    }

    private getCrateAt(tileX: number, tileY: number): Crate | null {
    const allCrates = this.crates.getChildren() as Crate[];
    const { x, y } = this.tileMap.tileToWorldXY(tileX, tileY);
    const crateAtNewLocation = allCrates.filter((crate) => {
    return crate.x === x && crate.y === y;
    });
    if (crateAtNewLocation.length === 0) {
    return null;
    }
    return crateAtNewLocation[0];
    }

    private getNextTile(
    start: Phaser.Tilemaps.Tile,
    direction: PlayerDirection,
    layer: Phaser.Tilemaps.DynamicTilemapLayer | Phaser.Tilemaps.StaticTilemapLayer,
    ): Phaser.Tilemaps.Tile {
    const { x, y } = start;
    switch (direction) {
    case 'playerDown':
    return layer.getTileAt(x, y + 1);
    case 'playerUp':
    return layer.getTileAt(x, y - 1);
    case 'playerLeft':
    return layer.getTileAt(x - 1, y);
    case 'playerRight':
    return layer.getTileAt(x + 1, y);
    default:
    throw new Error('Unexpected direction');
    }
    }

    private movePlayer(tileX: number, tileY: number) {
    const { x, y } = this.tileMap.tileToWorldXY(tileX, tileY);
    const crate = this.getCrateAt(tileX, tileY);
    if (crate) {
    // not the prettiest way, we simply move the crate along the same direction
    // knowing that the next spot is available
    const crateX = crate.x + x - this.player.x;
    const crateY = crate.y + y - this.player.y;
    const newTile = this.floorLayer.getTileAtWorldXY(crateX, crateY);
    crate.moveTo(crateX, crateY, newTile);
    }
    this.player.moveTo(x, y);
    }
    }

    Next, we implement our Player moveTo(). We use animations to let our character move, and use a tween to move our player naturally. By using the onComplete handler we keep track of whether our playing is still moving or not.

    The code to move a crate is done in a similar fashion.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    class Player extends Phaser.GameObjects.Sprite {
    moveTo(newX: number, newY: number) {
    const direction = this.getDirection(newX, newY);
    if (!direction) {
    return;
    }
    this.state = 'moving';
    this.scene.tweens.add({
    targets: this,
    x: newX,
    y: newY,
    duration: GAME_SPEED,
    onStart: this.onMoveStart,
    onStartParams: [direction],
    onComplete: this.onMoveComplete,
    });
    }

    private onMoveStart = (tween: Phaser.Tweens.Tween, object: Phaser.GameObjects.GameObject, direction: PlayerDirection) => {
    this.state = 'moving';
    this.anims.play(direction);

    if (this.idleTimer) {
    this.idleTimer.destroy();
    }
    }

    private onMoveComplete = () => {
    this.state = 'standing';
    this.anims.stop();

    // in the final version we have undos and restarts that destroys our player
    // this check ensures that the callback doesnt crash
    if (!this.scene) {
    return;
    }

    // reset player to start frame after movement is complete
    this.idleTimer = this.scene.time.delayedCall(500, () => {
    this.setFrame(START_FRAME);
    this.idleTimer = null;
    }, [], this);
    }

    private getDirection(newX: number, newY: number): PlayerDirection | null {
    if (newX > this.x) {
    return 'playerRight';
    }
    if (newX < this.x) {
    return 'playerLeft';
    }
    if (newY > this.y) {
    return 'playerDown';
    }
    if (newY < this.y) {
    return 'playerUp';
    }
    return null;
    }

    Game Finished Logic

    The final functionality we need to implement is the check whether the game is complete. We check that every goal has a crate. However, we implemented this in an illogical fashion: instead of looping over all the goals we loop over all the crates, and ensure that the number of crates in the right position matches the number of goals. Looking back, looping over the goals is a lot more logical, but we never got around to rewrite it.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    class LevelScene extends Phaser.Scene {
    private hasPlayerWon(): boolean {
    return this.allCratesInCorrectLocation();
    }

    private allCratesInCorrectLocation(): boolean {
    const crates = this.crates.getChildren() as Crate[];
    const inCorrectLocation = crates.filter((crate) => {
    const goal = this.goalLayer.getTileAtWorldXY(crate.x, crate.y);
    if (!goal) {
    return false;
    }
    return crate.onCorrectLocation(goal);
    });
    const goalTiles = this.getTiles((tile) => {
    return tile.index > 1;
    }, this.goalLayer);
    return inCorrectLocation.length === goalTiles.length;
    }
    }

    The crate.onCorrectLocation(goal) function simply checks whether the coordinates of the goal and the crate match.

    Conclusion

    We took our game with layers and sprites and added input handling. This enables us to move our player and crates in the game. We also added the logic of the game: we check whether crates can be moved, and whether the level is completed or not. Creating the game is now simply a matter of calling the right functions in your update loop, which we will leave up to you. In the next episode we will create a game menu using React on top of our game.

  • Sokoban Series: Part 2, Creating an Interactive Level

    |

    In this episode we will transform our tilemap from the previous episode into a map with different layers and sprites. This gives us a foundation to implement our game logic and to easily create new maps. Next to that, we will play around with the camera to render our map in the center of the canvas, so that maps with different sizes get rendered nicely.

    Object Classes

    I want to take a static definition of our game world, a tilemap, and convert it into something
    dynamic with sprites that we can play with. In sokoban we have the following objects:

    • Walls
    • Floor
    • Goals
    • Crates
    • Our hero

    The first three objects are static and will never change when playing, while the last two are dynamic. As the first three are static and don’t contain that much logic we can simply represent them using tiles and tilemaps. The dynamics ones can be represented using sprites. We discuss the latter two.

    Player Sprite

    Let’s open our editor and create a Player sprite. Most Phaser tutorials or documents that I have seen just use the base sprite class and modify its state externally. I find it nicer to have specialized classes for my objects that extends the sprite class.

    Create a sprites directory and player.ts inside that directory. For now our player won’t do much except be drawn on the screen. We’ll add animations later.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    import * as Phaser from 'phaser';

    const START_FRAME = 'Player/player_05'; // depends on your tilesheet, check out the JSON

    class Player extends Phaser.GameObjects.Sprite {
    constructor(scene: Phaser.Scene, x: number, y: number) {
    super(scene, x, y, 'assets', START_FRAME);
    }
    }

    export default Player;

    Our Player class doesn’t do much, besides calling the Sprite constructor with START_FRAME. This is the sprite that will be used to draw our player initially. Open assets.json to find the correct name.

    Crate Sprite

    Similar to our player we will create a crate sprite class as well:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    const START_FRAME = 'Crates/crate_12';

    class Crate extends Phaser.GameObjects.Sprite {
    constructor(scene: Phaser.Scene, x: number, y: number, private crateType: number) {
    super(scene, x, y, 'assets', crateTypeToAsset(crateType));
    }
    }

    export default Crate;

    Creating our Level in Tiled

    In sokoban every square can only contain a single item: a square is either a floor, a goal, a wall, a crate or contains the player. In theory we could represent the whole map as a single layer. I prefer to have multiple layers, where each layer contains a single object type.

    Multiple layers also enable us to diversify the look of our level. With a single layer we would not be able to specify the looks of the floor under a crate. It also makes it a bit easier to get all items of a certain type, as they are all in a single layer.

    We create a floor, crates, goal, spawn and walls layer. The spawn layer contains a single sprite that indicates the starting position of the player. By making it a separate layer we can simply not render that layer in our game, but still encode the information in our map.

    tiled-layer

    Creating our Level in Phaser

    So, let’s import our level into Phaser. Instead of using our MainScene from earlier we’ll create a dedicated LevelScene.

    This is (part of) the code:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    import * as Phaser from 'phaser';
    import Crate from '../sprites/crate';
    import Player from '../sprites/player';

    class LevelScene extends Phaser.Scene {

    private player: Player;
    private crates: Phaser.GameObjects.Group;

    // tilemap
    private tileSet: Phaser.Tilemaps.Tileset;
    private tileMap: Phaser.Tilemaps.Tilemap;

    // layers
    private floorLayer: Phaser.Tilemaps.DynamicTilemapLayer;
    private wallLayer: Phaser.Tilemaps.StaticTilemapLayer;
    private spawnLayer: Phaser.Tilemaps.StaticTilemapLayer;
    private goalLayer: Phaser.Tilemaps.StaticTilemapLayer;
    private crateLayer: Phaser.Tilemaps.StaticTilemapLayer;

    constructor() {
    super({
    key: 'LevelScene',
    });
    }

    preload() {
    this.load.tilemapTiledJSON('level01', `./assets/levels/level01.json`);
    }

    create() {
    this.tileMap = this.make.tilemap({ key: 'level01' });
    this.tileSet = this.tileMap.addTilesetImage('assets');
    this.createLevel();
    this.createPlayer();
    }

    private createLevel() {
    this.createLayers();
    this.createCrates();
    }

    private createLayers() {
    const x = 0;
    const y = 0;
    this.spawnLayer = this.tileMap.createStaticLayer('Spawns', this.tileSet, x, y);
    this.spawnLayer.setVisible(false);
    this.crateLayer = this.tileMap.createStaticLayer('Crates', this.tileSet, x, y);
    this.crateLayer.setVisible(false);
    this.floorLayer = this.tileMap.createStaticLayer('Floors', this.tileSet, x, y);
    this.wallLayer = this.tileMap.createStaticLayer('Walls', this.tileSet, x, y);
    this.goalLayer = this.tileMap.createStaticLayer('Goals', this.tileSet, x, y);
    }

    private createCrates() {
    const crateTiles = this.getTiles((tile) => {
    return tile.index > -1;
    }, this.crateLayer);
    const crateSprites = crateTiles.map((tile) => {
    const { x, y } = this.tileMap.tileToWorldXY(tile.x, tile.y);
    const { type } = tile.properties as { type: number };
    const crate = new Crate(this, x, y, type);
    this.add.existing(crate);
    return crate;
    });
    this.crates = this.add.group(crateSprites);
    }

    private createPlayer() {
    const playerSpawn = this.getSpawn();
    const { x, y } = this.tileMap.tileToWorldXY(playerSpawn.x, playerSpawn.y);
    this.player = new Player(this, x, y);
    this.add.existing(this.player);
    }
    }

    export default LevelScene;

    That’s a lot. Let’s break it down. In our preload function we load our tiled map data, and in our create funcion we’ll create the tile map. This is similar to our previous example. We turn our spawn and crate layer invisible. We don’t want to render our spawn, we just need it to know where our player starts. Our crates won’t be represented by tiles. Instead, we will use the Crate sprite we created earlier.

    The function createCrates will create all the crates. It uses a helper function getTiles to filter all the tiles of certain layer. We’ll find all the tiles of the crateLayer that have a positive index: Phaser either represents a non-existing tile as null, or can provide a stub tile with a negative index (but that still has an x and y coordinate etc.). We take all the tiles that have a crate, and create an instance of a Crate sprite. These are added to the Crate group. Note that crates use world coordinates, while tiles use tile map coordinates. World coordinates are the actual coordinates that are used to draw on the screen. Tile map coordinates are better suited for tile maps: the topleft tile has coordinate (0,0), the tile next to that (1,0) etc.

    We create our player in a similar way.

    So, how does getTiles and getSpawn work? Here is the code:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    class LevelScene {
    ...
    private getSpawn() {
    const spawns = this.getTiles((tile) => {
    return tile.index > - 1
    }, this.spawnLayer);
    if (spawns.length !== 1) {
    throw new Error(`[LevelScene] Expected single spawn`);
    }
    return spawns[0];
    }

    private getTiles(
    test: (tile: Phaser.Tilemaps.Tile) => boolean,
    layer?: Phaser.Tilemaps.StaticTilemapLayer
    ): Phaser.Tilemaps.Tile[] {
    this.tileMap.setLayer(layer || this.floorLayer);
    return this.tileMap.filterTiles((tile: Phaser.Tilemaps.Tile) => {
    return test(tile);
    }, this, 0, 0, this.tileMap.width, this.tileMap.height);
    }
    }

    getTiles uses filterTiles to filter out all the tiles of a tilemap. A tilemap has a current layer against which all operations run. So, we first set the active layer to the given layer (or the floor layer). filterTiles allows you to define a rectangle on which the filter operates. We always want to full tile map, so we start in the topleft corner (0,0), and have a rectangle with width tileMap.width and height tileMap.height.

    Next I want to make the distinction between tiles clearer, so it is easier for our players to navigate the gridlike map. We draw a horizontal and vertical grid with dotted lines. We create a generic function addGridLine that can draw horizontal and vertical dotted lines, and use this function to draw our grid.

    Here is the code:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    class Level {
    ...
    private createGridLines() {
    const lineLength = 6;
    const skipLength = 2;
    this.addVerticalLines(lineLength, skipLength);
    this.addHorizontalLines(lineLength, skipLength);
    }

    private addVerticalLines(lineLength: number, skipLength: number) {
    let currentX = 0;
    const stopX = this.tileMap.widthInPixels;
    const stopY = this.tileMap.heightInPixels;
    const next = (x: number, y: number) => ({ x: x, y: y + lineLength });
    const skip = (x: number, y: number) => ({ x: x, y: y + skipLength });
    const stop = (x: number, y: number) => y >= stopY;
    while (currentX <= stopX) {
    this.addGridLine(currentX, 0, next, skip, stop);
    currentX += this.tileMap.tileWidth;
    }
    }

    private addHorizontalLines(lineLength: number, skipLength: number) {
    let currentY = 0;
    const stopX = this.tileMap.widthInPixels;
    const stopY = this.tileMap.heightInPixels;
    const next = (x: number, y: number) => ({ x: x + lineLength, y: y });
    const skip = (x: number, y: number) => ({ x: x + skipLength, y: y });
    const stop = (x: number, y: number) => x >= stopX;
    while (currentY <= stopY) {
    this.addGridLine(0, currentY, next, skip, stop);
    currentY += this.tileMap.tileHeight;
    }
    }

    private addGridLine(
    startX: number,
    startY: number,
    next: (x: number, y: number) => { x: number, y: number },
    skip: (x: number, y: number) => { x: number, y: number },
    stop: (x: number, y: number) => boolean,
    ) {
    let currentX = startX;
    let currentY = startY;
    const line = this.add.graphics({
    x: 0, y: 0,
    lineStyle: { width: 1, alpha: 0.5, color: 0x000000 },
    fillStyle: { color: 0x000000, alpha: 1 },
    });
    line.beginPath();
    line.moveTo(startX, startY);
    while (!stop(currentX, currentY)) {
    const { x: nextX, y: nextY } = next(currentX, currentY);
    line.lineTo(nextX, nextY);
    const { x: skipX, y: skipY } = skip(nextX, nextY);
    line.moveTo(skipX, skipY);
    currentX = skipX;
    currentY = skipY;
    }
    line.closePath();
    line.strokePath();
    line.fillPath();
    }
    }

    Centering our Map

    We currently draw our map in the top left corner of our canvas. It would be nicer if our map would be drawn in the center, regardless of its size. We can do this using the Phaser 3 camera system, which got a nice revamp. I’ll be honest that it took me a while to get this working, and I noticed that on older versions of chrome this doesn’t work properly.

    So, this code renders our game in the center of the canvas:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    class LevelScene {
    private centerCamera() {
    const bounds = this.physics.world.bounds;
    const x = bounds.width / 2 - this.tileMap.widthInPixels / 2;
    const y = bounds.height / 2 - this.tileMap.heightInPixels / 2;
    this.cameras.remove(this.cameras.main);
    const camera = this.cameras.add(x, y, this.tileMap.widthInPixels, this.tileMap.heightInPixels, true);
    camera.setOrigin(0, 0);
    camera.setScroll(0, 0);
    }
    }

    It works by taking the bounds of our world, in other terms the size of our canvas. We compute the center point, and then offset that point with the half of our tilemap. x and y point to the top left corner of where we want to draw our tile map.

    Next, we remove the main camera. Don’t ask me why. If I simply updated the main camera the code didn’t work. It’s probably a mistake on my part, but I just moved on. We can’t simply remove the main camera without adding a new main camera, so we do that. We create a camera that projects onto x and y with the width and height of our map, but which ‘looks’ at the topleft corner. So, we can just keep on using (0,0) as the topleft corner of our game, while the camera renders everything in the center.

    In the final version I added some text (“Level Complete”) that grows when you complete a level. The text was cut of on the left and right side as the growing effect fell outside the viewport of our camera. To solve that we simply let the camera render from -100 with a width of widthInPixels + 200, and set the scroll to (-100, 0).

    Conclusion

    In this episode we converted our plain tilemap into different layers and sprites, and centered our game into the middle of the camera. Our sprites don’t do much… yet. That is for the next episode.