banner



How To Animate A Character Side Scroller

Recently I completed my commencement game, Penguin Walk, with aid of free art in Javascript and it gave me empirical feel of a known-fact surrounding game development – "The hardest thing about developing a game is finishing information technology."

Although, the game is dead uncomplicated and code runs in but few hundreds of lines, it took a lot of endeavour to finish information technology. The reason? I believe the hard matter related to game development, is that you are attempting to build something complex out of very simple elements (pixels). The same reason why edifice a programming language is hard – yous are trying to ensure that a stream of characters obeys formal grammatical rules and convert them into something that tin execute. In this post, I will describe how I created my side-scroller game.

Is Game Programming hard?

Think about information technology. What does it take to projection a bird from a slingshot, testify it flight in projectile motion, hitting a set of object which are and then blithe to move accurately, in accordance to laws of physics? Well, a lot. Y'all can only tell figurer what to paint on the screen, remainder of all the higher level abstractions, you build on your own.

Although, using a library might help a lot; after all, who tin can be expected to complete a desktop awarding if he has to program all controls on his own but if you compare the two, there are two complications that arise in game development –

  • It is impossible to define a generic component that can work everywhere. At best, you tin take some abstractions – sprites, and animations to help y'all make them on your own.
  • The interaction between objects in a game are far more than complicated than in normal applications.

I believe, programming a game, involves thinking at multiple levels of abstractions, which makes it challenging (and fun!).

Getting the art

"Only! only if I could do art, I would offset aircraft games." — A recurring idea that must have went through many programmers' head and to some extent information technology might exist true. Getting art done, isn't a piece of cake but guess what, you need non to. Enough of free and non-gratis resources are available to assistance you get started.

Although, information technology might non give you a highly polished look you fancy merely if y'all get a decent prototype, it is piece of cake to iterate with professional help to take a stride further. Then don't whine virtually your non-artistic background, commencement working with bachelor fine art and focus on the gameplay. I used gratis art from HasGraphics and OpenGameArt and free sounds furnishings from Soundbible.

Building the game

Animative using viewport and a larger window

The commencement step in making our side-scroller would exist to working out the animation part. Y'all are given number of objects, how would you animate them? One obvious choice would exist to work out the position, the visible office of each object in every frame and paint them on the canvas. Another arroyo, which I used, is to have a longer sail and a moving viewport that shows only the part of the former and keep updating it with newer object. Nosotros refer the longer canvas as "scene generator".

The init() function constructs two canvas objects, one a bigger window, another a viewport which is a sliced-off view of the bigger window. The latter is but meant for processing and hence isn't appended in the document.

Loading Resources

To ensure that all our resources are available when rendering, we must make sure they are loaded successfully before we initialize our game. Since, resource loading is asynchronous, we must have assist of callbacks to trigger something when all resources have been loaded. loadResources() part monitors the number of objects that have been loaded successfully, compares them to those which are required to load and fires the callback (init) when the procedure is finished.

Using sprites

Canvas' drawImage function allows you to pigment an prototype (or role of it) on sail. Using drawImage we can utilise a larger sprite prototype and ascertain what objects are where in sprite. Sprite object defines methods to pigment the objects on canvas. The init() function initializes the Sprite with the definition of objects (Ten, Y, Width, Height) :

                                    sprites.              addObjects              ({                                                                  "gground"              : [              36              ,                            19              ,                            107              ,                            90              ],                                                                  "sground"              : [              36              ,                            171              ,                            107              ,                            90              ],                                                                  "gstone"              : [              36              ,                            281              ,                            107              ,                            90              ],                                                                  "sstone"              : [              36              ,                            409              ,                            107              ,                            ninety              ],                                                                  "background"              : [              0              ,                            0              ,                            one              ,                            1              ]                                      });                              

The initialized class is used to create a Scene object where Sprite methods are called to paint on the scene generator:

                                    var                              scene                            =                                          new                                          Scene              (sceneGenContext, sprites, [imgObj.Cloud, sfxSounds]);                              

Creating a scene

Now we know how to create sprites, the next pace is to paint a scene using them. Recall that, nosotros are using "moving viewport" approach, so, all our painting would happen on the scene generator whose length is twice that of viewport. There are four basic objects in our game – the groundwork, clouds, lands and the animated penguin. The first three class office of our scene while the animated penguin is painted after the rendering the scene. The paintClouds(), paintBackground() methods are self-explanatory. The drawLand() part paints the land of given unit of measurement peak, by showtime series painting "soil" objects then painting "ground" object for their superlative. Each land's data is stored in landPoints array and then that we can check out penguin is going the correct way.

The drawLands() function creates iii land objects, each of length two. However, with these a niggling bit of sheet is left out, which we draw as a partial object, i.east, of length less than two. So we now take our bones scene, which looks like this,

image

Animating the scene

As we already discussed, nosotros would exist using "moving viewport" approach to have an animating scene. To do this, nosotros take "curX" variable in Scene object which dictates the portion of the scene generator to be painted on the viewport which is basically [curX, curX + viewport.width]. The actual painting of the Scene on the viewport is washed past showScene() in the Game object with:

                                    realContext.              drawImage              (scene.sceneGenContext.sail, scene.curX,                            0              ,                            CONFIG              .              CANVAS_WIDTH              ,                            CONFIG              .              CANVAS_HEIGHT              ,                            0              ,                            0              ,                            CONFIG              .              CANVAS_WIDTH              ,                            CONFIG              .              CANVAS_HEIGHT              );                              

