Drag sprite with finger example (and a question)

User avatar
Dav
Posts: 279
Joined: Tue Dec 30, 2014 5:12 pm
My devices: iPad Mini, iPod Touch.
Location: North Carolina, USA
Contact:

Drag sprite with finger example (and a question)

Post by Dav »

I thought someone may like a small example of moving a sprite on screen with the finger. I'm working on a sliding puzzle game now and needed something like this. I also have a question of the best way to prevent 2 sprites from overlapping each other on the screen.

In this code you drag a blue box around. If it collides with the red box, it's not suppose to move over it, but it does here. I'd like to prevent it from touching each other all together. what would be the best way to achieve that? Thanks for any input. The dragging example works ok, so here it is.

- Dav

Code: Select all

'dragsprite.txt
'Drag a sprite with finger example
'Code by Dav, JAN/2017

option base 1

graphics
refresh off

'draw blue box sprite
graphics clear 0,0,1
draw rect 2,2 to 98,198
sprite "b" scan 0,0,100,200
sprite "b" show
sprite "b" at 200,200

'draw red box sprite
graphics clear 1,0,0
draw rect 2,2 to 98,198
sprite "c" scan 0,0,100,200
sprite "c" show
sprite "c" at 400,400

graphics clear 0,0,0
refresh on

draw text "Drag blue box with finger" at 1,1
draw text "Don't collide with red one" at 1,30


do

  get touch 0 as tx,ty  'get first touch

  'if user presses on the blue sprite
  if sprite_hit("b", tx,ty) then
     'get sprite x,y location
     get sprite "b" pos sx,sy

     do

       get touch 0 as tx2,ty2 'get finger drag
       if tx2=-1 then break 'break loop if up

       'only move sprite if not hitting other
       if not sprites_collide("b","c") then
         sprite "b" at tx2-tx+sx,ty2-ty+sy
       end if

     until 0
  end if

  slowdown

until 0

Joel
Posts: 57
Joined: Fri Jan 15, 2016 1:36 pm
My devices: miniipad
Flag: Germany

Re: Drag sprite with finger example (and a question)

Post by Joel »

You should FIRST check the condition, THEN draw the sprite (or correct its position)

Code: Select all

'dragsprite.txt
'Drag a sprite with finger example
'Code by Dav, JAN/2017

OPTION BASE 1

GRAPHICS
REFRESH OFF

'draw blue box sprite
GRAPHICS CLEAR 0,0,1
DRAW RECT 2,2 TO 98,198
SPRITE "b" SCAN 0,0,100,200
SPRITE "b" SHOW
SPRITE "b" AT 200,200

'draw red box sprite
GRAPHICS CLEAR 1,0,0
DRAW RECT 2,2 TO 98,198
SPRITE "c" SCAN 0,0,100,200
SPRITE "c" SHOW
SPRITE "c" AT 400,400

GRAPHICS CLEAR 0,0,0
REFRESH ON

DRAW TEXT "Drag blue box with finger" AT 1,1
DRAW TEXT "Don't collide with red one" AT 1,30


DO

  GET TOUCH 0 AS tx,ty  'get first touch

  'if user presses on the blue sprite
  IF SPRITE_HIT("b", tx,ty) THEN
     'get sprite x,y location
     GET SPRITE "b" POS sx,sy

     DO

       GET TOUCH 0 AS tx2,ty2 'get finger drag
       IF tx2=-1 THEN BREAK 'break loop if up

       'only move sprite if not hitting other
       IF NOT SPRITES_COLLIDE("b","c") THEN
         SPRITE "b" AT tx2-tx+sx,ty2-ty+sy
'r'
         IF SPRITES_COLLIDE("b","c") THEN GRAPHICS CLEAR 1,0,0
''
       END IF

     UNTIL 0
  END IF

  SLOWDOWN

UNTIL 0

User avatar
Dav
Posts: 279
Joined: Tue Dec 30, 2014 5:12 pm
My devices: iPad Mini, iPod Touch.
Location: North Carolina, USA
Contact:

Re: Drag sprite with finger example (and a question)

Post by Dav »

