Fake 3d in 2d camera

D

Darren

Guest
I'm stacking sprites to make a fake 3d like so

Create event:
image_speed = 0;

draw event:
for (var i = 0; i < image_number; i++)
{
draw_sprite_ext(sprite_index, i, x, y - i, image_xscale, image_yscale, image_angle, c_white, image_alpha);
}

when I rotate them by image angle they have an awesome fake 3d effect, but I want to adjust the view angle and have the sprites adjust accordingly (if I do image angle they all pivot around their own axis, so I need to change the view angle instead, the objects are in the same place but they need to look different depending on where the camera is like 3d) how would I adjust the way the sprites are stacked to draw according to the view_angle?
 
Not sure if I understand correctly, but if so you'll need to add some code in your for loop.
i seems to be the depth order of your sprite stack where as 0 is the lowest sprite. So what you need to do is calculate the i into an offset for x and y depending on your view. With increasing i the offest get's larger. and that should do the trick.
Can't help you with the maths since I don't fully understand what you're trying to do - sorry :)
 

Hyomoto

Member
If I am understanding your question correctly you need to figure out how far from the edge of the view the sprites are. This is pretty simple really, you need to subtract the object x from the view x, then figure out how far away from the center it is, then use that outcome to subtract some value from where it is drawn. Here's a generic version:
Code:
var _dist_x = ( x - room_width / 2 ) / 100;
draw_sprite( sprite_index, image_index, x + _dist_x, y )
I've simply calculated how from from the center of the room the object is, then divided it by 10 so that every 100 pixels results in another offset of 1 full pixel. Then you do the same thing for y. You can easily adapt this to the use of views, like I said, by subtracting the view position and instead of room_width you use the view_width.
 
D

Darren

Guest
The mathematics totally confuses me. I've tried various methods, I love the effect so much but I just can't get it working. Hopefully if I show you guys what I'm going for it'll explain better.

This is the effect
http://www.like100bears.com/writing/2d-3d-in-gamemaker-studio

And this is it adapted to fake 3d

This is the creator explaining very vaguely how he did it
https://twitter.com/moppin_/status/794807870835392512

Using view angle just rotates the camera obviously, so I need to make the sprite angle change so that whilst everything stays in the same place, it looks as if you're looking at it from a different angle. image_angle does the effect I need, but they all rotate around themselves rather than stay in the same place.
 

RangerX

Member
Well this is not a 2D game in my opinion. You need a 3d plane as the ground and in the video there, some objects are 3D like the pillars on the ground, the wood cabin, etc
 
D

Darren

Guest
Well this is not a 2D game in my opinion. You need a 3d plane as the ground and in the video there, some objects are 3D like the pillars on the ground, the wood cabin, etc
They aren't, it's all 2d using the effect I'm trying to achieve.
 
N

Never Mind

Guest

Look at the way his image is stacked up!
You would be wrong to say that the images stay in the same place and only rotate.

..Yes they stay in the same theoretical 3D space (trees don't move) but in order to create that effect you'll probably be manipulating both the angles and locations things are drawn with.
(Well.. I guess if your main character is in the exact center of the view then technically it only needs to change image angle)

Some easy math functions for you to start playing with are:
lengthdir_x / lengthdir_y

Also, keep in mind
In that video the camera has only one rotation axis of freedom.
Notice how the level is tailored specifically for that camera's height and downward angle.
When your planning out your level environment and camera angles try to think of little tricks to make things easier on yourself.

If I were you I'd start by experimenting with a couple isometric projects before attempting this.
It should help you think in more 3D terms.

This is an interesting topic, I might make a little project to mess around with.
I have the feeling basic users could possibly cheat by carefully selecting sprite origin points to make some basic 3D effects.
But I haven't thought about it much yet. I'll come back if I find anything useful.
 
Last edited by a moderator:

RangerX

Member
Daren, like it or not, that wooden cabin and the pillars on the ground are either 3D or sprites with ALOT of angles.
Proof of that, everything that is 2D and a sprite doesn't change angle when the cam rotate (like any sprite would in a 3D world since its 2D). The pillars on the ground and cabin DO change angle so they are either 3D objects or sprites with alot of sub-image to cycle through and reproduce the look or 3D rotation. There's no other technical ways to do that cabin regardless of what the creator might say.
 
H

HammerOn

Guest
Daren, like it or not, that wooden cabin and the pillars on the ground are either 3D or sprites with ALOT of angles.
Proof of that, everything that is 2D and a sprite doesn't change angle when the cam rotate (like any sprite would in a 3D world since its 2D). The pillars on the ground and cabin DO change angle so they are either 3D objects or sprites with alot of sub-image to cycle through and reproduce the look or 3D rotation. There's no other technical ways to do that cabin regardless of what the creator might say.
You can notice the many stacked images if you watch in 720p.
The roof of the cabin are rectangles separated with more vertical space and stacked in the opposite direction to give the impression of an ramp.

Look at the way his image is stacked up!
You would be wrong to say that the images stay in the same place and only rotate.
They stay in the same position.
The trick is the sprite origin. If it was separate sprites with their own origin, you had to calculate the positions too.


This seems like a lot of work but the effect is really cool.
I would use 3D objects anyway since you can achieve an similar effect with pixel textures and orthographic camera in a faster way.

About OP question, when the view rotates the objects rotates in the opposite direction. It's just something like "-view_angle".
 
Last edited by a moderator:

RangerX

Member
Very hard to see with the video's jittering in the recording. (although its possible to be made like that, heck, there' could be a sprite for each pixel if he'd want)
 
N

Never Mind

Guest
@HammerOn When you say "They stay in the same position" if your talking about the video, then that doesn't seem possible to me.
Getting fancy with your sprite origins only works if the cameras angle never changes.
As soon as you want the cameras angle to change your probably doing some sort of displacement to the sub-images.

@Darren (op)
I found a simple way to set this up:

Here's the meat of it:
Code:
///obj_control step event

view_angle[0] += mouse_force_x;

with(all){
if(id != other.id and object_index != obj_drawshadows){
var CamForward = -view_angle[0]+90;
depth =  dot_product(x,y, lengthdir_x(1,CamForward ) , lengthdir_y(1,CamForward ) );
}
}
In like, a hundred bears example
the sub-images are drawn 1 pixel apart in an upwards stack:



..So for my trees I just modified it to stack in the upwards direction relative to the view_angle!
Code:
///obj_tree draw event
for (var i = 0; i < image_number; i++)
{
var xx = x + lengthdir_x(i,-view_angle[0]+90);
var yy = y + lengthdir_y(i,-view_angle[0]+90);
draw_sprite_ext(sprite_index, i, xx,yy, image_xscale, image_yscale, image_angle, c_white, image_alpha);
}

Boom! That should get something like this going. :)
Obviously there are a bunch of different ways you can achieve pseudo 3D effects.
 
Last edited by a moderator:
D

Darren

Guest
@HammerOn When you say "They stay in the same position" if your talking about the video, then that doesn't seem possible to me.
Getting fancy with your sprite origins only works if the cameras angle never changes.
As soon as you want the cameras angle to change your probably doing some sort of displacement to the sub-images.

@Darren (op)
I found a simple way to set this up:

Here's the meat of it:
Code:
///obj_control step event

view_angle[0] += mouse_force_x;

with(all){
if(id != other.id and object_index != obj_drawshadows){
var CamForward = -view_angle[0]+90;
depth =  dot_product(x,y, lengthdir_x(1,CamForward ) , lengthdir_y(1,CamForward ) );
}
}
In like, a hundred bears example
the sub-images are drawn 1 pixel apart in an upwards stack:



..So for my trees I just modified it to stack in the upwards direction relative to the view_angle!
Code:
///obj_tree draw event
for (var i = 0; i < image_number; i++)
{
var xx = x + lengthdir_x(i,-view_angle[0]+90);
var yy = y + lengthdir_y(i,-view_angle[0]+90);
draw_sprite_ext(sprite_index, i, xx,yy, image_xscale, image_yscale, image_angle, c_white, image_alpha);
}

Boom! That should get something like this going. :)
Obviously there are a bunch of different ways you can achieve pseudo 3D effects.
WOW! Honestly amazing job, well done. You've done it so simply and efficiently, I wish I had that kind of brain! Thank you so much.
 
N

Never Mind

Guest
Hey no problem ;) This is fun stuff !
You may be less amazed when you've spent as much time as I have tinkering with game related experiments.

Don't forget to share what you make with us
 
H

HorrellTech

Guest
A bit late to the cause here, but here is some code I made to get it to work.


//h2d_draw_auto(sprite_index, z);
var i;

for (i = 0; i < sprite_get_number(argument0); i += 1)
{
draw_sprite_ext(argument0, i, x + lengthdir_x(i, -view_angle + 90), y + lengthdir_y(i, -view_angle + 90), image_xscale, image_yscale, image_angle, c_white, image_alpha);
}
 
M

madcapacity

Guest
@HammerOn When you say "They stay in the same position" if your talking about the video, then that doesn't seem possible to me.
Getting fancy with your sprite origins only works if the cameras angle never changes.
As soon as you want the cameras angle to change your probably doing some sort of displacement to the sub-images.

@Darren (op)
I found a simple way to set this up:

Here's the meat of it:
Code:
///obj_control step event

view_angle[0] += mouse_force_x;

with(all){
if(id != other.id and object_index != obj_drawshadows){
var CamForward = -view_angle[0]+90;
depth =  dot_product(x,y, lengthdir_x(1,CamForward ) , lengthdir_y(1,CamForward ) );
}
}
In like, a hundred bears example
the sub-images are drawn 1 pixel apart in an upwards stack:



..So for my trees I just modified it to stack in the upwards direction relative to the view_angle!
Code:
///obj_tree draw event
for (var i = 0; i < image_number; i++)
{
var xx = x + lengthdir_x(i,-view_angle[0]+90);
var yy = y + lengthdir_y(i,-view_angle[0]+90);
draw_sprite_ext(sprite_index, i, xx,yy, image_xscale, image_yscale, image_angle, c_white, image_alpha);
}

Boom! That should get something like this going. :)
Obviously there are a bunch of different ways you can achieve pseudo 3D effects.
Hey @Never Mind - I know this a couple of years old but I just came across this now.

Can you explain how this:
Code:
var xx = x + lengthdir_x(i,-view_angle[0]+90);
var yy = y + lengthdir_y(i,-view_angle[0]+90);
makes the stacking relative to the view_angle? I'm confused as to why you need to make the view_angle negative and add 90 degrees to it?

Thanks a lot!
 
C

CROmartin

Guest
Hey @Never Mind - I know this a couple of years old but I just came across this now.

Can you explain how this:
Code:
var xx = x + lengthdir_x(i,-view_angle[0]+90);
var yy = y + lengthdir_y(i,-view_angle[0]+90);
makes the stacking relative to the view_angle? I'm confused as to why you need to make the view_angle negative and add 90 degrees to it?

Thanks a lot!
Hi! We all know that in the GM angle circle point 0 is on "right" side of circle, you are probably know that "face" or "front" of sprite should always be facing right side in sprite editor so you can use all 360 degrees effectively. Well thing is with this method we are setting "face" or "front" of sprite in up direction(we know that up in direction is 90 degrees) because naturally sprite stacking sprites on y will create that effect, well there is possibility to stack also on x to remove that "+90" by default but I think that would just complicate things. We are setting view_angle negative because we want feel like we are looking at objects(angle difference creates that feel), if we didn't set it like that objects would look like they are "looking, pointing" at us. Scheching things on paper while tracking angles in debugger will help you a lot in understanding this method.
 
Top