Thanks to KR155E’s demo (and the suggestion of using the older gccVB) I can finally start writing software for VB! Thanks a bunch!
I’ve been playing around with displaying BGMaps to the screen, but I realized that in order to do any work with small sprites, objects are what I should use. My question is… where do I start? I looked through libgccvb’s (the one that KR155E included with the demo) vbSetObject procedure, but I’m confused as to where to go next, can someone point me in the right direction? I know I should probably make an object world, but I’m totally lost as to where to go from there.
(Pretty soon, I’m going to want to start playing around with affine mode π )
I wouldn’t mess w/ using OBJs yet… BGMaps are easiest to use since you can set up a BGMap of large or small sizes, and move the entire image around by just changing a few parameters. OBJs are kinda a pain as you have to individually handle each 8×8 character, so if you have a 16×16 image in OBJs, to move it you have to individually move all 4 8×8 characters. The real advantage is that you can control many objects individually (1024 IIRC), where if you use BGMaps, you can only have 32 worlds, so it’s inefficient to waste a whole world on very small objects. But if you need less than 32 different things on the screen, and the images are larger than 8×8, then I’d recommend using BGMaps.
One type of game I could see OBJs being useful would be something like Robotron. This would have a lot of small characters (8×8 or less, and more than 32 of them) all individually going their own directions. A game where it wouldn’t be as useful would be something like the TMNT arcade game. This would have relatively few large characters (~64×32 and less than 32 on a screen at a time). That would be much easier to set each Turtle to it’s own world, and use a world or two for the scenery, and use the rest for enemies (it’d be limited to ~25 or so enemies at a time). It’s also inefficient to chunk that many OBJs together anyway, since with a max of 1024 OBJs, a 64×32 character would waste 32 (8×4) OBJs, which is just as limited as using the worlds (max of 32).
DogP
Have you tried the Wiki? If you have, try it again. I just finished editing it for clarity.
DogP’s post notwithstanding, I think there are definite uses for OBJs in a game. A large part of what makes “gamers” (i.e. those whose cable boxes are permanently set to G4TV :-P) ooh and ahh over modern games is the use of particle effects.
Some VB games (Panic Bomber, for one) already feature OBJ-based particle effects and there is no reason they can’t be used to great effect in homebrew, too, IMHO.
Also, as I hope my new Wiki article will show, it’s really not that confusing to use OBJs. Although, for particles and most other uses, I would steer clear of the “SetObject” routine. Using an optimized loop to edit OAM entries directly is a much better idea.
Make sure and post any specific questions if you still can’t get it working.
It’s basically the same thing slightly rearranged, but you’re quite welcome! π
One thing I was wondering is how often and how fast you can change backroung maps. Can you change a BGmap every frame?
The wiki helps a lot, but I have a clarification question…
If you create an object, using the vbSetObject procedure in libggcvb, It will create and object at the nth spot in OAM. When drawing worlds, the first object world only draws the last 256 objects in OAM. Does this mean that when using vbSetObject, you should start creating objects at n = 1024, and work your way backwards? Also, does this mean that in order to get to object #1, you have to have 4 object worlds?
I can see why you’d want to use BGMaps instead of OBJs for large sprites, but I’m still curious about OBJs. I also have some questions about display refreshes later.
Bruno:
You can write to any part of the VIP’s RAM (which includes Frame buffers, Chars, BGMaps, OBJs, Affine/H-Bias tables, and VIP Registers) any time except when it’s being accessed to draw the images displayed on the screen.
Here’s some code from the “vbSetWorld” function:
while (VIP_REGS[XPSTTS] & XPBSYR); // Edit the RAM
(It should probably be in vbSetObject, too… Also, it assumes the VIP is on {VIP_REGS[XPSTTS] & 2 == 2} and if not it will be an infinite loop.)
Fwirt:
1. The VIP does not work in 256 OBJ increments unless you set the SPTx regs that way.
2. It does not start at the “last” one (1023). It starts at whatever SPT3 is set to (it can be anywhere from 0 to 1023).
3. All 1024 OBJs can be drawn in one World; just set both SPT3 and SPT2 to 1023.
4. Check the Wiki again, because I just rewrote the “drawing procedure” explanation.
Hope that helps!
- This reply was modified 16 years, 6 months ago by RunnerPack.
RunnerPack and Fwirt: Yes, there definitely are good uses for OBJs (and I was also going to mention particle effects), and I didn’t mean to imply that they’re useless… I was just making a suggestion that if you’re just starting out, most “beginner” apps/games don’t need to make use of OBJs since they’re typically more complex/difficult to work with, and have fewer well documented examples of using them.
If you’re wanting to use them just for the sake of learning how to use OBJs, or if you have a specific reason that you want to use OBJs, that’s great… and just you bringing this up caused RunnerPack to update the Wiki with some good info… so thanks for that! I just wanted to make sure you’re not making it more complex than you needed to by thinking that BGMaps could only be used for Backgrounds.
DogP
Another retarded Bruno question:
Is there anyway to do HiBias on objects? And would there be any way to do hibias mode not only on the x axis but also on the y axis.
DogP: This is more just for the sake of learning how to use them. However, I was thinking of making a game that involves bullets for my contest entry, and I think that bullets are a good use for OBJs…
One more question I had about OBJs is… how DO you set the SPT# pointers? Is it as easy as SPT3 = 200? (That seems way too easy.)
Actually, I have a couple more questions, although they don’t necessarily pertain to objects. First: I’ve read a lot about changing palettes while the VB is drawing the screen. I was wondering, how can you tell when and where the VB is in the drawing process? Is there a register you can check? Secondly, since you’ve pointed out that BGMaps are a better idea for large sprites, would you accomplish animation by making a BGMap with all of the frames of your animation in it, and then just changing the MX/MY of the world to “play” the animation?
Bruno: I’m just a n00b, so I don’t know if I’m right about this, but from what I understand, the answer to both of your questions would be no. First of all, (correct me if I’m wrong) a world can only be an object world or an HBias world, not both. Secondly, because it’s HBias (not VBias) the shifting only works horizontally. There might be a way to implement software VBias, but it would likely be pretty complicated.
Bruno: Fwirt is right; neither H-Bias nor Affine transforms can be used on OBJs. But, the equivalent of “V-Bias” is exactly what Affine transforms are for. One way to accomplish rotation, for example, is to simply shear (think of turning a rectangle into a parallelogram) in first the X direction, and then the Y. When I understand Affine better, I’ll update the Wiki, unless someone smarter beats me to it π
Fwirt: Yes, you just have to set SPT3 to the first OBJ you want to show (i.e. the one with the highest number; usually 1023) and then set SPT2 to the one after the last one you want.
Then, you just have to fill in the OBJ data in the right sections of OAM and set a World to display OBJs. I’ve been updating the Wiki again; see if it makes more sense now.
Affine is nice and all, but hbias and vbias should be much faster to make some simple 3d worlds (look at DonkeyKong Country backrounds, imagin that in both directions). I actually found a demo for something like that, but it didnt have source code, and it was for some browser java stuff.
Bruno: Wait… I don’t think that you’re talking about HBias and VBias at all… I think that you just mean scrolling backgrounds? In order to do that, you just have to update the GX and GY values of whatever world you want to scroll (for example, decrease the GX value each step to make the background move left.) HBias is used to make the background look “wavy” by shifting each line left or right, not the whole background.
No, that would be just simple paralax scroll. Im talking about that special scroll that you can also do with HiBias (the water surfaces,etc… in the DKC backrounds)
Ahh…. I know what you mean now. Those DKC backgrounds do look rather cool. But RunnerPack is right, you’d have to use affine mode for that. Aside from affine mode, the only other way I can think of to get that effect would be to have a whole bunch of worlds layered on top of each other, and do a lot of parallax scrolling to achieve depth. That would use a whole bunch of worlds though, whereas affine only uses one.
Actually, to be honest, I did always wonder how they pulled that trick off in those DKC games.
Fwirt wrote:
Actually, to be honest, I did always wonder how they pulled that trick off in those DKC games.
The equivalent of H and V Bias is done on the SNES by using an interrupt that happens on every scanline. When the interrupt occurs, the scrolling registers (among others, like the palettes, etc.) are changed to make waves, etc.
I’m not an SNES dev’er, but I think this is how “Mode 7” effects work, too. (But I could be mistaken…)
Now it’s my turn to ask a question again. Here’s my code:
#include "libgccvb.h" #include "chartest.h" #include "maptest.h" //Screen is 384 X 224 int main() { int objX=0, objY=0; vbDisplayOn(); copymem((void*)CharSeg0, (void*)CHARTEST, 256*16); copymem((void*)BGMap(0), (void*)MAPTEST, 256*16); vbSetWorld(31, WRLD_ON, 108, 0, 76, 0, 0, 0, 168, 72); SPT3 = 0x100; SPT2 = 0x1; vbSetObject(2, OBJ_ON, objX, 0, objY, 9); vbSetWorld(30, WRLD_OBJ | WRLD_ON, 0, 0, 0, 0, 0, 0, 0, 0); vbSetWorld(29, WRLD_END, 0, 0, 0, 0, 0, 0, 0, 0); vbDisplayShow(); while(1) { if (vbReadPad() & (K_LR)) objX++; if (vbReadPad() & (K_LL)) objX--; if (vbReadPad() & (K_LU)) objY--; if (vbReadPad() & (K_LD)) objY++; vbSetObject(1, OBJ_ON, objX, 0, objY, 9); vbWaitFrame(40); }
But the compiler gives me the error “invalid lvalue in assignment” for both of the lines where i try to set the SPT pointers (lines 15 and 16). I also tried using decimal values, but I still got the error. Help?
Updated code:
#include "libgccvb.h" #include "chartest.h" #include "maptest.h" //Screen is 384 X 224 int main() { int objX=0, objY=0; vbDisplayOn(); copymem((void*)CharSeg0, (void*)CHARTEST, 256*16); copymem((void*)BGMap(0), (void*)MAPTEST, 256*16); vbSetWorld(31, WRLD_ON, 108, 0, 76, 0, 0, 0, 168, 72); VIP_REGS[SPT3] = 0x100; VIP_REGS[SPT2] = 0x1; vbSetObject(2, OBJ_ON, objX, 0, objY, 9); vbSetWorld(30, WRLD_OBJ | WRLD_ON, 0, 0, 0, 0, 0, 0, 0, 0); vbSetWorld(29, WRLD_END, 0, 0, 0, 0, 0, 0, 0, 0); vbDisplayShow(); while(1) { if (vbReadPad() & (K_LR)) objX++; if (vbReadPad() & (K_LL)) objX--; if (vbReadPad() & (K_LU)) objY--; if (vbReadPad() & (K_LD)) objY++; vbSetObject(1, OBJ_ON, objX, 0, objY, 9); vbWaitFrame(40); }
Look in the libgccvb.h file. Those constants near SPTx are used in the VIP_REGS[] array to get the real address.
Sorry for the confusion. (I guess it’s time for another round of updates to the wiki… Unless we change that in the new official library.)
Great! Thanks a lot! I have a good amount of programming experience, but not that much experience with C, let alone low-level C, so a lot of this is a whole new world to me. Luckily, it’s all been making sense so far.
RunnerPack, you deserve commendation for your work on the wiki. I was beginning to wonder if it would ever develop past an empty shell with quotes from David Tucker’s manual stuffed in it. Thanks to a lot of recent work, that’s changing!
Okay, I’m blowing the dust off of this topic.
While slowly working at getting Yoshi’s Cookie working, I’ve realized that unless I want to do some messy stuff with BGMaps, all the cookies are going to be constructed from objects. Reason: In Yoshi’s Cookie, the board seems to be made of a large grid of 8×8 tiles, with each cookie occupying 4 tiles (16×16). Unless I want to do some messy stuff with BGMaps, the easiest way to implement this seems to be to have a large grid of objects, and just modify their char references when necessary. I’ve already got that system working for the most part….
The problem is that the cursor (upper left corner) is doing some odd things. I have 2 object worlds, one for the cookie grid, and one for the cursor. This looks fine on the display, but when I check OBJ memory in Reality Boy Debug, one corner of the cursor always shows up in 2 banks of OBJ memory. What I mean by this, is that as my program is now, the lower right corner of the cursor is displayed not only in object set 2 (where it should be), but in object set 1 (not displayed) as well. I see this when I check objects in Reality Boy Debug. From what I know, It should be impossible for the same object to in 2 different object ranges (SPT2-SPT1 and SPT1-SPT0), so is this a glitch in my program, or in the emu?
Attachments: