Upcoming HTML5 Christmas Game: Christmas Quest

While my latest HTML5 game, Sea Life Vs Mines has been approved by FGL for distribution – and I already got my cash advance – I am developing a new game for this upcoming Christmas called Christmas Quest, and wanted to share with you the title screen:

It uses the snow taken from this Phaser example – yes it’s a Phaser game – because there’s no need to reinvent the wheel, and the music taken from the other two Christmas game I made: Christmas Couples and Hurry it’s Christmas.

Obviously a simple iframe with some content in it wouldn’t be that interesting, so here is the source code of the title screen, uncommented because it’s a commercial project.

This is the HTML file, index.html:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8" />
		<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
		<title>Christmas Quest</title>
		
		<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no, minimal-ui" />
		<meta name="apple-mobile-web-app-capable" content="yes" />
		<meta name="apple-mobile-web-app-status-bar-style" content="black" />
		<link rel="apple-touch-icon" sizes="256x256" href="icon-256.png" />
		<meta name="HandheldFriendly" content="true" />
		
		<meta name="mobile-web-app-capable" content="yes" />
		<link rel="shortcut icon" sizes="256x256" href="icon-256.png" />

          <style type="text/css">
			* {
				padding: 0;
				margin: 0;
			}
			body {
				background: #000;
				color: #fff;
				overflow: hidden;
				-ms-touch-action: none;
			}
			canvas {
				touch-action-delay: none;
				touch-action: none;
				-ms-touch-action: none;
			}
    		</style>
		
    		<script src="phaser.min.js"></script>
          <script src="src/boot.js"></script>
          <script src="src/preload.js"></script>
          <script src="src/gametitle.js"></script>
          <script src="src/main.js"></script>

    </head>
    <body>
    </body>
</html>

Then main.js initializes the game:

var game = new Phaser.Game(640, 960, Phaser.CANVAS, "");

game.log = function(){
	console.log("%c  Running "+game.state.getCurrentState().state.current+" state  ","color:white;background:red");
}

game.state.add("Boot", boot);
game.state.add("Loading", loading);
game.state.add("GameTitle", gameTitle);
game.state.start("Boot");

As you can see we have three states: Boot, Loading and Gametitle. To know more about Phaser states, check the post Phaser Tutorial: understanding Phaser states.

This is Boot, located in boot.js, it just preloads game logo and loading bar, and opens the game in full screen:

boot = {
     init: function() {
          game.log();
     },
     preload: function() {
          game.load.image("loading", "assets/sprites/loading.png");
		game.load.image("logo", "assets/sprites/logo.png"); 
     },
     create: function() {
          game.scale.scaleMode = Phaser.ScaleManager.SHOW_ALL;
		game.scale.pageAlignHorizontally = true;
		game.scale.pageAlignVertically = true;
		game.scale.setScreenSize(true);   
		game.physics.startSystem(Phaser.Physics.ARCADE);
		game.state.start("Loading");
     }
};

Then Preload, located in preload.js, loads all game assets while displaying logo and loading bar:

loading = {
     init: function() {
          game.log();
     },
	preload: function(){
          var loadingBar = game.add.sprite(320, 560, "loading");
          loadingBar.anchor.setTo(0.5);
          game.load.setPreloadSprite(loadingBar);
          var logo = game.add.sprite(320, 480, "logo").anchor.setTo(0.5);
          game.load.image("background","assets/sprites/background.png");
          game.load.image("snow_mask","assets/sprites/snow_mask.png");
          game.load.image("gametitle","assets/sprites/gametitle.png");
          game.load.image("gamesubtitle","assets/sprites/gamesubtitle.png");
          game.load.image("blackfade","assets/sprites/blackfade.png");
          game.load.spritesheet("snowflakes", "assets/sprites/snowflakes.png", 17, 17);
          game.load.spritesheet("snowflakes_large", "assets/sprites/snowflakes_large.png", 64, 64);
          this.load.audio("music","assets/sounds/music.mp3");   
	},
  	create: function(){
		game.state.start("GameTitle");
	}
}

Finally GameTitlegametitle.js – handles the title screen itself, along with its fade-in transition:

var title;
var subtitle;

gameTitle = {
	init: function() {
          game.log();
     },
  	create: function(){
		game.add.image(0, 0, "background");
          //
          backSnow = game.add.emitter(320, -32, 600);
          backSnow.makeParticles("snowflakes", [0, 1, 2, 3, 4, 5]);
          backSnow.maxParticleScale = 0.6;
          backSnow.minParticleScale = 0.2;
          backSnow.setYSpeed(20, 100);
          backSnow.setXSpeed(-15, 15);
          backSnow.gravity = 0;
          backSnow.width = 960;
          backSnow.minRotation = 0;
          backSnow.maxRotation = 40;
          backSnow.start(false, 14000, 20);
          //
          game.add.image(0, 415, "snow_mask");
          title = game.add.sprite(-320,170,"gametitle");
          title.anchor.setTo(0.5);
          subtitle = game.add.image(960,270,"gamesubtitle");
          subtitle.anchor.setTo(0.5);
          game.time.events.add(Phaser.Timer.SECOND * 4, this.showTitle, this);
          //
          music = game.add.audio("music",1,true);
          music.play("",0,1,true);
          //
          frontSnow = game.add.emitter(320, -32, 50);
          frontSnow.makeParticles("snowflakes_large", [0, 1, 2, 3, 4, 5]);
          frontSnow.maxParticleScale = 0.75;
          frontSnow.minParticleScale = 0.5;
          frontSnow.setYSpeed(50, 150);
          frontSnow.setXSpeed(-20, 20);
          frontSnow.gravity = 0;
          frontSnow.width = 960;
          frontSnow.minRotation = 0;
          frontSnow.maxRotation = 40;
          frontSnow.start(false, 14000, 1000);
		//
          var blackFade = game.add.sprite(0 ,0, "blackfade");
          var fadeTween = this.add.tween(blackFade);
		fadeTween.to({
			alpha: 0
		}, 4000, Phaser.Easing.Linear.Out, true);  
	},
     showTitle: function(){
          var titleTween = game.add.tween(title);
          titleTween.to({
			x: 320
		}, 2000, Phaser.Easing.Cubic.Out, true); 
          titleTween.onComplete.add(function(){
               var subtitleTween = game.add.tween(subtitle);
               subtitleTween.to({
     			x: 390
     		}, 2000, Phaser.Easing.Cubic.Out, true);
          });
     }
}

