From time to time a user has a need to position the mouse cursor over a sprite, hold the left button down and drag the sprite to a new position. Releasing the left button causes the sprite to stay in that new position. This demo shows one way to accomplish that. Run this demo from your Just BASIC Root Directory so the cave1.bmp and cave2.bmp sprites can be found. Of course, you can always substitute these 2 sprites with your own custom sprites.
A 1x1 invisible pixel is used to determine sprite collision for finding whether the mouse cursor was over a sprite when the left button was pressed down.
The code is well documented for explanations.
Demo 1 - Uses Branch Labels for Mouse Action Events
' Prevent the mainwindow from opening
Nomainwin
' Open a Graphicbox in a Window
WindowWidth = 407
WindowHeight = 454
UpperLeftX = Int((DisplayWidth - WindowWidth)/2)
UpperLeftY = Int((DisplayHeight - WindowHeight)/2)
Menu #main, "&File", "E&xit", [EndDemo]
Graphicbox #main.g, 0, 0, 400, 400
Open "Drag and Drop Sprites" for Window as #main
#main, "Trapclose [EndDemo]"
' Load the Sprites
Loadbmp "cave1", "SPRITES\cave1.bmp"
Loadbmp "cave2", "SPRITES\cave2.bmp"
' Draw a 1 x 1 Invisible Pixel Sprite
#main.g, "Down"
#main.g, "Color Black; Set 0 1"
#main.g, "Getbmp pixel 0 0 0 1"
' Add the Loaded BMP's as Sprites
#main.g, "Addsprite cave1 cave1"
#main.g, "Addsprite cave2 cave2"
#main.g, "Addsprite pixel pixel"
' Draw a Grid
#main.g, "Fill Brown"
For y = 0 to 400 Step 80
#main.g, "Line 0 ";y;" 400 ";y
Next y
For x = 0 to 400 Step 40
#main.g, "Line ";x;" 0 ";x;" 400"
Next x
#main.g, "Flush"
' Set the Grid as Background
#main.g, "Getbmp grid 0 0 400 400"
#main.g, "Background grid"
' Assign the Sprites to x, y Location
#main.g, "Spritexy cave1 320 320"
#main.g, "Spritexy cave2 360 320"
' Make the pixel Sprite Follow with the Cursor
#main.g, "When mouseMove [pixelFollow]"
' Look for a Collision between pixel and cave1 or cave2
' when the Left Button is Depressed
#main.g, "When leftButtonDown [checkCollision]"
' Show the Sprites in Current x, y positions
#main.g, "Drawsprites"
' Wait for Mouse Action
Wait
[pixelFollow]
' MouseX and MouseY special values that automatically
' retrieve and store mouse x, y positions
#main.g, "Spritexy pixel ";MouseX;" ";MouseY
#main.g, "Drawsprites"
Wait
[checkCollision]
#main.g, "Spritecollides pixel list$"
drag = Val(Right$(list$, 1))
' If the pixel has collided with one of the cave sprites then
' get the cave sprite number in value drag
If drag Then
' Stop checking for a collision
#main.g, "When mouseMove"
' Keep the cave sprite moving with the mouse cursor
#main.g, "When leftButtonMove [dragSprite]"
' When the left mouse button is released (up) then place the sprite
#main.g, "When leftButtonUp [placeSprite]"
End If
Wait
[dragSprite]
' The mouse cursor positions are captured in xVar and yVar
xVar = MouseX
yVar = MouseY
' The variable drag tells which cave sprite is being 'dragged'
cave$ = "cave";drag
' Assign these same x and y values to the cave sprite
' xVar - 20 and yVar - 40 positions the cave sprite so the mouse
' cursor appears to be centered over the cave sprite
#main.g, "Spritexy ";cave$;" ";xVar - 20;" ";yVar - 30
' Show the sprites in the recalculated x, y positions
#main.g, "Drawsprites"
Wait
[placeSprite]
' The left mouse button has now been released at MouseX, MouseY
' These mouse cursor positions are captured in xVar and yVar
xVar = MouseX
yVar = MouseY
' Use the global variable drag to determine which cave sprite
cave$ = "cave";drag
' Since each cell of the grid is 40 x 80, find the nearest increments
' This gives a 'Snap To Grid' effect
x = Int((xVar + 0.5)/40) * 40
y = Int((yVar + 0.5)/80) * 80
' Move the cave sprite to the calculated cell
#main.g, "Spritexy ";cave$;" ";x;" ";y
'Disable further dragging
#main.g, "When leftButtonMove"
' Disable further placing
#main.g, "When leftButtonUp"
' Cause the 1x1 pixel to follow the cursor again
#main.g, "When mouseMove [pixelFollow]"
' Check again for a collision when the left mouse button is down
#main.g, "When leftButtonDown [checkCollision]"
' Show the sprites in their recalculated x, y positions
#main.g, "Drawsprites"
Wait
[EndDemo]
Unloadbmp "cave1"
Unloadbmp "cave2"
Unloadbmp "pixel"
Close #main
End
Demo 2 - The same program, but using Subs for mouse event handlers rather than branch labels
' Prevent the mainwindow from opening
Nomainwin
' Declare drag as a Global Variable
' This is required so that drag can be seen within all subs
Global drag
' Open a Graphicbox in a Window
WindowWidth = 407
WindowHeight = 454
UpperLeftX = Int((DisplayWidth - WindowWidth)/2)
UpperLeftY = Int((DisplayHeight - WindowHeight)/2)
Menu #main, "&File", "E&xit", EndDemoMenu
Graphicbox #main.g, 0, 0, 400, 400
Open "Drag and Drop Sprites" for Window as #main
#main, "Trapclose EndDemo"
' Load the Sprites
Loadbmp "cave1", "SPRITES\cave1.bmp"
Loadbmp "cave2", "SPRITES\cave2.bmp"
' Draw a 1 x 1 Invisible Pixel Sprite
#main.g, "Down"
#main.g, "Color Black; Set 0 1"
#main.g, "Getbmp pixel 0 0 0 1"
' Add the Loaded BMP's as Sprites
#main.g, "Addsprite cave1 cave1"
#main.g, "Addsprite cave2 cave2"
#main.g, "Addsprite pixel pixel"
' Draw a Grid
#main.g, "Fill Brown"
For y = 0 to 400 Step 80
#main.g, "Line 0 ";y;" 400 ";y
Next y
For x = 0 to 400 Step 40
#main.g, "Line ";x;" 0 ";x;" 400"
Next x
#main.g, "Flush"
' Set the Grid as Background
#main.g, "Getbmp grid 0 0 400 400"
#main.g, "Background grid"
' Assign the Sprites to x, y Location
#main.g, "Spritexy cave1 320 320"
#main.g, "Spritexy cave2 360 320"
' Make the pixel Sprite Follow with the Cursor
#main.g, "When mouseMove pixelFollow"
' Look for a Collision between pixel and cave1 or cave2
' when the Left Button is Depressed
#main.g, "When leftButtonDown checkCollision"
' Show the Sprites in Current x, y positions
#main.g, "Drawsprites"
' Wait for Mouse Action
Wait
Sub pixelFollow handle$, xVar, yVar
#main.g, "Spritexy pixel ";xVar;" ";yVar
#main.g, "Drawsprites"
End Sub
Sub checkCollision handle$, xVar, yVar
#main.g, "Spritecollides pixel list$"
drag = Val(Right$(list$, 1))
' If the pixel has collided with one of the cave sprites then
' get the cave sprite number in value drag
If drag Then
' Stop checking for a collision
#main.g, "When mouseMove"
' Keep the cave sprite moving with the mouse cursor
#main.g, "When leftButtonMove dragSprite"
' When the left mouse button is released (up) then place the sprite
#main.g, "When leftButtonUp placeSprite"
End If
End Sub
Sub dragSprite handle$, xVar, yVar
' The mouse cursor positions are captured in xVar and yVar
' The variable drag tells which cave sprite is being 'dragged'
cave$ = "cave";drag
' Assign these same x and y values to the cave sprite
' xVar - 20 and yVar - 40 positions the cave sprite so the mouse
' cursor appears to be centered over the cave sprite
#main.g, "Spritexy ";cave$;" ";xVar - 20;" ";yVar - 30
' Show the sprites in the recalculated x, y positions
#main.g, "Drawsprites"
End Sub
Sub placeSprite handle$, xVar, yVar
' The left mouse button has now been released at xVar, yVar
' Use the global variable drag to determine which cave sprite
cave$ = "cave";drag
' Since each cell of the grid is 40 x 80, find the nearest increments
' This gives a 'Snap To Grid' effect
x = Int((xVar + 0.5)/40) * 40
y = Int((yVar + 0.5)/80) * 80
' Move the cave sprite to the calculated cell
#main.g, "Spritexy ";cave$;" ";x;" ";y
'Disable further dragging
#main.g, "When leftButtonMove"
' Disable further placing
#main.g, "When leftButtonUp"
' Cause the 1x1 pixel to follow the cursor again
#main.g, "When mouseMove pixelFollow"
' Check again for a collision when the left mouse button is down
#main.g, "When leftButtonDown checkCollision"
' Show the sprites in their recalculated x, y positions
#main.g, "Drawsprites"
End Sub
Sub EndDemo handle$
Unloadbmp "cave1"
Unloadbmp "cave2"
Unloadbmp "pixel"
Close #main
End
End Sub
Sub EndDemoMenu
Call EndDemo "#main"
End Sub