![]()
![]() |
OBEYBREW.COM | Tutorials | A Crash Course In HuC Part 6 A Crash Course In HuCPart 6 - Of Bonks And Magic ScrollsStatic screens are fine for some kinds of games but for most, you're going to have to do mapped backgrounds. Lucky for you, mapped backgrounds are almost as easy as sprites. Almost.What You'll LearnYou're gonna learn tiles whether you want to or not. :P Yeah seriously... this one's all about tiles and mapping. There's way more material to cover than sprites though, which is why I saved this for later... hey look, it's now later. :)Getting PreppedOkay, now you're going to have to start investing hard drive space in tools and such. We're going to start small... yer basic map editor. For the purposes of this tutorial, I am utilizing mappy, which HuC has built-in support for. It's free to download and runs in Windows and WINE.mappy website Since you're going to learn about tiles, having a few tiles kicking around can't hurt, eh? Oh, and I've already made a map for you. Ain't I nice? Yes I am! Oh, and be sure you've got the bonkwalk.pcx file floating around somewhere from the previous tutorial, as we'll reuse it here. We won't be reusing the old code though... we're starting anew mostly... keep the old code around though, as we'll copy a few things out of it. Get This Party StartedStart up a new source the same way you've done before, and be sure to include the bonkwalk.pcx sprites. Let's keep calling it bonk so we don't get confused. Now, we're going to add a few new pseudoinstructions. Our first one is going to be loading the map we're about to use. It's a single pseudoinstruction:#incbin(levelmap, "tut6map.fmp"); Now, we need to load our tiles. Remember the last tutorial where we used incchr? Well, there's another version of that called incchr_ex and we're going to use it here. It's going to be a little weird-looking and it takes quite a few arguments. #incchr_ex(leveltiles, "tut6pal0.pcx", 0, 0, 69, 2, 0,\ "tut6pal1.pcx", 0, 0, 51, 1, 1}; Ok so that was a handful! What's next? Well, we have a map and tiles but we need palette data too. You already know how to use incpal... name them levelpal0 and levelpal1. We're going to set up a few variables now but we're not going to do it inside of main. And why not? Because they're going to be globals... meaning they will be accessible from anywhere in the program. Now, some of you more experienced C coders will be moaning and groaning over this, as it's traditional wisdom in C coding to avoid using globals unless necessary. However, in HuC land, globals are not only faster than local variables, they also tend to be more reliable. To make a global variable, we simply define it outside of a function. It's that simple. So then... we make one int variable... call it bonkx. Then, we're going to need a couple of char variables. As in the prior tutorial, we can call them tics and frame. As you've probably noticed from the source listings and whatnot from prior tutorials, you can put multiple variables of the same type on one line to save yourself some unneeded extra typing. Pretty darn convenient. Also, as a general rule, try to use char whenever possible, as it's the machine's native type and is a lil faster than int. Use int when you need a larger range of numbers, as char can only be 0 to 255 but int can be anywhere from -32768 to 32767. Care To Comment?Okay, we should probably hit an important detail at this point. Experienced C coders can skip this part but for you newcomers, pay 'tension. As you may have noticed, your programs are starting to get long. When your program gets big and contains a lot of functions and doodads, it can become easy to forget what stuff does. We're only human after all, so we need to be able to give ourselves lil reminders here and there. In coder jargon these are called comments and they look a bit like this:/* this is a comment */ /* this is a multi- line comment */ Bonk Is Back!Okay so let's get Bonk going again. The spr_make code from our last tutorials should serve you well here also, so copy n paste it. And again, do what ya need to do to get ole Bonk back on the screen... copy from the last tutorial if you don't remember what to do... the code will be the same here.![]() Really not much else needs to be stated here... just make sure you remember to load_vram and satb_update so we can see the lil... ok big... guy. Bonk's World RevisitedNow for the real fun... we're going to create Bonk's world... or a small portion of it, really... remember that sick pseudoinstruction up at the top, incchr_ex? Well, time to put it and the map to good use. The first thing we do is tell HuC that we're gonna be using a map.set_map_data(levelmap, 64, 28); set_tile_data(leveltiles); load_tile(0x1000); Now, we told HuC that we've got a map and we told it how big it is. Now we have to tell HuC's mapper to draw the map. This is also pretty easy to do... load_map(0, 0, 0, 0, 64, 28); ![]() Wtf okay... here's the deal: HuC automatically sets up some of the palette colors for writing text. It's kind of foolish but it is what it is. So anyway, what do we do? What are we missing? Oh yeah... background palettes. This time, we're loading two of them, and you should be able to figure out not only how to do this but also which palettes to assign. If you do it right, you will end up seeing this: ![]() That's more like it! What We DidOkay, without getting overly technical here... what we've done up to this point is load the entire map into the BAT (the Background Attribute Table). Of course, we can only see about half of it, so we need a way to scroll this map. How convenient for us that there's a function to do that for us, so let's see if we can make the whole map scroll for us with a little demo code...for(bonkx=0; bonkx<256; bonkx++) { scroll(0, bonkx, 0, 0, 223, 0xc0); vsync(); } ![]() So, what did we do? Well, we used the scroll function to... well, scroll the screen. It's really that simple. Okay, it's not that simple... but weve just seen the simplest way of doing it. scroll has a number of arguments that we need to be aware of. The first one is the 'window', so to speak... in HuC, we can define up to four of these... 0 to 3. We're using the first one here. The second argument is the X location of the virtual window and the third is the Y location of the virtual window. This might seem confusing at first... and it can be. But basically... think of it like this: you have a picture drawn onto a piece of paper. And then, you have a small box frame that you put over it. Now, assume that you are only looking at the part of the picture that you can see in the box frame. If you move the box frame around, you see different parts of the picture. That's exactly what these two arguments of scroll are doing for you... moving that box frame around. Now... the next two arguments are the top and bottom of the scroll... no, these have nothing to do with where the box frame is, but these tell us how tall that box frame is. 0 here tells us start at the very top and 223 tells us end at the very bottom. Technically, 223 isn't the real very bottom, but it's the acceptable bottom for most TVs and we wanna make sure people can see everything right now. The last argument is a weird one... it's a value that tells HuC what to display in this window. When we set it for 0xC0 (this is decimal 192 for you purists out there), it says 'show me both sprites and tiles'. We can turn these off independently by changing the value, but we have to set it to specific values... we can't just throw it numbers willy-nilly and expect to get meaningful results. We can set it to 0x0, 0x40, 0x80, or as we've seen, 0xc0. This is 0, 64, 128, and 192 respectively. 0x0 obviously turns everything off. 0x40 will make it so only sprites are displayed, and 0x80 will make it so only the background is displayed. Bonk Is Not An Ice-SkaterOkay, so Bonk looks kinda foolish just sliding around the ground as if he's trying to be Gilbert Fuchs. Remember the animation code from the previous tutorial? For kicks, let's add it to this tutorial too. I won't go into much more description as to what we're doing here, as not much else needs to be described. Update the loop with the scroll function in it with this code:for(bonkx=0; bonkx<256; bonkx++) { scroll(0, bonkx, 0, 0, 223, 0xc0); tics++; if (tics > 4) { tics = 0; frame++; if (frame > 5) frame = 0; if (frame == 0) spr_pattern(0x5100); if (frame == 1) spr_pattern(0x5200); if (frame == 2) spr_pattern(0x5300); if (frame == 3) spr_pattern(0x5200); if (frame == 4) spr_pattern(0x5100); if (frame == 5) spr_pattern(0x5000); } satb_update(); vsync(); } So... What's Next?By now, you should understand the basics of scrolling. It might seem as if this tutorial series is moving a little slow at this point but there really is a lot of stuff to cover and you gotta get it all before you get balls-deep into a project and then realize 'wtf I'm lost here!'. A few things you might have noticed... our map is limited to 64 tiles wide, or two screens. Not very impressive! We didn't do any controls here... I'm sure you wanted Bonk to walk manually through the map, right? If you've looked at the graphics, you'll notice that even though we told it to load 69 tiles wide, the image is actually 70 tiles wide and on the second set of tiles, we told it 1 high, but the image is really 2 high. What gives? Well, HuC likes graphics in multiples of 16 pixels. Don't even try to get around this. You'll fail. Even if the additional pixels aren't used, they still have to be part of the image file. The unused graphics will not be compiled into your project, so don't worry... there won't be any wasted space. If you're one of those people who likes to put a one-pixel border around every tile... break that ridiculous habit right now... HuC does not like this and you'll never be able to convince it to like it... it'll just stick its fingers in its ears and say 'nyah nyah I can't hear you!'So if you've made it this far, you're doing great. Feel free to open the map file in mappy and have at some editing to get the hang of it. Next, we're going to look at a more advanced concept of game design... the state machine. This is an essential building block for many many types of games. Also, we're going to get into just how those other games have maps so big by delving into scroll wrapping. After the next tutorial, you will literally have enough firepower to make a basic scrolling game of your own. So, pull up your asbestos underpants and get ready. :P Full Program Listing#include "huc.h" #incspr(bonk,"bonkwalk.pcx",0,0,2,8); #incpal(bonkpal,"bonkwalk.pcx"); #incbin(levelmap,"tut6map.fmp"); #incchr_ex(leveltiles,"tut6pal0.pcx",0,0,69,2,0,\ "tut6pal1.pcx",0,0,51,1,1); #incpal(levelpal0,"tut6pal0.pcx"); #incpal(levelpal1,"tut6pal1.pcx"); int bonkx; char tics, frame; main() { init_satb(); tics = 0; frame = 0; bonkx = 104; spr_make(0,104,153,0x5100,FLIP_MAS|SIZE_MAS,NO_FLIP|SZ_32x32,0,1); load_palette(16,bonkpal,1); set_color(256,0); load_vram(0x5000,bonk,0x400); satb_update(); set_map_data(levelmap,64,28); set_tile_data(leveltiles); load_tile(0x1000); load_map(0,0,0,0,64,28); load_palette(0,levelpal0,1); load_palette(1,levelpal1,1); for (bonkx = 0; bonkx < 256; bonkx ++) { scroll(0,bonkx,0,0,223,0xC0); tics++; if (tics > 4) { tics = 0; frame++; if (frame > 5) frame = 0; if (frame == 0) spr_pattern(0x5100); if (frame == 1) spr_pattern(0x5200); if (frame == 2) spr_pattern(0x5300); if (frame == 3) spr_pattern(0x5200); if (frame == 4) spr_pattern(0x5100); if (frame == 5) spr_pattern(0x5000); } satb_update(); vsync(); } } spr_make(spriteno,spritex,spritey,spritepattern,ctrl1,ctrl2,sprpal,sprpri) int spriteno,spritex,spritey,spritepattern,ctrl1,ctrl2,sprpal,sprpri; { spr_set(spriteno); spr_x(spritex); spr_y(spritey); spr_pattern(spritepattern); spr_ctrl(ctrl1,ctrl2); spr_pal(sprpal); spr_pri(sprpri); } See AlsoA Crash Course In HuC - Part 7 | incchr_ex | set_map_data | set_tile_data | load_tile | load_map | scroll |