• Hey Guest! Ever feel like entering a Game Jam, but the time limit is always too much pressure? We get it... You lead a hectic life and dedicating 3 whole days to make a game just doesn't work for you! So, why not enter the GMC SLOW JAM? Take your time! Kick back and make your game over 4 months! Interested? Then just click here!

FATAL ERROR: trying to index a variable which is not an array

N

NickCikovic

Guest
I have been working on an interesting 2D platform game for about 8 months now. Everything with development was going good until this weird error showed up when I was trying to implement a tile collision system. The reason I switched to a tile collision system from the original system is because it is supposed to make slopes easier to implement. I'm following a few different tutorials to make this 2D platform game into something special. The main ones I'm looking at are ones made by Shaun Spalding, so if the code looks familiar, it should. I swear, I followed along EXACTLY as I should, and for some reason, this error keeps popping up when it never did before. I refreshed the cache, didn't work. Tried modifying the code a bit, didn't work. It's telling me there's an error in Line 10 of the InFloor script and that it's being called from Line 70 of the oPlayer object's Step Event. I'm completely stumped and any help is appreciated. The code is as follows.

InFloor Script
GML:
/// @description Checks to see if position is below the floor height of a given tile, returns how deep in floor
/// @arg tilemap
/// @arg x
/// @arg y

var pos = tilemap_get_at_pixel(argument0,argument1,argument2);
if (pos > 0)
{
    if (pos == 1) return (argument2 mod TILE_SIZE); //solid block, would end up returning true anyway but this is FASTER, GOTTAGOFAST.
    var thefloor = global.heights[(argument1 mod TILE_SIZE) + (pos * TILE_SIZE)];
    return ((argument2 mod TILE_SIZE) - thefloor);
} else return -(TILE_SIZE - (argument2 mod TILE_SIZE));
oPlayer Step Event
GML:
/// @description Movement & Collision

//Event Variables
var bbox_side;
var p1,p2,slope;

//Get inputs
key_right = keyboard_check_direct(vk_right);
key_left = keyboard_check_direct(vk_left);
key_up = keyboard_check(vk_up);
key_down = keyboard_check(vk_down);

//Calculate Movement
move = (key_right - key_left) * SPD_WALK
hsp = move;
vsp += SPD_GRAVITY

//Is my middle center touching the floor at the start of this frame?
var grounded = (InFloor(tilemap,x,bbox_bottom+1) >= 0);

//Jump
if (grounded || (InFloor(tilemap,bbox_left,bbox_bottom+1) >= 0) || (InFloor(tilemap,bbox_right,bbox_bottom+1) >= 0))
{
    if (key_up)
    {
        vsp = -SPD_JUMP;
        grounded = false;
    }
}

//Re apply fractions
hsp += hsp_fraction;
vsp += vsp_fraction;

//Store and Remove fractions
//Important: go into collision with whole integers ONLY!
hsp_fraction = hsp - (floor(abs(hsp)) * sign(hsp));
hsp -= hsp_fraction;
vsp_fraction = vsp - (floor(abs(vsp)) * sign(vsp));
vsp -= vsp_fraction;


//Horizontal Collision
if (hsp > 0) bbox_side = bbox_right; else bbox_side = bbox_left;
p1 = tilemap_get_at_pixel(tilemap,bbox_side+hsp,bbox_top);
p2 = tilemap_get_at_pixel(tilemap,bbox_side+hsp,bbox_bottom);
if (tilemap_get_at_pixel(tilemap,x,bbox_bottom) > 1) p2 = 0; //ignore bottom side tiles if on a slope.
if (p1 == 1) || (p2 == 1) //Inside a tile with collision
{
    if (hsp > 0) x = x - (x mod TILE_SIZE) + (TILE_SIZE-1) - (bbox_right - x);
    else x = x - (x mod TILE_SIZE) - (bbox_left - x);
    hsp = 0;
}
x += hsp;

//Vertical Collision
//is this not a slope?
if (tilemap_get_at_pixel(tilemap,x,bbox_bottom+vsp) <= 1)
{
    if (vsp >= 0) bbox_side = bbox_bottom; else bbox_side = bbox_top;
    p1 = tilemap_get_at_pixel(tilemap,bbox_left,bbox_side+vsp)
    p2 = tilemap_get_at_pixel(tilemap,bbox_right,bbox_side+vsp)
    if (p1 == 1) || (p2 == 1)
    {
        if (vsp >= 0) y = y - (y mod TILE_SIZE) + (TILE_SIZE-1) - (bbox_bottom - y);
        else y = y - (y mod TILE_SIZE) - (bbox_top - y);
        vsp = 0;
    }
}
var floordist = InFloor(tilemap,x,bbox_bottom+vsp);
if (floordist >= 0)
{
    y += vsp;
    y -= (floordist+1);       
    vsp = 0;
    floordist = -1;
}
y += vsp;


//Walk down slopes
if (grounded)
{
    y += abs(floordist)-1;
    //if at base of current tile
    if ((bbox_bottom mod TILE_SIZE) == TILE_SIZE-1)
    {
        // if slope continues
        if (tilemap_get_at_pixel(tilemap,x,bbox_bottom+1) > 1)
        {
            //move there
            y += abs(InFloor(tilemap,x,bbox_bottom+1));
        }
    }
}
 

curato

Member
if I am following you the key would be to see how you are declaring and initializing global.heights

Edit: dang jinx!
 
N

NickCikovic

Guest
Where are you defining global.heights?
It's in the Draw Event of oInit. Here is the code:
GML:
/// @description Build height table then start game
{
    draw_tilemap(tilemapid,0,0);
    for (var i = heightstoget-1; i >= 0; i--)
    {
        var check = 0;
        while (check <= TILE_SIZE)
        {
            global.heights[i] = check;
            if (check == TILE_SIZE) break;
            if (surface_getpixel(application_surface,i,check) != c_black)
            {
                break;
            }
            check++;
        }
    }
}

room_goto_next();
 
N

NickCikovic

Guest
if I am following you the key would be to see how you are declaring and initializing global.heights

Edit: dang jinx!
That's one thing I'm thinking I need to figure out. I'm still learning at this kind of thing.
 

curato

Member
That's one thing I'm thinking I need to figure out. I'm still learning at this kind of thing.
Yeah I think there is a logical error there somewhere I can't untangle which tile you are looking at. When I do this type of thing I just look at like I am doing a place_meeting command do a tilemap_get_at_pixel at the current position plus the speed you are traveling. If it is zero then you are good if not then you need to look at the number and see what that means to you. In a simple case that is the floor so you set speed to zero. In a more complicated example you need to figure the pixel perfect distance to land on that tile. (which i do just by doing a loop and reducing it by one until I get a zero then I move there then stop.
 

FrostyCat

Redemption Seeker
You need to pause the game for one step and NOT try to access global.heights at all while oInit sets up. Draw comes after Step in the step event cycle.

Alternatively, zero out global.heights in the Create event, and just allow one step of not having proper collisions while oInit sets up. Better than an error.
 
N

NickCikovic

Guest
You need to pause the game for one step and NOT try to access global.heights at all while oInit sets up. Draw comes after Step in the step event cycle.

Alternatively, zero out global.heights in the Create event, and just allow one step of not having proper collisions while oInit sets up. Better than an error.
I have yet to actually implement the pause feature, so that first method is out of the question for now, as I'm trying to make sure everything else is working correctly. I tried the second method, but that didn't do any good.
 
Top