G
GeekmasterK
Guest
Disclaimer: this is my first post on the forums here, so I can't provide a link to the tutorial I was following.
So, I'm working on a top-down RPG, and found an excellent tutorial on pixel-perfect tilemap collisions. It works flawlessly when colliding with objects, but when the player object reaches the room edge, I get the following error:
___________________________________________
############################################################################################
FATAL ERROR in
action number 1
of Step Event0
for object obj_player:
Push :: Execution Error - Variable Index [524,9184] out of range [1,-1] - -5.Heights(100003,16777184)
at gml_Script_scr_TestCollision (line 6) - var hh = global.Heights[column];
############################################################################################
--------------------------------------------------------------------------------------------
stack frame is
gml_Script_scr_TestCollision (line 6)
called from - gml_Object_obj_player_Step_0 (line 90) - yCol = scr_TestCollision(x, floor(y)+15);
I know that this kind of error is caused by an index exceeding the array limit, or going into the negative for the index. The problem is, I don't know how to prevent it in this case. After researching this problem extensively, I thought I would turn to the forums for help. Here's my code:
obj_init (initialization object)
scr_TestCollision (Script to check for collisions)
obj_player (player object)
Sorry if this post is long, but I've been wracking my brain against this problem for a while now. Help is appreciated!
Edit: Forgot to mention. My version of Game Maker is v2.0.6.146
So, I'm working on a top-down RPG, and found an excellent tutorial on pixel-perfect tilemap collisions. It works flawlessly when colliding with objects, but when the player object reaches the room edge, I get the following error:
___________________________________________
############################################################################################
FATAL ERROR in
action number 1
of Step Event0
for object obj_player:
Push :: Execution Error - Variable Index [524,9184] out of range [1,-1] - -5.Heights(100003,16777184)
at gml_Script_scr_TestCollision (line 6) - var hh = global.Heights[column];
############################################################################################
--------------------------------------------------------------------------------------------
stack frame is
gml_Script_scr_TestCollision (line 6)
called from - gml_Object_obj_player_Step_0 (line 90) - yCol = scr_TestCollision(x, floor(y)+15);
I know that this kind of error is caused by an index exceeding the array limit, or going into the negative for the index. The problem is, I don't know how to prevent it in this case. After researching this problem extensively, I thought I would turn to the forums for help. Here's my code:
obj_init (initialization object)
Code:
// Create event
#macro TILE_MAX 192 // Maximum number of tiles in tilemap
#macro TILE_SIZE 32 // Size of each tile (applies to both width and height)
Code:
// Draw event
global.Heights = [TILE_SIZE * TILE_MAX];
// Surface and buffer to store the tiles
var surf = surface_create(TILE_SIZE * TILE_MAX, TILE_SIZE);
var buff = buffer_create(TILE_SIZE * TILE_MAX * TILE_SIZE * 4, buffer_fixed, 1);
surface_set_target(surf);
draw_clear_alpha(0, 0);
// Loop through tiles
for(var i = 0; i < TILE_MAX; i++){
draw_tile(tl_test, i, 0, i*TILE_SIZE, 0);
}
surface_reset_target();
buffer_get_surface(buff, surf, 0, 0, 0);
// Nested loop to count the exact pixels of each tile
for(var xx = 0; xx < (TILE_SIZE * TILE_MAX); xx++){
var count = 0;
for(var yy = 0; yy < TILE_SIZE; yy++){
var pixel = buffer_peek(buff, (xx+(yy * TILE_SIZE * TILE_MAX))*4, buffer_u32);
if((pixel&0xff000000) != 0) break;
count++;
}
global.Heights[xx] = count;
}
buffer_delete(buff);
surface_free(surf);
room_goto_next();
Code:
// Define arguments
var _x = argument0;
var _y = argument1;
// Perform collision calculation
var t = tilemap_get_at_pixel(tileID, _x, _y) & tile_index_mask;
var column = (_x&(TILE_SIZE - 1)) + (t * TILE_SIZE);
var hh = global.Heights[column];
var yy = _y&(TILE_SIZE - 1);
// Check if a collision happens
if(hh == 0) return true;
if(hh == TILE_SIZE) return false;
if(yy >= hh) return true;
return false;
Code:
// Create event
// Set default facing direction
directionFacing = "Down";
// Set default movement speed
baseSpeed = 7;
// Get the ID of the collision tile layer
var layerID = layer_get_id("Collision");
tileID = layer_tilemap_get_id(layerID);
Code:
// Step event
// Temporary variables
var xMove = 0;
var yMove = 0;
// Keep player in the room
x = clamp(x, 0, room_width);
y = clamp(y, 0, room_height);
// Get inputs
if(keyboard_check(ord("A")) || keyboard_check(vk_left)){
xMove--;
image_speed = 0.5;
sprite_index = spr_player_walk_left;
directionFacing = "Left";
}
if(keyboard_check(ord("D")) || keyboard_check(vk_right)){
xMove++;
image_speed = 0.5;
sprite_index = spr_player_walk_right;
directionFacing = "Right";
}
if(keyboard_check(ord("W")) || keyboard_check(vk_up)){
yMove--;
image_speed = 0.5;
sprite_index = spr_player_walk_up;
directionFacing = "Up";
}
if(keyboard_check(ord("S")) || keyboard_check(vk_down)){
yMove++;
image_speed = 0.5;
sprite_index = spr_player_walk_down;
directionFacing = "Down";
}
// Idle animation
if(!(keyboard_check(ord("A")) || keyboard_check(vk_left)) && !(keyboard_check(ord("D")) || keyboard_check(vk_right)) && !(keyboard_check(ord("W")) || keyboard_check(vk_up)) && !(keyboard_check(ord("S")) || keyboard_check(vk_down))){
if(directionFacing == "Left"){
sprite_index = spr_player_idle_left;
}
if(directionFacing == "Right"){
sprite_index = spr_player_idle_right;
}
if(directionFacing == "Up"){
sprite_index = spr_player_idle_up;
}
if(directionFacing == "Down"){
sprite_index = spr_player_idle_down;
}
}
// Reduce diagonal move speed
var moveSpeed = baseSpeed;
if(xMove != 0 && yMove != 0) moveSpeed = baseSpeed * 0.75;
// Horizontal collision detection
x += xMove * moveSpeed;
//Left
var xCol = true;
while(xCol){
xCol = scr_TestCollision(floor(x)+15, y);
if(xCol){
xMove = 0;
x = floor(x - 1);
}
}
//Right
var xCol2 = true;
while(xCol2){
xCol2 = scr_TestCollision(floor(x)-15, y);
if(xCol2){
xMove = 0;
x = floor(x + 1);
}
}
// Vertical collision detection
y += yMove * moveSpeed;
//Down
var yCol = true;
while(yCol){
yCol = scr_TestCollision(x, floor(y)+15);
if(yCol){
yMove = 0;
y = floor(y - 1);
}
}
//Up
var yCol2 = true;
while(yCol2){
yCol2 = scr_TestCollision(x, floor(y)-15);
if(yCol2){
yMove = 0;
y = floor(y + 1);
}
}
Edit: Forgot to mention. My version of Game Maker is v2.0.6.146
Last edited by a moderator: