Pygame: Sprite placement and black rectangle border - pygame

Before I start, let me say that I'm a complete beginner at Pygame.
Here's my current program:
import pygame, sys, random
pygame.init()
white = ((255,255,255))
display_width = 800
display_height = 600
FPS = 15
gameDisplay = pygame.display.set_mode((display_width, display_height))
pygame.display.set_caption('Francis')
gameExit = False
lead_x = display_width/2
lead_y = display_height/2
lead_x_change = 0
lead_y_change = 0
clock = pygame.time.Clock()
while not gameExit:
for event in pygame.event.get():
if event.type== pygame.QUIT:
gameExit = True
francis = pygame.sprite.Sprite() #create sprite
francis.image = pygame.image.load("francis.png").convert() #load francis image
francis.rect = francis.image.get_rect() # use image extent values
francis.rect.center = [lead_x,lead_y]
gameDisplay.fill(white)
gameDisplay.blit(francis.image, francis.rect)
pygame.display.update()
clock.tick(FPS)
pygame.quit()
quit()
What I plan to do with this program is load in my sprite (francis) and use the arrow keys to move him across the screen. I plan to create that motion by having each arrow key pressed add or subtract 10 pixels from lead_x, which should be the sprite's x location. I'm not sure whether the code I used to load in the sprite is correct. I used "francis.rect.center" then gave the coordinates to that. Is there a better way to load and position a sprite?
Also, my sprite has a black rectangle around it whenever I load it. The sprite itself is a 30x70 picture. Where there is not a pixel of the actual person, I just have transparency. The transparency works fine, but whenever I load in the image, there's a black rectangle around the border of the sprite. I have a feeling this has to do with the way I loaded in the sprite, but I'd appreciate if you'd let me know. (I've tried converting it to png, bmp, and jpg. png and bmp both have black borders, and jpg has black background instead of transparency)
Any and all help is appreciated!

When you do your image load with
francis.image = pygame.image.load("francis.png").convert() #load francis image
you should do
francis.image = pygame.image.load("francis.png").convert_alpha() #load francis image
as png images have an alpha channel which is the transparent part of the image. If you don't know what this means load your image into an image editor and remove the part you do not need by selecting the and deleting them. Now these parts will contain no colour information and therefor will be the alpha channel for the image.
You can also set the colour key of the image by
francis.image.set_colorkey(0, RLEACCEL) # the colour key is set to 0
A key colour is also transparent. (That's how they shoot movies like spiderman, fantastic four etc. :-))
read this too
https://www.pygame.org/docs/ref/surface.html#pygame.Surface.set_alpha.
hope this helps.

Regarding how you position sprites, I believe the norm is to go by the top-left, but I don't think it matters much.
Try opening the picture in paint and saving it as a gif. Note of course that changing the file extension doesn't make a difference by renaming it, it is actually still the same file type. So to change a file type, you have to use the "save as" option and select a file type. Try using a gif or a png using this method assuming you haven't so far.

francis.rect.center = [lead_x,lead_y]
You set it as a list. I'm pretty sure it's meant to be a tuple i.e.
francis.rect.center = (lead_x,lead_y)
What does the ".convert" part do in "francis.image = pygame.image.load("francis.png").convert()"
I'm pretty sure it's not meant to be there, try removing it unless you specifically know you need it.
You forgot a crucial line in your code. On the end of the mainloop you should be saying the following line;
pygame.display.flip()
This has something to do with how it loads the pixels from top to bottom or something, I honestly don't know, but I'm pretty sure you need it otherwise the program wont work. I think it replaces pygame.display.update()

Related

PyGame Moving Animation and issue with background

here is my code:
import pygame
import sys
pygame.init()
FPS=30
clock=pygame.time.Clock()
white=(255,255,255) #background
screen=pygame.display.set_mode((480,320)) #screen size
pygame.display.set_caption("Zombie Game!")
mainsheet=pygame.image.load("C:\Python34\MyMan.png") #load image
sheet_size=mainsheet.get_size() #get size of img
steps_right=8 #first 8 pictures is moving to the right
jump=16 #next 8 (actually 5) is jumping
steps_left=24 #next 8 is moving to the left
cell_width=int(sheet_size[0]/8) #width of the one animation
cell_height=int(sheet_size[1]/4) #height of the one animation
cell_list=[]
for y in range(0,sheet_size[1],int(cell_height)): #looping through image
for x in range(0,sheet_size[0],int(cell_width)):
surface=pygame.Surface((cell_width,cell_height))
surface.blit(mainsheet,(0,0),(x,y,cell_width,cell_height))
cell_list.append(surface) #adding images to list
cell_position=0
running=True
pygame.key.set_repeat(50, 50) #if they hold the key
while running:
for event in pygame.event.get():
if event.type==pygame.QUIT:
pygame.quit()
sys.exit()
if event.type==pygame.KEYDOWN:
if event.key==pygame.K_RIGHT: #if to the right..
if cell_position <steps_right-1:
cell_position+=1
else:
cell_position=0
if event.key==pygame.K_LEFT:
if cell_position<steps_left-1 and cell_position>jump:
cell_position+=1
else:
cell_position=jump+1
if event.key==pygame.K_UP:
if cell_position<12 and cell_position>7:
cell_position+=1
else:
cell_position=8
screen.fill(white)
screen.blit(cell_list[cell_position],(100,10))
clock.tick(FPS)
pygame.display.update()
I know that maybe it isn't the best way to do it but it's my first try. But there are 2 problems(at least): 1)"Character" is moving(animated) but of course he doesn't move and I dont have any idea how to do that ,if it was only simple rectangle then I would,but this is a little bit complicated ..and 2) when I try to change the background to white instead of black,my character is in the small black square but background is white..thanks for help!!!! :-))
Notes:
"C:\Python34\MyMan.png": please start this with r"" or use double slashes. Otherwise, if you put this in a directory starting with n or something, things will break.
Background color is caused (presumably) by using a non-transparent image. png supports transparency. I think there might be a flag to send to Pygame to mark it as transparent, but I don't remember what it is.
For movement, look at the line screen.blit(cell_list[cell_position],(100,10)). That's an xy coordinate pair; change those from constants to variables, and change them in the event loop.

as3 MovieClip masking not working

I'm having difficulties trying to add some masks
mc1.mask = randMc;
Where mc1 = loaded MovieClip, and randMc is a pic imported to flash and converted as MovieClip. This is a very big game code I have there so I thought the Indexes might be the problem so I added this :
setChildIndex(randMc, (getChildIndex(mc1)-1));
But it didn't work meaning the movieclip stays the same, it won't mask with randMc...
Any suggestions?
Note: I also have used scaleX/Y on mc1
it seems that .png files are a mask including transparent pixels, so it's a square mask.. anyway I fixed it with
mc1.cacheAsBitmap = true;
randMc.cacheAsBitmap = true;
This way it the empty pixels won't "count" and the mask will be just like the imported .png on stage

Flash color transform

I'm having difficulty with transforming colour in Flash. It should be easy I think, but for some reason my code isn't working as expected.
I have a bitmap graphic consisting of a colour spectrum from red to yellow to green (you know, like you see in an audio level meter).
I simply want to sample a colour from that bitmap and then tint a movie clip on stage that sampled colour. (the effect I'll be going for is coloured progress - the closer you get to 100% green is displayed, the closer you are to 0% it's red - I haven't implemented that part yet, but I'm not worried about that).
Anyhow, I sample the colour just fine, and tint my clip, but no matter what I tint the clip it comes up a different colour than what I've sampled (the trace is a different colour than what I see on the clip). I can't see where I'm going wrong - I'm hoping it's a stupid mistake and someone can spot it easily.
import flash.display.BitmapData;
var bmd:BitmapData = new BitmapData(mc_colourbar.width, mc_colourbar.height);
bmd.draw(mc_colourbar);
var pixelvalue:uint = bmd.getPixel(0, 1);
trace(pixelvalue.toString(16));
var colourtransform:ColorTransform = mc_box.transform.colorTransform;
colourtransform.color = uint("0xff" + pixelvalue);
mc_box.transform.colorTransform = colourtransform ;
mc_box is the clip on stage I'm trying to tint - it's simply a white square.
Any help is appreciated, thanks in advance!
ColorTransform.color expects an RGB value, and it appears as though you're attempting to give it an ARGB value*.
Change the line:
colourtransform.color = uint("0xff" + pixelvalue);
to just:
colourtransform.color = pixelvalue;
and your code should work as expected.
*Though I don't think the way you're trying to do it here is correct.

Flash, AS3: Drawn objects are not the same

I'm playing with Open Flash Chart. Take a look at this chart:
http://teethgrinder.co.uk/open-flash-chart-2/line-solid-dot.php
As you can see, the rounded dot points look ugly. Some of them are more rounded, some of them less, they don't look the same, as they should. I don't know AS3 and have no idea what is the case. I checked the source code:
this.graphics.lineStyle( 0, 0, 0 );
this.graphics.beginFill( colour, 1 );
this.graphics.drawCircle( 0, 0, style.get('dot-size') );
this.graphics.endFill();
I tried to change the size or draw rectangles instead, but they still don't look the same. I guess the problem is somewhere else...
EDIT: I also noticed, that other elements also looks a little bit different (and they shouldn't) - for example axis ticks. My guess is that it is the quality problem. But when I right-click on the flash object, there is an option "quality" and the "high" is set (there is also a "medium" and a "low" to choose). Can I increase the quality level somewhere else?
From hollow dots, I came to realize there is something around each dot which separated each dot from the connecting lines & also produced blurry hollow dots.
Setting the attribute "halo_size" to 0 helped in this case.
I noticed the same gap in your sold dots examples as well. Maybe that's the problem.
To set stage quality, simply use:
stage.quality = "low";
stage.quality = "medium";
stage.quality = "high";
You may set it in the main class itself which happens to be the document class for this project.
I noticed that if the chart size is 400 x 400 these inconsistencies cease to exist. So the problem we see is a scaling problem & not at the place we think.
Besides, Setting line style allows a proper border around the circle. This will at least appear better.
this.graphics.lineStyle(1, colour, 1);
this.graphics.beginFill( colour, 1 );
this.graphics.drawCircle( 0, 0, style.get('dot-size') );
this.graphics.endFill();

Pygame how to change size of a surface?

How do you change the size of a surface in pygame that has an image (not scaling). When I load an image in pygame the surface becomes the size of the image. I need to change the size of the surface to be the size of a frame (sprite sheet).
Here is code I used to solve issue (thanks to Chris Dennett):
self.surface = pygame.Surface((20, 20))
self.surface.blit(pygame.image.load(imageName).convert_alpha(), (0,0), (0, 0, frameWidth, frameHeight))
For sprite sheets, you have 2 good options.
1) Load spritesheet as one Surface.
When blitting, use the source rect argument. This will blit just one frame, from the sheet.
2) Use subsurfaces.
Load spritesheet as one Surface.
Load a subsurface, of each frame you want : http://www.pygame.org/docs/ref/surface.html#Surface.subsurface
As far as you are concerned, the subsurface is a 'new' surface, with the width and height of the cell. But, it's not duplicate memory. It's linked.
From the docs:
Returns a new Surface that shares its pixels with its new parent. The
new Surface is considered a child of the original. Modifications to
either Surface pixels will effect each other. Surface information like
clipping area and color keys are unique to each Surface.
Create a new surface, passing in the desired width and height as arguments (i.e., how big the sprite is). Then use newsurf.blit(spritesheet, (0, 0), (posX, posY, newsurf.getWidth(), newsurf.getHeight())). Should work. Then you can use newsurf as your sprite. posX and posY should be the x and y you want to blit from in your sprite sheet respectively.