Original Post

Consider Insect Combat and Legend of Helga dead for now. While trying to figure out a game that uses absolutely NO random numbers that I could do, I finally found one: ChuChu Rocket. For those that don’t know, it’s a puzzle game where you guide a mouse in a maze to a rocket using arrows that you put in. Think Chip’s Challenge-like structure. I tried to put together a simple demo, but I’m having trouble with collision detection with the mouse (which is just a square for now). For collision detection, I copied the code from GoSub into this program, and it doesn’t want to work (the square mouse simply ignores the boundary.) It’s supposed to be every time the mouse hits a wall, it turns right. Everything is set up 16×16: the blocks used for the boundary and the mouse. Any thoughts as to why the collision detection code isn’t working?

17 Replies

Because you’re testing for the value of a BGMap cell, but to perform movement you’re moving the World itself (with GX and GY).

Other problems include:

1. Still using spaghetti code (goto label)
2. Reinitializing the VPU every time through the loop
3. Copying the Char/BGMap data to the VPU every time through the loop
4. Moving, then testing for collision, then moving again if collision detected

I would use a u8 array (or array of arrays) to store the levels and use the graphics data for what it is: graphics data.

Sounds like a good game to work on, though. Are you just going to translate the levels, try to make up your own, or both? What about coming up with new hazards/puzzle elements (its been forever since I played it, so I can’t suggest any :-P)

Looking forward to the finished product!

OK, I got rid of the goto thing and cleaned up the code a little. But what I don’t understand are the terms GX and GY. I thought I was doing the exact same thing in GoSub, and it worked that time. I checked the code to make sure all the numbers were in the right places when I set the worlds. Also, to have more than one block, I’m using different levels for the different blocks. Is there a different and better way to do this?

That looks a lot better (going a little heavy on the whitespace, but I can’t fault you for that).

It only takes a quick look in libgccvb.h and the wiki, but here is a quick run-down of vbSetWorld:

vbSetWorld(#, flags, GX, GP, GY, MX, MP, MY, W, H);

#: The World number to modify
flags: Visibility, BGMap number, Mode, etc.
GX: The horizontal position of the upper-left pixel of the World
GP: The parallax offset of the World
GY: The vertical position of the upper-left pixel of the World

MX: The horizontal position of the upper-left pixel of the source rectangle
MP: The parallax offset of the source rectangle
MY: The horizontal position of the upper-left pixel of the source rectangle

W: The width of the source rectangle, minus 1 (e.g. 383 for full-screen)
H: The height of the source rectangle, minus 1 (e.g. 223 for full-screen)

I found another problem: you’re not setting an end World. The first unused World should have the WRLD_END flag set, otherwise, every World will be drawn, wasting time and, on hardware, probably generating random garbage on screen.

I’m not sure about your terminology, but, if I understand you right, it’s actually a good idea to use different Worlds for different layers of the level (obstacles, “mice”, etc.).

What I was referring to in my first post was the practice of accessing the BGMap data to see what to collide with. It will be much more robust and “future-proof” if you use a map stored in a smaller format (like an array of unsigned chars) and use that for both collision testing and generating the BGMap data. Like so:

static const u8 level_one[16] = {
    1, 1, 1, 1,
    1, 0, 0, 1,
    1, 0, 0, 1,
    1, 1, 1, 1,
};

The real one will be much bigger, but you know what I’m getting at… You can also use an array of arrays, like so:

static const u8 level_one[4][4] = {
    { 1, 1, 1, 1 },
    { 1, 0, 0, 1 },
    { 1, 0, 0, 1 },
    { 1, 1, 1, 1 },
};

Also, that will not be sufficient for a complete level description. There will likely be some other data associated with a level. For that, you should use a struct. Any good C tutorial will help you with that.

Hope that helps!

I finally got a little demo working. Press the left + pad to move the cursor and A to place a block. The mouse will always turn right when it hits a block or the side. This isn’t how ChuChu Rocket actually works (in ChuChu Rocket, the blocks have arrows on them), so my level designs will have to be a little different than the actual ChuChu Rocket levels in the game. Right now you can only put 2 blocks on the board. And yes, I’ll be designing new levels for this game.

Attachments:

Is it supposed to work in Reality Boy?

When I tried it I could move anywhere and also outside the box. Perhaps it doesn’t matter for now…

I could only place two blocks and it’s also possible to place them outside the box.

Yep, it’s supposed to work that way. The next step is defining the borders, but right now, you can place the blocks anywhere. Oh, and if anyone wants to draw up a nice mouse sprite for me, go ahead.

Many changes:
+borders defined
+instead of a rocket, there is cheese
+puzzle #1 set up.

In puzzle #1, you can only use one block, so use it wisely. To make the mouse start moving, press Start.

The tentative title for this game: “Nice Mice”.

Also, I had to use a goto statement in order to make this work. Can anyone tell me how to make it work without it?

Attachments:


Or grab the “Little Mickey Mouse”-frames from that animation on this page:
http://yahoofreak.com/cartoon-animated-emoticons

VirtualChris wrote:
Also, I had to use a goto statement in order to make this work. Can anyone tell me how to make it work without it?

Just put your “while(1)” loop contents in a loop with an exit condition and put that and the “level_start” code inside the “while(1)” loop–which should actually be a “for(;;)” loop, I’ve been told, since it skips the superfluous testing of 1 each time through. Here’s an example for the inner loop:

int keep_looping = -1;

while (keep_looping) {
.
.
.
    if () keep_looping = 0;
}
I think you’re a very talented programmer, you just need to spend some time with a good C reference and try to absorb what the language has to offer. You’re good at knowing what needs done, you just need a larger vocabulary of tools and constructs with which to do it. I like that you used a function to check the BGMap (which I distinctly remember telling you to change 🙁 ;-)) but you need to carry that through to the rest of the code. Encapsulation is one of the keys to efficiency and re-usability (not to mention readability…).

Keep at it!

  • This reply was modified 14 years, 10 months ago by RunnerPack.

OK, but what if there’s two exit points, like in my example shown below? (by the way, the game *is* playable in its current form, so tell me what you think of level 2. Too hard? Too easy?)

Attachments:

In that case, I’d put the inner loop inside a function that returns a different value depending on where the game should go next. You can then test the return value inside your main infinite loop:

void main() {

    int next_part = 0;
    int level_num = 0;

    initialize();

    for (;;) {

        switch (next_part) {
        case 0:
            next_part = start_level(level_num);
            break;

        case 1:
            next_part = level(level_num);
            break;

        case 2:
            level_num++;
            next_part = 1;
            break;
        }
    } // Loop until power-down

}

int initialize() {
    // Stuff you have before the while(1) loop
}

int start_level(int level_num) {
    // Stuff you have between level_start: and level_reset:
    return 1;
}

int level(int level_num) {
    for (;;) {

        // Stuff you have after level_reset: (except testing the map array instead of the BGMap!)

        if (win_condition) {
            return 3;
        } else {
            return 2;
        }
    }
}

VirtualChris wrote:
OK, but what if there’s two exit points, like in my example shown below? (by the way, the game *is* playable in its current form, so tell me what you think of level 2. Too hard? Too easy?)

I tried it, perhaps the cursor could be just a thin line instead of looking the same as the blocks? The mouse moves really slow… Wasn’t there supposed to be a cat as well?

I haven’t figured out the solution yet, you can only place two blocks and then it’s supposed to get to the cheese.

What are the limits of the mouse’s movements, how does it move?

The mouse moves right when it hits an intersection. To place a block, press A. Pressing B undoes the previous block. Start makes the mouse move. Select resets the level. There is no cat in my game. I can make the mouse speed up if you want me to.

OK, after a long hiatus, I have returned to work on this. I changed the code a bit because I had no idea what it was doing since I worked on it last. Level 1 is new, and level 2 is what used to be the old level 1 (which I found a shortcut to, so now you have only one block instead of two.) Controls: B = place block, A = remove last block, START = begin moving mouse, SELECT = start level over again, left control pad = move cursor (which now blinks.)

Attachments:

You only need one block on the first level as well.

You should write something when you clear the second screen… 😉

What’s the solution to level 1 using only one block?

I sent a PM.

 

Write a reply

You must be logged in to reply to this topic.