Subscribe to GameFromScratch on YouTube Support GameFromScratch on Patreon

8. April 2013

Near the end of last week I announced the GameFromScratch game project and announced I was most likely going to use HTML5 as the development language of choice, while LibGDX and HaXe + NME were my runner up technologies.

 

The end result of the process is going to (hopefully!) be a published game on iOS and Android, but I intend to share as much as reasonably possible on GameFromScratch.com, including a running version of the game and most of, it not all of, the source code and eventually assets.  Obviously then, I want to do it in a technology that appeals to the majority of you, while still fighting my requirements ( I list them in the other post ).

 

Since I made that post, I've received some comments, tweets and a number of emails showing interest in various technologies.  So I've decided to put it to a poll, GFS's first ever!

 

 

I am not promising the winner in this poll is the technology I am going to go with, but it will certainly be given a large weighting when making my decision.

 

Copied from the earlier post, here are my specific requirements:

  • Turn based game
  • May require modest 3D support, otherwise sprite based
  • Excellent UI support ( UI heavy game )
  • Available on Android, iOS and on GameFromScratch.com at a minimum
  • In a language of interest or known to a large number of developers
  • Tools at low or no cost, so maximum number of readers can follow along
  • Reasonably quick development time
  • Good library support, little desire to re-invent the wheel

5. April 2013

The project is currently up on Github.

PlayscriptLogo

 

 

 

 

 

 

I will let them describe it in their own words:

PlayScript is an open source Adobe ActionScript compatible compiler and Flash compatible runtime that runs in the Mono .NET environment, targeting mobile devices through the Xamarin Studio MonoTouch and Mono for Android platforms. With a combination of Adobe FlashBuilder for Web and Xamarin Studio for mobile complex large scale cross-mobile-web projects can be developed with full IDE, source debugging and intellisense support on all platforms, with access to the full native mobile API's on the mobile platform.

The PlayScript compiler also targets both C++ and JavaScript (similar to the Haxe compiler) allowing ActionScript code to be run via JavaScript on the Web, or natively on PC and mobile (with some limitations). (NOTE: Presently the JS and C++ targets are at an experimental stage)

In addition to accurate ActionScript language support, the PlayScript compiler also supports a new language - PlayScript - which is derived from both C# and ActionScript. This new language supports all of the features of C#, including generics, properties, events, value types, operator overloading, async programming, linq, while at the same time being upwards compatible with ActionScript. The PlayScript language can be used to target both web and mobile (via Xamarin and JavaScript), and existing Flash code can easily be converted to PlayScript code by simply renaming files from .as to .play, and fixing a few issues related to the stricter syntax and semantics of the PlayScript language.

Finally, the PlayScript runtime supports a full Stage3D compatible implementation of the Flash runtime allowing games that are Stage3D compliant to run with very minor modifications on mobile via the Xamarin/Mono runtime. A subset of the "display" library is implemented to support Stage3D libraries such as Starling, Away3D, and Feathers, though there are no plans at the present time implement the full Flash display system.

And:

Features:

Native Performance

  • Using "unsafe" code.
  • Direct interop with native code (Cocos2D-X, other C++ based engines such as Page44, etc).
  • Optimized compiler for JavaScript generation.
  • Optional full C++ target with minimal app size and startup overhead.

Advanced Tools Support

  • Complete tool support including Syntax Highlighting and intellisense in the MonoDevelop IDE.
  • Source Debugging on all platforms (FlashBuilder for Flash).
  • Fast Release mode compiles and rapid iteration.

Full Platform API's

  • Complete iOS platform API via Xamarin MonoTouch and Mono for Android
  • Complete Windows/MacOSX API's.
  • Complete integration with UI builder (iOS), and Android GUI builder via Xamarin Studio.

Differences between PlayScript and ActionScript

  • PlayScript supports most features of C# 5.
  • PlayScript requires semicolons after all statements.
  • PlayScript uses block scoping for variables.
  • PlayScript requires breaks in switch statements.
  • PlayScript supports generics using the .<> syntax introduced in AS3 with the normal C# feature set.
  • PlayScript supports properties using the "property" keyword with syntax similar to C#.
  • PlayScript supports indexers and operator overloads using the "indexer" and "operator" keywords.
  • PlayScript implements AS3 namespaces by converting them to .NET internal.

