I’m going to try to incorporate those ideas into my project. I spent a lot of time trying to align my coins to the center of each side, and the rotation was a hassle. Your solution is much more elegant.
Dave - I’ve spent a lot of time trying to figure out how to hit test your coins. I think there’s some kind of calculation I need to do - either translate, rotate or both, inside the touched function. I’ve tried every combination and permutation I could think of, and I’m not getting it right. I’m saying this, so that you don’t think I’m just asking for the answer without trying to solve the issue myself. I also considered using a matrix to solve the problem, but saw that your draw code is using just translate and rotate.
Here’s my work so far - got various things to comment and uncomment.
function Chips:touched(touch,playerIndex)
self.dragging = false
if touch.state == BEGAN then
translate(WIDTH/2,HEIGHT/2)
local rotation = 90*(playerIndex-1)
rotate(rotation)
--local v1 = vec2(touch.x-WIDTH/2,touch.y-HEIGHT/2)
--local v1 = vec2(WIDTH/2-touch.x,HEIGHT/2-touch.y)
local v1 = vec2(touch.x,touch.y)
v1 = v1:rotate(math.rad(rotation))
if self.n == "penny" then
print(self.n..":" ..playerIndex.." rotation: "..rotation)
print(" x values: ("..v1[1]..":"..self.x..")")
print(" y values: ("..v1[2]..":"..self.y..")")
end
if touch.x > v1[1] and touch.x < v1[1]+self.size and
touch.y > v1[2] and touch.y < v1[2]+self.size then
--If I can get the hit test to work, then set
self.dragging = true
end
end
return self.dragging
end
@interactivenyc - Codea uses a matrix to rotate and translate, you can use this to calculate the final positions of each stack of coins. You could calculate this without a matrix, but it’s good to understand how the matrices work, you’ll need them if you get more complicated.
--in setup, run this
GetTouchPoints()
--which is defined like this
function GetTouchPoints()
touchPoints={}
--repeat the steps taken to draw, but apply them to a matrix in memory
for z=1,4 do
touchPoints[z]={}
local m=matrix(1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1) --"empty"matrix
m=m:rotate(90*z) --rotate our matrix
for i=1,4 do
local m1=m:translate(tab[i].x,tab[i].y) --translate our matrix
--translate to centre of screen and store the result
--m[13] and m[14] store the final x and y positions in the matrix
touchPoints[z][i]=vec2(WIDTH/2+m1[13],HEIGHT/2+m1[14])
end
end
end
--then you can use this touched function
function touched(t)
if t.state==ENDED then
local v=vec2(t.x,t.y) --make vec2, see how we use it with dist below
for i=1,4 do
for j=1,4 do
if v:dist(touchPoints[i][j])<30 then --adjust the radius 30 if you want
print("Touch=",i,j) --player touched tab[i] , coin[j]
end
end
end
end
end
Can I get at the values in tab{} directly by their index number, or do I have to do a for in pairs loop to get at the chips data? I was wondering if I could do tab[1][2] to get at the “penny” info, but that’s coming up nil.
I’m starting a new approach, creating a framework of sorts that will encapsulate a lot of the Sprite handling into a helper class called Sprite.
Sprite is now handling the translate/rotate and touched for each individual Coin that extends Sprite. I’m starting to get the Sprite to be draggable, but the dragging is wonky for some reason. Might somebody take a look?
Here’s another video - it seems the amount of weirdness increases with how far away the coin is from the origin. I must be doing something wrong with my dragDelta value. Do you see anything wrong with how I’m calculating that?
There must be something wrong with the math that’s being done. I found a magic number that when I add it to my rotation calculation, it helps tremendously:
if self.dragging then
local p = self.dragDelta:rotate(-self.r*.9948) --.9948 is the MAGIC NUMBER
sprite("Project:"..self.imgName,p[1],p[2],self.w,self.h)
end
BTW, I noticed in your code that you refer to vector components with [1], [2]. Though this works fine, personally I find it more readable (and a bit less typing) to do .x, .y
I think the issue you’re having before is that vec2.rotate takes the angle in radians, whereas the drawing rotate is in degrees. So the magic number you mentioned would actually be (2*pi)/360. I think that Codea autosuggestion messes up here: it misreads vec2.rotate as rotate, and prompts you for angle in degrees
Now I’ve got my players layed out again, and got my dragging routine working, but I need to restrict my touches to the player where the touch is actually happening. I’m not exactly sure how to go about figuring that out. Either the touch needs to be restricted in the Main touched code, or in the Player:touched function.
I’d like to avoid doing this in a hard coded way, and prefer to figure out a programmatic way to identify which Player is being dragged upon. Each Player’s bounds are defined by a rect that’s simply drawn in the Player:draw function. I
--in setup
touches={} --to hold touch info
function touched(t)
if t.state==BEGAN then
--insert code to identify which player started dragging
--then store touch ID and player ID
touches[t.touchID]=GetPlayerID(t.x,t.y)
--etc other code
elseif t.state==MOVING then
--touches[t.touchID] will tell you which player this is
--so you can decide what to do
--etc other code
else
touches[t.touchID]=nil --delete touch record
--etc other code
end