Continious Room - Views Problem

G

GewoonNiels

Guest
Hello and ty for trying to help me already,

Making a certain (side scrolling) room in my 2d game, was according to me not very difficult.
It would be a room which simply continued at the beginning when you reached the end of a room (x = room_width).

game maker forum SPACE EVO plaatje 1.png

It should also work vise versa, when you go through the starting wall of the room (x = 0), the player should end up at the end of the room.

Well i haven't yet programmed the actual teleportation of the player, but the problem is to line up the views:

I made use of 2 views:
view[0] = the main view which doesn't change in width or position unless you get to one of the borders.
view[1] = the added view which is the added view from the other side of the room, you are not already in.

My game contains a space ship which can move, with players input, left and right. So when he arrives at the beginning of the room it should look something like this:

game maker forum SPACE EVO foto 2.png
I know this doesn't tell you much: but "RESI" is a sprite which i put on the end of the room.

unfortunately it doesn't look like this, i edited the above picture in paint.
At the moment it looks like this:
game maker forum SPACE EVO foto 1.png
Again: "FARM" is a sprite which shouldn't be in the view, because it isn't at the end of het room.

So basically, my view overlay system does not work:

Code:
total_wview = room_height*aspect_ratio;

if x-.5*total_wview < 0{
    //main wview
    view_wview[0] = x+.5*total_wview;
    view_xview[0] = 0;
   
    view_wport[0] = view_wview[0];
    view_xport[0] = .5*total_wview-x;
   
    //added wview
    view_wview[1] = .5*total_wview-x;
    view_xview[1] = room_width-(.5*total_wview-x);
   
    view_wport[1] = view_wview[1];
    view_xport[1] = 0;
   
    //all hview
    view_hview[0] = room_height;
   
    view_yport[0] = 0;
    view_hport[0] = view_hview[0];
   
    view_hview[1] = room_height;
    view_yview[1] = 0;
   
    view_hport[1] = view_hview[1];
    view_yport[1] = 0;
   
    //visibility
    view_visible[0] = 1;
    view_visible[1] = 1;
}
The total_wview is the total width of the views combined which is 1920, the player should Always be in the middle of the screen so at 960.

Additionally i made a debugging message every step, so i could excatly see where my views are and what their width is, if that information is needed or if something is unclear, feel free to ask.

Again thank you for helping me,
GewoonNiels
 

TheouAegis

Member
Code:
if !x x = room_width + x;
else
if x > room_width x = x - room_width;

view_xview = x - view_wview/2;
if !view_xview
{
  view_visible[1] = 1;
  view_wview[1] = -view_xview;
  view_xview[1] = room_width - view_wview[1];
  view_xport[1] = 0;
  view_wport[1] = view_wview[1];
}
else if view_xview + view_wview > room_width
{
  view_visible[1] = 1;
  view_wview[1] = view_xview + view_wview - room_width;
  view_xview[1] = 0;
  view_xport[1] = view_xport + view_wport - view_wview[1];
  view_wport[1] = view_wview[1];
}
else view_visible[1] = 0;

Basically, view 0 is always visible and doesn't change. You only show view 1 when you need to cover up the outside of the room. If you leave it up all the time, you're wasting the computer's time. View 1 is only as big as the part of the room you need to cover up. View 1 will cover up view 0, so some things may get drawn twice, but any slowdown as a result should be negligible; if it bugs you, you can try restricting the drawing in a conditional like "if view_visible[1] && median(x,view_xview[1],view_xview[1]+view_wview[1])==x && view_current!=0", but that may be just as slow. You must set the view position manually - you should not use the built-in view_object variable (set the following object to noone). If you want vertical wrapping in addition to horizontal wrapping, you need another view, since at that point up to 3 views will be on the screen at any one time.


Another issue you may have is in regards to interacting with objects on the opposite side of the room. Make sure your projectiles and enemies all have the same room wrapping code (the first 3 lines in my code), otherwise your projectiles will reach the end of the room and not be able to kill anything.

Do NOT use the built-in room wrapping function. It does not wrap properly and will cause stuttering movement.
 
Last edited:
I

icuurd12b42

Guest
it's simpler to have the one view and have the objects render themselves where they are and at the other end of the room if they would be visible there.

pcode
draw:
if(inview()) draw_self();
if(inview_right()) draw_self_right();
if(inview_left()) draw_self_left();

the wrapping mentioned above should work to wrap properly. the only thing left to mention is you need to control the view manually instated of using the view follow so that the view can extend beyond the room dimention
 

TheouAegis

Member
I did say to move the view manually, but I guess it's good to clarify that in your version too it needs to still be manual.

As for the rendering the objects on the opposite side of the room, if you added tiles, you'd need to duplicate those around the outside of the room so that the view has backgrounds to look at, too.

Anyway, working code for dual-rendering:
Code:
if x - obj_player.x
{
  x -= room_width;
  draw_self();
  x += room_width;
  draw_self();
}
else
{
  x += room_width;
  draw_self();
  x -= room_width;
  draw_self();
}
 
G

GewoonNiels

Guest
Thank you both for responding!
I guess i didn't know views could overlap...

It works now, but i altered the code of TheouAegis code a little bit.
I changed the width of the view so it has the according aspect ratio, and my own coding format (i am too orderly :rolleyes:)
Code:
view_wview[0] = aspect_ratio*room_height;
view_xview[0] = x - view_wview[0]/2;

if view_xview[0] < 0
{
    view_visible[1] = 1;
    view_wview[1] = -view_xview[0];
    view_xview[1] = room_width - view_wview[1];
    view_xport[1] = 0;
    view_wport[1] = view_wview[1];
}
else if view_xview[0] + view_wview[0] > room_width
{
    view_visible[1] = 1;
    view_wview[1] = view_xview[0] + view_wview[0] - room_width;
    view_xview[1] = 0;
    view_xport[1] = view_xport[0] + view_wport[0] - view_wview[1];
    view_wport[1] = view_wview[1];
}
else{
    view_wview[1] = 0;
    view_wport[0] = view_wview[0];
    view_visible[1] = 0;
}
For the rendering of the objects in the views, i not much code is needed, because for now i will only have the main object move in between the views. I did however need to draw the object twice, when it is exactly at the border of view[0], so not only half a sprite is visible.

I used the wrapping code too, but i had one more question o_O
what does !x mean, since it is not a boolean??? (i changed it here into:
Code:
if x < 0{

  x = room_width + x;

}

else if x > room_width{

  x = x - room_width;

}
Thank you, it really helped me out!
 
I

icuurd12b42

Guest
Yeah, that !x meant
not x
and it was not logically correct to use the term in this situaltion...
 

TheouAegis

Member
It'd only cause issues if GMS glitches again and goes back to treating <0 as TRUE, which Russ said was not supposed to happen. Although granted, in other languages, that's the case.
 
I

icuurd12b42

Guest
It'd only cause issues if GMS glitches again and goes back to treating <0 as TRUE, which Russ said was not supposed to happen. Although granted, in other languages, that's the case.
Is it not considered false if < 0.5?

But it's not the reason I used the term logically correct

think of it like politically correct :)

correct
if(speed == 0)
incorrect
if(!speed)

The reason is not for logic's sake but the reasoning behind the logic itself purely as a programmer perspective.

As demonstrated by the reaction of the OP to change it to x<0 for example.
 
G

GewoonNiels

Guest
Thanks once again,

I see now, i found on google that in other programming languages it is indeed an common expression, !x.

But in this case it just makes more sense for me to use the < sign
 
Top