Wednesday, December 27, 2017

Making of Santa’s Search

I am posting this early today as I am going to The Last Jedi tonight so will be busy. I have decided that for next year I will not be interrupting my emulator project for game material unless it is for a game jam that I am participating in. Material relating to resurrecting Blazing Games games and the revised version of my Flash Game Development book will be on my resurrected Blazing Games development blog which I will be starting this Saturday. Now onto Santa’s Search.

When I originally create Santa’s Search, Flash did not have any 3D support at all. Worse yet, it didn’t have direct bitmap support so manually building an image was not possible. My Coffee Quest series was already using ray casting. The CQ ray caster had only partial perspective correction but after taking graphic programming courses I realize that the solution I found was simply wrong and that the better approach would simply do a world transform to make every ray act as if it were the center ray. But that is way off topic. The point I was trying to make is that at the time I couldn’t do ray casting so I went with a more primitive algorithm known as the painter’s algorithm.

The idea here is that you paint the things furthest from the player first then overpaint the items with things that are closer to the player. The downside to this approach is that you are potentially overdrawing the same pixel multiple times. As this is not a real-time game, this is not a huge concern so the painter’s algorithm works fine.


As you can see by the sprite atlas above, the game has three different blocks that it uses to draw the maze. A left-side block, a center block, and a right-side block. These are chosen based on the position of the block relative to the player’s viewpoint. Had I been a bit more ambitious with saving image atlas space, I could have had all three blocks combined into a single distorted block and have the sprite take just the appropriate chunk of the combined image. The deer and sled images are the same no matter which position the player is looking at them.

The original game was controlled using the keyboard. As mentioned in previous posts, I want the game to be able to be playable on touch devices. As the only controls are turning and moving, adding simple arrow buttons was the obvious choice. I was originally going to go with transparent arrows that turned solid when clicked on, but felt that the outlined arrows simply looked better so went with those.

The hard part of porting this game was assembling the sprite sheet as Flash CS 6 did extremely poor so I had to adjust the sheet manually then figure out the coordinates myself. The code was very quick to port and to my shock worked nearly flawlessly once all the “this” statements were added. Half a day’s worth of work and I have a playable game. Not too bad for porting. Let us hope that my future Flash to HTML5 ports go as smoothly as this one did.

See you next year!

Wednesday, December 20, 2017

Making Evil Gnome’s Revenge

Before I get to my game overview a brief update on my 2600 project. The assembler is functional now and while I do want to add more directives to it, will start on implementing the 6502 emulation adding new directives to the assembler as needed. I have a number of articles on my 2600 assembler ready and will be posting them next year. Now back to the evil gnome.

Evil Gnome’s Revenge was my 2012 game jam entry for Ludum Dare #25 which had the theme “You are the Villain.” At the time I really didn’t want to go down any of the dark paths that I had thought of and having had created both Santa’s Search and Santa’s Snowball years earlier I thought this would be a light-hearted way of making the player the villain without having them do anything outrageous. I can’t say that the herding concept was original as there are a number of games that have a similar mechanism with Munch’s Oddysee probably being the biggest influence.

The development time on this port was pretty abysmal as I made the cardinal mistake of working on it while watching TV. While I know that the human brain is not designed for multitasking, the lackluster performance I had while coding this clearly emphasizes how poor we humans are. The strange thing is that I normally have podcasts or other background noise playing so I had expected to have my normal development speed. When coding, however, I tend to tune out what I am listening to while the TV tended to take most of my attention as I got caught up with my shows before losing the contents of my PVR. The big lesson being that you shouldn’t let your recorded backlog build up that much. Coding is best done without distractions could also be considered a lesson if I didn’t already know that.

