Flip Sprite Horizontally in DirectX9

Just starting out? Need help? Post your questions and find answers here.
FlameofChange
New User
New User
Posts: 7
Joined: Sun Jun 09, 2024 8:03 am

Flip Sprite Horizontally in DirectX9

Post by FlameofChange »

Hello there.
In my game I need to constantly flip horizontally the sprites on the fly. TransformSprite and here we go.
However, in DirectX the sprite disappears, I highly suspect DirectX culling making the back face of the sprite disappear when flipped.
How to force it in the first place ?
I'm still in OpenGL but OpenWindow with no borders makes a bug where the screen goes black when leaving and going back to it (that one would be for another topic).
Alex777
User
User
Posts: 49
Joined: Sun Nov 16, 2008 12:47 am
Location: Cayman Is.
Contact:

Re: Flip Sprite Horizontally in DirectX9

Post by Alex777 »

Fred
Administrator
Administrator
Posts: 18204
Joined: Fri May 17, 2002 4:39 pm
Location: France
Contact:

Re: Flip Sprite Horizontally in DirectX9

Post by Fred »

I will probably disable backface culling for DX9 and DX11 to match OpenGL and llow easy flipping.

@FlameOfChange, could you post a snippet of the OpenGL windowed screen bug ?
FlameofChange
New User
New User
Posts: 7
Joined: Sun Jun 09, 2024 8:03 am

Re: Flip Sprite Horizontally in DirectX9

Post by FlameofChange »

Hello there.
@Alex777 The problem with this snippet is the symbol used no longer exist, purebasic throws a "_PB_Screen_Direct3DDevice doesn't exist" (not surprising from a 2010 post). This was one of the first thing I checked...

@Fred Oooooooo YEEEEEESSS you will save a lot of hair pulling !!!! I would suggest a constant or something configurable so we can trivially change it instead of rewriting most of screen and display engine...
For the windowed bug we checked it with another online mate of mine and strangely it only occurs on my computer with OpenGL (Windows 11, RTX 3070). It works fine on direct X.
TO REPRODUCE IT (without debug enabled)
1) Compile & start
2) F1 (it will fullscreen)
3) Alt-tab away
4) Alt-tab in
TADAAAAH it will flicker between the latest image and black
5) F1 (it will leave fullscreen)
IT REWORKS ! Go back to 2) to repeat the bug

TO REPRODUCE IT (with debug enabled)
1) Compile & start
2) F1 (it will fullscreen)
3) minimize the debug screen
TADAAAAH it will either flicker between the latest image and black, or just display black
4) F1 (it will leave fullscreen)
IT REWORKS ! Go back to 2) to repeat the bug

The snippet is not made by me, but that mentioned online mate (I don't know if he's on this server, he's called Nemerod)

Code: Select all

InitSprite()

If ExamineDesktops()=0:End 3:EndIf

Global screenSizeX=DesktopWidth( 0)
Global screenSizeY=DesktopHeight(0)
OpenWindow(0,0,0,screenSizeX-100,screenSizeY-100,"dev",#PB_Window_SizeGadget|#PB_Window_MinimizeGadget|#PB_Window_MaximizeGadget|#PB_Window_ScreenCentered)

#H2H_SC_WIN_MODE=(#WS_BORDER|#WS_SIZEBOX|#WS_DLGFRAME|#WS_SYSMENU)

OpenWindowedScreen(WindowID(0),0,0,screenSizeX,screenSizeY,1,0,0,#PB_Screen_WaitSynchronization)
Repeat:eee=WindowEvent()
  Select eee
    Case $0:Delay(1)
      temp=ScreenOutput()
      If temp
        If StartDrawing(temp)
          Box(0,0,screenSizeX,screenSizeY,$ff000000)
          DrawText(40,40,FormatDate("%hhH%iiM%ss",Date()))
          DrawText(40,60,Str(ims)):ims+1
          StopDrawing()
        EndIf
        FlipBuffers()
      EndIf
    Case $206
      tx=WindowWidth(0)
      ty=WindowHeight(0)
      CloseScreen()
      OpenWindowedScreen(WindowID(0),0,0,tx,ty,1,0,0,#PB_Screen_WaitSynchronization)
    Case #PB_Event_SizeWindow,#PB_Event_MaximizeWindow,#PB_Event_RestoreWindow 
      tx=WindowWidth(0)
      ty=WindowHeight(0)
      If tx<=0:tx=1:EndIf
      If ty<=0:ty=1:EndIf
      CloseScreen()
      OpenWindowedScreen(WindowID(0),0,0,tx,ty,1,0,0,#PB_Screen_WaitSynchronization)
    Case #PB_Event_Gadget
      r0=EventGadget()
      temp=0
      For a = 0 To 31
        temp|GetGadgetState(a)<<a
      Next
      SetWindowTitle(1,"WS_x = $"+Hex(temp))
      SetWindowLong_(WindowID(0),#GWL_STYLE,temp)
      UpdateWindow_(WindowID(0))
      ResizeWindow(0,#PB_Ignore,#PB_Ignore ,WindowWidth(0),WindowHeight(0))
    Case $100,$104;button pressed
      temp=EventwParam()
      Select temp
        Case $26;UP     ;
        Case $28;DOWN   ;
        Case $27;GAUCHE ;
        Case $25;DROIT  ;
        Case $20;SPACE  ;
        Case $0D;ENTER  ;
        Case $09;TAB    ;
        Case $DE;²      ;
        Case $70;F1     ;
          fullscreen!1
          If fullscreen
            temp=GetWindowLong_(WindowID(0),#GWL_STYLE)&~#H2H_SC_WIN_MODE
            SetWindowLong_(WindowID(0),#GWL_STYLE,temp)
            ResizeWindow(0,0,0,DesktopWidth( 0),DesktopHeight(0))
          Else
            temp=GetWindowLong_(WindowID(0),#GWL_STYLE)|#H2H_SC_WIN_MODE
            SetWindowLong_(WindowID(0),#GWL_STYLE,temp)
            ResizeWindow(0,#PB_Ignore,#PB_Ignore,DesktopWidth( 0)-100,DesktopHeight(0)-100)
          EndIf
        Case $71;F2     ;
        Case $72;F3     ;
        Case $73;F4     ;
        Case $74;F5     ;
        Case $75;F6     ;
        Case $76;F7     ;
        Case $77;F8     ;
        Case $78;F9     ;
        Case $79;F10    ;
        Case $7a;F11    ;
        Case $7b;F12    ;
        Default:Debug temp
      EndSelect
  EndSelect
Until eee=#PB_Event_CloseWindow
Why talking about it ? Well, I just need a TRUE fullscreen WITHOUT using OpenScreen() (it can softlock users...) :cry:
Bellow is my oversimplified game. Run it with OpenGL too !
Depending on the delay duration and the disabling of WindowBounds I get very funny yet in the same ballpark as above...

Code: Select all

InitSprite()
ExamineDesktops()
Global screenSizeX=DesktopWidth(0)
Global screenSizeY=DesktopHeight(0)

Global windowSizeX=DesktopWidth(0)
Global windowSizeY=DesktopHeight(0)

#H2H_SC_WIN_MODE=(#WS_BORDER|#WS_SIZEBOX|#WS_DLGFRAME|#WS_SYSMENU)
Procedure changeScreen(x.i,y.i)
	Debug "change screen"
	screenSizeX=x
	screenSizeY=y
	Debug "Full screen resize "+windowSizeX+" "+windowSizeY+" | "+screenSizeX+" "+screenSizeY
	temp=GetWindowLong_(WindowID(0),#GWL_STYLE)&~(#H2H_SC_WIN_MODE)
	SetWindowLong_(WindowID(0),#GWL_STYLE,temp)
	ResizeWindow(0,0,0,WindowWidth(0),WindowHeight(0))
	WindowBounds(0,windowSizeX,windowSizeY,windowSizeX,windowSizeY) ; disable this line and the Windows 11 bottom toolbar will still go on top of the screen, but the red squares will appear
EndProcedure
OpenWindow(0,0,0,screenSizeX,screenSizeY,"WHYYYY",#PB_Window_SizeGadget|#PB_Window_MaximizeGadget)
OpenWindowedScreen(WindowID(0),0,0,screenSizeX,screenSizeY,#True,0,0)
changeScreen(screenSizeX,screenSizeY)

Repeat
	Event = WindowEvent()
	Select Event
		Case 0
			ClearScreen(#Black)
			StartDrawing(WindowOutput(0))
			Box(Random(100),Random(100),Random(100,10),Random(100,10),#Red)
			StopDrawing()
			FlipBuffers()
			Delay(10) ; Low values may work better, else it won't display anything or just for one second... 10 works somewhat, 5 works but 100 don't...
		Case #PB_Event_Gadget
			Debug EventGadget()
			If EventGadget()=0
				End
			EndIf
	EndSelect
Until Event=#PB_Event_CloseWindow
[Edit] I have done two videos to prove it. When recording with OBS it doesn't show the flickering, so I did with my camera.
First snippet : https://www.youtube.com/watch?v=2ofxG2iIRN0
Second snippet : https://www.youtube.com/watch?v=DqgZQHaKEhc
Post Reply