Pygame image screen fill - python

I have a pygame program that is meant to fill the pygame window with Grass.png:
import pygame, sys
from pygame.locals import *
pygame.init()
screen = pygame.display.set_mode([600, 500])
def DrawBackground(background, xpos, ypos):
screen.blit(background, [xpos, ypos])
background = pygame.image.load('Grass.png')
xpos = 0
ypos = 0
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
while ypos >= -500:
while xpos <= 600:
DrawBackground(background, xpos, ypos)
xpos += 100
ypos -= 100
pygame.display.flip()
Only problem is, it only fills the first 100 pixel row with the image. What is wrong with the code? Thanks.

You're much better off using for loops rather than while loops to do that.
for y in range(5):
for x in range(6):
DrawBackground(background, x*100, y*100)
Makes the code much more readable and easier to debug.
But in answer to your question, like frr171 said, the origin point (0, 0) is in the top left corner of the screen. As you go right, the x axis increases and as you go down the y axis increases.

The y-axis is positive as you go down the screen - so while your first row is at a y-position of 0, the next row will be at a y-position of 100. Basically, you should be adding to the y-coordinate, not subtracting.

Related

Making my own grid in python

I'm new one in coding, so I expect that this is easy one, but I still can't figure this out.
So I'm trying to make a program that animates a diagram, but the problem is when am making animation with equation (0,0) obviously in upper left corner.
I need to make a grid that will represent this, so I cant input my equation and get right animation depends on this grid's numbers Grid here
UPD:
Sorry for being less specific than I should.
The goal is to make a program that animates HR diagram, outputs luminosity and temperature after you inputs solar mass.
I didn't input equation so far because I'm trying to figure out how pygame animation works.
What I got so far trying to animate diagonal line:
import pygame
from pygame.locals import *
pygame.init()
width = 600
height = 600
screen = pygame.display.set_mode((width, height))
background = pygame.image.load("background.png")
point = pygame.image.load("point.png")
clock = pygame.time.Clock()
speed = 100
x = 0
y = 0
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
quit()
screen.blit(background, (0,0))
screen.blit(point, (x,y),)
milli = clock.tick()
second = milli/1000.
dm=second * speed
x += dm
y = x
print (x, y)
if x > 600 or y > 600:
x = 0
y = 0
pygame.display.update()
So I need to make axis like in diagram, so I can just type down the equation and make correct animation and correct outputs
Use a 2 dimensional array to represent a grid structure in python.
w, h = 10000, 50000;
grid = [[0 for x in range(w)] for y in range(h)]

Why balls cannot move in my code in Pygame when I code 'Pong'? Can Someone help me to check my code?

I am a beginner in Pygame. I have coded a function for moving two balls in different direction and I follow the instructions coding it but it seems to be not working. I can draw two balls in screen but they will not move. I fixed it for almost 1 hour but no idea why balls aren't moving.
So, Can someone helps me check my code and just give me some hints. I will really appreciate anyone who helps me!
My code shows below
import pygame,sys,time
from pygame.locals import *
# User define function
def ball_move(Surface,white,pos,rad,speed):
size=Surface.get_size()
for item in [0,1]:
pos[item]=pos[item]+speed[item]
if pos[item]<rad:
speed[item]=-speed[item]
if pos[item]+rad>size[item]:
speed[item]=-speed[item]
# Open a brand-new window
pygame.init()
Screen_size = (500,400)
Title = ('Pong')
Frame_Delay = 0.01
Surface= pygame.display.set_mode(Screen_size,0,0)
pygame.display.set_caption(Title)
# Set up white color for drawing balls
white=pygame.Color('white')
# Now, we start to draw two balls
pos1=(100,200)
pos2=(400,200)
rad=10
ball1=pygame.draw.circle(Surface,white,pos1,rad,0)
ball2=pygame.draw.circle(Surface,white,pos2,rad,0)
pygame.display.update()
# Now, define speed
speed1=(2,-2)
speed2=(-2,2)
# Now, we define a loop
while ball1:
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
# Now, we move the ball
ball1move=ball_move(Surface,white,pos1,rad,speed1)
ball2move=ball_move(Surface,white,pos2,rad,speed2)
pygame.draw.circle(Surface,white,pos1,rad,0,0)
pygame.draw.circle(Surface,white,pos2,rad,0,0)
surface.fill(pygame.Color('black'))
Part of saulspatz answer is correct, part is incorrect. You don't have to use sprites if you dont want to. pygame.draw is not pretty but perfectly usable. The main problem does seem to be your understanding of what to do in your event loop. All this should go in it:
while running:
# Handdle your events
# update your state
# draw to your display
pygame.display.update()
Also I notice in your unreachable code after the loop you are filling after your draws. Remember whether you fill, blit, or draw the latest thing goes over the rest. So for your example:
import pygame ,sys, time
from pygame.locals import *
# User define function
def ball_move(surface, pos, rad, speed):
def _add(l_pos, l_speed, l_size):
l_pos += l_speed
if l_pos <= rad or l_pos >= l_size - rad:
l_speed = -l_speed
return l_pos, l_speed
size = surface.get_size()
pos_x, speed_x = _add(pos[0], speed[0], size[0])
pos_y, speed_y = _add(pos[1], speed[1], size[1])
return (pos_x, pos_y), (speed_x, speed_y)
pygame.init()
screen_size = (500, 400)
screen = pygame.display.set_mode(screen_size)
pygame.display.set_caption('Pong')
running = True
pos1 = (100, 200)
pos2 = (400, 200)
speed1 = (2, -2)
speed2 = (-2, 2)
rad = 10
while running:
# Handdle your events
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
# update your state
pos1, speed1 = ball_move(screen, pos1, rad, speed1)
pos2, speed2 = ball_move(screen, pos2, rad, speed2)
# draw to your display
screen.fill(pygame.Color('black'))
pygame.draw.circle(screen, pygame.Color('white'), pos1, rad)
pygame.draw.circle(screen, pygame.Color('white'), pos2, rad)
pygame.display.update()
There are a lot of problems with your code. The most basic is that you haven't figured out how event-driven programming works. You need to put the code that moves the balls inside your loop.
Another problem is that I don't think you want to use the pygame.draw module. It's been a long time since I wrote any pygame scripts, but as I remember, this module is useful for drawing fixed objects, like the background. A quick look at the docs seems to confirm this.
For moving objects, I think you need to look at the pygame.sprite module. Even if you got this code to work, it wouldn't move the balls. It would just draw a new ball at another position. So you would have first two balls, then four, then eight, ... . Sprites actually move. Not only is the object drawn at the new position, but it's erased at the old position. Your code don't address erasure at all.
Hope this helps.

How do I keep an image centered when rotating with Pygame and Pyganim [duplicate]

This question already has answers here:
How do I rotate an image around its center using Pygame?
(6 answers)
How to rotate an image(player) to the mouse direction?
(2 answers)
Closed 2 years ago.
Python Version: 3.4
I've recently started using Pygame and I have then started to use the module pyganim to handle animation of sprites.
http://inventwithpython.com/pyganim/
I have run into an issue when I try to rotate the animation. It has a strange effect, such as shown in this example http://i.imgur.com/g6Os9.gif, from this issue:
Weird shifting when using pygame.transform.rotate()
I have tried multiple fixes, such as finding the center of the image etc but as it is a pyganim object, I am blitting to my surface like: (where screen is my surface)
player.blit(screen, playerpos)
Changing the center of it seems to have no effect.
I have also tried swapping the image I'm using for a full black square, and I've still had no luck in debugging it.
I assume it is due to the fact I am blitting the pyganim object to my surface, and that I need to maybe blit it to another surface and rotate that? <- speculation!
The issue I believe lies here,
# Set player position and rotation
position = pygame.mouse.get_pos()
angle = math.atan2(position[1]-(playerpos[1]),position[0]-(playerpos[0]))
player.clearTransforms()
player.rotate((360-angle*57.29)-90)
playerpos1 = (playerpos[0]-(player.getRect().width/2), playerpos[1]-(player.getRect().height/2))
player.blit(screen, playerpos1)
As the actual rect of the Pyganim object doesn't change, no matter what rotation is put against it (I have some on screen logging that I verified this with). I think the standard methods for correction are void.
If anyone with some experience using Pyganim could shed some light it would be awesome!
Here is the code in full...
# Import modules
import pygame
from pygame.locals import *
import pyganim
import math
# Initialise
pygame.init()
width, height = 640, 480
screen=pygame.display.set_mode((width, height))
keys = [False, False, False, False]
playerpos=[100,100]
# Load images
player = pyganim.PygAnimation([('resources/images/tdt/p1.png', 0.3), ('resources/images/tdt/p2.png', 0.3), ('resources/images/tdt/p3.png', 0.3), ('resources/images/tdt/p2.png', 0.3)])
player.play()
grass = pygame.image.load("resources/images/tdt/bg.png")
grasswidth = grass.get_width()
grassheight = grass.get_height()
myfont = pygame.font.SysFont("monospace", 20)
# loop
while 1:
# clear the screen before re-drawing
screen.fill(0)
# draw the screen elements
for x in range(width//grasswidth+1):
for y in range(height//grassheight+1):
screen.blit(grass,(x*100,y*100))
# Set player position and rotation
position = pygame.mouse.get_pos()
angle = math.atan2(position[1]-(playerpos[1]),position[0]-(playerpos[0]))
player.clearTransforms()
player.rotate((360-angle*57.29)-90)
playerpos1 = (playerpos[0]-(player.getRect().width/2), playerpos[1]-(player.getRect().height/2))
player.blit(screen, playerpos1)
# render text
label = myfont.render("X pos: "+str(playerpos[0])+"| Y pos: "+str(playerpos[1]), 1, (255,255,0))
screen.blit(label, (20, 20))
# Update the screen
pygame.display.flip()
# loop through the events
for event in pygame.event.get():
#check if the event is the X button
if event.type==pygame.QUIT:
##if it is, quit the game
pygame.quit()
exit(0)
if event.type == pygame.KEYDOWN:
if event.key==K_w:
keys[0]=True
elif event.key==K_a:
keys[1]=True
elif event.key==K_s:
keys[2]=True
elif event.key==K_d:
keys[3]=True
if event.type == pygame.KEYUP:
if event.key==pygame.K_w:
keys[0]=False
elif event.key==pygame.K_a:
keys[1]=False
elif event.key==pygame.K_s:
keys[2]=False
elif event.key==pygame.K_d:
keys[3]=False
# Move player
if keys[0]: # W
playerpos[1]-=2
elif keys[2]: # S
playerpos[1]+=2
if keys[1]: # A
playerpos[0]-=2
elif keys[3]: # D
playerpos[0]+=2
OK
I have made some progress on this... The code I have written right now is basic and works for the shape in question, as it is easily divisible by 4! :D However, I will re-write it to be able to handle all eventualities, however, it may be that the boxes have to be square: here is the code now:
playerpos1 = rMoveAmount(playerpos,angle, 44)
player.blit(screen, playerpos1)
With rMoveAmount being:
def rMoveAmount(position, degrees, picsize):
#MOVE A BOX DEPENDING ON THE AMOUNT ROTATED
degTest = int(((360-degrees*57.29)-180)%90)
#Has to be split up into two sections, before the half 90 degree rotation
if degTest < 45:
t = int((((360-angle*57.29)-180)%45)//4)
nPos = (position[0] - t , position[1] - t )
#And after
if degTest > 44:
t = int((((360-angle*57.29)-180)%45)//4)
nPos = (position[0] + t - 11, position[1] + t - 11)
return nPos
So
It takes 1/4 of the angle (which would be between 0 - 11)
Then it uses that as the offset (as my pic is 44px and will always need to be shifted by 1/4)
As you can see, the pic size isn't currently used. And I think it was just luck that my picture size was 44 and fit so snugly into the middle of a half 90 degree rotation, and could also be divided by 11. However, I will work on being able to use this with more flexible sizes and update.
Edit 3:
Ok, this one should now work for all square images, it will also center the cursor correctly. I will just show the changes made, not the whole code again:
# 3 - Load images
player = pyganim.PygAnimation([('resources/images/tdt/p1.png', 0.3), ('resources/images/tdt/p2.png', 0.3), ('resources/images/tdt/p3.png', 0.3), ('resources/images/tdt/p2.png', 0.3)])
player.play()
playerSize = player.getRect().width
# 6.1 - Set player position and rotation
position = pygame.mouse.get_pos()
angle = math.atan2(position[1]-(playerpos[1]+(playerSize/2)),position[0]-(playerpos[0]+(playerSize/2)))
player.clearTransforms()
player.rotate((360-angle*57.29)-90)
playerpos1 = rMoveAmount(playerpos,angle, playerSize)
player.blit(screen, playerpos1)
And the method rMoveAmount changes:
def rMoveAmount(position, degrees, picsize):
#MOVE A BOX DEPENDING ON THE AMOUNT ROTATED
degTest = int(((360-degrees*57.29)-180)%90)
quartsize = picsize / 4
#Has to be split up into two sections, before the half 90 degree rotation
if degTest < 45:
#t = int((((360-angle*57.29)-180)%45)//4)
jump = (quartsize / 44)
nPos = (position[0] - (jump * degTest) , position[1] - (jump * degTest) )
#And after
if degTest > 44:
jump = (quartsize / 44)
nPos = (position[0] + (jump * degTest) - (picsize/2) , position[1] + (jump * degTest) - (picsize/2))
return nPos
Will now work with any square images.

A simple Python app is behaving erratically for no reason?

I've been going through some Python tutorials using Python 2.7 and Pygame and I decided to challenge myself. The tutorial showed how to make a ball move (right) across the screen, then pop back to the other (left) side of the screen at a specific speed. I wanted to make the ball bounce back and forth from left to right, so I wrote this:
bif = "bg.jpg"
mif = "ball1.png"
import pygame, sys
from pygame import *
from pygame.locals import *
pygame.init()
screen = pygame.display.set_mode((816,460),0,32)
background = pygame.image.load(bif).convert()
ball = pygame.image.load(mif).convert_alpha()
x = 0
clock = pygame.time.Clock()
while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
screen.blit(background, (0,0))
screen.blit(ball, (x, 160))
speed = 500
milli = clock.tick() #A tick is 1 millisecond
seconds = milli/1000.000000
dm = seconds * speed
if x == 0:
a = dm
elif x == 770:
a = -dm
x += a
pygame.display.update()
"bg.jpg" is a jpeg image that is 816 x 460 pixels and "bif.png" is a png image of a ball with a 50 pixel radius. Instead of moving back and forth at 500 pixels per second, the ball moves at a random speed to the right, then bounces off of the right side of the screen at a random speed to the left, and repeats this a random number of times. Then the ball keeps going in one direction and doesn't come back. I can't figure out why it's doing this. It behaves differently every time I run it. If anybody can figure out why, I'd be really thankful.
tick(), without arguments returns time which passed since last call. In your use it depends on rendering speed which will always be different that is why you get different speed each time.
Replace from speed = 500 to the end with:
speed = 1
if x == 0 or x == 770:
speed = -speed
x += speed
pygame.display.update()
clock.tick(60)

Python:Pygame: How to animate a ball to move in a sin() like pattern?

How would you make a ball move in a repetitive wavey pattern just like a sin() graph does?
You can use a counter, pygame's Clock, or just pygame.time.get_ticks to figure out the time. Here's some sample code to get you started.
import math
import pygame
pygame.init()
screen = pygame.display.set_mode((400,400))
while True:
t = pygame.time.get_ticks() / 2 % 400 # scale and loop time
x = t
y = math.sin(t/50.0) * 100 + 200 # scale sine wave
y = int(y) # needs to be int
screen.fill((0,0,0))
pygame.draw.circle(screen, (255,255,255), (x, y), 40)
pygame.display.flip()

Categories

Resources