A downloadable engine for Windows

Buy Now$4.99 USD or more

A simple first-person shooter engine (Game Maker Studio 1.4 and 2.x source file) that can be used to quickly get a FPS game project up and running. Not very advanced and pretty low on features, but that means it's easier to understand how all of the code works!

  • Moving around with different footstep sounds depending on what you step on.
  • Slopes in all directions.
  • Two example weapons: ammo, reload animation, bullet physics.
  • Fire bullets in any direction in three dimensions: the boring 3D maths is already done for you!
  • Example enemy.
  • Shield and health systems, dying when falling off the map or running out of health.
  • Pickups for ammunition, health, and armor.
  • Doors that open when you get near them and close again when you get far away.
  • Levels can be designed in layers, giving simple 3D functionality to Game Maker's default room editor. Layers are placed on top of each other when the level loads.
  • Seamless transition between different rooms letting you build levels made up from several small rooms.
StatusReleased
CategoryAssets
Rating
Rated 5.0 out of 5 stars
(6 total ratings)
AuthorYal
Made withGameMaker
Tags3D Platformer, engine, First-Person, FPS

Purchase

Buy Now$4.99 USD or more

In order to download this engine you must purchase it at or above the minimum price of $4.99 USD. You will get access to the following files:

Source Code (GMS1.4) (v2) 11 MB
Source Code (GMS2.3) (v2) 13 MB

Download demo

Download
YaruFPS Demo v2.exe 7.8 MB
Download
License Agreement 22 kB

Development log

Comments

Log in with itch.io to leave a comment.

Dear Yal,

Few of the players of my game have found next bug:



When I removed all the hedge-objects from the level, another object has triggered this message:




Do you know, what could be the problem? Could you help?

(3 edits)

I did some googling and it looks like the issue is that the batch of trianges becomes so big the players' graphics cards can't handle it. (800 MB VRAM sound very small these days but ah well...) 

So we need to reset the drawing batch every 1000 triangles. I tried to figure out the easiest way to do that and here's my idea.

1) Create a new script with the following function:

function triangles_break_batch(quads=6){
     global.triangles_so_far += 2*quads
     if(global.triangles_so_far >= 1000){
         global.triangles_so_far -= 1000
         draw_flush()
     }
}

2) Init global.triangles_so_far to 0 somewhere before any 3D drawing, e.g. In CONTROL's create event.

3) Put this new triangles_break_batch function at the start of the Draw event of all terrain objects. You'd compute "quads" like so,

//For a block or wall
triangles_break_batch((image_xscale + image_yscale + image_xscale*image_yscale)*2)
//For a floor or slope
triangles_break_batch(image_xscale*image_yscale*2)

I am using GM:S 1.4, which does not have functions. I can change your code into script-like, but just to be sure: I shall change the "draw_flush()", and calling the new scipt I shall set the "quads" equal to 

(image_xscale + image_yscale + image_xscale*image_yscale)*2

for blocks and walls?

(2 edits)

Yes, just having a script asset with the same name should work too

  • change "quads" to "argument0" in the script
  • if draw_flush doesn't exist (it was added late in 1.4) overwriting the world matrix (e.g. by d3d_transform_set_identity or matrix_set) should also force a flush of the geometry buffer

Blocks/walls should use that formula, yes (they do indeed add that many triangles). Maybe slap a ceil() around the expression for stability so it always becomes an integer even if a block is e.g. 1.5x its base size. (If you never stretch things out in the room editor it gets easier, then you can just use the hardcoded number 12 for blocks and 4 for floors)

hey! didn't help :[

What exactly does the updated code look like? Are you using draw_flush or d3d_set_identity?

I find it a bit weird that it still tries to allocate a giant buffer of 1/6th of everything else it's rendering when it's totally fine with thousands of smaller ones, are you sure you didn't miss adding the safety code anywhere?

(3 edits)

dear Yal! thank you for the great-great engine you made. could you please tell me, where to determine the distance of object rendering (and which script de-renders them eg. behind your back)?

also, where engine determines the size of the 3d-camera (if I ex. want to have it in 1x1)?

(+2)
  • Distance for object rendering: CONTROL's Draw Event, controlled by "global.darkness" variable.
  • De-rendering things behind your back: CONTROL's Alarm 0 event. (It deactivates things outside your field of view at the same distance in all directions but you could adjust this using parent_camera.direction to take a step in the direction the camera is looking when computing the region to keep active)
  • The size of the camera is controlled by two things: obj_player's collision mask (currently a 8x8 sprite) which is used for collisions in the XY plane, and the zheight variable (the height along the Z axis) which is used for collisions on the Z axis, which defaults to 24 - the actual variable used to compute the camera perspective is zdelta but it's currently computed based on zheight (so the player's eyes will always be roughly where their head should be)
(2 edits)
dear Yal! thank you very much for helping with the first issue. still, i didn't get the second problem solved. changing the sprite of obj_player mask doesn't change the ratio in which the game automatically start. for example, it looks like it starts in 16:9 ratio (copying my monitor) and stays the same when I resize the window (look picture below). how could I change the ratio of the camera to eg. 1:1 or 4:3?



UPD: Could you also by any chance help me with importing other d3d-models in the game? I accept "no" as an answer. If you could, I will write the problem I am having.
(+1)

Oh, seems like I misunderstood your question! Aspect ratio of the in-game view, not the collision mask of the object.

  • For output window size, this is controlled by the Game Maker room viewport properties. The most important one is the first room of the game (titlescreen) because this room's viewport size sets the initial game window size when the game loads, but you should change all of them to use the desired window size (the fields for "width" and "height" for both camera properties and viewport properties)
  •  
  • After doing this, most stuff should adapt automatically, with one exception: CONTROL's draw event has a line running d3d_set_projection_ext. One of the arguments here is the aspect ratio (specifically the "1.76" near the end - it's the "aspect" argument in the argument listing), you should change this according to the aspect ratio you're using: for 4:3 it's 1.333 (4 divided by 3), for a square window (1:1 aspect ratio) it's 1, and so on.

"D3D models" as in models exported by GM or as in 3D models in general? I've seen a lot of OBJ loader scripts on the forums over the years so I never saw a need to make one myself, and plenty of video tutorials going over it as well:

thank you a lot for your answers!! all works fully well now :)

no, i am not talking about importing itself (didn't write the question fully before getting your agreement to help me more, because i've already wrote a lot of questions), but about integrating them in the game. in fact, the only question is about collision. if I have imported eg. a pyramid, how to make an object solid (i.e. so the player would go through), when it has not a just-a-box shape?

one of the possible crutchy solutions would be check if player is touching the object and grow players z until it stops touching it. shitty one, but i will be happy even with it, if you could game me an idea, how to check a collision between d3d-object and the player.

(1 edit) (+1)

There's a system for more advanced collision check functions, it's used by the different ramp objects: the zcheck_script_bottom and zcheck_script_top variables. These are called with two arguments, the x and y position we're doing a collision check over, and should return the top/bottom Z value of the object at that point.

Pyramids are actually a pretty complicated shape (4 triangular regions with different slope) but I think the easiest way is to check the x and y position difference vs the centerpoint of the pyramid - e.g. if the x difference is larger than the y difference AND the point you check has a higher x value than the center of the pyramid, you're on the right-hand quadrant, so you'd lerp from the top Z value of the pyramid to the bottom Z value of the pyramid using the x difference divided by half the sprite_width of the pyramid object. (The left hand quadrant does the same calculation but mirrors the x difference, and the top and bottom uses the y difference and the sprite_height instead)

So, how do i actually put things like wall objects on top of each other? I tried just putting one on another layer, but that doesn't seem to work (i'm on the latest version of gms 2)

(2 edits) (+1)

Check the creation code of the room and you'll find this bit, this is what arranges the objects in 3D space:


The idea is that the level is arranged in chunks 640 pixels wide (for this room in particular - you can use whichever value you want here), every subsequent chunk is put on top of the previous one.


There's a handful of backgrounds for different grid sizes which can be used to help judging distance, the one used in this room is 640 pixels wide. (I've tried an approach where multiple floors are on different layers for a different project but IMO it's an even worse experience since there's no depth perception)

If you're really sure you wanna do this with layers instead, you could try changing the lines in terrain_flat_to_3d from

z = 64*(x div global.level_chunk_width)
x =     x mod global.level_chunk_width

into

z = 64*(depth div 100)

so the depth value (which is obtained from the layers by default) is used instead. (In this case you probably want to start from a fresh room - by default layers have their depths spaced 100 units apart but the layers in the dungeon_test rooms use compatibility values)

(2 edits)

Hey, I tried using the code you mentioned, and for some reason it results in anything i place higher than the first layer actually being LOWER

i made a new room and put in the CONTROL object and a floor and a couple of walls on the first instances layer, then made a new one on top with a few walls, and for some reason all those walls are actually lower than the things on the bottom layer

this even seems to happen even if everything is on the same layer, with the walls always being below where they should be for some reason (just to a lesser extent)

(1 edit)