The first surprise was that the game was created using the Starling library. This is a molehill library that takes advantage of the 3D capabilities that later versions of the Flash player added.  When I saw the starling imports I thought that perhaps I should consider StageGL, the WebGL based renderer that is in testing now but will eventually replace the stage.js library.  The map for the game, which is procedurally generated, is 64x64 with each tile being a movie clip that goes to the appropriate frame to display the tile at that location. Once set, however, the tiles do not change. Having 4096 sprites on the screen is probably not very good for performance, but by creating a 2048x2048 pixel cache then there is only one background image that the renderer is tracking giving the game 60 fps performance on decent machines. It is easy to cache sprites, as the following code shows.

// for speed reasons, cache the tilemap
this.tileMap.cache(0,0, 64*32, 64*32);

One of the substantial changes that I am making to all the games that I am porting is to make sure that the games work with touch interfaces. Touch input meant rewriting how the player moves as the original game used cursor or WASD for movement. The obvious solution was to simply have the player click to where they wanted to move to and head in that direction. The obstacles in the map, however, made this a bit tricky. A path-finding algorithm could have been used but I didn’t feel like writing one so I opted for a simple slide along the object system. This simply checks to see if the player is stuck and if so tries moving on just one of the axis. While this method still lets the player get stuck, most of the time the player will move around the obstacle.

if (this.canEnterTile(targX, targY, mover) == false) {
if (this.canEnterTile(targX, mover.worldY, mover) == false) {
if (this.canEnterTile(mover.worldX, targY, mover) == false) {
// we are stuck!
} else {
mover.worldY = targY;
}
} else {
mover.worldX = targX;
}
} else {
mover.worldX = targX;
mover.worldY = targY;
}

This is where things got strange. The game seemed to work fine with the change until the mouse was moved at which point the game stalled for a few seconds. Out of curiosity, I removed all the tiles from the tilemap image replacing It with a 2048x2048 shape. This solved the delay problem meaning that the problem was with how create.js handles clicking. All the tiles are being checked with a pixel accurate test to see if the tile is affected by the mouse event. The solution was to not have the game screen process the mouse event but grab the mouse events at the higher stage level then manually determine which tile was clicked on. When you are dealing with thousands of objects, different techniques must be used.

var clickX = e.stageX
var clickY = e.stageY;
this.gnome.targetX = (clickX - this.tileMap.x) / 32;
this.gnome.targetY = (clickY - this.tileMap.y) / 32;

With the major issues out of the way, this was not a difficult game to port. This only leaves the final game in the series which will be covered next week and then we can get back to my 2600 emulator.

Wednesday, December 13, 2017

Making Santa’s Snowball part 3 – tweens and gameplay

I was able to finish and post the second game in this years Santa’s trilogy and got the final game in the trilogy running. Tonight I will be cleaning up the game in ready for release next Friday. With my Christmas obligation finished I will be able to get back to the emulator, though next week will be a making of Evil Gnome’s Revenge post and the Wednesday after that will be a post about the making of Santa’s Search.

One of the important things I wanted to do while creating this project was work with tween.js as tweening is very important for animation and can be useful for all sorts of other things. The term tween comes from animation as a shorthand word for in-between. The lead animator would draw the key frames of an animation then other animators would draw all the frames in-between the two keyframes. Computers are now taking care of the in-between frames, which is why tools like Animate are still popular even though the Flash player is fading away.

Tween.js is not tied strictly to animation but can be used on any class to change the value of a variable over time. The associative array nature of JavaScript is what allows for this, but similar functionality can be done in C by using a pointer to the variable being changed. For Santa’s Snowball, tweening is only used for animation but it is not restricted to that. One thing that I could have done had I thought of it at the time was have the change of score be done at the moment of snowball impact instead of when the snowball was thrown by setting up a tween.

Tweening is an important part of the game as I use it for handling the turning of the billboards as well as for the snowballs. My billboard works by having a blank billboard shape (a white rectangle), a Santa image, and an evil Gnome image. This allows for three states of the billboard namely empty, Santa, or Evil Gnome. The show board function lets you indicate the type of board to show and hides Santa and/or the Evil Gnome based on the provided board type. The billboard, Santa, and the evil gnome are all then tweened into going from a shrunken width to their proper size. Hiding is simply shrinking the three of them which takes advantage of the fact that the unused images are already hidden. Here is the code for that.

/* shows the billboard appearing animation using the indicated type */
this.showBillboard = function(type) {
this.santa.visible = type == 1;
this.gnome.visible = type == 2;
cjs.Tween.get(this.shape).to({scaleX:.1}, 0).to({scaleX:1}, 500);
cjs.Tween.get(this.santa).to({scaleX:.1}, 0).to({scaleX:1}, 500);
cjs.Tween.get(this.gnome).to({scaleX:.1}, 0).to({scaleX:1}, 500);
}

/* shows the billboard disappearing animation */
this.hideBillboard = function() {
cjs.Tween.get(this.shape).to({scaleX:1}, 0).to({scaleX:.01}, 500);
cjs.Tween.get(this.santa).to({scaleX:1}, 0).to({scaleX:.01}, 500);
cjs.Tween.get(this.gnome).to({scaleX:1}, 0).to({scaleX:.01}, 500);
}

Testing this code did turn up a strange issue. When I had more than one billboard, all of them would show the same image. This was due to the fact that I am overriding the Easel.js’s Container class but forgot to call the initialize method. The poor way that classes are handled is not one of the better features of JavaScript but at least future versions do improve this. That being said, web assembly is probably the direction that I will be going in the future.

While tween.js does support motion paths, it does require a plugin be installed. By plugin, I mean within the create.js code not with the browser. This would not have been difficult to do, but since I would also have to come up with the curves to use I decided I would have a bit of fun and write a simple path generator for snowballs. I break the snowball path into three parts, with the line to the target being used as the base path. A third of the length is added to the point a third of the way through the line as well as 2/3 the way through to form a rudimentary curve. Each third of the line takes a slightly different amount of time to traverse so the snowball will move faster nearer to the player and slower further away. In addition to the path, the size of the snowball is also being tweened.  The code for handling the throwing of a snowball is below.

// create a path the hard way as didn't want to bother with motion paths
var endx = this.billboards[indx].x;
var endy = this.billboards[indx].y;
var dx = endx - 320;
var dy = endy - 440;
var linelen = Math.sqrt(dx * dx + dy * dy);
var thirdlen = linelen / 3;
var mid1x = 320 + dx / 3;
var mid1y = 440 + dy / 3 - thirdlen;
var mid2x = 320 + dx / 3 * 2;
var mid2y = 440 + dy / 3 * 2 - thirdlen;
this.snowball.visible = true;
cjs.Tween.get(this.snowball).to({x: 320, y:440, scaleX:1, scaleY:1}, 0).to
({x: mid1x, y:mid1y, scaleX:.25, scaleY:.25},200).to
({x: mid2x, y:mid2y, scaleX:.1, scaleY:.1},300).to
({x: endx, y:endy, scaleX:.02, scaleY:.02},400).call(this.playSplatSound).to({visible:false},1);
// animation ends with a splat so set up the 8 splat animations as well.
for (var cntrSplat = 0; cntrSplat < 8; ++cntrSplat) {
cjs.Tween.get(this.splats[cntrSplat]).wait(899).to
({x:endx, y:endy, scaleX:.02, scaleY:.02, visible:true},1).to
({x:endx+this.splatOffsetX[cntrSplat], y:endy+this.splatOffsetY[cntrSplat],scaleX:.005, scaleY:.005},300).to
({visible:false},1);
}
this.doneBillboardTime = Date.now() + 900;

I suppose I could have used a similar technique to generate the curve, but this approach works well. I am liking the Create.js library finding it not that much more difficult to use than Animate making it a better choice for developing games in JavaScript. As web assembly starts to take off, however, it is likely that my future will be either using Kotlin or C++ and compiling them to web assembly. Still, I have many flash games to port with most of them being easier to port using Create.js than porting to another language but there will be a few that may be worth the effort to re-write.

Wednesday, December 6, 2017

Making Santa’s Snowball part 2 - Multiple Scenes

Not much progress was made as I am upgrading my PVR so the weekend and last few evenings were spent getting caught up with my tv shows as I will lose everything on the PVR when the swap is done. I suppose this is a mixed blessing as I have been overdoing things lately so having a forced break was probably good but that means that the port of Evil Gnome’s Revenge may be delayed. I was hoping to post the game this weekend, and still may be able to, but working while watching TV is not very productive.  Still, either this weekend or next weekend will be the second game in my Santa trilogy where you play the bad guy and need to chase Santa’s reindeer out of their corral.

Last week we looked at the preloading of the assets. With all the assets ready to be used, we still have the problem of dealing with multiple scenes. Animate CC 2017 does not handle multiple scenes at all so my solution when creating multi-scene projects in Animate was to simply put each scene in its own MovieClip and then have the main timeline have keyframes with each of the difference scene movies in it. When you think about it, if you have total control over the stage then having a MovieClip that contains all the scenes is not necessary as you can simply have a single scene MovieClip on the stage at a time. This has the additional benefit that you don’t have to worry about removing event listeners as when a MovieClip is not on the stage it will not be getting the events. The following is my switching code:

spelchan.SantaSnowball.switchScene = function(newScene, e) {
var stage = spelchan.SantaSnowball.stage;
stage.removeChildAt(0);
switch(newScene) {
case spelchan.SantaSnowball.TITLE_SCENE:
stage.addChild(spelchan.SantaSnowball.titleScene);
break;

case spelchan.SantaSnowball.PLAY_GAME_SCENE:
stage.addChild(spelchan.SantaSnowball.playScene);
break;

case spelchan.SantaSnowball.ABOUT_SCENE:
stage.addChild(spelchan.SantaSnowball.aboutScene);
break;

case spelchan.SantaSnowball.INSTRUCTIONS_SCENE:
stage.addChild(spelchan.SantaSnowball.instructionsScene);
break;
case spelchan.SantaSnowball.WIN_SCENE:
stage.addChild(spelchan.SantaSnowball.winScene);
break;

case spelchan.SantaSnowball.LOSE_SCENE:
stage.addChild(spelchan.SantaSnowball.loseScene);
break;

case spelchan.SantaSnowball.BIG_LOSE_SCENE:
stage.addChild(spelchan.SantaSnowball.bigLoseScene);
break;

}
}

In hindsight, this is not the best way of doing this. I have come up with two better ways of doing this. The first way is to have an array of scenes and create each scene using the numerical constant as an index into this array. A simple verification that the index is valid then remove the old scene and add the new scene to the stage. Much easier code. I use numerical constants for efficiency but when you consider that this function is not being called that often and the constants are fairly large chunks of text that are transmitted it may be more practical just to use string names for the various scenes. As JavaScript uses associative arrays for variables, you could simply tie the scenes to actual variables within the class for your game. This is the approach I will be taking for the second game in this trilogy.

As can be discerned from the code, there are seven scenes that make up this game. Five of these scenes just consist of images and text with a button leading back to the title screen. The title screen has a slight bit of animation, plays a musical clip, then has three buttons for navigating to other scenes. The title screen actually is a good demonstration of one of the problems with my scene switching system. The movie clips do not restart when they are switched to. This could be forced by the switcher by simply calling a gotoAndPlay method but this would require that all the scenes have a gotoAndPlay method, which is not that big of an issue but something that needs to be considered.


An example of when you may have a scene that is not a movie clip is my Billboard class. This is created as a container that holds three objects. The class does do some animation but instead of making this animation frame based, it is controlled by separate function calls which take advantage of tweens to perform the animation. This allows for the billboards to remain open for a different amount of time based on the level of the game. I even take advantage of their flexibility by having the act of throwing a snowball adjust the closing timing of the billboard.

More on that next week where we finish off the game and take a look at the tween.js class in more detail.