Page 1 of 2

Rather Complicated Problem

PostPosted: Mon Nov 06, 2006 12:00 am
by Hedfone
I have a character in my game who's gun folows the mouse. I have 360 individual frames for each angle of the gun.
What I want to do, is on mouse button down, he gets recoil from the shot. Probably about 3-5frames upward OR 3-4 pixels backwards and then the gun returns to it's prior position.
Anyone? :D

EDIT: umm, new problem, GE doesn't seem to be letting me have more than 220-ish frames for an animation. is this normal?

Re: Rather Complicated Problem

PostPosted: Mon Nov 06, 2006 12:29 am
by makslane
Hedfone wrote:GE doesn't seem to be letting me have more than 220-ish frames for an animation. is this normal?


You can have a lot of frames in an animation. I have tested animations with more than 1000 frames without problems.

PostPosted: Mon Nov 06, 2006 8:22 pm
by Hedfone
oh, ya. Prob#2 fixed! :D Help wth #1?

PostPosted: Tue Nov 07, 2006 6:23 am
by DilloDude
First, use the ReDir function for aiming: http://game-editor.com/forum/viewtopic. ... ight=redir
Then, to aim towards the top, use ReDir with whatever direction variable you're using, aiming toward 90 (straight up), with whatever magnitude you want (probably greater for a more powerful gun). That should give you a nice result.

PostPosted: Wed Nov 08, 2006 12:54 am
by Hedfone
I don't really understand code very well(at all :oops: ). my forté is more graphics 8)
that entire toipic didn't really make sense to me. is there any way you could dumb it down a shade and just give me the essential coding that I'll need?
thank you :D

PostPosted: Wed Nov 08, 2006 6:29 am
by DilloDude
First, add the getangle and ReDir functions:
Code: Select all
double getangle(double A, double B)
{
    double result;
 
    result = B - A;
    if(result>180)
    {
        result = 360 - result;
        result *= -1;
    }
    else if (result < -180)
    {
        result = 360 + result;
    }
    return result;
}




double ReDir(double A, double B, double mag)
{
    double ang = getangle(A, B);
    if(abs(mag)<=abs(ang))
    {
        if(ang>0)
        {
            return A + mag;
        }
        else if (ang < 0)
        {
            return A - mag;
        }
        else
        {
            return 0;
        }
    }
    else
    {
        return B;
    }
}
add this in a section of Global Code.

Another function you will find useful is:
Code: Select all
void angWrap(double *ang)
{
    while (*ang >= 360)
    {
        *ang -= 360;
    }
    while (*ang < 0)
    {
        *ang += 360;
    }
}
This automatically 'wraps' a real variable to resemble an angle, eg. if I have an angle, 350, and I ncrease it by ten, making it 360, and use angWrap, it will make it equal to 0, which is the same as 360 degrees.

Now, you need a variable to represent the angle you are aiming at. Use the 'variables' panel (at the bottom of the script editor) to create a real variable, call it dir. (You might also want to make it an actor variable, depending on what else you have.) For this example, I'll also add how to make different weapons react differently. So create an integer variable called weapon. 0 will be a pistol, whcih you can aim quickly, with a reasonable amount of recoil, 1, a machine-gun, with slower aiming and heavier recoil, and 2 a shotgun with slow aiming and large recoil. Create another integer called aimspeed. This is for how fast the current weapon aims. Also, another integer called recoil, for how much recoil the current weapon has.

Now it will be silly if you are aiming right and you want to aim left to have to aim all the way up and over the top, or around the bottom to get there. For example if I am aiming north-east, and I move to aim at west, I should be able to immediately flip to north-west, and then aim down to straight west. So we will allow for this. Add the aprx function to Global Code:
Code: Select all
int aprx(double i, double j, double dif)
{
    if(j<=i+dif && j>=i-dif)
    {
        return 1;
    }
    else
    {
        return 0;
    }
}
this makes it easier to find if one value is aproximately equal to another.

Now, we need to make our character aim. Add a script editor draw actor event. Now, add this code:
Code: Select all
double aimang = direction(xscreen, yscreen, xmouse, ymouse);
//get the direction to the mouse

//to make the 'turn' effect:
char cursid = 1; //the 'side' of the current aim
char aimsid = 1; //the 'side' of the desired aim

if (aprx(dir, 180, 90))
{
    cursid = 0;//if dir is aproximately 180 (straight left), with 90 degrees variation, you are aiming left
}

if (aprx(aimang, 180, 90))
{
    aimsid = 0;//same for the disired aim
}

if (cursid != aimsid)//if the disired aim is on the opposite side from the current aim
{
    dir += getangle(dir, 90) * 2;//change aim by the angle size to the top times two
}

