Jump to content

  • Log In with Google      Sign In   
  • Create Account

DekuTree64

Member Since 29 Aug 2000
Offline Last Active Sep 25 2014 10:49 AM

#5177600 For-loop-insanity

Posted by DekuTree64 on 02 September 2014 - 12:51 AM

Classic mistake. There is a generic way to make it work, if you really want to, though:

uint8_t j = 0;

do
{
  printf("%i\n", j);
}
while (j++);

Which is pretty readable, since the while loop is clearly going to terminate as soon as j overflows. And like Ravyne said, it doesn't really make anything faster in general, that said I personally don't see this as an optimization tactic, but more as a type correctness thing, in other words, the loop variable is going to be used as an 8-bit unsigned integer, so let's not lie to ourselves, make it an 8-bit unsigned integer. But with this comes the responsibility of watching out for overflow and other low-level things which generally don't come up when simply using a sufficiently large signed integer like int, people will have their own opinions on that matter smile.png

Don't you mean ++j?

 

I just tried it on ARM7, which has only 32-bit registers, and it compiled to a compare with 256, branch if not equal. So it doesn't actually force the wrapping, but did get the logic correct, and no different than using an int and comparing with 256.




#5173199 Can't solve problems without googling?

Posted by DekuTree64 on 12 August 2014 - 04:31 PM

Lots of good answers here. I especially like Glass_Knife and phantom's.

 

Another thing you can do is read just the overview of the solution, and try to work out the details yourself, but with a chicken exit if you need it.

 

Also, don't be afraid to solve the same problem more than once :) Sometimes when you have a large and complex challenge, you just have to dive head first into it and make a big mess of code. Then refactor and it looks a little better. But with your deeper understanding of the problem, you might be able to approach it from a different angle and come up with a more elegant system overall.

 

A good example for me is side scroller collision detection with slopes. It seems so simple, and often it is, depending on how many cases you want to handle. But it can get really complicated if you want to support slopes steeper than 45 degrees, sloped ceilings, not having off-by-one problems between left and right slopes, colliding the center of your rectangle with the slope but corner when standing at the edge of a solid tile, etc. I finally managed a system that does everything I want, but it's not quite the level of elegance I want to reach before writing an article series on it (because all the articles I've read don't solve it completely). So one more iteration, one of these days :)




#5147238 How to stop users from manipulating Game Save Data

Posted by DekuTree64 on 15 April 2014 - 06:48 PM

First thing, don't make it so readable tongue.png Use meaningless labels, and no newlines so it's a pain to find the number you're after.

 

Second, do some sort of encryption on the numbers (could be as simple as differential encoding, so changing one number modifies everything after it).

 

For a single player game, there's no need to prevent save hacking... just deter it so the player doesn't feel like they're wasting time by playing the game when it would be so easy to type in a number. If anyone cares enough to make a save editor tool, let them have their fun.




#5146917 I need help with matrices

Posted by DekuTree64 on 14 April 2014 - 09:20 AM

Not meaning to hijack the thread, but I suspect using matrices would help me too.

 

I have a camera class, it has this simple function to apply it.

//Some weird shit going on here
//Old comment but kept for lols
void Camera::ApplyICam()
{
  glRotatef(-m_rotation.m_xValue*180/PI, 1.0, 0.0, 0.0);
  glRotatef(-m_rotation.m_yValue*180/PI, 0.0, 1.0, 0.0);
  glRotatef(-m_rotation.m_zValue*180/PI, 0.0, 0.0, 1.0);

  glTranslatef(-m_position.m_xValue, 
               -m_position.m_yValue, 
               -m_position.m_zValue);
}

 

 

My object class also stores position and rotation as two 3 dimensional vectors. Using this system I can move my camera and view my objects just fine, the problem comes when I want to rotate the object.

 

Doing a simple initial rotation is easy, I simply set my m_rotate in object, my question is how to rotate my object after this initial rotation. Say we have an aircraft and I want the plane to bank left aka roll anticlockwise along it's central axis by say 15 degrees. I am unsure how to calculate this rotation given that the plane is no longer aligned along one of our axis, it has its own arbitrary axis. Simply put I cannot figure out how I need to alter my initial rotation.

 

Here is part of my code showing the order of transformations

  glLoadIdentity();
  cam->ApplyICam();
  obj->AddRotation(0.0, 0.025, 0.0);
  obj->ApplyTransformations();
  obj->GetMesh()->DrawMesh();
  cam->ApplyICam();

This code correctly draws my object in position, spinning around the y axis by 0.025 per frame. What I want to know is how to make my object bank as described above, no matter how it happens to be rotated at the time.

 

I am sorry for the poor description, I have always had a hard time visualizing these rotations 

This is where you get into "incremental rotations". Store the aircraft's orientation as a matrix (or quaternion), and when the player wants to turn, generate a pitch, yaw or roll matrix with the small angle delta (your 0.025 value) and multiply the orientation by it. So for example a yaw rotation will rotate around the plane's current up axis, modifying the X and Z axes in the process. Then next time you want to do a pitch rotation, it will be around the modified X axis..It doesn't really matter what order you do them in if the player wants to rotate around multiple axes at the same time, since the change is so small each frame.

 

It can be more tricky at first, working with the orientation as a matrix/quaternion rather than angles, but it's actually easier once you get the hang of it. For example, if you want to move the plane forward, just multiply a vector (0,0,speed) by the orientation, and add it to the position.

 

And don't forget to re-normalize/orthogonalize the orientation periodically to correct any numerical accuracy problems that accumulate.




#5128303 "Oh God, Who Wrote This?", "You Did", "Wait? I wrote Thi...

Posted by DekuTree64 on 02 February 2014 - 08:22 PM

laugh.png That is indeed horrible. Way too many parenthesis to keep track of what's inside what (and some are entirely unnecessary). Try separating the function arguments onto separate lines so you can see them, and separate out some of the repeating ugly things into variables.

for (totalMatches = 1; totalMatches <= (pIt)->first->getSize(); ++totalMatches)
{
    int eventIndex = eventLog.size()-totalMatches;
    const Event *event = eventLog[eventIndex];
    if (!(pIt)->first->compare(
         (pIt)->first->getSize()-totalMatches,
         event->getType(),
         translator->translate(event->getKeyCode()),
         getTimeDiff(eventIndex)))
         break;
}

Or better yet, put the whole thing in a function that returns true at the end, and have the if statement return false instead of breaking.




#5108384 Appropriate number of bugs

Posted by DekuTree64 on 10 November 2013 - 07:39 PM

If those are the kind of bugs you have, then go fix 'em. Most of those sound less like mistakes and more like incomplete features. Minor visual things like shadows and model intersections won't impede anyone's work, so they can be put off until later, but failing to load or unload objects should be fixed right away.

 

The helper guys not helping is just an incomplete feature, so if someone was scheduled to do it and didn't finish it, then add it to their schedule for next iteration. If they did everything that could be done for the initial implementation given the state of the rest of the game at the time, then add it to their schedule whenever all the other prerequisites are up to speed. When you have a lot of things that interact with eachother, it can take several rounds and a lot of meetings to finish them.

 

As you gain experience, you'll get better at the analysis phase and foresee more details before writing any code. But you should also test code as you write it. For example, the thing of facing the wrong direction when loading the game... that should be pretty obvious if you test the loading code in a few different levels to make sure it's working before checking it in to source control. And you shouldn't check "implement save/load" off the list if you know it's not done yet.

 

And certainly not all bugs are created equal. Personally, when I track down a really tough crash bug, it's satisfying enough just to finally understand it and add it to my knowledge base of what to look out for in the future. But if alcohol motivates you, and it takes you all night to fix a bug, then take off early the next day and party :)




#5102310 "Pixel-Perfect" Collisions...

Posted by DekuTree64 on 17 October 2013 - 11:03 PM

What kind of game? I don't know of any tutorials, but for collision detection, it should be pretty straightforward. I'd do it with bitmasks, where each bit corresponds to one pixel of the sprite (1 for solid, 0 for non-solid). Then bitshift according to the sprites' relative X positions, AND together, and if the result is zero, no collision. Nonzero means one or more pixels overlapping. If you limit your sprites to 32 pixels wide, the collision mask can just be an array of 32-bit unsigned longs, one for each row of pixels in the sprite.

 

But I'd only use it for detection of collisions with bullets or other attacks, not for anything motion related. Motion is hard enough with geometric shapes, and pixel perfect might not behave well even if you did get it working (snagging pixels of the character on ledges and such)




#5101589 Final Fantasy VI game - chronological order of building & being challenge...

Posted by DekuTree64 on 15 October 2013 - 11:32 AM

I agree with the above post, stick with low res. 256x192 is good. Nintendo DS uses it, and it's very close to SNES. I'd recommend against widescreen. My current game (somewhere between FF1 and FF6 style) is on GBA and thus 240x160, which is a little cramped. Taller is better for these games, because the battle menu takes up a lot of vertical real estate.

 

High res pixel art is really hard, IME. 16x16 tiles and 16x24 sprites are my favorite, and look just right at 256x192.

 

If you ever want to chat about RPG making, feel free to message me :) I'm on MSN as my name here at hotmail.com.




#5101371 Final Fantasy VI game - chronological order of building & being challenge...

Posted by DekuTree64 on 14 October 2013 - 02:02 PM

I shall refer you to a thread on another forum, which is more art focused but still relevant http://wayofthepixel.net/index.php?topic=15726.0

And a guy you might like. One of the few to actually have some success in solo RPG making http://www.blossomsoft.com/gamedevs/

 

Don't worry, "flashing the FF card" on internet forums will always get you responses like you've gotten here. Doesn't mean you shouldn't do what you want.

 

My challenge to you is to create 30 minutes of fun gameplay, where all the artwork and music you see/hear is done by yourself.

 

As for how to approach it, first is story/design. The story is the core of the game, so spend as much time as you want on it to make it good. For gameplay design, just saying "FF6 like" eliminates a lot of the work for you. You just need to decide the specifics of the classic RPG formula you want to do. Then think up as many items/spells/monsters as you can. Then start making some real in-game artwork and music. The "vertical slice" approach. A couple map tilesets, a couple character sprites, a battle background, a couple monsters, a couple songs. Then do most of the programming.

 

Up to this point should be completed as quickly as possible (except the story)... maybe 1-6 months depending on your experience and the programming difficulty. Then you can get to the real work of the project, cranking out artwork and music, designing maps, and telling the story. Naturally, you'll encounter lots of stuff you forgot to program at first, and come up with new ideas along the way... just roll with it. That's why the pre-planned stage was considered quick and easy smile.png This phase takes forever, and will feel like you're not getting anywhere and will never finish most of the time. If you're like me, you'll have a tendency to abandon ship because your design wasn't good enough to be worth all the work still needing done.

 

Then comes testing/debugging/balancing. This is where you can see the light at the end of the tunnel, but you're still depressed at how far away it is. Usually work lots of overtime here.

 

Then finally you start running out of bugs and everything feels good and all of a sudden you notice it's actually a game and not just a random collection of features smile.png This is where you start putting on some finishing touches and can decide at any time when to call it done. Because it will never be done done.




#5100479 How to code game data

Posted by DekuTree64 on 11 October 2013 - 03:11 AM

I just make an enum of item ID values, a table of structs matching up to it where I enter data for each item, and then the player's inventory can be one of two styles:

 

a) The player can have at most 99 of each item, but can have 99 of every item in the game all at the same time (no inventory limit). The inventory is just an array of bytes that corresponds to the item ID enum, which tells how many of each item the player currently owns. When displaying the inventory, don't show any that are 0. Final Fantasy 6 does this style (although it lets you change the display order)

 

b) Each slot in the inventory is an item ID and number of how many. In this style you can carry more than 99 of the same item type, by having multiple bundles (e.g. 99 cure potions in one slot, 20 more in another slot). Most games that use this style have a fairly limited number of slots, so you often have to sell old weapons and armor to make room for new ones. Final Fantasy 4 does this style. Some games, such as Earthbound on SNES, only let you store one item in each slot. So if you have two cookies, it takes two slots. And you only have 20 slots or something total. Too frustrating, IMO.




#5098636 Pro and Cons to building a game engine

Posted by DekuTree64 on 03 October 2013 - 05:33 PM

Programming is just like any other skill- in the first few years, you'll be improving at a rapid pace, and routinely wanting to throw out your old stuff because it's so awful compared to what you can do now.

 

If you try to make a reusable engine early on, you'll just scrap it half way through and start over, then get it sort of done, try to make a game, find out the engine is totally inadequate, scrap it and start over, and so on. If you just want to make some tech demo stuff for learning experience, this is fine.

 

If your goal is to finish games, then just code exactly what you need and nothing more. No fancy engine features that "might come in handy someday". Design your game, make a list of necessary features, code them, try to actually make a level and discover all the stuff you didn't think of, code that, repeat until done. Next game, either start fresh and pick and choose any code bits from your old game as needed, or start from your old game and strip out everything you don't need. After a few iterations, you'll start to see what carries over and what doesn't, and how to redesign some of the stuff that doesn't so it does.

 

But even then you don't really need to isolate the engine. Engines are most useful when you have a decent size studio with several teams working on different games at the same time. Or when releasing on the net for other people to make games with it. Not much benefit for lone developers or a single small indie team.




#5098426 Z-Layer change

Posted by DekuTree64 on 03 October 2013 - 12:40 AM

Sort by Y position. In isometric, ignore the "altitude" of the sprite during the sorting, so jumping up doesn't affect the draw order, even though it does affect the Y position on screen. Any sorting algorithm will do. I keep my sprites in a linked list, and use an insertion sort where I traverse the list backward and rebuild it every frame, because it's simple and fast. If no sprites have changed order, it's linear time. Worst case is if they all completely reversed order, where it would be O(n2) time. But even that wouldn't be a big deal unless you have a ton of sprites, and most games it would never happen anyway.

void SpriteSystemYSort()
{
    Sprite *sprite = gSpriteActiveListHead;
    Sprite *activeListTail;

    if (sprite == NULL || sprite->next == NULL)
        return;    // No sorting to be done unless there's more than one sprite

    // Start from the tail of the list, for minimal insert time if the order hasn't changed since last frame
    while(sprite->next)
        sprite = sprite->next;

    // Rebuild the active list in Y sorted order. Start by adding the first sprite, to save a couple null checks in the loop
    gSpriteActiveListHead = activeListTail = sprite;
    sprite = sprite->prev;
    gSpriteActiveListHead->prev = gSpriteActiveListHead->next = NULL;
    while(sprite)
    {
        Sprite *prev = sprite->prev;
        Sprite *insert = gSpriteActiveListHead;

        while(insert != NULL && insert->pos.y > sprite->pos.y)
            insert = insert->next;

        if (insert == NULL)
        {
            sprite->prev = activeListTail;
            sprite->next = NULL;
            activeListTail->next = sprite;
            activeListTail = sprite;

        }
        else if (insert == gSpriteActiveListHead)
        {
            sprite->prev = NULL;
            sprite->next = gSpriteActiveListHead;
            gSpriteActiveListHead->prev = sprite;
            gSpriteActiveListHead = sprite;
        }
        else
        {
            sprite->prev = insert->prev;
            sprite->next = insert;
            insert->prev->next = sprite;
            insert->prev = sprite;
        }

        sprite = prev;
    }
}



#5098394 Another newbie question on RADs...

Posted by DekuTree64 on 02 October 2013 - 08:40 PM

x = cos(angle) * distance

y = sin(angle) * distance




#5098157 Help debug multidimensional array loop?

Posted by DekuTree64 on 01 October 2013 - 05:00 PM

Try this:

if(yClicked > y-(nx*65)-65 && yClicked < y-(nx*65))



#5097921 About separating game logic from rendering

Posted by DekuTree64 on 30 September 2013 - 01:46 PM

Don't put a draw function in the game objects.

 

Instead of drawing via the entity list, maintain a separate list of sprites and draw from that. Side advantage is that an entity can have multiple sprites, and non-entities can have sprites (e.g. menus) and you don't have to write any extra drawing loops.

 

That's assuming the game objects don't have a bunch of unique rendering code in each one. But if they do, see if you can factor it out into a few more generic "renderable" classes which can go in the same list with the sprites, or another separate list, depending on what works best.






PARTNERS