A Better Way to do Framerects.

Mar 3, 2010 at 5:15 AM
In my body, in my head
Forum Moderator
"Life begins and ends with Nu."
Join Date: Aug 28, 2009
Location: The Purple Zone
Posts: 5998
Alright, throughout my hacking work one thing that's bothered me in creating custom NPC entities is the framerects.
They just take up so much room, so inefficient! That's why today I sat down with a pencil and paper and devised a method
that I think should save tons of space, giving you freedom to use as many frames as you so desire on your entities.
Furthermore, this method is also easier in my opinion since you don't have to manually input each side,
rather the computer calculates most of it for you.

Code:
MOV EAX,[EBP+8]                          ;  C
MOV ECX,0F0                              ;  0F0 is the Left boundary of the frameblock
MOV EDX,[EAX+68]                         ;  +68, the frame #, or the column number of the image
SHL EDX,4                                ;  Here i'm shifting the offset by four because each frame is 16 pixels wide
ADD ECX,EDX                              ;  Add that to the previous to get our new Left side
MOV [EAX+54],ECX                         ;  Put it in it's place
ADD ECX,10                               ;  Now add the width of the frame, 16 again
MOV [EAX+5C],ECX                         ;  And put that where it goes
XOR ECX,ECX                              ;  Now to determine the up/down boundary. Here I XOR because the TOP is just zero
MOV EDX,[EAX+1C]                         ;  Use something like direction for the row #. +1C is just unused as near as I can tell.
SHL EDX,4                                ;  And shift again to move the appropriate height
ADD ECX,EDX                              ;  Now we have our top boundary
MOV [EAX+58],ECX                         ;  So it goes here
ADD ECX,10                               ;  Add another height
MOV [EAX+60],ECX                         ;  to get the bottom boundary
I'm not exactly sure, but I think that takes less room than declaring the rects of a single four-sided frame,
not counting the code at the bottom to put it into the right spots. With this method, you basically generate a
grid of rectangles for your frames. It works easiest with nice numbered widths and heights, but with a little creativity
you could make the frames just about any size rectangle I suppose. As near as I can see, the only downfalls are:

A) You have to have all your sprites aligned in a square/line/rectangle.
However, they oughta be that way anyway if you're doing things in a sensible manner.
B) Every frame must be the same size
C) Odd-sized frames could lead to some more challenging/space consuming calculations.

With this, however, it would take only a very small amount of code to produce an entity with an alphabet's worth of
frames that you could choose a letter from by <ANP the scriptstate and direction. If you wanted something like that :/

So, what are people's thoughts? Does this make sense?
 
Mar 3, 2010 at 5:33 AM
Been here way too long...
"Ha! Ha! Ha! Mega Man is no match for my Mimiga Man!"
Join Date: Jun 22, 2008
Location:
Posts: 251
Nice code! I was thinking about a way to do this, but I couldn't come up with anything that doesn't require the sprites to be rearranged. (I like creating better code that works with existing assets)

Very impressive!
 
Mar 3, 2010 at 7:14 AM
Not anymore
"Run, rabbit run. Dig that hole, forget the sun."
Join Date: Jan 28, 2010
Location: Internet
Posts: 1369
Age: 34
Granted, I've never really messed with NPC rects, but since you only have to insert one value for the left boundary initially and let a mostly automated process do the heavy lifting... much easier than defining each of the 4 rects by hand...

Thus, I can only say that this seems extremely useful for complex NPCs.
 
Mar 5, 2010 at 2:40 AM
In front of a computer
"Man, if only I had an apple..."
Join Date: Mar 1, 2008
Location: Grasstown
Posts: 1435
Noxid said:
Furthermore, this method is also easier in my opinion since you don't have to manually input each side,
rather the computer calculates most of it for you.
Does this mean you're storing them as (left,top,width,height) rather than (left,top,right,bottom), or do you mean something else altogether?
 
Mar 5, 2010 at 3:11 AM
In my body, in my head
Forum Moderator
"Life begins and ends with Nu."
Join Date: Aug 28, 2009
Location: The Purple Zone
Posts: 5998
Yeah, basically. The top and left aren't really stored but... just used, I guess? I don't really know the jargon that well. and height and width are what you multiply the row/column offset by, and also what you add...

So, Yup! L,U,W,H, and you don't store them in temporary variables but rather they're sort of hard-coded into your frame calculation.
 
Mar 6, 2010 at 6:41 PM
In front of a computer
"Man, if only I had an apple..."
Join Date: Mar 1, 2008
Location: Grasstown
Posts: 1435
Even if it's hard-coded, the values are stored somewhere in the executable. And what's that about height and width being multiplied by the row/column offset?
 
Mar 6, 2010 at 8:04 PM
In my body, in my head
Forum Moderator
"Life begins and ends with Nu."
Join Date: Aug 28, 2009
Location: The Purple Zone
Posts: 5998
Well, like I said, the terminology isn't so important to me as long as I know what it's doing. I'll try and explain it a bit more in depth I guess?

In the code I gave, lines 2 and 9 mark the origin of the sprite grid, in this case X= 0F0 Y= 0. In line 3, the column offset is stored in EDX so I can work with it. The next line multiplies EDX by 2^4, or 10 hex, because each frame I want to be 16 pixels wide. In other words, 10 is the width which is multiplied by the column number, to move the left side however many frames to the right. Next it's added to ECX Then it goes into it's place, and we add another width to ECX before we're done with it. The exact same process is applied to the height, where in line 11 we multiply by the height [2^4 again] and then add another 10 for the actual height.
 
Mar 6, 2010 at 10:12 PM
graters gonna grate
"Heavy swords for sale. Suitable for most RPG Protagonists. Apply now!"
Join Date: Jul 2, 2008
Location: &
Posts: 1886
Age: 31
So to make sure I understand correctly, the way this works is that instead of having to specify each framerect individually, you can just specify a grid of framerects and can then use any framerect from that grid. Is that about right?
 
Mar 7, 2010 at 2:21 AM
In my body, in my head
Forum Moderator
"Life begins and ends with Nu."
Join Date: Aug 28, 2009
Location: The Purple Zone
Posts: 5998
Yeah, that's it, simple as that.
 
Mar 7, 2010 at 1:53 PM
Senior Member
"This is the greatest handgun ever made! You have to ask yourself, do I feel lucky?"
Join Date: May 4, 2006
Location: Florida
Posts: 115
Age: 43
I was afraid this would happen.
I figured there were far more efficient ways to code the frame rects, specifically by calculating them on the fly. This will certainly allow for more room to modify behaviors. You cloud even take this a step further and convert this into a function that takes only a few parameters (initial location and sprite size). Though the frame rects get stored on the stack so a function call might screw that up. But even that could be worked around with some fancy stored addresses and jump calls.
The only problem I see with this is that it could essentially break any procedural attempts to pull the frame rects from the exe.
Still, great job Noxid.
 
Nov 28, 2010 at 3:57 AM
Been here way too long...
"Life begins and ends with Nu."
Join Date: Jan 4, 2008
Location: Lingerie, but also, like, fancy curtains
Posts: 3054
Noxid linked to this thread, and I saw wistils post, so here it is functionized, for better or worse:
Code:
push ebp
push edx
push ecx
mov ebp,esp
sub esp,10
mov eax,[ebp+8]
cdq
idiv [ebp+C]
mov ecx,eax
imul ecx,ecx,[ebp+14]
add ecx,[ebp+1c]
mov [ebp-10],ecx
add ecx,[ebp+14]
mov [ebp-8],ecx
imul eax,eax,[ebp+10]
add eax,[ebp+18]
mov [ebp-C],eax
add eax,[ebp+10]
mov [ebp-4],eax
lea eax,[ebp-10]
mov esp,ebp
pop ecx
pop edx
pop ebp
ret

55 89 E5 51 52 8B 45 08 99 F7 7D 0C 89 C1 0F AF
4D 14 03 4D 1C 89 4D F0 03 4D 14 89 4D F8 0F AF
45 10 03 45 18 89 45 F4 03 45 10 89 45 FC 8D 45
F0 5A 59 89 EC C3

Calling it:
Code:
push leftbound		// farthest left
push topbound		// farthest up
push width		// width of each frame
push height		// height of each frame
push columns		// number of columns before it wraps (ie, in a rectangle, this is how wide it is)
push framenum		// which frame to draw
call func
add esp,18
and then it returns the offset into eax for you to do as you will.

This may not work entirely atm, so just point out any silly (or grave) erros that I may have made.
 
Nov 28, 2010 at 2:12 PM
Pirate Member
"Heavy swords for sale. Suitable for most RPG Protagonists. Apply now!"
Join Date: Dec 26, 2007
Location: Lithuania
Posts: 1946
The way you explained it Noxid it looks a lot easier than it is.
 
Top