Hello again. This problem is related to a previous topic I opened (https://forum.yoyogames.com/index.php?threads/cropping-an-objects-sprite-with-code.92396/)
Most of the suggestions levied there did not solve the issue and I could not wrap my head around it, so I torched most of that code and began following a different method based on suggestions made there. However, for the sack of completeness, I will begin from the start explaining the code I have and its current issue. (I am not having cropping issues too similar to the previous topic's, that is why this is a new thread).
In my game, I am developing a tower stacking mini game. The goal of the game is to take a horizontal log shaped block thats moving back and forth at the top of the screen and to stack it on top of previous blocks placed as precisely as they can. If the player misses, the overhanging part of the block gets cut off. If the player ends up with blocks shaved too much before the game ends after, say, 20 blocks, they lose.
Here we have a collision event. The object
Explaining how this works line by line:
First, I must explain all this code is for when we have already placed a block. When we place a block, it gets swapped out with a "dummy block" to stand in its place while the original block immediately teleports back to the top of the screen.
In this code, We check if our regular block is not at the top of the screen (this might not be needed but I thought if aint broke dont fix it), then we get the difference between the X Origin points between the regular block and the dummy block it just contacted. For the sake of the crop function used later, we also get the inverse of the difference (negative/opposite sign). We then set it so the tracking variable "hasPressedX" is false to make sure the game doesnt instantly drop the next block. We then set our regular block's Y position to 24 pixels above the dummy block to force it the proper spot in case we stopped the falling block at the wrong y position.
We then create a new dummy block at the exact spot the regular block stopped, and then immediately we increment the "pieceIndex" by 1 to help track which number of piece we are on. We then also add the newDummy instance to an array called blockArray. We then have a check to see if our xDifference was negative or positive, and depending on which one, we activate the specific crop direction function we want. After cropping, the resetPiece function executes. Here is its simple code inside the create event of this object:
Moving on, I have to preface that first before I get crop_right working I'm trying to get crop_left working. Anyway, setting crop_left to true activates the following code in the DRAW EVENT of
First, we check if an instance of the newDummy (the particular instance we just created) exists. If it does, we check if we are working with the particular instance we just created too. Then, if we turned on crop_left, it first gets the current xDifference of our particular instance of the dummy block and stores that in xDiffIndex. After that, we round the x value of the dummy block to make sure its a solid number, and then we crop the sprite using those parameters.
Skipping down a bit, we find that if we didnt activate crop_left or right, we just draw_self(). Further down, if the id of the current instance is not the same as the id of the newest Dummy, we take the ds_grid we defined earlier like this:
and then we take that ds_grid and resize it by making its height equal to the current pieceIndex + 1. In the first column of that grid and in the y position of that column equal to the pieceIndex, we add in whatever the current instance's width is. The next part is we add in the current xDifference into the second column and the same y position as the pieceIndex.
We should then draw each individual piece we drop according to the recorded xDifference and width it had. However, in practice, this does not quite happen...
My main concern is why it crops the very first block slightly from the very right when the second block drops. My second concern is how each block placed after the second crops as if the whole block underneath it were still there, but thats besides the point. I forst want to focus on why the first block crops on its right erroneously. If you have a solution for the second problem however, I'm open to it.
Thank you for reading all this text, I'm aware how complicated this may be to understand
(P.S. this time I'll be more open to re-reading and FULLY understanding any presented help and solutions. Last post was a bit of fiasco and I apologize for my behavior. Thank you for taking the time out of your busy day to respond if you do. Me and my other junior dev partner are banging our heads together trying to solve this mini game code challenge)
(EDIT: gif link was broken)
Most of the suggestions levied there did not solve the issue and I could not wrap my head around it, so I torched most of that code and began following a different method based on suggestions made there. However, for the sack of completeness, I will begin from the start explaining the code I have and its current issue. (I am not having cropping issues too similar to the previous topic's, that is why this is a new thread).
In my game, I am developing a tower stacking mini game. The goal of the game is to take a horizontal log shaped block thats moving back and forth at the top of the screen and to stack it on top of previous blocks placed as precisely as they can. If the player misses, the overhanging part of the block gets cut off. If the player ends up with blocks shaved too much before the game ends after, say, 20 blocks, they lose.
Here we have a collision event. The object
obj_blockPiece
is dropped, and as soon as it collides with an instance of obj_dummyBlock
, it executes this code:
GML:
/// @description
// only allow this code to run if the piece is dropped
if self.y > 69 {
xDifference = round(self.x - other.x);
xDiffInverse = xDifference * -1;
hasPressedX = false;
// get the instance id of the object collided with
collidedID = other.id;
self.y = collidedID - 24;
// the math in the Y makes sure the y position of the piece is 16 pixels above the origin point
newDummy = instance_create_layer(self.x, collidedID.y - 24, "Puzzle_Elements", obj_dummyBlock);
pieceIndex += 1;
array_set(blockArray, pieceIndex, newDummy);
// if the block is placed left, the xDifference is negative. Inverse that number to measure difference from the left
if xDifference < 0 {
xDifference = xDiffInverse;
// record what the current Piece's x difference is in an array
array_set(pieceArray, pieceIndex, xDifference);
crop_left = true;
if obj_dummyBlock.xDiffIndex {
obj_dummyBlock.new_width = obj_dummyBlock.new_width-dummyBlock.xDiffIndex;
}
}
if xDifference > 0 {
crop_right = true;
}
crop_left = true;
resetPiece();
}
First, I must explain all this code is for when we have already placed a block. When we place a block, it gets swapped out with a "dummy block" to stand in its place while the original block immediately teleports back to the top of the screen.
In this code, We check if our regular block is not at the top of the screen (this might not be needed but I thought if aint broke dont fix it), then we get the difference between the X Origin points between the regular block and the dummy block it just contacted. For the sake of the crop function used later, we also get the inverse of the difference (negative/opposite sign). We then set it so the tracking variable "hasPressedX" is false to make sure the game doesnt instantly drop the next block. We then set our regular block's Y position to 24 pixels above the dummy block to force it the proper spot in case we stopped the falling block at the wrong y position.
We then create a new dummy block at the exact spot the regular block stopped, and then immediately we increment the "pieceIndex" by 1 to help track which number of piece we are on. We then also add the newDummy instance to an array called blockArray. We then have a check to see if our xDifference was negative or positive, and depending on which one, we activate the specific crop direction function we want. After cropping, the resetPiece function executes. Here is its simple code inside the create event of this object:
Code:
function resetPiece() {
spawnX = random_range(137, 348);
self.y = 69;
self.x = spawnX;
turn += 1;
}
obj_dummyBlock
:
GML:
show_debug_message("newDummy X = " + string(x));
show_debug_message("DSGRID X = " + string(ds_grid_width(widthGrid)));
show_debug_message("DSGRID Y = " + string(ds_grid_height(widthGrid)));
show_debug_message("argument 7 = " + string(widthGrid[# 1, obj_blockPiece.pieceIndex]));
//draw_rectangle_color(x-36, y-40, x+36, y, c_red, c_blue, c_yellow, c_green, true);
if instance_exists(obj_blockPiece.newDummy) {
if id == obj_blockPiece.newDummy.id {
if obj_blockPiece.crop_left { //-36
xDiffIndex = array_get(obj_blockPiece.pieceArray, obj_blockPiece.pieceIndex);
x = round(x);
draw_sprite_part(sprite_index, image_index, xDiffIndex, 0, new_width, sprite_height, (x-36)+xDiffIndex, y-40);
show_debug_message("newDummy crop_left X = " + string(x));
} else if obj_blockPiece.crop_right {
} else {
draw_self();
}
} else {
ds_grid_resize(widthGrid, 2, obj_blockPiece.pieceIndex + 1);
ds_grid_set(widthGrid, 0, obj_blockPiece.pieceIndex, new_width);
ds_grid_set(widthGrid, 1, obj_blockPiece.pieceIndex, xDiffIndex);
draw_sprite_part(sprite_index, image_index, widthGrid[# 1, obj_blockPiece.pieceIndex], 0, widthGrid[# 0, obj_blockPiece.pieceIndex], sprite_height, (x - 36)+widthGrid[# 1, obj_blockPiece.pieceIndex], y-40);
//draw_rectangle_color(x-(sprite_width/2), y-(sprite_width/2), x+(sprite_width/2), y+(sprite_height/2), c_red, c_red, c_red, c_red, true);
}
} else {
draw_self();
}
Skipping down a bit, we find that if we didnt activate crop_left or right, we just draw_self(). Further down, if the id of the current instance is not the same as the id of the newest Dummy, we take the ds_grid we defined earlier like this:
GML:
// create event of obj_dummyBlock
new_width = sprite_width;
xDiffIndex = noone;
widthGrid = ds_grid_create(2, 1);
We should then draw each individual piece we drop according to the recorded xDifference and width it had. However, in practice, this does not quite happen...
My main concern is why it crops the very first block slightly from the very right when the second block drops. My second concern is how each block placed after the second crops as if the whole block underneath it were still there, but thats besides the point. I forst want to focus on why the first block crops on its right erroneously. If you have a solution for the second problem however, I'm open to it.
Thank you for reading all this text, I'm aware how complicated this may be to understand
(P.S. this time I'll be more open to re-reading and FULLY understanding any presented help and solutions. Last post was a bit of fiasco and I apologize for my behavior. Thank you for taking the time out of your busy day to respond if you do. Me and my other junior dev partner are banging our heads together trying to solve this mini game code challenge)
(EDIT: gif link was broken)
Last edited: