Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Resizing window.  (Read 7566 times)

0 Members and 1 Guest are viewing this topic.

Viruses

  • Jr. Member
  • **
  • Posts: 77
    • View Profile
Resizing window.
« on: January 20, 2012, 01:07:29 am »
So while i was developing, i noticed something when i changed the window size. So in my game i had the player that moved at a certain speed when you pressed a button. But whenever you resize the window, the player gets bigger and i believe the graphics gets worse too. But the problem is that the speed just decreases ALOT. And when I resize it to a much smaller size, the speed of things gets much faster. Also when i resize it small, the player collision messes up. So basically what i want to know is that how do you keep your game data consistent even if then change the size to very small or very large?

RedIrony

  • Newbie
  • *
  • Posts: 23
    • View Profile
Resizing window.
« Reply #1 on: January 20, 2012, 03:19:52 am »
I'm actually trying to figure this out myself at the moment.

It sounds like you're having two problems: The first is the way you're measuring time, and the second is how you're measuring space.

When you make the window really big, there are more pixels involved, and your video card has to do more work. This means that it takes a longer time to get things done. This means that if you put the player's movement in the main loop (no timer), then the speed can vary depending on how long it takes for the rest of the loop to execute.

One way to handle this would be to have a timer execute everything every so many milliseconds. This means that everything (ideally) happens at fixed intervals. Another way is to measure the time that has passed since the player's move function was called. Then you can use this to calculate how much to move the player in a given direction. If the time has been short, the player only moves a little. If it's been longer, the player moves farther. The net result is that the user moves at a constant speed.

As far as the collision issues go, I'm not completely sure, but I think that it is probably because you're measuring in pixels instead of some other unit. What I mean is that (X, Y) in your game world is relative to the upper-left corner of your screen, instead of some point in space. A better way to handle this is to establish your own unit of distance (lets say meters). If you measure everything in meters, you can preserve relative distances, even when the number of pixels in a meter changes. You can also have fractions of a meter, whereas pixels are discrete values.

I believe the answer in SFML is to use Views.

*whew* That was a lot of text. Sorry about that. Does it help at all? Perhaps you could post some more details of how you're implementing this.

Viruses

  • Jr. Member
  • **
  • Posts: 77
    • View Profile
Resizing window.
« Reply #2 on: January 20, 2012, 05:27:43 am »
Thanks for that response! I think the timer thing would work. So could i just make a timer and then every like 1 second(just as an example), the main loop in the main function would run? Or do i have to make timers for more stuff? Cause ive already got my code and it going to change alot if im going to be implementing this. Any suggestions?


EDIT: And what you said about the whole pixel thing and collision, well im doing collision with Window.GetWidth() . So then the player cant go past that.. And i didn't get the whole meter thing you said. Can you please elaborate on that? Thanks in advance!

RedIrony

  • Newbie
  • *
  • Posts: 23
    • View Profile
Resizing window.
« Reply #3 on: January 20, 2012, 05:57:31 am »
Well, I'm a bit of an amateur, but yeah, that should work. I'm tempted to use the System::Clock object instead, but having the game run in a continuous loop like that would peg the CPU, right?

What I mean by the meter thing is this: You can't control how many pixels a user has. How big their screen is is something that is just beyond your control. Because of this, you have to create your own system of measurement that you can convert to pixels during render time. Looking at the Window::View object, I think SFML might even be doing that for you. I'm not sure. I pretty much started it today.

Suppose you did measure by pixels, and your player sprite is 100px^2. Your view might be 800x600px. If the user makes the window smaller, they can change that number without scaling the player (in theory). What happens if the world is shrunk to 90px? The player size doesn't change, so now your collision goes berserk.

Another problem is that if you measure everything in pixels, you can't have fractions. What if your sprite is 33 pixels, and you need to shrink it down 50%, and then expand it by 200%. With floating point numbers you'd go from 33 to 16.5 to 33 again. With pixels (integers) you'd go from 33 -> 16 -> 32. You'd be slowly losing information due to rounding errors.

However, suppose the player is 1 "unit" wide and high, and the world view is 100x100 "units." Each unit, at render time, is equivalent to a certain number of pixels. If the view gets changed, then you can change that number of pixels. Everything is just as many "units" big as it was before, so even though it is drawn the smaller on the screen, everything is still proportionate.

I'm not sure if that makes any more sense...

Mario

  • SFML Team
  • Hero Member
  • *****
  • Posts: 879
    • View Profile
Resizing window.
« Reply #4 on: January 20, 2012, 01:02:45 pm »
Don't use the window size/resolution for anything game world related, unless you'd like to keep the pixel ratio 1:1 (i.e. 1 game pixel/unit relates to 1 real pixel on screen).

You'll usually want to have your own game coordinate system and then just use sf::View to translate your game world to screen coordinates.

