Sprite Dragging
Root / Programming Questions / [.]
WuulfCreated:
Could someone help me find out how to drag sprites on the touchscreen?, I already know how to do simple dragging, but I'm talking about how to drag the sprite from the point at which I touch the sprite, instead of the middle of said sprite?You wouldn't need anything else, a single Sprite is like one coordinate.
A while ago I made some code to do this (with a technique stolen from kantackistan). Doesn't really account for rotation, etc. but it works well enough. Added a few a lot of comments, but feel free to ask questions if you need more info.
' Here's the demonstration... ACLS XSCREEN 3 ' Sample scene. A bunch of random objects ' you can drag around. DISPLAY 1 DRAG_CURSOR FOR I%=0 TO 31 J%=SPSET(I%) SPOFS J%,RND(304)+8,RND(224)+8 SPHOME J%,8,8 DRAG_ITEM J% SPSCALE J%,RND(3)+1,RND(3)+1 NEXT I% WHILE 1 VSYNC CALL SPRITE WEND ' ...and here's the library portion. ' Makes a very small (1x1 px) sprite that functions ' as a cursor and stores sprite dragging state. ' Only call it once! DEF DRAG_CURSOR ' I set the UV to 4, 4 but it doesn't really matter. VAR I%=SPSET(4,4,1,1,1) ' We aren't dragging any sprite yet. SPVAR I%,0,-1 ' Make sure this sprite collides with draggable sprites. SPCOL I%,0,256 ' Set the callback up. SPFUNC I%,"DRAG_CURSOR_SPR" END ' Makes a sprite draggable. DEF DRAG_ITEM ID% SPCOL ID%,1,256 END ' The callback for the cursor sprite. ' This should run every frame, via CALL SPRITE. DEF DRAG_CURSOR_SPR VAR T%,X%,Y% TOUCH OUT T%,X%,Y% ' Move the cursor to where we are touching the screen. SPOFS CALLIDX,X%,Y% IF T% THEN ' If we are touching the screen... IF SPVAR(CALLIDX,0)>-1 THEN ' If we already are dragging a sprite, just ' move that sprite (var #0) by the offset (vars #1 and #2) SPOFS SPVAR(CALLIDX,0),X%+SPVAR(CALLIDX,1),Y%+SPVAR(CALLIDX,2) ELSE ' Otherwise, we need to look for if a sprite hit the cursor. ' Get what sprite the cursor hit. ' If it's -1, we didn't hit anything. VAR H%=SPHITSP(CALLIDX) ' If you just started touching the screen ' (as indicated by touch time (T%) being 1, the first frame) ' and you touched a sprite ' (as indicated by hit sprite (H%) being not -1) ' then store some info about it. IF T%==1 && H%>-1 THEN VAR OX%,OY% ' Before we move anything, where is the hit sprite? SPOFS H% OUT OX%,OY% ' And we can notify it that it's being dragged by setting its ' 7th variable to 1. SPVAR H%,7,1 ' Also, store the ID of that sprite so we can use it later. SPVAR CALLIDX,0,H% ' Also, store the offset of the cursor vs. the hit sprite. SPVAR CALLIDX,1,OX%-X%:SPVAR CALLIDX,2,OY%-Y% ENDIF ENDIF ELSE ' If we aren't touching the screen ' but we still have a sprite stored, ' release the sprite. IF SPVAR(CALLIDX,0)>-1 THEN ' Let the other sprite know it's no longer being dragged. SPVAR SPVAR(CALLIDX,0),7,0 ' And we don't need to know about the other sprite's ID anymore. SPVAR CALLIDX,0,-1 ENDIF ENDIF END
A while ago I made some code to do this (with a technique stolen from kantackistan). Doesn't really account for rotation, etc. but it works well enough. AddedIt gives me a error in else var h%=sphitsp(callidx)a fewa lot of comments, but feel free to ask questions if you need more info.show very messy code
' Here's the demonstration... ACLS XSCREEN 3 ' Sample scene. A bunch of random objects ' you can drag around. DISPLAY 1 DRAG_CURSOR FOR I%=0 TO 31 J%=SPSET(I%) SPOFS J%,RND(304)+8,RND(224)+8 SPHOME J%,8,8 DRAG_ITEM J% SPSCALE J%,RND(3)+1,RND(3)+1 NEXT I% WHILE 1 VSYNC CALL SPRITE WEND ' ...and here's the library portion. ' Makes a very small (1x1 px) sprite that functions ' as a cursor and stores sprite dragging state. ' Only call it once! DEF DRAG_CURSOR ' I set the UV to 4, 4 but it doesn't really matter. VAR I%=SPSET(4,4,1,1,1) ' We aren't dragging any sprite yet. SPVAR I%,0,-1 ' Make sure this sprite collides with draggable sprites. SPCOL I%,0,256 ' Set the callback up. SPFUNC I%,"DRAG_CURSOR_SPR" END ' Makes a sprite draggable. DEF DRAG_ITEM ID% SPCOL ID%,1,256 END ' The callback for the cursor sprite. ' This should run every frame, via CALL SPRITE. DEF DRAG_CURSOR_SPR VAR T%,X%,Y% TOUCH OUT T%,X%,Y% ' Move the cursor to where we are touching the screen. SPOFS CALLIDX,X%,Y% IF T% THEN ' If we are touching the screen... IF SPVAR(CALLIDX,0)>-1 THEN ' If we already are dragging a sprite, just ' move that sprite (var #0) by the offset (vars #1 and #2) SPOFS SPVAR(CALLIDX,0),X%+SPVAR(CALLIDX,1),Y%+SPVAR(CALLIDX,2) ELSE ' Otherwise, we need to look for if a sprite hit the cursor. ' Get what sprite the cursor hit. ' If it's -1, we didn't hit anything. VAR H%=SPHITSP(CALLIDX) ' If you just started touching the screen ' (as indicated by touch time (T%) being 1, the first frame) ' and you touched a sprite ' (as indicated by hit sprite (H%) being not -1) ' then store some info about it. IF T%==1 && H%>-1 THEN VAR OX%,OY% ' Before we move anything, where is the hit sprite? SPOFS H% OUT OX%,OY% ' And we can notify it that it's being dragged by setting its ' 7th variable to 1. SPVAR H%,7,1 ' Also, store the ID of that sprite so we can use it later. SPVAR CALLIDX,0,H% ' Also, store the offset of the cursor vs. the hit sprite. SPVAR CALLIDX,1,OX%-X%:SPVAR CALLIDX,2,OY%-Y% ENDIF ENDIF ELSE ' If we aren't touching the screen ' but we still have a sprite stored, ' release the sprite. IF SPVAR(CALLIDX,0)>-1 THEN ' Let the other sprite know it's no longer being dragged. SPVAR SPVAR(CALLIDX,0),7,0 ' And we don't need to know about the other sprite's ID anymore. SPVAR CALLIDX,0,-1 ENDIF ENDIF END
A while ago I made some code to do this (with a technique stolen from kantackistan).Hey cool! Glad to see the technique caught on.
Do you know if dragging a sprite of a custom size like this is possible?Yes, you should be able to drag any sprite of any size. When SPHITSP() is triggered between your draggable sprite and your cursor sprite, save the difference in position as two values, X and Y. That's how it will remember where exactly on the sprite you grabbed. If you want to cheat, you could also just SPLINK the draggable sprite to your cursor (and SPOFS it by -X, -Y) until the drag is finished, then unlink it.
Will using SPLINK look weird?No idea. Only one way to find out!