//make normal aiming
dir = ReDir(dir, aimang, aimspeed);
angWrap(&dir);

animpos = dir;//or any other script for the animpos


All very well for the aiming. Now you want to make different guns work. To start, add the script on your players create actor:
Code: Select all
weapon = 0;//pistol

aimspeed = 10;
recoil = 20;
//adjust these two variables as suits; I haven't tested them, but make sure you change them everywhere


Now, we want script to change weapon. Say you press keys 1 - 3 to select. Key 1 should change weapon to 0, 2 to 1, and 3 to 2. Add a keydown on your player, for keys, 1, 2 and 3, make sure it is 'at least one key is pressed', and repeat is disabled. Add this script:
Code: Select all
switch(getLastKey())
{
    case KEY_1:
    weapon = 0;
    aimspeed = 10;
    recoil = 20;//see note in previous section
    break;
   
    case KEY_2:
    weapon = 1;
    aimspeed = 10;
    recoil = 15;
    break;
   
    case KEY_3:
    weapon = 2;
    aimspeed = 7;
    recoil = 20;
    break;
}


Have a mouse sensor actor that sends activation events to your character for every shot. You'll need to have a way of limiting how often you can shoot, and for making weapons automatic. I'll leave that to you, but you'll probably want to change more variables in the keydown event, above.
Add this script for the activation event:
Code: Select all
//any script you want for creating bullet and playing sound etc.

//the recoil script:
dir = ReDir(dir, 90, recoil);
angWrap(&dir);

animpos = dir;//or any other script for the animpos
I think this should do what you want. If you have problems, just ask, and I'll see if I can fix them.

One piece of advice, which applies to most code you get from anywhere: try to understand what it does, and why it works. It''l make it easier to find problems, make it easier to addapt it to your own use, increase your learning and knowledge of coding and it will make you feel better knowing, not only that someone-gave-me-this-code-and-it-does-what-I-want, but This-code-that-someone-gave-me-does-what-I-want-and-I-understand-why.
If, when you write code, you put lots of comments throught it, it will help others to understand, and it can sometimes make it easier for you to figure out, either as you go, or looking back on it.

PostPosted: Thu Nov 09, 2006 2:23 am
by Fuzzy
Can I Simplify this for you?
Code: Select all
void angWrap(double *ang)
{
    while (*ang >= 360)
    {
        *ang -= 360;
    }
    while (*ang < 0)
    {
        *ang += 360;
    }
}


Code: Select all
double angWrap(double ang){return ang%359}


should do the same thing.

you can use it in a line like this:

Code: Select all
angle = angWrap(angle);


or even

Code: Select all
angle = angWrap(angle+carrotjuice);

PostPosted: Thu Nov 09, 2006 2:30 am
by DilloDude
Cool!
Except ideally you'd want
Code: Select all
double angWrap(double ang){return ang%359.999999}

but with angles, decimals probably wouldn't be that important, so maybe only 359.9. It doesn't matter much.

PostPosted: Thu Nov 09, 2006 2:39 am
by Fuzzy
DilloDude wrote:Cool!
Except ideally you'd want
Code: Select all
double angWrap(double ang){return ang%359.999999}

but with angles, decimals probably wouldn't be that important, so maybe only 359.9. It doesn't matter much.


You sir, are right 99.999999 percent of the time. I should have added that series of 9s after the decimal. Thanks.

PostPosted: Thu Nov 09, 2006 4:24 am
by DilloDude
Another thing you could do to simplify use is to put angWrap inside ReDir so you don't have to put it afterwrds, you just put ReDir and it does it for you. That way, you'd only have to use angWrap when you are manually increasing the angle : dir += 23;angWrap...

PostPosted: Thu Nov 09, 2006 8:21 am
by DilloDude
The only problem is that % only works with integers.
And it only does the positive one (-1 returns -1, when it should return 359);

PostPosted: Thu Nov 09, 2006 2:54 pm
by Sgt. Sparky
about the frame stuff, i have an entire level made with one animation. and whenever i load it with GE, GE crashes and some times i have to restart the computer... :cry: so an entire really cool level will not work...*is veryx999ect. sad* could you help me?

PostPosted: Thu Nov 09, 2006 3:20 pm
by makslane
Send to my email

PostPosted: Thu Nov 09, 2006 3:28 pm
by Sgt. Sparky
ARgh :evil: ! even the compressed version of the picture will not send... :cry: :( :x :evil: :x :( :cry: and there is noway to post it here, you would have to scroll way to the left and right... :evil: :x :? :( :cry:

PostPosted: Thu Nov 09, 2006 8:38 pm
by Hedfone
try breaking the huge picture up into several screen length pictures and making them seperate actors. yeah, it's a pain, but...what can ya do? :D