a boundary where the current coordinates of the mouse
pointer resides.
I have added three code examples to illustrate the
dare I say 'pro and cons' of these implementations.
Should also note there are also other routes as always...
Before setting up a 'hit box' we'll need to
get the mouse pointer coordinates this is where
the implementations differ.
a) fb basically GetMouse (see manual for more information)
- multi platform
- no additional libs required
- only works in focused window?
- only returns relative coordinates not absolute
a) winapi GetCursorPos
https://docs.microsoft.com/en-us/window ... tcursorpos
- not multi platform
- needs windows.bi
- works on whole desktop regardless of focused window
- only returns absolute coordinates not relative
however can be mitigated by ScreenToClient
https://docs.microsoft.com/en-us/window ... entoclient
- of course there are many more mouse related calls
c) sld2 SDL_MOUSEMOTION, SDL_MOUSEBUTTONDOWN etc
https://wiki.libsdl.org/CategoryMouse
- multi platform
- needs sdl2/sdl.bi
- only works in focused window
- can return absolute and relative coordinates (bit funky though)
- native support of SDL_PointInRect (surprise that's where I got it from..)
Ok so much for mouse pointers and buttons.
All three implementations utilize more or
less the same method of detecting whether or
not the mouse is in a specific area and of course
can be combined by the mouse button press.
Sdl's rect, possibly, could be overloaded with
say .visible .color etc the freebasic user-defined type
allows that flexibility quite elegantly.
FB implementation
Code: Select all
' based on code contained in fb manual for getmouse
' added example hitbox detection by thrive4 2022
' init screen
dim screenwidth As integer = 640
dim screenheight As integer = 480
' init hit box and cordinates
Type rect
x As integer
y As integer
w As integer
h As integer
End Type
Dim boxa As rect
dim boxb as rect
dim boxc as rect
boxa.x = 100
boxa.y = 100
boxa.w = 100
boxa.h = 100
boxb.x = 300
boxb.y = 100
boxb.w = 100
boxb.h = 100
' example proportional placing hit box
boxc.x = (screenwidth * 0.5) - ((screenwidth * 0.35f) * 0.5f)
boxc.y = screenheight - screenheight * 0.15f
boxc.w = screenwidth * 0.35f
boxc.h = screenheight * 0.15f
' mouse pointer used for pointinrect
dim mouse as rect
mouse.x = 0
mouse.y = 0
mouse.w = 0
mouse.h = 0
' lifted from line 104 https://github.com/libsdl-org/SDL/blob/2b3c16eb5b3af0829bf5b18966a31dd16dbecad2/include/SDL_rect.h
function hitbox(p as rect, r as rect) as boolean
if ((p.x >= r.x) and (p.x < (r.x + r.w)) and (p.y >= r.y) and (p.y < (r.y + r.h))) then
return true
else
return false
end if
end function
' init mouse feedback
Dim As Integer x, y, buttons, res
' Set video mode and enter loop
ScreenRes screenwidth, screenheight, 8
' draw hit boxes
Line (boxa.x, boxa.y) - (boxa.x + boxa.w, boxa.y + boxa.h), 15, b
Line (boxb.x, boxb.y) - (boxb.x + boxb.w, boxb.y + boxb.h), 15, b
Line (boxc.x, boxc.y) - (boxc.x + boxc.w, boxc.y + boxc.h), 15, b
' get mouse x, y and buttons. discard wheel position.
Do
res = GetMouse (x, y, , buttons)
Locate 1, 1
If res <> 0 Then '' Failure
#ifdef __FB_DOS__
Print "Mouse or mouse driver not available"
#else
Print "Mouse not available or not on window"
#endif
Else
Print Using "mouse position: ###:### buttons: "; x; y;
If buttons And 1 Then Print "l";
If buttons And 2 Then Print "r";
If buttons And 4 Then Print "m";
' method 1
'if x > boxa.x and x < boxa.x + boxa.w and y > boxa.y and y < boxa.y + boxa.h then print "boxa";
'if x > boxb.x and x < boxb.x + boxb.w and y > boxb.y and y < boxb.y + boxb.h then print "boxb";
'if x > boxc.x and x < boxc.x + boxc.w and y > boxc.y and y < boxc.y + boxc.h then print "boxc";
' method 2 emulate SDL_PointInRect
mouse.x = x
mouse.y = y
select case true
case hitbox(mouse, boxa)
print "boxa"
case hitbox(mouse, boxb)
print "boxb"
case hitbox(mouse, boxc)
print "boxc"
case else
end select
Print " "
End If
' use sleep to keep cpu usage low
sleep(60)
Loop While Inkey = ""
End
Code: Select all
' based on code contained in fb manual for getmouse
' modified for win api
' added example hitbox detection by thrive4 2022
' windows mouse
#Include "windows.bi"
Dim vpoint as Point
' needed to get handle with FindWindowA
' or use appname = mid(command(0), instrrev(command(0), "\") + 1)
dim title as string = "mouse_winapi_tut"
Windowtitle title
' init screen
dim screenwidth As integer = 640
dim screenheight As integer = 480
' init hit box and cordinates
Type rectA
x As integer
y As integer
w As integer
h As integer
End Type
Dim boxa As rectA
dim boxb as rectA
dim boxc as rectA
boxa.x = 100
boxa.y = 100
boxa.w = 100
boxa.h = 100
boxb.x = 300
boxb.y = 100
boxb.w = 100
boxb.h = 100
' example proportional placing hit box
boxc.x = (screenwidth * 0.5) - ((screenwidth * 0.35f) * 0.5f)
boxc.y = screenheight - screenheight * 0.15f
boxc.w = screenwidth * 0.35f
boxc.h = screenheight * 0.15f
' mouse pointer used for pointinrect
dim mouse as rectA
mouse.x = 0
mouse.y = 0
mouse.w = 0
mouse.h = 0
' lifted from line 104 https://github.com/libsdl-org/SDL/blob/2b3c16eb5b3af0829bf5b18966a31dd16dbecad2/include/SDL_rect.h
function hitbox(p as rectA, r as rectA) as boolean
if ((p.x >= r.x) and (p.x < (r.x + r.w)) and (p.y >= r.y) and (p.y < (r.y + r.h))) then
return true
else
return false
end if
end function
' Set video mode and enter loop
ScreenRes screenwidth, screenheight, 8
' draw hit boxes
Line (boxa.x, boxa.y) - (boxa.x + boxa.w, boxa.y + boxa.h), 15, b
Line (boxb.x, boxb.y) - (boxb.x + boxb.w, boxb.y + boxb.h), 15, b
Line (boxc.x, boxc.y) - (boxc.x + boxc.w, boxc.y + boxc.h), 15, b
' get mouse x, y and buttons. discard wheel position.
Do
GetCursorPos(@vpoint)
' used for relative mouse pointer position
ScreenToClient(FindWindowA(NULL, title), @vpoint)
Locate 1, 1
Print Using "mouse position: ###:### buttons: "; vpoint.x; vpoint.y;
If GetAsyncKeyState(VK_LBUTTON) < 0 Then Print "l";
If GetAsyncKeyState(VK_RBUTTON) < 0 Then Print "r";
If GetAsyncKeyState(VK_MBUTTON) < 0 Then Print "m";
' method 1
'if vpoint.x > boxa.x and vpoint.x < boxa.x + boxa.w and vpoint.y > boxa.y and vpoint.y < boxa.y + boxa.h then print "boxa";
'if vpoint.x > boxb.x and vpoint.x < boxb.x + boxb.w and vpoint.y > boxb.y and vpoint.y < boxb.y + boxb.h then print "boxb";
'if vpoint.x > boxc.x and vpoint.x < boxc.x + boxc.w and vpoint.y > boxc.y and vpoint.y < boxc.y + boxc.h then print "boxc";
' method 2 emulate SDL_PointInRect would be more practical to use vpoint directly but ok
mouse.x = vpoint.x
mouse.y = vpoint.y
select case true
case hitbox(mouse, boxa)
print "boxa"
case hitbox(mouse, boxb)
print "boxb"
case hitbox(mouse, boxc)
print "boxc"
case else
end select
Print " "
' use sleep to keep cpu usage low
sleep(60)
Loop While Inkey = ""
End
compile and run with sdl2.dll in same location as compiled exe
sdl2 dll can be found here:
https://www.libsdl.org/download-2.0.php
Code: Select all
' sdl 2 example hitbox detection with mouse by thrive4 2022
#include once "SDL2/SDL.bi"
' setup sdl
dim event as SDL_Event
dim running as boolean = True
dim mousebutton as string
dim screenwidth As integer = 640
dim screenheight As integer = 480
Dim As SDL_Color backgrondcolor = (75, 85, 95, 0)
Dim As SDL_Color boxcolor = (255, 255, 255, 0)
Dim As SDL_Texture Ptr texture
Dim As SDL_Window Ptr glass = SDL_CreateWindow("mouse_sdl2_tut", 100, 100, screenwidth, screenheight, SDL_WINDOW_RESIZABLE)
' used for method 2 hitbox detection
dim mousepos as SDL_Point
SDL_ShowCursor(SDL_ENABLE)
' init hit box and cordinates
dim boxa as SDL_Rect
boxa.x = 100
boxa.y = 100
boxa.w = 100
boxa.h = 100
dim boxb as SDL_Rect
boxb.x = 300
boxb.y = 100
boxb.w = 100
boxb.h = 100
' example proportional placing hit box
dim boxc as SDL_Rect
boxc.x = (screenwidth * 0.5) - ((screenwidth * 0.35f) * 0.5f)
boxc.y = screenheight - screenheight * 0.15f
boxc.w = screenwidth * 0.35f
boxc.h = screenheight * 0.15f
' renderer
Dim As SDL_Renderer Ptr renderer = SDL_CreateRenderer(glass, -1, SDL_RENDERER_ACCELERATED Or SDL_RENDERER_PRESENTVSYNC)
if (renderer = NULL) Then
print "sdl2 could not create render"
SDL_Quit()
End If
' get mouse x, y and buttons
while running
while SDL_PollEvent(@event) <> 0
' basic window interaction
select case event.type
case SDL_KEYDOWN and event.key.keysym.sym = SDLK_ESCAPE
running = False
exit while
case SDL_WINDOWEVENT and event.window.event = SDL_WINDOWEVENT_CLOSE
running = False
exit while
case SDL_MOUSEMOTION
mousebutton = ""
' method 1 note motion used to be mouse
'if (event.motion.x > boxa.x and event.motion.x < boxa.x + boxa.w and _
' event.motion.y > boxa.y and event.motion.y < boxa.y + boxa.h) then
' mousebutton = "mouse in zone boxa"
'end if
'if (event.motion.x > boxb.x and event.motion.x < boxb.x + boxb.w and _
' event.motion.y > boxb.y and event.motion.y < boxb.y + boxb.h) then
' mousebutton = "mouse in zone boxb"
'end if
' method 2 note booelan true needs to be 1 to evaluate
mousepos.x = event.motion.x
mousepos.y = event.motion.y
select case 1
case SDL_PointInRect(@mousepos, @boxa)
mousebutton = "mouse in zone boxa"
case SDL_PointInRect(@mousepos, @boxb)
mousebutton = "mouse in zone boxb"
case SDL_PointInRect(@mousepos, @boxc)
mousebutton = "mouse in zone boxc"
case else
' nop
end select
case SDL_MOUSEBUTTONDOWN
' button
select case event.button.button
case SDL_BUTTON_LEFT
mousebutton = "left"
case SDL_BUTTON_MIDDLE
mousebutton = "middle"
case SDL_BUTTON_RIGHT
mousebutton = "right"
case else
' nop
end select
end select
wend
' background
SDL_SetRenderDrawColor(renderer, backgrondcolor.r, backgrondcolor.g, backgrondcolor.b, backgrondcolor.a )
SDL_RenderClear(renderer)
' draw hit boxes
SDL_SetRenderDrawColor(renderer, boxcolor.r, boxcolor.g, boxcolor.b, boxcolor.a)
SDL_RenderDrawRect(renderer, @boxa)
SDL_RenderDrawRect(renderer, @boxb)
SDL_RenderDrawRect(renderer, @boxc)
SDL_RenderPresent(renderer)
SDL_SetWindowTitle(glass, "mouse_sdl2_tut | coord: " & event.motion.x & ":" & event.motion.y & " | button: " + mousebutton)
' use sdl_delay to keep cpu usage low
SDL_Delay(30)
wend
'clean up sdl
SDL_DestroyTexture(texture)
SDL_DestroyRenderer(renderer)
SDL_DestroyWindow(glass)
SDL_Quit()
End