Editing a 2D Array in Sections in C++

Kurt91

Well-Known Member
OP
Member
Joined
Sep 9, 2012
Messages
589
Trophies
1
Age
33
Location
Newport, WA
XP
2,244
Country
United States
I'm taking some college courses on programming, and thought that I'd try to make a dungeon-crawler/text adventure game as practice in my free time. So far, it's going pretty well. Whenever I start trying to think out how to do something, we just happen to have a lecture on what would help me for that particular part the next day. For example, I'm trying to think of the easiest way to implement character stats, and one or two days later we start learning about structures. I start wondering about interpreting user input, and we start learning about tokenizing strings. (which means that if I'm careful about how I line things up, I could make a text parser that should be able to understand natural sentence structure instead of strictly "Walk North", and giving the game more of a DnD vibe.) I've got one problem that I can't seem to figure out, though.

I want to make a first-person view appear on screen. After looking things up and doing a bit of research, I think I have the best way to do this figured out. I want to use a 2D array and make changes to it depending on what's around the player. Once everything has been worked out, print the array to the screen to make an ASCII image of a first-person view. The problem is, I need to make changes to the array in sections. If there's a wall to the player's left, I need to essentially make a trapezoid shape of entries on the left third of the array "image" without touching the rest of the array. I'd need to do the same on the right side of the array if there's a wall to the right, without touching the left side of the array at all.

I know that if I'm creating the array, I can put it together like: array[][] = {{1,2,3,4,5},{1,2,3,4,5},{1,2,3,4,5}}. This was what got me thinking that arrays are the way to go, since it would be very easy to read my code if I put each part of the array in a separate line and use white space to essentially let me see what the finished "picture" section will look like inside of my code. However, asking my teacher about it during a few minutes between classes revealed that while I can create an array like that, I can't necessarily edit the array like that without placing something like "0" inside of the extra spots, which would erase all of the other parts of the array. I could just code the change for each individual slot separately, but that's going to be a nightmare as far as readability goes, and if I find a better more-appealing way to draw part of the dungeon in ASCII art later on, making adjustments would be insanely difficult.

Does anybody have any ideas how I can get this done? I really want to use arrays, since I realize that it would be easier to increase "draw distance" by making more checks and drawing more "layers" onto the array image. If I just use pre-determined full images, I'm going to need to place a TON of images so I can cover every single possibility.
 

supersega

Well-Known Member
Newcomer
Joined
Apr 25, 2018
Messages
83
Trophies
0
Location
A place in a place
XP
184
Country
United States
This is a very cool idea, albeit a very challenging one. What you are basically doing is creating a 2D graphics engine with arrays. The issue with arrays is that they are statically defined, so it will be hard to add values like your professor said. I really think that having "hallway", or walled parts of arrays that are statically defined, and modifying the array elements between these wall arrays will create something like you want. Sort of like how in Shining In The Darkness creates enemies in a hallway as when you encounter them, except your hallways/stone walls will be statically defined.
 

Kurt91

Well-Known Member
OP
Member
Joined
Sep 9, 2012
Messages
589
Trophies
1
Age
33
Location
Newport, WA
XP
2,244
Country
United States
I already know how to make dynamically-sized arrays, but for simplicity's sake, I've got a really big MHEIGHT and MWIDTH pair of constants, and am making the actually-used area within the constraints of "height" and "width". Building the array for the actual levels isn't the problem. (Although for actually reading the array from an external file, so that I can add additional levels without going into the code again each time, I looked up and found this: https://stackoverflow.com/questions/32998105/reading-a-2d-array-from-a-file-in-c I'm basically copying this method, and it covers building the level. I just write the height and width on the first line, and then starting from the second line, draw the level out using "#" as a solid wall, "." as an empty space to walk through, "S" as starting location, and "E" for exit location.)

My "image" for the first-person view is a constant size, so I shouldn't need to do anything as far as changing the size. I just need to change the existing values accordingly for each section of wall that is within the player's field of view. I already have things planned out as far as figuring out what needs to be drawn and when. It should be something like...

Inside the "Player" structure will be an "x-value" and "y-value". These will be equivalent initially to the intended starting coordinates. For each time the screen is written to, it will check

if(levelArray[Player.x - 1][Player.y -1] == "#"){
//Draw the correct section of "image" as a wall pillar
}

This will be done for the entire "cone of vision" and will be a different series of coordinates depending on which direction the player is facing. (Again, another value within the "Player" structure) The furthest wall pillars will be drawn first, going from the outside edges towards the middle, one check at a time. The closer pillars will be drawn last so that they overwrite the further layer and block off what shouldn't be seen.

