#### Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

# Relative touch

Posts: 318

Hi, so I’m experimenting with a relative touch version of Starsceptre

It’s easy to get the ship to follow my finger if I use:

`````` sh.x=touch.x
sh.y=touch.y
``````

sh.x is the x position of the Ship
sh.y if the y postition of the ship

I’m looking to implement a couple of lines of code that moves the ship relative to where you finger is. So if the ship starts off in the middle of the screen, when I Touch I want it to work out it’s relative position to the ship and when I move adjust the x of the ship accordingly. Currently it just snaps to the position of the touch.

I’ve been wracking my brain and not been able to work out the code. Can anyone help?

Thanks
Rich

• Mod
Posts: 9,079

Are you after something like this or did I not understand what you’re after.

``````displayMode(FULLSCREEN)

function setup()
sx,sy,dx,dy=WIDTH/2,HEIGHT/2,0,0
end

function draw()
background(40, 40, 50)
sprite("Tyrian Remastered:Evil Orb",sx-dx,sy-dy)
end

function touched(t)
if t.state==BEGAN then
tx,ty=t.x,t.y
elseif t.state==MOVING then
dx,dy=tx-t.x,ty-t.y
elseif t.state==ENDED then
sx,sy,dx,dy=sx-dx,sy-dy,0,0
end
end
``````
• Posts: 318

THanks @dave1707 - that works great. I’m just gonna look into how it works to help my head ! Lol. Thank you

• Posts: 318

Hey @dave1707 - so I understand that code well now. Great piece of code.

What I’m finding is if you touch a second finger it interrupts the code and the ship jumps around. So I’m looking to define a single touch, then multiple touch is to be ignored by this code.

• Mod
Posts: 9,079

@Majormorgan Try this.

``````displayMode(FULLSCREEN)

function setup()
sx,sy,dx,dy,td=WIDTH/2,HEIGHT/2,0,0,0
end

function draw()
background(40, 40, 50)
sprite("Tyrian Remastered:Evil Orb",sx-dx,sy-dy)
end

function touched(t)
if t.state==BEGAN and td==0 then
tx,ty,td=t.x,t.y,t.id
elseif t.state==MOVING and td==t.id then
dx,dy=tx-t.x,ty-t.y
elseif t.state==ENDED and td==t.id then
sx,sy,dx,dy,td=sx-dx,sy-dy,0,0,0
end
end
``````
• Posts: 509

A small adjustment to use `vec2`s:

``````displayMode(FULLSCREEN)

function setup()
position = vec2(WIDTH/2,HEIGHT/2)
end

function draw()
background(40, 40, 50)
sprite("Tyrian Remastered:Evil Orb",position.x,position.y)
end

function touched(t)
if t.state==BEGAN and not tid then
offset = position - vec2(t.x,t.y)
tid = t.id
elseif tid and tid==t.id then
position = vec2(t.x,t.y) + offset
if t.state == ENDED then
tid = nil
end
end
end
``````
• Mod
edited December 2017 Posts: 9,079

Here’s a way using vec3's, but it’s a little confusing.

``````displayMode(FULLSCREEN)

function setup()
ship=vec3(WIDTH/2,HEIGHT/2,0)
end

function draw()
background(40, 40, 50)
sprite("Tyrian Remastered:Evil Orb",ship.x,ship.y)
end

function touched(t)
if t.state==BEGAN and ship.z==0 then
diff=ship-vec3(t.x,t.y,t.id)
elseif t.state==MOVING and math.abs(diff.z)==t.id then
ship=vec3(t.x,t.y,0)+diff
elseif t.state==ENDED and math.abs(diff.z)==t.id then
ship.z=0
end
end
``````
• Posts: 509

@dave1707 I really do not recommend using `vec3`s. If you want to combine the data into a single object, use a table.

``````displayMode(FULLSCREEN)

function setup()
ship={
position = vec2(WIDTH/2,HEIGHT/2)
offset = vec2(0,0),
inTouch = false,
sprite = "Tyrian Remastered:Evil Orb"
}
end

function draw()
background(40, 40, 50)
sprite(ship.sprite,ship.position.x,ship.position.y)
end

function touched(t)
if t.state==BEGAN and not ship.inTouch then
ship.inTouch = true
ship.offset = self.position - vec2(t.x,t.y)
ship.touchid = t.id
end
if ship.inTouch and ship.touchid == t.id then
ship.position = vec2(t.x,t.y) + ship.offset
if t.state == ENDED then
ship.inTouch = false
end
end
end
``````

But of course, by this stage you may as well introduce a class.

``````Ship = class()

function Ship:init(p,s)
self.position = p
self.sprite = s
end

function Ship:draw()
sprite(self.sprite, self.position.x,self.position.y)
end

function Ship:touched(t)
if not self.inTouch then
self.offset = self.position - vec2(t.x,t.y)
self.inTouch = true
self.touchid = t.id
return true
end
if not self.touchid == t.id then
return false
end
self.position = vec2(t.x,t.y) + self.offset
if t.state == ENDED then
self.inTouch = false
end
return true
end

function setup()
ship = Ship(vec2(WIDTH/2,HEIGHT/2), "Tyrian Remastered:Evil Orb")
end

function draw()
background(40,40,50)
ship:draw()
end

function touched(t)
if ship:touched(t) then
return
end
end
``````
• Mod
Posts: 9,079

@LoopSpace For this purpose, a vec3 worked just fine. Would I use a vec3 or vec4 to hold different variables, probably not, but then it would depend on what I was doing. As I said above, it’s a little confusing mixing the vec3 data and having to take the absolute value of the Touch ID to get it to work. Using a table or a class works, but those use more code compared to what is actually needed. The above examples just show that there are different ways to accomplish the same thing. It just depends on your coding style and what you’re used to.

• Posts: 509

@dave1707 Different coding styles is fine, but I don't think that co-opting a vec3 or vec4 like that is good style. It implies a relationship between the components that doesn't exist. Using a table is hardly any more code but keeps the relationship of the different pieces clear.

• Mod
Posts: 9,079

@LoopSpace Like I said, it all depends on your coding style. Would I mix data in a vec for a production program, no. Would I mix data in a vec just to show it can be done, yes. My days of production programming are long gone, but my days of hacked programming is still going on. Right now I’m a lazy programmer. In my examples I use a lot of abbreviated names (a couple of characters long) just so I don’t have to type much. I don’t expect someone to take my code and use it in their code without understanding what it does and changing the variable names to something that they understand. A lot of times I rewrite code just to make it as small as possible just to do it. I wouldn’t consider myself a good teacher.

• Posts: 509

@dave1707 But people do take your code and work with it since you provide so many examples, often without really understanding it. So you really ought to consider all your code here as "production programming". There are lots of things that "can be done", but shouldn't be and without any commentary then people who don't know better are going to think that that is a good idea.

• Mod
Posts: 9,079

@LoopSpace You’re probably correct, I should do a better job with my examples. As I said, I’m not a very good teacher and I’m a lazy programmer and I probably won't change. Even when I was working I never commented my code even though I was told more than once to do so. I always said that the code was the comments because it was always correct and current.

• Posts: 318

Thanks @dave1707 and @LoopSpace these are really cool

Currently I can using the version before Vec2 onwards was introduced. This works great for me.

Now one thing I would love to have is based on how fast I move the finger left or right I’d like to measure that change so I can switch the state of the ship to another state. Currently the ship is in flat mode. When you start to move slowly right it tilts right (I have the animation code already for that) and if you move faster right it goes to extreme tilt right.

Ignore calling the states, for decidImg how far I’ve dragged do I use touch.delta?

Thanks and Merry Christmas!!!!

• Mod
Posts: 9,079

@Majormorgan You can use t.deltaX to determine how fast you’re moving your finger. Each call to the touched function MOVING will give you how far your finger moved.

• Posts: 318

Works a treat @dave1707 - perfect!

One other question. When the ship dies some of the touches are still engaged and play up on the next life. Is there a way to reset all that touches?