Differences between PlayScript and CSharp

  • PlayScript requires the use of the "overload" keyword on addtional overload methods (allows more readable JavaScript code by only mangling overload method names).
  • PlayScript does not support using blocks.
  • PlayScript does not support checked, unchecked.
  • PlayScript does not "presently" support unsafe code (though this will be added in the future). Currently unsafe code can be added to mobile projects via C#.
  • In PlayScript you may not directly access the base properties of Object (ToString(), GetType(), GetHashCode()) unless you cast an objet to a System.Object. Doing this however will make your code incompatible with the C++ or JavaScript target backends.

 

The provided the following example code:

// Basic types
var b:byte;
var sb:sbyte;
var s:short;
var us:ushort;
var i:int;
var u:uint;
var l:long;
var ul:ulong;
var f:float;
var d:double;

// Conditional compilation
#if DEBUG
#else
#endif

// Fixed arrays
var a:int[] = new int[100];

// Properties
public property MyProperty:int {
   get { return _myInt; }
   set { _myInt = value; }
}

// Events
public event MyEvent;

// Delegates
public delegate MyDelegate(i:int):void;

// Operators
public static operator - (i:int, j:int):int {
}

// Indexers
public indexer this (index:int) {
   get { return _a[index]; }
   set { _a[index] = value; }
}

// Generics
public class Foo.<T> {
    public var _f:T;

    public function foo<T>(v:T):void {
    }
}

// Async
async function AccessTheWebAsync():Task.<int> 
{ 
    var client:HttpClient= new HttpClient();
    var getStringTask:Task.<String> = client.GetStringAsync("http://msdn.microsoft.com");
    var urlContents:String = await getStringTask;
    return urlContents.Length;
}

Very interesting. So basically they are making a HaXe like cross platform tool based on a hybrid of ActionScript and C#, targeting existing Stage3D libraries.

News, Programming ,

4. April 2013

Well, this certainly wasn't expected, and I double checked the calendar, it's no longer April 1st...

 

Introducing Corona SDK Starter

Okay, so here’s where it gets really exciting. From very early on, we have focused on democratizing app development. We felt (and still do) that anyone could create the next great app with Corona. Since then, Corona has been embraced by indies and your apps have hit the top of the charts.

Indies are a key part of our community, so today, we are taking that vision a step further. We are announcing Corona SDK Starter – a completely FREE version of Corona that lets you publish to all the platforms we support without paying us a single cent.

With Corona SDK Starter and the Starter tier of Corona Cloud, you can publish amazing, connected apps faster and more affordably (free!) than ever before. We are the only platform that lets developers do this. A lot of other products have hidden fees or force some sort of watermark/splash screen. There is no such restriction with Starter. That’s the difference between “fake free” and a true free option.

So, what's the catch?

If you want to access certain specific features like in-app purchase and analytics, you’ll need to subscribe to a paid plan. You can still build with those features on your own device, but you can’t publish apps to the store if they use those premium features. Daily builds are also only available to paying subscribers.

Not really much of a catch in the end, at least so far as existing Corona goes.

 

There is however also a "coming soon" Corona, that will be available in the Pro version:

Graphics

As I talked about last week, our bleeding-edge OpenGL-ES 2.0/shader-based graphics engine is in the works. You are going to be blown away with what you can do. I’ll talk about that more later but I did want to give you a teaser.

If you watch this week’s CoronaGeek episode, you’ll be able to see 5,000 fish running at 60 fps! It may be hard to tell from the video, but this is what I showed to a lucky few at GDC. I recommend watching the whole show, but if you’re pressed for time, you can skip to roughly the 35:00 mark.

Plugins

Second, there’s Project Gluon, a.k.a plugins. We’ve done a ton of plumbing work so that you’ll be able to do integrate 3rd party services and functionality into your app, and do so painlessly from the comfort of the Corona Simulator.

Now there’s good news and bad news here. There are a lot of moving parts, so plugins didn’t quite make it to the public release — and yes, I’m disappointed too.

But the good news is that plugins are coming very soon! We’re getting ready to seed this to beta testers this month. We are actively building a library of plugins that will be hosted on our servers. We’re working with folks like Amazon to get you more monetization options. We are acutely aware that this is a big issue for a lot of you.

Device Access

Lastly (for now), we have found a way for you to access certain Java and Objective-C APIs from Lua! On the Android side, we already have the foundation there thanks to Enterprise, and we’re looking at how we can accelerate bringing those Enterprise innovations down to Pro developers. In parallel, we also have a proof-of-concept on the iOS side, so I’ll have more news once we’re past the research phase.

The pro version is going to have a 599$ a year price tag, but existing customers will be able to subscribe for 349$.

 

