Wolfenclone

The Partridge Family were neither partridges nor a family. Discuss.
Firepath
Posts: 77
Joined: March 10th, 2018, 11:53 pm

Wolfenclone

Post by Firepath » August 23rd, 2018, 1:43 am

Hey doodz.

I haven't been on much in the last couple of months and haven't watched any Chili stuff for probably as long. I want the 3D to get ahead more so I can watch a few without forgetting the previous one.

I also gotta get to looking at sound at some point, which Chili has also done and from what I have seen looks pretty awesome.

Anywhooo...

I've been working on and off on trying to clone Wolf3D, and started with making a map editor, which is still a loooong way from being useful, but it's progressing.

I have got a bunch of things working, most of which are bare bones and need fleshing out, but that is just kind of adding "content" not actual logic.

My latest work was getting settings loading from a config file. Currently this loads one setting, which is a list of list files. It then opens this list of list files (just one at the moment, textures) and loads those lists into their appropriate list in the settings object. It then can be used to somewhat dynamically fill the menu I have created.

The more that I add to it, the more it is hard to notice the work that has gone into it. I started with a blank Chili framework. There is mouse zooming and navigation, and multi-selection of blocks, deleting them, etc.

I made the closed areas highlight with the red fill so you know when an area is enclosed. I want to enhance this later so when the player start is added the closed fill colour is blue, to show closed playable area vs closed non-playable.

Once all the element (or a lot of them) are in play and have properties (something I am working on "next") I will work on "playing" the game from this map / top-down perspective. Movement and collision-detection on this view. Wolf3D is really a 2D game, much like DOOM and I also want to similarly recreate that style of rendering the 3D.

Anyways, I've attached a screenshot for your enjoyment.
Attachments
Wolfenclone.png
(231.36 KiB) Not downloaded yet

Firepath
Posts: 77
Joined: March 10th, 2018, 11:53 pm

Re: Wolfenclone

Post by Firepath » August 23rd, 2018, 1:45 am

Oh yeh I'm using this program "Slade" to get into the Wolf artwork. The sounds are also accessible, even the sweet, sweet, PC speaker sound effects.

albinopapa
Posts: 4373
Joined: February 28th, 2013, 3:23 am
Location: Oklahoma, United States

Re: Wolfenclone

Post by albinopapa » August 23rd, 2018, 4:18 am

Neat idea, good luck and keep us updated.
If you think paging some data from disk into RAM is slow, try paging it into a simian cerebrum over a pair of optical nerves. - gameprogrammingpatterns.com

Firepath
Posts: 77
Joined: March 10th, 2018, 11:53 pm

Re: Wolfenclone

Post by Firepath » August 26th, 2018, 3:23 am

Ok so I've made some pretty big progress, most of which is not visible ha!

I updated the image menu hovering to also expand the hovered item by 50% to make it easier to see each one, also because it was neat and I wanted to do it.

I create move logic to allow moving blocks of selected cells around. Handy!

Main thing I've done (took all day, but I think worth it) is to split out each different tool from the editor. I had an enum for what current mode the left mouse button was in, and did things depending on that. Now it is streamlined quite a bit with polymorphic edit tools, specifically various types of mouse button edit tools.

The logic was split out so each tool (none (yeh I know, pointless maybe), insert, select, move) had only logic pertaining to what it does and the editor knows less about editing, other than having tools.

I then created a delete tool, which I replaced the right-click function with, as that is what it did. I also added it as a left click option for consistency and because I can.

I then made the insert tool show the current fixture image on the cell it was on, as well as being highlighted in insert colour (green). Helpful!

I added control modes (holding control key whilst clicking) to the insert and delete to mass insert or delete (respectively) the currently selected cells.


It is so easy now to expand on the tooling and functionality in the program now I have tools in there to do what I want. I'm "done" with the nitty-gritty of converting grid coordinates into screen coordinates, working out the drawing and scaling of sprites, etc. I've built up to a higher level where work put in produces tangible results.


Oh I changed the sprite effect functors, built from Chili's tutorials examples to inherited classes, which is a bit more text and not quite as nice to look at, but Graphics no longer needs to be templated. I haven't split the logic back out into the cpp file yet, but will at some point.


The next exciting (to me anyway) thing is to finish off making the fixture menu load dynamically, starting with the walls, which is all I have currently. (And some of those aren't going to stay as walls.) I have a text file for the fixtures that links fixtures to the texture (loaded from another list file), and will, in the future, also have all the other information (score value, health value, ammo value, 2d / 3d, whether it blocks movement, etc.) for each fixture. In the bottom of the fixture file is the menu structure for it, which will organise the fixture menu without having to hard-code it into the program.


Then I need to do a file menu, with some saving a loading. I'll need to make some rudimentary (but fitting and functional) dialogues to use for this. This should be fairly easy due to the way I've implemented keyboard and mouse events, and all the font, box and border drawing tools I have built in.

As for the mouse and keyboard events - I added a handled flag on it so the event can be passed through the hierarchy of objects and handled internally. If the event has been handled already the handler just returns.

I want to have the level editor complete so I can have a complete (and valid) level before starting on movement / gameplay, which will, at first, all be done in the top-down view. I might even get enemy AI and animations happening in this view, why not?

Then after that it should basically just be making the 3D renderer to put on top of it. (And then a game menu, etc.)


I'm going back to work tomorrow (had two weeks off, not that I worked on this for more than a couple of days though) so progress will slow again. I'm out of a bit of a stagnant rut I was in with this project though. Exciting things to do and I know (mostly) how I'm going to do them.

Added some screens to show some different stuff, mostly not that amazing.
Attachments
Wolfenclone4.png
(112.72 KiB) Not downloaded yet
Wolfenclone3.png
(255.13 KiB) Not downloaded yet
Wolfenclone2.png
(161.55 KiB) Not downloaded yet

albinopapa
Posts: 4373
Joined: February 28th, 2013, 3:23 am
Location: Oklahoma, United States

Re: Wolfenclone

Post by albinopapa » August 26th, 2018, 4:28 am

Seems like you are getting the hang of things fairly well, have you coded before? I usually don't see anyone on here use polymorphism on their projects very often. I think egizz was probably the only "beginner" I've seen use it and it also was for a user interface. Not that no one else on here has, or even the only beginner, but the only one that comes to mind.
If you think paging some data from disk into RAM is slow, try paging it into a simian cerebrum over a pair of optical nerves. - gameprogrammingpatterns.com

Firepath
Posts: 77
Joined: March 10th, 2018, 11:53 pm

Re: Wolfenclone

Post by Firepath » August 26th, 2018, 6:10 am

I've been a C# developer for nearly 8 years so... yeh. Been into C++ since early high school (which is from 13 years back in my day) and wanted to make games since then - early 90s.

But yeh Chili's videos really taught me stuff I have never learned before. Polymorphism and how and why to use it really became a lot clearer after seeing his vids. I'm really getting my head around const correctness and pointers and references (none really a C# thing).

I'm using std::unique_ptr<T> to store things and passing a pointer from it (unique_ptr.get()) where I need to hold a reference to something but not own / manage its lifetime.

I have been returning references where I need a method to get one of these pointers, to make dealing with it easier (like a local variable, no indirection ( -> ), etc.) when you get it. I think I should be storing the things I currently use raw pointers for, as references too, but haven't investigated it yet to be confident that it works how I think. Although, hang on, I have tried, and they way I'm doing things (like I generally do in C#) is I need things to be nullable / not necessarily instantiated upon construction of the object they are in. For the bounds that I am using them, I think pointers and references work the same, with pointers requiring dereferencing or indirection and also allowing it to be nullptr.

albinopapa
Posts: 4373
Joined: February 28th, 2013, 3:23 am
Location: Oklahoma, United States

Re: Wolfenclone

Post by albinopapa » August 26th, 2018, 7:49 am

As far as storing the pointer that is owned by a unique_ptr, not really good practice. For stuff like that, you probably want a shared_ptr.

You can store references, but as you may or may not know they can't be null. So in classes where you must provide one and only one reference to an object like Graphics it's doable because there is only one instance of Graphics and should be passed to any constructor for an object wanting to store a reference to the Graphics object.

References at least as far as the compiler is concerned get passed as pointers, but semantically are treated as the object allowing you to use the dot operator instead of using the arrow.

A reference cannot be reassigned either, so there is no "pointer arithmetic" allowed since they are treated as objects and not pointers.

These two things are similar:

Code: Select all

int a = 7;

// A reference can only be assigned once, but the value it refers to is mutable by default
int& aRef = a;
// A constant pointer would be similar in nature, but still requires dereferencing when used with objects
int* const pConstPointerA = &a; // aConstPointer cannot be reassigned now to another int*

// Now a constant reference or a reference to a constant object to be precise can only be assigned once and is immutable
int const& = a;
// A const pointer to const data is similar to a const ref
int const* const pConstPointerConstA = &a;  // Cannot be reassigned and cannot change the value being pointed to.
Hopefully this helps more than confuses.
If you think paging some data from disk into RAM is slow, try paging it into a simian cerebrum over a pair of optical nerves. - gameprogrammingpatterns.com

albinopapa
Posts: 4373
Joined: February 28th, 2013, 3:23 am
Location: Oklahoma, United States

Re: Wolfenclone

Post by albinopapa » August 26th, 2018, 7:55 am

BTW, I don't usually write:
int const& // read as reference to constant int data
int const* // read as pointer to constant int data
int const*const // read as constant pointer to constant int data

I prefer:
const int&
const int*
const int*const

It's all preference, but I believe the former set is mostly accepted by the C++ community, while the ladder is probably mostly used by plebs like myself.
If you think paging some data from disk into RAM is slow, try paging it into a simian cerebrum over a pair of optical nerves. - gameprogrammingpatterns.com

User avatar
chili
Site Admin
Posts: 3948
Joined: December 31st, 2011, 4:53 pm
Location: Japan
Contact:

Re: Wolfenclone

Post by chili » August 26th, 2018, 2:40 pm

The level editor looks pretty sick!

One thing to be careful with about references is using them as members of classes. You really gotta know what you're committing to there. The main issue is that you will be preventing you object from being assignable, which will make it difficult if not impossible to use with containers for one. Another issue as papa mentioned is you won't be able to represent an empty state of =null, and you might want that as well.
As far as storing the pointer that is owned by a unique_ptr, not really good practice. For stuff like that, you probably want a shared_ptr.
I wouldn't agree with this. If there is one clear owner for an object A, use unique_ptr and have other objects reference A via dumb pointer is the baseline. Shared pointer is for when you have multiple objects referencing A and you're not sure which one will die first, so you share the responsibility of resource management and last one to leave turns out the lights.
Chili

albinopapa
Posts: 4373
Joined: February 28th, 2013, 3:23 am
Location: Oklahoma, United States

Re: Wolfenclone

Post by albinopapa » August 27th, 2018, 3:29 am

chili wrote:The level editor looks pretty sick!

One thing to be careful with about references is using them as members of classes. You really gotta know what you're committing to there. The main issue is that you will be preventing you object from being assignable, which will make it difficult if not impossible to use with containers for one. Another issue as papa mentioned is you won't be able to represent an empty state of =null, and you might want that as well.
As far as storing the pointer that is owned by a unique_ptr, not really good practice. For stuff like that, you probably want a shared_ptr.
I wouldn't agree with this. If there is one clear owner for an object A, use unique_ptr and have other objects reference A via dumb pointer is the baseline. Shared pointer is for when you have multiple objects referencing A and you're not sure which one will die first, so you share the responsibility of resource management and last one to leave turns out the lights.

Well, that's the way I understood him to be using it, storing the raw underlying pointer in some other class while maintaining the smart pointer somewhere else which could possibly lead to dangling pointers. I agree that if you are just passing the raw pointer to a function, then yes do that and not the unique_ptr or even a unique_ptr&. But if you are storing the underlying raw pointer in different classes, then I still advise caution and stand by "not good practice".
If you think paging some data from disk into RAM is slow, try paging it into a simian cerebrum over a pair of optical nerves. - gameprogrammingpatterns.com

Post Reply