Official Fangame Help Topic

Wow, thanks so much Troid. Must’ve taken such a long time to type. :astonished:

I read the whole thing and it’s definitely going to take a while, so I’ll do it step by step. I’ll draw the map, and edit this post later with it, then continue on to the next step.

EDIT:

Finished; I made the map according to the rooms in my game.

That would work, but what about rooms larger than one square?

It’d work even for rooms large than one square. As long as the room size matches its scaled-down size on the map, it will work. Remember, Samus’s position in the room is also used to determine where she is on the map.

Okay, now I’m working on the script. It’s somewhat confusing since I’ve never used scripts before. (Well, maybe like, once. :astonished:)

I changed my first room’s settings to

global.room_x = 1; global.room_y = 2;

Now I made a script called "init_area_1’ (hope that’s right). Now, I’m not sure on what I should do about the green text (setting the map/adding symbols). [i]How]/i] would I do that? Do I have to change the map to another sprite including the symbols I want to add, or is there an easier way?

Sorry for all the questions, :astonished:

Okay, I’ll try to clear this up.

Symbols on the map that change during the game (items and anything else) shouldn’t be a part of your map image. So, instead of having different images for each combination of collected items and such, there’s only one map image and the symbols are drawn over it in-game.

Also, GM always works in Quadrant IV (y axis inversed), with 0,0 in the upper-left corner. So on your map there… Point (1,2) isn’t the upper-left corner of a room. >_>
The room in the upper-left corner is (0,0), the room to the right of it is (1,0), etc.

Yeah, “init_area_1” is correct. To answer your question about what to do there… Look just beyond that part in my first post. There are a bunch of global arrays to be set up for the area. So, here’s an example of what you could do:

[code]global.mapimage = ***; // Replace *** with the name of the map sprite
global.area_width = 6;
global.area_height = 6;

/*
You do have global variables for the items, right?
So that if you collect an item, leave the room, and come back…
…It’s not there? If so, here’s where you look at all those
to see if they’re collected or not, and set the correct symbol
on the map
*/

// So you’d clear out all junk from previous areas on the map
for (i = 0; i < 6; i += 1)
{
for (j = 0; j < 6; j += 1)
{
   global.area_symbol[i,j] = 0;
   // Each element in this array is the position on the map
   // And whether it has a symbol or not
   // The value it stores is up to you
   // 0 is the default in my example, meaning no symbol
   // 1 might represent, maybe, an uncollected item
   // Then when you’re drawing the symbols later
   // Draw the right one based on the value in the array
}
}

// Then here’s where you’d fill in the symbols over the default set above
if (global.itemcollected[0] == true) global.area_symbol[5,5] = 2;
else global.area_symbol[5,5] = 1;

// etc.[/code]

Okay, thanks for clearing up the “Quadrant IV” thing. Since I spawn at the bottom of the upper-left corner’s room, I set it to (0,1).

For “global.area_width”, I guess that’s the length and width of the whole map sprite in blocks, right?

About items, yes, they’re global variables. And if I want a symbol to appear in a room, I’d change “global.area_symbol[i,j]” from 0 to something like 2-3 for a Chozo statue or Missile tank, right?

As for “i and j”, since they’re both set at 0, do I have to set “j” to one, since the global.room’s y is 1?

And finally (:o) the actually drawing of the minimap is confusing. How would I draw only a 2 by 4 section of the map, and make the map move to another part of a room when Samus does?

  1. No, doesn’t matter where you spawn. The coordinates of the room have to be the coordinates of the box in its upper-left corner. If you set it at the bottom of that room, when you do get it working it’ll think Samus starts in the box below that. Remember, Samus’s position in the room is used as well as the coordinates of the room to find Samus’s position on the map. So if Samus is at position (50,400) in the room, then that will be divided and floored to represent the number of boxes over she is in the room and then added to the room coordinates.

  2. Yeah.

  3. Yeah. For now it doesn’t matter, just maybe say what each number represents in comments so you can quickly look them up later when it does matter.

  4. Nope, this is setting up the entire area. All items in the area, etc. Doesn’t matter what room you’re in, the area goes from (0,0) to (5,5).

  5. See the last sentence of #1.
    So say each square in the map represents 320x240 pixels. Divide Samus’s x coordinate in the room by 320 and then floor() it (floor() is a function that returns everything before the decimal point. So if Samus.x/320 is 0.99, it’ll return 0 (she still wouldn’t be in the next box over)) Then add the room’s x position onto that and you have her position on the map.

Do the same with the y coordinate but use 240 instead. Keep in mind that this should be the center of Samus, so if her x and y are located at her upper-left corner, add her width/2 to the x and height/2 to the y to get her center. GM has functions for determining that if you need to use them.

For drawing the mini-map, find Samus’s position on the map first (then, of course, set that box as visited in the global array), store it in some variables, and then draw the boxes around her position. Like in this:

// For all the boxes around Samus... draw_black_square(); // This goes behind the map, to fill in any boxes not being drawn. // Obviously you won't use "draw_black_square();" for (i = samusMapx-1; i <= samusMapx+1; i += 1) { for (j = samusMapy-1; j <= samusMapy+1; j += 1) { &nbsp; &nbsp;// Make sure this doesn't draw outside the map leading to an array error &nbsp; &nbsp;if (i > 0 && j > 0 && i < global.area_width && j < global.area_height) &nbsp; &nbsp;{ &nbsp; &nbsp; &nbsp; &nbsp;// Only draw the box and the symbol over it if it's been explored &nbsp; &nbsp; &nbsp; &nbsp;if (global.area1_explored[i,j] == true) &nbsp; &nbsp; &nbsp; &nbsp;{ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;draw_box(); // draw_sprite_general() is a good function to use here &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;draw_symbol(); // >_> &nbsp; &nbsp; &nbsp; &nbsp;} &nbsp; &nbsp;} } }

We’re getting there :smiley:

Wow, so many boxes. :astonished:

I’m not sure on what I really have to “draw” under “draw_box” and “draw_symbol”. :astonished:

I mean, there’s more than one symbol (Chozo Statue, Tank, Save Station, Map) and there’s more than one box (Empty box, blue box, green box).

this is why i never got into coding >.>;

i dont seem to have the right mindset. i downloaded visual C# from mason’s little linky in his topic and have been reading some tutorials, but im lost after the “Hello, World!” one… i cant even decipher the simple map code you put up for XMegadragon :cry:

i even bought a BLITZBasic book and read it all the way through, but i failed to create a simple text-based shooter (ex playership = “<-O->”)

its kinda hard without somebody there teaching you. maybe i should take a class.

i went to the bookstore looking for things on C# but when i saw the only books there were, give or take, 700 pages long and there was no “Programming in C# for Dummies” i became discouraged. :neutral_face:

Neither can I. :astonished:

Think this is simple? Troid just makes it look easy, that’s all. :stuck_out_tongue:

Xmega: For draw_box(), try:
draw_sprite_part(global.mapimage,0,1+i8,1+j8,8,8,50+i8,50+j8);
(changed my mind about draw_sprite_general()… didn’t know about draw_sprite_part())

Change those two 50’s in the middle to the upper-left corner coordinates of the mini-map. (Like how you did with other HUD stuff)

draw_sprite_part() draws a piece of a sprite. So you don’t have to worry about the different box types–it’ll draw the one used on your map image.

For draw_symbol()…
This is where you go back and check what you put for the different symbols on the map. Note that the only symbols you should put in the symbols array are ones that change during the game, like items. (They go from circles to dots when you collect them)
Other symbols you can just stick onto the map image and not worry about.

Anyway, you just do a bunch of “if” statements to figure out which symbol it is (ignoring it if it’s 0), then draw the symbol at the same coordinates as the box above.

So, like:
if (global.area_symbol[i,j] == 1) draw_sprite(…);
else if (global.area_symbol[i,j] == 2) draw_sprite(…);
Etc.

HP:
You can’t just read a BLITZBasic book and expect to have it all mastered–maybe if you payed attention well enough as you read it you’ll be able to read some BLITZBasic programs… But definitely not write them. That takes practice and experience with writing in the language, and you’ll always have to keep referring back to the book for a long time.

Plus, I wouldn’t even know how to make a text-based shooter. If you want to learn how to program, start smaller. >_>

This is what I have so far:

[code]DRAW EVENT OF HUD:

// For all the boxes around Samus…
draw_sprite(spr_mapdata,0,view_xview[view_current]+275,view_yview[view_current]+2); // This goes behind the map, to fill in any boxes not being drawn.
// Obviously you won’t use “draw_black_square();”
for (i = samusMapx-1; i <= samusMapx+1; i += 1)
{
for (j = samusMapy-1; j <= samusMapy+1; j += 1)
{
  // Make sure this doesn’t draw outside the map leading to an array error
  if (i > 0 && j > 0 && i < global.area_width && j < global.area_height)
  {
      // Only draw the box and the symbol over it if it’s been explored.
      if (global.area1_explored[i,j] == true)
      {
          draw_sprite_part(global.mapimage,0,1+i8,1+j8,8,8,50+i8,50+j8);
          draw_symbol(); // XMD: I’ll do this part once I actually draw the symbols.
      }
  }
}
}[/code]

[code]ROOM CREATION CODE:

global.room_x = 0;
global.room_y = 0;

[/code]

[code]init_area_1 Script:

if (global.area != 1) // Replace * with the number of the area
{
global.mapimage = Map1; // Replace *** with the name of the map sprite
global.area_width = 6;
global.area_height = 6;

/*
You do have global variables for the items, right?
So that if you collect an item, leave the room, and come back…
…It’s not there? If so, here’s where you look at all those
to see if they’re collected or not, and set the correct symbol
on the map
*/

// So you’d clear out all junk from previous areas on the map
for (i = 0; i < 6; i += 1)
{
for (j = 0; j < 6; j += 1)
{
  global.area_symbol[i,j] = 0;
  // Each element in this array is the position on the map
  // And whether it has a symbol or not
  // The value it stores is up to you
  // 0 is the default in my example, meaning no symbol
  // 1 might represent, maybe, an uncollected item
  // Then when you’re drawing the symbols later
  // Draw the right one based on the value in the array
}
}

// Then here’s where you’d fill in the symbols over the default set above
if (global.itemcollected[0] == true) global.area_symbol[5,5] = 2;
else global.area_symbol[5,5] = 1;

// etc.
}
[/code]

I’ll change the HUD Draw Event code as soon as I make my symbols.

Add “init_area_1();” to the room creation codes. It doesn’t get called by itself :stuck_out_tongue:

Also, yeah, you still need to change the x and y coordinates of where the upper-left corner of the mini-map is drawn (Right now it will either show up kind of in the upper-left of the screen, or the upper-left corner of the entire room <_<)

Also, unless “global.itemcollected[0]” happens to be both the item in the lower-right corner and the name of the var used to store whether said item has been collected, that should be changed, too. To whatever your global var for storing that item is. You’ll also want to add the symbol for the other item in there.

And when you collect an item, it should change the symbol for it on the map to collected, so that it doesn’t require the player to leave the entire area and come back just for that to be updated. >_>

  1. To execute scripts you use “script_execute”, right? It mentions that you need to mention two arguments, too. I’m new at scripts; so what should I put in for them?

Next, the code for displaying the minimap is:

draw_sprite(spr_Map1,0,view_xview[view_current]+276,view_yview[view_current]+3);

That will get the map to the right position.

This is the draw_sprite_part code. I’ve never used it before, and I have no idea how to comprehend it. :astonished:

draw_sprite_part(global.mapimage,0,1+i*8,1+j*8,8,8,50+i*8,50+j*8); :astonished:

I guess the I’s and J’s represent length and width, but can I just do this:

draw_sprite_part(spr_Map1,0,view_xview[view_current]+276,view_yview[view_current]+3);

About the “global.itemcollected[0]” part, the two global variables for missiles are “global.missiles” and “global.maxmissiles”.

Ouch. My head hurts; so many things to fix, lol. I’ll just concentrate on finishing all the sprites for now.

:O_O:

EDIT:

Erm… Okay.

To execute a script using code, just call it like any old function. The line “init_area_1();” would work. It doesn’t require any arguments.

Look up how draw_sprite_part() is called in GM’s help to comprehend it. >_>
Your call to it should actually be:
draw_sprite_part(global.mapimage,0,1+i8,1+j8,8,8,view_xview[view_current]+276+i8,view_yview[view_current]+3+j8);

The i’s and j’s are just integers that change with the for statements. I use i for --Wait, I just noticed a typo in that.

Sorry, here’s what your function call should be:
draw_sprite_part(global.mapimage,0,1+i8,1+j8,8,8,view_xview[view_current]+276+(i+1-SamusMapx)*8,view_yview[view_current]+3+(j+1-SamusMapx)*8);

There. Use that for drawing the sprite box. The same x and y coordinates used in the function I just gave (the entire “view_xview[view_current]+276+(i+1-SamusMapx)*8” should be used for the x coordinate, same idea for the y) should also be used for drawing the symbols in their right places.

Do those store which missiles you’ve collected, or how many? >_>
You’ll need global variables for exactly what missile expansions you’ve collected, otherwise you can’t tell the mini-map how to display their symbols on the map.

Finally, the symbols shouldn’t be boxes like that, since they’ll be displayed OVER boxes. Just keep a solid color as a background with no borders, so that it can be transparent when used in GM.

And once again, only the symbols that change during the course of the game should be part of the extra symbol graphics, like items. Other symbols you can draw right onto the map of the area like you did.

Edit: Oh yeah, and in the script that draws the mini-map, be sure to do this before beginning to display it:

This clears up that first part:

(Ignore the part that actually came after that quote in the post it’s from–it’s not necessary)
So the line for the x might look like this:
SamusMapx = floor(Samus.x/320)+global.room_x;

Also, at the start of the draw even of what you have so far…

That’s supposed to be a black box, not the entire map of the area. See, the mini-map only going to display the boxes you’ve visited so far, so if it doesn’t draw one because you haven’t visited it, it’ll instead be filled in by the giant black box behind the mini-map.

So it should be more like this:
draw_set_color(c_black);
draw_rectangle(view_xview[view_current]+275,view_yview[view_current]+2,view_xview[view_current]+299,view_yview[view_current]+26,false);
draw_set_color(c_white);

I added init_area_1(); to the room creation code, and fixed the drawing code to this:

draw_sprite_part(global.mapimage,0,1+i*8,1+j*8,8,8,view_xview[view_current]+276+(i+1-Map1)*8,view_yview[view_current]+3+(j+1-Map1)*8);

Map1 is the name of my image.

For the global missile variables, does that mean I have to make a new variable for every Missile Expansion I add in? :astonished:

About the symbols, what you told me to do is what I already did. The red is the solid color that will be transparent in GM. I’ll also remove the Save/Map symbols since they stay the same throughout the game.

Here’s what’s about your edit:

I have no script that draws the map, it’s a code in my object “obj_hudcontrol”.

Here’s what in it now:

[code]Map1 = floor(Samus.x/320)+global.room_x;
Map1 = floor(Samus.y/240)+global.room_y;

draw_set_color(c_black);
draw_rectangle(view_xview[view_current]+275,view_yview[view_current]+2,view_xview[view_current]+299,view_yview[view_current]+26,false);
draw_set_color(c_white);

for (i = samusMapx-1; i <= samusMapx+1; i += 1)
{
for (j = samusMapy-1; j <= samusMapy+1; j += 1)
{

  if (i > 0 && j > 0 && i < global.area_width && j < global.area_height)
  {
      if (global.area1_explored[i,j] == true)
      {
          draw_sprite_part(global.mapimage,0,1+i8,1+j8,8,8,view_xview[view_current]+276+(i+1-Map1)*8,view_yview[view_current]+3+(j+1-Map1)*8);
          draw_symbol(); // XMD: I’ll do this part once I actually draw the symbols.
      }
  }
}
}[/code]

EDIT: Fixed it some more:

[code]Map1 = floor(Samus.x/320)+global.room_x;
Map1 = floor(Samus.y/240)+global.room_y;

draw_set_color(c_black);
draw_rectangle(view_xview[view_current]+275,view_yview[view_current]+2,view_xview[view_current]+299,view_yview[view_current]+26,false);
draw_set_color(c_white);

for (i = Map1-1; i <= Map1+1; i += 1)
{
for (j = Map1-1; j <= Map1+1; j += 1)
{

  if (i > 0 && j > 0 && i < global.area_width && j < global.area_height)
  {
      if (global.area1_explored[i,j] == true)
      {
          draw_sprite_part(global.mapimage,0,1+i8,1+j8,8,8,view_xview[view_current]+276+(i+1-Map1)*8,view_yview[view_current]+3+(j+1-Map1)*8);
          draw_symbol(); // XMD: I’ll do this part once I actually draw the symbols.
      }
  }
}[/code]

Edit again: I really think I should use my old “mapdata” sprite; it’s just an empty map grid. So, if there’s a room you haven’t explored yet, it’ll look like the rest of the grid, with no room there, or atleast no visible room there. :astonished:

Erm. O_o

If Map1 is the name of your image, why are you sticking it in in place of Samus’s coordinates on the map?

You set Samus’s x coordinate on the map to Map1, then set her y coordinate to it right afterwards… The drawing code is going to think that her x is the same value as her y and get all messed up. That is, if it even RUNS while you’re trying to set values to a sprite…

Leave Samus’s x and y coordinates on the map as the names “SamusMapx” and “SamusMapy”. They need to be two separate variables and why call them anything different.

The only place you would use Map1 is at the start of init_area_1(), which you did, to store the id of the sprite that it draws the boxes from.

…You saying you didn’t already have that before? What happens if you collect an item, step out of the room, then walk back in? If it’s there again, then yes, you’ll have to make global variables storing if it’s collected for each item. (I would use an array, actually, but there wouldn’t be a difference in this case) If not… Don’t tell me you use that state-saving room thing GM has. >_>

Anyway, don’t make separate missile expansion objects for each room or anything. Use the same one, but give it some code that it can execute in the room’s creation code for that expansion. Like, ‘missile_expansion.collection = “global.area1_missile1 = true”;’ And in the missile expansion object, when it’s collected, it would have ‘execute_string(collection);’ (in addition to changing its symbol on the map). That way you can assign each instance a different variable for its collection without cluttering up your objects list. And to relate this to our mini-map again, in init_area_1() it’ll check each items’s variable in the area and give it the right symbol.

Alright. The white borders should go, though. (If you take one of those symbols and stick it over the map of the area you made, it shouldn’t add anything but the symbol itself, so that it can be placed over any box on the map)

So, fixing all that… Want to test-run the code we have so far? Report any errors or glitches that occur.

When I collect an item and step out of the room, then come back, the item stays gone. o_o

And no, I don’t use those F5/F6 GM saving stuff. In fact, I don’t a save system at all, :astonished:.

I also can’t run the game yet because it won’t compile.

^^ This is what I was talking about. It saves the state (or “status”) of the room.

Do enemies reappear when you leave and return? If so, figure out what makes them different from items. (Maybe just being in a non-persistent room) If not… You must have that thing above activated, in which case you’ll need to set up a global variable for each item storing whether it’s been collected or not, just for the mini-map. (I hate room persistence in GM) Follow the paragraph in my previous post on how to do so for missile instances in this case.

Finally, is it not “compiling” because of the mini-map code or something else?

Heh, yeah, the room’s persistent. :blush: So, should I take it off?

And it’s not compiling because of the minimap code.

This is what I have:

[code]
Room 1’s Creation code
global.room_x = 0;
global.room_y = 0;

global.area1_explored[i,j] = true

init_area_1();

//Item Collection Code
m_e.collection = “global.area1_missile1 = true”;
e_t.collection = “global.area1_=energy1 = true”;[/code]

That’s fine.

[code]/////MAP CODE/////

Map1 = floor(Samus.x/320)+global.room_x;
Map1 = floor(Samus.y/240)+global.room_y;

//Draw Black Box Code :open_mouth:
//draw_set_color(c_black);
//draw_rectangle(view_xview[view_current]+275,view_yview[view_current]+2,view_xview[view_current]+299,view_yview[view_current]+26,false);
//draw_set_color(c_white);
//End of Draw Black Box Code

draw_sprite(spr_mapdata,0,view_xview[view_current]+275,view_yview[view_current]+2);

for (i = samusMapx-1; i <= samusMapx+1; i += 1)
{
for (j = samusMapy-1; j <= samusMapy+1; j += 1)
{

 if (i > 0 && j > 0 && i < global.area_width && j < global.area_height)
 {
     if (global.area1_explored[i,j] == true)
     {
         draw_sprite_part(global.mapimage,0,1+i8,1+j8,8,8,view_xview[view_current]+276+(i+1-SamusMapx)*8,view_yview[view_current]+3+(j+1-SamusMapx)*8);
         draw_symbol();      
     }
 }
}
}[/code]

It’s the draw_symbol temporary thing that won’t compile. I’m working on it.

[code]if (global.area != 1) // * = area #
{
global.mapimage = Map1; // * = map sprite
global.area_width = 6;
global.area_height = 6;

/*
You do have global variables for the items, right?
So that if you collect an item, leave the room, and come back…
…It’s not there? If so, here’s where you look at all those
to see if they’re collected or not, and set the correct symbol
on the map
*/

// So you’d clear out all junk from previous areas on the map
for (i = 0; i < 6; i += 1)
{
for (j = 0; j < 6; j += 1)
{
  global.area_symbol[i,j] = 0;
  // Each element in this array is the position on the map
  // And whether it has a symbol or not
  // The value it stores is up to you
  // 0 is the default in my example, meaning no symbol
  // 1 might represent, maybe, an uncollected item
  // Then when you’re drawing the symbols later
  // Draw the right one based on the value in the array
}
}

// Then here’s where you’d fill in the symbols over the default set above
if (global.itemcollected[0] == true) global.area_symbol[5,5] = 2;
else global.area_symbol[5,5] = 1;

// etc.
}[/code]

Working on global variables for tanks.

Sorry I’m going so slow, my internet is being really evil right now. :astonished:

I’ve done what’s crossed out.

You don’t have to make it not persistent if you don’t want to (you’ll then have to do a little extra work to get it not to reappear again). The global variable you set up is all that’s needed for the mini-map.

Typo in Room1’s creation code. From the last line: “global.area1_=energy1 = true”. There’s an extra equal sign.

The map code won’t work because SamusMapx and SamusMapy were never initialized. This:

Map1 = floor(Samus.x/320)+global.room_x;
Map1 = floor(Samus.y/240)+global.room_y;

Should be this:

SamusMapx = floor(Samus.x/320)+global.room_x;
SamusMapy = floor(Samus.y/240)+global.room_y;

And just a friendly remind that draw_symbol() can be replaced with draw_sprite()'s (with all the if statements for which symbol it is in that box–see an earlier post of mine). The same coordinates as the box should be used. Point (view_xview[view_current]+276+(i+1-SamusMapx)*8, view_yview[view_current]+3+(j+1-SamusMapx)*8)

If you need any help in that final part down there with the crossed-out text, feel free to ask.

begins playing Final Countdown music