And that’s how I made a stunning title screen in a short time with Phaser.

You can also download the source code and have a look at it.

Get the most popular Phaser 3 book

Through 202 pages, 32 source code examples and an Android Studio project you will learn how to build cross platform HTML5 games and create a complete game along the way.

Get the book

214 GAME PROTOTYPES EXPLAINED WITH SOURCE CODE
// 1+2=3
// 100 rounds
// 10000000
// 2 Cars
// 2048
// A Blocky Christmas
// A Jumping Block
// A Life of Logic
// Angry Birds
// Angry Birds Space
// Artillery
// Astro-PANIC!
// Avoider
// Back to Square One
// Ball Game
// Ball vs Ball
// Ball: Revamped
// Balloon Invasion
// BallPusher
// Ballz
// Bar Balance
// Bejeweled
// Biggification
// Block it
// Blockage
// Bloons
// Boids
// Bombuzal
// Boom Dots
// Bouncing Ball
// Bouncing Ball 2
// Bouncy Light
// BoxHead
// Breakout
// Bricks
// Bubble Chaos
// Bubbles 2
// Card Game
// Castle Ramble
// Chronotron
// Circle Chain
// Circle Path
// Circle Race
// Circular endless runner
// Cirplosion
// CLOCKS - The Game
// Color Hit
// Color Jump
// ColorFill
// Columns
// Concentration
// Crossy Road
// Crush the Castle
// Cube Jump
// CubesOut
// Dash N Blast
// Dashy Panda
// Deflection
// Diamond Digger Saga
// Don't touch the spikes
// Dots
// Down The Mountain
// Drag and Match
// Draw Game
// Drop Wizard
// DROP'd
// Dudeski
// Dungeon Raid
// Educational Game
// Elasticity
// Endless Runner
// Erase Box
// Eskiv
// Farm Heroes Saga
// Filler
// Flappy Bird
// Fling
// Flipping Legend
// Floaty Light
// Fuse Ballz
// GearTaker
// Gem Sweeper
// Globe
// Goat Rider
// Gold Miner
// Grindstone
// GuessNext
// Helicopter
// Hero Emblems
// Hero Slide
// Hexagonal Tiles
// HookPod
// Hop Hop Hop Underwater
// Horizontal Endless Runner
// Hundreds
// Hungry Hero
// Hurry it's Christmas
// InkTd
// Iromeku
// Jet Set Willy
// Jigsaw Game
// Knife Hit
// Knightfall
// Legends of Runeterra
// Lep's World
// Line Rider
// Lumines
// Magick
// MagOrMin
// Mass Attack
// Math Game
// Maze
// Meeblings
// Memdot
// Metro Siberia Underground
// Mike Dangers
// Mikey Hooks
// Nano War
// Nodes
// o:anquan
// One Button Game
// One Tap RPG
// Ononmin
// Pacco
// Perfect Square!
// Perfectionism
// Phyballs
// Pixel Purge
// PixelField
// Planet Revenge
// Plants Vs Zombies
// Platform
// Platform game
// Plus+Plus
// Pocket Snap
// Poker
// Pool
// Pop the Lock
// Pop to Save
// Poux
// Pudi
// Pumpkin Story
// Puppet Bird
// Pyramids of Ra
// qomp
// Quick Switch
// Racing
// Radical
// Rebuild Chile
// Renju
// Rise Above
// Risky Road
// Roguelike
// Roly Poly
// Run Around
// Rush Hour
// SameGame
// SamePhysics
// Save the Totem
// Security
// Serious Scramblers
// Shrink it
// Sling
// Slingy
// Snowflakes
// Sokoban
// Space Checkers
// Space is Key
// Spellfall
// Spinny Gun
// Splitter
// Spring Ninja
// Sproing
// Stabilize!
// Stack
// Stick Hero
// String Avoider
// Stringy
// Sudoku
// Super Mario Bros
// Surfingers
// Survival Horror
// Talesworth Adventure
// Tetris
// The Impossible Line
// The Moops - Combos of Joy
// The Next Arrow
// Threes
// Tic Tac Toe
// Timberman
// Tiny Wings
// Tipsy Tower
// Toony
// Totem Destroyer
// Tower Defense
// Trick Shot
// Tunnelball
// Turn
// Turnellio
// TwinSpin
// vvvvvv
// Warp Shift
// Way of an Idea
// Whack a Creep
// Wheel of Fortune
// Where's my Water
// Wish Upon a Star
// Word Game
// Wordle
// Worms
// Yanga
// Yeah Bunny
// Zhed
// zNumbers