At every frame, curX changes and different portion gets painted on viewport. Additionally, updateLandPoints() checks if the electric current land hasn't gone out of focus with (this.landPoints[0].posX + this.landPoints[0].width - this.curX) < 30, in which instance, the offset landPoint is removed from the assortment and the new focus land is repainted equally ground one. Later on curx becomes larger then viewport's width, the first one-half of larger window gets spliced to the first half and second one-half is regenerated. Something which happens in generateScene():

                                    this              .              generateScene                                          =                                          function              ()                                      {                                                                  // Splice second half to outset                                                      sceneGenContext.              drawImage              (sceneGenContext.canvas,                            CONFIG              .              CANVAS_WIDTH              ,                            0              ,                            CONFIG              .              CANVAS_WIDTH              ,                            CONFIG              .              CANVAS_HEIGHT              ,                            0              ,                            0              ,                            CONFIG              .              CANVAS_WIDTH              ,                            CONFIG              .              CANVAS_HEIGHT              );                                                      spriteObj.              paintBackground              (                            CONFIG              .              CANVAS_WIDTH                              );                                                                              // Assign new positions to spliced lands                                                                  var                              i                            =                                          0              ;                                                                  while              (                            typeof                                          this              .landPoints[i]                            !==                                          "undefined"                              )                                                      {                                                                  this              .landPoints[i].posX                            -=                                          CONFIG              .              CANVAS_WIDTH              ;                                                      i              ++              ;                                                      }                                                                              // Regenerate scene.                                                                  this              .              paintClouds              (              CONFIG              .              CANVAS_WIDTH              );                                                                  this              .              drawLands              (              CONFIG              .              CANVAS_WIDTH              );                                                                  this              .curX                            -=                                          CONFIG              .              CANVAS_WIDTH              ;                                      };                              

And so out animation logic in a nutshell is, keep updating viewport with new coordinates over the larger window and when information technology is about to end, recreate the larger window. The penguin is animated over the viewport past painting a new frame of penguin's animation every fourth dimension penguin.paintFrame is called.

The Game

Now finally, we get in at edifice our game logic. So what does our game have? Change land peak on "Upward" / "Downwardly" key press, check if penguin is walking on levelled land, and trigger game over it isn't.

Changing Land Peak

When a key is pressed, it triggers keyHit() method:

                                    this              .              keyHit                                          =                                          role              (                            keyCode                              )                                      {                                                                  switch              (keyCode)                                                      {                                                                  instance                                          CONFIG              .              ACTION_MAP              .              LAND_UP              :                                                                  if              (                            this              .gameBegun ) scene.              updateHeightLand              (              one              );              pause              ;                                                                              case                                          CONFIG              .              ACTION_MAP              .              LAND_DOWN              :                                                                  if              (                            this              .gameBegun ) scene.              updateHeightLand              (              0              );              break              ;                                                                              case                                          CONFIG              .              ACTION_MAP              .              GAME_START              :                                                                  this              .              beginGame              ();              break              ;                                                      }                                      };                              

When LAND_UP and LAND_DOWN keys, call updateLandHeight() which repaints lands to a newer peak. I faced a trouble while building this. Before I directly used to change landHeight without storing original generated meridian. Since the logic is to modify height of all lands on the same level, it used to modify lands which were not originally, on the aforementioned level. For eg, lets say acme of generated lands are – 1, 1, two, three. After pressing "Upwards", the new heights are "2, 2, 2, 3". Without storing original height, the logic would also change the height of the tertiary ane. The solution was to store original acme separately, i.e, use origHeight.

                                    var                              i                            =                                          0              ;                                      while              (                            typeof                                          this              .landPoints[i]                            !==                                          "undefined"                                          &&                              oldOrigHeight                            ==                                          this              .landPoints[i].origHeight )                                      {                                                                  if              ( inc                            &&                                          this              .landPoints[i].landHeight                            <                                          4                              )                                                                  ++              this              .landPoints[i].landHeight;                                                                              if              (                            !              inc                            &&                                          this              .landPoints[i].landHeight                            >                                          1                              )                                                                  --              this              .landPoints[i].landHeight;                                                                              this              .              clearLand              (              this              .landPoints[i].posX, oldHeight,                            this              .landPoints[i].landLength);                                                                  this              .              drawLand              (              this              .landPoints[i].landHeight,                            this              .landPoints[i].landLength,                            this              .landPoints[i].posX,                            true              ,                            "ground"              );                                                                  i              ++              ;                                      }                              

The apply of clearLand() is simply to clear out part of land when its height is decremented.

Checking Game Over

The checkGameOver() function checks if height of two sequent is uneven and triggers gameOver when visible length of first country has fallen before threshold. we accept used two different thresholds. Ane to cheque when penguin collides with a country and the other when penguin falls from state of college height. For eg,

image

Considering two lands are uneven and showtime country's visible length is almost beneath threshold, gameover is triggered immediately after. triggerGameOver resets the state of the game, and our game can be restarted.

The Game Loop

The showScene() also is our principal execution loop. Using requestAnimationFrame() we repetitively request and paint scene on our canvas. We also call checkGameOver() to come across if there has been any collision and reset the state of the game, in that case.

Conclusion

So that sums upwards our mini game. It was a fantastic experience seeing it to the finish. At that place are many game frameworks available that can save yous from the problem of creating abstractions, be sure to bank check them out. The nigh important lesson I learned was to stick around and come across information technology to finish.

So if you wish to build a game, build it like a MVP. Take free art, or maybe just circles and polygons, and focus on building game play. Once you accept something good, you can showtime iterating with improve fine art and visual furnishings simply the important thing is to get started.


Source: https://shubhamjain.co/2015/04/20/creating-side-scroller-game-in-html5-and-javascript/

Posted by: watkinsworick.blogspot.com

0 Response to "How To Animate A Character Side Scroller"

Post a Comment

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel