Shake screen without black borders

Started by rongel, Mon 27/07/2020 11:24:38

Previous topic - Next topic

rongel

Hi! I have an issue that has been bugging me for ages, and finally decided to ask.

So I want to create a shaking screen effect. ShakeScreenBackground is just what I want, except it creates an ugly black border on top of the screen. I have some extra space at the top of my room (it's a very high scrolling room), so I want that part to be revealed, instead of the black, empty area.

I've undersood that it's a constraint of the engine, and that I should animate the viewport instead. I tried, but didn't have much luck.  I tested it with something like this:

Code: ags
Screen.Viewport.Y +=5;


It too created the black bar on top of the screen, eventhough my room should still continue there. 

So what would be the best way to achieve the shaking screen effect? I'm using the Smoothscroll module, but I tried disabling it and got still the same results. Would the new camera system help?
Dreams in the Witch House on Steam & GOG

Crimson Wizard

#1
Quote from: rongel on Mon 27/07/2020 11:24:38I have some extra space at the top of my room (it's a very high scrolling room), so I want that part to be revealed, instead of the black, empty area.

In that case you should move Camera (Game.Camera), not Viewport. Viewport defines where on screen the room is shown, Camera defines which part of the room is shown.

PS. Before 3.5.0 the "viewport" was actually "camera", so SetViewportX actually meant "set camera's x" in modern terms. When reading old threads or tutorials on this topic you have to replace "viewport" with "camera" :).

rongel

Thanks CW!

Yes, using Game.Camera seems to work. I had to disable the Smoothscroll first, using SmoothScroll_ScrollingOff();. But I think I can turn it on again after the effect.

Now I just have to figure out a good way to animate the camera to create the shaky effect. Any tips?  :-D
Dreams in the Witch House on Steam & GOG

rongel

Ok, I think I can manually animate the camerashake in room_RepExec(). It just needs testing to see what values work. So only thing that is missing compared to ShakeScreenBackground is that I have to make the effect blocking. That's because the camera manipulation won't work when smoothscroll is on.

But I think I can live with this!
Dreams in the Witch House on Steam & GOG

Crimson Wizard

#4
Quote from: rongel on Mon 27/07/2020 13:02:29
Ok, I think I can manually animate the camerashake in room_RepExec(). It just needs testing to see what values work. So only thing that is missing compared to ShakeScreenBackground is that I have to make the effect blocking. That's because the camera manipulation won't work when smoothscroll is on.

To make it blocking, don't put it in room_RepExec. Instead move camera in a loop and call Wait(1) to force game redraw:
Code: ags

void BlockingShakeScreen( int shake_power, int shake_time, .. other parameters ..)
{
     int counter;
     while (counter < shake_time)
     {
           // ... change camera coords here
           Wait(1);
           counter++;
     }
}



PS. fixed example, forgot to increment counter.

rongel

QuoteTo make it blocking, don't put it in room_RepExec. Instead move camera in a loop and call Wait(1) to force game redraw:

This seems to work nicely! I can make few different shake speeds / types and repeat them as long as I want. Much better than manually adding every single movement.

Thanks again!
Dreams in the Witch House on Steam & GOG

eri0o

You can read the positions from an array or calculate using something like a sin function

rongel

Quote from: eri0o on Mon 27/07/2020 14:01:35
You can read the positions from an array or calculate using something like a sin function

I'm afraid that might be too much for my coding skills...

I had some trouble deciding how to do the speed of the shakes. Something like this works fine for fast shakes, where I just change the camera's placement:

Code: ags
Game.Camera.Y += shake_power; 
Wait(1);
Game.Camera.Y -= shake_power; 
Wait(1);


But if I want to make a slower shake that has several inbetween frames,  the above method wont work. And I don't think we can animate the camera directly? I figured out an ugly way to do it, but it could use improvement.
Dreams in the Witch House on Steam & GOG

Crimson Wizard

Quote from: rongel on Mon 27/07/2020 14:54:02
But if I want to make a slower shake that has several inbetween frames,  the above method wont work. And I don't think we can animate the camera directly? I figured out an ugly way to do it, but it could use improvement.

What do you mean by "animating directly"?

You can move camera in smaller increments too, simply by breaking big move into steps. Example:
Code: ags

int normal_y = Game.Camera.Y;
int shake_y = normal_y - shake_power;
while (Game.Camera.Y > shake_y)
{
     Game.Camera.Y = Game.Camera.Y - 1;
     Wait(1);
}
while (Game.Camera.Y < normal_y)
{
     Game.Camera.Y = Game.Camera.Y + 1;
     Wait(1);
}

Increment amounts and Wait argument may be made dependent on some "speed" parameter.

Also, I believe latest Tween module has camera functions, letting you move camera smoothly in certain style.

rongel

QuoteWhat do you mean by "animating directly"?

I mean that there are no commands that would move the camera, like Game.Camera.Move(122, 150, eBlock);

QuoteYou can move camera in smaller increments too, simply by breaking big move into steps. Example:

Yes, I have something vaguely similar, but this seems much sophisticated!
Dreams in the Witch House on Steam & GOG

Crimson Wizard

#10
Quote from: rongel on Mon 27/07/2020 15:41:34
I mean that there are no commands that would move the camera, like Game.Camera.Move(122, 150, eBlock);

The above example practically does same thing, and you may write blocking function yourself as extender:
Code: ags

import void MoveBlocking(this Camera*, int x, int y, int pixels_per_tick);

Code: ags

void MoveBlocking(this Camera*, int x, int y, int pixels_per_tick)
{
    while (this.X != x || this.Y != y)
    {
        int distx = this.X - x;
        int disty = this.Y - y;
        if (distx < 0) distx = -distx;
        if (disty < 0) disty = -disty;
       
        if (distx <= pixels_per_tick) 
            this.X = x; // snap if too close
        else if (this.X < x)
            this.X += pixels_per_tick;
        else if (this.X > x)
            this.X -= pixels_per_tick;

        if (disty <= pixels_per_tick) 
            this.Y = y; // snap if too close
        else if (this.Y < y)
            this.Y += pixels_per_tick;
        else if (this.Y > y)
            this.Y -= pixels_per_tick;

        Wait(1);
    }
}



The above is a crude example, and it's mostly useful for straight movements. Also for non-blocking movement you would have to write a somewhat more complicated system that updates movement in rep-exec.

I believe that Tween module already has these though.

rongel

QuoteI believe that Tween module already has these though.

Yes, I'm using Tween module as well, and I'm very happy with it. This current room that I'm working on is a bit special. I'm using Smooth Scrolling & Parallax so that I have nice smooth camera movements, and the parallax effect as well. But yes, it looks like that I could disable the smooth scroll feature and use Tween module to control the camera directly (currently there is a dummy character as a camera). I think the parallax effect still works, eventhough smooth scroll is disabled.
Dreams in the Witch House on Steam & GOG

SMF spam blocked by CleanTalk