Now the code is using the native run but with a follow animation for the brake frames.I liked how it turns out. Question: do we need to use a freespecial for that? Can't we use the native run?
I don't want to use many cancels to use runattack, run jump, etc.
anim idle
loop 1
delay 16
offset 127 179
bbox 117 109 19 72
@cmd animVar "runFlag" 1 openborconstant("ANI_FOLLOW15") #CHANGE TO THE BRAKE ANIMATION IF THE RUNFLAG IS 1
frame data/chars/heroes/blaze/sor2/idle00.png
frame data/chars/heroes/blaze/sor2/idle01.png
frame...
I suggest taking a look in my Super Mario template, I have this kind of mechanic there.I'd like to create a character with a lot of inertia:
The character runs fast, and when the player releases the arrow keys, the character slides forward slightly, like skating on ice.
After referring to your project, I feel like doing this:I suggest taking a look in my Super Mario template, I have this kind of mechanic there.
I think the Run animation will not work because the character will go to Idle as soon as you release the directional keys. You can maybe try a keyscript to detect a directional key released and force a transition between the Run animation and possibly a Follow animation that contains the brake frames.After referring to your project, I feel like doing this:
1. A keyloop script.
2. The Run animation has running frames and braking frames, when the keyloop script is executing, only loop play the running frames.
@cmd dasher 1 0 0
frame data/chars/bosses/bongo/bkm/fire02.png
@cmd dasher 0.5 0 0
frame data/chars/bosses/bongo/bkm/fire03.png
@cmd dasher 0.1 0 0
frame data/chars/bosses/bongo/bkm/fire04.png
//DETECT LEFT/RIGHT KEYS RELEASED
if(playerkeys(iPIndex, 2, "moveleft") || playerkeys(iPIndex, 2, "moveright")){
doSomething();
}
void dasher(float Vx, float Vy, float Vz)
{//Dash with desired speed!
void self = getlocalvar("self");
int dir = getentityproperty(self,"direction");
if(dir == 0){Vx = -Vx ;}
changeentityproperty(self, "velocity", Vx, Vz, Vy);
}
I was just thinking about this:After detecting the release of the arrow left/right keys, jump to the animation follow{xx}.I think the Run animation will not work because the character will go to Idle as soon as you release the directional keys. You can maybe try a keyscript to detect a directional key released and force a transition between the Run animation and possibly a Follow animation that contains the brake frames.
Then, you can insert a @cmd dasher in every frame of the Follow animation which gradually reduces the character's speed, I'm using it in some dash attacks.
Code:@cmd dasher 1 0 0 frame data/chars/bosses/bongo/bkm/fire02.png @cmd dasher 0.5 0 0 frame data/chars/bosses/bongo/bkm/fire03.png @cmd dasher 0.1 0 0 frame data/chars/bosses/bongo/bkm/fire04.png
Code://DETECT LEFT/RIGHT KEYS RELEASED if(playerkeys(iPIndex, 2, "moveleft") || playerkeys(iPIndex, 2, "moveright")){ doSomething(); }
Code:void dasher(float Vx, float Vy, float Vz) {//Dash with desired speed! void self = getlocalvar("self"); int dir = getentityproperty(self,"direction"); if(dir == 0){Vx = -Vx ;} changeentityproperty(self, "velocity", Vx, Vz, Vy); }
hmm it can work, I'm doing some tests.Instead of using ‘anim run’, add a ‘com f f freespecial1’. then make this ‘anim freespecial1’play running & braking frames.
com f f freespecial15
anim freespecial15
loop 0
delay 10
offset 127 179
bbox 125 113 17 68
@cmd keyMove 2 1 6
@cmd keyFlip
frame data/chars/heroes/blaze/sor2/run00.png
@cmd keyMove 2 1 6
@cmd keyFlip
@cmd sound "data/sounds/sorx_run.wav"
frame data/chars/heroes/blaze/sor2/run01.png
@cmd keyMove 2 1 6
@cmd keyFlip
frame data/chars/heroes/blaze/sor2/run02.png
@cmd keyMove 2 1 6
@cmd keyFlip
frame data/chars/heroes/blaze/sor2/run03.png
@cmd keyMove 2 1 6
@cmd keyFlip
@cmd sound "data/sounds/sorx_run2.wav"
frame data/chars/heroes/blaze/sor2/run04.png
@cmd keyMove 2 1 6
@cmd keyFlip
frame data/chars/heroes/blaze/sor2/run05.png
@cmd keyLoop "moveleft" 0
@cmd keyLoop "moveright" 0
@cmd keyFlip
@cmd dasher 2 0 0
frame data/chars/heroes/blaze/sor2/idle00.png
@cmd dasher 1 0 0
frame data/chars/heroes/blaze/sor2/idle01.png
@cmd dasher 0.5 0 0
frame data/chars/heroes/blaze/sor2/idle02.png
@cmd dasher 0.1 0 0
frame data/chars/heroes/blaze/sor2/idle03.png
void keyMove(float xVel, float zVel, int brakeFrame)
{//Move entity if direction button is pressed
//Use the brakeFrame to define to what frame the entity will jump when all keys are released in order to start the brake
void self = getlocalvar("self");
int iPIndex = getentityproperty(self,"playerindex");
float xdir = 0;
float zdir = 0;
if(xVel != 0){
if(playerkeys(iPIndex, 0, "moveleft")){
xdir = -xVel;
}
else
if(playerkeys(iPIndex, 0, "moveright")){
xdir = xVel;
}
else
{
updateframe(self, brakeFrame);
}
}
else
{
xdir = NULL();
}
if(zVel != 0){
if(playerkeys(iPIndex, 0, "moveup")){
zdir = -zVel;
}
else
if(playerkeys(iPIndex, 0, "movedown")){
zdir = zVel;
}
}
else
{
zdir = NULL();
}
changeentityproperty(self, "velocity", xdir, zdir);
}
void keyFlip(int opposite)
{//Change entity's facing direction if left or right is pressed
void self = getlocalvar("self");
int iPIndex = getentityproperty(self,"playerindex"); //Get player index
if(opposite == NULL()){
if(playerkeys(iPIndex, 0, "moveleft")){changeentityproperty(self, "direction", 0);}else
if(playerkeys(iPIndex, 0, "moveright")){changeentityproperty(self, "direction", 1);}
}
else
{
if(playerkeys(iPIndex, 0, "moveleft")){changeentityproperty(self, "direction", 1);}else
if(playerkeys(iPIndex, 0, "moveright")){changeentityproperty(self, "direction", 0);}
}
}
void keyLoop(void key, int frame, void var, void value)
{//Loops defined frame if defined key is held
//Use "var" if you want to define a variable requirement, otherwise let it empty
void self = getlocalvar("self");
int iPIndex = getentityproperty(self,"playerindex");
if(var != NULL()){
if(getglobalvar(var) == value){
if(playerkeys(iPIndex, 0, key)){updateframe(self, frame);}
}
}
else
{
if(playerkeys(iPIndex, 0, key)){updateframe(self, frame);}
}
}
Sir, I was just talking about a idea, made you answer my questions for so long. I feel embarrassed, thank you.hmm it can work, I'm doing some tests.
Don't worry buddy. Please, make a try with the latest script I posted, I'm curious to know if it will work fine in your game.Sir, I was just talking about a idea, made you answer my questions for so long. I feel embarrassed, thank you.
So cool, you also made the circle run.Here's all the codes I used in the video.
Perfect! I'm not at liberty to record a video to show you right now, I'm tweaking the values and I'll get the brake attack animation that goes with it done as soon as I can and show you.Don't worry buddy. Please, make a try with the latest script I posted, I'm curious to know if it will work fine in your game.
GreatPerfect! I'm not at liberty to record a video to show you right now, I'm tweaking the values and I'll get the brake attack animation that goes with it done as soon as I can and show you.
Hello Sir, I modified your Mario project for testing and the results were not good, I must have missed something - this is my process:GreatGlad the code works
void keyMove(float xVel, float zVel, int brakeFrame)
{//Move entity if direction button is pressed
//Use the brakeFrame to define to what frame the entity will jump when all keys are released in order to start the brake
void self = getlocalvar("self");
int iPIndex = getentityproperty(self,"playerindex");
float xdir = 0;
float zdir = 0;
if(xVel != 0){
if(playerkeys(iPIndex, 0, "moveleft")){
xdir = -xVel;
}
else
if(playerkeys(iPIndex, 0, "moveright")){
xdir = xVel;
}
else
{
updateframe(self, brakeFrame);
}
}
else
{
xdir = NULL();
}
if(zVel != 0){
if(playerkeys(iPIndex, 0, "moveup")){
zdir = -zVel;
}
else
if(playerkeys(iPIndex, 0, "movedown")){
zdir = zVel;
}
}
else
{
zdir = NULL();
}
changeentityproperty(self, "velocity", xdir, zdir);
}
void keyFlip(int opposite)
{//Change entity's facing direction if left or right is pressed
void self = getlocalvar("self");
int iPIndex = getentityproperty(self,"playerindex"); //Get player index
if(opposite == NULL()){
if(playerkeys(iPIndex, 0, "moveleft")){changeentityproperty(self, "direction", 0);}else
if(playerkeys(iPIndex, 0, "moveright")){changeentityproperty(self, "direction", 1);}
}
else
{
if(playerkeys(iPIndex, 0, "moveleft")){changeentityproperty(self, "direction", 1);}else
if(playerkeys(iPIndex, 0, "moveright")){changeentityproperty(self, "direction", 0);}
}
}
void keyLoop(void key, int frame, void var, void value)
{//Loops defined frame if defined key is held
//Use "var" if you want to define a variable requirement, otherwise let it empty
void self = getlocalvar("self");
int iPIndex = getentityproperty(self,"playerindex");
if(var != NULL()){
if(getglobalvar(var) == value){
if(playerkeys(iPIndex, 0, key)){updateframe(self, frame);}
}
}
else
{
if(playerkeys(iPIndex, 0, key)){updateframe(self, frame);}
}
}
void dasher(float Vx, float Vy, float Vz)
{//Dash with desired speed!
void self = getlocalvar("self");
int dir = getentityproperty(self,"direction");
if(dir == 0){Vx = -Vx ;}
changeentityproperty(self, "velocity", Vx, Vz, Vy);
}
runscript data/scripts/run/default.c
com f f freespecial15
anim freespecial15
loop 0
delay 10
offset 24 39
bbox 125 113 17 68
@cmd keyMove 2 1 6
@cmd keyFlip
frame data/chars/mario/run00.gif
@cmd keyMove 2 1 6
@cmd keyFlip
frame data/chars/mario/run01.gif
@cmd keyMove 2 1 6
@cmd keyFlip
frame data/chars/mario/run00.gif
@cmd keyMove 2 1 6
@cmd keyFlip
frame data/chars/mario/run02.gif
@cmd keyLoop "moveleft" 0
@cmd keyLoop "moveright" 0
@cmd keyFlip
@cmd dasher 2 0 0
frame data/chars/mario/turn00.gif
@cmd dasher 1 0 0
frame data/chars/mario/turn00.gif
@cmd dasher 0.5 0 0
frame data/chars/mario/turn00.gif
@cmd dasher 0.1 0 0
frame data/chars/mario/turn00.gif
Can't compile script ‘Mario’ data/chars/mario/mario.txt
anim freespecial15
loop 0
delay 10
offset 24 39
bbox 125 113 17 68
#---------- ------wrong ↓--- ---
# @cmd keyMove 2 1 6
# @cmd keyFlip
# frame data/chars/mario/run00.gif
# @cmd keyMove 2 1 6
# @cmd keyFlip
# frame data/chars/mario/run01.gif
# @cmd keyMove 2 1 6
# @cmd keyFlip
# frame data/chars/mario/run00.gif
# @cmd keyMove 2 1 6
# @cmd keyFlip
# frame data/chars/mario/run02.gif
# @cmd keyLoop "moveleft" 0
# @cmd keyLoop "moveright" 0
# @cmd keyFlip
#---------- ------wrong ↑--- ---
@cmd dasher 2 0 0
frame data/chars/mario/turn00.gif
@cmd dasher 1 0 0
frame data/chars/mario/turn00.gif
@cmd dasher 0.5 0 0
frame data/chars/mario/turn00.gif
@cmd dasher 0.1 0 0
frame data/chars/mario/turn00.gif
@cmd keyMove 2 1 6
@cmd keyFlip
@cmd keyLoop ‘moveleft’ 0
@cmd keyLoop ‘moveright’ 0
//DETECT LEFT/RIGHT KEYS RELEASED
if(playerkeys(iPIndex, 2, ‘moveleft’) || playerkeys(iPIndex, 2, ‘moveright’)){
doSomething();
}
Hello Sir, I modified your Mario project for testing and the results were not good, I must have missed something - this is my process:
1, created a new folder called run in the Data\scripts\ folder, edited a default.c and pasted what you provided:
void keyMove(float xVel, float zVel, int brakeFrame)
......
void keyFlip(int opposite)
......
void keyLoop(void key, int frame, void var, void value)
......
void dasher(float Vx, float Vy, float Vz)
......
2. Modify mario.txt and add these:
runscript data/scripts/run/default.c
com f f freespecial15
anim freespecial15
......
After running, report error:
Can't compile script ‘Mario’ data/chars/mario/mario.txt
I tried to troubleshoot the error, and after gradually adding ‘#’ in front of ‘ @cmd’ in mario.txt, I found the problem here:
anim freespecial15
loop 0
delay 10
offset 24 39
bbox 125 113 17 68
---------- ------wrong ↓--- ---
@cmd keyMove 2 1 6
@cmd keyFlip
frame data/chars/mario/run00.gif
@cmd keyMove 2 1 6
@cmd keyFlip
frame data/chars/mario/run01.gif
@cmd keyMove 2 1 6
@cmd keyFlip
frame data/chars/mario/run02.gif
@cmd keyMove 2 1 6
@cmd keyFlip
frame data/chars/mario/run00.gif
@cmd keyLoop ‘moveleft’ 0
@cmd keyLoop ‘moveleft’ 0
@cmd keyFlip
---------- ------wrong ↑--- ---
@cmd dasher 2 0 0
frame data/chars/mario/turn00.gif
@cmd dasher 1 0 0
frame data/chars/mario/turn00.gif
@cmd dasher 0.5 0 0 0 frame data/chars/mario/turn00.gif
frame data/chars/mario/turn00.gif
@cmd dasher 0.1 0 0 frame data/chars/mario/turn00.gif
frame data/chars/mario/turn00.gif
When one of these appears in the txt:
@cmd keyMove 2 1 6
@cmd keyFlip
@cmd keyLoop ‘moveleft’ 0
@cmd keyLoop ‘moveright’ 0
I open the game, it will just appear as ‘load...’ and exit.
If I put ‘#’ in front of these 4 ‘@cmd’, the game executes - Mario can't fastrun by pressing the arrow keys in a row, and Mario brakes after any movement.
My guess is that I missed this line when I copied the script to cause this:
//DETECT LEFT/RIGHT KEYS RELEASED
if(playerkeys(iPIndex, 2, ‘moveleft’) || playerkeys(iPIndex, 2, ‘moveright’)){
doSomething();
}
If the error is due to missing this line, could you please tell me where this should be pasted?
This is the mario.txt and default.c used for testing, which I've also put here.
The keyscripts I posted (keyMove, keyFlip, keyLoop) were not developed to be used in the super mario template, I made them to be applied directly in your game (or in an empty BOR mod). The super mario template already has other scripts managing the Run feature and will conflict with the keyscripts.Hello Sir, I modified your Mario project for testing and the results were not good, I must have missed something - this is my process:
I liked how it turns out. Question: do we need to use a freespecial for that? Can't we use the native run?Yeah, it worked better than I thought! Very very close to the native Run feature, you had a good idea.
The problem is that the native run changes to idle instantly as soon as you release the directional keys. However, I'm testing some workarounds right now and found a way to make it work using native run, I only need to finish some adjustments.I liked how it turns out. Question: do we need to use a freespecial for that? Can't we use the native run?
I don't want to use many cancels to use runattack, run jump, etc.
Now the code is using the native run but with a follow animation for the brake frames.I liked how it turns out. Question: do we need to use a freespecial for that? Can't we use the native run?
I don't want to use many cancels to use runattack, run jump, etc.
anim idle
loop 1
delay 16
offset 127 179
bbox 117 109 19 72
@cmd animVar "runFlag" 1 openborconstant("ANI_FOLLOW15") #CHANGE TO THE BRAKE ANIMATION IF THE RUNFLAG IS 1
frame data/chars/heroes/blaze/sor2/idle00.png
frame data/chars/heroes/blaze/sor2/idle01.png
frame data/chars/heroes/blaze/sor2/idle02.png
frame data/chars/heroes/blaze/sor2/idle03.png
frame data/chars/heroes/blaze/sor2/idle00.png
frame data/chars/heroes/blaze/sor2/idle01.png
frame data/chars/heroes/blaze/sor2/idle02.png
frame data/chars/heroes/blaze/sor2/idle03.png
anim walk
loop 1
delay 14
offset 127 179
bbox 124 107 12 73
@cmd animVar "runFlag" 1 openborconstant("ANI_FOLLOW15") #CHANGE TO THE BRAKE ANIMATION IF THE RUNFLAG IS 1
frame data/chars/heroes/blaze/sor2/walk00.png
@cmd setEntityVar "runFlag" NULL() #CLEAR THE RUNFLAG IF THE PLAYER HOLD THE WALKING INSTANCE
frame data/chars/heroes/blaze/sor2/walk01.png
frame data/chars/heroes/blaze/sor2/walk02.png
frame data/chars/heroes/blaze/sor2/walk03.png
frame data/chars/heroes/blaze/sor2/walk04.png
frame data/chars/heroes/blaze/sor2/walk05.png
anim run
loop 1
delay 10
offset 127 179
bbox 125 113 17 68
@cmd setEntityVar "runFlag" 1 #SET THE RUNFLAG VARIABLE
@cmd saveSpeed #SAVE THE CURRENT SPEED DURING THE RUN ANIMATION
frame data/chars/heroes/blaze/sor2/run00.png
@cmd saveSpeed
@cmd sound "data/sounds/sorx_run.wav"
frame data/chars/heroes/blaze/sor2/run01.png
@cmd saveSpeed
frame data/chars/heroes/blaze/sor2/run02.png
@cmd saveSpeed
frame data/chars/heroes/blaze/sor2/run03.png
@cmd saveSpeed
@cmd sound "data/sounds/sorx_run2.wav"
frame data/chars/heroes/blaze/sor2/run04.png
@cmd saveSpeed
frame data/chars/heroes/blaze/sor2/run05.png
anim follow15 #BRAKE ANIMATION
loop 0
delay 16
offset 127 179
bbox 117 109 19 72
@cmd loadSpeed 2 2 #LOAD PREVIOUSLY SAVED SPEED IN THE RUN ANIMATION AND REDUCE GRADUALLY
frame data/chars/heroes/blaze/sor2/idle00.png
@cmd loadSpeed 2 2
frame data/chars/heroes/blaze/sor2/idle01.png
@cmd loadSpeed 2 2
frame data/chars/heroes/blaze/sor2/idle02.png
@cmd dasher 0 0 0
frame data/chars/heroes/blaze/sor2/idle03.png
@cmd setEntityVar "runFlag" NULL() #CLEAR THE RUNFLAG
@cmd setIdle #SET ANIMATION TO IDLE
frame data/chars/heroes/blaze/sor2/idle00.png
anim runattack #BLITZ
fastattack 1
jugglecost 4
forcedirection -1
otg 1
loop 0
delay 10
offset 127 179
@cmd hitfx "data/sounds/sor3_hit5.wav"
@cmd voice "data/voices/sor2_blaze_attack3.wav"
@cmd setEntityVar "runFlag" NULL() #CLEAR THE RUNFLAG DURING RUNNING ATTACKS
frame data/chars/heroes/blaze/sor2/runatk00.png
frame data/chars/heroes/blaze/sor2/runatk01.png
void animVar(void variable, float value, void ani)
{
void self = getlocalvar("self");
if(getentityvar(self, variable) == value){
executeanimation(self, ani, 1);
setentityvar(self, variable, NULL());
}
}
void setEntityVar(void variable, void value)
{
setentityvar(getlocalvar("self"), variable, value);
}
void dasher(float Vx, float Vy, float Vz)
{
void self = getlocalvar("self");
int dir = getentityproperty(self,"direction");
if(dir == 0){Vx = -Vx ;}
changeentityproperty(self, "velocity", Vx, Vz, Vy);
}
void saveSpeed()
{
void self = getlocalvar("self");
float xDir = getentityproperty(self,"xdir");
float zDir = getentityproperty(self,"zdir");
setentityvar(self, "xdir", xDir);
setentityvar(self, "zdir", zDir);
}
void loadSpeed(int reduceX, int reduceZ)
{
void self = getlocalvar("self");
float Vx = getentityvar(self, "xdir");
float Vz = getentityvar(self, "zdir");
float Vy = 0;
if(reduceX){
Vx = Vx/reduceX;
setentityvar(self, "xdir", Vx);
}
if(reduceZ){
Vz = Vz/reduceZ;
setentityvar(self, "zdir", Vz);
}
changeentityproperty(self, "velocity", Vx, Vz, Vy);
}
void setIdle()
{//Reset to idle instance
void self = getlocalvar("self");
setidle(self, openborconstant("ANI_IDLE"));
}