So, nutshell version is… the product we know today as Corona is now available for free, minus some web services.  Their is a new more powerful version coming soon, at it will be a paid only version with a price increase.

 

So basically, if you haven't used Corona, it's great news.  If you are an existing subscriber, not so much.

 

You can read the entire release here.

News ,

4. April 2013

Now that my book is published it's time to move on to my next project.  Given the original purpose of this site, with a two year distraction, I think it's high time that I get around to actually creating and publishing a game!  I intend to share as much of the development process, code, assets, etc… as I go, including having the WIP game playable here!

 

What I have in my head is a science fiction business simulation game.  Trust me, the actual game is a hell of a lot more exciting than that title indicates, I will flesh out the details in further blog posts.  If you played old school BBS games, or many of the recent Kairosoft or Tycoon style games, you should have an inkling of the type of game I am considering.  I actually tend to find these styles of turn based games are the best fit for mobile games, especially in the world of play 5 minutes here, 5 minutes there.

 

One of the biggest requirements in creating a game is being able to post about it here.  I want to share as much of the development experience as possible, and hopefully be as interesting to as large an audience as possible.  Ultimately I do intend to sell the game on at least iOS and Android, but I would also like to give it away here.  I would also like to make all of the source, and eventually ( once I've hopefully sold a few copies ) the assets available as I go.

 

So here are my current requirements:

  • Turn based game
  • May require modest 3D support, otherwise sprite based
  • Excellent UI support ( UI heavy game )
  • Available on Android, iOS and on GameFromScratch.com at a minimum
  • In a language of interest or known to a large number of developers
  • Tools at low or no cost, so maximum number of readers can follow along
  • Reasonably quick development time
  • Good library support, little desire to re-invent the wheel

 

For the last week I've been mulling these requirements around in my head and I think I've settled on my technology of choice.  First I will go through my list of considered but discounted technologies and the reasons why.

LoomScript I recently finished evaluating Loom and I was rather impressed.  There is CSS style markup and tweening support for making a solid UI relatively easily, it targets all the desired platforms, except the web ( MacOS and Windows builds might offset this lacking to a degree ).  That said though, at the end of the day, it's just not that popular yet, so I would be writing about a technology a very small minority of you are interested in.

Unity is an obvious choice.  It would handle the 3d portions better than any other engine i've considered and it is certainly popular, so would probably be relevant for a lot of you.  At the end of the day though, it's a 3D engine, not a 2D one.  Of course, you can accomplish a great deal using 3rd party libraries, for an additional cost.  At the end of the day, that was the biggest mark against Unity, the cost factor.  Although I own a 3.x license from the give away, and could ultimately buy a 4.x license when ready to ship, I don't want to go that route if I don't really need the majority of the features it buys me.  The UI support too is also remarkably sparse.

Scaleform was another one I considered.  On the UI side of the fence, it may be the strongest option.  It's basically a game optimized version of Flash and is used in hundreds of games to provide the UI functionality.  That said, it's pretty niche in the indie world at this point and the amount of supporting materials is pretty light right now.

C++, very little gain.  Would love to take a closer look at the GamePlay3D engine, but it's overkill for this game project.

Flash/AIR is another option.  In all my years, I somehow completely avoided doing any Flash development.  Keep in mind, I am not talking about browser based Flash, I am talking Flash as a development environment.  I haven't completely disregarded Flash as an option, but puzzling out the eco-system was rather confusing.  Not really sure what level of commitment would be need to be made to work with Flash.  I do really wish FlashDevelop was available on MacOS…  Not ruled out Flash yet, but probably not.

The LUAs. I really like all of the Lua based game engines but none are a particularly good fit.  I don't believe any of them support web deployment right now, Corona and Gideros both have a price tag attached and Moai is a poor fit… I am not writing a high performance game, so there aren't enough wins to make it worth while, as I'd have to roll my own UI system, etc.

LibGDX/PlayN Both support a good number of platforms, both are libraries of interest to me.  In the case of PlayN, I just found the entire build process ( MAVEN!!! ) so tedious and prone to breakage, plus I would be pretty much rolling my own UI.  LibGDX is on my todo to look into further and hasn't been discounted completely, but UI support is there.

HaXe + NME Still looking into this one, it's a maybe.

 

At the end of the day, that leaves an obvious choice and two maybes.

 

HTML5 It's popular, library support is staggering, UI support is a no brainer ( I can use a few thousand existing HTML libraries ), hosting it on this website is also a no brainer, I can easily port to Windows 8 and Chrome app stores and frankly, I want to see what the HTML5 developer experience is like on a full game.  There is one possible achilles heel to this decision though… native support.  I want to deploy as a native app at the end of the day, and there are options for this ( XDK, CocoonJS, PhoneGap ), but there are also problems.  WebGL support is I believe only available on Cocoon and it's "coming soon".  The game in my mind isn't performance intensive, but I don't know if native WebView is fast enough, probably rendering PhoneGap a non-starter… I need to (very very very soon) try the various native deployment options and see how it goes.

 

That said, if HTML5 doesn't work out, I've got two runners up picked out.  HaXe and libGDX.

 

Is there any mainstream language you would prefer I do this project in?  Anyways… wish me luck, first steps and all of that...

News, Programming ,

2. April 2013

I hear over and over again in programmer forums, mostly beginner forums, that C++ is hard because you have to manually manage memory!  This is not only wrong, it's dangerous.  Whenever you see this comment, be wary about following this persons advice in the future. Why?  Simply put, because if you are manually managing memory in C++, you are probably doing it wrong.  We will look at why in a moment.

 

Secondary to the fact you really shouldn't be manually managing memory all that often in C++, even if you have to, it shouldn't really be all that hard.  Memory management in C++ doesn't make the language hard, it makes it fragile, their is a big difference.  The concepts behind memory management really aren't rocket science, it's the kind of thing you can learn in an afternoon.  However, screwing it up can easily introduce a bug into your application or cause it to outright crash.  This is what I mean by fragile.

 

So in this post we are going to start with why you shouldn't be managing memory manually, show you how you actually go about doing this, then finally for those times you absolutely have to, show you the ins and out of basic C++ memory management.  One thing I should point out right away is many of the things I discuss in this article didn't exist until somewhat recently (such as smart pointers).  Languages evolve, C++ certainly has.  I assume you are using a reasonably current complier, if you aren't, much of what we discuss may not be applicable to you.

 

Before we can go too far, there are a few concepts you need to understand.  When working in C++, there are three kinds of memory you need to be aware of.

 

The Stack, the Heap and all the other kinds we are going to pretend don't exist.

 

First we will talk about the types we won't talk about.  In this discussion I am oversimplifying things slightly to focus on the stuff that is most relevant 99% of the time.  There are other kinds of memory ( globals, statics, registers, etc… ), but until you need to know about them, you can safely ignore them.

 

That leads us back to the stack and the heap.  Let's start with the stack...

 

The Stack

The stack is well named, think about a stack of plates at a cafeteria, and you have the basic idea of what the stack is like.  

StackOfPlates

Each time you create a variable on the stack, think of it like adding a plate to the top of this pile.  When a variable goes out of scope, think of it like removing a plate from the pile.

 

Let's look at it with actual code.

#include <iostream>

 

void SomeFunction(int a2, int b2)

{

    int c=3;

    int d=4;

    std::cout << a2+b2+c+d;

}

 

int main(int argc, const char * argv[])

{

 

    int a = 1;

    int b = 2;

    SomeFunction(a,b);

}

 

This simple program creates a pair of values a and b and passes their values to the function SomeFunction() which then creates two more variables c and d and adds them all together, printing out the total.

 

So, what is happening here on the stack?  Look at the following diagram and think in terms of the stack of plates (bowls?) above:

 

Stack

 

As this code runs, first a is added to the stack, then b.

Next copies of a and b are sent as parameters to our function, resulting in a2 and b2 being added to the stack.  This is an important concept to grasp.  When you pass a standard variable by value, it's actually only the value that is used, a new variable is created for each parameter.

Then within our function, c and d are created (on the stack) as well.

 

Now is when the stack starts to make sense…  when things are deallocated.  See, the stack is very aware of scope and when a variable will die.  At the end of our function, d, c, b2 and a2 all go out of scope, so they are removed from the stack, like grabbing plates from the top of a plate stack.

After our function call, our stack will look like:

Stack2

Then finally our program execution ends, and b and a will be popped from the stack as well.

 

The nice thing about the stack is, the program knows when a stack variable is no longer needed ( when it goes out of scope ) and gets rid of it for you.  In my initial revision of this post, I made the stack sound like a bad place to create your variables and this is very much NOT the case.  In fact, unless you have a very good reason ( see the following paragraph ), you should always favour allocating on the stack, it's a heck of a lot less error prone and often quicker.

 

The downside to the stack are two fold.  First, it has a limited size… depending on your platform and your compiler settings, ranging from KB to a couple of MB in size.  I believe Visual C++ 2010 on Windows creates a default stack of 1MB.  Next, sometimes you want variables to outlive the scope they are declared in… quite often actually, such as a function that allocates a big chunk of memory to big to efficiently return by value ( and thus creating a copy ).  In this case you need...

 

The Heap

 

The heap is nothing special, don't confuse it with the data structure "heap", they have nothing to do with each other.  This "heap" in question is simply slang English… like you might say you have "a heap of clothing", you have a "heap of memory".  It's simply a big pool of memory available for your application.  Unlike the stack, which is very ordered and organized, the heap is just a gigantic blob of memory.

Now, the bright side to the heap is… theres lots of it.  As much memory as your system contains… in fact, probably much more thanks to virtualization.  When we are talking about manual memory management, it's the heap that we are talking about.

So, how do you create memory and destroy memory on the heap?  This is where new and delete come in.

Consider this super contrived example:

#include <iostream>

 

void FillBuffer(char * buffer)

{

    for(int i = 0;i < 10000000;i++)

        buffer[i] = 'A';

}

 

int main(int argc, const char * argv[])

{

    char * buf = new char[10000000];

    FillBuffer(buf);

    delete [] buf;

}

 

Here we create our variable buf on the heap, this is obvious from the use of new.  It is then passed into the function FillBuffer, which fills it with the character A.  Finally it is deleted.  There are a few things of note here, two showing the advantages of the heap, and one potential hand grenade.

First this code allowed us to make a 10MB data structure, you simply couldn't do this on the stack.  If you want to see first hand, try running the following code on your computer:

 

#include <iostream>

 

int main(int argc, const char * argv[])

{

    char buf[10000000];

    for(int i =0;i< 10000000;i++)

        buf[i] = 'A';

}

 

On MacOS, you get EXC_BAD_ACCESS errors as a result, and that makes sense, as you are trying to allocate more memory ( on the stack… new wasn't used ) than is available.  So, obviously if you have a large amount of data, it has to be on the heap.

The other major advantage to the above code is when you call FillBuffer, only a pointer to the data is passed ( 4bytes in size on 32bit Windows, 8bytes in size on 64bit ) instead of creating a 10MB copy.  If this concept doesn't make a lot of sense right now, bear with me, I will explain what a pointer actually is in a bit more detail shortly.

 

So, what then is the problem with direct memory management?  Well, remember this line:

delete [] buf;

Had I accidentally printed:

delete buf;

We would have just leaked 10 MB of memory!  If you don't manually release(delete) the memory you allocate using a pointer, when the pointer goes out of scope, that memory is lost. In this contrived example, its easy enough to remember a delete for every new, but in a real application, it's a very simple mistake to make, as is forgetting to include [] when dealing with an array of values!  It's even easier to leak memory when an exception occurs, causing your program to not necessarily run in the order you expected it to.


One thing to keep in mind here, I said earlier that if exists on the Heap, it was allocated with new.  This is true but somewhat misleading.  For example, when you use many of the standard C++ data structures, such as std::vector, even though you may create the object on the stack internally it is still allocating memory on the heap for it's own data.  It is just taking care of most of the heavy lifting for you.

 

So, thats a quick view of the stack, the heap and how memory works…  now I want you to forget it all!

 

As a new to C++ developer, every single time you find yourself typing new or delete, it should raise an alarm bell of sorts!  Don't get me wrong, there are reasons to use both, but they should be few and far between.  What then is the alternative?

 

Resource Acquisition is Initialization (RAII)

That sound scary?  Don't worry, its nowhere near as bad as it sounds.  RAII is a term/idiom coined by C++'s creator Bjarne Stroustrup.  I'll go with the Wikipedia description:

In this language, the only code that can be guaranteed to be executed after an exception is thrown are the destructors of objects residing on the stack. Resource management therefore needs to be tied to the lifespan of suitable objects in order to gain automatic allocation and reclamation. Resources are acquired during initialization, when there is no chance of them being used before they are available, and released with the destruction of the same objects, which is guaranteed to take place even in case of errors.

Again, this sounds much scarier than it really is.  The part that you need to really pay attention to is this one: needs to be tied to the lifespan of suitable objects in order to gain automatic allocation and reclamation.

Remember earlier how I said objects on the stack are automatically disposed when they go out of scope, while new'ed objects on the heap aren't, and if not manually deleted, will result in a leak?  Well, thats where smart pointers come in.  Esentially a smart pointer is a variable created on the stack, that creates the heap memory for you.  However, when it goes out of scope, it's destructor will be called and the resources it manages will then be disposed.  Let's take a look at our previous example, just using a smart pointer instead.

#include <memory>

 

void FillBuffer(std::unique_ptr<char[]> & buffer)

{

    for(int i = 0;i < 10000000;i++)

        buffer[i] = 'A';

}

 

int main(int argc, const char * argv[])

{

    std::unique_ptr<char[]> buf(new char[10000000]);

    FillBuffer(buf);

}

 

 

I will be the first to admit that the syntax of a smart pointer isn't the most beautiful thing in the world, but it has many advantages.  The first and most obvious… notice we no longer delete the pointer?  Don't worry, this doesn't result in a memory leak, this is RAII in action.  See what's happening here is, std::unique_ptr lives on the stack and full fills a pretty simple function.  On creation, it allocates your memory.  When it's destructor is called, it de-allocates your memory.  Since the destructor is guaranteed to be called if an exception occurs, there is no fancy error handling required here, and since the unique_ptr lives on the stack, it will be destroyed ( and thus the memory it holds ) when it goes out of scope.

The second less obvious thing here, notice as a parameter to FillBuffer, our pointer is based by reference? ( & ).  This is a by product of the unique_ptr.  Just like Highlanders, there can be only one.  unique_ptr's will prevent copies of the pointer from being made.  Sometimes this is desired behaviour, but sometimes you want to have multiple pointers to the same object.  In that case you can used std::shared_ptr.  Shared pointers work a bit differently, the allow multiple different pointers to point to the same thing and keep a reference count of the number of things pointing at your object.  Each time one is destroyed, the reference count is reduced, if the reference count hits zero, the memory is freed.  unique_ptr and shared_ptr both perform different functions, but both work to make memory management more controlled, more predictable and less fragile.  Once you get over the syntax, they actually result in a lot less work too, as your error handling is greatly simplified, you don't have to watch memory usage so closely, etc...

TL;DR version.  Smart pointers essentially wrap your heap based memory allocation in a stack based object.  This objects creation and destruction manage the lifecycle of your memory, simplifying error handling and making memory leaks a great deal less likely.

 

A small primer of C++ style memory management

It's possible at this point that you have very little prior experience with memory management at all, so to understand why something is better, it can prove handy to understand the way that is worse.  It's also quite possible that the idea of a pointer is completely alien to you, so let's have a quick primer of what a pointer is and how it works.

Let's look at a very simple program:

#include <iostream>

 

int main(int argc, const char * argv[])

{

    int * i = new int();

    *i = 42;

    std::cout << *i;

    delete i;

}

Here we are creating a pointer i that points to type int.

This is an important concept to get your head around.  A pointer is NOT the same type as what it points to.  I will explain this more in a moment, for now let's carry on.

You declare a pointer type using the asterix '*' operator.  As we saw earlier on, to allocate memory on the heap you use the new operator, therefore the line:

    int * i = new int();

Creates a pointer to type int named i and allocates space for an int on the heap using new.

Somewhat confusingly, the * operator is also used to access the data a pointer points to.  One important thing to keep in mind, a pointer is ultimately a location in memory.  On a 32 bit system there are 4,294,967,295 bytes (2^32) of memory and a pointer is simply the location of one of those bytes.  If it helps, you can simply think of pointers as bookmarked locations in memory.  To actually read what is at the location, you "dereference" it, which is where the * operator comes in.  So the line:

*i = 42;

Is saying, at the memory location pointed to by i, write the value 42.  Since we told the compiler what type of data our pointer points to, it knows how to do the rest.  Again, you dereference a pointer to read it's contents too, like we do when printing it out cout.  Once again, the compiler knows what the memory pointed to contains because it knows what type of data the pointer points to.

 

Let's go back in time a moment, remember when I said a pointer is not the same type as what it points to… this is very important to realize.  If you say 

    char * c = new char();

Just like before, you are creating a pointer to type char NOT a char.  This little sample might make the difference a bit more clear.

#include <iostream>

 

int main(int argc, const char * argv[])

{

    char c = 'A';

    int i = 42;

    

    char * ptrC = new char();

    *ptrC = 'A';

    int * ptrI = new int();

    *ptrI = 42;

    

    

    std::cout << "char c has value of " << c << " is located at " << static_cast<void*>(&c) << " and is " << sizeof(c) << " bytes" << std::endl;

    

    std::cout << "int i has value of " << i << " is located at " << static_cast<void*>(&i) << " and is " << sizeof(i) << " bytes" << std::endl;

    

    std::cout << "char ptrC has value of " << *ptrC << " is located at " << static_cast<void*>(ptrC) << " and is " << sizeof(ptrC) << " bytes" << std::endl;

    

    std::cout << "int ptrI has value of " << *ptrI << " is located at " << static_cast<void*>(ptrI) << " and is " << sizeof(ptrI) << " bytes" << std::endl;

}

 

(And yes, this example leaks memory).

Here is the results of running this application on 64bit Mac OSX, if you are on a 32bit OS, your results will be slightly different.

char c has value of A is located at 0x7fff5fbff8bf and is 1 bytes

int i has value of 42 is located at 0x7fff5fbff8b8 and is 4 bytes

char ptrC has value of A is located at 0x1001000e0 and is 8 bytes

int ptrI has value of 42 is located at 0x100103a60 and is 8 bytes


As you can see, both of our pointers are 8 bytes ( 64bit OS, 2^64 == 8 bytes ), even though the data they point to is substantially smaller.  In the case of a char pointer, the pointer is actually 8 times larger than the data it points to!  As I mentioned earlier, each pointer is actually just a location in memory.  That is what the 0x____________ represents.  This is a 64 bit address in hexadecimal form.

One other thing you might have noticed is even standard data types have a memory address, you can access the location of a variable in memory using the address of operator ( & ).  This makes the following possible:

#include <iostream>

 

int main(int argc, const char * argv[])

{

    int i = 42;

    int *pointerToI = & i;

    std::cout << "The answer to the meaning of life is "  << *pointerToI << std::endl;

 

    if(pointerToI == &i)

    {

        std::cout << "Memory locations are the same" << std::endl;

    }

}

 

Which will print:

The answer to the meaning of life is 42

Memory locations are the same


You need to be careful with ownership here, there are a number of potential pitfalls. If you point to a stack variable that goes out of scope, you are in for a world full of hurt, consider:

#include <iostream>

 

int main(int argc, const char * argv[])

{

    int * meaningOfLife = NULL;

    {

        int i = 42;

        meaningOfLife = &i;

    }

    std::cout << *meaningOfLife << std::endl;

}

 

The problem here is, meaningOfLife is now pointing at a memory address that is no longer valid.  i ceased to be when it went out of scope.  Now the most insidious part… if you run the above code, it will work and appear to display proper results.  Just because a location in memory is no longer valid, doesn't mean it doesn't still hold the correct data, memory isn't blanked when it is released.  This means your pointer will appear to work properly… until something reuses that address, then KABOOM!

 

 

Pointers to Pointers

Let's take a look at one more common hang up with C++ memory management, pointers to pointers.  We are getting awfully close to an inception moment here.  Consider:

#include <iostream>

 

int main(int argc, const char * argv[])

{

    int ** pointerToPointerToInt;

    

    int * pointerToInt = new int(42);

    pointerToPointerToInt = &pointerToInt;

    

    std::cout << **pointerToPointerToInt << std::endl;

    

    int * pointerToDifferentInt = new int(43);

    *pointerToPointerToInt = pointerToDifferentInt;

    

    std::cout << **pointerToPointerToInt << std::endl;

}

 

As you can see, you can actually have pointers to pointers, this is done using multiple * operators.  In fact, you can have pointers to pointers to pointers to pointers if you really wanted to, and that would use ****.

Otherwise, a pointer to a pointer works almost identically to a normal pointer.  The only difference is, when you dereference a pointer to a pointer using the * operator, you are left with an ordinary pointer.  You have to dereference it twice to get what it is pointing at.  In the above example, when we wanted to change the pointer our pointerPointer pointed at, we dereferenced it a single time, but when we wanted to access the actual value pointed at, we dereferenced it twice.  Pointers to pointers aren't actually all that uncommon, a linked list is often implemented this way… fortunately the logic is consistent.

 

The Array… think of it as another pointer...

On last thing to touch on… the array.  You may recall earlier when we created our char buffer, we actually did it using the array operator.  At the end of the day, an array is mostly just trickery over a continuous block of memory.  When you say:

char alphabet[24];

You are actually saying "give me a block of memory 24 chars long".  So pointers are arrays can do some rather neat things...

#include <iostream>

 

int main(int argc, const char * argv[])

{

    const char alphabet[] = { 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',

        'Q','R','S','T','U','V','W','X','Y','Z' };

    

    const char * letter = &alphabet[0];

    std::cout << *letter << std::endl;

    

    for(int i = 0; i < 26; i++)

        std::cout << *(letter++);

    

    letter = &alphabet[0];

    

    std::cout << std::endl << letter[5] << std::endl;

}

 

Run this code and we will see:

A

ABCDEFGHIJKLMNOPQRSTUVWXYZ

F

 

For the record, almost everything you see above IS A VERY BAD IDEA!  This is the kind of code we are trying to avoid, as it is horrifically fragile, but lets take a look at what we are doing here...

First we create a const char array holding the characters of our alphabet.  You cannot take the location of an array...

&alphabet;

An array is just a chunk of memory, if you want it's "location" you actually take the location of the first item in the array, that is exactly what:

const char * letter = &alphabet[0];

Does, this creates a pointer to type char and points it at the first character in our alphabet array.  As you can see, when we print it out we get A as expected.

Next we loop through the letters of alphabet printing our dereferenced pointer value.  You may notice each iteration we ++ our pointer… welcome to pointer arithmetic.  Remember before when I said a pointer was simply a location in memory, and an array was a continuous block of memory, well, you can iterate between pointer items using arithmetic.  The line:

(letter++)

Is functionally the same as

letter = letter + sizeof(char);

 

You may notice later on, we access our pointer like it was an array, when we called:

    std::cout << std::endl << letter[5] << std::endl;

The array subscript operator ( [ ] ) is functionally equivalent to doing the following

    std::cout << std::endl << letter[5 * sizeof(char)] << std::endl;

Be very with pointer arithmetic and using the subscript operator though, as there are absolutely no bounds checking done, so there is nothing to prevent you from trying to access a location that doesn't exist.

 

Hey, wait a minute here!!!

You may have noticed we use the * operator to both declare and dereference pointers.  We also use the & operator to both declare a reference as well as to get the address of a variable…  how does that work?

 

Well, it's all about context.  When declaring a variable or defining parameters, * indicates a pointer while & indicates a reference.  However, in all other scenarios, the operators have their alternate meaning.  I personally think this was a bit of a mistake for clarity reasons.

 

Conclusion 

Ok… so maybe it isn't EASY per say, but memory allocation in C++ isn't the black magic it is made out to be.  Especially because, 99% of the time, you should be able to completely ignore the later half of this document.  More to the point, if you stick to the standard datatypes like vector, map and string, they take care of all of this stuff for you!

 

If you find yourself using new, delete or working with a non const pointer, it should be an alarm bell of sorts.  Stop, take a closer look at your code and ask yourself "could I accomplish this task using a standard type?"  or "would a reference work instead?".  If the answer to either question is true, you are almost certainly better off refactoring your code.

Programming ,

Month List

Popular Comments

Browser usage on GameFromScratch.com
Subscribe to GameFromScratch on YouTube Support GameFromScratch on Patreon


16. May 2012

 

I asked a few days back about how many people would be interested in an HTML5/RPG series.  Between comments and emails I’ve received, there appears to be a fair bit of interest and I’ve decided to go ahead with it.  As HTML gaming is somewhat new to me, I am not sure yet exactly the format the series will take.  I think it will be a hybrid between a blog and a tutorial series; combining musings with instruction, with the ever present caveat that “I might be doing something really stupid!”.

 

 

Anyways, one of those things I always hated about browser development was cross browser support.  As I do more and more research, it seems that Internet Explorer is still very unpleasant to support.  What I got to wondering was, just how many people actually use IE anymore, I surely don’t 99.9% of the time.  So I took a look at this sites statistics since the start of 2012:

 

image

 

I was rather shocked to  see a few things.  First, I’ve known Chromes popularity has been growing, but I had no idea it was to that degree.  I suppose I shouldn’t be shocked, I use Chrome almost exclusively.  What I found perhaps the next most shocking is that Safari is beating out Internet Explorer!  I know both benefit from being bundled with the OS, but given the 10 to 1 sales gap between Windows and Mac, you would figure IE would be much higher.

 

That said, all of these statistics are fairly meaningless, as the audience to a site like GameFromScratch are going to be much more technically savvy than most sites.

 

I mostly just found them interesting and to use it as an excuse to not officially support IE when developing my tutorials, at least until Windows 8 ships with the next version.

Totally Off Topic

blog comments powered by Disqus

Month List

Popular Comments