how to change the batch object of a sprite in pyglet?
def createSprite(obj, batch, layer):
img = pyglet.resource.image(obj.path)
img.width = obj.w
img.height = obj.h
return pyglet.sprite.Sprite(img, x=obj.x, y=obj.y, batch=batch, group=layer)
Very ambiguous question... But, good theme.
In pyglet the sprite objects have a property called batch that can be changed in ejecution time. Is very simple, asuming that x is a object of the Sprite class, then:
x.batch = pyglet.graphics.Batch()
Related
I have created a pygame mask around the main sprite. My game consists of tiles with collisions rects. set up around them.
How can I check if the mask on my main sprite collides with a rect. of one of my tiles in my world without having to create more masks (as that is inefficient)? I know there are 'collide rect' and 'collide mask' functions in pygame. Is a collision function for a mask and a rect?
Is a collision function for a mask and a rect?
No, but you could write one yourself and use it as callback for the group collide functions:
def collide_mask_rect(left, right):
xoffset = right.rect[0] - left.rect[0]
yoffset = right.rect[1] - left.rect[1]
try:
leftmask = left.mask
except AttributeError:
leftmask = pygame.mask.Mask(left.size, True)
try:
rightmask = right.mask
except AttributeError:
rightmask = pygame.mask.Mask(right.size, True)
return leftmask.overlap(rightmask, (xoffset, yoffset))
The real perfomance issue with masks is creating them at runtime from a surface (like collide_mask does with from_surface, but creating filled masks shouldn't be that bad.
But if performance becomes an issue, consider either caching the masks, assigning them to the sprites or create them in the sprites in advance.
I'm trying to read a PDF and insert an image at bottom(Footer) of each page in PDF. I've tried with PyMuPDF library.
Problem: Whatever the Rect (height, width) I give, it doesn't appear in the bottom, image keeps appearing only on the top half of the page (PDF page).
My code:
from fitz import fitz, Rect
doc = fitz.open("test_pdf2.pdf")
def add_footer(pdf):
img = open("footer4.jpg", "rb").read()
rect = Rect(0, 0, 570, 1230)
for i in range(0, pdf.pageCount):
page = pdf[i]
if not page._isWrapped:
page._wrapContents()
page.insertImage(rect, stream=img)
add_footer(doc)
doc.save('test_pdf5.pdf')
Processed_image with footer image in the middle of the page:
https://i.stack.imgur.com/HK9mm.png
Footer image:
https://i.stack.imgur.com/FRQYE.jpg
Please help!
Please let me know if this can be achieved by using any other library.
Some pages internally change the standard PDF geometry (which uses the bottom-left page point as (0, 0)) to something else, and at the same time do not encapsulate this doing properly as they should.
If you suspect this, use PyMuPDF methods to encapsulate the current page /Contents before you insert your items (text, images, etc.).
The easiest way is Page._wrapContents() which is also the friendly way to keep incremental PDF saves small. The MuPDF provided Page.cleanContents() does this and a lot more cleaning stuff, but bloats the incremental save delta, if this is a concern.
After doing little trial and error I was able to figure out the problem. I was missing out on proper dimensions of Rect, I had to give 0.85*h in second parameter.
below is the code:
from fitz import fitz, Rect
doc = fitz.open("test_pdf2.pdf")
w = 595
h = 842
def add_footer(pdf):
img = open("footer4.jpg", "rb").read()
rect = fitz.Rect(0, 0.85*h, w, h)
for i in range(0, pdf.pageCount):
page = pdf[i]
if not page._isWrapped:
page._wrapContents()
page.insertImage(rect, stream=img)
add_footer(doc)
doc.save('test_pdf5.pdf')
use:
wrapContents – Page.wrap_contents()
https://pymupdf.readthedocs.io/en/latest/znames.html?highlight=wrapContents
from fitz import fitz, Rect
doc = fitz.open("example.pdf")
w = 250
h = 400
def add_footer(pdf):
img = open("firmaJG.png", "rb").read()
rect = fitz.Rect(0, 0.85*h, w, h)
for i in range(0, pdf.pageCount):
page = pdf[i]
if not page._isWrapped:
page.wrap_contents()
page.insertImage(rect, stream=img)
add_footer(doc)
doc.save('test_pdf5.pdf')
This is a simple example of how I draw a pixelated image in my game:
SCALE = 6
class MyApp(App):
def build(self):
parent = Widget()
texture = self.load_some_texture()
texture.min_filter = 'nearest'
texture.mag_filter = 'nearest'
with self.canvas:
PushMatrix()
Scale(SCALE)
self.pixelart = Rectangle(texture=texture, pos=(0, 0), size=(64, 64))
PopMatrix()
return parent
Is this the best and most efficient way to make a pixelated game in Kivy? If not, what is?
with self.canvas:
Scale(6)
self.pixelart = Rectangle(texture=texture, pos=(0, 0), size=(64, 64))
I think you're fighting the widget system a bit - instead of doing this, why not leave out the scale, set the Rectangle pos/size to the widget pos/size (and make a binding so that it follows the widget pos/size when they change), and then set the widget pos and size to change everything at once. This way the widget will work as expected, as everything tracks it. Or if you want the button to be a widget that behaves normally, you could put your pixel drawings in a different Widget that doesn't have any normal behaviour of its own.
For resetting scale (and other matrix instructions), you can put your scale changes between PushMatrix and PopMatrix canvas instructions.
This might be a very uninformed question.
I've been trying to figure out QGraphics*, and have run into a problem when trying to move an item (a pixmap) relative to or inside of the QGraphicsView.
class MainWindow(QMainWindow,myProgram.Ui_MainWindow):
def __init__(self):
super().__init__()
self.setupUi(self)
self.scene = QGraphicsScene()
self.graphicsView.setScene(self.scene)
pic = QPixmap('myPic.png')
self.scene.addPixmap(pic)
print(self.scene.items())
This is the relevant part of the program with an arbitrary PNG
My goal, for example, would be to move the trash-can to the left-most part of the QGraphicsView.
I tried appending this to the code above:
pics = self.scene.items()
for i in pics:
i.setPos(100,100)
However, it doesn't make a difference, and even if it did, it would be awkward to have to search for it with a "for in".
So my questions are:
How do I access a QPixmap item once I have added it to a QGraphicsView via a QGraphicsScene. (I believe The QPixmap is at this point a QGraphicsItem, or more precisely a QGraphicsPixmapItem.)
Once accessed, how do I move it, or change any of its other attributes.
Would be very grateful for help, or if anyone has any good links to tutorials relevant to the question. :)
The problem is that you need to set the size of your scene and then set positions of the items, check this example:
from PyQt4 import QtGui as gui
app = gui.QApplication([])
pm = gui.QPixmap("icon.png")
scene = gui.QGraphicsScene()
scene.setSceneRect(0, 0, 200, 100) #set the size of the scene
view = gui.QGraphicsView()
view.setScene(scene)
item1 = scene.addPixmap(pm) #you get a reference of the item just added
item1.setPos(0,100-item1.boundingRect().height()) #now sets the position
view.show()
app.exec_()
So I have this dial image I'm using for a PyQt widget. Right now, as you can see, the gradient indicator, the arc of green-yellow-red is static and is part of the image.
I want to create this dynamically, so that based on some ranges, the color can be determined. For example, instead of equal parts green and red, I might want about 60 degrees worth of it to be red and the rest green and yellow. For this, I shall specify some range (eg. 0-90 degrees worth should be green etc).
Any ideas on how I can draw such a CURVED color gradient?
To accomplish this, one way is to create a widget and do a custom paintEvent. You will build up this result with a couple elements:
Draw the static pixmap of the gauge background
Draw a pie shape with a gradient
Re-fill the center with the original image to cut it back out again
You will need to cache the pixmap once in the init so you don't keep creating it from disk. Then you can give the widget a method to set the value from 0.0 - 1.0.
class GaugeWidget(QtGui.QWidget):
def __init__(self, initialValue=0, *args, **kwargs):
super(GaugeWidget, self).__init__(*args, **kwargs)
self._bg = QtGui.QPixmap("bg.png")
self.setValue(initialValue)
def setValue(self, val):
val = float(min(max(val, 0), 1))
self._value = -270 * val
self.update()
def paintEvent(self, event):
painter = QtGui.QPainter(self)
painter.setRenderHint(painter.Antialiasing)
rect = event.rect()
gauge_rect = QtCore.QRect(rect)
size = gauge_rect.size()
pos = gauge_rect.center()
gauge_rect.moveCenter( QtCore.QPoint(pos.x()-size.width(), pos.y()-size.height()) )
gauge_rect.setSize(size*.9)
gauge_rect.moveCenter(pos)
refill_rect = QtCore.QRect(gauge_rect)
size = refill_rect.size()
pos = refill_rect.center()
refill_rect.moveCenter( QtCore.QPoint(pos.x()-size.width(), pos.y()-size.height()) )
# smaller than .9 == thicker gauge
refill_rect.setSize(size*.9)
refill_rect.moveCenter(pos)
painter.setPen(QtCore.Qt.NoPen)
painter.drawPixmap(rect, self._bg)
painter.save()
grad = QtGui.QConicalGradient(QtCore.QPointF(gauge_rect.center()), 270.0)
grad.setColorAt(.75, QtCore.Qt.green)
grad.setColorAt(.5, QtCore.Qt.yellow)
grad.setColorAt(.25, QtCore.Qt.red)
painter.setBrush(grad)
painter.drawPie(gauge_rect, 225.0*16, self._value*16)
painter.restore()
painter.setBrush(QtGui.QBrush(self._bg.scaled(rect.size())))
painter.drawEllipse(refill_rect)
super(GaugeWidget,self).paintEvent(event)
You can expand on this widget even more by exposing a way to set the colors and also maybe even changing the start and end ranges. They would be attributes that the paintEvent would reference, just like the value attribute it is using now.
You can also adjust the color stop values to change the balance of the ranges.
Make sure to have the paintEvent do as little processing as possible.