I messed around a bit and got very weird results, after a while I think I figured it out. There's some legacy shenanigans going on with the depth values, so you need to explicitly read them from the layers. This version of the code seems to work as intended:

z = -64*(layer_get_depth(layer) div 100)

But you also need to do two more things:

  • CONTROL currently changes its depth value in the create event, cut this line and paste it in the Room Start event (otherwise it gets an extreme depth value which in turn messes up where the player spawns on the Z axis)
  • Likewise, all of the "floor" objects sets their depth to 0 in the create event, remove this entirely.

The question is this - can I buy an engine, develop a game based on it, and sell it in styme, of course, indicating in the credits data about the engine?

Yes. Even indicating in the credits is optional.

(Note that this is a GameMaker: Studio source file so you may need a license for that to create a standalone game, depending on target platform)

In the License Agreement you state:

 "Games can be played but not resold, reposted or such. Assets can be used to create games, books, movies and such, but cannot be distributed in editable form." 

 What does that mean? By "Games" do you mean this engine?

Only asking because how I read it and interpreted it was that I can't sell/distribute my game if I get the engine and make one.

Let's say I make a game and change every aspect becides the FPS camera, can I sell/distibute said game?

(+1)

I'm using the same EULA for games and assets for convenience since a lot of the content would be the same. The line you're referring to is for my games ("Games" in the EULA), it doesn't apply to engines and other asset packs ("Assets" in the EULA).

The only thing I'm asking for this engine is, don't let other people (outside of your team) have the source code, only compiled game executables. So making a game with this engine and distributing that is totally OK. Uploading a copy of say, Dracula's Tower to Steam and claiming you made it is not OK.

(+1)

Gotcha, thanks for the clarification! I have the engine bookmarked for when I'm up for the FPS challenge. (Best GMS FPS Engine that I have found)

Hey, do you have a Discord server where I can ask for help with the engine? A friend and I wanted to make a Doomlike game, but I have no idea where to start with this.

My first idea would be to either fix the reloading system or remove it entirely

I don't; I prefer questions (and more importantly, answers) being somewhere they're publicly accessible, so they can help more than one person.

I'm not sure if I can wholeheartedly recommend this engine for new projects anymore since it just barely survived the GMS1-->GMS2 transition (it's originally made in GM6, so this is the third layer of compatibility functions...) and Yoyo have hinted at new 3D tech being on the roadmap, it might be completely obsolete in the near future. Depends a bit on project scope, of course.

Really? Didn't know they were teasing 3D. Where can I see this?
Oh well, I can always just use the 1.4 version.

If you check the "Announcements" channel on the official forums, there's the new "2D-3D" tool (used to make prerendered sprites in the style of Donkey Kong Country). Yoyo hired one of the more prolific 3D creators as a staff member and have hinted at more cool stuff happening, but it's all very vague so far.

Hey man, I made a game with this engine. CHECK IT OUT!!!!

(+1)

Oh wow, I expected people to use this engine for simple Doom clones and you went ahead and made a fantasy immersive sim?? Nice job!

(+1)

Thanks! Your framework has been a MASSIVE help to me over the past two years I've been developing Saccharine Pale! It will ALWAYS be free for you!

honestly at this point its essentially a completely different engine, other than the layered level editor lol

I want the torch to be active closer to the player. where can i find the code?

CONTROL object's Step Event:

I have the latest gamemaker S2. but my game can't go fullscreen. i have "fullscreen" mode on and "Allow fullscreen switching" why is this?

it worked with "window_set_fullscreen(true);"

Did you have "allow the player to resize the window" turned off, perhaps? (It wins out over all other window options)

hey, for some reason movement control not working at all on mac (gms 2.3.2), any ideas what can help?

Which movement control is not working? Mouse to control the camera or WASD to walk?

There's two different functions to alter the mouse position, window_mouse_set and display_mouse_set. The manual doesn't make it clear if there's any difference between them (e.g. platform support) but it points out that the game needs to have focus for them to work... I wonder if that's detected differently on Mac perhaps?

To detect movement keys (WASD) when the game doesn't have focus it could be worth trying keyboard_check_direct instead of keyboard_check, it works even when the window doesn't have focus.

 Can i use this for commercial projects?

Yes, of course!

(1 edit)

Trying to add new weapons. I see your logic in the script init_weapons. However, where are you declaring the "wp_UNARMED" or "wp_PISTOL"? I can clearly see how you added items, just can't get those wp_ declared to allow more than the two weapons you have in the example. 

Using GMS2 FYI

They're defined in the default compatibility location, scripts --> macros. (Lines 22-25). There's a machine gun example weapon as well, but it's sort of hidden so it's easy to miss.

(+1)

Thanks Yal, great engine!

Hey Yal, nearly got it all figured out. I was trying to make some of the walls more rectangular and less squared. I used the below to do so in the draw event and it looks perfect. However, the collision box is still the full square. I made sure to also change the tops and bottoms.


draw_set_color(c_gray)
d3d_draw_floor(x   ,y+32 ,     zbottom+0.01,x + sprite_width,y + sprite_height,zbottom+0.01,my_fex,image_xscale,image_yscale)//Floor
draw_set_color(c_white)
d3d_draw_floor(x    ,y+32,     ztop-0.01   ,x + sprite_width,y + sprite_height,ztop-0.01,my_fex,image_xscale,image_yscale)//Ceiling
d3d_draw_wall(x ,y+32  ,zbottom+0.01,x + sprite_width,y+32     ,ztop-0.01,my_wex,image_xscale,1)//Back wall
d3d_draw_wall(x   ,y   + sprite_height,zbottom+0.01,x    ,y+32,ztop-0.01,my_wex,image_yscale,1)//Left
d3d_draw_wall(x + sprite_width,y+32,zbottom+0.01,x + sprite_width,y  + sprite_height,ztop-0.01,my_wex,image_yscale,1)//Right
d3d_draw_wall(x + sprite_width   ,y + sprite_height,zbottom+0.01,x,y + sprite_height,ztop-0.01,my_wex,image_xscale,1)//Front?

(+1)

Yeah, the collision code first does a standard Game Maker collision and then does a Z collision check (using a per-instance collision function to allow for things like slopes) to see if the overlapping objects are colliding vertically as well... so the collision mask of the terrain object's sprite is used for the XY collision check regardless of what you draw. If you make the walls more narrow than the sprite, you should change the collision mask to match this (either by giving the walls a new sprite, or changing the existing sprite's collision mask to not cover the entire sprite).

(+1)

Perfect, thank you!

(2 edits)

Neat stuff. why does the lighting appear weird at times, kind of flickers if you're not looking at a wall directly or not as bright. Also there is a little z-fighting between two floor panes, in the first room. When it switches from walking on floor_sqr256 to floor_sandstone, i have to jump a little to continue to move or it 'sticks'.

(1 edit)

I looked into the lightning code. The problem seems to be caused by the lighting using per-vertex lighting instead of per-pixel (so the entire polygon gets the exact same lighting), which was the old "basic" lighting model... and I can't find the function to use advanced lighting in the GMS2 manual... so it might've been deprecated in GMS2, so everything uses the bad lighting model now :<

Not sure about the "floor sticking" you mention... there is floor sticking I'm aware of (go through the door to dungeon_test2 and turn right, and then exit through the archway onto the stone void), but that's caused because you end up in the void outside the level and the collision checking is simplified (no slope checks - and floors have a height of 1 so their top ends up at z = 1 while the void is at z = 0). When I test play the first room, the transition between the small hedge maze and the indoors area works flawlessly.

Hello, I just try to open with GM2 on MAC but when I try to run the game nothing happens. The workspace is empty. This is normal? Do I need to do something? Thanks.

No, it's not normal. Are there any error messages while importing the project?

Also, make sure the compile target isn't set to "Windows (VM)", it might default to that since it's what I had selected when exporting the source file.

Right, my mistake. Thanks it works. Cheers. 

Hi Yal !

