A-Engine Guide for LF2 coders

View previous topic View next topic Go down

A-Engine Guide for LF2 coders

Post by A-MAN on 16th May 2014, 12:52 pm

Hey LF2 fellas! I have been working on this little project of mine, the A-Engine. Inspired by the ability of LF2 to be fully modded, I started writing a beat 'em engine (written using C++ using SDL loading imgs, sounds and input and OpenGL for rendering) which you guys won't face any limitations in your developing. The scripting syntax is very similar to that of LF2's data changing, but with more syntactic sugars to make the scripting way easier for you. All that mentioned, the A-Engine literally supports mostly everything you will need. The menus interface is customizable, and so are game mechanics; the gravity, the friction and even the FPS can be changed to suit your needs. Not to forget to mention how you're given control over allocating the number of frames in your .a file (the .dat file) or even the number of images you can load. You also have the support to do some inline sprite editing including filtering, changing transparency, transformations and some other even greater stuff. PNGs, BMPs, JPGs, non animated GIFs and hopefully animated GIFs and APNGs are to be supported too. As for controls, you are given the choice to have a 4th button for whatever purpose, and the key combinations are limitless as long as you keep it down to 6 key presses max. This also includes Holding buttons or clicking them. The time interval between each key press can be set as well. Dynamic stages ranging from windy platformed mountains to icey slippery surroundings are supported. A 3rd meter bar was also implemented for those whom are interested in having an additional one for stamina or whatlike.A lot of other features were implemented, but the one that I am most fond of is the Variables, Registers and Functions systems. Consider the following basic frame example:


Code:
[panda=py]
#this is a comment
[f=20]  #Frame start. This is frame 20.
|STANDING|NOSHADOW|             #These are the "Switches". Does the job of "state:" in LF2
img=0 delay=3 center=39, 99     #img=->pic: delay=->wait: center=->centerx:centery:
vel_x=0 vel_y=3-3 vel_z=0       #vel_x=->dvx:.note the 3-3;will be evaluated at runtime to 0
c<a>=30 c<d>=30 c<j>=30 c<s>=30 #hit_a, hit_d, hit_j, hit_s; s being the 4rth button
h<a>=30 h<d>=30 h<j>=30 h<s>=30 #thats for holding the 4 buttons
[/f]    #Frame end


Now this is pretty basic right? Notice the switches I used. Instead of having a single state, we can now have more than a state by using multiple switches. The object in that frame will be considered standing (will go to walking frames if any arrow button is clicked) and will have no shadow.Now lets try to do something different. Something that is considered hard to do wiht LF2. Suppose you would like to have clicking attack take you to a frame based on a condition. For instance, you would like to have clicking attack while your HP is lower than 250 take you to frame 25;else, you would like to got to frame 30. You will have to use the "conditional operator ("?")" for it. C programmers will find this familiar XD:
Code:
[panda=py]
somevar= myhp<250?iftrue:iffalse;
In the A-Engne script though, you will have to start that with a "~" and end with a ";" for parsing's sake:
Code:

c<a>=~@curr_hp@<250?25:30; #if current hp is less than 250, goto 25;else, to 30
Now that same syntax can be used for the "delay=", "center=" or any other tag as well. Now notice how "curr_hp" was surrounded by a pair of "@"s. It just means that this is a "variable"; it varies according to game. You can't change or edit that. There are other variables as well storing your object's velocity, id, position in x,y and z..etc. Now to get even more flexible, you can store data in "registers". For every object, you have got 52 registers for you to manipulate and even share with other follower objects. The registers can be accessed by surrounding any alphabet, capital or small, with a pair of "$" (horraay PHP developers XD). To store data in any register, you use a special tag: "set_reg=" taking 2 parameters:
Code:
[panda=py]
[f=3]
img=0 center=30,30 delay=1
set_reg=$a$, 30             #store the value 30 in the reg a.It's a bit of ASM's "MOV" here XD
alpha=125                   #a simple tag for changing the transparency of this sprite to 125/255
[/f]

[f=4]                       #notice how I didn't have any "goto=" tag in frame 3.
                            #I ignored it because I didnt' have to. In case you leave
                           #a goto of a frame, it will automatically goto the frame
                            #with the number that comes after its' number.
