Positioning a moving image/rect with Pygame - python

I would like to position my image and rect, but they are already moving back and forth. Can I still manually position their start point at this stage, when they are already on the move?
Currently the Image bounces back and forth on the screen. I would like to position the start point of this motion to an arbitrary point, say (0,100) of my window. Is there a way to set this positioning of my image and rect so that it can keep it's movement but just start from another point? Currently it's stuck on the top, I've tried a few things that didn't work:
self.image = pygame.image.load('picture.jpg')
self.rect = self.image.get_rect()
self.screen.fill(self.bg_color)
self.rect.move_ip(5,0) #only moving on the x axis
if self.rect.left < 0 or self.rect.right > self.width:
self.speed[0] = -self.speed[0]
self.screen.blit(self.image,self.rect)
pygame.display.flip()
Is there a way where I can set a starting position for my Surface object and rectangle?

Sure. Just do
self.rect.move_ip(0, 100)
to move to (0,100).
See the pygame.Rect docs for more.

Related

Rotating the player about the center point in pygame

I am making a game where there are two players and they can shoot each other. Their movement will be defined by a rotation around a fixed point, the point will be(600, 300), which is the center of our screen. The player will keep rotating around the point as long as they are pressing a certain button(which is keep providing force to our player) else they will fall(due to gravity). I think it would help to think of it as a ball attached to a point using a string. The string is attached as long as a button is pressed and gets unattached as soon as the button is released and the ball flies off. Here is my player class
class Player:
def __init__(self):
self.pos = [500, 200]
self.width = 30
self.height = 30
self.player = pygame.image.load("player.png").convert_alpha()
self.player = pygame.transform.scale(self.player, (self.width, self.height))
self.rect = self.player.get_rect()
self.rotated_player = None
self.anguler_vel = 0
self.Fg = 0.05
self.Fp = 0
self.arm_length = 0
Fp is the force perpendicular to the force of gravityFg. Fg is the force which is pulling it down on our player. Fp is defined by math.sin(theta) * Fg. I am keeping track of Fp because i want the player to keep moving in the direction of rotation after its unattatched from the string. arm_length is the length of the string.
I have a Point class, which is the point about which our player will rotate. Here's the point class.
class Point:
def __init__(self,x, y):
self.pos = [x, y]
dx = self.pos[0] - player.pos[0]
dy = self.pos[1] - player.pos[1]
self.angle = math.atan2(dy, dx)
Now, i need help with the actual rotation itself. I am aware that adding a certain value to the angle every single frame would make it go around. But how would i make it go around a certain point that i specify and how would the arm length tie into this?. I find that it is really difficult to implement all of this because the y-axis is flipped and all the positional values have to be scaled down when using them in calculations because of the FPS rate. Any help on how this is done would be appreciated as well. Thanks
When you use pygame.transform.rotate the size of the new rotated image is increased compared to the size of the original image. You must make sure that the rotated image is placed so that its center remains in the center of the non-rotated image. To do this, get the rectangle of the original image and set the position. Get the rectangle of the rotated image and set the center position through the center of the original rectangle. e.g.:
def rotate_center(image, rect, angle):
rotated_image = pygame.transform.rotate(image, angle)
new_rect = rotated_image.get_rect(center = rect.center)
return rotated_image, new_rect
screen.blit(*rotate_center(image, image_rect, angle))
Alos see How do I rotate an image around its center using PyGame? and How to rotate an image(player) to the mouse direction?

Pygame moving image not appearing on moving background

So, i have a moving background for my pygame that is working fine. Now i wanted to add an obstacle (like a rock), that would be at the bottom of the screen and would move with the background. However, the image (obstacle) just disapears after appearing for a couple of seconds. I want the rock to appear over and over, however, it does not appear. Cant figure out whats wrong. Plz help, thanks!
background = pygame.image.load('background.png')
backgroundX = 0
backgroundX2 = background.get_width()
obstacle = pygame.image.load('obstacle.png')
obstacleX = 0
obstacleX2 = obstacle.get_width()
# use procedure for game window rather than using it within loop
def redrawGameWindow():
# background images for right to left moving screen
screen.blit(background, (backgroundX, 0))
screen.blit(background, (backgroundX2, 0))
man.draw(screen)
screen.blit(obstacle, (obstacleX, 380))
screen.blit(obstacle, (obstacleX2, 380))
pygame.display.flip()
pygame.display.update()
The main loop:
while run:
screen.fill(white)
clock.tick(30)
pygame.display.update()
redrawGameWindow() # call procedure
obstacleX -= 1.4
obstacleX2 -= 1.4
if obstacleX < obstacle.get_width() * -10:
obstacleX = obstacle.get_width
if obstacleX2 < obstacle.get_width() * -10:
obstacleX2 = obstacle.get_width()
The surface.blit() (i.e.: screen.blit) function takes an image and top-left co-ordinates of where to draw it.
In the code provided the two copies of obstacle are drawn at obstacleX and obstacleX2 - one of which is set to 0, and the other the width of the image. So this should result in the two images being drawn next to each other, on the left side of the window, at line 380.
If these images are no longer being drawn after a while, this could be caused by -
The variables obstacleX and obstacleX2 being changed to an off-screen position
The image obstacle being changed to a blank (or otherwise invisible) version
There is no evidence in the small code sample above, but since the question suggests the images move, it's my guess that the obstacleX and obstacleX2 co-ordinates of the drawing positions are being changed to become off-screen.
EDIT:
It's apparent that your objects are starting at position 0 (window left), and the position is being updated obstacleX -= 1.4 which is moving the obstacle further left. This is why they start on-screen, but soon disappear.
Put your screen dimensions into constants, e.g.:
WINDOW_WIDTH = 400
WINDOW_HEIGHT = 400
And use these instead of peppering your code with numbers. This reduces the number of changes needed if you decide to change window sizes, and it also allows calculations based on window width.
So start your obstacle just off the screen.
obstacleX = WINDOW_WIDTH # off-screen
obstacleX2 = WINDOW_WIDTH + 100 # Further away from first obstacle
In the main update-loop, when the position of the items change, check to see if they need to be re-cycled back to in-front of the player:
# Move the obstacles 1-pixel to the left
obstacleX -= 1.4
obstacleX2 -= 1.4 # probably just 1 would be better
# has the obstacle gone off-screen (to the left)
if ( obstacleX < 0 - obstacle.get_width() ):
# move it back to the right (off-screen)
obstacleX = WINDOW_WIDTH + random.randint( 10, 100 )
# TODO - handle obstacleX2 similarly

Updating the Bullet Class. Why is the y-coordinate value decreasing when the bullet is going up?

I created a class to update the bullet's position in this alien invasion game from a book i'm reading called, "Python Crash Course". What i'm having trouble understanding is why is the bullet corresponding to a decreasing y-coordinate when it's going up? Also, why is it necessary to subtract the self.speed_factor which is (1) from self.y which would be the bullet.
Description of the Code here https://imgur.com/corhigt
def update(self):
"""Move the bullet up the screen."""
# Update the decimal position of the bullet.
self.y -= self.speed_factor
# Update the rect position.
self.rect.y = self.y
def draw_bullet(self):
"""Draw the bullet to the screen."""
pygame.draw.rect(self.screen, self.color, self.rect)
In (almost) all graphics engines, the X axis goes left to right. However, the Y axis goes top to bottom, the opposite of how we usually think of the Y axis. As you increase an object's Y coordinate, it will be moving downwards on the screen.

Pygame animation with multiple states

I am trying to figure out the best way to create an animation with multiple states but I can't seem to find any examples on a clean way to achieve what I'm after.
I have a sprite sheet for a character that has two states of jumping animations, there are 6 frames where the character animation is essentially jumping off the ground.
There are another 6 frames where the character is in a "jump loop" so the character is already off the ground but the arms etc move slightly.
When I put all the images into a list and iterate through them the initial part of the jump looks fine because the character gets off the ground and then goes into the jump loop. But once the jump loop sequence of frames is done the animation goes back to the start mid air, so it looks as though the character is just jumping off something.
The code for the function I have thus far is as follows
def animate(self):
now = pg.time.get_ticks()
# Jumping
if self.jumping:
if now - self.last_update > 18:
self.last_update = now
if self.left:
self.current_frame = (self.current_frame + 1) % len(self.jump_l)
bottom = self.rect.midbottom
self.image = self.jump_l[self.current_frame]
self.rect = self.image.get_rect()
elif self.right:
self.current_frame = (self.current_frame + 1) % len(self.jump_r)
bottom = self.rect.midbottom
self.image = self.jump_r[self.current_frame]
self.rect = self.image.get_rect()
self.rect.midbottom = bottom
The animation works but essentially what I want to do is to only how the first 6 frames and then loop over the last 6 frames until the character lands.
I would recommend splitting up the animation Spritesheet so you have one row with the six frames for jumping up, and then another row for the other six falling frames.
Once you can do that, just check if your sprites velocity variable is positive or negative like this:
if self.vel > 0:
# Switch animation frames to jumping up
elif self.vel < 0:
# Switch animation frames to falling down
Thanks guys, I did split the animation into two (not the spritesheet) and I got it to work with the velocity (self.vel.x > 0) but after some consideration those extra 6 frames didn't really add much to the animation so I just took it out and used the loop part of the jump as the animation.
Looking closer at it there are only really 3 frames which are when the character lifts his leg slightly before he is in full jump and it isn't really noticeable and thus didn't really add anything to it so I scrapped the idea.

Changing direction of rotation Pygame

How would you change the direction of a rotating image/rect in Pygame? Applying positive and negative degree values works but it seems to only be able to rotate one direction throughout my window. Is there a way to ensure a change in direction of rotation?
Perhaps change up rotation of a spinning image every 5 seconds, or if able to change the direction of the spin when hitting a X or Y axis.
I've added some code below.
It seems like switching movement directions is easy with rect.move_ip as long as I specify a speed and have location clause, it does what I want. Unfortunately rotation is't like that. Here I'l adding angles to make sure it spins, but no matter what I try, I'm unable to negate the rotation.
def rotate_image(self): #rotate image
orig_rect = self.image.get_rect()
rot_image = pygame.transform.rotate(self.image, self.angle)
rot_rect = orig_rect.copy()
rot_rect.center = rot_image.get_rect().center
rot_image = rot_image.subsurface(rot_rect).copy()
return rot_image
def render(self):
self.screen.fill(self.bg_color)
self.rect.move_ip(0,5) #Y axis movement at 5 px per frame
self.angle += 5 #add 5 anglewhen the rect has not hit one of the window
self.angle %= 360
if self.rect.left < 0 or self.rect.right > self.width:
self.speed[0] = -self.speed[0]
self.angle = -self.angle #tried to invert the angle
self.angle -= 5 #trying to negate the angle rotation
self.angle %= 360
self.screen.blit(self.rotate_image(),self.rect)
pygame.display.flip()
I would really like to know how to invert rotation of a image. You may provide your own examples.
As far as I know, there is only one way of rotating the image using
pygame.transform.rotate(surface, angle)
You can check the official documentation
http://www.pygame.org/docs/ref/transform.html
Here is the example code:-
screen = pygame.display.set_mode((640,480))
surf = pygame.image.load("/home/image.jpeg").convert()
while True:
newsurf = pygame.transform.rotate(surf, -90)
screen.blit(newsurf, (100,100))
pygame.display.flip()
time.sleep(2)
This code will keep on rotating the image after every 2 seconds by 90 degrees in clockwise direction.
Hope this helps..

Categories

Resources