in

Tutorial – Stylistic Fake 3D

A technique I frequently use in games is fake 3D. This may just be seen as a ploy for attention – “why use fake 3D when Game Maker has REAL 3D built-in right off the bat?” Well, there are advantages to it. It’s much easier to manipulate object depth manually. You can draw something ontop of another without any of those odd graphical issues where the two seem to keep “striping” into each other. You can use surfaces. You can ignore the concept of perspective. You can even do it in Game Maker Lite. There are plenty of things you can do with it. So  how do you?

Firstly, you should know how to use lengthdir_x and lengthdir_y properly. If you don’t, it doesn’t take much to learn – here’s something that will hopefully help.

The GML code for the functions are (and note that you’ll pretty much ALWAYS use them as a pair):

lengthdir_x(len,dir);
lengthdir_y(len,dir);

Their purpose is to give you a coordinate, if you take (0,0) and translate it len pixels in the direction dir (note the way direction is done in GM – 0 degrees is right, 90 degrees is up, 180 degrees is right, 270 degrees is down). Of course, it’s unlikely you’d need anything to be relative to (0,0), so your typical code may be something like:

oBall.x=x+lengthdir_x(len,dir);
oBall.y=y+lengthdir_y(len,dir);

An example of lengthdir is shown here:

If you still don’t understand lengthdir, look up some other tutorials on Game Maker Community – there are many very helpful ones.

Okay, so for the first little fake 3D test, you’re going to need a circle, which you can move with the directional buttons. Furthermore, he should be taking the screen view with him as he moves. Create a circular sprite (centralising its origin), give it an object and name it oCircle, and put this in Step:

if keyboard_check(vk_left) {x-=4;}
if keyboard_check(vk_right) {x+=4;}
if keyboard_check(vk_up) {y-=4;}
if keyboard_check(vk_down) {y+=4;}

view_xview[0]=x-320;
view_yview[0]=y-240;

Make a quick background which just needs to be a non-solid colour. A square will do fine. Make a new room, put the background in with it looping forever, put the guy somewhere in the room, and activate views and View 0 (tick “Enable the use of views”, make sure View 0 is highlighted, then click “Visible when room starts”) but DO NOT have it set to follow the player character (this is already done with the two last lines of code above, and holds the extra advantage of not stopping when the view hits the end of the room).

Now, to start with some fake 3D, make another object, calling it oPole. It doesn’t need a sprite, it will be drawn to be visible. Open up Draw, put in something like “draw_set_color(vk_red)” just to make sure it’s visible when drawn, then follow it up with the start of a draw_line code. Put x1 and y1 as x and y. x2 and y2 will be where the perspective is given.

Imagine you’re looking down on an area, where a number of poles are stuck into the ground perfectly vertically. You’ll notice that, as the poles get further away from the centre, from a 2D perspective two things happen. They appear longer, and they appear to point away from the centre. This is the effect we need to recreate.

Save and close the Draw event. Open up Create. Initialise two variables like so:

drawlength=0;
drawdirection=0;

Save and close Create, then open Step (click Step again afterwards). Because, in that world, poles looked to be longer as they were further away, the length and direction of the end point of the drawn line will need to be altered depending on their position. It’s made easier because oCircle, thanks to its view code, will ALWAYS be central. Therefore, the two variables can be relative to the player’s position. Add this to the open Step code box:

drawlength=point_distance(x,y,oCircle.x,oCircle.y);
drawdirection=point_direction(x,y,oCircle.x,oCircle.y)+180;

The +180 added at the end of point_direction is to ensure the line is pointing AWAY from oCircle, not TOWARDS it. point_distance is useful for length in this situation because of the line’s need to appear shorter as the player gets closer.

So now we have what’s necessary to finish off that draw_line. Save and close Step and reopen Draw. The code should now be modified to read as such:

draw_set_color(c_red);
draw_line(x,y,x+lengthdir_x(drawlength,drawdirection),y+lengthdir_y(drawlength,drawdirection));

Save and close the object, open the room again, and dot some oPoles around in it. Save and close the room, and run the game. Have a walk about and see what it’s like.

Provided it’s working (which it should be), that’s the bare bones to making one kind of fake 3D with Game Maker. I won’t keep going with the details, but here are some things to think about if you’re wanting to make a game with this style.

  • draw_triangle is very useful for making thick-looking items such as buildings. To make a wall you’ll need two triangles.
  • To draw things at the right depth (from the 3D point of view), you can generally work it by simply setting depth to point_distance(x,y,oCircle.x,oCircle.y);. The further away something is, the further back it will appear. There may be minor graphical hitches with this, particularly if you have objects of varying sizes right next to each other, but it’ll work generally.
  • To alter the 3D-POV height of something, DIVIDE (less high) or MULTIPLY (higher) the drawlength code. Do not add or subtract, it will look wrong.
  • Most objects will require more than one set of drawlength/drawdirection variables (either make an array or just add a number to the end of the variable names). For example, cuboids will require two sets – one for calculating the top left corner, and one for the bottom right (top right and bottom left are just done by mixing the codes of these two).
  • If you’re using the effect frequently in a game you’ll probably want to shorten the variable names for the sake of convenience – dl and dd or even just l and d will work fine and don’t require a massive amount of interpretation.

Around eight months ago I released a game using this kind of 3D, along with its source code. If you’re having a bit of trouble, or simply want to see how I did it, you can download the source here. It will work with Game Maker 7 or 8, and in Pro or Lite.

What do you think?

11 Comments

Leave a Reply
  1. Hey Andrew, can you post the code for cubes? the lines was like this:

    draw_set_color(c_red);
    draw_line(x,y,x+lengthdir_x(drawlength,drawdirection),y+lengthdir_y(drawlength,drawdirection));

    so i thought i could do this:

    draw_set_color(c_blue);
    draw_rectangle(x,y,x+lengthdir_x(drawlength,drawdirection),y+lengthdir_y(drawlength,drawdirection));

    can you tell me what i did wrong?

  2. Hey THANKS MAN!!! This has helped me HEAPS!!! I found out about this site because virgildog1950 on youtube was advertising and giving credit to you. TY A LOT MAN!! PS can you show us one of your 3d games???

  3. Ah, 2.5D. I’ve messed around with it in the past, and managed some simple math that doesn’t involve trig. To translate something from R3 space (x,y,z) to screenspace (sx,sy) when the camera is looking directly down on the x/y plane (z being the depth variable) it’s just some basic math:

    halfw = view_wview/2
    cx = x – view_xview
    sx = x – z*(cx-halfw)/(halfw+z)

    and similarly for y. Any time you use point direction, point distance, and lengthdir, it can always be simplified ALOT.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Current thinking on Game Maker for Nintendo DS and iPhone

GMIndie Podcast 2 – Sandy Duncan Interview