img=2 center=30,30 delay=1 goto=0
set_reg=$a$, $a$+1          #I increment the value of $a$ by 1.
[/f]
Sweet, right? Now you are even given 100 more GLOBAL variable which are just shared between everything. These registers are basically from 1 to 99 ($0$, $1$...$99$). Third, we've got oursevles some "functions" to do cool stuff for us. A function is surrounded with a pair of "&"s. Suppose you would like to launch your opponent upwards with an angle 30 degrees and velocity of 10 px/frm (pixels per a (1/FPS)th of a second):
Code:
[panda=py]
[f=222] #knock opponent
img=123 goto=0 delay=2 center=0,0
set_rect[               #and here is our itr!!  
|FALL|                  #"switch"; will have the opponent fall now matter what
x=0 y=0 z=-8            #the x,y,z coords for where the rect starts
w=10 h=30 d=16          #the width,height and depth of the rect
rect_density=2          #arest/vrest; the no. of objects the rect can hit at once
hit_interval=30         #how many delay units will it take for the rect to hit again
x_impact=10*&COS{30}&   #dvx of the rect.We multiply by cos(angle) to get x-component
y_impact=-10*&sin{30}&  #dvy of the rect.We multiply by sin(angle) to get y-component
damage=20
]
[/f]


Now lets try to make use of the vars, regs and the functions to do something cool. Suppose you would like to have some cool physics stuff in your game. You would like your forward-up uppercut to knock the enemy away, or to be more accurate, transfer your momentum in x and y to him, and then heal your HP with a random value between 0 and 100. To do this, you will have to store his current velocity in a register (the mass in the calculation is handled by the engine itself). Then you will be doing some momentum physics to find your new velocity and his new velocity.:
Code:
[panda=py]
[f=532] #uppercut
img=421 center=(30+30)/2,(5+5)*3  #evaluates to center=30,30
delay=$b$-2                       #supposing b is 3; it evaluates to 1              
vel_x=10 vel_y=-12
set_rect[                                
x=0 y=0 z=-8 w=10 h=30 d=16                    
damage=40
copy_target_reg=@x_vel@|@y_vel@,$x$|$y$      
#copy target's x,y velocity to your regs $x$, $y$
x_impact=@x_vel@ y_impact=@y_vel@
success=533                       #if this rect successfully hit, goto 533
]                                              
[/f]

[f=533] #Recoil frame
f_x=$x$*-1 f_y=$y$*-1    #f_x,y,z sets force on you equal to the value to make you accelerate
center=0,0
img=999 delay=1
goto=0 hit_ground=44     #hit_ground is the frame you will goto if you reach the ground
add_hp=&randint{0, 100}& #the randint function returns a random int between its 2 arguments
[/f]

There are still a loooooot of tags you can use, but I will just list them down later.
Lets see what frame components do we have for the A-Engine. In LF2, the only think you could use in an object's dat file are frames. This isn't true for the A-Engine though!. In addition to having frames in your .a files, you can pack frames together in a sequence. For that to work though, the frames must have consequtive img numbers, same delay and center values.

Consider the following example:

Code:
[panda=py]
[f=4]
img=0 center=30, 30 delay=1 #the goto is automatically set to )4+1)
[/f]
[f=5]
img=1 center=30, 30 delay=1 #goto=5+1
[/f]
[f=6]
img=2 center=30, 30 delay=1 #goto=6+1
[/f]
[f=7]
img=3 center=30, 30 delay=1 #goto=7+1
[/f]
[f=8]
img=4 center=30, 30 delay=1 #goto=8+1
[/f]
[f=9]
img=5 center=30, 30 delay=1 #goto=9+1
[/f]
[f=10]
img=6 center=30, 30 delay=1 #goto=10+1
[/f]
[f=11]
img=7 center=30, 30 delay=1 goto=1000 #delete object
[/f]
Now using sequences (), that can be:
Code:
[panda=py]
[s=4->11]
img=0                   #will be incremented for every frame in the seq
center=30, 30 delay=1   #these will be common for all frames in the seq
goto=1000               #this goto will be executed at frame 11
[/s]

Note that it is possible to change a frame in the sequence if that particular frame was rewrote down:
Code:
[panda=py]
[f=4]
img=0 center=30, 30 delay=1 #the goto is automatically set to )4+1)
[/f]
[f=5]
img=1 center=30, 30 delay=1 #goto=5+1
[/f]
[f=6]
img=2 center=30, 30 delay=1 #goto=6+1
[/f]
[f=7]
img=3 center=123, 440 delay=433 #hey look! my tags are different!
[/f]
[f=8]
img=4 center=30, 30 delay=1 #goto=8+1
[/f]
[f=9]
img=5 center=30, 30 delay=1 #goto=9+1
[/f]
[f=10]
img=6 center=30, 30 delay=1 #goto=10+1
[/f]
[f=11]
img=7 center=30, 30 delay=1 goto=1000 #delete object
[/f]
with sequences you can do
Code:
[panda=py]
[s=4->11]
img=0 center=30, 30 delay=1 goto=1000              
[/s]
[f=7] #this frame will rewrite frame 7 in the sequence
img=3 center=123, 440 delay=433
[/f]


Oh and here is a list I rushed with, HOPEFULLY, all the in-frame tags you can use:
TagLF2's EquivalentUse
[f=x][/f]<frame> x name </frame>assigns the beginning and the end of a frame;x being the frame id
img=xpic:xthe id of the texture this frame should show
center=x,ycenterx:x centery:ythe coords of the point which acts as the object's feet
delay=xwait:xhow much extra (1/FPS)th of a second should this frame last
goto=xnext:xthe next frame to be played after this
x_vel=xdvx:xsets a velocity for your object on x-axis
y_vel=xdvy:xsets a velocity for your object on y-axis
z_vel=xNAsets a velocity for your object on z-axis
x_acc=xNAaccelerates the object on the x-axis; independent of object's "Inertia"
y_acc=xNAaccelerates the object on the y-axis; independent of object's "Inertia"
z_acc=xNAaccelerates the object on the z-axis; independent of object's "Inertia"
max_sx_limit=xNAsets a maximum allowed speed for the x-axis (regardless of the direction)
max_sy_limit=xNAsets a maximum allowed speed for the y-axis (regardless of the direction)
max_sz_limit=xNAsets a maximum allowed speed for the z-axis (regardless of the direction)
max_vx_limit=xNAsets a maximum allowed velocity for the x-axis
max_vy_limit=xNAsets a maximum allowed velocity for the y-axis
max_vz_limit=xNAsets a maximum allowed velocity for the z-axis
x_force=xNAaccelerates the object on the x-axis;considering the object's "Inertia"
y_force=xNAaccelerates the object on the y-axis;considering the object's "Inertia"
z_force=xNAaccelerates the object on the z-axis;considering the object's "Inertia"
x_drag=xNAdecelerates the object on the x-axis relative to its velocity; x-air resistance
y_drag=xNAdecelerates the object on the y-axis relative to its velocity; y-air resistance
z_drag=xNAdecelerates the object on the z-axis relative to its velocity; z-air resistance
x_hold_vel=xNAx velocity when the controller of the object holds "Forward" or "Backward"
y_hold_vel=xNAy velocity when the controller of the object holds "Up" or "Down"
z_hold_vel=xdvz:xz velocity when the controller of the object holds "Up" or "Down"
x_hold_acc=xNAaccelerates the object on the x-axis when the controller of the object holds "Forward" or "Backward"
y_hold_acc=xNAaccelerates the object on the y-axis when the controller of the object holds "Up" or "Down"
z_hold_acc=xNAaccelerates the object on the z-axis when the controller of the object holds "Up" or "Down"
x_hold_force=xNAaccelerates the object on the x-axis;considering the object's "Inertia", when the controller of the object holds "Forward" or "Backward"
y_hold_force=xNAaccelerates the object on the y-axis;considering the object's "Inertia", when the controller of the object holds "Up" or "Down"
z_hold_force=xNAaccelerates the object on the z-axis;considering the object's "Inertia", when the controller of the object holds "Up" or "Down"
c<a>=xhit_a:xan immediate destination from this frame when the controller clicks "Attack"
c<d>=xhit_d:xan immediate destination from this frame when the controller clicks "Defend"
c<j>=xhit_j:xan immediate destination from this frame when the controller clicks "Jump"
c<s>=xNAan immediate destination from this frame when the controller clicks "Special"
c<f>=xNAan immediate destination from this frame when the controller clicks "Forward"
c<b>=xNAan immediate destination from this frame when the controller clicks "Backward"
c<u_a>=xNAan immediate destination from this frame when the controller clicks "Up"
c<d_a>=xNAan immediate destination from this frame when the controller clicks "Down"
c<l_a>=xNAan immediate destination from this frame when the controller clicks "Left"
c<r_a>=xNAan immediate destination from this frame when the controller clicks "Right"
h<a>=xNAan immediate destination from this frame when the controller holds "Attack"
h<d>=xNAan immediate destination from this frame when the controller holds "Defend"
h<j>=xNAan immediate destination from this frame when the controller holds "Jump"
h<s>=xNAan immediate destination from this frame when the controller holds "Special"
h<f>=xNAan immediate destination from this frame when the controller holds "Forward"
h<b>=xNAan immediate destination from this frame when the controller holds "Backward"
h<u_a>=xNAan immediate destination from this frame when the controller holds "Up"
h<d_a>=xNAan immediate destination from this frame when the controller holds "Down"
h<l_a>=xNAan immediate destination from this frame when the controller holds "Left"
h<r_a>=xNAan immediate destination from this frame when the controller holds "Right"
add_hp=xNAadds x "Health Points"
add_sp=xmp:-xadds x "Stamina Points"
add_rp=xNAadds x "Rage points"
x_y_z_translate=x,y,zNAmove the object x pxs on the x-axis, y pxs on the y-axis and z pxs on the z-axis
alpha=xNAset a new alpha/transparency value for the sprite between 0-255
loop=x,y,zNAgoto frame z after the frame has been replayed x times if and only if the previous frame was y
set_reg=$x$,yNAsave the integer y in the register x, where x is any alphabet, capital or small. x can also be a "G_" followed by number between (0-100) incase you're saving to a global register
Frame Components:
In LF2, we had itrs and bdys for hits and damage related stuff, wpoints to set a position of a weapon if any is hold, cpoints for

catching, and opoints for spawning objects. In the A-Engine, these stuff are covered quite differently. The wpoints and the

cpoints were omitted. You've been given only 7 components that will hopefully cover all your needs:
1-The "set_rect[ ]" component (itr); for hits, platforming, catching or any other stuff that directly affects the target player.
2-The "set_bdy[ ]" component (bdy); for invulnerability areas, defending..etc.
3-The "call_object[ ]" component (opoint); for spawning new objects into the screen and controlling them around.
4-The "set_combination[ ]" component; for advanced keys input and combinations.
5-The "draw_shape[ ]" component; for drawing simple colored circles, rectangles, ellipses...etc.
6-The "set_transformation[ ]" component; for skewing, cutting, translating, stretching..etc of the sprites.
7-The "set_media[ ]" component (not implemented yet); for playing and simple editing of sounds and video clips.
Now lets try to do something with inputs. We will create a key combination that works just like Super Smash Brother's. To do this, we are going to be using the "set_combination" component. Here is a list of all the tags that can be used inside "set_combination[]":
TagUse
sequence=(args*)sets the sequence of the keys required for the combination to work. args you put can be c<x> for clicks and h<x> for holds, where x can be "a" for "Attack", "j" for "Jump", "d" for "Defend", "s" for "Special", "f" for "Forward", "b" for "Backward", "u_a" for "Up", "d_a" for "Down", "l_a" for "Left" or "r_a" for "Right. A maximum of 6 buttons can be put separated by a comma.
time_interval=xthe time interval in milliseconds required between each key press for the combination to work. Placing the magic number "4321" will ignore all the time between each press (just like LF2)
goto=xthe immediate destination frame when the combination conditions are met.
delay=xthe extra (1/FPS)th of a second the goto should wait before it immediately nexts to the destination frame
set_reg=$x$,ysave the integer y in the register x, where x is any alphabet, capital or small. x can also be a "G_" followed by number between (0-100) incase you're saving to a global register. This tag will only work when the combination happens successfully.
condition=putting a value of 0 (false) will make the Engine ignore this combination completely. To be used with the conditional operator.
Now lets start with a simple example first; Davis's Dragon punch combination (D^A):
Code:
[panda=py]set_combination[   #here is our combination component
sequence=(c<d>,c<u_a>,c<a>)
time_interval=4321   #we don't consider the delays b/w the presses
goto=250             #we goto the dragon punch frame
]  #the rest of the tags are unnecessary in this case

Now lets try to have dragon punch work in Smash Bros'  style. Having it as a smash Up attack would've been been clicking "Up" followed by "Attack" with a small time interval between the presses:
Code:
[panda=py]set_combination[   #here is our combination component
sequence=(c<u>,c<a>) #Up followed by attack
time_interval=100    #100 milliseconds being a 10th of a second is the interval b/w the 2 presses
goto=250             #we goto the dragon punch frame
]  #the rest of the tags are unnecessary in this case

As a light Up attack, it would've been holding Up and clicking attack while Up is held:
Code:
[panda=py]set_combination[   #here is our combination component
sequence=(h<u_a>,c<a>)#hold Up and then click Attack
time_interval=0   #no time interval at all. Up must be held when Attack is pressed
goto=250             #we goto the dragon punch frame
]  #the rest of the tags are unnecessary in this case

~To be continued


Last edited by A-MAN on 29th May 2014, 7:22 am; edited 2 times in total

◄∞▐▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▌∞►
avatar
A-MAN
Revolutionary Army
Revolutionary Army

A-MAN : Team A Leader
Posts : 2690
Reputation : 347
Bellies Bellies : 18841
Online
Offline


View user profile http://onepiecea-edition.yourme.net

Back to top Go down

Re: A-Engine Guide for LF2 coders

Post by A-MAN on 29th May 2014, 7:23 am

~UPDATE

◄∞▐▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▬▌∞►
avatar
A-MAN
Revolutionary Army
Revolutionary Army

A-MAN : Team A Leader
Posts : 2690
Reputation : 347
Bellies Bellies : 18841
Online
Offline


View user profile http://onepiecea-edition.yourme.net

Back to top Go down

View previous topic View next topic Back to top

- Similar topics

 
Permissions in this forum:
You cannot reply to topics in this forum