Thanks and merry Christmas!!

• Mod
Posts: 9,079

Are you saving the touches in a table. If so, when the ship dies just set the table to nil and start over.

• Posts: 318

Perfect. Thank you @dave1707 I’m really starting to understand this stuff. Got it saving to a table and wiping that when I start over. Perfect

• Posts: 23

Complete novice, so forgive the stupid question.

I”m using the vec2 ship class example above and believe I understand how it works, but when I try and do it over a background image, or at least how I think that should be done after searching on here, instead of getting a moving ship, I get the image I used for the background replacing the ship and that moves instead!

The only difference in the draw function is the sprite command below (I setup the image variable in setup.

Could someone enlighten me please so I get a moving ship, not a pictur...?

function draw()

``````background(40, 40, 50)
-- Set background
sprite(imageBackground, WIDTH/2, HEIGHT/2, WIDTH, HEIGHT)

ship:draw()
``````

end

• Mod
Posts: 9,079

@RaggedTooth Heres the ship code along with the star background.

``````displayMode(FULLSCREEN)

function setup()
tab={}
for z=1,300 do  -- number of stars
x=math.random(WIDTH)
y=math.random(HEIGHT)
s=math.random(8)    -- size
sp=math.random(3)   -- speed
c=color(math.random(255),math.random(255),math.random(255))
table.insert(tab,{x=x,y=y,s=s,sp=sp,c=c})
end
ship = Ship(vec2(WIDTH/2,HEIGHT/2), "Tyrian Remastered:Evil Orb")
end

function draw()
background(40,40,50)
for a,b in pairs(tab) do
fill(b.c)
ellipse(b.x,b.y,b.s)
b.y=b.y-b.sp
if b.y<-10 then
b.y=HEIGHT+20
end
end
ship:draw()
end

function touched(t)
if ship:touched(t) then
return
end
end

Ship = class()

function Ship:init(p,s)
self.position = p
self.sprite = s
end

function Ship:draw()
sprite(self.sprite, self.position.x,self.position.y)
end

function Ship:touched(t)
if not self.inTouch then
self.offset = self.position - vec2(t.x,t.y)
self.inTouch = true
self.touchid = t.id
return true
end
if not self.touchid == t.id then
return false
end
self.position = vec2(t.x,t.y) + self.offset
if t.state == ENDED then
self.inTouch = false
end
return true
end
``````
• Posts: 23

Thanks Dave, although even my capabilities could merge those!

The starfield code really helps though, thank you.

I still want to display the static image below all this though and whilst this line does it correctly, I don’t get why the image also replaces the ship sprite...

sprite(imageBackground, WIDTH/2, HEIGHT/2, WIDTH, HEIGHT)

• Mod
Posts: 9,079

@RaggedTooth I’m not sure why you’re having trouble with the imageBackground line. Since I don’t have whatever you imageBackground is, I replaced it with the Cargo Bot image for this example. The ship moves and the background doesn’t.

``````displayMode(FULLSCREEN)

function setup()
ship = Ship(vec2(WIDTH/2,HEIGHT/2), "Tyrian Remastered:Evil Orb")
end

function draw()
background(40,40,50)
sprite(asset.builtin.Cargo_Bot.Startup_Screen,WIDTH/2,HEIGHT/2,WIDTH,HEIGHT)
ship:draw()
end

function touched(t)
if ship:touched(t) then
return
end
end

Ship = class()

function Ship:init(p,s)
self.position = p
self.sprite = s
end

function Ship:draw()
sprite(self.sprite, self.position.x,self.position.y)
end

function Ship:touched(t)
if not self.inTouch then
self.offset = self.position - vec2(t.x,t.y)
self.inTouch = true
self.touchid = t.id
return true
end
if not self.touchid == t.id then
return false
end
self.position = vec2(t.x,t.y) + self.offset
if t.state == ENDED then
self.inTouch = false
end
return true
end
``````
• Posts: 23

It appears I’m not now. Just tried putting it back in and with the starfield code there it works.

Hmm.

Thank you.