Thanks, Joel. That was helpful. I reset sprite position now if colliding, so now the sprites will not overlap and get stuck like before.

Thank you!

- Dav

Code: Select all

'dragsprite.txt
'Drag a sprite with finger example
'Code by Dav, JAN/2017

OPTION BASE 1

GRAPHICS
REFRESH OFF

'draw blue box sprite
GRAPHICS CLEAR 0,0,1
DRAW RECT 2,2 TO 98,198
SPRITE "b" SCAN 0,0,100,200
SPRITE "b" SHOW
SPRITE "b" AT 200,200

'draw red box sprite
GRAPHICS CLEAR 1,0,0
DRAW RECT 2,2 TO 98,198
SPRITE "c" SCAN 0,0,100,200
SPRITE "c" SHOW
SPRITE "c" AT 400,400

GRAPHICS CLEAR 0,0,0
REFRESH ON

DRAW TEXT "Drag blue box with finger" AT 1,1
DRAW TEXT "Don't collide with red one" AT 1,30


DO

  GET TOUCH 0 AS tx,ty  'get first touch

  'if user presses on the blue sprite
  IF SPRITE_HIT("b", tx,ty) THEN
     'get sprite x,y location
     GET SPRITE "b" POS sx,sy

     DO

       GET TOUCH 0 AS tx2,ty2 'get finger drag
       IF tx2=-1 THEN BREAK 'break loop if up
       
       'save current x,y pos of sprite
       GET SPRITE "b" POS sx2,sy2
       
       SPRITE "b" AT tx2-tx+sx,ty2-ty+sy
       
       'if they now collide, reset to old x,y
       IF SPRITES_COLLIDE("b","c") THEN 
          sprite "b" at sx2,sy2
          break
       END IF

     UNTIL 0
  END IF

  SLOWDOWN

UNTIL 0

Joel
Posts: 57
Joined: Fri Jan 15, 2016 1:36 pm
My devices: miniipad
Flag: Germany

Re: Drag sprite with finger example (and a question)

Post by Joel »

yeah, thats much nicer. but if you drag the blue box very fast, it will stop at a position which is more or less distant to the other box.
what about calculating the correct position with the help of the last saved one and the wrong overlapped one?

DrChip
Posts: 167
Joined: Wed Oct 22, 2014 3:26 pm
My devices: iPhone 4 to 6+,iPad mini to iPad air 2

Re: Drag sprite with finger example (and a question)

Post by DrChip »

'A little beep is nice! Fun!

Code: Select all

'dragsprite.txt
'Drag a sprite with finger example
'Code by Dav, JAN/2017

OPTION BASE 1

GRAPHICS
REFRESH OFF

'draw blue box sprite
GRAPHICS CLEAR 0,0,1
DRAW RECT 2,2 TO 98,198
SPRITE "b" SCAN 0,0,100,200
SPRITE "b" SHOW
SPRITE "b" AT 0,0

'draw red box sprite
GRAPHICS CLEAR 1,0,0
DRAW RECT 2,2 TO 98,198
SPRITE "c" SCAN 0,0,100,200
SPRITE "c" SHOW
SPRITE "c" AT SCREEN_WIDTH()/2,SCREEN_HEIGHT()/2

GRAPHICS CLEAR 0,0,0
REFRESH ON

DRAW TEXT "Drag blue box with finger" AT 1,1
DRAW TEXT "Don't collide with red one" AT 1,30


DO

  GET TOUCH 0 AS tx,ty  'get first touch

  'if user presses on the blue sprite
  IF SPRITE_HIT("b", tx,ty) THEN
     'get sprite x,y location
     GET SPRITE "b" POS sx,sy

     DO

       GET TOUCH 0 AS tx2,ty2 'get finger drag
       IF tx2=-1 THEN BREAK 'break loop if up
       
       'save current x,y pos of sprite
       GET SPRITE "b" POS sx2,sy2
       
       SPRITE "b" AT tx2-tx+sx,ty2-ty+sy
       
       'if they now collide, reset to old x,y
       IF SPRITES_COLLIDE("b","c") THEN 
          SPRITE "b" AT sx2,sy2
          BEEP
          BREAK
       END IF

     UNTIL 0
  END IF

  SLOWDOWN

