Jump to content
Sven-Seyfert

[Solved] GDI+ problem with collision for a specific area

Recommended Posts

Sven-Seyfert

Hi Community,

I already created a collision detection system for a GDI+ Game that I will still work on for a while. But I want to replace my own approch (that is to complex and not dynamic) with the possibilities of _GDI_Plus_PathIsVisiblePoint(). I'm was looking around and found an example from @UEZ here that I edited for my needs.

Unfortunately there is no collision on a specific height (Y position) for the movement from left --> right or from right <-- left. Why?

The backgrounds of the pictures are only for visualization where the boundaries of the rectangles are. The collision refers to the red rectangle. The player shoudn't move into this area (movement stop).

Thanks for any suggestion - I'm grateful!
Sven

The animated GIF should hopefully explain my problem further:

Spoiler

CollisionAreaProblem.gif.1b79e7869220a1d65a8509401e301e6e.gif

[Solved] final solution:
Thanks to the Community.

Code:

Spoiler
; includes ---------------------------------------------------------------------
#include-once
#include <GDIPlus.au3>
#include <Misc.au3>



; declaration ------------------------------------------------------------------
Global Const $iGuiWidth             = 1000
Global Const $iGuiHeight            = 690
Global Const $iGuiLeft              = 10
Global Const $iGuiTop               = 10
Global Const $GUI_EVENT_CLOSE       = -3
Global $bExit                       = False

Global Const $iPlayerWidth          = 32
Global Const $iPlayerHeight         = 48
Global Const $iPlayerStep           = 4
Global $iXPosPlayer                 = 16
Global $iYPosPlayer                 = 16

Global Const $iTreeWidth            = 128
Global Const $iTreeHeight           = 160
Global Const $iXPosTree             = 100
Global Const $iYPosTree             = 100

Global Const $iWidthCollisionBlock  = 40
Global Const $iHeightCollisionBlock = 20
Global Const $iXCollisionBlock      = 145
Global Const $iYCollisionBlock      = 220

Global Const $sPlayerImg            = 'player01_01.png'
Global Const $sTreeImg              = 'tree01_01.png'



; gui --------------------------------------------------------------------------
Global $hMainGui = GUICreate( '', $iGuiWidth, $iGuiHeight, $iGuiLeft, $iGuiTop )
GUISetState( @SW_SHOW, $hMainGui )



; init -------------------------------------------------------------------------
Opt( 'GUIOnEventMode', 1 )
GUISetOnEvent( $GUI_EVENT_CLOSE, '_exitToggle' )
OnAutoItExitRegister( '_exit' )

_GDIPlus_Startup()

Global $hGraphics  = _GDIPlus_GraphicsCreateFromHWND( $hMainGui )
Global $hBitmap    = _GDIPlus_BitmapCreateFromGraphics( $iGuiWidth, $iGuiHeight, $hGraphics )
Global $hBuffer    = _GDIPlus_ImageGetGraphicsContext( $hBitmap )
Global $vRed       = _GDIPlus_BrushCreateSolid( 0xFFFF0000 )
Global $hPlayerImg = _GDIPlus_ImageLoadFromFile( $sPlayerImg )
Global $hTreeImg   = _GDIPlus_ImageLoadFromFile( $sTreeImg )



; functions --------------------------------------------------------------------
Func _isCollisionRect( $iX, $iY, $iWidth, $iHeight, $iXBlock, $iYBlock, $iWidthBlock, $iHeightBlock )
    Return ( $iX + $iWidth > $iXBlock And $iY + $iHeight > $iYBlock And $iX < $iXBlock + $iWidthBlock And $iY < $iYBlock + $iHeightBlock )
EndFunc

Func _isCollisionPoint( $iX, $iY, $iXBlock, $iYBlock, $iWidthBlock, $iHeightBlock ) ; currently unused
    Return ( $iX > $iXBlock And $iY > $iYBlock And $iX < $iXBlock + $iWidthBlock And $iY < $iYBlock + $iHeightBlock )
EndFunc

Func _exitToggle()
    $bExit = True
EndFunc

Func _exit()
    _GDIPlus_BrushDispose( $vRed )
    _GDIPlus_GraphicsDispose( $hBuffer )
    _GDIPlus_BitmapDispose( $hBitmap )
    _GDIPlus_GraphicsDispose( $hGraphics )
    _GDIPlus_Shutdown()

    GUIDelete( $hMainGui )
EndFunc



; processing -------------------------------------------------------------------
While Not $bExit And Sleep( 25 )
    _GDIPlus_GraphicsClear( $hBuffer )

    _GDIPlus_GraphicsDrawImageRect( $hBuffer, $hPlayerImg, $iXPosPlayer, $iYPosPlayer, $iPlayerWidth, $iPlayerHeight ) ; draw player
    _GDIPlus_GraphicsDrawImageRect( $hBuffer, $hTreeImg, $iXPosTree, $iYPosTree, $iTreeWidth, $iTreeHeight ) ; draw tree
    If $iYPosPlayer >= $iYCollisionBlock Then _GDIPlus_GraphicsDrawImageRect( $hBuffer, $hPlayerImg, $iXPosPlayer, $iYPosPlayer, $iPlayerWidth, $iPlayerHeight ) ; draw player in the forground
    _GDIPlus_GraphicsFillRect( $hBuffer, $iXCollisionBlock, $iYCollisionBlock, $iWidthCollisionBlock, $iHeightCollisionBlock, $vRed ) ; just for visualization purpose

    If _IsPressed( '25' ) Then ; left
        If Not _isCollisionRect( $iXPosPlayer - $iPlayerStep, $iYPosPlayer, $iPlayerWidth, $iPlayerHeight, $iXCollisionBlock, $iYCollisionBlock, $iWidthCollisionBlock, $iHeightCollisionBlock ) Then
            $iXPosPlayer -= $iPlayerStep
        EndIf
    EndIf

    If _IsPressed( '27' ) Then ; right
        If Not _isCollisionRect( $iXPosPlayer + $iPlayerStep, $iYPosPlayer, $iPlayerWidth, $iPlayerHeight, $iXCollisionBlock, $iYCollisionBlock, $iWidthCollisionBlock, $iHeightCollisionBlock ) Then
            $iXPosPlayer += $iPlayerStep
        EndIf
    EndIf

    If _IsPressed( '26' ) Then ; up
        If Not _isCollisionRect( $iXPosPlayer, $iYPosPlayer - $iPlayerStep, $iPlayerWidth, $iPlayerHeight, $iXCollisionBlock, $iYCollisionBlock, $iWidthCollisionBlock, $iHeightCollisionBlock ) Then
            $iYPosPlayer -= $iPlayerStep
        EndIf
    EndIf

    If _IsPressed( '28' ) Then ; down
        If Not _isCollisionRect( $iXPosPlayer, $iYPosPlayer + $iPlayerStep, $iPlayerWidth, $iPlayerHeight, $iXCollisionBlock, $iYCollisionBlock, $iWidthCollisionBlock, $iHeightCollisionBlock ) Then
            $iYPosPlayer += $iPlayerStep
        EndIf
    EndIf

    _GDIPlus_GraphicsDrawImageRect( $hGraphics, $hBitmap, 0, 0, $iGuiWidth, $iGuiHeight )
WEnd

 

 

player01_01.png

tree01_01.png

Edited by Sven-Seyfert

// Innovation creates curiosity - curiosity innovation //

Share this post


Link to post
Share on other sites
UEZ

You have to add two additional check points otherwise the corner of the player sprite will stay outside  the red path object.

 

; includes ---------------------------------------------------------------------
#include-once
#include <GDIPlus.au3>
#include <Misc.au3>



; declaration ------------------------------------------------------------------
Local Const $iGuiWidth            = 1000
Local Const $iGuiHeight           = 690
Local Const $iGuiLeft             = 10
Local Const $iGuiTop              = 10
Local Const $GUI_EVENT_CLOSE      = -3

Local Const $iPlayerHeight        = 48
Local Const $iPlayerWidth         = 32
Local Const $iPlayerStep          = 4
Local $iXPosPlayer                = 16
Local $iYPosPlayer                = 16

Local Const $iXPosBlueRectangle   = 100
Local Const $iYPosBlueRectangle   = 100
Local Const $iBlueRectangleWidth  = 128
Local Const $iBlueRectangleHeight = 160

Local Const $iXPosTree            = 100
Local Const $iYPosTree            = 100
Local Const $iTreeWidth           = 128
Local Const $iTreeHeight          = 160

Local Const $sPlayerImg           = 'player01_01.png'
Local Const $sTreeImg             = 'tree01_01.png'



; gui --------------------------------------------------------------------------
Local $hMainGui = GUICreate( '', $iGuiWidth, $iGuiHeight, $iGuiLeft, $iGuiTop )
GUISetState( @SW_SHOW, $hMainGui )



; init -------------------------------------------------------------------------
Opt( 'GUIOnEventMode', 1 )
GUISetOnEvent( $GUI_EVENT_CLOSE, '_exit' )
_GDIPlus_Startup()

Local $hGraphics    = _GDIPlus_GraphicsCreateFromHWND( $hMainGui )
Local $hBitmap      = _GDIPlus_BitmapCreateFromGraphics( $iGuiWidth, $iGuiHeight, $hGraphics )
Local $hBuffer      = _GDIPlus_ImageGetGraphicsContext( $hBitmap )

Local $vWhite       = _GDIPlus_BrushCreateSolid( 0xFFFFFFFF )
Local $vBlue        = _GDIPlus_BrushCreateSolid( 0xFFABCDEF )
Local $vRed         = _GDIPlus_BrushCreateSolid( 0xFFFF0000 )

Local $hGraphicPath = _GDIPlus_PathCreate()
_GDIPlus_PathAddRectangle( $hGraphicPath, 130, 215, 70, 35 ) ; set red collision area

Local $hImagePlayer = _GDIPlus_ImageLoadFromFile( $sPlayerImg )
Local $hImageThree = _GDIPlus_ImageLoadFromFile( $sTreeImg )


; functions --------------------------------------------------------------------
Func _exit()
    _GDIPlus_PathDispose( $hGraphicPath )
    _GDIPlus_BrushDispose( $vRed )
    _GDIPlus_BrushDispose( $vBlue )
    _GDIPlus_BrushDispose( $vWhite )
    _GDIPlus_GraphicsDispose( $hBuffer )
    _GDIPlus_BitmapDispose( $hBitmap )
    _GDIPlus_BitmapDispose( $hImagePlayer )
    _GDIPlus_BitmapDispose( $hImageThree )
    _GDIPlus_GraphicsDispose( $hGraphics )
    _GDIPlus_Shutdown()

    GUIDelete( $hMainGui )
    Exit
EndFunc



; processing -------------------------------------------------------------------
While 1
    _GDIPlus_GraphicsClear( $hBuffer )

    _GDIPlus_GraphicsFillRect( $hBuffer, $iXPosPlayer, $iYPosPlayer, $iPlayerWidth, $iPlayerHeight, $vWhite ) ; draw player background
    _GDIPlus_GraphicsFillRect( $hBuffer, $iXPosBlueRectangle, $iYPosBlueRectangle, $iBlueRectangleWidth, $iBlueRectangleHeight, $vBlue ) ; draw tree background

    _GDIPlus_GraphicsDrawImageRect( $hBuffer, $hImagePlayer, $iXPosPlayer, $iYPosPlayer, $iPlayerWidth, $iPlayerHeight ) ; draw player
    _GDIPlus_GraphicsDrawImageRect( $hBuffer, $hImageThree, $iXPosTree, $iYPosTree, $iTreeWidth, $iTreeHeight ) ; draw tree

    _GDIPlus_GraphicsFillPath( $hBuffer, $hGraphicPath, $vRed ) ; draw red collision area

    If _IsPressed( '25' ) Then ; left
        If Not Check_for_Collision($iXPosPlayer - $iPlayerStep, $iYPosPlayer, $iXPosPlayer - $iPlayerStep + $iPlayerWidth, $iYPosPlayer, _
                                   $iXPosPlayer - $iPlayerStep, $iYPosPlayer + $iPlayerHeight, $iXPosPlayer - $iPlayerStep + $iPlayerWidth, $iYPosPlayer + $iPlayerHeight, $hGraphicPath) Then
            $iXPosPlayer -= $iPlayerStep
            _GDIPlus_GraphicsFillRect( $hBuffer, $iXPosPlayer, $iYPosPlayer, $iPlayerWidth, $iPlayerHeight, $vWhite )
        EndIf
    EndIf

    If _IsPressed( '27' ) Then ; right
        If Not Check_for_Collision($iXPosPlayer + $iPlayerStep, $iYPosPlayer, $iXPosPlayer + $iPlayerStep + $iPlayerWidth, $iYPosPlayer, _
                                   $iXPosPlayer + $iPlayerStep, $iYPosPlayer + $iPlayerHeight, $iXPosPlayer + $iPlayerStep + $iPlayerWidth, $iYPosPlayer + $iPlayerHeight, $hGraphicPath) Then
            $iXPosPlayer += $iPlayerStep
            _GDIPlus_GraphicsFillRect( $hBuffer, $iXPosPlayer, $iYPosPlayer, $iPlayerWidth, $iPlayerHeight, $vWhite )
        EndIf
    EndIf

    If _IsPressed( '26' ) Then ; up
        If Not Check_for_Collision($iXPosPlayer, $iYPosPlayer - $iPlayerStep, $iXPosPlayer + $iPlayerWidth, $iYPosPlayer - $iPlayerStep, _
                                   $iXPosPlayer, $iYPosPlayer - $iPlayerStep + $iPlayerHeight, $iXPosPlayer + $iPlayerWidth, $iYPosPlayer - $iPlayerStep + $iPlayerHeight, $hGraphicPath) Then
            $iYPosPlayer -= $iPlayerStep
            _GDIPlus_GraphicsFillRect( $hBuffer, $iXPosPlayer, $iYPosPlayer, $iPlayerWidth, $iPlayerHeight, $vWhite )
        EndIf
    EndIf

    If _IsPressed( '28' ) Then ; down
        If Not Check_for_Collision($iXPosPlayer, $iYPosPlayer + $iPlayerStep, $iXPosPlayer + $iPlayerWidth, $iYPosPlayer + $iPlayerStep, _
                                   $iXPosPlayer, $iYPosPlayer + $iPlayerStep + $iPlayerHeight, $iXPosPlayer + $iPlayerWidth, $iYPosPlayer + $iPlayerStep + $iPlayerHeight, $hGraphicPath) Then
            $iYPosPlayer += $iPlayerStep
            _GDIPlus_GraphicsFillRect( $hBuffer, $iXPosPlayer, $iYPosPlayer, $iPlayerWidth, $iPlayerHeight, $vWhite )
        EndIf
    EndIf

    _GDIPlus_GraphicsDrawImageRect( $hGraphics, $hBitmap, 0, 0, $iGuiWidth, $iGuiHeight )

    Sleep( 10 )
WEnd

Func Check_for_Collision($x1, $y1, $x2, $y2, $x3, $y3, $x4, $y4, $hPath)
    Return BitOR(_GDIPlus_PathIsVisiblePoint($hPath, $x1, $y1), _GDIPlus_PathIsVisiblePoint($hPath, $x2, $y2), _
                 _GDIPlus_PathIsVisiblePoint($hPath, $x3, $y3), _GDIPlus_PathIsVisiblePoint($hPath, $x4, $y4), _
                 _GDIPlus_PathIsVisiblePoint($hPath, $x1, ($y1 + $y3) / 2), _GDIPlus_PathIsVisiblePoint($hPath, $x2, ($y2 + $y4) / 2))
EndFunc

 

Further _GDIPlus_ImageLoadFromFile in an endless loop causes a memory leak!


Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Share this post


Link to post
Share on other sites
Sven-Seyfert

Hi @UEZ,

thanks a lot for the way to do it right with _GDIPlus_PathIsVisiblePoint(). I edit my post #1 with the final code solution by a other suggestion from Mars (german forum) because it's more easy and shorter.

I will not produce any memory leaks in the future ;) .

Thanks for your help - I'm grateful!
Sven


// Innovation creates curiosity - curiosity innovation //

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

×