I try to integrate the deltatime function to your engine (essential for an action game)
delta = 60/1000000*delta_time; (in obj_player's Begin_step)

What do you think is the most appropriate place to integrate him?

I've tried:
xspeed = median(-movespeedmax,movespeedmax,xspeed*delta + lengthdir_x(accel,direction))

But not very convincing...
Thanks !

It might be better to keep the internal speed computations as-is (measured in 60 per second), but have anything that changes x/y/z (e.g. "x += xspeed") take the delta into account instead ("x += xspeed*delta"). Changing the internal speed computations won't feel right until you change every acceleration, friction, maximal speed, etc... if you just change the "make speed affect coordinates" bit there's a lot less things that needs changing.

(+1)

Thank you very much for your valuable advice. The engine is well thought and it's relatively easy to add things

Great engine, but a few small questions:

- When you shoot straight, the bullets go straight from the center of the screen, but how do you keep them centered when you look up (ztilt)?

- The collision between the walls and the bullets doesn't seem to work...

- What's this script?
collide_3d_circle(parent_enemy)
?!?!?!?????!!!!???? The script is not visible in the script list? It's a ghost script and yet it works ?!? I must have missed something...
Ditto for zcheck_script_bottom: I don't understand...

Thank you !!

Scripts can have multiple tabs, collide_3d_circle is a tab of collide_3d.  zcheck_script_bottom is a variable that's set to different variables for each terrain object, there's no actual script with that name. (Blocks use collide_block_bottom, slopes use the collide_slope_*_bottom family)

I think the collision-checking bug with bullets is because collidecheck() uses place_meeting() to check for collisions, so the bullets need to have a sprite to be able to collide with the terrain.

I think bullets might leave you off-center when shooting upwards/downwards because of the coordinate computation in the ss_pistol / ss_machinegun scripts... right now they're created at 60% off the player's height instead of in their absolute center, but the camera is placed at 80% of the player's height. (I suppose 60% felt like the height you'd have your hands at when holding a gun, if your eyes are at 80%? Or maybe it's just an oversight)

Thank you very much for the answer!
The multiple tabs of scripts I didn't know, I'm learning thank you!

For the bullets collision with walls, even putting a sprite it doesn't work (parent_bullet). But by putting code in obj_bullet_pistol it seems to work. To be seen...

Otherwise to make the bullets always centered on the screen according to the ztilt doesn't seem so obvious to me. When the ztilt is at its highest value, ztilt=-90: dividing it by 2 pulls in the middle, unfortunately it doesn't work for the other ztilt values. Anyway, I'm going to look for...

Thanks again!

(+1)

Tabbed scripts is removed in current GMS2, so don't get too used to them, I guess :P (But they will be a thing again once the 2.3 update is released, when you can define "functions" and scripts are changed into source code files)

Yes, that's correct, the different bullet types (pistol, machinegun etc) needs to have the sprite, because those are the objects that actually spawn. The parent just is a container for code / behavior they have in common.

As for making bullets always spawn in the center of the view: go into ss_pistol and ss_machinegun and change the line

n.z = z + cz + zheight*0.6

into

n.z = z + cz + zheight*0.8

and they will now be in sync with the camera.

(+1)

A thousand thanks! Everything's working fine now! (For the bullets, I had put a sprite too small)

(1 edit) (+1)

Sorry, two more things:

- For bullets colliding: OK, but then, if I'm on a wall, it won't shoot... but well, not too hard to correct...

- For the shooting in the middle of the screen, I wanted to say that when you shoot with the titlt at 0, the bullet goes to the middle of the screen, it's OK (imagine that your sight is in the middle of the screen). But if you shoot higher, the bullet doesn't conform to the middle of the screen anymore (it's as if your sight is no longer in the middle of the screen).

I was just making these remarks because it's important for an fps, but the engine is already remarkable!

(1 edit)

Hi there! I purchased and downloaded the engine but when I ran it and clicked play I got this error :S


https://gyazo.com/0d89ea440f2da9ca41ac41c5a75b7a9d

Could you please upload the screenshot directly (or copypaste the error as plaintext) instead of using a URL shortener? I have no way of knowing if that link is a valid image or a site that will steal all my credentials.

Aah yes that is completely fair enough lovely ^_^ Here ya go!

(3 edits)

Change the first line of both the affected scripts like this and it should work:

var a = argument1, b= argument0;


Basically the problem is that the collision scripts need to take two arguments (x and y) but some shapes don't have collisions based on the x/y values, so they don't use the arguments. We can work around this using dummy variables. When the engine was originally made, it didn't matter that every argument was used, just the last... and then in the latest version(s) this was changed to require using every argument.

(+1)

Aaah I see! Thank you very much for providing the fix! :D :D :D What inspired you to create this? :

Are the walls made of d3d_draw_wall or d3d_draw_block or something else ?



Depends a bit depending on which object, but most block-type objects are 4 d3d_draw_wall and 2 d3d_draw_floor calls (so the top, bottom and sides can have different textures).

thanks. I'm making a 3D game and drawed walls wih d3d_draw_wall but it caused performance issues. I found a way to draw blocks with vertex buffer, it's a lot faster.

Does this work if you export it as HTML5?

(2 edits)

No idea, I've never tried. The engine is quite a performance hog and the HTML5 version of GM doesn't have super good performance since it's doubly interpreted, and you'd lose out on both hardware-accelerated 3D rendering and hardware lights. Also I'm pretty sure the way the mouse position is read to let you aim with the mouse just wouldn't work in HTML5 (since you can't control the mouse position other than on the desktop ports, and the code is based on resetting the mouse to the center of the screen all the time so you get motion from its absolute position).

(+1)

Awesome stuff! Thank you! 

(+1)

Hi,

Error in Script collide_slope_x_bottom at line 0 : no references to argument 0 but references argument 1 (Idem for _x2)

Is no a serious problem, just replace argument1 by argument0
According to GM versions, the bug does not appear...

Otherwise very good engine!

Thanks, I'll look into it... arguments checking is a relatively new thing compared to how long the YaruFPS code base has been around. I don't remember exactly how the script works, it might be that it uses the same argument signature as the other collide scripts but doesn't actually USE all the arguments.

(1 edit)

yes I have the same error in 1.4.999, might be older versions don't have it

(+1)

Yeah, I looked into the code and there's commented-out code that used argument0 in the script. Change the first line into "var a = argument0, b = argument1;" (instead of "var a = argument1;") and the error should be fixed. (The collision scripts need a certain format because they're called using script_execute() depending on the object's terrain type, but not every script uses both arguments)

(+1)

Would be great if dear Yal improved this package more, so far it's bare bones. But I see the potential in here.

I searched but seems there isn't yet sort of main menu+ levels selection asset in the store here, so throwing an idea

(+1)

Hello, I just downloaded the source code and I'm having trouble understanding a lot of the code. Mainly with the whole terrain and Level Grid stuff. I was wondering if you could maybe comment the code there a little more or elaborate on those a bit here? Thanks! I very much like this asset, there's a lot of good things here!

(1 edit)

Shouldn't be impossible, I'll see what I can do!

The main idea is that you make the level in "layers" corresponding to different Z layers, then the engine puts them together when the room loads (moving everything to the first layer, and adapting their Z values accordingly). It's mainly there to make it easier to design 3D levels in GM's room editor and doesn't have any benefits other than that.

(There's a bunch of backgrounds that add a grid to the Room Editor; those backgrounds are used to figure out the size of the Z-slices, so it gets a bit more WYSIWYG than if you had to keep track of a "slice_width" variable or somesuch)

There's also the terrain/ceiling-terrain (which is probably what I named "Level Grid" originally... was a while since I touched the source code last!), which is essentially support for less rectangular ground, and which can be randomly generated. Its purpose is to make the ground in outdoors / cave areas look less like it's made out of cubes, but I couldn't figure out good ways to CONTROL it from within the editor, so it's a bit of an experimental feature. There's special objects that will generate (and draw) terrain if you place them in a room, TERRAINCONTROL and TERRAINCEILCONTROL, look into the init_terrain() script (which has a commented-out block of code that randomly generates terrain) and the "field" room for an example of how to use it.

The "layers that get stacked on top of each other" and polygonal terrain features aren't mutually exclusive, either, so this could be used for levels like a tower in the middle of a forest, or such. (In Dearelict, the trees are actually just very tall cylinders with a bark texture, players just ASSUMES they're trees that stretch so far into the darkness they can't see any of their leaves. Tricks like this can be useful to save CPU power for enemies and stuff like that, GM and 3D rendering isn't really a match made in heaven...)

(+1)

Wow. Okay I get it now thanks for your help and very quick response haha! This is a really awesome asset!

Another quick question, if you increase the view distance and darkness then everything works good except the lighting still seems to pop in. How can I fix this?

(2 edits)

Did you increase the size of the active region as well? (Lighting is controlled by objects, so it won't happen until they load in)

If you did that and it still doesn't work, there's a few things you could try...

  • Have lighting objects always be active, it shouldn't add too much of a performance penalty and it'll prevent them from popping into existence too abruptly. (But it WILL add a bit of performance penalty, so be careful about not having hundreds of lighting objects in the same room)
  • Try to avoid clustering too many lighting objects together, since only the 8 nearest ones are used (since there's a hard limit to how many lights the rendering system can handle) and which are the nearest ones can change suddenly.
  • It could be worth messing around with lighting sources' radius so they light stuff up less when they're far away (e.g. some code like radius = min(normalradius,<big number> - <number smaller than 1>*point_distance(x,y,player.x,player.y) ), but it could be a bit of work to fine-tune it. (The small number is the factor light radius changes with compared to distance, something like 0.25 should work well, and the big number should be the distance the light radius is fully restored, divided with the small number... if I didn't get the maths wrong, at least x3)
(+1)

Okay so the problem was that only 8 lights are used at once.  Its not that big of a deal though again thanks for the help. You and your asset are making learning 3d a lot easier for me!

Hello I downloaded the source game file but whenever I boot up the game by running it in Game Maker Studio Pro. I receive this error when I press start on the main menu.

___________________________________________
############################################################################################
FATAL ERROR in
action number 1
of Draw Event
for object obj_wall_sandstone_block64:

Fatal Error: Can not create vertex buffer of size 147456 bytes
6386 vertex buffers allocated with total size of 919104 KB
 at gml_Object_obj_wall_sandstone_block64_DrawEvent_1 (line 5) - d3d_draw_wall(x  ,y  ,zbottom+0.01,x + sprite_width,y     ,ztop-0.01,my_wex,image_xscale,1)
############################################################################################

Any solutions? I would really like to play around with the engine after paying for it.

This is the second time I've seen this thing appear, so I did a bit of research. Found this GMC topic that suggests that you should call d3d_set_identity() every 10,000 draws, when you're using an integrated graphics card you have less VRAM and that puts a hard-cap on how much 3D drawing you can do. (And I use a dedicated graphics card, so I never ran into this issue myself while developing the engine)

One way to see if it works is to just add a d3d_transform_set_identity() to the first line of the drawing code of the terrain blocks (e.g. the obj_wall_sandstone_block64 and perhaps a couple of its relatives) so that it flushes the vertex buffers occasionally... it's going to be overkill to do it before you draw EVERY piece of terrain, and it could have a performance impact, but it should solve the problem. If it solves the problem, you're pretty much good to go, and what you'd do is something like this (to reduce the performance impact):

  • Add a script called "flush_the_vertex_buffer" and set up a global counter variable
  • Reset it to 0 every step in the controller object
  • add the flush_the_vertex_buffer script to every terrain block's draw event
  • The script should increment the global counter, and if it's above a certain value (e.g. 10,000), set it to 0 and call d3d_transform_set_identity().

If you can confirm adding in some d3d_transform_set_identity() calls solves the problem for you, I'll get a fix for this into the source file ASAP.

Deleted 5 years ago

Thanks, glad you like it so far! ^__^

To extend the range of sight: obj_titlescreen's Create event, the code block labelled "Init global variables". There's two variables that controls this: global.darkness (which controls how far you can see) and global.activate (which controls when stuff is loaded in). Make sure global.activate is always bigger than global.darkness, or stuff will just visibly load in and it just looks weird.

(3 edits) (+1)

Hi Yal,


I'm loving the engine and the work you've put into it, thanks!

I have two things I need help with:

-I want to alter the starting position of the bullet so it doesn't always spawn in the center of the screen, and instead I can alter it's starting coordinates so it always spawns at the tip of the gun (so I can move it left/right, up/down relative to screen, so no matter the size of the gun sprite I can always center it at the end of the barrel); I'm at work at the moment so I can't recall the exact names of the scripts but there was one with cx, cy, cz variables that I figured defined the bullet starting position, but no matter how much I played around with them I just couldn't get the desired result.


*The yellow circle is the bullet - I need it to spawn at the very end of the gun barrel*


-Another thing I need helping with is - I can't seem to find where I can set the size of the "level grid", that is, how do I define where is the border of the level itself and where the upper layers of the level begin within the room (I hope this question makes sense).

Any help is greatly appreciated!
Best regards,

First of all,  the easy thing: the level grid size is based on the width of the background you use for the level grid. (See the script terrain_flat_to_3d for the details). So basically, if you want a grid that's 2560 pixels wide, use a background that's 2560 pixels wide. Any size should work, but unless it's a multiple of your room grid size it's gonna be hard to keep objects from different layers aligned :P


For the second question... the 3D maths is kinda hard... which is why I skipped that part in the engine :P You'll need to find a reference point (e.g. the player's x, y and zbottom), then find the delta X/Y/Z to the tip of the gun, then spawn the bullet there. If you know the length of all the 'moving parts' (e.g. "spine", "shoulders" and "arm+gun"), you could just compute the X/Y/Z vectors of each part individually and then the tip of the gun should be there.

For each thing...

  • X coordinate should be lengthdir_x(1,angle against 'forwards')*lengthdir_x(1,angle against 'up')*(length of thing along X axis)
  • Y coordinate should be lengthdir_y(1,angle against 'forwards')*lengthdir_x(1,angle against 'up')*(length of thing along Y axis)
  • Z coordinate should be lengthdir_y(1,angle against 'up')*(length of thing along Z axis)

And since the spine is always just Z coordinate and shoulders are always just XY coordinates, this should be possible to simplify a bit. But yeah, it won't really get any easier than this, so guess why games like Wolfenstein and Doom had the gun in the middle so you didn't need to keep track of anything other than the Z coordinate :P

(+1)

Thanks Yal! The "layering" level 3D system is very clever. Regarding the positioning of the bullets - I got that eventually resolved on the GM forum, and you are right - it's very hard and I don't think I'm yet at the level to properly utilize them complex maths and matrices needed for what I'm trying to achieve. So I guess for now I'll just stick with the "gun at the center of the screen"

Cheers!

Sounds like a plan... it's always possible to change it later in case you get better at 3D maths later, and working with 3D is a good way to learn about 3D, I guess :P

IMO the hardest part is figuring out how 3D vectors work (which needs linear algebra so you can actually do math with them - but you need to learn visualizing them as well in order to figure out HOW to use them for any given problem), once you've got that part down you can solve more or less any problem by doodling down a few lines on paper and putting variable names at all angles and lengths you'll need to use in the game. Don't underestimate doodling on paper, it helps visualizing stuff MUCH better than the maths formulae on their own :3

(+1)

Indeed, doodling (& writing) on paper does wonders for me. Good to know that it's helping you out too, Yal :)

What is the easiest way to add a smooth crouching feature into this engine?

Nice and smooth engine btw ;)

I'd probably go about it this way, editing obj_player a bit:

  • Add a new variable iscrouching which defaults to false, is set to true in the step event whenever the crouching key is held (you'll need to edit the get_keys script to add in checks for the new crouch key) and false otherwise.
  • Add in a new code block in the Begin Step event:  when the crouching variable is true, lower zheightmovespeedmax and jumpspeed to something lower than their defaults, when it's false set them back to their default values. zheight in particular influences both the player's collision checking and where the 3D camera is located.
  • If you want the camera position to smoothly move up and down, you could use the lerp function rather than setting the zheight variable directly to the values for crouching/standing.
  • In order to avoid collision issues where the player crouches, gets under something low, and then un-crouches, you'll probably want to only allow switching from crouching to standing when there's enough free space over you that you can stand there with your original zheight. Depending on how you design your levels, though, this might not be a problem (e.g. if the player never crawls under anything and all ceilings are so high you can't bop your head into them, they can't get into a situation where this collision thing becomes an issue)

Let me know if something's unclear, and good luck :)

Would this work on GMS2?

It should work in theory (since there's compatibility scripts converting the old 3D functionality into new), but I've had some issues converting other 3D engines to GMS2 so I can't say with certainty it will. (For instance, there's a bug with drawing transformed models with <1 scaling factors that causes massive slowdowns). Still a bit torn whether it'd be better to make a GMS2 version from scratch of all my engines or convert them and try to deal with version differences.

(+1)

Your call :P I bought your other engine to learn GML. There's not a lot of great source material out there. So, I'm trying to learn it all (last GM i used was 8)

At least it shouldn't be too hard to relearn Studio, it's basically GM8 with some stuff removed (execute_string() being the most important loss, a lot of people used that, and also sleep() and screen_redraw())... and some stuff added, like room/image editors where you can scroll and pan with the mouse wheel. Also, you can resize instances in the room editor now, which is wonderful for a lot of cases.


...oh, wait, you were talking about Studio 2. Derp. How do I forget things like this so easily x3

Studio 2 definitely is a bigger step up since it's based on the new stuff in Studio 1 more than it's based on its GM8 roots, but it's still mostly the same core loop. All the changes done from GM8--->GMS1 still apply, but on top of that:

  • Layers is a pretty major feature, and can be used in various ways... there's functions to only check a particular layer for instances/tiles, so you can have layers for each floor of a building etc.
  • Views has been generalized to cameras, which basically is the d3d_set_perspective() function except it now can view 2D planes as well. You can have more cameras than you have views and switch what cameras are displayed in which view on the fly, letting you make dramatic camera movements and stuff more easily.
  • Tiles has been revamped to allow autotiles and animated tiles, but this is mostly an editor thing.
  • Backgrounds and sprites have been merged into one resource.
  • Sprite editor supports layers for each subimage and you can draw while a sprite is animated, which lets you do some animations much easier.

I'm pretty new to GMS2 myself, but hopefully this helped you in some way :P

Yea, I've been trying to learn GMS2. It's a bit different than GMS 1.4 (I have both anyways so it doesn't really matter) Converting some of my projects has worked "successfully" but things dont function as they should. So just trying to figure things out xD

So am I free to use all these assets? Anyway, nice engine. I actually recently got my own FPS engine working with slopes so it's neat to see how you did it :)

Yup. They're so placeholder-y that I don't see why you would want to use them, but they're included in the price :)

are the codes commented?

Yes.