Need your opinions on my stand-alone Cave Story game...

Old topic!
The last post in this thread is over 60 days old. Posting in this thread will be considered a bump, so please make an attempt to be courteous if you go ahead with it.

If the last post is over 6 months old, it may instead be a better idea to start a new topic. If you aren't sure about what to do, feel free to ask a staff member for help, or try to locate a 'general questions'-type thread if it exists in this (sub-)forum.
Feb 25, 2013 at 9:20 AM
Senior Member
"I, Ikachan. The Life and Documentary of the OrigiNAL SQuiD."
Join Date: Oct 29, 2012
Location: England
Posts: 178
Age: 22
Quote's jump is a bit weird, in Cave Story the game has very floaty jumping, you move up quite slowly in this version you go up a bit to fast.
When you only have a 1 block space usually n you jump hitting into the block above you get a good boost in speed and can do it quite rapidly, in this it is a bit
weird and slower.

Also, this is amazing, I do love GameMaker it is very underrated and most people I know who have seen it think it is weak and the only things you can do is the
drag and drop.

Awesome work as well, I was surprised at how well you have captured the game fell so far.
 
Feb 25, 2013 at 9:25 PM
Professional Whatever
"Life begins and ends with Nu."
Join Date: Jan 13, 2011
Location: Lasagna
Posts: 4489
I don't disagree that the scripting elements of Game Maker are pretty decent, but it's just that the common languages used in the field such as C++ and Javascript are so much more powerful.
 
Feb 25, 2013 at 9:44 PM
Senior Member
"I, Ikachan. The Life and Documentary of the OrigiNAL SQuiD."
Join Date: Oct 29, 2012
Location: England
Posts: 178
Age: 22
Yeah the it's basic and less powerful than most other outlets but as a starting tool it is probably the best, also don't need a powerful language to do great things, many amazing games were made in GameMaker
-Spelunky
-An Untitled Story
-Jumper Series

Also Iji but yes it is good if you don't have much experience. As long as you don't rely completely on the DnD aspect.
Yeah, I agree.

You forgot about Dustforce, which is one of the few Game Maker games that actually made it to be sold on Steam. I also believe that Pineapple Smash Crew was completed in Game Maker. I know that it started in Game Maker. Anyway, that game made it on to Steam as well, and both of those came before Steam GreenLight existed.
Yeah, forgot about those and Hotline Miami.
 
Feb 25, 2013 at 10:32 PM
Professional Whatever
"Life begins and ends with Nu."
Join Date: Jan 13, 2011
Location: Lasagna
Posts: 4489
Also Iji but yes it is good if you don't have much experience. As long as you don't rely completely on the DnD aspect.
 
Feb 26, 2013 at 12:25 AM
Senior Member
"Huzzah!"
Join Date: Nov 23, 2009
Location: ... I got nothin'
Posts: 219
Age: 32
This is awesome. It's good to see someone that uses Game Maker that knows a good amount on how to use it. Well done on this project so far!

I actually started out using tons of DnD in Game Maker, because Game Maker actually started out as strictly DnD (before YoYo Games, when it was just Mark Overmars), if I remember correctly. But about a year or two ago I decided to discipline myself to only use code, so the only DnD I do now is to call scripts.

Game Maker is actually a lot more professional and more powerful than most people realize. It's just that it doesn't force you to do things correctly, so you can be horribly inefficient and still have a game that runs. Still, GML is a scripting language, not a programming language, so it simply isn't realistic to expect to have TOTAL flexibility and the efficiency obviously suffers no matter what. But GM:Studio is supposed to be get a rewrite, introducing a LLVM which will make Game Maker a lot more efficient and more powerful, increasing code and game logic to roughly 10x faster (source is from the Game Maker Studio "roadmap").

@PixelVortex: You forgot about Dustforce, which is one of the few Game Maker games that actually made it to be sold on Steam. I also believe that Pineapple Smash Crew was completed in Game Maker. I know that it started in Game Maker. Anyway, that game made it on to Steam as well, and both of those came before Steam GreenLight existed.

The point is that Game Maker is powerful enough to make professional quality indie games.
 
Mar 5, 2013 at 9:26 AM
Senior Member
"Huzzah!"
Join Date: Nov 23, 2009
Location: ... I got nothin'
Posts: 219
Age: 32
I just played demo 3. It feels pretty nice. If you ever need help on things like platforms that you can jump up through and land on and that can be moving and/or sloped, or if you need help on programming solid slopes or icey surfaces (I know, Cave Story didn't have ice), etc. I have already made a platformer engine with those things, and I can give you the editable .gmk version (GM 8) if you'd like to check out the code. It looks like you're more than capable to do those things yourself, but I just thought that I'd throw that out there.

One thing I did notice is that you haven't taken into account for the big head and small body masks. The original Cave Story has a smaller collision detection zone for the body/feet than it does for the head. Yours appears to just be one large rectangle. The problem with this is that you don't fall off of a ledge as soon as you should. This is a pretty big issue if you want to make it as close to the original as possible. With your engine, even if the gravity, movement speeds, and jump height were all exactly like the original, you could still jump farther in your engine than you could in the original, because the mask for the feet on yours is wider than it is in the original. Also, enemies will hit you differently than in the original, if you use the existing mask for damage collision detection.

In my engine I mentioned above, I did big head and small body collision detection, because I was using a modded Cave Story Quote sprite as the main character. Unfortunately, the way I did masks was a bit messy as I used multiple images for my character's mask and switched between them. Perhaps you can pull it off more efficiently. Anyway, with a big head and small body, there are a few complications that arise. One is that you don't want to have your character land on the corner of a ledge and hang by his/her (Curly FTW!) chin. Pixel avoided this by pushing the character away from the block so you couldn't land with your head. The only way I could get this to work in Game Maker was to make my mask have multiple detection masks within it, because Game Maker wasn't being friendly to me with it's limited collision checking options. I had to have a left and right detection mask to account for this.

In the case that you find yourself needing help with Game Maker, feel free to send me a message. I know Game Maker pretty well and I'd love to at least try to help you out.
 
Mar 6, 2013 at 2:04 AM
Senior Member
"Huzzah!"
Join Date: Nov 23, 2009
Location: ... I got nothin'
Posts: 219
Age: 32
Very good. Couldn't have done it better myself.

I ran into an oddity though. When I first started out, Quote's feet were placed on the ground, but after traveling to the far right and then back again, I noticed that there was a pixel of space between Quote's feet and the ground. I tried jumping around a lot to see if it would revert, but I couldn't get Quote's feet back on the ground, no matter what I did. I restarted and tried again and got the same results.

EDIT: I ran another test. I figured out how to screw it up and revert it back at will. I did this simply by repeatedly knocking my head against a block as I fell (I can be a very violent person when I test games). So it has something to do with the head bumping that is causing it to mess up the mask placement or something. I don't know how you're coding it, so I can't really say, but I'm sure you'll figure it out.
 
Mar 9, 2013 at 10:09 AM
Banned
"It's dangerous to go alone!"
Join Date: Dec 29, 2012
Location:
Posts: 37

if isCollisionRightHead() or isCollisionLeftHead(){
while isCollisionLeftHead() {x+=1 y+=.5 if xVel<0 xVel=0 if frac(y)!=0 y+=.5}
while isCollisionRightHead() {x-=1 y+=.5 if xVel>0 xVel=0 if frac(y)!=0 y+=.5}}





Fixed by adding that frac part.



Thing is, mask wasn't screwed up.



Rounding the x/y values under which the sprite was drawn was screwed up.



http://www.youtube.com/watch?v=1PabHGdcKU0&feature=youtu.be







Neew videeo.



Edit: ...





It works.





Why does it work?


It's not supposed to work.



http://www.mediafire.com/?n9n5ole3giq0sa2



I actually made the damn weapon switch system work.





What.
 
Mar 11, 2013 at 7:36 AM
Lvl 1
Forum Moderator
"Life begins and ends with Nu."
Join Date: May 28, 2008
Location: PMMM MMO
Posts: 3712
Age: 28
FrozenFire said:
One thing I did notice is that you haven't taken into account for the big head and small body masks. The original Cave Story has a smaller collision detection zone for the body/feet than it does for the head. Yours appears to just be one large rectangle.
Actually no, the original cave story engine just has 1 rectangle for quote's hit box, both for collisions and damage. It's just smaller than his head/conforms more to his body than his head.
 
Mar 11, 2013 at 1:47 PM
Banned
"It's dangerous to go alone!"
Join Date: Dec 29, 2012
Location:
Posts: 37
Last time I checked, his head can't move inside of walls to fit in the mask width of his body.
 
Mar 11, 2013 at 2:58 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: 6000
The Core said:
Last time I checked, his head can't move inside of walls to fit in the mask width of his body.
I have no idea what this is supposed to mean but GIR is right.
 
Mar 11, 2013 at 5:21 PM
Senior Member
"I, Ikachan. The Life and Documentary of the OrigiNAL SQuiD."
Join Date: Oct 29, 2012
Location: England
Posts: 178
Age: 22
I have no idea what this is supposed to mean but GIR is right.
He is saying that if the hit box was for Quote was made to fit more closely to the body then Quote's head should be going inside the edges of the tiles when you run into them, due to their being no hit box there.

@The Core
I agree with GIR as well, I am not going by any numbers but from what I can see in-game, by running into walls and such, his hit box should be about 9x10px width and 15px height.
 
Mar 11, 2013 at 6:03 PM
CARLSOOOOOON AAAAND PEEEEETERSSSSSS!
"Wacka-Wacka-Wacka-Wacka-Wacka-Wacka-Wacka-Wacka-BLEIUP"
Join Date: May 21, 2012
Location: Location Location. Thats my motto.
Posts: 304
Age: 24
I've tried to play the newest version of the build, but when I started the exe, it screwed everything up and I could only see the bottom right of the window(and may I mention that it made my start menu button look 20 sizes too big?)
 
Mar 12, 2013 at 9:08 AM
Senior Member
"Huzzah!"
Join Date: Nov 23, 2009
Location: ... I got nothin'
Posts: 219
Age: 32
GIRakaCHEEZER said:
Actually no, the original cave story engine just has 1 rectangle for quote's hit box, both for collisions and damage. It's just smaller than his head/conforms more to his body than his head.
I'll take your word for it, because I'm guessing you or someone else has gotten into the game code and have seen how it works. I was just going by how the head acted in contrast to the body, as it pushes Quote away when his head hits a platform edge when falling downward past it, and I made the wrong conclusion based on how Game Maker does things with it's crappy collision and lack of specific precision checking. As far as I know, Game Maker can't accomplish this in the way that Pixel did. At least, not with a single rectangular image mask collision; it's just not possible to do without having lots of collision bugs. However, if you eliminate image masks in Game Maker and only go only by x and y coordinates, then you can do all your collisions just fine, you just can't use Game Maker's built in collision system when you go that route. It's a far better way to go without using the limiting image masks, but I didn't suggest it because I really didn't think about it until now.

EDIT: Actually, I just randomly thought up a way to use Game Maker's built in collisions and only use ONE collision mask. You simply make it the height of the head and the width of the feet and place it in the middle of the head. If anyone uses Game Maker they will understand why you would need to do this because simply by checking if there is a solid at x+1, it will check x+1 on ALL y positions that the image takes up. There is no way to check only a certain y position of the image, it will always include all y positions of the mask. I'd explain it further, but it seems like The Core is doing just fine as is. Yeah, I think I'm going to be working on moving on from Game Maker, probably to SFML or something.
 
Mar 13, 2013 at 3:59 AM
Banned
"It's dangerous to go alone!"
Join Date: Dec 29, 2012
Location:
Posts: 37
Does anyone have the source code to Pixel's dialogue/text box?
 
Mar 13, 2013 at 4:04 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: 6000
yeah sure
Code:
void renderTextbox()
{
    Rect clipRect;
    Rect frameRect = {0,0,488,16};
    //get xBase and yBase
    int xBase = 77;
    int yBase, i;
    if (msgState & 1) //if the message box is at the top
        yBase = 40;
    else
        yBase = 348;

    clipRect.left = xBase + 17;
    clipRect.right = clipRect.left + 460;
    clipRect.up = yBase + 16;
    clipRect.down = clipRect.up + 96;
    if (msgState & 0x40) { //show the box
        rectBlit(BMP_TEXTBOX, frameRect, xBase, yBase);
        frameRect.up += 16;
        frameRect.down += 16;
        for (i = 1; i < 7; i++)
            rectBlit(BMP_TEXTBOX, frameRect, xBase, yBase + i*16);
        frameRect.up += 16;
        frameRect.down += 16;
        rectBlit(BMP_TEXTBOX, frameRect, xBase, yBase + 0x70);
    }
    if (msgState & 0x80) { //show the text
        frameRect.up = 0;
        frameRect.right = 460;
        frameRect.down = 20;
        int currentRow; //current row -> the current top row

        if (textRow > 2)
            currentRow = (textRow-2)%4;
        else
            currentRow = 0;
        //offset the text from the face
        int txtOff = 20;
        if (currentFace)
            txtOff += 100;
        //update the face position
        if (facePos < 90)
            facePos += 16;
        //update text position
        if (textOffset > 0)
            textOffset -= 3;
        for (i = 0; i < 4; i++) { //for each thing
            clipBlit(BMP_TEXT1 + currentRow, frameRect, xBase + txtOff, yBase + (LINE_SPACING * i) - 12 + textOffset, clipRect);
            currentRow++;
            if (currentRow > 3)
                currentRow = 0;
        } //for each text obj.
        //render the face
        if (currentFace) {
            int faceSize = 96;
            frameRect.left = (currentFace % 6) * faceSize;
            frameRect.up = (currentFace / 6) * faceSize;
            frameRect.right = frameRect.left + faceSize;
            frameRect.down = frameRect.up + faceSize;
            clipBlit(BMP_FACE, frameRect, facePos, yBase + 12, clipRect);
        }
        //render cursor blip
        if (!(msgState & 2)) {
            frameRect.left = 476;
            frameRect.up = 64;
            frameRect.right = frameRect.left + 12;
            frameRect.down = frameRect.up + 20;
            if ((blipTimer++%20)>12) {
                if (tscState == 2) {
                    int lastRow = textRow;
                    if (lastRow > 2)
                        lastRow = 2;
                    int blipX = FONT_WIDTH * (textColumn+1) + xBase + txtOff;
                    int blipY = yBase + lastRow * LINE_SPACING + 20 + textOffset;
                    clipBlit(BMP_TEXTBOX, frameRect, blipX, blipY, clipRect);
                }
            }
        }
    }//if showText


    //render yes/no box
    if (tscState == 6) {
        frameRect.left = 304;
        frameRect.up = 96;
        frameRect.right = frameRect.left + 160;
        frameRect.down = frameRect.up + 64;

        rectBlit(BMP_TEXTBOX, frameRect, 434, 288);

        frameRect.left = 224;
        frameRect.up = 176;
        frameRect.right = frameRect.left + 32;
        frameRect.down = frameRect.up + 32;

        rectBlit(BMP_TEXTBOX, frameRect, 422 + 80*selectionCursor, 308);
    }
}
 
Mar 13, 2013 at 4:17 AM
Banned
"It's dangerous to go alone!"
Join Date: Dec 29, 2012
Location:
Posts: 37
... Damn, lots of variables to define. Are you sure that's all there is to the message box code? Besides rendering?


clipBlit(BMP_TEXT1 + currentRow, frameRect, xBase + txtOff, yBase + (LINE_SPACING * i) - 12 + textOffset, clipRect);

BMP_TEXT1, need more info on that.
 
Mar 13, 2013 at 4:54 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: 6000
well there's also the TSC portion
Code:
            case TSC_NO:
                if (msgState & 0x80) {
                    if (msgState & 2) {
                        //count
                        int length = 0;
                        char c = -1;
                        while ( (c = currentCommand.string[msgPos + length]) ) {
                            if (c == '\r') {
                                break;
                            }
                            length++;
                        }
                        char* messageStr = new char[length+1];
                        memcpy(messageStr, ¤tCommand.string[msgPos], length);
                        messageStr[length] = 0;
                        writeTextTo(BMP_TEXT1 + (textRow+1)%4, messageStr, textColumn*FONT_WIDTH, 0);

                        if (c == '\r') {
                            msgPos += length + 2;
                            eventPos--;
                            textRow++;
                            if (textRow > 2) { //if we need scrolling
                                textOffset = LINE_SPACING;
                                clearBitmap(BMP_TEXT1 + (textRow+1)%4);
                            }
                        } else {
                            msgPos = 0;
                        }
                        textColumn = 0;
                        delete[] messageStr;
                    } else {
                        char next[4];
                        bool wide = false;
                        next[0] = currentCommand.string[msgPos];
                        next[1] = currentCommand.string[msgPos+1];
                        next[3] = '\0';
                        if(next[0] & 0x80){
                            next[2] = '\0';
                            wide = true;
                        }
                        else{
                            next[1] = '\0';
                        }
                        if (next[0] != 0) {
                            textColumn++;
                            if (next[0] == '\r' || next[0] == '\n') { //carriage return
                                msgPos += 2;
                                textRow++;
                                if (textRow > 2) { //if we need scrolling
                                    textOffset = LINE_SPACING;
                                    clearBitmap(BMP_TEXT1 + (textRow+1)%4);
                                }
                                textColumn = 0;
                            } else { //character
                                playSound(SFX_fx_msg);
                                if (next[0] != '=') {
                                    writeTextTo(BMP_TEXT1 + (textRow+1)%4, next, textColumn*FONT_WIDTH, 0);
                                } else {
                                    Rect circRect = {128, 96, 140, 108};
                                    blitTo(BMP_TEXTBOX, BMP_TEXT1 + (textRow+1)%4, circRect, textColumn*FONT_WIDTH, 4);
                                }
                                if(wide){
                                    textColumn++;
                                    msgPos+=2;
                                }
                                else{
                                    msgPos++;
                                }
                            }
                            eventPos--; //keep the event position where it is until we're done here
                        } else { //reached the end of the string
                            msgPos = 0;
                        }
                    }
                }
                stopParse = true;
                break;


#define BMP_TEXT1 30
#define BMP_TEXT2 31
#define BMP_TEXT3 32
#define BMP_TEXT4 33

spriteArray[30] = new SpriteSet(460, 20); //textbox line 1
spriteArray[31] = new SpriteSet(460, 20); //textbox line 2
spriteArray[32] = new SpriteSet(460, 20); //textbox line 3
spriteArray[33] = new SpriteSet(460, 20); //textbox line 4
they're array indexes
 
Top