Subscribe to GameFromScratch on YouTube Support GameFromScratch on Patreon
20. October 2014

 

Now we are going to look at available raster graphics programs available on iPad.  While this post is part of an over all series about creating a game using only an iPad, this post should be of use to anyone looking to create art in general.  The iPad ( and other tablets ) are becoming increasingly viable ways of creating art, especially 2D art.  One major reason for this is cost.  An iPad is generally cheaper than a PC/Mac + graphics tablet, but it’s software costs where this really becomes obvious.  For example, the desktop version of Photoshop ( before it went subscription ) used to cost about $800.  The tablet version of Photoshop… $10!  Another desktop/tablet example is ArtRage, which ( although vastly cheaper ) is available at $50 on Desktop, it is only $5 on iPad.  Granted, they aren’t identical products, and often the iPad version has less functionality, but I tend to find it has all the functionality I generally need.  You mileage may vary.

 

So we are going to take a look at some of the Raster and Vector packages available on iPad.  Raster and Pixel mean basically the same thing, although “Pixel Art” has often come to represent a very specific style, with fat chunky pixels like from the 8 and 16bit era.  We will also look at two options aimed specifically at this style.  We will also look at Vector graphics packages, which allow you to define brush strokes mathematically, making for nice scalable graphics. 

 

I have also done a video quickly showing each application running, so you can have a better idea what the experience is like.  I only spend a couple minutes with each, but a few minutes is often all you need to decide if something is right for you or not!  All testing was done on a iPad Air, so if your device is slower, your experience may not be as good.

 

This video is a quick demonstration of every application mentioned below.  You can view it directly here.

 

 

Ok, let’s jump right in:

 

Photoshop Touch

iTunes Link

Cost: $9.99

Screenshot(s):

Photoshop

 

Comments:

Be careful when it comes to the Photoshop products, Adobe have released a number of Photoshop branded iOS projects and most of them are focused on photo manipulation and most useless to you.  The version you want is Photoshop Touch.  This is the mobile version of the venerable desktop Photoshop application.  While certainly stripped from it’s desktop counterpart, it is still impressively capable.

One immediately useful feature is the allowed canvas size.  Earlier versions where limited in canvas size, while now you can successfully create a 4096x4096 texture, which is the reasonable upper limit of what you will ever want to create.  I will admit though, at this size things can get a bit sluggish at times, although the painting experience is just fine, running tools like magic wand select or applying fx can bring up a wait logo.  Speaking of which, that is two areas where Photoshop really shines compared to it’s peers.  The selection tools are great, including a magic wand, scribble selection, polygon, lasso, etc select and deselect tools.

Tools are solid but not exceptional.  Feedback is great, there is no lag even on large files.  Navigation takes a bit to get used to, but is quick once you know what you are doing.  It has a few standout tools, such as the clone and heal brushes, which are somewhat rare.  Otherwise you are left with paint, burn, smudge, spray and erase as your primary art tools.  You do however have a ton of fine control over each tool, such as brush patterns, angle, scatter, size, flow and transparency.  You have to set it up yourself, but you can emulate basically any brush type you desire.

Of less use to game art, but still occasionally valuable, Photoshop Touch has 16 built in adjustments like Black&White, Shadow/Highlight, etc.  There are also 30+ filters built in, such as Sharpen, Drop Shadow, Blur, Glass, Comic, Watercolor, Sephia, etc.  There are also an impressive number of manipulation tools tucked away in here for cropping, scaling, rotating, transforming(warping) and fairly solid text tools as well.

Where Photoshop Touch really shines is layers.  You can have several layers, either new, cloned or imported from existing media.  Layer control is solid making it easy to move layers up, down, merge and delete as well as altering the opacity.  Additionally layers can be normal, darken, multiply, lighten, overly, subtracted, etc.  Fx can be limited to an individual layer. 

While Photoshop Touch may not be the program you create your art in, it should probably be in your toolbox for the sheer amount of flexibility it gives you.  In terms of alterations and manipulation of images, it can’t really be touched.  The selection, copy/paste, import and layering tools are easily the best out of any tool I look at.

In terms of getting your work out at the end of the day, unfortunately there is no direct Dropbox integration, but that isn’t really surprising given Adobe have their own cloud storage system, Creative Cloud.  In addition to their cloud offering, you can also save to the local photo roll.  There is however a Share option, allowing you to export the file ( as JPG, PSD, PSDX or PNG ) to just about any iPad application ( including dropbox ) or to email, printers, etc.  However the process is remarkably slow and sometimes simply doesn’t work.  At the end of the day, you can get just about anything in and out of Photoshop Touch that you would expect, but it can be awfully slow at times.

I suppose it’s fair to point out, it’s actually Photoshop Touch I used to resize and export the screenshots from my iPad to my Mac while creating this post.  It’s just a handy tool to have.

 


 

Autodesk Sketchbook Pro

iTunes Link

Cost: $3.99 for Pro Tools

Screenshot(s):

AutodeskSketchbook

 

Comments:

This product is a bit difficult for me to cover, as the version I have doesn’t actually seem to exist anymore.  At some point they moved from a premium iPad only product (Sketchbook Pro) to an freemium model, where you can download the base (Sketchbook Express), then for $3.99 unlock the premium tools.  I believe at the end of the day, they become the same product, but if there are minor differences, I apologize now.  As I am not entirely certain what is in the free vs pro edition, the below will be describing the complete purchased product.

Sketchbook is exactly what the name suggests, a virtual sketchpad.  It’s an impressive one at that.  It’s got a minimal interface that get’s out of your way ( all of the things you see in the above screenshot are brought up by pressing the circular icon.  Let go and it’s just you and your drawing. Drawing tools are pretty typical with pen, pencil, market, highlighter, erase, smudge and airbrush available, plus the ability to choose custom brushes/stamps from probably 100+ presets, including common pencil type (2H, 8B, etc) and oddly enough, so clip art.  Responsiveness while drawing is instant.  Using a quick pop up tool you are able to alter your brushes dimensions and opacity with a single touch.  One nice feature, lacking from many similar products, is the ability to draw lines and shapes, although curves didn’t seem to work.

There are a couple unique to Sketchbook features, of varying levels of usefulness.  There is a symmetry draw mode, enabling you to draw mirrored about a centre point.  You can also do time lapsed recording and collaborative sketching with someone else with their own copy of Sketchbook.  Sketchbook also has decent text creation abilities built in.  Most importantly (to me), Sketchbook also has layer support, although nowhere near that of Photoshop Touch.  Even just a single layer to enable tracing for animation is invaluable. 

You can export from your gallery directly to the local photo gallery, to iTunes, email, etc… as well as directly to Dropbox.  You can create images up to 1800x2400 in size, although the size of image limits the number of layers.  A 1800x2400 image can for example have 4 layers, while a 768x1024 image can have up to 18 layers.  The largest image you are able to create is 2830x2830.  No idea why it stops there…  Even at that size, performance remains smooth.

Sketchbook is a great product for creating sketches, the brushes are natural, performance is good and tools are complete enough to recreate most anything.  The interface is faster to navigate than Photoshop Touch, but it has a great deal less functionality, with absolutely no filters, effects, selection tools and minimal layer functionality.  For drawing however, I would take it over Photoshop Touch every day.


 

Art Rage

iTunes Link

Cost: $4.99

Screenshot(s):

ArtRage

 

Comments:

This is the most applicably named application I have ever encountered!  It’s an amazing application for creating digital art, and it is horrifically rage inspiring!  ArtRage attempts to recreate real world art process digital, and does an incredibly good job of it.  You can choose your paper type (grain), metallic-ness then go to town using tools like paint, roller, trowel, crayons, markers, pens, erasers, pencils, airbrush and a couple different paint brushes.  For each brush you can set a number of settings specific to each tool such as pressure, thinning etc.  You really can recreate a very “painterly” feel.  So why the rage?

Well that part is simple.  This application lags.  Always lags and I absolutely cannot use it for that reason.  Regardless to the complexity of your scene, your paint brush will always been a half a second behind where you are touching.  Of all the applications I looked at, this one had by far the worst performance.  If you can handle the delay while drawing, this application is certainly worth checking out, especially if you are looking for a natural media look.  I personally cannot get over the lag.

From a technical perspective, Art rage allows a maximum canvas size of 2048x2048.  It supports layers with an absolute ton of blending modes.  There is no manipulation tools for selection, transformation nor any filters or effects.  This is a painting program focused on painting and nothing more.  It however probably does the best job of recreating brushes and paper in the digital world.  It has the ability to export to Dropbox as well as save locally, but not to send to other applications on your iPad.


 

Bamboo Paper

iTunes Link

Cost: Free for Base + up to $3.99 to add tools

Screenshot(s):

BambooPaper

 

Comments:

Made by Wacom, famous for the titular Bamboo tablets.  The free version ships with a pen, then for 99 cents each, or $3.99 for all, you can add tools such as Brush, Crayon, Pencil etc.  It’s got a slick package, good export support (including Dropbox) and does feel like working in a notebook.

That said, it’s simply too limited to be used for much more than sketching.  Lack of layer support, minimal dimension options, no selection tools, filters or advanced brushes.

 


 

Paper

iTunes Link

Cost: Free then up to $6.99 for all tools

Screenshot(s):

Paper

Comments:

Paper is a somewhat famous application, as it has been used in Apple promotional materials.  It is also incredibly basic, basically just trying to mimic the drawing on paper experience.  As you can see from the screenshot above, I only have the free version installed.  For up to $6.99 you can add other art tools like a pencil, marker, paint brush, colour mixer, etc.  Export abilities are limited to save to camera roll and send to app.

The drawing is nice and natural, but it’s too limited to be of much use for game development.  Additionally, it’s price is hard justified compared to similar applications.  Can’t really recommend paper other than for sketching if the minimal interface floats your boat.


 

Skeches

iTunes Link

Cost: Free to start, up to $4.99 for all tools, plus text and layers

Screenshot(s):

Sketches

 

Comments:

Sketches is very similar to Paper and  Bamboo Paper, in that it emulates a classic sketchbook.  However the major exception is, with the premium purchase of $4.99 you gain among other things, layer support.  Additionally the free version includes a complete set of tools, but limits the customizability of each.  It contains all of the same tools as the previous two applications.  The interface can be minimized by swiping aside panels.  Navigation is multitouch based and to be honest is confusing as hell until you get used to it.

You are able to export to a number of formats, including Dropbox.  You can select from a number of paper types, but unfortunately have very little control of resolution of the image, maxing out at that of a Retina iPad.

Of all the sketch based drawing applications, this one was easily my favourite, even with it’s somewhat unnatural navigation interface. 


 

Concepts

iTunes Link

Cost: Free to $6.99 for full toolset

Screenshot(s):

Concepts 

 

Comments:

Of all the applications I’ve covered yet, Concepts is probably the most unique, and in some ways, the most powerful.  Designed for creating sketches for concept art, it comes with several tools you haven’t seen yet.  For example, there is a tool for tracing lines and arcs.  There are snapping tools for snapping to the grid.  Speaking of which, the grid can be turned off, on, and set to a number of different densities and formats, including isometric, which can be invaluable if that is the art style you are going for.  There is full layering support, but they are intended for organization/tracing/layering and not artistic effects.  Beyond transparency, there are no blending options for layers.

Artistic tools are somewhat limited to pens, pencils and markers.  More natural art style would be hard to achieve in this program as a result.  That said, the color system is amazing and emulates COPIC markers, allowing you to create pretty much the same tools that concept artists use.

For precision works, this is hands down the best choice out there.  For drawing striaght edges, lines and curves, only the next option comes close.  For more painterly effects, this is a poor choice.  There is no filter or fx support.  Export support is robust, and actually capable of exporting to DXF ( Autocad ), SVG ( Vector ) and PSD formats.  You can also export as an image to the local camera roll, as well as export to Dropbox and others ( including somewhat shockingly, Adobe’s Creative Cloud ).

If you are doing concept art, or going for a technical look, this is hands down your best choice.

 


 

Adobe Illustrator Draw

iTunes Link

Cost: Free!

Screenshot(s):

 AdobeDraw

Comments:

Adobe make a number of products of a very similar nature, Adobe Ideas, Adobe Lines and Adobe Sketch.  Adobe Draw however ties together the best of each of them and has some very interesting abilities.  By far and away the most important feature is the ability to use an angle or french curve ( like shown above ) to draw straight lines and curves.  The actual drawing features are somewhat limited, mostly pen/pencil style drawing implements.  You can control the brush tip size, colour and opacity and that’s it. There is layer support buts it’s tied to each tool somewhat oddly.  The response is quick, the interface is nice and clean and though limited, the brushes are different enough to be useful.

All that said, this application is free.  It’s good and it’s free.  In some ways the drawing tools are amongst the best available.  The angle/french curve functionality is exceedingly well implemented, much better than the curve support in Concepts, which is the only other program that offers similar functionality.  Export functionality is fairly traditional, you can save to the local camera roll, upload to creative cloud and hit the standard share with targets, including Dropbox.  Unfortunately it seems you have little (no?) control over the canvas size.

I don’t really understand the business model here, but free is a wonderful price.  Be sure to check this one out.

 


 

Inkist

iTunes Link

Cost: Free *for a limited time, seemingly forever

Screenshot(s):

Inkist 

 

Comments:

I will be honest, I had a great deal of trouble navigating my way around this application.  Even saving a file was somewhat perplexing.  In many ways it has an interface like many desktop art packages like GIMP or Paintshop.  That interface doesn’t necessarily work on a touch device.

There is actually a LOT of functionality packed in here, more so than most of the packages listed here, except perhaps Photoshop Touch. There is full layering support, but limited to 3 layers ( I think, who knows whats behind that interface that I couldn’t figure out! ), and all kinds of blending functionality between layers.  Art tools are somewhat limited.  I think everything you need is in here, but accessing it is somewhat of a trick.

That said, it’s listed as free for a limited time, and that was over a year ago.  It doesn’t seem like this application is still being developed, so it’s a completely free option.  For that reason alone you should check it out, the interface might click for you better than it did me.  If nothing else, the price is right!

 


 

Pixel Art Packages

 

Sprite Something

iTunes Link

Cost: $4.99

Screenshot(s):

SpriteSomething

 

Comments:

This application is unique in the list as it is specifically aimed at low resolution ( 8/16bit ) pixel art.  At it’s core it’s a fat bit grid editor.  You draw pixel by pixel, although it does have some handy tools like fill, line drawing, etc. There is also layering ability, but there is no blending between layers, it’s literally just stacked pixels. You work in a massively zoomed in window, but you can preview the end result as you work.  There are also tools for doing frame by frame animation sequences, including onion skinning functionality.  This part of the interface can be a bit clunky.

One very unique thing about sprite something is, it has a simple level editor built in as well.  See the video for more details.  Export is limited to email and local camera roll.  If you are working in fat bit pixel style, this is your best ( and almost only ) option. 

 


Codea

iTunes Link

Cost: $9.99

Screenshot(s):

Codea 

 

Comments:

I’m just mentioning this one for thoroughness.  If you are reading this as part of the overarching iPad game creation tutorial, there is a simple pixel art example “Spritely” built into Codea.  Its another fat bit grid editor for pixel art.  It’s very simple but may be enough for you if you have simple requirements.

Obviously not recommended to non-Codea users.

 


Vector Graphics Packages

 

Vector graphics applications work a bit differently than raster packages we described above ( except perhaps Concepts which is a cross between Raster and Vector graphics ).  Raster applications work on a pixel by pixel basis.  Vector graphics on the other hand work on mathematic formulas representing each brush stroke.  This gives you a bit less fine control over the end results, but allows you to scale up or down to any graphic resolution you want.

 

Inkpad

iTunes Link

Cost: Free and Open Source

Screenshot(s):

 Inkpad

Comments:

Completely free and open source, Inkpad is a powerful vector graphics package.  If you’ve ever used Inkscape on a PC, you know what you are in for.  You draw using paths, manipulate curves either straight line or bezier for curved edges and using simple geographic shapes, build, color and layer them to create more complex images. 

Inkpad has full layer support, although they don’t really effect each other like in raster packages.  You can however bring in a standard graphic as a background or to trace over.  Inkscape supports saving as an image locally or exporting as PDF or SVG.

Once again, it’s completely free.  Free is nice.

 

iDraw

iTunes Link

Cost: $8.99

Screenshot(s):

IDraw

 

Comments:

iDraw has one of those iNames iAbsolutely iHate, but don’t judge the package by it’s name.  I absolutely love this package and strongly recommend it to anybody reading this that wants to work with vector graphics.  This application works very similar to Inkpad, except with more functionality, more polish and a higher price tag.  I have struggled in the past with vector graphics applications such as Inkscape ( unwieldy ) and Illustrator ( overwhelming ) and iDraw is the first one that just “clicked” for me.  Once again, the basic concept remains the same, you draw shapes using lines (paths), fill those paths with colors or gradiants, and layer them to make more complex shapes.  One major difference between this and Inkpad is the free form drawing tools, that allow you to use it much more similar to a traditional drawing package.

iDraw is also available as a complete application on Mac and files are interchangeable.  This page has full layer support and is capable of saving directly to Dropbox.  Files can be exported as iDraw, PDF ( very very very useful with Codea as we will soon see ), SVG, PSD, PNG and JPEG, with resolutions of 72, 144 or 300dpi.

 

 

Summary

 

This is only a small subset of graphics packages available on iPad, but does represent a large cross section of them, as well as featuring most of the “big names”.

 

Myself, if I were to only be able to keep a couple applications, my personal choices would be:

  • Photoshop Touch — for image manipulation, modification, effects and some creation
  • iDraw — Vector graphics made easy
  • Adobe Draw — Great sketching app, excellent line and curve support, completely free
  • Sketches — Most versatile drawing app with different brushes like watercolour, paint, etc
  • Concepts — Perfect for technical drawings, similar to Adobe Draw but much more technical, Copic integration
 
If I had absolutely no budget available, I would most certainly recommend people download:
 
  • Sketches — For all your sketching needs, I’d pay for it, so free is awesome
  • Inkpad — Powerful vector graphics, completely free
  • Inkist — The interface is rather awful, but it gives you a lot of editing functionality, completely free
 
All told, that represents under 20$ worth of purchases and provides a level of power way taken together that exceeds any desktop application at many times the price.  Even for a total spend of $0, you can end up with a remarkably complete 2D art package.

Art


15. October 2014

 

With this post we begin our voyage of creating a game from scratch entirely on an iPad.  We start by covering what is perhaps the most important piece, Codea.  This is the part of the puzzle that actually allows us to write and run code on the iPad, so yeah… it’s a bit critical.

 

This post is a bit of a milestone of sorts, this is the very first time I’ve done a voiced over video.  I intend to start doing video production a bit more often to supplement text tutorials, articles and reviews, so I hope you don’t find my delivery overly annoying!  Bear with me a bit while I get used to doing voice work and work out the kinks on video production.  Things will get better!  Um, I hope.

 

Here is the video, don’t worry, a text and picture based version follows for those with a video aversion.  The video is recorded in 1080p, so for the best video quality, I recommend directly opening the file on YouTube.

 

 

So, what exactly is Codea?

 

Basically it’s a complete game development system for iPad, that enables you to create games for the iPad, on the iPad.  It’s Lua based, includes a complete game library, code editor, asset manager, shader programmer, tons of examples and more.  It’s available on the App Store for $10.  Let’s take a quick guided tour of Codea.

 

The Main Interface

 

The interface itself is quite clean and basic.  When you load up Codea, you are greeted by this page:

 

Photo 2014-10-15, 2 21 13 PM

 

Tools

 

Across the top are the examples, across the bottom are your projects.  You can easily clone an example into a project, as you can also duplicate existing projects.  If you notice at the top left there is a bar with an arrow to it’s right.  This brings out the tools panel:

 

Photo 2014-10-15, 2 21 23 PM

 

From the top to bottom we have:

  • Reference – Brings up the integrated help files
  • Shader Lab – An interactive (and excellent) GLSL shader editor
  • Assets -  Asset management ( graphics, sounds, shaders, etc )
  • AirCode – Enable Codea for editing using a computer with a web browser.

 

Settings

 

To the top right is the settings panel.

Photo 2014-10-15, 2 21 18 PM

 

Here you can set your theme and font sizing, and most importantly, link your Dropbox.  This allows you to Dropbox account to Codea, enabling you to easily get assets in and out of Codea, something not easily done on iOS devices.

 

Code Editing

 

When you open a project, this is where you end up:

Photo 2014-10-15, 2 22 11 PM

 

Across the top are tabs representing the files in your project.  Press the + on the top right to create a new class or file.  As you can see, across the top of the soft keyboard, they’ve added a number of keys to make programming easier.  These include a cursor for moving left and right, tab for, um… tabbing.  There is also an integrated Find and Help buttons.  If you hook up a USB keyboard, the soft keyboard goes away.

 

Here is the find dialog:

 

Photo 2014-10-15, 2 20 34 PM

 

And much more important, the integrated help files:

Photo 2014-10-15, 2 20 53 PM

 

Running your code ( clicking the Play icon at the bottom right ), brings you to this screen:

Photo 2014-10-15, 2 20 16 PM

 

The parameters section enable you to create handy UI controls to interact with your app.  Output is basically a text console.  The icons enable you to pause, restart, take a snapshot and video cap of your app running.  When you run Aircode, your iPad goes to this screen, allowing you to live edit code and see it run in real time.

 

Code Editing Helpers

 

I’ll admit, coding on a touch screen without a keyboard isn’t a great experience, but Codea have made the process somewhat more bearable.  First was the keyboard extensions above.  Additionally they have implemented some nice touch friendly features, like:

 

Color Picker:

Photo 2014-10-15, 2 22 20 PM

 

Asset Chooser:

Photo 2014-10-15, 2 22 00 PM

Codea actually includes a fair bit of free content to get you started.

 

Font Chooser:

Photo 2014-10-15, 2 22 14 PM

 

GLSL Editor

I mentioned earlier that there is an integrated GLSL editor:

Photo 2014-10-15, 2 21 33 PM

You can edit the Vertex and Fragment scripts and see the result in realtime on the right.  The Bindings is where you can set parameters in to your shader.  As I said in the video, I really hope this gets spun off into it’s own product!

 

 

It’s a clean, simple but fairly comprehensive set of tools.  The included samples are quite impressive as well.   We will cover coding at a point in the future.

 

So that’s Codea.  We will get to know it a lot better of the next few weeks.

Programming


11. October 2014

 

 

So at this point in time we’ve covered configuring Cocos2d-x, basic graphics, mouse, touch and keyboard event handling but wouldn’t it be nice to, you know… do something?  Most games are pretty boring if they are completely static, no?  Well in this tutorial section we are going to make things a bit more interesting.  One of the ways we are going to add a bit of life to our game is using Actions, which we will cover in a second.  First we need to cover something else, the game loop.

 

Handling Updates

 

Pretty much every game ever made has a game loop, even if it’s hidden by the game engine.  A Cocos2d-x game is no exception, although it might not be immediately obvious.

What's a game loop?


A game loop is essentially the heart of a game, what causes the game to actually run. The following is a fairly typical game loop:

void gameLoop(){
   while (game != DONE){
      getInput();
      physicsEngine.stepForward();
      updateWorld();
      render();
   }
   cleanup();
}

 

As you can see, it's quite literally a loop that calls the various functions that make your game a game.  This is obviously a rather primitive example but really 90% of game loops end up looking very similar to this.

 

However, once you are using a game engine, things get slightly different.  All this stuff still happens, it’s just no longer your codes responsibility to handle it anymore.  Instead the game engine performs the loop and each step then calls back to your game code.  Consider when your game handles input events, where do those events come from?  Well chances are the game engine has a getInput() somewhere inside it, and as part of that process calls your event handlers.  Even though you don’t have to handle the games lifecycle yourself, it’s helpful to understand what’s going on behind the scenes.

 

So far in all of our examples we either handled everything in init() or in response to input event callbacks and that can only get you so far.  What happens when you want to update your game independently to input events?  One option is to update your game every time you render a frame of graphics, but this is generally not a great idea.  It’s very common to try to run graphics as fast as possible but update the game at a fixed frequency.  Plus, logically, does it really make sense to be updating stuff during a function that’s responsible for drawing graphics?  No, not really.

 

Fortunately there is a ready and much better named alternative… you guessed it, update.  The method update is part of the Node class and is easily overridden.  Let’s take a quick look at a game that handles update.  I got so sick of recreating scenes each time I created a new project, so the name might look somewhat familiar.

Also you are going to need a sprite for this sample.  Personally I am using a picture of my car… yeah, that’s it.

 

 

Veyron

 

Feel free to use whatever you want.  Now the code:

 

HelloWorld.h

#pragma once

#include "cocos2d.h"

class HelloWorld : public cocos2d::Layer
{
public:
    static cocos2d::Scene* createScene();
    virtual bool init() override;
    CREATE_FUNC(HelloWorld);

    void update(float) override;

private:
   cocos2d::Sprite* sprite;
};

 

HelloWorld.cpp

#include "HelloWorldScene.h"

USING_NS_CC;

Scene* HelloWorld::createScene()
{
    auto scene = Scene::create();
    auto layer = HelloWorld::create();
    scene->addChild(layer);
    return scene;
}

bool HelloWorld::init()
{
    if ( !Layer::init() )
    {
        return false;
    }
    
    sprite = Sprite::create("Veyron.png");
    sprite->setPosition(this->getBoundingBox().getMidX(), this->getBoundingBox().getMidY());
    this->addChild(sprite, 0);
    
    this->scheduleUpdate();
    return true;
}

void HelloWorld::update(float delta){
   auto position = sprite->getPosition();
   position.x -= 250 * delta;
   if (position.x  < 0 - (sprite->getBoundingBox().size.width / 2))
      position.x = this->getBoundingBox().getMaxX() + sprite->getBoundingBox().size.width/2;
   sprite->setPosition(position);
}

 

Now, if you run the code you get:

 

action1

 

So what’s going on here?  Well think back to that game loop example I gave earlier.  Now imagine somewhere deep inside Cocos2d-x when it performs the “updateWorld” portion, that it loops through all the the Nodes in the game and calls their update() method.  Well that’s basically exactly what happens.  The line:

 

     this->scheduleUpdate();

 

Is what tells Cocos2d-x to call the Node's update function.  We then override update to implement our logic.  The sole paramater passed to update is a float value representing the amount of time, in seconds since the last time the update function was called.  Therefore if it’s been 1/10 of a second since the last time update was called, the value passed in will be 0.1.

 

Inside the update itself, we simply change the position of our sprite until it is fully off screen on the left hand side.  At which point we move it to the right hand side and repeat the process.  The only code that is of interest here is this line:

position.x -= 250 * delta;

 

This is a pretty common technique in game dev for creating smooth animations.  What we are saying here is we want to move by 250 pixels to the left.  The problem is, we have no idea how fast our update is going to be called, so on a faster computer the car will move faster and on a slower computer it will move slower.  This is obviously not ideal.  Enter the delta value.  Since we know how long it was since the last frame, we know if we multiply our move amount by the fraction of a second each frame takes, it will perform roughly the same speed on all computers.  So, using the 0.10 value above, this means we are running 10 updates per second, so each time we will be updating by 250 * 0.10 or 25, literally a 10th of the amount we want to update.  If however this value is over one second, things will get screwy.  That said, if your game is running at less than 1FPS, you’ve got bigger problems to worry about!  So, in a nutshell, when moving on a frame by frame basis, express your units in seconds, then multiply them by the delta passed in to the update function.

 

Now remember earlier when I said it’s possible to run your updates in the render method but it wasn’t always ideal, how then do we control the frequency that our update is called?

 

Well, we can’t really as you never know how fast the computer or phone you are going to be running is.  You do however have control over the priority the updater will view your update function with.  By default when you call scheduleUpdate() your update function will be called every single frame.  If the node you are updating doesn’t actually need to be updated every frame, you are just wasting CPU power ( and battery life ).  If you have a lower priority update you can tell Cocos2d-x this using:

this->scheduleUpdateWithPriority(42);

 

The actual value passed in is simply relative to other priorities.  When Cocos is trying to decide which update’s to call, it will first call all of the update() that don’t have a priority set.  Then it will call the one with the lowest value, then the next highest, etc.  So if you have three Node with update set, one with no priority set, one with a priority of 42 and one with a priority of 13, the no priority update will be called first, then the 13 and finally the 42.  In some ways you aren’t actually setting the priority, you are setting the lack of priority! 

 

In place of overriding update() you can also use schedule and scheduleOnce to schedule any function to be called.  Either after a period of time or a number of times.  The called function needs to have the same profile as update, that is takes a single float parameter and a void return type.

 

Sometimes however instead of reacting each frame and updating your world, you just want to “fire and forget” something.  For example let’s say you want to move an object to a certain location over a certain period of time.  This is where Actions come in.

 

Using Actions

 

As just mentioned, Actions allow you to set something in motion and forget about it.  Actions are remarkably consistent in how they work, so I will only show small snippets of code for each one.  We are using the following code as our base:

 

#include "HelloWorldScene.h"

cocos2d::Scene* HelloWorld::createScene()
{
    auto scene = cocos2d::Scene::create();
    auto layer = HelloWorld::create();
    scene->addChild(layer);
    return scene;
}

bool HelloWorld::init()
{
    if ( !Layer::init() )
    {
        return false;
    }
    
    sprite = cocos2d::Sprite::create("Veyron.png");
    sprite->setPosition(this->getBoundingBox().getMidX(), this->getBoundingBox().getMidY());
    this->addChild(sprite, 0);
    
    auto listener = cocos2d::EventListenerKeyboard::create();
    listener->onKeyPressed = [=](cocos2d:: EventKeyboard::KeyCode code, cocos2d::Event * event)->void{
      // This is where our different actions are going to be implemented
      auto action = cocos2d::MoveTo::create(2, cocos2d::Vec2(0, 0));
      sprite->runAction(action);
   };

    this->_eventDispatcher->addEventListenerWithSceneGraphPriority(listener,this);
        return true;
}

 

This is also our first example of using an Action. In this case we are using the MoveTo action to move the target node to the position (0,0) over a duration of 2 seconds. You run the action on a Node using the runAction method.  Run it and press any key and you will see:

 

MoveTo

 

There are several similar actions, let’s take a look at a couple of them now.  Instead of MoveTo, there is also MoveBy, which enables you to move your node relative to it’s current position, like so:

 

   auto listener = cocos2d::EventListenerKeyboard::create();
   listener->onKeyPressed = [=](cocos2d:: EventKeyboard::KeyCode code, cocos2d::Event * event)->void{
      auto action = cocos2d::MoveBy::create(2, cocos2d::Vec2(300, 300));
      sprite->runAction(action);
   };

 

When you run this, instead of moving to a destination over a period of 2 seconds, we instead move by 300 right and 300 up over the same time period.

 

MoveBy

 

There are several similar Actions that can be used to transform and modify a Node such as RotateBy, RotateTo, ScaleTo, SkewTo, TintTo, TintBy and more.

 

In addition to transforming nodes, you can actually loop and sequence actions, to make combo’s.  Let’s take a look at an example of a sequence of several actions.  In this example we are going to perform a ScaleBy, TintTo then FadeTo back to back using the Sequence action.

 

   listener->onKeyPressed = [=](cocos2d:: EventKeyboard::KeyCode code, cocos2d::Event * event)->void{
      cocos2d::Vector<cocos2d::FiniteTimeAction*> actions;
      actions.pushBack(cocos2d::ScaleBy::create(1.5, 1.5));
      actions.pushBack(cocos2d::TintTo::create(1.5, 255, 0, 0));
      actions.pushBack(cocos2d::FadeTo::create(1.5, 30));
      
      auto sequence = cocos2d::Sequence::create(actions);

      sprite->runAction(sequence);
   };

 

And when run:

Sequence

 

There are two things to be aware of from this example. First you may notice that TintTo takes three GLubyte values to repesent the red, green and blue values of the colour, while FadeTo takes a single GLubyte value to represent that alpha or transparency.  A GLubyte is an 8bit value that ranges from 0 to 255 in value.  In all cases 255 is the fully on value, and 0 is the fully off value.  Therefore the value (255,0,0) is 100% red, 0% green, 0% blue, while the value 30 in TintTo is 30/255 or 11.7% opaque.  The second import thing to note is the use of Vector.  This is a cocos2d value type, NOT a std::vector, although ultimately behind the scenes, I believe it is still implemented using a std::vector.  This means you cant use it as a std::vector, nor can you use a std::vector where a cocos2d::Vector is expected.  This also unfortunately means you can’t use initializer lists.

 

So, that’s how you can perform a number of actions in sequence, what happens if you want to perform them all at once?  You can do that too using Spawn, which personally I think could really have a better name!  Let’s look at exactly the same example using Spawn instead.  The only difference is I increased the duration of each action to 4 seconds, mostly just to make it easier to screen capture. :)

 

   listener->onKeyPressed = [=](cocos2d:: EventKeyboard::KeyCode code, cocos2d::Event * event)->void{
      cocos2d::Vector<cocos2d::FiniteTimeAction*> actions;
      actions.pushBack(cocos2d::ScaleBy::create(4, 1.5));
      actions.pushBack(cocos2d::TintTo::create(4, 255, 0, 0));
      actions.pushBack(cocos2d::FadeTo::create(4, 30));
      
      auto parallel = cocos2d::Spawn::create(actions);

      sprite->runAction(parallel);
   };

 

And run it:

parallel

 

You also have the ability to repeat actions, both a certain number of times, or simply forever.  That is exactly what this example is going to do.  The first action moves to the right by 10 pixels every 0.2 of a second.  The second action scales the sprite up 30% every 2 seconds.  The first action will be repeated 10 times, the second forever, or until it crashes your computer that is. :)

 

   auto listener = cocos2d::EventListenerKeyboard::create();
   listener->onKeyPressed = [=](cocos2d:: EventKeyboard::KeyCode code, cocos2d::Event * event)->void{
      auto action = cocos2d::MoveBy::create(0.2, cocos2d::Vec2(10, 0));
      auto action2 = cocos2d::ScaleBy::create(2, 1.3);
      auto repeat = cocos2d::Repeat::create(action, 10);
      auto repeatForever = cocos2d::RepeatForever::create(action2);

      sprite->runAction(repeat);
      sprite->runAction(repeatForever);
   };

 

Running:

repeat

 

So far we’ve only looked at Actions inherited from ActionInterval, which are actions that happen over time.  There are also actions that happen instantly, let’s take a look at some of them now.  These actions inherit from ActionInstant.  In this example we illustrate several instant actions ( as well as a MoveTo, DelayTime and Sequence, as a bunch of instant actions doesn’t make for a great demonstration! )

 

   auto listener = cocos2d::EventListenerKeyboard::create();
   listener->onKeyPressed = [=](cocos2d:: EventKeyboard::KeyCode code, cocos2d::Event * event)->void{
      cocos2d::Vector<cocos2d::FiniteTimeAction*> actions;
      actions.pushBack(cocos2d::MoveTo::create(1, cocos2d::Vec2(0, 0)));
      actions.pushBack(cocos2d::DelayTime::create(1));
      actions.pushBack(cocos2d::Place::create(cocos2d::Vec2(
         this->getBoundingBox().getMidX(), this->getBoundingBox().getMidY())));
      actions.pushBack(cocos2d::DelayTime::create(1));
      actions.pushBack(cocos2d::FlipX::create(true));
      actions.pushBack(cocos2d::DelayTime::create(1));
      actions.pushBack(cocos2d::FlipY::create(true));
      actions.pushBack(cocos2d::DelayTime::create(1));
      actions.pushBack(cocos2d::Hide::create());
      actions.pushBack(cocos2d::DelayTime::create(1));
      actions.pushBack(cocos2d::Show::create());
      actions.pushBack(cocos2d::DelayTime::create(1));

      actions.pushBack(cocos2d::CallFunc::create([=]()->void{
         this->setColor(cocos2d::Color3B::RED);
      }));

      actions.pushBack(cocos2d::DelayTime::create(1));
      actions.pushBack(cocos2d::RemoveSelf::create(false));

      auto sequence = cocos2d::Sequence::create(actions);
      sprite->runAction(sequence);
   };

 

This code running:

Instant

 

As you can see, instant actions work almost indentically.  FlipX mirrors the Node along the X axis, FlipY does the same across the Y axis.  DelayTime we havent used yet, does exactly what it’s name says, delays for the given amount of seconds before executing the next Action.  The Place action can by thought of as a 0 duration MoveTo call, putting the Node at the specified position.

 

CallFunc and RemoveSelf are the two actions that probably require the most explanation.  CallFunc enables you to call code using an action, in this case I use a lambda that simply changes the background color of the Layer.  CallFunc is an incredibly important action and allows you to do just about anything using Actions, such as updating state, playing a sound, etc.  RemoveSelf is another handy action… it’s basically a kill switch.  When a removeSelf action is encountered, that Node is removed from it’s parent.  Passing true causing cleanup to be done.  This is incredibly handy for something like handling the lifespan of a bullet in the scene for example.

 

Setting a Layer's Background Color


You may have noticed I changed the background of the scene in the previous example using a call to setColor(). However if you try to run this code as is, you will notice it doesn't actually work. This is because, behind the scenes, I made a couple small changes. Instead of our scene inheriting from Layer we instead inherit from LayerColor, which adds, you guessed it, color information. Additionally, install of calling Layer::init() in our own init, we call LayerColor::initWithColor(). With these two changes you can now set the background color in the layer.

 


Odds and Ends

 

There are a few interesting topics that fit into this chapter but we didn’t cover yet, so I am going to shoehorn them here at the end.  One very common activity developer’s want to perform when working with Actions is to pause them.  As you can have several Actions running at once, so then, what do you do when you want to pause your game?  Thankfully it’s quite simple to accomplish using ActionManager.

 

HelloWorldScene.h

#pragma once

#include "cocos2d.h"

class HelloWorld : public cocos2d::LayerColor
{
public:
    static cocos2d::Scene* createScene();
    virtual bool init() override;
    CREATE_FUNC(HelloWorld);

private:
   cocos2d::Sprite* sprite,*sprite2;
   cocos2d::Label* label;
   bool spritePaused = false;
   cocos2d::Vector<Node*> pausedNodes;
};

 

HelloWorldScene.cpp

#include "HelloWorldScene.h"

cocos2d::Scene* HelloWorld::createScene()
{
    auto scene = cocos2d::Scene::create();
    auto layer = HelloWorld::create();
    scene->addChild(layer);
    return scene;
}

bool HelloWorld::init()
{
   if (!LayerColor::initWithColor(cocos2d::Color4B::BLACK))
    {
        return false;
    }
    
   label = cocos2d::Label::createWithSystemFont("Press space to pause all, 1 to pause left", "Arial", 30);
   label->setPosition(cocos2d::Vec2(this->getBoundingBox().getMidX(), this->getBoundingBox().getMaxY() - 20));

   sprite = cocos2d::Sprite::create("Veyron.png");
   sprite2 = cocos2d::Sprite::create("Veyron.png");
   sprite->setPosition(250, this->getBoundingBox().getMidY());
   sprite2->setPosition(700, this->getBoundingBox().getMidY());

   auto rotate = cocos2d::RotateBy::create(1, 45);
   auto rotate2 = cocos2d::RotateBy::create(1, -45);

   auto repeat1 = cocos2d::RepeatForever::create(rotate);
   auto repeat2 = cocos2d::RepeatForever::create(rotate2);

   this->addChild(label,0);
   this->addChild(sprite, 0);
   this->addChild(sprite2, 0);
    
   sprite->runAction(repeat1);
   sprite2->runAction(repeat2);
   auto listener = cocos2d::EventListenerKeyboard::create();
   listener->onKeyPressed = [=](cocos2d::EventKeyboard::KeyCode code, cocos2d::Event * event)->void{
      // On Spacebar, Pause/Unpause all actions and updates
      if (code == cocos2d::EventKeyboard::KeyCode::KEY_SPACE){
         if (pausedNodes.size()){
            cocos2d::Director::getInstance()->getActionManager()->resumeTargets(pausedNodes);
            pausedNodes.clear();
            spritePaused = false; // In case user currently has 1 pressed too
         }
         else
            pausedNodes = cocos2d::Director::getInstance()->getActionManager()->pauseAllRunningActions();
         label->setString("Spacebar pressed");
      }
      // Pause/UnPause just sprite 1
      if (code == cocos2d::EventKeyboard::KeyCode::KEY_1){
         if (spritePaused)
            sprite->resumeSchedulerAndActions();
         else
            sprite->pauseSchedulerAndActions();
         spritePaused = !spritePaused;
         label->setString("1 pressed");
      }
      
   };

   this->_eventDispatcher->addEventListenerWithSceneGraphPriority(listener,this);
   return true;
}

 

And run it:

ActionManager

 

As you can see using ActionManager you are able to pause execution of Actions, either to a single Node or all Nodes at once.  In the event of a single Node it’s simply a matter of calling pauseSchedulerAndActions and resumeSchedulerAndActions.  You can also call pause() which is also result in the Node no longer receiving events too.

 

In the event of pausing all running actions by calling getActionManager()->pauseAllRunningActions() this returns a cocos2d::Vector off all the Nodes that were paused.  When resuming, you simply pass this Vector back in a call to resumeTargets().

 

Earlier on we called scheduleUpdate() with resulted in our update method being called every frame.  However you can also schedule any kind of function using the scheduler.  Let’s take a look:

 

#include "HelloWorldScene.h"

cocos2d::Scene* HelloWorld::createScene()
{
    auto scene = cocos2d::Scene::create();
    auto layer = HelloWorld::create();
    scene->addChild(layer);
    return scene;
}


void HelloWorld::callOnce(float delta){
   cocos2d::MessageBox("Called after 10 seconds elapsed", "Message");
}

bool HelloWorld::init()
{
   if (!LayerColor::initWithColor(cocos2d::Color4B::BLACK))
    {
        return false;
    }
   
   this->scheduleOnce(schedule_selector(HelloWorld::callOnce), 10);
    return true;
}

 

This code will wait 10 seconds and then call our method callOnce().

 

So, even though the event loop is hidden away in a Cocos2d-x, there are plenty of ways you can control the action, be it using updates, scheduling functions to run or using Actions.

 

Programming


29. September 2014

 

 

Welcome to the GameFromScratch.com Cocos2d-x tutorial series.  Cocos2d-x is a cross platform, C++ based port of the popular Cocos2D ObjectiveC game development library. Using the most recent version of Cocos2D-x you can target Windows, Mac, Linux, iOS and Android.  Previous versions enabled you to target even more targets including Blackberry and Tizen.  The history of Cocos2D-x is actually very important, as it factored in many of the design decisions that the library has taken.

 

This series will walk through the all aspects of using Cocos2d-x to create a game.  This particular part covers the process of getting Cocos2d-x installed, creating an initial project and looks at a bare bones Hello World example.

 

Cocos2D History

 

As I mentioned earlier, the history of Cocos2D is fairly important to understanding how it works, so we are going to start of with a quick, hopefully not-boring, history lesson.  I promise you, this will be the only history lesson in this entire series!  Unless of course I do more of them…  If you want a more thorough history, you can always check out the wiki.

 

Ok… history time.

 

Way back in 2008, Cocos came to be, named after the town of Los Cocos, Argentina, in case you were wondering where exactly the name came from.  It started from a gathering of Python developers in, you guessed it, Los Cocos.  As you may be able to guess from the fact it was started by a bunch of Python developers, Cocos started off being written in Python.

 

Then came along this little phone named the iPhone, and a version of Cocos2D was ported to ObjectiveC for use on iOS, the aptly named cocos2d-iphone.  A number of Cocos2d-iphone developed apps started appearing on the iPhone, including StickWars, which hit number 1 on the App Store.  Now we hit the fast forward button on history and see that Cocos2d is ported to a number of platforms.

 

One of those ports was of course Cocos2d-x, which was a port of Cocos2D to C++, the subject of our tutorial here.  Cocos2d-x itself also spawned a number of ports, including HTML and XNA.  Along the way a number of tools were developed as well, including an editor named CocosStudio (itself the spawn of a number of child projects ) and CocosCodeIDE and IDE for Lua and JavaScript scripting in Cocos2d-x.

 

So, why does this all matter?

 

Well, it’s important that you be aware that Cocos2d-x is a port of an Objective-C library which itself was a port of a Python library.  Each language and platform has had an effect on the development of Cocos2d-x, for better or worse.  You will run into some concepts and think “why the hell did they do this?”.  More often than not, it’s Cocos2D’s history that provides the reason.

 

One final important thing to realize with Cocos2d-x, a number of the most active developers behind the project are not primarily English speakers.  Cocos2D-x is extremely popular in China for example.  This is by no means a negative, but we aware sometimes language can be a bit of a barrier when looking for help and reading documentation.

 

 

What Version are you using?

 

At the point I am writing this, I am using Version 3.3beta 0 to create tutorials, and as new versions are released I will try to stay with the most recent version.  This is because I am trying to future proof this series as much as possible.  In all honesty, I know this is going to be quite annoying as well, when I created by cocos2d-html5 tutorial series, the number one problem was version changes.  Cocos2d-x is a library that get’s refactored quite a bit, so if you are far in the future and some code I provided doesn’t work, this is probably why.  Always make sure to read the comments at the bottom of each part, it may contains clues to the problem you are facing.

 

So then, what version should you use?  That answer is a bit trickier.  You have a choice between Cocos2d 2.x, 3.0 or 3.x right now.  The 2.x version is obviously the older version and less actively developed, if at all (edit – according to this thread, 2.x is no longer being supported).  That said, 2.x also supports the most platforms, including Windows Phone, Marmalade, Tizen, Blackberry and more.  Additionally, as of writing, every single book targets 2.x.  3.2 is the (currently) stable release of the most current version, while 3.x is the development version.

 

Again, I will be using the most current version as I go, and if history has taught me anything, this is going to lead to tons of issues! ;)  Warning, Here be dragons!

 

HTBD

 

 

 

Setting Up Cocos2D-x

 

In order to get started with Cocos2d-x, you need to have a couple things installed already, depending on platform you are developing on. 

 

Obviously you need a C++ compiler.  If you are working on Windows, Visual Studio 2013 is currently the recommended version.  You can download a free version named Visual Studio Express for Windows Desktop  ( note, there is also a version called Visual Studio Express for Windows, you do NOT want this version… yeah, brilliant naming by Microsoft there eh? ).  Of course if you have a complete version installed it will work fine as well.  You can also use older versions of Visual Studio, back to 2010 I believe, but this series will assume you are using the most recent version.

 

On Mac OS, Xcode is the obvious solution.  It’s also free, so that’s nice.  As of writing Xcode 6 is currently in late beta, but will work just fine.  Xcode 5 should also work just fine.  Personally I am not a huge Xcode fan and use AppCode for development on Mac, but it is not a free tool.  You may see it on occasion in screenshots, so I figured I would put it out there.  By default Xcode does not install the command line tools, so I would install those as well, you can find instructions here and official documentation here.

 

You also need to have Python installed.  Don’t worry, Python isn’t used to code in Cocos2d-x, but some of the tools require it, including the tool you use to create your project, so obviously this install is pretty important.  Another important note, so I’m going to use bold and shout at you for a second.  YOU NEED TO INSTALL PYTHON 2.7x!  The newest version, Python 3.x does not work and you will be wasting your time.  So go ahead download Python 2.7.x here.  On Windows you want to make sure Python is added to the PATH environment variable.  If it isn’t, you can get instructions here.

 

Finally if you are intending to develop for Android, you need to have a version of the Android SDK, ANT and Android NDK installed.  You need at least version 9 of the NDK ( 10 is the current as of writing.  EDIT – NDK 10 currently doesn’t work!  Read here for details.  Here for the ticket.  There is a work-around, but using NDK 9 is probably your easiest bet ) to work with Cocos2d-x.  Now to make life slightly more complicated, if you are on Windows, the Android NDK also requires Cygwin 1.7 or higher to be installed.  Fortunately, Cygwin has no further requirements.  When downloading the Android SDK, do not download the ADT package, but instead scroll further down the page and install using the “Get the SDK for an existing IDE” link.  As an FYI, the SDK is the Java SDK along with the tools needed for Android development, the NDK is the C++ toolchain for Android development, while Ant is a Java build system.

 

Please note, Cocos2d-x and be used with other IDE’s such as Eclipse or Qt Creator, but I will not be covering the process in this tutorial.

 

Oh and of course you need to download cocos2d-x itself!  Simply download and extract the library somewhere on your system.

 

 

Creating a Cocos2d-x project

 

Ok, now that you’ve got everything installed and configured, it’s time to create a project.  Open up a terminal window or command line and change to the directory you extracted cocos2d-x.

 

MacOS  Cocos2d Config and New Project Instructions:

 

Enter:

./setup.py

source ~/.profile

cocos new -l cpp -p com.gamefromscratch.gamename -d ~/Documents/Projects/cocos2d gamename

Ss6

 

Windows Cocos2d Config and New Project Instructions:

 

Open a command prompt and CD to the directory you extracted Cocos2D to.  Run the command:

python setup.py

 

If you get an error about not being able to find Python, that PATH is not configured correctly.  Depending if you have certain environment variables set or not, the install may now ask you the install directory of your Android NDK, SDK as well as Ant, provide them.  If you’ve not installed the NDK and SDK before now, do so before performing this step.

 

The next step depends on your operating system version.  If you are running Windows XP ( and possibly Vista ), you now need to restarted your computer for the changes to take effect.  If you are running Windows 7 or 8.x, simply close your command prompt and open a new one.

 

Now type:

cocos new -l cpp -p com.gamefromscratch.gamename -d C:\path\to\game\here gamename

 

Creating a New Project:

 

The tool to create cocos projects is “cocos” and it resides in [cocosSDKfolder]/tools/cocos2d-console/bin.  -l is an L by the way, this is where you specify the language for the project you want to create.  The options are cpp and lua currently, in this case we want cpp.  -p is for specifying the package, mostly for Android I assume.  This uses Java’s standard reverse domain name format.  Don’t worry if you don’t have a website, make something up.  The -d parameter is the directory where you want to create the project.

 

Now that our project is (hopefully!) created, lets take a look at what it’s created for us.

 

Ss1

 

Here you can see it has created a number of key directories for you, we will take a closer look at each one.

 

Each folder prefixed with proj. is where project files and platform specific code goes, be it android, iOS and Mac, linux, Windows or Windows Metro ( or.. what was previously known as Metro ). 

 

The cocos2d folder however is where the cocos SDK itself is copied.  This is a complete copy of Cocos2d, including docs, libraries, headers, etc.  Just a warning, this folder is 250MB in size and will be created for each cocos2D project you create using cocos new!  You can set up your projects to use a common install of cocos2d-x, by specifying the engine path when calling cocos new.  Just be aware, if you are tight on space and are going to be making a number of cocos2d-x projects, you may want to look into this further.

 

The resources folder is a common repository for all the various assets that your game will use, such as graphics, sound, etc.  The Classes folder is perhaps most important of all, this is where your non platform specific code goes!  Right now the contents should look like:

Ss2

 

These code files create a simple application to get you started, although we are ultimately going to replace the contents.  The expression AppDelegate comes from Mac programming, so if you are a Windows or Linux developer, it might be a bit alien to you.  An AppDelegate is a helper object that goes with the main window and handles events common to applications such as starting up, minimizing and closing.  You won’t really spend much time here, that instead is where the Scene file comes in.  We will look at code shortly so each piece will make a bit more sense.

 

Now let’s look at the platform specific portions for both win32 and ios_mac.

 

win32:

Ss3

 

ios_mac:

Ss4

 

As you can see, each folder contains all the platform specific code, resources and most importantly, project files for each platform.  In the case of ios_mac, it further contains platform specific folders for each platform.

 

All platforms have their own unique entry point ( main, WinMain, etc ) and different ways of handling different things.  Most of this is just relevant on start up and cocos2d-x takes care of this for you.  However at some point in the future you may need to add platform specific code, such as perhaps an ad network that only works on iOS.  This is where you would add platform specific code.  That said, 99% of your game logic should be put in the common Classes folder.  This make’s it so you can write your code in one platform, then simply open up the project files for another platform and run your game.  This is how you are able to handle many platforms with a single code base using cocos2d-x.

 

Getting Started — MacOS/XCode

 

To get started developing on MacOS, double click the .xcodeproj in the folder proj.ios_mac.  This should automatically load Xcode for you.  Now at the top bar you should be able to select which project you want, iOS or Mac.  As iOS requires the simulator or a device to execute, initially developing on the Mac can be a great deal quicker.

 

Ss5

 

Getting Started — Windows/Visual Studio

 

To get started developing on Windows, double click the .sln file in the folder proj.win32.  This will load Visual Studio for you.  Simply press Play (Local Windows Debugger) to start the compilation process:

image

 

Once you’ve selected, simply click the Play icon.  Your project will now compile and a few minutes later you should see:

Ss7

 

If you are new to C++, don’t worry, the first compilation is always the nastiest.  From now on when you press play, the compilation should be many times faster.

 

You can also run directly from the terminal using the cocos utility, like so:

 Ss8

Use -p ios to run iOS.  This command requires you to have installed the command line tools mentioned earlier.  Running from the terminal makes it so you don’t have to open the Xcode IDE if you prefer.

 

 

Hello World

 

Now let’s take a look at the minimal useful cocos2d-x application.  While the cocos new created project creates a Hello World application of sorts, it’s a pretty sloppy starting point.  First, it has needlessly complications for an app that is supposed to be a minimum example, it’s commented in a manner that only makes sense if you come from an Objective-C background and finally, it even uses deprecated methods.

 

Therefore we are going to look at a cleaner Hello World sample.  We simply replace the code in each file with the code I provide below.  Don’t worry, all of the functionality we hack out will be covered in future tutorials.

Let’s start with the AppDelegate class.

 

AppDelegate.h

#pragma once

#include "cocos2d.h"

class  AppDelegate : private cocos2d::Application
{
public:
    AppDelegate();
    virtual ~AppDelegate();

    virtual bool applicationDidFinishLaunching();
    virtual void applicationDidEnterBackground();
    virtual void applicationWillEnterForeground();
};

 

 

AppDelegate.cpp

#include "AppDelegate.h"
#include "HelloWorldScene.h"

USING_NS_CC;

AppDelegate::AppDelegate() {

}

AppDelegate::~AppDelegate() 
{
}

bool AppDelegate::applicationDidFinishLaunching() {
    auto director = Director::getInstance();
    auto glview = director->getOpenGLView();
    if(!glview) {
        glview = GLViewImpl::create("Hello World");
        glview->setFrameSize(640, 480);
        director->setOpenGLView(glview);
    }

    auto scene = HelloWorld::createScene();
    director->runWithScene(scene);

    return true;
}

void AppDelegate::applicationDidEnterBackground() {
}

void AppDelegate::applicationWillEnterForeground() {
}

 

The biggest change I have made from the default implementation is to remove all but the barest requirements of an application.  You may notice I’ve also replaced the include guards with pragma once statements.  Some people will find this controversial because pragma once isn’t standard and therefore unportable.  This may be true, if you are using a compiler from 1985.  If on the other hand you are using any modern C++ compiler, pragma once is supported.  Include guards and pragma once perform the same task, except pragma once is more concise and less error prone.  If you want to switch back to include guards, feel free.  From this point on, I will however, not be using them.

 

OK, back to the code itself.  Our AppDelegate header is pretty straight forward, it declares a constructor, destructor and three methods, applicationDidFinishLaunching, applicationDidEnterBackground and applicationWillEnterForeground.  All three of these methods are pure virtual functions from ApplicationProtocol, from which Application ( and in turn AppDelegate ) inherit, so we must provide an implementation of each, even if it’s empty.

 

Now onto AppDelegate.cpp.  First we start off with the macro USING_NS_CC; which is just short for “using namespace cocos2d”.  Personally I don’t see a big win in using a macro over typing using namespace cocos2d, but generally I find many uses of macros unagreeable.  This however is the style the cocos team went with, so I will follow along.  As you can see, both or constructor, destructor, applicationDidEnterBackground and applicationWillEnterForeground all have empty implementations, so applicationDidFinishLaunching is where all of our logic resides.

 

If these names seem a bit long winded to you, they have been taken directly from the iOS world.  Basically the enterBackground/enterForeground methods are called when your application gains and loses focus, while applicationDidFinishLaunching is called when your application is loaded ( at the end of the loading process ).  Here we get an instance of the Director singleton, then use it to either get the GLView, or create a GLViewImpl, which is a default implementation of GLView.  Basically GLView is the OpenGL representation of your window or screen, depending on what kind of device you are running.  We then set the resolution of the window ( this is not required, I just wanted a smaller resolution for screen shots ) by calling setFrameSize() then set the view as active by calling Director’s setOpenGLView().  Now that we have a window, we create an instance of our scene calling createScene() and once again, use the Director to set this scene active using runWithScene().

 

Aren't Singletons bad?

You may notice in the above code that Director is very important to the operation of Cocos2d-x.  Director is an implementation of a design pattern known as a Singleton, or as some would say, an anti-pattern.  If you’ve spent much time on programming forums, you will see thread after thread calling Singletons evil.  In a nutshell, a singleton is a delayed, but guaranteed to be instantiated global variable in a pretty dress.  Sometimes too, a global variable is just what you need, which is why you will find a number of game engines make use of singletons to provide globally available interfaces.  At this point the matter is pretty much moot, if you use Cocos2d-x, you use Director, or you don’t use Cocos2d-x.

One of the major source of bugs with Singletons, especially in C++, is multithreading.  When you have this global instance being access from all kinds of locations and controlling so many things, how do you handle concurrent requests?  Well have I got good news for you!  You don’t. :)

That’s because Cocos2d-x isn’t thread safe.  Or more accurately, Cocos2d-x’s memory management ( anything derived from cocos2d::Ref ) and OpenGL rendering aren’t thread safe.  To make this clear, you can use threads in a Cocos2d-x application, but you need to be very careful what those threads interact with.  Other than the threading problems, some of the biggest problems that come from using Singletons are related to code maintenence, as you are coupling so many systems together.  Fortunately, this is the cocos2d-x team’s problem to deal with, not yours.  Unless of course you are on the Cocos2d-x team that is.

 

Now let's take a look at our scene, HelloWorldScene.

 

HelloWorldScene.h

#pragma once

#include "cocos2d.h"

class HelloWorld : public cocos2d::Layer
{
public:
    static cocos2d::Scene* createScene();
    virtual bool init();  
    
    CREATE_FUNC(HelloWorld);
};

 

HelloWorldScene.cpp

#include "HelloWorldScene.h"

USING_NS_CC;

Scene* HelloWorld::createScene()
{
    // 'scene' is an autorelease object
    auto scene = Scene::create();
    auto layer = HelloWorld::create();

    scene->addChild(layer);

    return scene;
}

bool HelloWorld::init()
{
    if ( !Layer::init() )
    {
        return false;
    }
   
    auto label = Label::createWithSystemFont("Hello World", "Arial", 96);
    label->setAnchorPoint(cocos2d::Vec2(0.0, 0.0));
    this->addChild(label, 1);

    return true;
}

 

In our header once again I’ve replaced the header guard with pragma pack.  We are declaring our scene class HelloWorld, which inherits from Layer which is a Node which can receive input events, such as touch, keys and motion.  We declare createScene() which returns a static Scene pointer.  As you may recall, we called this method earlier in AppDelegate to create our scene.  We also override the method init that we inherited from Node and is where we do our initialization logic.  Finally there is a bit of macro magic in the form of CREATE_FUNC(HelloWorld).

Let’s take a quick look at exactly what this macro is doing:

 

#define CREATE_FUNC(__TYPE__) \
static __TYPE__* create() \
{ \
    __TYPE__ *pRet = new __TYPE__(); \
    if (pRet && pRet->init()) \
    { \
        pRet->autorelease(); \
        return pRet; \
    } \
    else \
    { \
        delete pRet; \
        pRet = NULL; \
        return NULL; \
    } \
}

 

Granted, it’s not always the easiest code to read, as this is code for generating code, but essentially after this macro runs, we’ve got:

static HelloWorld* create(){
    HelloWorld *pRet = new HelloWorld(); 
    if (pRet && pRet->init())
    { 
        pRet->autorelease();
        return pRet; 
    } 
    else 
    { 
        delete pRet; 
        pRet = NULL; 
        return NULL; 
    }
} 

 

So, essentially, the macro is creating a create() function that allocates an instance of our class, calls the init method that we provided and then, most importantly, calls autorelease() we inherited from Ref.  I will cover why this is important in a few minutes, depending of course on how fast you read. :)

 

Now on to HelloWorldScene.cpp.  The createScene() method is pretty straight forward.  We create a Scene object, then an instance of our HelloWorld class ( which inherits from Layer ) and add our layer to the scene then return the scene ( which our AppDelegate then passed to Director->runScene() ).

In init() we perform the bulk of our logic.  First we call our base classes init function ( which is very important to do ), then create a Label using createWithSystemFont(), which predictably enough, using the built in system font (in this case Arial ) to create the Label’s text.  We then set the Labels anchor point to the bottom left, which means this node will be positioned relative to it’s bottom left corner.  I will cover anchor points in more detail in the next tutorial, so ignore this for now.  Finally we add the freshly created Label to our layer.  Finally we return true to indicate that initialization worked as expected.

 

Now if run our “game”, we should see:

image

 

 

Aren't we leaking memory like mad?

So you may have noticed we create all kinds of pointers using create() calls, but never once called delete.  As you can see in the code generated by the CREATE_FUNC, we are creating a new instance of our class, but we never do delete it.  Aren’t we leaking memory here?  Thankfully the answer is no and the reason is in the call to init() and autorelease() that the macro made and why it was so important we called our base classes init() in our own init method.

This is another legacy of Cocos2d-x’s Objective-C roots.  Objective-C provides a form of memory management via ARC, Automatic Reference Counting.  Basically each time something references an object, it’s count is increased, each time something reference an object goes away, the count is decreased, when the count hits zero, the object is released.  In many ways, this is pretty much the same functionality C++ smart pointers provide, but Cocos2d predates the standardization of smart pointers.

There is more to their usage that we will cover later on.  For now though, you can safely assume any cocos2d object created with a create() function, that inherits from Ref, does not need to be delete.  In fact, such objects must not be deleted!

 

In the next part we will take a look at working with graphics in Cocos2d-x.  Don’t worry, it will be much less verbose and much heavier in code!

Programming


12. September 2014

 

 

Apparently on September the 9th Phaser 2.1 was released  followed quickly by the ohhhh oops Phaser 2.1.1 hotfix release.  It is important to note that this releasePhaser Logo has some code breaking changes in it, so read carefully before upgrading to see how your code might be impacted!

 

 

The release notes:

 

Version 2.1.1. of Phaser is an emergency point release. It addresses a potential race condition that could happen in States that tried to change state from the create method but had an empty preloader or pre-cached assets.

