Thread Rating:
  • 5 Vote(s) - 3.8 Average
  • 1
  • 2
  • 3
  • 4
  • 5
The A-Engine: A new Beat 'em Up game engine
#58
A-Engine is a fighting game engine (no longer restricted to beat-em ups :P, even though, for now, it might still lack features if what you're doing isn't a beat'em up) written in C++ as I've mentioned in the first paragraph of the first post.
Quote:ok I see C++ Programming job.
So how much You made it?
I suppose you want to ask how long have I been working on this? around 1.5 years. I should've released the first version of this quite a while ago, but several recent events in my life have slowed me down a bit.

Enough of the programming language talk here, here is something that is more related to the topic:


A small article I wrote that explains expressions in A-Engine: http://opae.a-superlab.com/forum/viewtop...?f=14&t=43

Ctrl+V from forum:


It has been long since I last posted any A-Engine progress, and I thought I should post something just to let you guys know I am working on this. Here are some important updates from the top of my head, in brief, starting from what may concern you all the most:

-No more magic numbers. Constants. If anyone has read any of my old posts regarding the A-Engine, they'd be aware of "4321"; a number which usually means nothing and is often used to disable a tag. This has often looked weird and hindered readability when writing long logical expressions. Now, you simply type "NONE" in its place, and suddenly, it's all making sense. In other words, no more "4321". It's now "NONE" and is meant to be typed like that. In additions there are 3 more constants to make things more readable, "MATH_PI" (3.141..), "TRUE" (1) and "FALSE" (0).

-Re-written the pair of frame components which handled collision detection (set_rect[] and set_bdy[]). Now called set_culpritbox[] and set_victimbox[]:
Prototypes:
Code:
set_cultpritbox[
                   x= y= z= w= h= d= goto_when_success= damage= x_impact= y_impact= z_impact= hit_frequency=
                   effect= strength= knock= victim_goto= success_victim_goto= x_victim= y_victim= z_victim=
                   hit_density= flags= set_reg= set_victim_reg= remote_id= fetch_victim_data= x_y_z_effect_translate=
                   set_obj_reg= success_set_reg= success_set_obj_reg= success_set_victim_reg= success_fetch_victim_data=
                  ]
set_victimbox[
                 x= y= z= w= h= d= when_hit= defend= flags= resistivity= inertia= budged_dp= set_reg=
                 set_culprit_reg= set_object_reg= fetch_culprit_data= broken_dp= broken= budged= budged_resistivity=
                 budged_inertia= absorb_damage= absorb_strength= absorb_knock= absorb_x_impact=
                 absorb_y_impact= absorb_z_impact= penetrated_dp= defend_inertia= defend_resistivity= falling=
                 knocked= in_pain=
                 ]
While this might not be very cool to those of you whom came from an LF2 modding background , I had to do this to help making things more self-explanatory for everyone. The plan for the future is to have different variations of set_culpritXXX and set_victimXXX where XXX can be "box" for rectangular hitboxes, "point" for point hit"boxes", "circle" for circular hit"boxes", and so on.. In addition to the rename, I've added a whole bunch of new tags that adds lots of what you can do with them. Damage and defending states now can be handled in a much flexible way, although that required changing how "dp" (defend points) and "kp" (knock points) work a little bit.

-New pair of frame components: set_catchbox[] and set_caughtpoint[]:
Prototypes:
Code:
set_catchbox[
                 |THROWFRONT|FACESELF|FACEAWAY|THROWBACK|
                 id= x= y= z= w= h= d= x_caught= y_caught= z_caught= success= catch_period=
                 grip= damage= thrown_x_vel= thrown_y_vel= thrown_z_vel= state_caught_goto=
                 front_caught_goto= back_caught_goto= condition= flags= set_reg= set_object_reg=
                 set_victim_reg= fetch_victim_reg=
               ]
set_caughtpoint[
                    |SLIP|
                    x= y= z= condition= flags= set_reg= set_object_reg= set_culprit_reg=
                    fetch_culprit_data= escape= thrown=
                    ]
For doing grab attacks and generally anything where your goal is to control other object(s) on the screen (could be a pickable weapon or a vehicle or stuff I haven't thought of). And yes, you can use it to grab more than one targets at a time.

-Perfected expressions:
Finally got around fixing some bugs with how the engine parses and evaluates expressions. And now that the engine was capable of doing lots of calculations that makes a chasing ball, I believe I've finally made it perfect!
Here is a frame of a ball that chases only to the front, and limiting its movement to a max of 25 degrees to any of the directions, implemented in pure A-Script using set_reg= tags and expressions :
Code:
[f=0] #Chasing Energy Ball 1
# Get on-screen id of nearest object which id's not 500 and not of your team
set_reg=$t$, &get_nearest_obj{@id@==500 && @team@ != @this_team@}

# Store the difference in x/y/z positions
set_reg=$x$, &fetch_object_data{$t$, @x_position@} - @x_position@
set_reg=$y$, &fetch_object_data{$t$, @y_position@} - (@y_position@ + 30)
set_reg=$z$, &fetch_object_data{$t$, @z_position@} - @z_position@

# Cancel the whole thing if you're not facing the correct direction
set_reg=$x$, ~(@facing@ == 0 && $x$ > 0) || (@facing@ == 1 && $x$ < 0) ? $x$ : NONE;

# Calculate the x and the y angles from the target
set_reg=$a$, ~$x$ == NONE ? NONE : &atan{$y$/$x$};
set_reg=$b$, ~$x$ == NONE ? NONE : &atan{$z$/$x$};

# Limit the max angle to 25
set_reg=$a$, ~$a$ != NONE && $a$ > 25 ? 25 : $a$;
set_reg=$a$, ~$a$ != NONE && $a$ < -25 ? -25 : $a$;

set_reg=$b$, ~$b$ != NONE && $b$ > 25 ? 25 : $b$;
set_reg=$b$, ~$b$ != NONE && $b$ < -25 ? -25 : $b$;

# Calculate velocities according to the angles. But if no one is in front of you,
# get random offsets for velocity
set_reg=$y$, ~$a$ == NONE ? &randint{-2, 2} : ~@facing@ == 0? &sin{$a$} : -&sin{$a$}; * 15;
set_reg=$z$, ~$b$ == NONE ? &randint{-2, 2} : ~@facing@ == 0? &sin{$b$} : -&sin{$b$}; * 15;
set_reg=$x$, ~$x$ == NONE ? 13 : &cos{$a$} * 15;

img=0 center=56,24 delay=2 x_vel=$x$ y_vel=$y$ z_vel=$z$
set_transformation[center=56,24 x_scale_factor=$s$ y_scale_factor=$s$]
[/f]
All of this was a great test that proved expressions work wonderfully, but at the same time, writing up all this just to have the ball chasing someone was a bit of an over-work. For that reason, I worked on a new frame component "track_target[]" which provided tags that does this for you in a line or two.

-New frame component: track_target[]:
Prototype
Code:
track_target[
                 |FACEFORWARD|FACEBACKWARD|
                 target_id= x_acc= y_acc= z_acc= r_acc= max_x_vel= max_y_vel= max_z_vel= max_r_vel= condition=
                 fetch_target_data= set_obj_reg= set_reg= set_target_reg= x_vel= y_vel= z_vel= x_y_z_offset= max_xz_angle=
                 max_xy_angle= store_xz_angle= store_xy_angle=
]
I am not going to explain how that works in detail, since everything will be explained in the documentation, but what you use it for is tracking a target. You will mostly find this useful when coding say a chasing energy ball, or a targeting system perhaps.

-Main loop's Time Blocks:
For those who don't know what a main loop in the A-Engine is, it basically is a block of tags surrounded by "{main_loop}{/main_loop}". These tags are to be run in every frame. You can use "set_reg =", "add_hp =", "add_sp =" and other tags that has to do with points, in addition to the recent addition of "call_object[]" and "call_sound[]" frame components which allow you to spawn either an object or play a sound in every frame iteration. You usually would use a main loop when you'd want to set a timer or spawn objects, say sweat particles, every frame period regardless of the frame you're in. You may as well now use it in stage files to do things like spawning lightnings or meteors. Time blocks allow you to set a time interval where the tags written in its block would run:
Code:
{main_loop}
add_hp = 10; #add 10 Health points every frame unit of time.
:30; #a time block; every tag beneath would run only once every 30 frames
add_hp = 20; #add 20 HP every 30 frames
:120; #another time block
#..etc..etc  
{/main_loop}

-Dividing your character/object into multiple files:
The "#import[filename.a];" in-file tag will import and replace itself with the content of the file in between the [] when the file is loaded. This allows you to divide your files and helps with readability:
http://i.imgur.com/A1fBloP.png (only template/main.a file is loaded, and it imports the rest)
You may as well place the assets and everything that has to do with your character in its own folder.


-Now for what's being focused on currently:
.Reworking the stage (BG) files. Adding more tags and features that makes creating stages much more flexible. Layers won't have an id anymore, and are now divided into [fgl] and [bgl] (foreground layers that are rendered to the front of objects and background layers that are rendered at the back). New tags that has to do with automatically generating stage elements and bgs of infinite (or very huge) boundaries.
.Started working on the A-Coder; A simple editor in C++ being written with the wxWidgets libraries. Supports auto-completion and syntax highlighting that helps with faster development.

-A word on the release:
It's getting close. If you've read that post in the chit-chat thread, then you probably understand the gravity of the situation where I am. I have been working really hard with mostly all the time I've got, and I'm glad to say everything is going smooth and steady (but slow =P). I will do my best to keep on updating this thread, even if with no much details.

Few decisions I've made regarding the first A-Engine release (Beta 1.0):

.No platform objects: While the A-Engine has promised to have that feature early, I am sorry to say it won't make it to the first A-Engine release. I am planning to use "Box2D", and amazing physics library that is capable of doing mechanical physics to a huge degree of accuracy and in a very optimized manner. You're free to use the current platforms functionality within the "set_culpritrect[]" frame component, but beware as it will be completely replaced later with something new and much more robust in the future.

.Shadows: You all saw how OPAE makes use of these cool pre-rendered shadows? I am sorry to say there is a chance (even though it might still not happen) that I am going to keep it as simple as a circular shadow for the first A-Engine release, and here is why: They're overly simple direct projections of the sprites as it becomes evident the moment you stand on a platform. In the future, I plan to make allow loading 3D-models for buildings or anything with a remarkable size in the z-axis. With that, shadows which can blend and turn and twist according to its surroundings will be possible to do, and I really don't want to re-work the shadows in the future now that I have a clear vision for how I would like them to be.

.No custom AI: Yes, I know, this really sucks, but it's all for the sake of getting a first build to work with. The plan for the future is to allow writing up AI in 2 different ways:
1-Using a real scripting language. Considering Python and Angel Script (for all of those who've came from the LF2 community and have already gotten used to Angel Script): This option will allow full control to what your AI will be able to do.
2-Using a simplified fixed "pipeline" for the beginners: Very simple AI written in A-Script. It will probably involve simple tags that defines conditions and corresponding key-combinations.

.VS mode only: Well.. Yes.. VS MODE ONLY. I can justify: At first, the plan was to get fixed common modes (VS mode, stage mode, battle mode, story mode) that can be mapped to different game mode options in the menu. But then I thought it might be better to just give the developers the freedom to set rules for any mode they'd want to code. Time battles, DBZ's Tenkaichi Budokai tournament rules where players can lose if they're out of the ring, etc..etc should all be possible to code with "mode logic" a-files. The following is an example pseudo-code that shows how I am planning to have these work (an example of a timed mode and Harry Potter's "Squiddish" game mode):
http://pastebin.com/bn6W7xwk
Implementing that would take time to make it to the first release, however, I promise to make it my first priority in the next release.

.ENOUGH with optimizations, for now, for the sake of the release: I have got to admit the A-Engine is pretty slow currently. The engine can begin to hiccup at around 50 objects on the screen on some computers. The reason behind that can be summed up in the following 2 reasons:
1-Expressions: In order to be able to do all the awesome stuff with the registers, functions and variables, the values of the tags had to be stored in "string" variables. These are quite expensive to operate with, especially that what I am doing is effectively creating 1000s of new strings every frame as a result of parsing and converting them to other appropriate types after evaluation. A solution to this problem became clear the moment I adopted C++11 and learnt about the new "auto" identifier. Implementing the solution is very straightforward but time consuming which is why I wanted to leave this for later. Turned out that can't work.
2-Collision detection: is pretty darn slow. I've considered, and in fact already implemented a Quad-Trees based solution for this, but I came across several conflicts with other tags that requires lots of tuning I will be doing later. For that, I had reverted back to the old nested looping ways until then.

Finally, I will do my best to try and post here every now and then. Questions or suggestions will be hopefully answered and considered.
[Image: signature.png]
A-Engine: A new beat em up game engine inspired by LF2. Coming soon

A-Engine Dev Blog - Update #8: Timeout

Reply
Thanks given by:


Messages In This Thread
RE: The A-Engine: A new Beat 'em Up game engine - by A-Man - 06-22-2015, 08:48 PM
A-Engine Supports 3D! - by A-Man - 11-23-2015, 07:40 AM
The A-Engine: Naming Conventions - by A-Man - 01-04-2016, 07:16 PM



Users browsing this thread: 4 Guest(s)