PokerChips Project: Classes and Inheritance

Faroutski, Dave! That’s beautiful. Thank you, thank you, thank you!

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 github: https://github.com/interactivenyc/DavePoker

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

Thanks in advance

@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

If you’re intrigued by the matrix, see here

https://coolcodea.wordpress.com/2014/11/26/184-what-is-modelmatrix/comment-page-1/

Thanks Dave - yeah, the math was confusing me :slight_smile:

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.

You can get the values directly. You use the names that are in the chips:init function.

    print(tab[1].x)
    print(tab[1].n)
    print(tab[1].col)

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?

https://github.com/interactivenyc/SpriteHandling

TIA

shouldn’t you be adjusting self.x and self.y when you drag?

I made a change that works better now.

Are you able to run the program yourself? Do you use WorkingCopy?

Here’s a video now, to demonstrate where it’s at. The drag is still a little weird, but at least it’s working.

http://youtu.be/ZVt8pCo-m-I

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?

http://youtu.be/DOHBBpvmAPU

NOPE! The amount of weirdness has to do with how much the coin is being rotated.

http://youtu.be/h6Z64qkGvpM

Instead of cancelling the rotate with this p = p:rotate(-self.r) why not pop the transform of the stack? So do something like (untested)

popMatrix()
pushMatrix()
translate(self.x+self.dragDelta.x, self.y+self.dragDelta.y)
rotate(self.r)
sprite("Project:"..self.imgName,0,0,self.w,self.h)

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

One more video demonstrating:

http://youtu.be/qYQPucmGZHA

I think we posted at the same time, don’t know if you saw my suggestion above

Thanks Yojimbo - that works!

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 noticed that in your code, and will change accordingly. Thanks again!

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

Any thoughts? Here’s a video of how it looks now:

http://youtu.be/jryTXtlj9K8

You can use touch ID to keep track of the touches. That way everyone can be moving coins at the same time and they would be independent of each other.

--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