How to get rect of a pygame Surface without transparent parts?
I am implementing collision detection and want to check if a rectangular object is touching the player. My wall uses .set_colorkey(background) where background is the specified background colour. The problem is that when I get my wall's rectangle with .get_rect(), it gets the full image's size which includes the transparent parts instead of just the opaque parts.
I thought about making the wall image file smaller in size to remove the background but that would be inconvenient as I would need to do this for each partially transparent image I have. I also thought about using arrays to get the colour and checking if it matches the background colour and getting the rectangle's size from there but that would be slow and cumbersome.
for x, y in ((i, j) for i in land_x for j in land_y):
# land_x, land_y hold the tiles to be checked
try:
tx1, ty1, tx2, ty2 =
texture[land[y][x]].get_rect()
# tx1, ty1 coordinates of top-left corner
# tx2, ty2 width and height respectively
if tx2 == 0 and ty2 == 0:
continue # skip to other objects
tx1 = x*64 - tx2/2
ty1 = y*64 - ty2/2
px1, py1, px2, py2 =
PLAYER.get_rect()
px1 = player_x - px2/2
py1 = -player_y - py2/2
if p.Rect(px1, py1, px2, py2).colliderect(
p.Rect(tx1, ty1, tx2, ty2)
):
player_x -= direction_x
break # go outside loop to start checking y
except IndexError: # incase player is outside map
pass # skip to other objects
The .get_rect() outputs a rectangle the size of the whole image whereas I want a rectangle that doesn't include the transparent parts.
Example:
texture is a 64x64 image with a 48x48 block in the centre.
The background colour is removed and a 48x48 solid coloured block is left (even though the image size is still 64x64).
Expected Output:
texture.get_rect() should output a rectangle of size 48x48.
Actual Output:
texture.get_rect() instead outputs a rectangle of size 64x64.
Any help on this would be appreciated :D
python pygame pygame-surface
add a comment |
I am implementing collision detection and want to check if a rectangular object is touching the player. My wall uses .set_colorkey(background) where background is the specified background colour. The problem is that when I get my wall's rectangle with .get_rect(), it gets the full image's size which includes the transparent parts instead of just the opaque parts.
I thought about making the wall image file smaller in size to remove the background but that would be inconvenient as I would need to do this for each partially transparent image I have. I also thought about using arrays to get the colour and checking if it matches the background colour and getting the rectangle's size from there but that would be slow and cumbersome.
for x, y in ((i, j) for i in land_x for j in land_y):
# land_x, land_y hold the tiles to be checked
try:
tx1, ty1, tx2, ty2 =
texture[land[y][x]].get_rect()
# tx1, ty1 coordinates of top-left corner
# tx2, ty2 width and height respectively
if tx2 == 0 and ty2 == 0:
continue # skip to other objects
tx1 = x*64 - tx2/2
ty1 = y*64 - ty2/2
px1, py1, px2, py2 =
PLAYER.get_rect()
px1 = player_x - px2/2
py1 = -player_y - py2/2
if p.Rect(px1, py1, px2, py2).colliderect(
p.Rect(tx1, ty1, tx2, ty2)
):
player_x -= direction_x
break # go outside loop to start checking y
except IndexError: # incase player is outside map
pass # skip to other objects
The .get_rect() outputs a rectangle the size of the whole image whereas I want a rectangle that doesn't include the transparent parts.
Example:
texture is a 64x64 image with a 48x48 block in the centre.
The background colour is removed and a 48x48 solid coloured block is left (even though the image size is still 64x64).
Expected Output:
texture.get_rect() should output a rectangle of size 48x48.
Actual Output:
texture.get_rect() instead outputs a rectangle of size 64x64.
Any help on this would be appreciated :D
python pygame pygame-surface
add a comment |
I am implementing collision detection and want to check if a rectangular object is touching the player. My wall uses .set_colorkey(background) where background is the specified background colour. The problem is that when I get my wall's rectangle with .get_rect(), it gets the full image's size which includes the transparent parts instead of just the opaque parts.
I thought about making the wall image file smaller in size to remove the background but that would be inconvenient as I would need to do this for each partially transparent image I have. I also thought about using arrays to get the colour and checking if it matches the background colour and getting the rectangle's size from there but that would be slow and cumbersome.
for x, y in ((i, j) for i in land_x for j in land_y):
# land_x, land_y hold the tiles to be checked
try:
tx1, ty1, tx2, ty2 =
texture[land[y][x]].get_rect()
# tx1, ty1 coordinates of top-left corner
# tx2, ty2 width and height respectively
if tx2 == 0 and ty2 == 0:
continue # skip to other objects
tx1 = x*64 - tx2/2
ty1 = y*64 - ty2/2
px1, py1, px2, py2 =
PLAYER.get_rect()
px1 = player_x - px2/2
py1 = -player_y - py2/2
if p.Rect(px1, py1, px2, py2).colliderect(
p.Rect(tx1, ty1, tx2, ty2)
):
player_x -= direction_x
break # go outside loop to start checking y
except IndexError: # incase player is outside map
pass # skip to other objects
The .get_rect() outputs a rectangle the size of the whole image whereas I want a rectangle that doesn't include the transparent parts.
Example:
texture is a 64x64 image with a 48x48 block in the centre.
The background colour is removed and a 48x48 solid coloured block is left (even though the image size is still 64x64).
Expected Output:
texture.get_rect() should output a rectangle of size 48x48.
Actual Output:
texture.get_rect() instead outputs a rectangle of size 64x64.
Any help on this would be appreciated :D
python pygame pygame-surface
I am implementing collision detection and want to check if a rectangular object is touching the player. My wall uses .set_colorkey(background) where background is the specified background colour. The problem is that when I get my wall's rectangle with .get_rect(), it gets the full image's size which includes the transparent parts instead of just the opaque parts.
I thought about making the wall image file smaller in size to remove the background but that would be inconvenient as I would need to do this for each partially transparent image I have. I also thought about using arrays to get the colour and checking if it matches the background colour and getting the rectangle's size from there but that would be slow and cumbersome.
for x, y in ((i, j) for i in land_x for j in land_y):
# land_x, land_y hold the tiles to be checked
try:
tx1, ty1, tx2, ty2 =
texture[land[y][x]].get_rect()
# tx1, ty1 coordinates of top-left corner
# tx2, ty2 width and height respectively
if tx2 == 0 and ty2 == 0:
continue # skip to other objects
tx1 = x*64 - tx2/2
ty1 = y*64 - ty2/2
px1, py1, px2, py2 =
PLAYER.get_rect()
px1 = player_x - px2/2
py1 = -player_y - py2/2
if p.Rect(px1, py1, px2, py2).colliderect(
p.Rect(tx1, ty1, tx2, ty2)
):
player_x -= direction_x
break # go outside loop to start checking y
except IndexError: # incase player is outside map
pass # skip to other objects
The .get_rect() outputs a rectangle the size of the whole image whereas I want a rectangle that doesn't include the transparent parts.
Example:
texture is a 64x64 image with a 48x48 block in the centre.
The background colour is removed and a 48x48 solid coloured block is left (even though the image size is still 64x64).
Expected Output:
texture.get_rect() should output a rectangle of size 48x48.
Actual Output:
texture.get_rect() instead outputs a rectangle of size 64x64.
Any help on this would be appreciated :D
python pygame pygame-surface
python pygame pygame-surface
asked Dec 31 '18 at 22:55
GeeTransitGeeTransit
694215
694215
add a comment |
add a comment |
2 Answers
2
active
oldest
votes
If you want to ignore the transparent pixels in your collision detection, you're talking about pixel-perfect collision.
To do this in pygame, pygame offers the Mask class. You usually create your masks with pygame.mask.from_surface and use it together with pygame.sprite.spritecollide and pygame.sprite.collide_mask.
Maybe think about using pygame's Sprite class to make use of all the features it offers.
Even if you don't want to use pygame's build-in collision detection, you can take a look at the source to see how it works.
add a comment |
You are making this too hard. You know the size of your objects. Add a smaller collision rect to each of your objects at creation time and use that for collision. Or use a circle if that is better for the object.
tile.crect = Rect(whatever)
Or just multiply the existing rect dimensions by some scale factor for your collision rect. Don't do all of these calculations. Store a Rect for each collideable object and have a rect for the player.
tx1 = x*64 - tx2/2
ty1 = y*64 - ty2/2
px1, py1, px2, py2 =
PLAYER.get_rect()
px1 = player_x - px2/2
py1 = -player_y - py2/2
Then just test collision directly:
for t in tiles:
if player.rect.colliderect( t.rect ):
If the player is a sprite its rect moves around. Look at the example code in the doc.
https://www.pygame.org/docs/ref/sprite.html
Thanks for answering with clarity. The game I am making will be able to be changed with different textures with different sizes, thus I won't be able to know the sizes beforehand. I will check out the link on sprites, as that looks useful to me. Thanks again :D
– GeeTransit
Jan 1 at 0:06
I've reevaluated my game and how it works. I am going to have users specify the 'hitbox' for a specified texture. Unfortunately, I am going to leave this question unanswered as I want to have a backup for when the user does not specify a 'hitbox'.
– GeeTransit
Jan 1 at 0:20
Yeah if the user doesn't specify a hitbox then you would need to check for the transparent pixel and just do that once at the start and create the hitbox Rect or store a ratio like 0.8 and as you are doing multiply the Rect by that before testing collision.
– MarkReedZ
Jan 1 at 15:35
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53991988%2fhow-to-get-rect-of-a-pygame-surface-without-transparent-parts%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
If you want to ignore the transparent pixels in your collision detection, you're talking about pixel-perfect collision.
To do this in pygame, pygame offers the Mask class. You usually create your masks with pygame.mask.from_surface and use it together with pygame.sprite.spritecollide and pygame.sprite.collide_mask.
Maybe think about using pygame's Sprite class to make use of all the features it offers.
Even if you don't want to use pygame's build-in collision detection, you can take a look at the source to see how it works.
add a comment |
If you want to ignore the transparent pixels in your collision detection, you're talking about pixel-perfect collision.
To do this in pygame, pygame offers the Mask class. You usually create your masks with pygame.mask.from_surface and use it together with pygame.sprite.spritecollide and pygame.sprite.collide_mask.
Maybe think about using pygame's Sprite class to make use of all the features it offers.
Even if you don't want to use pygame's build-in collision detection, you can take a look at the source to see how it works.
add a comment |
If you want to ignore the transparent pixels in your collision detection, you're talking about pixel-perfect collision.
To do this in pygame, pygame offers the Mask class. You usually create your masks with pygame.mask.from_surface and use it together with pygame.sprite.spritecollide and pygame.sprite.collide_mask.
Maybe think about using pygame's Sprite class to make use of all the features it offers.
Even if you don't want to use pygame's build-in collision detection, you can take a look at the source to see how it works.
If you want to ignore the transparent pixels in your collision detection, you're talking about pixel-perfect collision.
To do this in pygame, pygame offers the Mask class. You usually create your masks with pygame.mask.from_surface and use it together with pygame.sprite.spritecollide and pygame.sprite.collide_mask.
Maybe think about using pygame's Sprite class to make use of all the features it offers.
Even if you don't want to use pygame's build-in collision detection, you can take a look at the source to see how it works.
answered Jan 2 at 8:49
slothsloth
74.1k14127169
74.1k14127169
add a comment |
add a comment |
You are making this too hard. You know the size of your objects. Add a smaller collision rect to each of your objects at creation time and use that for collision. Or use a circle if that is better for the object.
tile.crect = Rect(whatever)
Or just multiply the existing rect dimensions by some scale factor for your collision rect. Don't do all of these calculations. Store a Rect for each collideable object and have a rect for the player.
tx1 = x*64 - tx2/2
ty1 = y*64 - ty2/2
px1, py1, px2, py2 =
PLAYER.get_rect()
px1 = player_x - px2/2
py1 = -player_y - py2/2
Then just test collision directly:
for t in tiles:
if player.rect.colliderect( t.rect ):
If the player is a sprite its rect moves around. Look at the example code in the doc.
https://www.pygame.org/docs/ref/sprite.html
Thanks for answering with clarity. The game I am making will be able to be changed with different textures with different sizes, thus I won't be able to know the sizes beforehand. I will check out the link on sprites, as that looks useful to me. Thanks again :D
– GeeTransit
Jan 1 at 0:06
I've reevaluated my game and how it works. I am going to have users specify the 'hitbox' for a specified texture. Unfortunately, I am going to leave this question unanswered as I want to have a backup for when the user does not specify a 'hitbox'.
– GeeTransit
Jan 1 at 0:20
Yeah if the user doesn't specify a hitbox then you would need to check for the transparent pixel and just do that once at the start and create the hitbox Rect or store a ratio like 0.8 and as you are doing multiply the Rect by that before testing collision.
– MarkReedZ
Jan 1 at 15:35
add a comment |
You are making this too hard. You know the size of your objects. Add a smaller collision rect to each of your objects at creation time and use that for collision. Or use a circle if that is better for the object.
tile.crect = Rect(whatever)
Or just multiply the existing rect dimensions by some scale factor for your collision rect. Don't do all of these calculations. Store a Rect for each collideable object and have a rect for the player.
tx1 = x*64 - tx2/2
ty1 = y*64 - ty2/2
px1, py1, px2, py2 =
PLAYER.get_rect()
px1 = player_x - px2/2
py1 = -player_y - py2/2
Then just test collision directly:
for t in tiles:
if player.rect.colliderect( t.rect ):
If the player is a sprite its rect moves around. Look at the example code in the doc.
https://www.pygame.org/docs/ref/sprite.html
Thanks for answering with clarity. The game I am making will be able to be changed with different textures with different sizes, thus I won't be able to know the sizes beforehand. I will check out the link on sprites, as that looks useful to me. Thanks again :D
– GeeTransit
Jan 1 at 0:06
I've reevaluated my game and how it works. I am going to have users specify the 'hitbox' for a specified texture. Unfortunately, I am going to leave this question unanswered as I want to have a backup for when the user does not specify a 'hitbox'.
– GeeTransit
Jan 1 at 0:20
Yeah if the user doesn't specify a hitbox then you would need to check for the transparent pixel and just do that once at the start and create the hitbox Rect or store a ratio like 0.8 and as you are doing multiply the Rect by that before testing collision.
– MarkReedZ
Jan 1 at 15:35
add a comment |
You are making this too hard. You know the size of your objects. Add a smaller collision rect to each of your objects at creation time and use that for collision. Or use a circle if that is better for the object.
tile.crect = Rect(whatever)
Or just multiply the existing rect dimensions by some scale factor for your collision rect. Don't do all of these calculations. Store a Rect for each collideable object and have a rect for the player.
tx1 = x*64 - tx2/2
ty1 = y*64 - ty2/2
px1, py1, px2, py2 =
PLAYER.get_rect()
px1 = player_x - px2/2
py1 = -player_y - py2/2
Then just test collision directly:
for t in tiles:
if player.rect.colliderect( t.rect ):
If the player is a sprite its rect moves around. Look at the example code in the doc.
https://www.pygame.org/docs/ref/sprite.html
You are making this too hard. You know the size of your objects. Add a smaller collision rect to each of your objects at creation time and use that for collision. Or use a circle if that is better for the object.
tile.crect = Rect(whatever)
Or just multiply the existing rect dimensions by some scale factor for your collision rect. Don't do all of these calculations. Store a Rect for each collideable object and have a rect for the player.
tx1 = x*64 - tx2/2
ty1 = y*64 - ty2/2
px1, py1, px2, py2 =
PLAYER.get_rect()
px1 = player_x - px2/2
py1 = -player_y - py2/2
Then just test collision directly:
for t in tiles:
if player.rect.colliderect( t.rect ):
If the player is a sprite its rect moves around. Look at the example code in the doc.
https://www.pygame.org/docs/ref/sprite.html
answered Dec 31 '18 at 23:58
MarkReedZMarkReedZ
5967
5967
Thanks for answering with clarity. The game I am making will be able to be changed with different textures with different sizes, thus I won't be able to know the sizes beforehand. I will check out the link on sprites, as that looks useful to me. Thanks again :D
– GeeTransit
Jan 1 at 0:06
I've reevaluated my game and how it works. I am going to have users specify the 'hitbox' for a specified texture. Unfortunately, I am going to leave this question unanswered as I want to have a backup for when the user does not specify a 'hitbox'.
– GeeTransit
Jan 1 at 0:20
Yeah if the user doesn't specify a hitbox then you would need to check for the transparent pixel and just do that once at the start and create the hitbox Rect or store a ratio like 0.8 and as you are doing multiply the Rect by that before testing collision.
– MarkReedZ
Jan 1 at 15:35
add a comment |
Thanks for answering with clarity. The game I am making will be able to be changed with different textures with different sizes, thus I won't be able to know the sizes beforehand. I will check out the link on sprites, as that looks useful to me. Thanks again :D
– GeeTransit
Jan 1 at 0:06
I've reevaluated my game and how it works. I am going to have users specify the 'hitbox' for a specified texture. Unfortunately, I am going to leave this question unanswered as I want to have a backup for when the user does not specify a 'hitbox'.
– GeeTransit
Jan 1 at 0:20
Yeah if the user doesn't specify a hitbox then you would need to check for the transparent pixel and just do that once at the start and create the hitbox Rect or store a ratio like 0.8 and as you are doing multiply the Rect by that before testing collision.
– MarkReedZ
Jan 1 at 15:35
Thanks for answering with clarity. The game I am making will be able to be changed with different textures with different sizes, thus I won't be able to know the sizes beforehand. I will check out the link on sprites, as that looks useful to me. Thanks again :D
– GeeTransit
Jan 1 at 0:06
Thanks for answering with clarity. The game I am making will be able to be changed with different textures with different sizes, thus I won't be able to know the sizes beforehand. I will check out the link on sprites, as that looks useful to me. Thanks again :D
– GeeTransit
Jan 1 at 0:06
I've reevaluated my game and how it works. I am going to have users specify the 'hitbox' for a specified texture. Unfortunately, I am going to leave this question unanswered as I want to have a backup for when the user does not specify a 'hitbox'.
– GeeTransit
Jan 1 at 0:20
I've reevaluated my game and how it works. I am going to have users specify the 'hitbox' for a specified texture. Unfortunately, I am going to leave this question unanswered as I want to have a backup for when the user does not specify a 'hitbox'.
– GeeTransit
Jan 1 at 0:20
Yeah if the user doesn't specify a hitbox then you would need to check for the transparent pixel and just do that once at the start and create the hitbox Rect or store a ratio like 0.8 and as you are doing multiply the Rect by that before testing collision.
– MarkReedZ
Jan 1 at 15:35
Yeah if the user doesn't specify a hitbox then you would need to check for the transparent pixel and just do that once at the start and create the hitbox Rect or store a ratio like 0.8 and as you are doing multiply the Rect by that before testing collision.
– MarkReedZ
Jan 1 at 15:35
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53991988%2fhow-to-get-rect-of-a-pygame-surface-without-transparent-parts%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown