Windows Warp3D - Game Engine, Level Editor & Model Editor - Free Exe Demo Out Now

Joe Ellis

Member
@Micah_DS Thanks for the links about the d3d format, it looks like it'll be quite simple to do and I'm definitely gonna make import and export for it.

The skeletal system is pure gml and shaders so it should work in html. I don't know if the built in 3d settings and functions work the same in html and if there would be problems, but most of the things as they're all in gml should work on all the other platforms apart from the way the engine handles textures through the dll. It's making me wonder if I should back track to using sprites as textures.. it'd be more awkward but maybe worth it. It doesn't make a good enough difference to me but I'm thinking of what other people want at this point.

Well it's cool how you're thinking of moving to using my model program instead. Or maybe it can just be a useful addition to your set of tools, as it's still compatible with other model editors through obj format and soon d3d, so if there are things you'd rather do in other programs, you can.
 

Yal

🐧 *penguin noises*
GMC Elder
Really looking forward to this! I've been working on getting one of my old 3D projects up to speed, but a lot of its limitations (and my limitations :p) are making it clear it'll have a much lower quality ceiling than Warp3D... so not sure I'm gonna use my project myself if there's better options to choose from xP

Since you explicitly wondered about other people doing 3D stuff in GM a few pages back, you could perhaps be interested in my approach?

My system uses objects for collision checking (but has a single model for all the level geometry, so you won't notice objects being deactivated further away), which simplifies a lot of things but also makes levels need to be based off of a rectangular grid (so the building blocks fits together). Slopes and such are handled by a "prism" object whose four corners may have different height. Things are sped up by a quadtree / hashmap system that minimizes looping, and deactivation as well.

There's a dynamic lighting system which supports an arbitrary amount of active lights at once - since GL ES 1.0 has a very strict limit on how many uniforms you can pass in, I solved this by passing in a texture with data encoded in color. The shader is a bit of a kitchen sink that applies light, specular highlights, (hacky simplified) normal maps, and a simple shadow map system where objects draw 2D shadows which get applied to all horizontal surfaces - I implemented dynamic shadows too at first, but the precision is so bad if you keep texture sizes small and compatible it just didn't look good at all.

I implemented volumetric lightning as well, using a pretty simple approach: lights render spheres and cones based off of their area of effect, and it's drawn to a very small canvas and then blurred and stretched and overlaid on top of the normal scene.

Yesteday I spent hours fixing an issue where dynamic models (i.e. anything other than the terrain) would apparently use both object and world space coordinates at once for lightning calculations, couldn't find the root cause, and eventually gave up on fixing it - so my workaround was to give the entire model the same flat lighting based off of a single point. Good enough for flat sprites, but it's a big failure for 3D models :V
1586687941490.png
 

Joe Ellis

Member
@Yal That sounds like some cool stuff!
The dynamic lighting system with info onto a texture seems like a really good idea that I hadn't really thought of doing, thanks for sharing that :)

It could make it possible to use alot of lights without a for loop in the shader aswell as being able to supply way more info than uniforms.
Each instance would be able to have a set of uvs for each of the lights it's affected by and could be gotten by getting the instance's grid cell and lights that are in that cell.
The only thing I'm worried about is the number of texture reads it'd have to do, cus the x, y and z would need a separate pixel each and be packed into 24 bit values, aswell as the radius unless it was an 8bit value and multiplied by a "max_radius" value and then could be in the a channel of rgb. So it would be 4 texture reads * by the number of lights each instance is affected by, so 8 at minimum, Which might be ok.
It could be possible to write the xyz as a single pixel and use a grid_res, but might be too limited..

I might try and do something like this at some point. I still haven't really made a solid decision for the lighting system, cus there are so many different ways you could do it. At the minute I'm just using separate instances for dynamic lights, which is ok for temporary things like light from guns, projectiles and explosions, but I need to think of a better way to handle lots of static lights, preferably rendering all of them in a single batch. But your idea has given me a few extra things to consider
 

Joe Ellis

Member

I found the old vertex texture sampling dll and made a new demo with it.
I'm planning on trying to see what else you can do with this.
The next thing I'm going to try is using it with a geosphere and wrapped spherical mapping,
cus I'm just using a polar sphere with d3d_draw_ellipsoid on the demo, so that'll remove that weird spike in the middle.

There will be a few examples of using this in Warp3D but you can get the dll, source code and demo project here:
https://forum.yoyogames.com/index.php?threads/gm-community-dll-collection-discussion.70032/
 

Joe Ellis

Member
Got some nice eye candy things here while I'm getting the engine bug free and ready to use..

I was messing about with fog, setting a long distance so it's more of a haze..
and then found that if the sky sphere isn't aligned with the view position it creates a nice glow across the sky:







Also tested dynamic lights moving about and stuff, runs fine of course cus the engine is amazing, also introducing the wonders of minge!


The video is the result of the new dynamic light system I worked out this week @Yal
It works with instances at heart, instances that in their activate event (user event1) they call light_update()
Which, if the instance hasn't been registered to the global.lights list,
it adds it, gives it a light_index (for the light data arrays passed into the shader)
and adds it's position, color and radius to the light data arrays that are passed to the shader.
The shader takes in the positions, colors and radiuses of all the lights and applies it to the geometry;
and goes up in bands of 8, so if only 8 lights are active, it uses shd_lights_x8, if more than 8 are active it uses shd_lights_x16, and again with shd_lights_x24.
Also with the fact that the lights are instances, they automatically have light_update() in their activate event (event_user1) and light_remove() when they're deactivated (in event_user2)
So they'll work automatically without any set up, besides setting their position, color and radius.
Also the fact that they're handled with instances allows you to make any type of light object you want, with a step event that could..
be a torch or candle, be a projectile, an explosion.. increasing\decreasing the radius and brightness of the color,
a magical effect when you collect something. etc.

So I'm pretty happy with this lighting system, it'll be great for many games' purposes..
The only thing it can't do is use normalmapping, as it doesn't use textures.. it adds the light as a separate pass than the actual material stuff, so for normalmapping to work you'd have to disable the deferred lighting pass and just do it all in one shader instead. But this is all supported anyway, it's just the priority I'm designing the engine is for more cartoony and retro looking games, as this is kind of what the gms engine is best for handling
 

Joe Ellis

Member

I've made collision for the 3rd person camera so it doesn't go through walls,
which is essential really so I'm glad I got this working. It could be better maybe,
but it's acceptable for a template.
I haven't got much else done this week apart from a few bug fixes.
I haven't felt very good this week, I think I had a down period with my cyclothymia,
but it could also have been cus I haven't seen my friends in quite a while, cus I heard
alot of people have been depressed recently cus of that.

I feel ok again now though, so I'll get more done next week.

I'm planning on releasing an exe demo of the engine as soon as possible so
everyone can try it out and decide if they actually wanna use it.
 
That is something carrying Game Maker's potentials upwards. If it is compatible with GMS 1.4 (which I use it because my Windows is 32-bit) I can consider using it after I upgraded myself a lot.

Keep working!
 

Joe Ellis

Member
Update-

The model editor is completely finished and bug free

Rom packing complete, which is needed for when a game is finished or compiled as an exe
(Which I'm going to use for the playable demo exe game, then I can include textures that I bought but can't resell with the editor)

Built in loading screen and fade in out while loading levels (easily customizable)

Bullet collisions (instant line collisions)

Weapon handling for the 1st person player,
fire rate, ammo depletion etc. all built into a single object "obj_gun", which can be turned into any type of gun by editing it's variables and then saved as a "preset" (saved instance)
several guns will be included as templates:
pistol (single bullet)
shotgun (scattered several bullets)
machinegun (rapid fire bullets with lower accuracy than a pistol)
bomb launcher
bazooka
flamethrower
lightning gun

Game gui\hud displaying health, armour and ammo for the current weapon (easily customizable)

New player object, one which follows a path left and right like games like pandemonium and klonoa.

I've also implemented a completely new thing, which I've been thinking about since the beginning of the engine but never worked out a way that I was comfortable with, but I surprisingly had an epiphany the night before and got it all set up the next day.
"Events" or "Sequences" Basically a list of actions\scripts that are run in a sequence one after the other, and can include pauses\gaps where it waits for a certain amount of frames before doing the next thing.
So this has made loads more cool things possible, like explosion sequences, cut-scenes, complex triggers which do several things at once like turn off 3 lights, turn off a machine, play a powering down sound and alert 3 enemies.

The scripts are handled as "actions", which have to be predefined on startup,
you basically call action_begin(name, script)
then add the arguments the script uses in the same way you define variables for an object:

action_begin("Set Model", instance_set_model)
var_instance("Instance")
var_model("Model", "default")
action_end()

action_begin("Instance Set Variable", _variable_instance_set)
var_instance("Instance")
var_string("Var Name", "none")
var_any("Value")
action_end()

This is giving the engine the variables\arguments and their type that the action needs to know for the script it uses.
Then you simply drag and drop the actions into an event.

The event displays the list of actions on the left and the highlighted action's argument values on the right:


Then the event can be triggered\played by any instance in the level, usually done by a trigger type object.

It seems perfect, so hopefully tests will confirm this :)


