Sign in to follow this  
synth_cat

would you support a windowed-mode pro game?

Recommended Posts

I have a somewhat subjective question (more or less) to ask: Would you pay money to buy a game which could only ran in windowed mode, with no fullscreen exclusive option? Here's my situation: I am in my third year of development on my game, which I intend to publish/sell for profit. I am writing this in DirectX, by the way. If it were possible, I would like to leave out fullscreen-exclusive mode in my game because it would shorten development time. This is because fullscreen-mode (in Direct3d, at any rate) can at times be fraught with issues. Video-card specific issues, like the shifting around of D3D resources, problems with RenderSet calls, and such. These are issues that I quite frankly do not have the experience, tools, or hardware to handle. I am pressed for time, also. I am already about a year behind schedule with this game. I should let you know that the game does work fun in fullscreen mode on my own computer - it's just that I am almost sure that strange problems would come up if I were to try running the game in that mode on any other computer. I realize that leaving out fullscreen-exclusive mode would be an act of laziness on my part, but I have very limited time in which I can work on this project, and I'd like to simplify production as much as I can. Thanks in advance for any input! -synth_cat

Share this post


Link to post
Share on other sites
Unless your game is really small, the switch between windowed mode to fullscreen mode shouldn't be that big of a hassle. HOWEVER I am aware of the blunders of DirectX! Direct3D expects you to have a WS_POPUP window for fullscreen mode, and a (*usually*) WS_OVERLAPPED (or similar style) window for windowed mode.

Switching between window styles is not easy to do in Windows, and it screws a lot of things up. So do we need to create 2 windows for this? I'll leave it up to you to figure out (I'm trying to figure this out myself!). Look at the way DXUT does it.

In addition to these problems, there's a butload of resource management issues that we need to take care of when eg. the user Alt-Tabs or presses the Windows key. When the device is lost, practically all is lost. All device states and settings need to be reset, many resources need to be reloaded (or OnDeviceLost(..) or whaever).

Maybe we should all switch to OpenGL.

It all depends on the type of game. For a FPS, I would expect fullscreen mode.

Share this post


Link to post
Share on other sites
I would typically expect full-screen mode in most games, but it depends on the type of game. Is this a top-down RPG? Windowed mode is fine. An RTS? either or. A FPS or first-person RPG? Anything immersive I prefer to play fullscreen, in general.

To the above poster: it's actually not *that* hard. Look in to the SetWindowLong and SetWindowPos Win32 API calls. (Essentially you use SetWindowLong to modify the window's style parameters and then SetWindowPos to make sure that Windows actually recognizes the changes). Of course, you also have to make sure to reset the D3D device.

Share this post


Link to post
Share on other sites
I really think that it depends on the kind of game. For something like Bejewelled, it would be fine. If you are writing the next blockbuster FPS, it would probably be best to go with the option of windowed or fullscreen.

EDIT - If you want, I will be happy to post some C++ code that I have used in the past, that has worked for me. It handles pretty much any resolution, 0, 2, and 4x multisampling, vsynch (on or off), and a few other things.

EDIT2 - It loosk like penwan beat me to it.

Share this post


Link to post
Share on other sites
As an addendum, here's the code in my engine that I use to switch back and forth between windowed mode and fullscreen. If anybody sees anything glaringly wrong, be sure to let me know -- but it works for me. (note: GetRectFromParams is a convenience function I use that uses the AdjustWindowRectEx call to make sure the actual client size is the size expected) -- also the device reset is handled elsewhere when the code receives the message confirming the resize

const DWORD     WINDOWED_STYLE      = WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
const DWORD WINDOWED_EX_STYLE = WS_EX_APPWINDOW;
const DWORD FULLSCREEN_STYLE = WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
const DWORD FULLSCREEN_EX_STYLE = 0;

Result Window::ShowFullscreen(bool fullscreen)
{
ASSERT_WINDOW_HANDLE();

if(fullscreen && !IsFullscreen())
{
DisplayMode dm = Display()->CurrentMode();

mStyle = FULLSCREEN_STYLE;
mExStyle = FULLSCREEN_EX_STYLE;

SetWindowLong(mWnd, GWL_EXSTYLE, mExStyle);
SetWindowLong(mWnd, GWL_STYLE, mStyle);
SetWindowPos(mWnd, HWND_TOP, 0, 0, dm.width, dm.height,
SWP_SHOWWINDOW | SWP_FRAMECHANGED);

mFullscreen = true;
}
else if(!fullscreen && IsFullscreen())
{
mStyle = WINDOWED_STYLE;
mExStyle = WINDOWED_EX_STYLE;

SetWindowLong(mWnd, GWL_EXSTYLE, mExStyle);
SetWindowLong(mWnd, GWL_STYLE, mStyle);

// Make the window a sane size if necessary
RECT rc;
DisplayMode dm = Display()->CurrentMode();
if(mPrevXpos < 0 || mPrevYpos < 0 ||
mPrevWidth > static_cast<s32>(dm.width) ||
mPrevHeight > static_cast<s32>(dm.height))
{
rc.left = 0;
rc.right = dm.width >> 1;
rc.top = 0;
rc.bottom = dm.height >> 1;
}
else
{
GetRectFromParams(&rc, mPrevXpos, mPrevYpos, mPrevWidth, mPrevHeight);
}

mFullscreen = false;
SetWindowPos(mWnd, HWND_TOP, rc.left, rc.top, rc.right - rc.left,
rc.bottom - rc.top, SWP_SHOWWINDOW | SWP_FRAMECHANGED);
InvalidateRect(NULL, NULL, FALSE);
}
return SUCCESS;
}

Share this post


Link to post
Share on other sites
Quote:
Original post by ouraqt
Unless your game is really small, the switch between windowed mode to fullscreen mode shouldn't be that big of a hassle. HOWEVER I am aware of the blunders of DirectX! Direct3D expects you to have a WS_POPUP window for fullscreen mode, and a (*usually*) WS_OVERLAPPED (or similar style) window for windowed mode.


Direct3D doesn't expect anything. It works perfectly fine if you have a WS_OVERLAPPEDWINDOW style, but you'll still be able to interact with the title bar, which can cause problems.

Quote:
Original post by ouraqtSwitching between window styles is not easy to do in Windows, and it screws a lot of things up. So do we need to create 2 windows for this? I'll leave it up to you to figure out (I'm trying to figure this out myself!). Look at the way DXUT does it.


Switching back and forth between windows styles is pretty trivial. It does require a slight hack to get back to the WS_OVERLAPPEDWINDOW, but nothing major. I don't have the time at the moment, but I'll dig through my library for a snippet later.

Quote:
In addition to these problems, there's a butload of resource management issues that we need to take care of when eg. the user Alt-Tabs or presses the Windows key. When the device is lost, practically all is lost. All device states and settings need to be reset, many resources need to be reloaded (or OnDeviceLost(..) or whaever).


Use managed resources. Not a single resource that I create needs to be reset when I alt-tab out of my application. It may not be the most efficient or best way to do it, but it's easier and it's worked perfectly so far.

Quote:
Maybe we should all switch to OpenGL.

You make it sound like OpenGL solves everything and is free of all problems. While it does solve some of the aforementioned issues, it definitely has issues of its own.

@OP: I personally like to play all of my games in fullscreen mode because when I'm playing my game I'm not doing anything else. Plus, I don't want to accidentally click outside of the window or accidentally close the game (by clicking the close button in the title bar) if the in-game cursor doesn't line up with Windows cursor. That being said, I can't really say whether or not I would buy a game if it was just windowed. If I want it bad enough I would probably buy it.

Share this post


Link to post
Share on other sites
There is a certain mmorpg that can be run in windowed mode and in full screen. The full screen mode is nothing more than the window's client area resized to the screen size and positioned so that only the client area is visible. You can have your browser on top the game screen. The only difference is that it mutes the sound when sent to the background. You can switch tasks or access the start menu with normal shorcuts in both modes. This is good, especially that the ingame help system has links to the game's webpages that start your browser.

Share this post


Link to post
Share on other sites
Certainly if development is being done with it as a windowed application, then there is no big reason to take advantage of exclusive mode unless performance has become a concern.

I'd go with a maximized window with no border or title bar as the "full screen" option given to the user.. the end user doesnt care how its implimented.

Share this post


Link to post
Share on other sites
Thanks for all the replies!

For clarification, my game is a top-down shooter. Immersive-ness was always meant to be a plus in this game, so I suppose I really should try to use full-screen mode.

Thanks for the source code. Does it use an external library? I ask this because of the functions like InScreen(), which don't seem to exist by default in my IDE.

Quote:

Use managed resources. Not a single resource that I create needs to be reset when I alt-tab out of my application. It may not be the most efficient or best way to do it, but it's easier and it's worked perfectly so far.

That seemed like a good idea to me, and I tried it. However, when I did this, the creation of one of my vertex buffers failed (the second one.) This happens in either windowed or full-screen mode. Do you know why this may have happened?

Share this post


Link to post
Share on other sites
Off Topic:

Quote:
Original post by penwan
If anybody sees anything glaringly wrong, be sure to let me know

Nothing glaringly wrong, just a matter of taste: You can gain the slightest increase in speed, code size and readability with:

if (fullscreen == IsFullscreen()) return SUCCESS;
if (fullscreen) {
// Set Fullscreen
} else {
// Set Windowed
}



This in no way warranted a reply, but that toggle-if structure you are using has always bugged me [rolleyes].

Regards
Admiral

Share this post


Link to post
Share on other sites
Quote:
Original post by Rockoon1
Certainly if development is being done with it as a windowed application, then there is no big reason to take advantage of exclusive mode unless performance has become a concern.

I'd go with a maximized window with no border or title bar as the "full screen" option given to the user.. the end user doesnt care how its implimented.


The driver is likely to understand that qs q fullscreen mode and enter fullscreen mode automatically. It is how I implemented it in two previous engines and both ati and nvidia drivers treated this as a real fullscreen mode.

Ultimately, it means that you have to manage the disposable resources, as well as the device lost state - which is, I think, the biggest problem in a game. Fortunately, this problem can be solved with a clever design of your resource classes (resources that are likely to be reseted should be duplicated in memory. During the reset, loop over the resources to reset them - if the resource is managed oor in the system pool you don't have to do anything, but if the resource is in the default pool, you'll have to release it and recreate it once the you have reseted the device. The pseudo code I used was something along the line of:
if (device lost)
{
for each resource
{
if resource needs to be reseted
{
release resource
released_resource.push_back(resource);
}
}
if (reset device ok)
{
for each resource in released_resources
recreate resource
}
}

Since device reset happen only in a limited number of situations (alt-tab, hibernation, ...) you don't really care if it takes a few seconds to rebuild the whole thing.

Of course, it needs you to create some kind of abstraction around the driver and the resource. If you didn't do that, you'll have hard time to figure what resource should be released and recreated - and the whole thing becomes a PITA.

HTH,

Share this post


Link to post
Share on other sites
Quote:
To the above poster: it's actually not *that* hard. Look in to the SetWindowLong and SetWindowPos Win32 API calls. (Essentially you use SetWindowLong to modify the window's style parameters and then SetWindowPos to make sure that Windows actually recognizes the changes). Of course, you also have to make sure to reset the D3D device.
I know the API calls (thanks to MSDN) but I always get weird glitchy errors when changing the window style of a Direct3D window. (I've never actually tried to change the style of a NON-D3D win.) Has anyone done this successfully?
Quote:
You make it sound like OpenGL solves everything and is free of all problems. While it does solve some of the aforementioned issues, it definitely has issues of its own.
Of course it does. But I've heard that OpenGL handles more of the resource management than D3D does (I don't do OGL programming). I know, both of them are just 3D APIs.
Quote:
Direct3D doesn't expect anything. It works perfectly fine if you have a WS_OVERLAPPEDWINDOW style, but you'll still be able to interact with the title bar, which can cause problems.
True, but you should NEVER have a fullscreen app that uses a WS_OVERLAPPEDWINDOW style. Not only does the title bar create problems, but also the corners are rounded in WinXP (so you could accidentally click on the window behind your game window).
Quote:
Switching back and forth between windows styles is pretty trivial. It does require a slight hack to get back to the WS_OVERLAPPEDWINDOW, but nothing major. I don't have the time at the moment, but I'll dig through my library for a snippet later.
That is the problem I always encounted. I've never been able to switch back to a W_OVERLAPPEDWINDOW style. If I remember correctly, the window stops resoponding (I need to look over my code more, maybe I created some weird eternal loop with the window procedure or something).
Quote:
Use managed resources. Not a single resource that I create needs to be reset when I alt-tab out of my application. It may not be the most efficient or best way to do it, but it's easier and it's worked perfectly so far.
I use managed resources as well. But then you still need to reset all of the device states/settings, which can be annoying. Also, if you have any D3DX resources (ie. fonts or sprites) or cursor stuff then it needs to be done manually (I think).

Share this post


