Rotate and Midhandle?

Monkey Forums/Monkey Programming/Rotate and Midhandle?

zoqfotpik(Posted 2013) [#1]
I need to draw a rotated imagerect from a spritesheet.

My sprites are 48*48 pixels wide. They are arranged in squares on the sheet.

The following function is a wrapper so I can specify tile x and y coordinates instead of having to specify the x and y of each individual sprite in pixels on the sheet.

I wish to set image.midhandle to the center of the desired sprite, on draw (spritesheet tilex + 24, spritesheet tiley + 24).

But it's not functioning as desired. It's rotating around a point which I would guess to be 0,0 on the spritesheet. Ideas?

Function DrawGameSprite(image:Image, x:Int, y:Int, sheetx:Int, sheety:Int)
	image.SetHandle(sheetx * 48 +24, sheety * 48 +24)
	DrawImageRect(image, x, y, sheetx*48, sheety*48,48,48,0)
End Function



darky000(Posted 2013) [#2]
From what I understood from the Help file. It creates an offset of the image handled so SetHandle should be created inside your GrabImage or LoadImage.

On your GrabImage for example:
Field obj:Image

...

obj = GrabImage( x, y, width, height, frames, SetHandle(24, 24))


Then in your function
Function DrawGameSprite(image:Image, x:Int, y:Int, sheetx:Int, sheety:Int)
	DrawImageRect(image, x, y, sheetx*48, sheety*48,48,48, 0)
End Function


Although what you are doing is the same as what MidHandle does. We can change your GrabImage statement to this:
Field obj:Image

obj = GrabImage( x, y, width, height, frames, Image.MidHandle)



zoqfotpik(Posted 2013) [#3]
I'm actually not using grabimage. On game create, should I grabimage each individual 48x48 sprite into its own image object? Wouldn't that result in slowdown from sprite swapping?

Understand that the way I'm doing it, I am addressing a different portion of the image with every sprite draw, so the imagehandle needs to be set anew each time.


darky000(Posted 2013) [#4]
What are you using?

Yes. If you want your objects to have an image. What do you mean by sprite swapping? If you have your spritesheet(atlas) loaded on OnCreate, then grabbing sprites won't be an issue that much.


BigAnd(Posted 2013) [#5]
If you just set the mid handle on your sprite sheet to 24,24 it will work. You don't need to add the offset to where your sprite is in the sprite sheet.


dawlane(Posted 2013) [#6]
Try doing it this way. Note this is part of a sprite class I wrote while back. The location and size of the sprite (and frames) in a atlas are stored in an array. You should be able to adapt it to you needs.




Gerry Quinn(Posted 2013) [#7]
GrabImage is your best friend in situations like this.

Don't draw from raw sprite sheets unless you know you will always be happy with a top left handle. If you're scaling or rotating, don't even think about it.


skape(Posted 2013) [#8]
I'm actually not using grabimage. On game create, should I grabimage each individual 48x48 sprite into its own image object? Wouldn't that result in slowdown from sprite swapping?

The image object created from GrabImage uses the same texture reference as the original sheet, so all images grabbed should use the same draw... (At least I believe that's what we determined a while back.)


zoqfotpik(Posted 2013) [#9]
I was under the impression grabimage created a new object. I also thought it was terribad slow. I will take another look, thanks gents!


Gerry Quinn(Posted 2013) [#10]
GrabImage does create a new Image object. But the graphic data referred to by this object is just a square of the graphic data of the parent object. So it does not add anything to video memory.

The important definition of "slow" is "makes my framerate or other user-visible parameters too low". Clearly GrabImage does not fit this definition in all cases. I would guess that it fits it in very few cases.

If you convert 100 sprites from a spritesheet to individual images, all that means is that you assign about 5K of normal RAM to store the grabbed image objects, and there's a little extra arithmetic for the CPU when it is going from your DrawImage() command to an instruction to the graphics controller to blit some data to the back buffer.


zoqfotpik(Posted 2013) [#11]
I guess I am still going by the Blitzmax grabimage which I found very slow. You can see it in my image recursion code snippet on the max forum. There may have been some other reason for that. Some others claim the demo is silky smooth for them but probably they have newer cards than my GeForce 8800GTS which is still running great considering I got it in 2007...

Looks like Dawlane's method (no pun intended) is what I'm going to go with. My draw was working but I was just not understanding the handling of matrices...


Shinkiro1(Posted 2013) [#12]
Don't let the BlitzMax GrabImage confuse you. It does something completely different.
When you use GrabImage in monkey the overhead is that you create 1 new object. Think of it as if you are creating a Vector Object, performance wise it's practically the same.


zoqfotpik(Posted 2013) [#13]
Yes, I see that now Shinkiro. There are probably some very interesting uses for this...

I have tried with Grabimage and nothing shows up when I try the draw. And of course as soon as I typed that I immediately saw what the problem was and fixed it within 30 seconds of typing it.

Grabimage needs a frame parameter of at least 1.

The final draw commands that I used were as follows.

PushMatrix
Translate 100,100  ' this is where I was drawing to
Rotate ticks
DrawImage(testsprite,0,0)
PopMatrix	


This resulted in the desired behavior. As I do with everything I will write a small wrapper function for this. I was not able to understand the reason for the misbehavior on the default DrawImage command-- when trying the draw with x and y in the DrawImage without a prior translate statement, the rotate was thrown out of whack, it looked like it was trying to rotate around 0,0 in the final image.

But hell with it, it works fine for my purposes now.


Gerry Quinn(Posted 2013) [#14]
Just as an addendum, I was just now working on something where I had to use DrawImageRect() anyway, and rotate the images.

I found that if I set the handle (of the complete image) to where it would be if the image was just the rectangle before each draw, it seemed to work.

In otherwords:

image.SetHandle( wRect * 0.5, hRect * 0.5 )
DrawImageRect( image, xScreen, yScreen, xRect, yRect, wRect, hRect, rotation, scalex, scaley )

Just thought it might be useful to know... I guess DrawImageRect() is less awkward than I had thought!

[I tried to do something with the handle on the off-chance it would work, before I started wading into matrix transforms.]