For instance, here's what I've already figured out as far as drawing things. Note that while these are copy-pasted from Notepad for now, the border will be a straight write-to-screen and not part of the actual array. (Also, the Code window makes it look way more stretched out than it is. It looks much better in Notepad.) First off, the initial state of the view window is a 45x19 array with the following setup.
Code:
[ ]###########################################[ ]
 #          \                       /          #
 #           \                     /           #
 #            \                   /            #
 #---------------------------------------------#
 #\             \               /             /#
 # '\            \             /            /' #
 #   '\           \           /           /'   #
 #---------------------------------------------#
 #                                             #
 #                                             #
 #                                             #
 #---------------------------------------------#
 #   ./           /           \           \    #
 # ./            /             \           '\  #
 #/             /               \            '\#
 #---------------------------------------------#
 #            /                  \             #
 #           /                    \            #
 #          /                      \           #
[ ]###########################################[ ]

The first check will look at the array in the coordinate two spaces in front of the player and two spaces to their left. If it finds a "#" in that space, the viewport array is altered like so...

Code:
[ ]###########################################[ ]
 #          \                       /          #
 #           \                     /           #
 #            \                   /            #
 #---------------------------------------------#
 #|.            \               /             /#
 #|||.           \             /            /' #
 #|||||.          \           /           /'   #
 #|||||||--------------------------------------#
 #|||||||                                      #
 #|||||||                                      #
 #|||||||                                      #
 #|||||||--------------------------------------#
 #|||||'          /           \           \    #
 #|||'           /             \           '\  #
 #|'            /               \            '\#
 #---------------------------------------------#
 #            /                  \             #
 #           /                    \            #
 #          /                      \           #
[ ]###########################################[ ]

The same process is repeated for the right side, but since it's visually identical other than mirroring, I won't add it in here. Next, we keep the distance from the player, but we move one section to the center. If this section is marked as solid, then we have another series of "draws" that overwrites the existing values in the array and looks like this:

Code:
[ ]###########################################[ ]
 #          \                       /          #
 #           \                     /           #
 #            \                   /            #
 #---------------------------------------------#
 #||||||||||||||\               /             /#
 #|||||||||||||||\             /            /' #
 #||||||||||||||||\           /           /'   #
 #|||||||||||||||||----------------------------#
 #|||||||||||||||||                            #
 #|||||||||||||||||                            #
 #|||||||||||||||||                            #
 #|||||||||||||||||----------------------------#
 #||||||||||||||||/           \           \    #
 #|||||||||||||||/             \           '\  #
 #||||||||||||||/               \            '\#
 #---------------------------------------------#
 #            /                  \             #
 #           /                    \            #
 #          /                      \           #
[ ]###########################################[ ]

By working inward like that, each section of overwrites will overwrite the section that came before it correctly. If I need the center pillar and an edge, but not the section in-between, the overwrites will be spaced out that the finished image will look correct. (Also, the grid being shown is just a placeholder, the actual initial state of the array has an ASCII ground and ceiling. The grid was just to determine the drawing pattern.) The only part I'm uncertain about is whether the front-most center square would make more sense as your current location or the space directly in front of the player.

I know that for each section I want to draw as a pillar, I can just do a crap-ton of value changes and it will work. However, it will make reading my code an absolute mess. Each value change would be a separate line, and while I'll be able to see what it's doing technically, I won't be able to easily determine which value changes are altering which ASCII component of each pillar, making altering the drawing pattern later on much more difficult, and only practical with a complete rewrite from scratch each time. I want to be able to fit multiple value changes into a single line so that I can use white space and make it more easily view-able in the code editor. Optimally, I'd like to use white-space to basically have the drawing itself viewable inside the code, so I can just redraw it in the code editor and visually see what I'm going to end up with. If this isn't possible, I'll have to start taking really careful notes of the coordinates for each piece of each pillar and put them in one at a time.
 
Last edited by Kurt91, , Reason: Needed to check the code windows to make sure that I set them up correctly.

SubstituteCS

Well-Known Member
Newcomer
Joined
Oct 22, 2015
Messages
80
Trophies
0
XP
251
Country
United States
Have you considered a custom structure for your arrays?
In one of my college C assignments, this structure
typedef struct
{
int Count;
void** Values;
} SSizedArray;
worked absolute wonders for dynamically sized arrays. The void** Values being a pointer to (generally) an array, but could very much as well be a pointer to another SSizedArray (for nesting.)

In the question of how to update partial sections of arrays, you could consider the ASCII image to be "pixels" and treat the positions as indices in the array. Then knowing the row and column of the "pixel" you can set it rather easily.

On the other hand, it is much easier to implement dynamically sized ""arrays"" using something such as a linked-list. If you have it be doubled-ended, you get O(1) insertion and deletion from the front/back, however it isn't easy to find a specific element other than sequentially searching, which is O(N) time.

Resizing an array could be done, but the realloc may not be fast.
 
Last edited by SubstituteCS,

Site & Scene News

Popular threads in this forum

General chit-chat
Help Users
  • No one is chatting at the moment.
    Jayro @ Jayro: Thanks for that bundle, I had the games already but got all the DLC for them for just $5. What a... +1