Link to post
Share on other sites
Quote:
Original post by ouraqt
Quote:
To the above poster: it's actually not *that* hard. Look in to the SetWindowLong and SetWindowPos Win32 API calls. (Essentially you use SetWindowLong to modify the window's style parameters and then SetWindowPos to make sure that Windows actually recognizes the changes). Of course, you also have to make sure to reset the D3D device.

I know the API calls (thanks to MSDN) but I always get weird glitchy errors when changing the window style of a Direct3D window. (I've never actually tried to change the style of a NON-D3D win.) Has anyone done this successfully?

Yes, I have and it works fine, although I don't use SetWindowPos().

Quote:
Original post by ouraqt
Quote:
You make it sound like OpenGL solves everything and is free of all problems. While it does solve some of the aforementioned issues, it definitely has issues of its own.

Of course it does. But I've heard that OpenGL handles more of the resource management than D3D does (I don't do OGL programming). I know, both of them are just 3D APIs.

It's good that you know that, but making statements like that is a really good way to start a flame war. It's especially bad to make a statement like that on hearsay[smile].

Quote:
Original post by ouraqt
Quote:
Direct3D doesn't expect anything. It works perfectly fine if you have a WS_OVERLAPPEDWINDOW style, but you'll still be able to interact with the title bar, which can cause problems.

True, but you should NEVER have a fullscreen app that uses a WS_OVERLAPPEDWINDOW style. Not only does the title bar create problems, but also the corners are rounded in WinXP (so you could accidentally click on the window behind your game window).

The corners aren't necessarily rounded, it depends on the theme. But despite that, when you create a full screen device I'm pretty sure the window is maximized (And maximized windows don't have rounded corners. But I'm not positive that it maximizes the window.) Anyway, you're right and you should never create a fullscreen device for a window with a titlebar.

Quote:
Original post by ouraqt
Quote:
Switching back and forth between windows styles is pretty trivial. It does require a slight hack to get back to the WS_OVERLAPPEDWINDOW, but nothing major. I don't have the time at the moment, but I'll dig through my library for a snippet later.

That is the problem I always encounted. I've never been able to switch back to a W_OVERLAPPEDWINDOW style. If I remember correctly, the window stops resoponding (I need to look over my code more, maybe I created some weird eternal loop with the window procedure or something).

This is the code I'm using at the moment. It works fine on all the computers that I've tested it on (6 if I remember correctly.)

if(!Fullscreen)
{
SetWindowLong(WndHandle, GWL_STYLE, WS_POPUP);
PresentParams.Windowed = false;

GuiManager.PreDeviceReset();
D3DSprite->OnLostDevice();
DeviceComPtr->Reset(&PresentParams);
GuiManager.PostDeviceReset();
D3DSprite->OnResetDevice();
}
else if(Fullscreen)
{
SetWindowLong(WndHandle, GWL_STYLE, WS_OVERLAPPEDWINDOW);
PresentParams.Windowed = true;

GuiManager.PreDeviceReset();
D3DSprite->OnLostDevice();
DeviceComPtr->Reset(&PresentParams);
GuiManager.PostDeviceReset();
D3DSprite->OnResetDevice();

int Width = PresentParams.BackBufferWidth, Height =PresentParams.BackBufferHeight;
int WindowX = 0, WindowY = 0;
int WindowWidth = Width, WindowHeight = Height;

RECT WndRect = {0, 0, Width, Height};
AdjustWindowRectEx(&WndRect, WS_OVERLAPPEDWINDOW, false, 0);
WindowWidth = WndRect.right - WndRect.left;
WindowHeight = WndRect.bottom - WndRect.top;

GetWindowRect(GetDesktopWindow(), &WndRect);
WindowX = (WndRect.right / 2) - (WindowWidth / 2);
WindowY = (WndRect.bottom / 2) - (WindowHeight / 2);

MoveWindow(WndHandle, WindowX, WindowY, WindowWidth, WindowHeight, FALSE);
ShowWindow(WndHandle, SW_HIDE);
ShowWindow(WndHandle, SW_SHOWNORMAL);
}



Quote:
Original post by ouraqt
Quote:
Use managed resources. Not a single resource that I create needs to be reset when I alt-tab out of my application. It may not be the most efficient or best way to do it, but it's easier and it's worked perfectly so far.

I use managed resources as well. But then you still need to reset all of the device states/settings, which can be annoying. Also, if you have any D3DX resources (ie. fonts or sprites) or cursor stuff then it needs to be done manually (I think).

True, I didn't actually think about that, but I usually don't use D3DX interfaces (ID3DXLine, ID3DXSprite, and ID3DXFont.) Still, if your resource management system is setup correctly, it shouldn't be a problem. I modified my system to support it by just supplying 2 functions.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
i want to say:
i would never play a game in window mode.
full-screen only is ok for me, as long as you can alt-tab and alt-f4.
i think theres no need to have a windowed game with resizing and whatever.

Share this post


Link to post
Share on other sites
Quote:
The corners aren't necessarily rounded, it depends on the theme. But despite that, when you create a full screen device I'm pretty sure the window is maximized (And maximized windows don't have rounded corners. But I'm not positive that it maximizes the window.) Anyway, you're right and you should never create a fullscreen device for a window with a titlebar.
I suppose it does depend on the theme (most people just use Luna), however you should never assume the user will have a particular theme anyway.

Also, I made a fullscreen FPS demo with a WS_OVERLAPPEDWINDOW window. The corners were still rounded. If you want a window maximized, you have to do it yourself (but you should be using WS_POPUP anyways).
Quote:
Yes, I have and it works fine, although I don't use SetWindowPos().
I think you should use SetWindowPos(...) so Windows will update the window cache.
Quote:
True, I didn't actually think about that, but I usually don't use D3DX interfaces (ID3DXLine, ID3DXSprite, and ID3DXFont.)
So what do you draw text with? I suppose you could make your own text-drawing engine, but that would take forever! You must be a real D3D guru. I don't really use ID3DXLine much, but what about ID3DXSprite? It makes drawing sprites (and particles!) much easier. You hand-code all of this yourself?
Quote:
This is the code I'm using at the moment. It works fine on all the computers that I've tested it on (6 if I remember correctly.)
I'll look at it and see if it works for me. I think the source of my glitches was a poorly programmed message loop. You always have to remember to avoid calling your WinProc from within your WinProc. Many Windows dunctions will inevitably call your window procedure without telling you first (which could easily make your app hang).

Share this post


Link to post
Share on other sites
Quote:
Original post by ouraqt
Quote:
The corners aren't necessarily rounded, it depends on the theme. But despite that, when you create a full screen device I'm pretty sure the window is maximized (And maximized windows don't have rounded corners. But I'm not positive that it maximizes the window.) Anyway, you're right and you should never create a fullscreen device for a window with a titlebar.

I suppose it does depend on the theme, however you should never assume the user will have a particular theme anyway.

Agreed[smile].

Quote:
Original post by ouraqt
Also, I made a fullscreen FPS demo with a WS_OVERLAPPEDWINDOW window. The corners were still rounded. If you want a window maximized, you have to do it yourself (but you should be using WS_POPUP anyways).

Thanks, that's good to know. Now I can stop telling people bad information lol.

Quote:
Original post by ouraqt
Quote:
Yes, I have and it works fine, although I don't use SetWindowPos().

I think you should use SetWindowPos(...) so Windows will update the window cache.

Thanks for the info. I actually was reading through the documents to see how SetWindowPos(). I'll be updating my library when I'm done posting[smile].

Quote:
Original post by ouraqt
Quote:
True, I didn't actually think about that, but I usually don't use D3DX interfaces (ID3DXLine, ID3DXSprite, and ID3DXFont.)

So what do you draw text with? I suppose you could make your own text-drawing engine, but that would take forever! You must be a real D3D guru. I don't really use ID3DXLine much, but what about ID3DXSprite? It makes drawing sprites (and particles!) much easier. You hand-code all of this yourself?

Font engines are pretty easy to do once you learn the algorithms, the only real problem I've had is batching things. I coded a system that is very similar to ID3DXSprite, but a custom system allows for much more flexibility.

Share this post


Link to post
Share on other sites
So is the best way to switch from fullscreen/windowed mode to change the window style? Or is it better (and more stable) to create 2 windows, with different styles, and only allow one to be visible at a time? Microsoft should explain this to us.

I think it might be unsafe to be drawing on a window other than your main window (you can only have one main window). Actually if I remember correctly, D3D takes in a window for input (so when the window looses focus the device is lost, etc.) and an optional, different window for drawing (just pass a different window handle to Present(...)). Hmm...

This is a common factor that nearly very game incorporates in one way or another, so why is it so perplexing to me?

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this