About the pandemonium style player:

It works by making a path for the player to walk along and one for the camera that moves as the player does, but the camera's path points are offset to make the camera face more forwards or backwards and I seem to have nailed the way the camera worked on pandemonium:



Also here's a video of the shotgun in action:



So in summary, the engine is pretty much fully functional. All I'm doing now is making sure there's plenty of example code and objects to work with so people aren't lost when they start using it. I feel this is one of the most important parts.
It's things like, I've got weapons sorted, firing them and different ways they work, but not switching between weapons yet, so it'd be kind of crap if I didn't include this, people would feel like the guy doesn't care, which I don't want and isn't the case.
I have sorted the weapon switching though this week, just need to test it out.
But there's a few other things like that where I can't include one thing without the other that goes with it, so I'm just gonna try to buckle down and get them all sorted. thumbsup

But a playable demo will be coming really soon, and also a free exe version of the two editors, which will be able to save\load levels and models the same as the full\project version, so you can spend as long as you want trying it out and deciding whether it's worth buying or not.

Let's watch one more spyro video, I couldn't resist

 

Micah_DS

Member
I don't think I ever commented on the editor's GUI, but I find it very soothing, like it'd be pleasant to work in. Perhaps it has something to do with Windows 3.1 through 98 being my childhood? :p It reminds me of those operating systems. Of course, the updates on the project are also exciting me, as always. :)
 

Joe Ellis

Member
Let's have a look at the unfinished 1st person template:

Suicide Groundhog Day

When there are no enemies in the level, the only goal is to die as soon as possible,
here are my attempts:


I might need to adjust the radius of the explosions, cus I was really close to loads of them but didn't get hurt :( and yes, some of the guns are still yellow.

But as you can see it's got weapon pickups and switching, ammo,
the player can get hurt by explosions and the screen flashes red,
the more hurt the more red it goes.
The player takes fall damage, and can die, which it states when you are dead.

The weapons currently are:

Handgun\pistol
shotgun
machinegun
bomb launcher
Bazooka

I also did a cool thing with the explosion sounds where it mixes 3 sounds
together at random ratios so that each explosion sounds different.

Also the menu works with saving and loading games, you can literally save
the game whenever you want and it'll load the game in the exact state that was saved,
which is obviously a really sought after feature.

I've also made a PBR shader, I basically copied and pasted the shader from the gl tutorials site,
then condensed it into 10 lines instead of 100, which will be faster cus there are alot less
variables\vectors created and several of them are reused instead of being created 3-4 times.

Next I'm gonna make it work with maps for roughness, metalicness and attentuation.
But I'm gonna make it use one texture for all 3, cus it's so wastful how they're all grayscale,
so I'll make a simple combiner that combines the 3 into one texture per color channel,
and maybe if there could be a 4th one that can go into the alpha. Ah! the ambient occulsion

The thing I love about this pbr shader is that it's so veratile and can literally be used
for every material in the game, which is great for performance cus only one shader needs
to be set, and global uniforms like the sun direction and color only need to be set once
instead of for every shader used.

So, what is there left to finish?

A template enemy that has a state based ai. (Mostly coded but I need to test it and probably
tweak things to do with avoiding walls and ledges)

A template generic animated character model, that the enemies will use and
the player when it's 3rd person

Attatching weapons to character's hands, using the animations & the positions and rotations of
the bones. This is also coded, but I haven't had a chance to test it yet, but
it should work cus I coded it right, converting the dual quaternions of the bone's frames,
lerping them based on the frame_merge (point it's at during merge from frame1 to frame2),
then normalizing them in the same way the shader does
and then converting it to a matrix, then multiplying that with the gun's base matrix
Gotta say thanks to @TheSnidr for the conversion from dualquat to matrix, cus his project had a script for this so I just copied and pasted it from that, lol

The plasma rifle (that shoots actual projectiles, like on the video from a few months back
where it bounces off walls) (basically done before, just need to put it into the plasma rifle)

A simple melee weapon, like a hammer or just fists, I need to make at least one
melee weapon just so it's in there for a start, I'll make more after the first release,
like an add on, melee weapon preset pack or something.
But I need to at least make the object that handles this, cus it needs to be
a different object to the guns.

And then, the 3rd person template, I'm not sure what to do for it,
I'm gonna use all the same stuff from the 1st person template, but
the character will have animations and hold each weapon in it's hand.
And then I'll make a basic level with platforms and stuff.
Most of this stuff has been done before, and it all works,
but there's the thing with the player's health, ammo etc.
So I'll just make it the same as the 1st person player, then
it's like a 3rd person rpg type game, and if someone wants to make
a simpler type of game they can simply not use\take out certain bits
 
Last edited:

Joe Ellis

Member
hey could you explain your "depixelizing technique" a bit further, I'm looking for a way to get rid of that jagged horizontal edges without soften them
Hi, I'm not sure how to explain it that well,
it worked by getting 16 samples of the shadowmap spread out from the uv, subtracting the pixel's depth\id then adding them together and dividing it by the biggest difference, then use a few uniforms to compress the range to sharpen it.
I've got the shader code here:
//Create 8 uv offsets for sampling
vec2
uv1 = u_texel_size * normalize(vec2(-1.0, -1.0)),
uv2 = u_texel_size * normalize(vec2(0.0, -1.0)),
uv3 = u_texel_size * normalize(vec2(1.0, -1.0)),
uv4 = u_texel_size * normalize(vec2(1.0, 0.0)),
uv5 = u_texel_size * normalize(vec2(1.0, 1.0)),
uv6 = u_texel_size * normalize(vec2(0.0, 1.0)),
uv7 = u_texel_size * normalize(vec2(-1.0, 1.0)),
uv8 = u_texel_size * normalize(vec2(-1.0, 0.0));

//Sample the shadowmap and get the differences between the id of each sample and the object's id
float
s1 = abs(texture2D(smp_shadowmap, uv + uv1).x - u_id),
s2 = abs(texture2D(smp_shadowmap, uv + uv2).x - u_id),
s3 = abs(texture2D(smp_shadowmap, uv + uv3).x - u_id),
s4 = abs(texture2D(smp_shadowmap, uv + uv4).x - u_id),
s5 = abs(texture2D(smp_shadowmap, uv + uv5).x - u_id),
s6 = abs(texture2D(smp_shadowmap, uv + uv6).x - u_id),
s7 = abs(texture2D(smp_shadowmap, uv + uv7).x - u_id),
s8 = abs(texture2D(smp_shadowmap, uv + uv8).x - u_id),
s9 = abs(texture2D(smp_shadowmap, uv + (uv1 * 2.0)).x - u_id),
s10 = abs(texture2D(smp_shadowmap, uv + (uv2 * 2.0)).x - u_id),
s11 = abs(texture2D(smp_shadowmap, uv + (uv3 * 2.0)).x - u_id),
s12 = abs(texture2D(smp_shadowmap, uv + (uv4 * 2.0)).x - u_id),
s13 = abs(texture2D(smp_shadowmap, uv + (uv5 * 2.0)).x - u_id),
s14 = abs(texture2D(smp_shadowmap, uv + (uv6 * 2.0)).x - u_id),
s15 = abs(texture2D(smp_shadowmap, uv + (uv7 * 2.0)).x - u_id),
s16 = abs(texture2D(smp_shadowmap, uv + (uv8 * 2.0)).x - u_id);

float result = 14.0;

//Check there is at least 1 sample with the object's id (if there are none the shade will be full shadow)
if (sign(s1*s2*s3*s4*s5*s6*s7*s8*s9*s10*s11*s12*s13*s14*s15*s16) == 0.0)
{
//Divide sum by the biggest difference
result = (s1+s2+s3+s4+s5+s6+s7+s8+s9+s10+s11+s12+s13+s14+s15+s16) /
max(s1, max(s2, max(s3, max(s4, max(s5, max(s6, max(s7, max(s8, max(s9, max(s10, max(s11, max(s12, max(s13, max(s14, max(s15, s16)))))))))))))));
}

shade = min(1.0, max(0.0, 2.0 * min(1.0, shade * u_bright * (u_cap - (min(u_blur, max(0.0, (result - u_bias) * u_strength)) / u_blur)))));
But this version was using id mapping instead of depth mapping, so it was alot simpler to do, and I couldn't recreate the exact results when I changed it to depthmapping, and I had to add a couple of extra things to stop weird artifacts happening, and I'm still trying to find the project that had it working properly, cus I've got about 20 different versions of it and I can't remember which one it was, but I'll let you know when I find it.
I would recommend using id mapping though if it's possible, cus it is alot easier to work with and experiment with in the shader, but it is more awkward to set up each object (or group of faces) having different id's.
If you don't know how it works, you basically give each model a different id which gets rendered to the shadowmap, then all the shader has to do is ask if the current pixel's id is the same as the id on the shadowmap, if it's different something else must be in front of it.
 
Hi, I'm not sure how to explain it that well,
it worked by getting 16 samples of the shadowmap spread out from the uv, subtracting the pixel's depth\id then adding them together and dividing it by the biggest difference, then use a few uniforms to compress the range to sharpen it.
I've got the shader code here:
//Create 8 uv offsets for sampling
vec2
uv1 = u_texel_size * normalize(vec2(-1.0, -1.0)),
uv2 = u_texel_size * normalize(vec2(0.0, -1.0)),
uv3 = u_texel_size * normalize(vec2(1.0, -1.0)),
uv4 = u_texel_size * normalize(vec2(1.0, 0.0)),
uv5 = u_texel_size * normalize(vec2(1.0, 1.0)),
uv6 = u_texel_size * normalize(vec2(0.0, 1.0)),
uv7 = u_texel_size * normalize(vec2(-1.0, 1.0)),
uv8 = u_texel_size * normalize(vec2(-1.0, 0.0));

//Sample the shadowmap and get the differences between the id of each sample and the object's id
float
s1 = abs(texture2D(smp_shadowmap, uv + uv1).x - u_id),
s2 = abs(texture2D(smp_shadowmap, uv + uv2).x - u_id),
s3 = abs(texture2D(smp_shadowmap, uv + uv3).x - u_id),
s4 = abs(texture2D(smp_shadowmap, uv + uv4).x - u_id),
s5 = abs(texture2D(smp_shadowmap, uv + uv5).x - u_id),
s6 = abs(texture2D(smp_shadowmap, uv + uv6).x - u_id),
s7 = abs(texture2D(smp_shadowmap, uv + uv7).x - u_id),
s8 = abs(texture2D(smp_shadowmap, uv + uv8).x - u_id),
s9 = abs(texture2D(smp_shadowmap, uv + (uv1 * 2.0)).x - u_id),
s10 = abs(texture2D(smp_shadowmap, uv + (uv2 * 2.0)).x - u_id),
s11 = abs(texture2D(smp_shadowmap, uv + (uv3 * 2.0)).x - u_id),
s12 = abs(texture2D(smp_shadowmap, uv + (uv4 * 2.0)).x - u_id),
s13 = abs(texture2D(smp_shadowmap, uv + (uv5 * 2.0)).x - u_id),
s14 = abs(texture2D(smp_shadowmap, uv + (uv6 * 2.0)).x - u_id),
s15 = abs(texture2D(smp_shadowmap, uv + (uv7 * 2.0)).x - u_id),
s16 = abs(texture2D(smp_shadowmap, uv + (uv8 * 2.0)).x - u_id);

float result = 14.0;

//Check there is at least 1 sample with the object's id (if there are none the shade will be full shadow)
if (sign(s1*s2*s3*s4*s5*s6*s7*s8*s9*s10*s11*s12*s13*s14*s15*s16) == 0.0)
{
//Divide sum by the biggest difference
result = (s1+s2+s3+s4+s5+s6+s7+s8+s9+s10+s11+s12+s13+s14+s15+s16) /
max(s1, max(s2, max(s3, max(s4, max(s5, max(s6, max(s7, max(s8, max(s9, max(s10, max(s11, max(s12, max(s13, max(s14, max(s15, s16)))))))))))))));
}

shade = min(1.0, max(0.0, 2.0 * min(1.0, shade * u_bright * (u_cap - (min(u_blur, max(0.0, (result - u_bias) * u_strength)) / u_blur)))));
But this version was using id mapping instead of depth mapping, so it was alot simpler to do, and I couldn't recreate the exact results when I changed it to depthmapping, and I had to add a couple of extra things to stop weird artifacts happening, and I'm still trying to find the project that had it working properly, cus I've got about 20 different versions of it and I can't remember which one it was, but I'll let you know when I find it.
I would recommend using id mapping though if it's possible, cus it is alot easier to work with and experiment with in the shader, but it is more awkward to set up each object (or group of faces) having different id's.
If you don't know how it works, you basically give each model a different id which gets rendered to the shadowmap, then all the shader has to do is ask if the current pixel's id is the same as the id on the shadowmap, if it's different something else must be in front of it.

actually I had id mapping implemented in order to avoid self shadowing, tho it didn't quite work well for me, I guess I need to bring camera closer and calculate the range more precisely, thanks for answering btw
 

Joe Ellis

Member

I've done more stuff for the shooter template,

I've made a basic enemy ai similar to doom. They walk towards the player but offset at random angles and shoot at the player at random times. It needs a few improvements like making them not walk off ledges over a certain height, and maybe strafing side to side sometimes to make them harder to hit. But I'm quite happy with how they turned out so far. They use a good "sight checking" script, which is the same method as the bullet collision script using a ray and finding out which triangles it intersects, only it simply returns false as soon as there is an intersection rather than having to get the closest intersection, so it's pretty efficient.

I've made a basic inventory menu, with 3d thumbnails for each item and has multiple pages/catagories, it still needs improvements like making the last item picked up or used be the highlighted one when it pops up, and also they currently display in the order you picked them up, which doesn't feel that good with the weapons cus they're like: shotgun, handgun, machinegun, bomb launcher.
So I'm going to make it display them in the order they're defined: handgun, shotgun, machinegun, bomb launcher
But I'll still keep the other way cus it might be better for some games like rpg's, and I'll make a grid version aswell.

Also made a better item handling system where you define items in a script that runs when the game loads up, so they're global resources,
making it alot easier to organize all the different types of items and what they do.
Eg. for item pickups, there is now only one object (obj_item) and you can choose the actual item resource that it uses, then the model and pickup script are automatically used for that item.
This makes it alot easier in cases if you change what an item does or it's appearance, you simply change it in the init script and the change will be applied to all item pickups in the game. Otherwise you'd have to update each item pickup instance separately.

I also made a teleporter (Every game needs a teleporter ;D)
 

Joe Ellis

Member
Hi everyone,
The program itself is finished now.
So I'm going to release for free download an exe version of it!
So you can try out the 2 editors, make levels, models, materials and save them.
The only thing you won't be able to do is program things in gml.
So this is basically the evaluation version, which I think is fair cus if you use it for a while and end up deciding you're not gonna make your 3d game with it, you haven't wasted 30$ that you would've spent out of curiosity if there wasn't this version.

Before the official "paid" version, I still need to finish the example projects for the 1st person shooter and 3d platformer, although both of these are working in code sense, I need to make a few models for characters, to implement the animation part, and make enemies for the 3d platformer.

But I came up with a perfect idea for the platformer demo:

A turtle as the main character (easy to model and animate)
and he has several abilties:

He can belch fireballs
He can charge(run very fast), his head sucks into the shell and he's a running turtle shell (Very dangerous)
He can curl up into his shell for safety, and he can also skid\slide if he does this while running
and if you press jump while in mid air, a helicopter\propellor comes out of the top of his shell and he does a slow helicopter glide like on rayman 2 & 3

Then the enemies are gonna be:

A big cave monster, that throws boulders at you if you're far away
and if you're close he thumps you, or hits you with a club

and for small enemies, evil helicopter gremlins that fly up and down\left and right and spit acid balls at you.

and also some kind of simple ones that walk up and down a certain spot,
and maybe ones that stand around and fire canon balls at you from their blunderbusses.

So I think with all of those, it will provide a wide range of things that are normally in 3d platformers, thus creating a good template to work from :D

Here's a video of the 3d platformer demo\player object,
and this is the main reason why I started making this engine, so I could make a 3d platformer that's kind of a cross between spyro, medievil and rayman 2. The level on the video is a spyro level :D I have made a few of my own, but for making a cool video, the spyro levels are alot better. (I need to stop using the spyro levels to advertize my product, sooner or later insomniac games are gonna cop my ass)

I've also debuted my own music on this video, I would be nervous, but jolo applies so it's fine

 

Joe Ellis

Member
Looks really good man! I wonder, what do you do to calculate the 3D collisions?
Thanks!

It mostly uses spherical collisions, I don't know if you know about them so I'll explain about them:

The concept is that the instance has a sphere radius around it's position.
If any triangles intersect the sphere, you push the instance back so that the sphere is in contact with the triangle's surface.

First you make a vector from the instance's position to one of the triangle's vertices (any will give the same result)
and get the dot product of this vector and the triangle's normal.
This gives the distance from the instance to the nearest point on the triangle's plane,
(It could be negative or positive depending what side of the triangle the instance is on, but when multiplied with the triangle's normal it gives the right direction to push the instance back)

So if the abs(distance) is less than the sphere radius, it means the instance's sphere is colliding with the triangle's plane.
Then you just need to push the instance back, using the triangle's normal * (the sphere radius - the distance).

However this point could be miles away from the actual triangle, as it just gives the nearest point along the triangle's plane.

So then you need to check whether the point is inside the triangle. There are a few ways to do this, but I started using one that involves precalculated "edge tangents". As it cuts out a few cross products and other calculations.

These tangents are made by getting the cross product of each edge vector and the triangle's normal, which produces a vector that sticks out from the edge at 90 degrees and also lies along the triangle's plane.

So then you can use dot products of each edge tangent and the vectors from the instance to one of the vertices on each edge.
If there is more than 90 degrees difference (if the dot is < 0), the nearest point is outside the triangle.
You can see from this picture:

All the green lines have < 90 degrees difference from the edge tangents
and the red ones are > 90 degrees difference with the nearest edge's tangent

I also drew this to explain what's happening more in 3d, but it turned out a bit confusing lol:


I was trying to show how it kind of creates an invisible prism, and the check is getting whether the instance is inside this prism or not.

Anyway, if it passes all 3 edge checks, the nearest point is inside the triangle, then all you have to do is push the instance back using the triangle's normal and the original distance we got from the 1st dot product.

If it's outside the triangle, the sphere could still intersect one of the edges.
Luckily only one of the edge checks can fail at a time, and the one that fails is the nearest, so then you just have to get the nearest point along the edge and check if this point is inside the sphere (ei. distance to the point < sphere radius)
then push the instance back in the direction to the nearest point * (sphere radius - distance).

Here is the full code:
It might be able to be improved and optimized in some places, I'm not sure, but it seems to work fine and is pretty fast, probably cus most triangles don't make it past the initial distance check (plus a bbox check before that)

GML:
///collision_precise_ball(list of triangles)

var
l = argument0, i = 0, t, vx, vy, vz, d, nx, ny, nz;

repeat l[0]
{
t = l[++i]

//Bbox check
if rectangle_in_rectangle(bbox_x1, bbox_y1, bbox_x2, bbox_y2, t[_tri.bbox_x1], t[_tri.bbox_y1], t[_tri.bbox_x2], t[_tri.bbox_y2])
&& rectangle_in_rectangle(1, bbox_z1, 1, bbox_z2, 0, t[_tri.bbox_z1], 1, t[_tri.bbox_z2])
{
vx = x - t[_tri.x1]
vy = y - t[_tri.y1]
vz = z - t[_tri.z1]
d = dot_product_3d(vx, vy, vz, t[_tri.nx], t[_tri.ny], t[_tri.nz])

//Distance Check
if abs(d) < mask_radius
{

//Edge 1 Check
if dot_product_3d_normalised(vx, vy, vz, t[_tri.t1x], t[_tri.t1y], t[_tri.t1z]) <= 0
{

//If outside, get nearest point along the edge
d = median(0, t[_tri.e1l], dot_product_3d(x - t[_tri.x1], y - t[_tri.y1], z - t[_tri.z1], t[_tri.e1x], t[_tri.e1y], t[_tri.e1z]))

//Get direction normal to the point and the distance
nx = x - (t[_tri.x1] + (t[_tri.e1x] * d))
ny = y - (t[_tri.y1] + (t[_tri.e1y] * d))
nz = z - (t[_tri.z1] + (t[_tri.e1z] * d))
d = point_distance_3d(0, 0, 0, nx, ny, nz)
nx /= d
ny /= d
nz /= d
}
else
{

//Edge 2 Check
if dot_product_3d_normalised(x - t[_tri.x2], y - t[_tri.y2], z - t[_tri.z2], t[_tri.t2x], t[_tri.t2y], t[_tri.t2z]) <= 0
{

//If outside, get nearest point along the edge
d = median(0, t[_tri.e2l], dot_product_3d(x - t[_tri.x2], y - t[_tri.y2], z - t[_tri.z2], t[_tri.e2x], t[_tri.e2y], t[_tri.e2z]))

//Get direction normal to the point and the distance
nx = x - (t[_tri.x2] + (t[_tri.e2x] * d))
ny = y - (t[_tri.y2] + (t[_tri.e2y] * d))
nz = z - (t[_tri.z2] + (t[_tri.e2z] * d))
d = point_distance_3d(0, 0, 0, nx, ny, nz)
nx /= d
ny /= d
nz /= d
}
else
{

//Edge 3 Check
if dot_product_3d_normalised(x - t[_tri.x3], y - t[_tri.y3], z - t[_tri.z3], t[_tri.t3x], t[_tri.t3y], t[_tri.t3z]) <= 0
{

//If outside, get nearest point along the edge
d = median(0, t[_tri.e3l], dot_product_3d(x - t[_tri.x3], y - t[_tri.y3], z - t[_tri.z3], t[_tri.e3x], t[_tri.e3y], t[_tri.e3z]))

//Get direction normal to the point and the distance
nx = x - (t[_tri.x3] + (t[_tri.e3x] * d))
ny = y - (t[_tri.y3] + (t[_tri.e3y] * d))
nz = z - (t[_tri.z3] + (t[_tri.e3z] * d))
d = point_distance_3d(0, 0, 0, nx, ny, nz)
nx /= d
ny /= d
nz /= d
}
else
{

//If passed all edge checks simply use the triangle's normal as the direction
nx = t[_tri.nx]
ny = t[_tri.ny]
nz = t[_tri.nz]
}
}
}

//Final distance check for if the point is on one of the edges
if d < mask_radius
{

//Subtract distance from the sphere radius
d = mask_radius - d

//Ground check
if nz <= slope_limit
{ground = true}

//Push the instance back with the normal * distance
x += nx * d
y += ny * d
z += nz * d

//Update the instance's bbox coordinates
instance_get_bbox_sphere()

//Bounce
d = dot_product_3d(t[_tri.nx], t[_tri.ny], t[_tri.nz], xspeed, yspeed, zspeed)
xspeed = lerp(xspeed, xspeed - 2 * d * t[_tri.nx], bounciness) * fric
yspeed = lerp(yspeed, yspeed - 2 * d * t[_tri.ny], bounciness) * fric
zspeed = lerp(zspeed, zspeed - 2 * d * t[_tri.nz], bounciness) * fric

}
}
}
}

This is all you need to do for standard spherical collisions, like on the videos with the bouncing ball, but because the player and characters are usually taller than they are wide, the script needs to be a bit different and do another calculation if the sphere distance check fails, which gets the z point on the triangle from the instance's x & y coordinates (for the ground and ceiling), but luckily this is quite simple to do and you can also use gm's built in point_in_triangle function for the 1st part. Then you can sort these z coordinates to make them snap onto slopes while walking down them and headbutt ceilings. Without the slope snapping, it kind of bumps down them, so this makes it look and feel a lot better, like it's running down them smoothly.
This is the script currently:
I think it could still be improved a bit though, and the slope snapping has ruined the natural slope friction that the sphere part usually does, like walking slower up steep slopes, so I need to put something in to handle that

GML:
///collision_precise_entity(list of triangles)

var
l = argument0, i = 0, t, vx, vy, vz, d, highest_ground = 1000000, pz;

repeat l[0]
{
t = l[++i]

//Bbox check
if rectangle_in_rectangle(bbox_x1, bbox_y1, bbox_x2, bbox_y2, t[_tri.bbox_x1], t[_tri.bbox_y1], t[_tri.bbox_x2], t[_tri.bbox_y2])
&& rectangle_in_rectangle(1, bbox_z1, 1, bbox_z2, 0, t[_tri.bbox_z1], 1, t[_tri.bbox_z2])
{
vx = x - t[_tri.x1]
vy = y - t[_tri.y1]
vz = z - t[_tri.z1]
d = dot_product_3d(vx, vy, vz, t[_tri.nx], t[_tri.ny], t[_tri.nz])

//Distance check
if abs(d) <= mask_radius
{

//Edge 1 check
if dot_product_3d_normalised(vx, vy, vz, t[_tri.t1x], t[_tri.t1y], t[_tri.t1z]) <= 0
{

//If outside, get distance from nearest point on the edge
d = median(0, t[_tri.e1l], dot_product_3d(x - t[_tri.x1], y - t[_tri.y1], z - t[_tri.z1], t[_tri.e1x], t[_tri.e1y], t[_tri.e1z]))
d = point_distance_3d(x, y, z, t[_tri.x1] + (t[_tri.e1x] * d), t[_tri.y1] + (t[_tri.e1y] * d), t[_tri.z1] + (t[_tri.e1z] * d))
}
else
{

//Edge 2 check
if dot_product_3d_normalised(x - t[_tri.x2], y - t[_tri.y2], z - t[_tri.z2], t[_tri.t2x], t[_tri.t2y], t[_tri.t2z]) <= 0
{

//If outside, get distance from nearest point on the edge
d = median(0, t[_tri.e2l], dot_product_3d(x - t[_tri.x2], y - t[_tri.y2], z - t[_tri.z2], t[_tri.e2x], t[_tri.e2y], t[_tri.e2z]))
d = point_distance_3d(x, y, z, t[_tri.x2] + (t[_tri.e2x] * d), t[_tri.y2] + (t[_tri.e2y] * d), t[_tri.z2] + (t[_tri.e2z] * d))
}
else
{

//Edge 3 check
if dot_product_3d_normalised(x - t[_tri.x3], y - t[_tri.y3], z - t[_tri.z3], t[_tri.t3x], t[_tri.t3y], t[_tri.t3z]) <= 0
{

//If outside, get distance from nearest point on the edge
d = median(0, t[_tri.e3l], dot_product_3d(x - t[_tri.x3], y - t[_tri.y3], z - t[_tri.z3], t[_tri.e3x], t[_tri.e3y], t[_tri.e3z]))
d = point_distance_3d(x, y, z, t[_tri.x3] + (t[_tri.e3x] * d), t[_tri.y3] + (t[_tri.e3y] * d), t[_tri.z3] + (t[_tri.e3z] * d))
}
}
}

//Final distance check for if the point is on one of the edges
if d <= mask_radius
{

//Ground check
if t[_tri.nz] <= slope_limit
{
ground = true

//Only push along the z axis if ground, so that it doesn't slide down slopes while standing still
z += t[_tri.nz] * (mask_z2 - d)
}
else
{

//Wall
//Only push horizontally
d = mask_radius - d
x += t[_tri.nx] * d
y += t[_tri.ny] * d
}

//Update the instance's bbox
instance_get_bbox()
}
}
else
{

/*Added part for when sphere distance check fails*/

//If not in sphere radius, the instance could still collide with ceiling at the top of it's bbox
//or with the ground at the bottom (if the bbox isn't cubic)

//Check the instance is over\under the triangle first (in 2d)
if point_in_triangle(x, y, t[_tri.x1], t[_tri.y1], t[_tri.x2], t[_tri.y2], t[_tri.x3], t[_tri.y3])
{

//Ceiling check
if t[_tri.nz] >= -slope_limit
{

//Get z point on triangle
pz = z - (d / t[_tri.nz])
if pz < z
&& pz > bbox_z1
{
z += pz - bbox_z1
zspeed = 0
instance_get_bbox()
}
}
else
{
//Snapping onto Slopes
if zspeed >= 0
&& !ground
&& ground_last
&& t[_tri.nz] <= slope_limit
&& z - (d / t[_tri.nz]) < z + mask_z2 + ground_snap
{highest_ground = min(highest_ground, z + (t[_tri.nz] * (mask_z2 - d)))}
}
}
}
}
}

//Snapping onto Slopes (final part)
if ground_last
&& !ground
&& highest_ground < 1000000
{
ground = true
z = highest_ground
instance_get_bbox()
}
 

Joe Ellis

Member

I've got the animation part fully working, and it's amazing! This is the most exciting week I've ever had!
I've decided to make the example character an egg with arms and legs, called Eggzample.
And the world he's in is completely food\kitchen related, so far I've made a little level made out of blocks of cheese, and his weapon is a spatula\fish slice. There will be far more to come after this *menacing smile*
Also the free exe demo will be released next friday, even if it has bugs, cus I really want everyone to try it out :D

Also got attatching other instances to bones working, so Eggzample holds his spatula very menicingly and hits people over the head with it :D

You can also, without me even realizing, attach other instances with models with bones onto the main character and attach things onto that, so I made the player hold a miniature version of himself on his leg, and that version hold another miniature version of itself on it's leg. (Crayyyzeee)

Yeah if you want to try out the demo, keep an eye out! I'm going to put it up for download next friday regardless of bugs, cus most things work. After that I'm gonna fix all the bugs, then the real version will be released.
The real version is a gm project, and allows you to code certain objects etc.
but the free version is a full working version of the level, model and material editors, so you can still make a huge amount of things before even getting the full version.

Also, when any of you try out the demo, I'd really appreciate feedback on how user friendly and easy it is to use, follow and get the hang of. And also if you have any crashes, it'd really help me alot if you told me about them. I probably know about most of them, but there could be some things I haven't found out, so any info will be useful to me :)
I'll post this next week when I upload the demo anyway, till then, peace out, fellow homies *cringey gangsta pose*
 

Joe Ellis

Member
Hi everyone! The free exe demo is now available :D

Here's the download link: (And I've also put it on the opening post)

https://drive.google.com/file/d/1jpu3hA6ki6OlbK2PWh_vi0OoOiR0wWS_/view?usp=sharing

I've fixed alot of bugs this week, I think the pressure of promising to upload the demo has motivated me alot.
There are still some bugs, so make sure that you save very often, and if you're about to try something you haven't done before, save the file you're working on, cus there are bugs lurking around in the less common parts of the program.
I'm going to make a full list of known bugs, and if you find one that isn't listed it would be great if you let me know about it via pm or a post on here.

There a 3 demo levels, a spyro style one, crash bandicoot style and doom\early shooter style.

There is one issue with some of the items not working with both types of player objects,
the guns and ammo only work with the 1st person player, and the gems, extra lives and the spatula(melee) only work with the 3rd person player. I'm going to sort this out pretty soon.
There is also an issue when the 3rd person player falls off into the sky the level doesn't restart,
so you have to restart it yourself by pressing R.

Also some of the gameplay is a bit glitchy, especially on the 1st person level, but I'll keep improving it as time goes on.

I will keep uploading new versions of the demo, probably every week as I make and improve more things.

Editor Controls -

Move Camera - WASD

Toggle Mouse Look - Tab

Fast Camera - Hold Shift

Play Level - P


Demo Level Controls -

Move - Arrow Keys

Jump - Space

Attack - Ctrl

Strafe - Hold Alt + Left & Right

Action\Open Door - X

Crouch - C

Look Up - A

Look Down - Z

Center View - End

Main Menu - Escape

Inventory - I

Return To Editor - P

Restart Level - R


I hope you all have fun trying it out, and I'd love to hear what you all think of it :D
 
Last edited:

inertias

Member
What a great milestone! Congrats dude!

Tried the demo for a little bit just to mess around. Any reason why certain keys aren't working? I could pretty much only do WASD movement. Can't use pg up/down to go vertical or rotate or anything.
 

Joe Ellis

Member
What a great milestone! Congrats dude!

Tried the demo for a little bit just to mess around. Any reason why certain keys aren't working? I could pretty much only do WASD movement. Can't use pg up/down to go vertical or rotate or anything.
Thanks! Sorry about that though, are you using a laptop? I had a feeling this might happen cus of laptop keyboards being a different layout, but I wasn't able to test it cus I haven't got one. I'll have to test it on my dad's or brothers soon.
Just to clarify, do you mean you can't move objects up and down with pgup\down or did you mean the camera? Cus the camera only uses wasd to move and you have to use the mouse to control the angle of it, when mouselook is on (toggled by pressing tab)
I think I need to add something that moves the camera vertically though, cus it's a bit awkward at times having to look down and hold S or W to move it vertically.
Thanks for letting me know about the problem though, and for trying it out, I really appreciate it
 

inertias

Member
Thanks! Sorry about that though, are you using a laptop? I had a feeling this might happen cus of laptop keyboards being a different layout, but I wasn't able to test it cus I haven't got one. I'll have to test it on my dad's or brothers soon.
Just to clarify, do you mean you can't move objects up and down with pgup\down or did you mean the camera? Cus the camera only uses wasd to move and you have to use the mouse to control the angle of it, when mouselook is on (toggled by pressing tab)
I think I need to add something that moves the camera vertically though, cus it's a bit awkward at times having to look down and hold S or W to move it vertically.
Thanks for letting me know about the problem though, and for trying it out, I really appreciate it
Ah, I didnt know about pressing tab. Ok, that solved the issue. I still feel like there are some controls/keys that dont work, but I'd have to mess around more and write things down. I am not using a laptop btw.
 

Joe Ellis

Member
Ah, I didnt know about pressing tab. Ok, that solved the issue. I still feel like there are some controls/keys that dont work, but I'd have to mess around more and write things down. I am not using a laptop btw.
Cool, that's a relief
Sorry I forgot to put the controls for the camera on the list at the side, I'll have to put them on and upload a new version.
If you could let me know which keys don't work when you find out that'd be a huge help, I'll have to check them all, I thought they all worked
 

Joe Ellis

Member
Update -

It's been a bit slow recently, but I've fixed a lot of bugs that were in the previous demo version.
Here are some highlights of recent development:

1. I've begun porting the project to gms2.3! I've made a few nice changes to the code using the new features, and I'm converting all arrays that are dealt with using enums (nodes) into structs. Also the project used hundreds of script_executes and now they can\need to be replaced with method variables.

There is one problem to do with the virtual asset browser that's in the editor and recreating the asset tree, the new project format has made it harder to get the folder structure and asset layouts. The 1.4 version used to just read the project file and interpret all the layout of the folders and what assets were in them. So I need to make a new version of this where it reads the project file, defines each asset as a node, then opens the .yy file and retrieves it's folder path in the asset tree. However this won't need to be done for finished projects compiled to exe, the engine will just use a simple rom file which lists all the assets' names, types and folder index.

There's also a problem that's emerged from scripts being replaced with functions, you can't get the index of a function from a name with asset_get_index. So all instances that have variables holding a script to be used with script_execute can't work without having all the functions cataloged by name. So I need to make the engine open every script's text file, gather all the functions' names, create nodes for them holding the function index, then put these nodes into a map, a list and the asset folder tree. But to get the correct function index for each one as they're read from the script text files the engine needs to list the scripts in the order they're defined in the project file, as that's the same order they get executed in on startup where the functions are defined. So then if the engine opens every script in that order it can simply increment the function index (starting at 100001) for each function found.


2. I've added .obj model export, so now you can import and edit models made in warp3d into blender etc. and then back again.

My main plan for me was to use blender's good uv unwrapping for character textures, cus I still haven't managed to make uv unwrapping work well in warp3d, and I don't know if I ever will, so having this cross compatibility and using other tools' strengths will be really handy.

You could also use blender's ambient occlusion baking, here's a picture of that with a model for a game I'm working on with a friend:



I might bring back the lightmapper into the model editor, cus it worked really well, the only reason I took it out was cus the editor was unable to generate proper unwrapped uvs for more complex meshes like characters or curved geometry, so it was useless without that.
Also @Micah_DS I've made the d3d model importer :) For anyone that uses Model Creator or has d3d models from older projects.

3. I've made an improvement to the rendering pipeline, which has allowed choosing textures per mesh, per instance, and they're separate to materials. Materials now just contain uniform values, so it's allowed you to use different textures on different models and meshes that share the same material. So now each mesh has a material and a "base texture". I've also made it so you can assign a shader instead of a material, which is useful for shaders that only use global variable uniforms like sun_direction and ambient_color. These "global shaders" don't have any "material uniforms", so there's no need to create a material using this shader, as it won't contain any uniform values. So this has made it handy being able to just choose a global shader and a texture for the mesh, especially with early prototyping of the game.
You can also choose the materials and textures for each mesh per instance in the world editor.

I had avoided doing this before cus I thought it would have a big impact on performance setting textures per vertex buffer, but after testing it it hasn't seemed to have made any noticeable difference in the framerate. So I decided to add this feature as I've been wanting it to be like that for a while now and it's made materials and stuff way easier to manage. Also it might actually provide better performance as it will reduce the amount of materials needed and therefore uniform sets.

Also there is no longer any need for the texture dll, as gms2 now has the functions it uses and there is no problem with mipmapping for externally loaded textures. Textures will still be loaded from external png's, but will use sprite_add and sprite_get_texture instead, and sprite_delete when the textures are unloaded. It's also allowed textures to be set to the gm_basetexture sampler, so that's saved having to use d3dx_texture_set for every vertex_submit now.

The only problem is, it used to have a function for loading a png from a buffer, which I was gonna use when a project is compiled to an exe, all the texture png's would've got glued together into one file, then the function would load them from the correct spot in the file.
But without this function, I think the only alternative is to use buffer_load_partial, or buffer_copy, to get the png from the rom, save the buffer, then use sprite_add. So this will probably be alot slower than before. If it's horribly slow I'll probably just make the engine use sprites defined in the asset tree instead, although this will be more awkward in cases when you've got a lot of textures and just want to test out which ones are the best, you'll have to add each one as individual sprites. So I want to avoid having to do that if possible. I could make it so the project version of the game uses external files, and compiled exe's have to use internal sprite textures with the same name, then you'd only have to add the final textures that the game uses when you release an exe of it.


So overall it's going well, and I think the porting is gonna take a lot less time than I thought :)

I think I will only release the full version for gms2.3, as it's gonna be really hard to keep track of both versions, especially how they have different languages now. But if there are quite a lot of people who want to use it in 1.4 I might consider keeping the 1.4 version up to date, and I'll probably release the first full version for both, as I pretty much have that already minus a few bug fixes and final object templates.

I'll be uploading a new exe version in the next few days :)
 
Hello, been lurking forever. I just tried playing around inside the demo for the first time and if I click on the mesh of any model it crashes. (On my laptop btw, will try on my tower later)

GML:
___________________________________________
############################################################################################
FATAL ERROR in
action number 1
of  Step Event0
for object obj_editor:

trying to index a variable which is not an array
at gml_Script_var_step_asset
############################################################################################
--------------------------------------------------------------------------------------------
stack frame is
gml_Script_var_step_asset (line -1)
gml_Script_properties_step
gml_Script_browser_step
gml_Script_mouse_get_gui
gml_Script_gui_form_step
gml_Script_mouse_get_gui
gml_Script_editor_step_world
gml_Object_obj_editor_Step_0
 

Joe Ellis

Member
@CrunchCaptain Hi, thanks for letting me know and trying it out. I think that bug has been fixed now. I'm going to upload a new version of the demo soon with that and a few other bugs fixed.
Also the manual isn't actually written yet, I'd just made the gui for displaying it etc. The manual probably won't be there until the full release, but I have written a few parts of it so far, so I'll upload that as a simple text file or something soon
 

Micah_DS

Member
@Micah_DS I've made the d3d model importer :) For anyone that uses Model Creator or has d3d models from older projects.
Awesome, thank you! :)
Just so you know, I haven't tried the demo or really followed the project in the past month or so, but that's not for lack of interest. Life threw me some curve balls, so I haven't kept up on this for that reason.
I look forward to diving into the demo and reading up more properly on features and updates later.

