NSAffineTransforms, among other things

suhbataar
Unregistered
 
Post: #1
I just started looking at Cocoa and ObjC, and I am - as many others, I'm sure - surprised at how easy it is to get going. I am working on a Tetris-clone in order to get myself going. In it, I have arranged it thus that each piece is represented ideally by a 4x4 "matrix". I then have an array of the 4 points of the lower-left corner of those squares in the matrix that are in the actual shape. The coordinates (in the surrounding coordinate system) of the lower left corner in the matrix are stored as another point, to represent the position of the shape.

To rotate the shapes I tried using combined NSAffineTransforms that first translated the origin to an axis-of-rotation-point, then rotated and then translated the other way. However, I didn't get it to work, and ended up defining the matrix for the transformation instead, using NSAffineTransform with that instead.

Everything worked fine until I started letting the shapes fall down. Now when I do that, and take in key events that rotate it too, the rotations start going in wide circles, and the shapes start jumping all over the place. I know this might not be expressed in the clearest possible way, but any ideas of what is going wrong would be helpful.

I'd also like to ask some advice on Timers while I'm at it. I'm using an NSTimer to step the game forward. What are the pros & cons of doing this as opposed to using a separate thread? Also I'm using keyCodes to determine what key has been pressed, not letting those events that are repeated (isARepeat) do anything, so that the player has to keep tapping keys instead of just holding one down. I don't want the player's key-repeat system prefs to influence the game. However, it seems sort of unresponsive because of this. Any tips on how to handle key input would be appreciated.
Quote this message in a reply
Moderator
Posts: 608
Joined: 2002.04
Post: #2
Regarding multithreading: I doubt multithreading here would be a good idea. Since it sounds like NSTimer is working for you, don't bother switching.
Quote this message in a reply
DoG
Moderator
Posts: 869
Joined: 2003.01
Post: #3
As for timers, don't rely on them pacing your game. Typically, fire your timer more frequently than strictly necessary, and check inside your idle loop with UpTime() or GetCurrentEventTime() the exact time.

Also, with NSAffineTransform, the order of the transformation is critical. Try exchanging the order of how you apply the rotation and movement transforms.
Quote this message in a reply
Moderator
Posts: 608
Joined: 2002.04
Post: #4
Regarding what DoG said: if you prefer a Cocoa solution, you can use NSTimeInterval. There is a post somewhere regarding a FPS counter which shows how to find the change in time using NSTimeInterval.
Quote this message in a reply
Member
Posts: 469
Joined: 2002.10
Post: #5
suhbataar Wrote:I just started looking at Cocoa and ObjC, and I am - as many others, I'm sure - surprised at how easy it is to get going. I am working on a Tetris-clone in order to get myself going. In it, I have arranged it thus that each piece is represented ideally by a 4x4 "matrix". I then have an array of the 4 points of the lower-left corner of those squares in the matrix that are in the actual shape. The coordinates (in the surrounding coordinate system) of the lower left corner in the matrix are stored as another point, to represent the position of the shape.

To rotate the shapes I tried using combined NSAffineTransforms that first translated the origin to an axis-of-rotation-point, then rotated and then translated the other way. However, I didn't get it to work, and ended up defining the matrix for the transformation instead, using NSAffineTransform with that instead.

Everything worked fine until I started letting the shapes fall down. Now when I do that, and take in key events that rotate it too, the rotations start going in wide circles, and the shapes start jumping all over the place. I know this might not be expressed in the clearest possible way, but any ideas of what is going wrong would be helpful.
The reason your shapes are making wide arcs is because you are applying your transforms in the wrong order. When you do any transformation, you multiply it by the current transformation; so if you translate before you rotate, you'll rotate from a new origin. Here's the order you should do the transforms in:
1) set the transform to the identity
2) translate to the final world position.
3) rotate to your local rotation.
4) scale to your local scale
5) translate to your local centerpoint.

if you're doing your transforms by multiplying beforehand, you'll want to prepend the transforms in that order. The local centerpoint is the point within your sprite that you want to do the scaling and rotating around; the centerpoint will be the pixel that ends up at the final world position.

p.s. don't do multithreading unless you're fully versed in distributed objects messaging and locking.

---Kelvin--
15.4" MacBook Pro revA
1.83GHz/2GB/250GB
Quote this message in a reply
suhbataar
Unregistered
 
Post: #6
OK, I got it together. I changed my model so that the axis of rotation is the same as the "position" point so that all rotations are around the origin of the shape. I tried using NSAffineTransform to use the rotations, but it didn't work. I then tried using the matrices instead and it worked perfectly. Maybe I'm doing something wrong, but there's something weird about how the rotations work. It maps both the points (0,1) and (1,1) onto (-1,0)...

I also added a second timer that takes care of user input, and the game is much smoother now. Thanks for your opinions.
Quote this message in a reply
Post Reply 

Possibly Related Threads...
Thread: Author Replies: Views: Last Post
  Run down of things I need to learn and tools needed jaked 11 3,798 May 7, 2009 04:54 PM
Last Post: AnotherJake