E.g. you can create a sf::View with an origin at (160,120) and a width/height of (320,240). This will cause your game to always show this part of the game world, no matter how high/low the actual resolution is. Depending on what you're drawing (polygons vs. textures) this might cause blocky textures, but it will keep your screen (and the perceived velocity) the same.

If you don't want to do this (and keep a fixed 1 world pixel = 1 real pixel) ratio, then you might have to scale your velocities based on your game size (i.e. the window size).

Viruses

  • Jr. Member
  • **
  • Posts: 77
    • View Profile
Resizing window.
« Reply #5 on: January 20, 2012, 10:33:32 pm »
But I dont get the sf::View at all. In fact, this is probably the second time ive heard of it. I'm beginner to it so please explain and thanks!

RedIrony

  • Newbie
  • *
  • Posts: 23
    • View Profile
Resizing window.
« Reply #6 on: January 21, 2012, 05:25:11 am »
It's basically a camera. I'm trying to code up a demo, but I built SFML 2, and the tutorials are for 1.6.

RedIrony

  • Newbie
  • *
  • Posts: 23
    • View Profile
Resizing window.
« Reply #7 on: January 21, 2012, 07:53:31 am »
So here's what I came up with. Notice that we're not moving the sprite around, we're moving the view (camera) around. The other thing is that I think (hope) that this is the wrong way to move the view around, setting it every time, but it's the only way I could find.
Code: [Select]


#include <SFML/Graphics.hpp>

int main()
{
// Set up the window
sf::RenderWindow Window(sf::VideoMode(800, 600, 32), "SFML Sample Application");
   
// Load resources
sf::Image ourImage;
ourImage.Create(64, 64, sf::Color(85, 85, 85));

sf::Texture ourTexture;
ourTexture.Create(64, 64); // Give our texture a width (in pixels)
ourTexture.LoadFromImage(ourImage);

sf::Sprite ourSprite;
ourSprite.SetTexture(ourTexture);
ourSprite.SetPosition(0, 0);
ourSprite.SetScale(5, 5);

// Create our own view (none of that sissy default stuff)
sf::View ourView;
ourView.Reset(sf::FloatRect(100, 100, 400, 200));
ourView.SetViewport(sf::FloatRect(0.f, 0.f, 1.f, 1.f));
Window.SetView(ourView);

// Main loop
while (Window.IsOpen())
{
// Handle Events
sf::Event e;
while (Window.PollEvent(e))
{
// Lets handle the events
switch (e.Type)
{
case sf::Event::Closed:
Window.Close();
break;
case sf::Event::KeyPressed:
// Handle Keyboard input
if(e.Key.Code == sf::Keyboard::W)
ourView.Move(0.f, -10.f); // Move up
else if(e.Key.Code == sf::Keyboard::A)
ourView.Move(-10.f, 0.f); // Move left
else if(e.Key.Code == sf::Keyboard::S)
ourView.Move(0.f, 10.f);// Move down
else if(e.Key.Code == sf::Keyboard::D)
ourView.Move(10.f, 0.f);// Move right
break;
default:
break;
}
}

// Clear the old stuff
Window.Clear(sf::Color(0, 255, 255));

// Re-draw our sprite
Window.Draw(ourSprite);

// Display the window (swap buffers?)
Window.SetView(ourView);
Window.Display();
}
return 0;
}

Viruses

  • Jr. Member
  • **
  • Posts: 77
    • View Profile
Resizing window.
« Reply #8 on: February 05, 2012, 03:17:18 am »
But doesn't that just move the view around? How does that solve the problem?

RedIrony

  • Newbie
  • *
  • Posts: 23
    • View Profile
Resizing window.
« Reply #9 on: February 05, 2012, 10:00:27 pm »
Yes, but take a look at this part:
Code: [Select]

// Create our own view (none of that sissy default stuff)
sf::View ourView;
ourView.Reset(sf::FloatRect(100, 100, 400, 200));
ourView.SetViewport(sf::FloatRect(0.f, 0.f, 1.f, 1.f));
Window.SetView(ourView);


Notice that we're calling two functions on ourView before we give it over to the window: Reset() and SetViewport().

SetViewport() allows us to tell the view how much of the RenderTarget (in this case, think window or form) that we want the viewport to take up. The viewport, incidentally, is what you are resizing.

Reset() lets us determine how much of the game world we want to show. In this case, our upper-left corner is (100,100) and we're showing a 400x200 box, which is why the rectangle (which is actually a square) appears distorted. Notice that this isn't a 400x200 pixel box, it is a 400x200 unit/meter/whateveryouwanttocallit box.

The reason that this is important is that it means that you can start defining the sizes and locations of everything relative to the size of your view, not the viewport. Once you do that, when someone messes with the window, the viewport will get scaled, and everything inside will only appear to scale, much like a real camera.

 

anything