UNTIL 0

User avatar
Dav
Posts: 279
Joined: Tue Dec 30, 2014 5:12 pm
My devices: iPad Mini, iPod Touch.
Location: North Carolina, USA
Contact:

Re: Drag sprite with finger example (and a question)

Post by Dav »

Good suggestion, Joel. I'll work on figuring that out. Dr. Chip, you're right, I added some sound too. Here's where I went with this in the last couple hours. I added multi sprite detection and also an 'again' label to make sure finger touch stays on the same sprite (without it, it would pass onto the sprite it hit).

It's starting to shape up a little better. As always, your suggestion/advice for improvement are much appreciated!

Edit: Dr Chip I think your beep worked better. The fast repeated notes call I used seems to overload sB eventually, so I put in a small delay to prevent crash.

- Dav

Code: Select all

'dragsprite.txt
'Drag a sprite with finger example
'Code by Dav, JAN/2017

option base 1

graphics
set orientation top
get screen size sw,sh

refresh off

sprites=7

'draw red box sprite
graphics clear 1,0,0
draw rect 2,2 to 98,198
sprite "1" scan 0,0,100,200
sprite "1" show
sprite "1" at 1,1


'draw blue box sprites
for a = 2 to sprites
   graphics clear 0,0,1
   draw rect 2,2 to 98,198
   sprite str$(a) scan 0,0,100,200
   sprite str$(a) show
   sprite str$(a) at 110*(a-1),100*a
next a


graphics clear 0,0,0
refresh on


do


  get touch 0 as tx,ty  'get first touch

  for a = 1 to sprites

  'if user presses on sprite
  if sprite_hit(str$(a), tx,ty) then
     again:

     'get sprite x,y location
     get sprite str$(a) pos sx,sy

     do

       get touch 0 as tx2,ty2 'get finger drag
       if tx2=-1 then break 'break loop if up
       get sprite str$(a) pos sx2,sy2
       sprite str$(a) at tx2-tx+sx,ty2-ty+sy

       if blocked then
         sprite str$(a) at sx2,sy2
         break
       end if

     until 0

      if touch_x(0)>-1 then 
         get touch 0 as tx,ty 
         goto again 'keep on same sprite
      end if

  end if

  next a

  slowdown

until 0

def blocked()
for t= 1 to .sprites
   if t= .a then goto skip
   if sprites_collide(str$(.a),str$(t)) then
     notes set "112:tc8"
     notes play
     pause .1
     return 1
   end if
   skip:
next t
blocked=0
end def

User avatar
rbytes
Posts: 1338
Joined: Sun May 31, 2015 12:11 am
My devices: iPhone 11 Pro Max
iPad Pro 11
MacBook
Dell Inspiron laptop
CHUWI Plus 10 convertible Windows/Android tablet
Location: Calgary, Canada
Flag: Canada
Contact:

Re: Drag sprite with finger example (and a question)

Post by rbytes »

Dav, I tried a different approach to your blue Sprite, red Sprite. I have the logic figured out for both vertical and horizontal movement, but so far I have only done the code for horizontal movement. Try dragging the blue Sprite sideways from either side of the red Sprite, to it and then across it. The blue Sprite stops dead when almost but not touching the Red sprite. There is no rebound, no matter how fast you drag. You can still drag th blue Sprite up or down. But If you drag blue Sprite down or up against the red Sprite's top or bottom it will just stick, because that code still needs to be entered.

I have inserted comments on what coding is needed. Vertical detection would use the same pattern as horizontal detection.

Code: Select all

'dragsprite.txt
'Drag a sprite with finger example
'Code by Dav, JAN/2017
'Collision detection by rbytes

GET SCREEN SIZE sw,sh
OPTION BASE 1
OPTION SPRITE POS CENTRAL
GRAPHICS
REFRESH OFF

'draw blue box sprite
GRAPHICS CLEAR 0,0,1
DRAW RECT 2,2 TO 98,198
SPRITE "b" SCAN 0,0,100,200
SPRITE "b" SHOW
SPRITE "b" AT 0,0

'draw red box sprite
GRAPHICS CLEAR 1,0,0
DRAW RECT 2,2 TO 98,198
SPRITE "c" SCAN 0,0,100,200
SPRITE "c" SHOW
SPRITE "c" AT SCREEN_WIDTH()/2,SCREEN_HEIGHT()/2

GRAPHICS CLEAR 0,0,0
REFRESH ON

DRAW TEXT "Drag blue box with finger" AT 1,1
DRAW TEXT "Don't collide with red one" AT 1,30


DO

  GET TOUCH 0 AS tx,ty  'get first touch

  'if user presses on the blue sprite
  IF SPRITE_HIT("b", tx,ty) THEN
     'get sprite x,y location
     GET SPRITE "b" POS sx,sy

     DO

       GET TOUCH 0 AS tx2,ty2 'get finger drag
       IF tx2=-1 THEN BREAK 'break loop if up
       
       'save current x,y pos of sprite
       GET SPRITE "b" POS sx2,sy2
       
       SPRITE "b" AT tx2-tx+sx,ty2-ty+sy
     
       IF SPRITES_COLLIDE("b","c") THEN
         ' blue sprite is vertically coincident with red sprite
         ' blue sprite is left of red sprite
         IF sy2 >sh/2-200 AND sy2<sh/2+200 AND sx2<=sw/2-100 THEN
           SPRITE "b" AT sw/2-100,sy2
         ENDIF
         ' blue sprite is vertically coincident with red sprite
         ' blue sprite is right of red sprite
         IF sy2 >sh/2-200 AND sy2<sh/2+200 AND sx2>=sw/2+100 THEN
           SPRITE "b" AT sw/2+100,sy2
         ENDIF
         
         ' blue sprite is horizontally coincident with red sprite
         ' blue sprite is above red sprite
         ' code
         
         ' blue sprite is horizontally coincident with red sprite
         ' blue sprite is below red sprite
         ' code
         
          BEEP
          BREAK
       END IF

     UNTIL 0
  END IF

  SLOWDOWN

UNTIL 0
The only thing that gets me down is gravity...

User avatar
Dav
Posts: 279
Joined: Tue Dec 30, 2014 5:12 pm
My devices: iPad Mini, iPod Touch.
Location: North Carolina, USA
Contact:

Re: Drag sprite with finger example (and a question)

Post by Dav »

Thanks, rbytes. That behaves real well.

- Dav

User avatar
Dav
Posts: 279
Joined: Tue Dec 30, 2014 5:12 pm
My devices: iPad Mini, iPod Touch.
Location: North Carolina, USA
Contact:

Re: Drag sprite with finger example (and a question)

Post by Dav »

rbytes, I think the behavior of your sprite blocking approach is what I'm after for the sliding puzzle, so will pursue in that direction. Instead of hard coded x/y placement in the red spite in the calculations, I'm going to to get/use the position/size for the colliding sprites and use those instead. Sprites sizes will be different in the puzzle. Something like this..

Get sprite "b" pos bpx,bpy
Get sprite "b" size bsx,bsy

Get sprite "c" pos cpx,cpy
Get sprite "c" size csx,csy

I still haven't got my thinking around your calculations fully yet, but will play around with it today. Math comes hard for me, I never got past intro to algebra in school. I really admire the advanced math skills you and the others here have. Anyway, you gave me an technique to pursue. Thanks.

- Dav

User avatar
Dav
Posts: 279
Joined: Tue Dec 30, 2014 5:12 pm
My devices: iPad Mini, iPod Touch.
Location: North Carolina, USA
Contact:

Re: Drag sprite with finger example (and a question)

Post by Dav »

Hit a road block trying to figure out how to correct when hitting a sprite from any side. I can correct left&right, or top&bottom, but not all at same time. This of course is trying to put the sprite side by side, and not leave such a gap between when dragging. I could go back to using the previous correcting way, but I like the smoother look of close together.

Here's what I have so far. The code in red (in the blocked function) is the problem I'm having a hard time figuring out. If I could figure out how to tell WHICH side the sprite is being hit from...

- Dav

Code: Select all

'freeblock.txt
'free red block from the room.
'move blue blocks out of the way.
'Code by Dav, JAN/2017

option base 1

graphics
set orientation top
get screen size sw,sh

refresh off

sprites=7

'draw red box sprite
graphics clear 1,0,0
draw rect 2,2 to 98,198
sprite "1" scan 0,0,100,200
sprite "1" show
sprite "1" at 51,51


'draw blue box sprites
dx=110!dy=300
for a = 2 to sprites
   graphics clear 0,0,1
   draw rect 2,2 to 98,198
   sprite str$(a) scan 0,0,100,200
   sprite str$(a) show
   sprite str$(a) at dx,dy
   dx=dx+110
   if dx>sw-50-110 then
     dx=110!dy=dy+300
   end if
next a

graphics clear 0,0,0

'draw exit sprite
sprite "exit" scan 0,0,110,50
sprite "exit" show
sprite "exit" at sw/2-55,sh-50

'draw walls
fill color .3,.3,.3
fill rect 0,0 to sw,50 'top
fill rect 0,0 to 50,sh 'left
fill rect sw-50,0 to sw,sh 'right
fill rect 0,sh-50 to sw,sh 'bottom



refresh on


do


  get touch 0 as tx,ty  'get first touch

  for a = 1 to sprites

  'if user presses on the sprite
  if sprite_hit(str$(a), tx,ty) then
     again:

     'get sprite x,y location
     get sprite str$(a) pos sx,sy

     do

       get touch 0 as tx2,ty2 'get finger drag
       if tx2=-1 then break 'break loop if up

       get sprite str$(a) pos sx2,sy2
       sprite str$(a) at tx2-tx+sx,ty2-ty+sy

       'see if red box hits exit sprite
       if sprites_collide("1","exit") then 
          sprites delete
          end
       end if

       'see if red sprite hits another sprite
       if blocked then
         'sprite str$(a) at sx2,sy2
         click ! break
       end if

       'make sure sprite stays within walls
       get sprite str$(a) pos lx,ly
       get sprite str$(a) size lsx,lsy
       'check left
       if lx<50 then
         sprite str$(a) at 50,sy2
         click ! break
       end if
       'check right
       if lx>sw-50-lsx then
         sprite str$(a) at sw-50-lsx,sy2
         click ! break
       end if
       'check top
       if ly<50 then
         sprite str$(a) at sx2,50
         click ! break
       end if
       'check bottom
       if ly> sh-50-lsy then
         sprite str$(a) at sx2,sh-50-lsy
         click ! break
       end if

     until 0

      if touch_x(0)>-1 then 
         get touch 0 as tx,ty 
         goto again 'keep on same sprite
      end if

  end if

  next a

  slowdown

until 0

def blocked()
for t= 1 to .sprites
   if t= .a then goto skip
   if sprites_collide(str$(.a),str$(t)) then

'r'

       get sprite str$(.a) pos ax,ay
       get sprite str$(.a) size asx,asy

       get sprite str$(t) pos tx,ty
       get sprite str$(t) size tsx,tsy

       'need a better way to figure out
       'which side to correct. 
       'if i could tell wich side of sprite
       'was being hit, that would help...

       'right & left seem to work.

       'hitting sprite on right
       if ax+asx>tx and tx>ax then 
          sprite str$(.a) at tx-asx,ay
       end if

       'hitting sprite on left
       if ax<tx+tsx and tx < ax then
          sprite str$(.a) at tx+tsx,ay
       end if
       
       'hitting sprite below
       if ay+asy>ty and ay < ty then
         'sprite str$(.a) at ax,ty-asy
       end if

       'hitting sprite on top
       if ay<ty+tsy and ty>ay then
         'sprite str$(.a) at ax,ty+tsy
       end if

''

     'sprite str$(.a) at .sx2,.sy2

     return 1
   end if
   skip:
next t
blocked=0
end def

def click
     notes set "113:tc8"
     notes play
     pause .1
end def

Post Reply