Subscribe to GameFromScratch on YouTube Support GameFromScratch on Patreon
8. August 2013

 

This is a kinda cool opportunity, this weeks Humble Indie Bundle actually includes the source code to many of the games included.

image

 

Four games plus tons of extra content. The Humble Weekly Sale features a new deal every Thursday. Be sure to jump on this amazing offer before it’s gone! This week, pay what you want for Uplink, Darwinia, Multiwinia: Survival of the Flattest, DEFCON, Voxel Tech Demo, City Generator Tech Demo, and source code access to Uplink, Darwinia, Multiwinia: Survival of the Flattest, and DEFCON. Plus you'll receive a never-before-heard story of Introversion from the studio's founders Mark and Chris. If you pay $19.99 or more in the first 24 hours of this weekly sale, you’ll also receive early access to Prison Architect and the full game upon its release, DRM-free and on Steam for Windows, Mac, and Linux! After the first 24 hours, you can still get Prison Architect with a purchase of $24.99 or more!

 

Fire it up DRM-free and cross-platform. Your purchase will get you four wonderful games DRM-free and on Steam for Windows, Mac, and Linux as well as two tech demos DRM-free for Windows. Pre-ordering Prison Architect will get you instant access to the alpha and the completed game DRM-free and on Steam for Windows, Mac, and Linux when it is finished as well as the early access game! Full system requirements for the games can be found here.

 

Pay what you want. Pay anything you want to receive four amazing games, two tech demos, and source code access. Pay $1 or more to receive Steam keys. Pay $19.99 or more within the first 24 hours of this sale and $24.99 afterwards to get Prison Architect!

 

Support vital charities. Choose how your purchase is divided: between Introversion Software, the Child’s Play Charity, or the Electronic Frontier Foundation. And, if you like this weekly sale, a tip to Humble Bundle would be greatly appreciated!

 

From what I can tell, at least for Uplink, the source code is written in C++.  Introversion previously offered the Uplink Developer CD.  What however is absent is the license it is being released under.  Be careful there, I am always hesitant accessing source code to a license that isn’t strongly defined.  Don’t want to end up on the wrong end of a nasty lawsuit because your game is similar to one of these titles and you peeked at the source.  I’m sorta surprised the license isn’t part of the release information.

I actually believe I own all of these games many times over as it is.  Until I hear terms of the code license, I’m staying away.

 

EDIT:

Thanks to @DarkCisum on Twitter, I have links to the licenses released that prior code releases used, it’s a fairly safe assumption the licensing remains the same.

Defcon License

Darwinia License

Uplink License

 

Wearing my IANL ( I am not a lawyer ) hat, I don’t see anything too scary, but also find the license a bit too vague for my personal comfort.

News ,

8. August 2013

 

In the previous post, we looked at creating a simple design concept for our game jet sprite.  Now we are going to start modelling our jet using Blender.

 

Of course, I cannot teach Blender in a single post.  Fortunately I have already covered modelling in Blender in a prior tutorial series.

 

Programmer Art: Blender for Programmers

 

If you already have experience with Blender, EXCELLENT!  Jump right in.  If however you haven’t much/any experience with Blender, I will assume you have gone through all of the above tutorials.  So instead of saying "Press X to delete the faces” I will simple say “delete the face”.  Dont worry, just keep the Quick Reference open in another tab and you should be OK.  If a concept is new or not covered in the above tutorials, I will go into a bit more detail.

 

In the design area, we created a top and side profile of our image, now if trimmed them down to two separate images, side and top.

 

Side.png

Side

 

Top.png

top

 

We are going to use these as modelling aids in Blender.

 

Setting up a background image in Blender.

 

Load up Blender, delete the default cube, then switch to Top view in 3D View.  Make sure you are in Orthographic view mode ( 5 on the number pad ).

Bring up the properties window ( N ) then locate Background Images and enable it:

image

 

Then click Add Image.  The dialog will expand with more options.

Click the Axis pulldown and select Z Axis Top, like so:

image

 

Click the Open button and find your top reference image.

image

 

Your Blender should now look something like this:

image

 

In the Properties window, near the bottom of the Background Image panel, you should see a manipulator for X and Y. 

image

 

Move the image along the X axis so it’s aligned with the Y axis in your top view, like so:

image

 

Now repeat the same process for side image.  It is exactly the same process.  Click Add Image, and another image will be available in the panel.  This time select axis as X Left and obviously use the side reference image instead.  If you have done it successfully, your Left view (Ctrl + 3 on numpad ) should look like this:

 

image

 

Now we want to make sure the two views are somewhat the same size in both the left and top views.  The way I do this is to simply create a cube the length of the reference image in the side view ( Add cube, S)cale + Y ), like so:

image

 

Then switch into Top View:

image

 

Hmmmm… this isn’t right… our top reference image is far too big ( or I suppose, the side image is far too small… ).

 

It’s a simple enough fix.  In the properties window, where we adjusted the X position earlier, there is also a setting for size.

image

 

Adjust the size and position of the background image until it matches the dimensions of your cube.  Be sure to use the proper dimensions, as there will be a set of controls for each the top and side background images.  IF you need to see through the CUBE texture while adjusting, hit the Z key to enable XRay mode.  When you are done, your top view should look like:

image

 

Perfect.  We now have two perfectly calibrated background images to work with.  Now delete the rectangle, we no longer need it.

 

OK, that section got a bit picture heavy, so I will end this part here so page load times don’t become insane.


Click here for the Next Part


Art , ,

7. August 2013

 

This isn’t an area I spend a ton of time on, as I haven’t got much talent for drawing.  That said, if I just fire up Blender and start modelling I tend to be a lot slower then if I nail down the basics of my concept, at least the proportions and overall shape, before even beginning to model.

 

In this case my concept was pretty simple… I want to make a jet that is a throwback to classic planes of old like the twin tailed Lockheed P38 Lightning or the DeHavilland Vampire, except with wing mounted engines like the Me-262.  However, I want it to appear near-future modern, like a contemporary of the F22 Raptor or F35 Lightning II.

 

For non plane buffs, I basically want:

 

This (P38):

p38

 

Or This (Vampire):

Vamp

 

With engines like these (Me-262):

me262

 

But more modern/futuristic, like this ( F22 ):

f22

 

 

Got it?  So basically I want a retro style twin tailed jet that looks futuristic.

 

So, time for some doodling!  I have a tendency to start with something really quick, break it down into individual pieces and go from there.  This way I get mostly the correct perspective, but I can work on smaller details instead of big picture… I can also quickly decide what works and what doesn’t.

 

For this, I worked entirely on my iPad Mini using a 5 dollar stylus and the application iDraw, which is a vector based graphic suite for iOS and MacOS.  Obviously any sketching app would work, as would paper if you have access to a scanner or digital camera.

 

Here is my first brain dump of the concept, side and top view:

1

 

I'm relatively happy with the top view, but hate the under-wing engine and am not a fan at all of the side profile.  I am thinking wingmounted engines don't work too well with the look I am shooting for here.

 

Instead I am going to switch to a single jet engine, like the Vampire pictured above.  Let’s clean up the tail section a bit and move to a single centrally mounted engine, again top and side view:

2

 

OK, I'm pretty happy with that look over all, now I’m going to look at the top and wing layout.  I start with:

3

 

Not really a fan.  Doesn’t make a ton of sense for the wing to extend out in front of the air intake.  Instead I decide to extend the air intake forward quite a bit, like so:

4

 

I like the overall shape better, it’s starting to look more modern, but I am still not a fan of the cockpit, nor have I nailed down the side profile yet.

 

On to the side profile.  I start with a quick sketch of the side, now using the forward wing, air intake and single engine. 

5

 

I did a quick sketch in black and it’s too fat and not very modern.  Drew over it in red more to my liking.

 

Now it’s a matter of figuring out the cockpit I am still not happy with, as well as the front view.

6

 

Started with a 3/4 view of the cockpit area, a rough front sketch, then a slightly cleaner one.  Over all, I’m pretty happy with the front profile.

 

So, I’ve got my basic design down, now the most important part, as a modelling aid and so I get the proportions generally right, I trace over the side and top view of my design using the line tool and end up with this:

7

 

The basic outline for the side and top profile of our jet.  I am certainly going to win no awards for artistic talent, but it should be sufficient for my needs and over all, I’m fairly pleased with the design concept.

 

You will see how we use it in the next part when we fire up Blender.

Art, Design

7. August 2013

 

I am about to create a game sprite for my own use and I figured I would document the process.  I am going to make an animated jet sprite and ultimately output a multi-frame single sprite sheet ready for use in a game.

 

Through the process I (may) cover:

  • Concept design ( as far as I do it anyway… )
  • Modeling it in Blender ( probably over multiple parts )
  • Texture painting in Blender
  • Texture finishing in GIMP or another image manipulation program
  • Animation ( maybe, might be overkill ) in Blender
  • Rendering in Blender
  • Making a sprite sheet, probably using TexturePacker
  • Using the sprite sheet in code (maybe ), probably using Haxe/OpenFL/Some Haxe Library, but subject to change.

 

Basically if I need to do it, I will document the process.

 

Keep in mind… I am a programmer who dabbles in art, and it shows!  We are just one step up from programmer art here, but the process is pretty much the same, you just need to add a bit more talent and patience. I am certainly not recommending anyone follow my work process, but it may give you some ideas.  Worst case scenario, it may just give you a good laugh!

 

Hope you enjoy.

News, Art , ,

4. August 2013

 

I took a look at the Awe6 inverted game framework a couple months back and was quite impressed.  Shortly after I decided to go with Haxe the NME project announced the rebranding to OpenFL and move to Haxe 3, something I looked upon with some doom and gloom.  Fortunately it’s not that bad after all.  A couple days ago, Awe6 announced a new release supporting OpenFL and Haxe 3, among other things.

 

From the release notes:

 

RC 2,0,572

 

Major release, some breaking changes. Includes:

  • Haxe 3 compatible (refactor to new syntax and conventions)
  • NME drivers replaced with OpenFL drivers
  • Optional paramaters refactored (Floats, Ints, Bools made non-nullable)
  • Run script NME references replaced with OpenFL references
  • FlashDevelop templates updated for above
  • API docs not yet revised, due to chxdoc compatibility

 

Good news and good work.

 

So, I guess I have to eat some crow about the move to OpenFL.  At this point in time, Aw6, Flixel and Haxepunk are all compatible with OpenFL.  So it appears the move hasn’t fragmented the landscape as much as I expected.

Programming, News

 

Month List

Popular Comments

GameDev math recipes: Collision detection using bounding circles
Subscribe to GameFromScratch on YouTube Support GameFromScratch on Patreon
12. December 2012

In our prior tutorial we looked at using an axis aligned bounding box to perform collision testing.  One big downside was the handling of sprite rotation.  Today, we will look at using a circle instead of a rectangle for our collision detection. The circle has the obvious advantage of being the same size no matter how much you rotate it.  It is also extremely fast to calculate and test for collisions.  Although as you can see from the application to the right, it isn't extremely accurate.

 

Just the Math

Calculating the bounding circle radius:

function getBoundingCircleRadius(sprite){

    return Math.sqrt(((sprite.image.width/2 * sprite.image.width/2)

            + (sprite.image.height/2 * sprite.image.height/2)));

 

}

 

Checking for an intersection between circles


function circlesIntersect(c1X,c1Y,c1Radius, c2X, c2Y, c2Radius){

    var distanceX = c2X - c1X;

    var distanceY = c2Y - c1Y;

 

    var magnitude = Math.sqrt(distanceX * distanceX + distanceY * distanceY);

    return magnitude < c1Radius + c2Radius;

}


 

 

Description

As mentioned earlier, a bounding circle removes the complexity of dealing with rotation.  This is a bit of a double edge sword though.  An axis aligned bounding box can be tighter and more accurate than a bounding circle, but as it rotates it quickly becomes less so.  The following application illustrates the same shape bounded by both a bounding box and a bounding circle.  As you can see, at some points the bounding box is a great deal more accurate, but as it rotates, it becomes a great deal less accurate:

 The calculations for the bounding circle are however a great deal easier to perform.  Let's take a look at them now.

Math.sqrt(((sprite.image.width/2 * sprite.image.width/2)

            + (sprite.image.height/2 * sprite.image.height/2)));

First we start off by calculating the radius of our sprite's image.  This is a matter of calculating the length of furthest point from the centre, giving us the smallest possible radius that encompasses our sprite.  The process is rather straight forward and is calculated using pythagorean theorem again.  We are essentially calculating the magnitude (or distance) from the centre of our sprite to the corner, we do this by forming a right angle triangle.

For a bit of a refresher on pythagorean theorem (which is used A LOT), consider this diagram I stole:

pythagorean theorem

 

a is the X coordinate of our corner, b is the Y coordinate of our corner, therefore the distance or magnitude ( the second is the correct term mathematically ) between those two points is c, which you can calculate by taking the square root of the square of a plus the square of b.  Or using our actual variable names, distance = square root( x * x + y * y).  The resulting value of this equation is the distance between x and y.  So, how did we come up with the values for x and y?  That part was simple, since our pivot is at the centre of our sprite, x is simply half the width of the image, while y is half the height.

If that just confused the hell out of you, the following diagram might help a bit.  It illustrates how pythagorean theorem is being applied to our actual jet sprite to calculate the distance to the corner.

DistanceToCorner

 

So, now we have the distance to the corner, which we can now use it as our circle's radius.  Now we need to figure out how to determine if an intersection occurs.

var distanceX = c2X - c1X;

var distanceY = c2Y - c1Y;

 

var magnitude = Math.sqrt(distanceX * distanceX + distanceY * distanceY);

return magnitude < c1Radius + c2Radius;

This again is a simple and quick equation.  Actually, its the exact same formula again, this time though, we calculate x and y by measuring the magnitude ( distance ) between each of our circles centre points.  Once we have calculate the magnitude between the two circles, we simply check to see if that distance value is less than the total radius of both circles.  If the magnitude is less than the radius of both circles combined, they intersect, otherwise they don't.

One thing you should be aware of ( but not too concerned with initially ) is the square root operation is an expensive one and generally something you want to avoid.  A square root is many times slower to perform than a multiplication or division.  In this situation, it is a very easy to eliminate, you simply square both sides, like so:

function circlesIntersect(c1X,c1Y,c1Radius, c2X, c2Y, c2Radius){

    var distanceX = c2X - c1X;

    var distanceY = c2Y - c1Y;     

    var magnitudeSquared = distanceX * distanceX + distanceY * distanceY;

    return magnitudeSquared < (c1Radius + c2Radius) * (c1Radius + c2Radius);

}

 

If you are still struggling with the math though, these kinds of optimizations can happen later if they are needed at all.  It's often easier to optimize after the fact anyways, so don't worry too much about being fast quite yet.  It's far too easy to get caught up optimizing prematurely.

 

Complete Code

<!DOCTYPE html>

<html>

<head>

    <script src="http://code.createjs.com/easeljs-0.5.0.min.js"></script>

    <script>

        var jetSprite,jetSprite2;

        var boundingCircle1, boundingCircle2;

        var actualBounds;

 

        var stage;

 

        document.addEventListener('DOMContentLoaded', demo,false);

 

 

        function getBoundingCircleRadius(sprite){

            return Math.sqrt(((sprite.image.width/2 * sprite.image.width/2)

                    + (sprite.image.height/2 * sprite.image.height/2)));

 

        }

 

        function createBoundingCircle(sprite,useMaxExtents){

            var g = new createjs.Graphics();

            g.setStrokeStyle(2);

            g.beginStroke(createjs.Graphics.getRGB(0,0,255));

            var radius = getBoundingCircleRadius(sprite);

            g.drawCircle(sprite.x,sprite.y,radius);

            return new createjs.Shape(g);

        }

 

        function circlesIntersect(c1X,c1Y,c1Radius, c2X, c2Y, c2Radius){

            var distanceX = c2X - c1X;

            var distanceY = c2Y - c1Y;

 

            var magnitude = Math.sqrt(distanceX * distanceX + distanceY * distanceY);

            return magnitude < c1Radius + c2Radius;

            // Note, sqrt is a slow operation, square both sides for better performance

            // var magnitudeSquared = distanceX * distanceX + distanceY * distanceY;

            // return magnitudeSquared < (c1Radius + c2Radius) * (c1Radius + c2Radius);

        }

 

        function demo(){

            stage = new createjs.Stage("theCanvas");

 

            jetSprite = new createjs.Bitmap("jetsprite.small.png");

            jetSprite.regX = 30; // Half image width

            jetSprite.regY = 40; // Half image height

            jetSprite.y = 200;

            jetSprite.x = 100;

 

            jetSprite.image.onload = function(){

                boundingCircle1 = createBoundingCircle(jetSprite);

                stage.addChild(boundingCircle1);

            }

 

            stage.addChild(jetSprite);

 

 

 

            jetSprite2 = new createjs.Bitmap("jetsprite.small.png");

            jetSprite2.regX = 30; // Half image width

            jetSprite2.regY = 40; // Half image height

            jetSprite2.y = 200;

            jetSprite2.x = 300;

 

            jetSprite2.image.onload = function(){

                boundingCircle2 = createBoundingCircle(jetSprite2);

                stage.addChild(boundingCircle2);

            }

 

 

            stage.addChild(jetSprite2);

 

            //And go...

            stage.update();

 

            // onFrame will be called each "tick". Default is 50ms, or 20FPS

            createjs.Ticker.addListener(onFrame);

        }

 

        function onFrame(elapsedTime) {

            jetSprite.x++;

            jetSprite.rotation = jetSprite.rotation+1;

            stage.removeChild(boundingCircle1);

            boundingCircle1 = createBoundingCircle(jetSprite);

 

            stage.addChild(boundingCircle1);

            stage.addChild(boundingCircle2);

 

            if(circlesIntersect(jetSprite.x, jetSprite.y, getBoundingCircleRadius(jetSprite),

                    jetSprite2.x, jetSprite2.y, getBoundingCircleRadius(jetSprite2)))

            {

                jetSprite.x = 100;

            }

 

            stage.update();

        }

    </script>

 

</head>

<body>

<canvaswidth=400height=400id="theCanvas"style="background-color:black"/>

</body>

</html>

 

 

See Also

See Collision Detection using an axis-aligned bounding box for details on bounding boxes.

 

If you are still struggling with the use of triangles, you really need to wrap your head around this concept.  This Youtube video ( with horrible audio ), gives a good example of pythagorean theorem in action:

 

 

Programming

blog comments powered by Disqus