there is no longer any need for the texture dll, as gms2 now has the functions it uses and there is no problem with mipmapping for externally loaded textures.
Does that mean the project is entirely native GML now? If so, that's a super plus in my book.
 

Joe Ellis

Member
@Micah_DS Yeah it will be entirely native gml now. Also the fact that I've converted all the nodes to structs has made the code a lot easier to read and understand, so it'll be good for people who want to code more advanced things that deal with the nodes, and also use parts of the code to make their own things, like the 3d geometry system.
I'm planning on uploading the new demo version tonight and I'll write some info on the new features and how to work with them :)
 

Joe Ellis

Member
Good news with the porting the gms2.3, I've ported all of the code and it now loads up without crashing, which means the new startup sequence works, with reading the project file and building the asset tree, putting all the assets into the correct folders and creating nodes for them holding their indices\file paths. Plus all the functions get put into the tree, where scripts are essentially folders containing all the functions that're defined in them.
Super excited for getting everything finalized and start making games in 2.3 :D Wooooo
 

Joe Ellis

Member
Not sure when all the bugs will be fixed, there are only a few now though, and the porting the 2.3 should only take a couple more weeks as the bulk of it's done, I just need to test everything thoroughly.
You can try the demo version now though, although it does have a lot of bugs, a lot of them have been fixed while I was porting to 2.3, cus I had to revise through all 40,000 lines of code and I spotted a few problems. But the demo has 3 levels you can play.
I don't think I'll be supporting the 1.4 version anymore, cus I've changed that much of the code that it'll be really hard and confusing for me to keep developing new stuff with both versions :( I did want to have both versions available, but I don't think it's a good idea regarding time, and it'll probably make me go mad.
 
Top