Page 1 of 2
Drag sprite with finger example (and a question)
Posted: Wed Jan 11, 2017 8:04 pm
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
Re: Drag sprite with finger example (and a question)
Posted: Wed Jan 11, 2017 8:29 pm
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
Re: Drag sprite with finger example (and a question)
Posted: Wed Jan 11, 2017 8:51 pm
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
Re: Drag sprite with finger example (and a question)
Posted: Wed Jan 11, 2017 10:37 pm
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?
Re: Drag sprite with finger example (and a question)
Posted: Wed Jan 11, 2017 10:59 pm
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
Re: Drag sprite with finger example (and a question)
Posted: Thu Jan 12, 2017 12:26 am
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
Re: Drag sprite with finger example (and a question)
Posted: Thu Jan 12, 2017 2:57 am
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
Re: Drag sprite with finger example (and a question)
Posted: Thu Jan 12, 2017 3:13 am
by Dav
Thanks, rbytes. That behaves real well.
- Dav
Re: Drag sprite with finger example (and a question)
Posted: Thu Jan 12, 2017 1:03 pm
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
Re: Drag sprite with finger example (and a question)
Posted: Fri Jan 13, 2017 3:21 am
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