I have a pygame sprite animation where the position and shape of the sprite changes throughout a certain animation sequence (eg. - attack). How do I adjust the sprite's rect for collisions?
My Image: in one part of the animation, my sprite is at the center of a png image file (96x64 pixels). In another part of the animation, my sprite is near the right side of the png image file (96x64 pixels). In another part of the animation, the sprite changes shape (caused by sword movement). Etc.
Do I have to do some math and calculation to adjust the collision rect. of the sprite each frame of the animation or is there an easier method?
I am new to pygame so I'm not sure of all the different features and am not sure where to begin with creating the different rects. for each frame.
PS. I am using a ready-made sprite I found online - each frame is 96x64 pixels in dimension
Frame 1, 11, 22:
It's been a while since I've worked with Pygame but I believe you can use a pygame.mask object. A mask is basically an object with the precise outline of the foreground of an image. It takes considerably more computation power but if you only create a mask for the one main character then it should be okay.
You can create a mask from the image:
myMask = pygame.mask(myImage)
Then you can either use its rect or create a new surface to use:
myRect = myMask.get_rect() # Returns the pygame.Rect object that conatains mask, or:
mySurface - myMask.to_surface() # Returns a pygame.Surface object of the mask
Hope this helps, my info is from:
https://www.pygame.org/docs/ref/mask.html
Related
In a webpage created with node/webpack, vega-lite, and vegaEmbed, I have a layer with rect marks with short annotations inside them using text marks. I'd like to clip the text to its surrounding rect but haven't figured out a way to do this and hope someone can point me in the right direction.
I realize text has a limit property in pixel units. If I could determine the pixel units of my rect marks (I don't know how to do this), using limit seems like a reasonable approach.
Also, if I knew the pixel extents of my rectangle, I can then write code to align the text within the rect which would be desirable. Currently I just use the same x as the rect, with a dx offset.
I've read about background for text which is a similar problem, but not the same.
I developed a small tkinter GUI to display (and export) images stored in a proprietary format. I managed to load the data into a 3D numpy uint8 array. I want to display one slice of that 3D array in a tkinter.canvas. To do so I used ImageTk.PhotoImage.
Underneath the Canvas I inserted a tk.Scrollbar. My goal is to use that scrollbar to let the user actively "scroll" though the 3D Array. Basically when the slider is moved or any of the arrows is pressed the slice corresponding to the slider position should be displayed in the canvas.
Right now I have the issue that I don't understand how to set the range of the scrollbar to my z-Dimension and then how to bind the scrollbar events to the movement or arrow actions to update the canvas.
Right now I don't have example code since this is a more conceptual problem.
Could you point me in the right direction how to solve this?
Best TMC
edit: Photo
Tkinter Gui with Canvas and Scrollbar
The solution is to use tkinter.Scale instead of tkinter.Scrollbar . As a side note, the command within:
scale = tk.Scale(yourTkFrame, from_=min, to=max, orient='horizontal', command=doSomething)
passes two values to the function doSomething.
Using the Scale allows to use the scale.get() method to retrieve the position between min and max values. Those can then be used to set the image corresponding to the selected position on the slide.
To set this up, I used svgwrite library to create a sample SVG image (20 squares of length 100 at random locations on a display size of length 400)
import svgwrite
import random
random.seed(42)
dwg = svgwrite.Drawing('x.svg', size=(400,400))
dwg.add(dwg.rect(insert=(0,0), size=('100%', '100%'), fill='white')) # White background
for i in range(20):
coordinates = (random.randint(0,399), random.randint(0,399))
color = (random.randint(0,255), random.randint(0,255), random.randint(0,255))
dwg.add(dwg.rect(coordinates, (100, 100),
stroke='black',
fill=svgwrite.rgb(*color),
stroke_width=1)
)
dwg.save()
I then wrote a sample pygame program to generate a PNG image of the same sample. (A seed has been used to generate the same sequence of squares.)
import pygame
import random
random.seed(42)
display = pygame.display.set_mode((400,400))
display.fill((255,255,255)) # White background
for i in range(20):
coordinates = (random.randint(0,399), random.randint(0,399))
color = (random.randint(0,255), random.randint(0,255), random.randint(0,255))
pygame.draw.rect(display, color, coordinates+(100,100), 0)
pygame.draw.rect(display, (0,0,0), coordinates+(100,100), 1) #For black border
pygame.image.save(display, "x.png")
These are the images that I got (SVG's can't be uploaded to SO, so I have provided a screenshot. Nevertheless, the programs above can be run to output the same).
My question is, why is the PNG (on the left) richer and sharper than the corresponding SVG image? The SVG looks blurred and bland, comparatively.
EDIT: One can notice the fine white line between the first two squares at the top-left corner. It's not very clear in the SVG.
Two things I think may impact:
You are using an image viewer, which could distort the vectorial SVG image. I think all of the vector images viewers get the actual screen size, then export the vectorial image into a matrix image sized in function of the size of the screen you have. Then they display the matrix image. If they render the image with softened sharpness, or if they have a problem by getting the size of your screen, the image may be blurred.
To make the PNG image, you use pygame. But you are using another module to make the SVG image. This module may function differently, and also exports the image with another quality than if you were exporting it with pygame.
For me personally the SVG image appears blurred with Gimp, for example, but not with another SVG viewer.
So I think the problem comes from your image viewer.
I use Imagedraw module to draw rectangle, which is very simple:
blank=Image.new("RGB",[pixelx,pixely],"black:")
draw=ImageDraw.Draw(blank)
draw.rectangle(x1,y1,x2,y2,fill='white')
This gives me a straight line rectangle in white.
But can I change the roughness of edge of this rectangle?
I am trying to make the rectangle look more similar to practical image.
If I cannot achieve this by Imagedraw, what module can help me do that.
Thanks a lot!
It's difficult to know precisely what effect you are after.
I can tell you that Pillow has filters - https://pillow.readthedocs.io/en/5.2.x/reference/ImageFilter.html
from PIL import ImageFilter
im = im.filter(ImageFilter.BLUR)
Changing the angle of your rectangle - by selecting co-ordinates that are not a flat rectangle - would create pixelated edges.
Otherwise, I might suggest randomly changing individual pixels along the edges using https://pillow.readthedocs.io/en/5.2.x/reference/PixelAccess.html
from PIL import Image
px = im.load()
px[0, 0] = (0, 0, 0)
Although that could be slow. It depends on the size of your image and the need for speed.
I have an image of size 480x800 pixels and there is a icon on one corner which I need to place. What I want is that to ignore all touches on the transparent areas and detect only the area where the icon is.
I found a solution in SO to this problem but it just tells the code to be used. I need to know exactly where to put that code since I am a beginner and don't know much about cocos2d so I expect a step by step solution.
Cocos2d 2.0 - Ignoring touches to transparent areas of layers/sprites
Do not use glReadPixels because it affected by bugs in android drivers. You can translate CCTouch to CCPoint in image coordinates using convertTouchToNodeSpace, and read image pixel at given point.
Create CCImage from file that contains semi-transparent picture, and read one pixel at tap point; it should be {0,0,0,0} for transparent area.
Don't forget to check that tap is not outside picture, and create pixel index in CCImage::getData() array with formulae unsigned index = x * imageWidth + y.