View like in Smash Bash [SOLVED]

#1

Hey,

i am interrested in perspective camera view and stuff related to that. I found the game SMASH BASH and really love the way it looks.
I googled many times the last two weeks, found stuff like Mode7, Parallax scrolling and 2.5D. But im a bit lost when it comes to defold and rendering.
I also looked at this article and tryed to figure out, how dont starve works. I kinda made my brain explode watching these trees for hours :see_no_evil:

Are there any tutorials / examples on how to set up my project to get a view like in SMASH BASH?

1 Like

#2

Games like Don’t Starve or others like Animal Crossing use tricks with their sprites and cameras. Imagine all of the sprites are on a super steep cliff and are trying to stand at an angle to stay on the cliff. So sprites are rotated a bit to face the camera. That’s the secret sauce to making it look good.

Smash Bash (the latest demo build from here http://smash-bash.com/ ) is like this too. What you’re probably missing is rotating the sprites right.

Mode7 like effects are possible. If there’s a specific type of effect you want mention it.

For parallax effects you just offset the positions by a small multiplier based on y position or whatever arbitrary thing you want such as camera position or layer.

Keep practicing, learning, and asking questions!

3 Likes

#3

Interesting Theme.

Moving a character/player behind some objects (f.e. trees, buildings etc)… how does it works?

Of cause using the Z-value may help here. Scrolling a background (like in dont starve the water f.e.) maybe a different layer.

I dont know how all these “pseudo 3d-effects” are working. maybe someone else can say something better.

I could imaging (a cheap and fool way) could be changing the Z-Values of the displayed objects depending on the player-pos (Z).
Followed by the move-speed of the object where the move-speed (horizontal) is depending to the Z-position.

1 Like

#4

Don’t Starve is actually pretty straightforward 3D (see here with a mod that frees the camera) but all the sprites are billboards—they always rotate to face straight at the camera. I believe you can do that in a vertex shader.

If you don’t actually need perspective, you can just make a 2D game with a bit of draw-order juggling. Here’s a nice little explanation of a few techniques for that. That’s how most top-down games are done, like Zelda, Hyper Light Drifter, etc.

You can use a perspective (or orthographic) camera, angled slightly, and sprites stood on end for trees, buildings, etc. Like so:

If you angle the sprites away from the camera your probably get a better look, like Pkeod said:

5 Likes

#5

The link of ross explains what I tried to say ( my thinkings about it) :slight_smile:

0 Likes

#6

maybe @GerodruS would love to share some tips or scripts. And receive the credit for being a reference =]

1 Like

#7

Thank you guys for all that hints :slight_smile:
I guess i will read a bit about rendering.

I guess i have to do that inside a render script? Or is it better to do that inside a normal script file, where i just change the objects z coordinates between -1 and 1?
Aaand i thought i can’t set sprites inside the editor without an game object? So i need, for example, a gameobject for every tree?

0 Likes

#8

Check out this

Yes, you need a game object for each tree. You could stream in gos in and out as your player moves around the world.

0 Likes

#9

Hey, i can be useful too! :3

Hi @LosJustos, what @Pkeod and @ross.grams are saying are essentially correct for SMASH BASH. For me this approach was mostly inspired by Ragnarok Online (though the level itself is 3D there), we remembered about Don’t Starve a bit later. I’ll just explain the steps a little i guess:

  1. We have a perspective camera, which is looking onto the ground under some angle (22.5 degrees on x axis worked well for us). FOV is 1.0177028.
  2. Ground tilemap is flat.
  3. All sprites (characters, trees, houses, etc) are rotated onto the same angle as camera, so they are kinda perpendicular to the view (because the camera is perspective it is actually correct only for the center point, but it doesn’t matter).
  4. We also have some special 2.5d objects (like “vertical” fences), which contain 2+ sprites, some are horizontal, which is not rotated and is parallel to the ground (for the top part of the fence and the shadow), some are vertical (perpendicular to the camera - vertical bars, usually 2/3 per fence). We have some simple trigonometry math to position this object correctly, because the top part should be shifted a little bit. Some “awesomely” drawn explanations here:
  5. There are also some other flat objects, like dirt on the ground.
  6. Draw order is simple: tilemap -> ground objects -> all other objects.

Basically thats all what we have, all z-sorting is done by the engine (although we have some glitches when objects are located nearby, even though they have different Y/Z coordinate). Here’s how it’ll look like if we change the angle to more extreme value:
dmengine_2017-10-28_17-25-03
Initially we had a rotating script on every object, but because of 1024 scripts limit we had to fix it. Now we have collections containig multiple sprites (positioned by level-designers hand), and one script on this collection, which knows about amount of the objects and simply calls

for i = self.index_start, self.index_end do
  go.set_rotation(camera_rotation, predicate .. tostring(i))
end

Objects have to be named correctly of course.

While this is basically real 3d, you can do some simple 2.5d as @stephenkalisch proposed. Orthogonal camera, flat sprites, and you change z on them depending on their y value. Something like position.z = -position.y / 1000. This way sprites which are further away will be drawn first, and closer sprites will be drawn last (and will be in the front). This is kinda easier on the engine and saves you from some glitches, but you lose a real 3d look without perspective camera.

And with 3d and some simple shaders you can do some fun stuff like this (coub).
dmengine_2017-10-28_17-52-15

12 Likes

#10

Wow thank you very much. It sounds to be much work to design one level with this method^^

0 Likes

#11

Well, for smaller maps you can live with 1 rotating script per object, so you design the level in the same way as standart 2d map without almost any overhead: you just place an object on the ground and it will rotate automatically on launch.
And collections with multiple static objects (5-10 trees for example) can be reused in different parts of the map, so it’s technically even faster. :smile:

0 Likes

#12

Do i understand you right?
I just rotate the sprites around the x axis, like shown in ross.grams picture? Till now i thought i have to rotate them that they face to the camera. If i move right, they will update their rotation.

It gets more and more understandable :heart_eyes:

2 Likes

#13

Yes, we only rotate object around x axis once (same 22.5 degrees angle as the camera). This is not “billboards”, where sprite always looks towards the camera, but with small Field of View player doesn’t really notice the distortion if the sprite is near the edges.
With high FoV, however, it will be noticeable (like the houses in my last screenshot), but good 3d feeling is easily achieved with low FoV values. You can just move the camera higher if you want to zoom-out instead of increasing FoV.

And again, you don’t have have to manually rotate every object, you can just add a simple script to every sprite object, which calls something like go.set_rotation(camera_rotation) in start(), where camera_rotation is the ‘global’ rotation of the camera (you can get it via script too) and is stored somewhere globally, so every sprite can access it.
This way you can play around with camera angle without having to change every object on the screen. You can even set rotation on every update(), then you can even change camera rotation during the gameplay if you want to.

Also note that the ‘pivot’ point of the sprite object should be in the legs, so it is rotated around ground point, not aroud the center. This might not be noticeable at a glance, but still is a bad idea.

4 Likes

#14

okay.
I will experiment a bit.

Thank you very much.

0 Likes

#15

I tryed out a bit and got some problems.
First of all, i setted up my perspective camera like described here: https://read.bookofdefold.com/defold-a-z/cameras/prespective-camera.html

I created a tilemap and placed 3 trees onto it. I rotated the Trees with 22.5 and it looks pritty nice.

But if i now rotate the camera with 22.5 i get some errors. My trees have to be on much higher z values. If i change the y value to a higher one, i have to increase the z value too.
Here i have set the z value of the tree to 75. below it will not be shown. If i increase the y value of my tree it dissapears. Also it looks weird. The Tree “moves” on the ground because its to heigh.

My camera has following settings:
aspect_ratio: 1.0
fov: 1.0177028
near_z: 0.1
far_z: 1000.0
auto_aspect_ratio: 1

I played around with them, but didnt get any better result.

1 Like

#16

Yeah, we had that problem. You should do two things:

  1. Check that your tree object pivot is at the bottom (move sprite upwards). Spawned tree should have its position to have z=0, so it is located right on the ground.
    java_2017-10-29_01-06-02
  2. Because of the similar position, engine can’t really decide which object (tree or tilemap) to draw first, so we have to tell him that manually. Change your render script to draw tilemap first, and objects after that. It should look something like this:
-- some setup, viewport, blend func, etc...

render.draw(self.tilemaps) -- self.tilemaps = render.predicate({'tilemap'}) in the init() function
render.draw(self.objects) -- same

-- rendering gui

In the tilemap material (you can copy the builtin one into the project and use it instead) you should add tag tilemap, same goes for the trees material:
java_2017-10-29_01-16-14
What happens there is that you assign tags to the materials, then in render-script create predicates with this tags (each predicate can contain multiple tags). After that, you call draw() for every predicate you want to draw, and the engine will draw every object that contains requested tags.
Think of it as a custom render-order right now, you just manually tell the engine, in which order you want it to draw everything. Although it is much more powerful thing, you can pass different parameters to the shader as second argument. You can draw object twice with different parameters (and even override shaders iirc), for example creating an outline for your object or something else.

Also note that with custom draw order your trees will be visible even if they are completely underground (in case you were planning to move them down to hide them for example :sweat_smile:)

5 Likes

#17

I did set the pivot to the bottom allready.

I understand what you write there and will try it tomorrow. (kinda late here…)

Thank you for that nice help.

1 Like

#18

I got it work. Nice!

4 Likes