The list of changes below are from 2.1.0 - 9th September 2014

 
New Features
  • Updated to p2.js 0.6.0 - this was an API breaking change, so please see the p2.js section of this change log specifically if you're using p2 in your game.
  • If you are using CocoonJS, please set your game render type to CANVAS and not WEBGL or AUTO. You should also disable any of the ScaleManager screen resizing or margin setting code. By default in this mode CocoonJS will now set 'screencanvas=true' which helps with performance significantly.
  • Ninja Physics is no longer included in the build files by default. Not enough people were using it, and not enough contributions were coming in to help polish it up, so we've saved the space and removed it. It's still available in the grunt build files if you require it, but we're deprecating it from the core library at this time. It will make a return in Phaser3 when we move to a modular class system.
  • ScaleManager has a new scaleMode called RESIZE which will tell Phaser to track the size of the parent container (either a dom element or the browser window if none given) and set the canvas size to match it. If the parent changes size the canvas will resize as well, keeping a 1:1 pixel ratio. There is also a new ScaleManager.setResizeCallback method which will let you define your own function to handle resize events from the game, such as re-positioning sprites for a fluid responsive layout (#642)
  • The width and height given to the Phaser.Game constructor can now be numbers or strings in which case the value is treated as a percentage. For example a value of "100%" for the width and height will tell Phaser to size the game to match the parent container dimensions exactly (or the browser window if no parent is given). Equally a size of "50%" would tell it to be half the size of the parent. The values are retained even through resize events, allowing it to maintain a percentage size based on the parent even as it updates.
  • Device will now detect for Kindle and PS Vita (thanks @lucbloom)
  • Device will now detect for Cordova (thanks @videlais #1102)
  • Arcade Physics Body.skipQuadTree is a new boolean that if set to true when you collide the Sprite against a Group it will tell Phaser to skip using a QuadTree for that collision. This is handy if this Body is especially large.
  • Arcade Physics World.skipQuadTree will disable the use of all QuadTrees in collision methods, which can help performance in tightly packed scenes.
  • Cordova 'deviceready' event check added (thanks @videlais #1120)
  • Loader.useXDomainRequest boolean added. If true (the default is false, unless the browser is detected as being IE9 specifically) it will use XDomainRequest when loading JSON files instead of xhr. In rare IE edge-cases this may be required. You'll know if you need it (#1131 #1116)
  • Added support for Tiled objects type field (thanks @rex64 #1111)
  • Tile properties are now copied from the Tiled JSON data to the Phaser.Tile objects when parsed (thanks @beeglebug #1126)
  • All Images now have a frameData value, even if it's only one frame. This removes lots of engine code needed to check if images are sprite sheets or not, and simplifies game code too (thanks @lucbloom #1059)
  • Added a new Phaser.Rope object. This allows for a series of 'chained' Sprites and extends the Rope support built into Pixi. Access it via game.add.rope (thanks @codevinsky #1030)
  • Phaser.Device.isAndroidStockBrowser will inform you if your game is running in a stock Android browser (rather than Chrome) where you may wish to scale down effects, disable WebGL, etc (thanks @lucbloom #989)
  • Phaser.Camera has a new property position which is a Point object that allows you to get or set the camera position without having to read both the x and y values (thanks @Zielak#1015)
  • TileSprite now has the alive property, which should help with some Group operations (thanks @jonkelling #1085)
  • Events.onDestroy is a new signal that is dispatched whenever the parent is being destroyed. It's dispatched at the start of the destroy process, allowing you to perform any additional house cleaning needed (thanks @jonkelling #1084)
  • Group.onDestroy is a new signal that is dispatched whenever the Group is being destroyed. It's dispatched at the start of the destroy process, allowing you to perform any additional house cleaning needed (thanks @jonkelling #1084)
  • ScaleManager.destroy now removes the window and document event listeners, which are no longer created anonymously (thanks @eguneys #1092)
  • Input.Gamepad.destroy now destroys all connected SinglePads and clears event listeners.
  • SinglePad.destroy now clears all associated GamepadButton objects and signals.
  • Device.node and Device.nodeWebKit are two new properties (thanks @videlais #1129)
  • P2.PointProxy.mx and my values are get and set in meters with no pixel conversion taking place.
  • P2.InversePointProxy.mx and my values are get and set in meters with no pixel conversion taking place.
  • Pointer.dirty is a new boolean that is set by the InputHandler. It tells the Pointer to re-check all interactive objects it may be over on the next update, regardless if it has moved position or not. This helps solve issues where you may have a Button that on click generates a pop-up window that now obscures the Button (thanks @jflowers45 #882)
  • SoundManager.destroy is a new method that will destroy all current sounds and reset any callbacks.
  • StateManager.clearCurrentState now handles the process of clearing down the current state and is now called if the Game is destroyed.
  • Game.destroy now clears the current state, activating its shutdown callback if it had one. It also now destroys the SoundManager, stopping any currently running sounds (#1092)
  • Animation.onUpdate is a new event that is dispatched each time the animation frame changes. Due to its intensive nature it is disabled by default. Enable it withAnimation.enableUpdate = true (#902)
  • Device now has new features to support detection of running inside a CocoonJS.App (thanks@videlais #1150)
  • Support for CocoonJS.App's 'onSuspended' and 'onActivated' events, making it so that the timers and sounds are stopped/started and muted/unmuted when the user swaps an app from the background to the fore or the reverse (thanks @videlais #1152)
  • Canvas.removeFromDOM(canvas) will remove a canvas element from the DOM.
  • Game.destroy now removes the games canvas element from the DOM.
  • ScaleManager.setMinMax(minWidth, minHeight, maxWidth, maxHeight) is a handy function to allow you to set all the min/max dimensions in one call.
  • ArcadePhysics.collide and overlap can now accept 2 Arrays of objects to be used in the collision checks (thanks @ctmartinez1992 #1158)
  • RetroFont has a new property called frameData which contains the Frame objects for each of the letters in the font, which can be used by Sprites.
  • Phaser.Canvas.setImageRenderingCrisp now sets image-rendering: pixelated, perfect for pixel art, which is now supported in Chrome 38.
  • Phaser.Mouse will now add a listener to the window to detect mouseup events. This is used to detect if the player releases the mouse while outside of the game canvas. Previously Pointer objects incorrectly thought they were still pressed when you returned the mouse over the canvas (#1167)
  • Rectangle.centerOn(x,y) allows you to quickly center a Rectangle on the given coordinates.
  • Group.addMultiple allows you to pass an array of game objects and they'll all be added to the Group in turn.
  • The StateManager will now check if a State has a method called resize. If it does, and if the game is running in the RESIZE Scale Mode then this method will be called whenever the game resizes. It will be passed two parameters: width and height that will match the games new dimensions. Resizing can happen as a result of either the parent container changing shape, or the browser window resizing.
  • Rectangle.topRight returns a Point object that represents the top-right coordinate of the Rectangle.
  • The grunt script now builds a new version of Phaser without any physics (including Arcade Physics), Tilemaps or Particles. This build is called phaser-no-physics.js and works stand-alone. Please note that things like the GameObjectFactory aren't changed, so they will still try and create a Tilemap for example should you ask them to (thanks @eguneys #1172)
  • Camera.roundPx is a new boolean. If set to true it will call view.floor as part of its update loop, keeping its boundary to integer values. Set to false to disable this from happening (#1141)
  • Phaser.Easing.Default is a new property that is used when a specific type of ease isn't given. It defaults to Linear.None but can be overridden to anything (thanks @alvinsight)
 
Updates
  • TypeScript definition updates to help fix for the noimplicitany option (thanks @Waog#1088)
  • TypeScript definitions fixes and updates (thanks @clark-stevenson @englercj @saikobeeand @rhmoller)
  • All of the Pixi geom classes have been removed from the build file as they aren't needed (the Phaser.Geom classes overwrite them), saving some space in the process.
  • Improved consistency of clone methods on geometry classes (thanks @beeglebug #1130)
  • Removed Cache.isSpriteSheet method as no longer required (see #1059)
  • Added Cache.getFrameCount to return the number of frames in a FrameData.
  • Input.setMoveCallback has been removed due to deprecation.
  • BitmapData.refreshBuffer has been removed and replaced with BitmapData.update.
  • BitmapData.drawSprite has been removed due to deprecation. Use BitmapData.draw instead.
  • Pointer.moveCallback has been removed due to deprecation.
  • SinglePad.addButton has been removed due to deprecation.
  • P2.Body.loadData has been removed due to deprecation.
  • P2.World.defaultFriction and defaultRestitution have been removed due to deprecation.
  • Canvas.create noCocoon parameter has been removed due to deprecation.
  • Color.getColorInfo, RGBtoHexstring, RGBtoWebstring and colorToHexstring has been removed due to deprecation.
  • P2.PointProxy.x and y values are now returned in pixels (previously they were returned in meters). See PointProxy.mx/my for meter values.
  • P2.InversePointProxy.x and y values are now returned in pixels (previously they were returned in meters). See PointProxy.mx/my for meter values.
  • Arcade.overlap and collide are now more consistent about allowing a Group vs. Group or Group vs. Array of Groups set (thanks @pyromanfo #877 #1147)
  • The Pointer move callbacks are now sent an extra parameter: fromClick allowing your callbacks to distinguish between the Pointer just moving, or moving as a result of being pressed down (thanks @iforce2d #1055)
  • GamePad and SinglePad onAxisCallback parameters have changed. You are now sent: this (a reference to the SinglePad that caused the callback), the axis index and the axis value in that order.
  • If Time.elapsed was > Time.timeCap it would reset the elapsed value to be 1 / 60. It's now set to Time.timeCap and Time.timeCap defaults to 1 / 60 * 1000 as it's a ms value (thanks@casensiom #899)
  • Tiled polylines are now imported into the map objects property as well as map collision (#1117)
  • Tile.setCollision now adjusts the tiles interesting faces list as well, this allows you to create one-way jump tiles without using custom callbacks on a specific tile basis (thanks@RafaelOliveira #886)
  • Stage.offset has been moved to ScaleManager.offset
  • Stage.bounds has been removed, you can access it via Stage.getBounds.
  • Stage.checkOffsetInterval has been moved to ScaleManager.trackParentInterval
  • ScaleManager.hasResized signal has been removed. Use ScaleManager.setResizeCallback instead.
  • The World bounds can now be set to any size, including smaller than the game dimensions. Before it was locked to a minimum size of the game canvas, but it can now be anything.
  • ScaleManager.orientationSprite has been removed because it never displayed correctly anyway (it would be distorted by the game scale), it will be bought back in a future version by way of a custom orientation state.
  • ArcadePhysics.overlap has been updated so that the Body.overlapX/Y properties are set to the amount the two bodies overlapped by. Previously they were zero and only populated during the separation phase, but now the data is available for just overlap checks as well. You can then use these values in your ovrelap callback as required - note that they are changed for every check, so a Sprite overlap tested against 10 other sprites will have the overlapX/Y values updated 10 times in a single collision pass, so you can only safely use the values in the callback (#641)
  • Cache.getImage now returns null if the requested image wasn't found.
  • BitmapData now returns a reference to itself from all of its drawing related methods, allowing for easy function chaining.
  • The default size of a BitmapData if no width/height is given has been changed from 100x100 to 256x256.
  • Phaser.Text.destroy will now destroy the base texture by default (#1162)
  • BitmapData.copyPixels is now called BitmapData.copyRect and the method signature has changed.
  • BitmapData.draw method signature has changed significantly.
  • Phaser.Canvas.getSmoothingEnabled will return true if the given context has image smoothing enabled, otherwise false.
  • Math.numberArrayStep is a new method that allows you to return an array of numbers frommin to max including an optional step parameter (thanks @codevinsky #1170)
  • Removed redundant if check from StateManager.preUpdate (thanks @FedeOmoto #1173)
 
Bug Fixes
  • Remove escaping backslashes from RetroFont text set documentation (thanks @jackrugile#1051)
  • Phaser.Loader was incorrectly getting the responseText from _xhr instead of _ajax on IE9 xDomainRequests (thanks @lardratboy #1050)
  • Phaser.Physics.P2.addPolygon now takes a nested array again (thanks @wayfu #1060)
  • Fix for previous PR #1028 where the P2.setBoundsToWorld call was overriding setBoundsToWorld in the P2 constructor (thanks @Dumtard #1028)
  • Fix for scale issues in CocoonJS using webgl renderer and screencanvas (thanks@txusinho #1064)
  • Resolves issue with pixel perfect click / over detection on Sprites that used trimmed image atlases for animations or frames > 0.
  • Group.swap() updates the Z index values properly (thanks @Blank101 #1090)
  • Device now recognises ChromeOS as a desktop (thanks @alvinsight @hilts-vaughan#1091)
  • Fixed Point.rotate bug (thanks @gamedolphin #1107)
  • InputHandler.checkBoundsRect was incorrectly assigning a property in Sprites fixed to the camera being dragged left (thanks @CraigBeswetherick #1093)
  • Swapped argument order of Rectangle.containsRect (thanks @beeglebug #1095 #1125)
  • The Game configuration object "renderer" property was being wrongly assigned to Game.renderer instead of renderType (thanks @FedeOmoto #1127)
  • Fixed Group.removeBetweens default endIndex (thanks @darfux #1142)
  • Debug.cameraInfo no longer crashes if the camera bounds are nulled (thanks @wayfu#1143)
  • Camera.setBoundsToWorld no longer crashes if the camera bounds are nulled (thanks@wayfu #1143)
  • Fixed the resolution uniform type in the SampleFilter (thanks @VictoryRice #1137)
  • Calling P2.Body.destroy or ArcadePhysics.Body.destroy wouldn't null the parent sprite body, causing it to error in the next update (thanks @jonathanhooker #1077)
  • BitmapFonts are now correctly added to the Cache._bitmapFont array and returned via Cache.getBitmapFont (thanks @prudolfs #1076)
  • InputHandler docs updated to avoid Pointer data-type confusion (#1097)
  • If you used a single Game configuration object and didn't specify the enableDebug property it would crash on Debug.preUpdate (thanks @luizbills #1053)
  • The P2.World.postBroadphaseHandler now checks if the returned pairs array is empty or not before processing it (thanks @wayfu #934)
  • Tilemap.hasTile now checks the Tile.index value and will return false if the index is -1 (i.e. a non-active tile) (thanks @elgansayer #859)
  • Sound.restart used to cause the Sound to double-up if it was already playing when called. Now correctly stops the sound before restarting it (thanks @wombatbuddy #1136)
  • GamePad axis detection now works again properly in Firefox (#1035)
  • GamepadButton.justPressed and justReleased now correctly report if the button has just been pressed or released (thanks @padpadpad #1019)
  • TilemapParser.getEmptyData now correct adds an empty bodies array into layers. This fixes an issue where p2 couldn't convert a csv map into collision tiles (thanks @sru #845)
  • CocoonJS doesn't support mouse wheel events so they've been moved into a conditional check (thanks @videlais #1151)
  • ScaleManager window.resize handler would constantly dispatch enterPortrait and enterLandscape events on window resizing, regardless if it actually entered that orientation or not.
  • Added Sound._muteVolume which stops Firefox and IE9 crashing if you try to unmute a sound that hasn't yet been muted, which can also happen as a result of a game visibility change (thanks @osmanzeki #1108 #1123)
  • P2.World.getSprings used to return an empty array, but now returns all the Springs in the world (#1134)
  • Tween.generateData would skip the end values in the data array. They are now included as the object in the final array element.
  • Rectangle.bottom setter swapped the order of the calculation (thanks @JakeCoxon #1165)
  • Phaser.Text wouldn't render the text to its local canvas if you passed the text on the constructor and didn't add it to the display list. If a string is given it now updates the local canvas on creation.
  • Signal.removeAll would ignore the context parameter and remove all bindings regardless (thanks @alect #1168)
  • P2.Body.addCapsule didn't use to pass the radius value through pxm, but now does so you have to specify it in pixels, not meters.
 
p2.js 0.6.0 Changes and New Features
  • DistanceConstraint signature changed to take the new localAnchors.
  • World.createDistanceConstraint signature changed to include new local anchors (thanks@rhmoller #1169)
  • RevoluteConstraint signature changed to include worldPivot.
  • P2.Body now uses the new Body.type value instead of Body.motionState, however as P2.Body already have a property called type we have left the motionState getter/setter in for now.
  • World.enableBodySleeping has been removed and replaced with World.sleepMode.
  • Phaser P2.Springs are now LinearSprings by default.
  • World.createRotationalSpring will now let you create rotational springs.
 
Breaking changes
  • Renamed property .motionState to .type in class Body.
  • Changed constructor of RevoluteConstraint. Now the local pivots are passed as options instead of direct arguments. See the constraints demo.
  • Removed World.prototype.toJSON and .fromJSON.
  • Removed properties .enableBodySleeping and .enableIslandSleeping from World instances. The enum .sleepMode can be used instead. See the sleep demo.
  • Converted Spring to a base class for the new LinearSpring and RotationalSpring classes. LinearSpring can be used as the old Spring.
  • Utils.ARRAY_TYPE can now be overridden by injecting a global called P2_ARRAY_TYPE. Support for GLMAT_ARRAY_TYPE has been removed.
 
Other changes
  • Added flag .enableFrictionReduction to Narrowphase.
  • Added RevoluteConstraint.prototype.setLimits.
  • Added PrismaticConstraint.prototype.setLimits.
  • LockConstraint, DistanceConstraint, and GearConstraint can now be constructed from current body transforms.
  • RevoluteConstraint can now be constructed from the current body transforms and a world point.
  • Material id can now be passed via constructor.
  • ContactMaterial instances now have a property .contactSkinSize.
  • Added method Body.prototype.getAABB.
  • Limits for DistanceConstraint. See the DistanceConstraint demo.
  • Added Body.prototype.overlaps.
  • Added class OverlapKeeper.
  • If substepping is used in World.prototype.step, the substeps are aborted if slower than real time.
  • Added Heightfield/Convex and Heightfield/Circle collision support.
  • Added property .overlapKeeper to World.
  • EventEmitter.prototype.has can now check if any listeners were added to a given topic.
  • Added Utils.defaults.

 

In reading through the changes, I do not believe any of the GameFromScratch Phaser tutorial series will be impacted if you use the newest version.

News


AppGameKit Studio

See More Tutorials on DevGa.me!

Month List