I'm making a game and I want to check collision between player and block, and push back player if neccesary.
def collide(self,player):
if self.solid:
if self.rect.colliderect(player.rect):
if self.rect.bottom-1 <= player.rect.top and player.pos == 'up':
player.up = 0
player.rect.move(0,1)
if self.rect.top+1 >= player.rect.bottom and player.pos == 'down':
player.down = 0
player.rect.move_ip(0,-1)
if self.rect.left+1 <= player.rect.right and player.pos == 'right':
player.right = 0
player.rect.move_ip(-1,0)
if self.rect.right-1 >= player.rect.left and player.pos == 'left':
player.left = 0
player.rect.move_ip(1,0)
but for some reason it doesn't work. Can someone help me?
Thanks in advance
Try replacing
def Collide(player,self):
by
def collide(self, player):
if this is a method of some kind of Obstacle class. Just guessing ... :)
If you want your objects to be pushed back, then the easiest way is will involve modifying your update() function just a little bit.
Each time you move, record the current position as "self._oldposition" (or something similar)
When you collide, you will need to set the current position to the old position (self._oldposition)
This will take care of most of your collision problems.
Related
I ran into a problem with the pygame library while building my app.
A part of my code is as follows: at the beginning of the class in the init method
I create my enemies.
self.create_enemy
And then, that method is like this
def create_enemy(self):
self.available_space_x = 10
for enemy_number in range(self.sets.enemy_number):
self.enemy = Enemy(self)
self.available_space_x += 150
self.enemy.x = self.available_space_x
self.enemy.rect.x = self.enemy.x
self.enemys.add(self.enemy)
The work of this method is that it creates 5 enemies in different places and then adds it to the group of my enemies.
Next, part of the main method is as follows:
self.enemys.draw(self.screen)
self.checkenemymove()
self.update_enemys()
That is, it creates my enemies and then executes this function:
def checkenemymove(self):
if self.human.human_rect.x >= self.enemy.rect.x:
self.goenemleft = False
self.goenemright = True
elif self.human.human_rect.x < self.enemy.rect.x:
self.goenemright = False
self.goenemleft = True
This method makes the enemy move to the right if the player is ahead of the enemy (player side) or the enemy moves to the left if the player is behind the enemy.
And finally this method is executed:
def update_enemys(self):
if self.goenemright:
self.enemy.image = self.enemy.enemy_images[0]
self.enemy.x += self.sets.enemy_speed
self.enemy.rect.x = self.enemy.x
if self.goenemleft:
self.enemy.image = self.enemy.enemy_images[1]
self.enemy.x -= self.sets.enemy_speed
self.enemy.rect.x = self.enemy.x
The problem is that if I run the program, only the last enemy will do this, and wherever the player goes, the enemy will also move in that direction.
Please help me, thank you.
I wanted the enemy to move towards me, but only one enemy moves towards me.
Remove the self.enemy attribute from the class. You don't need it because all enemies are contained in the self.enemys pygame.sprite.Group. Therefore, you need only the group of enemies:
def create_enemy(self):
available_space_x = 10
for enemy_number in range(self.sets.enemy_number):
enemy = Enemy(self)
available_space_x += 150
enemy.x = available_space_x
enemy.rect.x = enemy.x
self.enemys.add(enemy)
Use a for-loop to move all enemies in the self.enemys list:
def update_enemys(self):
for enemy in self.enemys:
if self.goenemright:
enemy.image = self.enemy.enemy_images[0]
enemy.x += self.sets.enemy_speed
enemy.rect.x = enemy.x
if self.goenemleft:
enemy.image = self.enemy.enemy_images[1]
enemy.x -= self.sets.enemy_speed
enemy.rect.x = enemy.x
Thank you very much, I have come to the conclusion that I should do this:
def checkenemymove(self):
for enemy in self.enemys:
if self.human.human_rect.x >= enemy.rect.x:
enemy.image = self.enemy.enemy_images[0]
enemy.x += self.sets.enemy_speed
enemy.rect.x = enemy.x
elif self.human.human_rect.x < enemy.rect.x:
enemy.image = self.enemy.enemy_images[1]
enemy.x -= self.sets.enemy_speed
enemy.rect.x = enemy.x
I am new to programming and started with pygame zero. I am making a little game where you shoot a rocket to an alien. But my rocket keeps stuck to the border when fired, I made a reload function but I want it to go automatically ( when it hits the border or alien to go back to its normal position). Can anyone help me with that?
alien = Actor('alien', (100,100))
ship =Actor('ship', (500,400))
rocket_fire = Actor('rocket_fire', (500,400))
WIDTH = 1000
HEIGHT =500
def draw():
screen.clear()
screen.blit('space_back', (0,0))
rocket_fire.draw()
ship.draw()
alien.draw()
def move_ship(ship):
if keyboard.left:
ship.x -= 3
rocket_fire.x -= 3
elif keyboard.right:
ship.x += 3
rocket_fire.x += 3
elif keyboard.space:
animate(rocket_fire, pos = (ship.x,0))
elif keyboard.r:
rocket_fire.pos = (ship.x,ship.y)
def move_alien(alien):
alien.right +=2
if alien.left > WIDTH:
alien.right = 0
collide = rocket_fire.colliderect(alien)
if collide == 0:
alien.image = 'alien'
elif collide == 1:
alien.image = 'nuclear_explosion'
def update():
rocket_fire.draw()
ship.draw()
alien.draw()
move_ship(ship)
move_alien(alien)
You can try to assign the initial values to 'rocket_fire' after 'collide == 1'.
elif collide == 1:
alien.image = 'nuclear_explosion'
// rocket_fire = (500,400) -> this is just a representation to assign position; not accurate as per the code
Im sorta new to python and pygame, and I need help with something relating to acceleration. I followed a tutorial on youtube on how to make a base for a platforming game, and I've been using it to create a game that plays like a Kirby game. One of the tiny little details i notice in a Kirby game is how he skids when you move in a direction and then quickly move turn to the other direction, and for the past few days I was figuring out how to get it to work. The solution I came up with was to make it so instead of the character just moving whenever a key is pressed, the character will accelerate and then stop accelerating once it's reached its max speed, and then quickly slow down and accelerate again once you press another direction key. Problem is, I dont know how to program acceleration. Can anyone help me with this?
Here is the code i wrote for the game (first bit is for collision, second bit is for actually moving the player):
def move(rect, movement, tiles):
collide_types = {'top': False, 'bottom': False, 'right': False, 'left': False}
rect.x += movement[0]
hit_list = collide_test(rect, tiles)
for tile in hit_list:
if movement[0] > 0:
rect.right = tile.left
collide_types['right'] = True
if movement[0] < 0:
rect.left = tile.right
collide_types['left'] = True
rect.y += movement[1]
hit_list = collide_test(rect, tiles)
for tile in hit_list:
if movement[1] > 0:
rect.bottom = tile.top
collide_types['bottom'] = True
if movement[1] < 0:
rect.top = tile.bottom
collide_types['top'] = True
return rect, collide_types
Second bit:
player_move = [0, 0]
if move_right:
player_move[0] += 2.5
elif run:
player_move[0] += -3
if move_left:
player_move[0] -= 2
elif run:
player_move[0] -= -3
player_move[1] += verticle_momentum
verticle_momentum += 0.4
if verticle_momentum > 12:
verticle_momentum = 12
elif slow_fall == True:
verticle_momentum = 1
if fly:
verticle_momentum = -2
slow_fall = True
if verticle_momentum != 0:
if ground_snd_timer == 0:
ground_snd_timer = 20
Instead of directly changing the position of the character on button press, you should change the velocity.
So for example, taking movement on the X axis only:
acc = 0.02 # the rate of change for velocity
if move_right:
xVel += acc
if move_left:
xVel -= acc
# And now change your character position based on the current velocity
character.pose.x += xVel
Other things you can add: make it so when you don't press any keys you lose momentum so you can come at a stop. You can do this by substracting from velocity or adding to it a certain decay factor (which is smaller than your acceleration constant, but you will have to tune it as you experiment with your game).
I have to make a space invaders game for my intermediate python class using the Zelle graphics package. I have been having some issues with the projectile, it will run through the code, shoot the bullet, and continue to move the bullet, but while the bullet is moving, I can't move the character. I assume this is a pretty simple problem, but I'm not experienced enough with programing yet. Thanks.
from graphics import *
from time import *
game_over = False
win = GraphWin("skulls and bones", 500, 500)
skull = Image(Point(250, 450), "skull_2.gif")
skull.draw(win)
bullet = Circle(Point(250, 250), 10)
bullet.setFill("red")
def bone():
value = 0
key = win.getKey()
if key == "x":
bullet.draw(win)
return bullet
def space_ship_move():
key = win.getKey()
if key == "a":
skull.move(-10, 0)
if key == "d":
skull.move(10, 0)
if key == "x":
bone()
for i in range(100):
sleep(1)
bone().move(0, -5)
return key
while not game_over:
space_ship_move()'''
There are two problems: First, win.getKey() blocks until the user presses a key. You don't want to do that - use win.checkKey(). Second, you need to decouple animation and input handling because you want your bullet to also move if there is no input. You can do this with the following structure:
def space_ship_move():
handle_input()
animate()
sleep(0.1)
handle_input() is mostly what you already had in there:
bullet = None
bulletAnimStep = -1
def bone():
global bullet, bulletAnimStep
if bullet is not None:
bullet.undraw()
bullet = Circle(Point(250, 250), 10)
bullet.setFill("red")
bullet.draw(win)
bulletAnimStep = 0
def handle_input():
key = win.checkKey()
if key == "a":
skull.move(-10, 0)
if key == "d":
skull.move(10, 0)
if key == "x":
bone()
I assumed bone() was supposed to be responsible for creating a new bullet. This is what the current function does. It also sets a bulletAnimStep to 0, indicating that we are at the beginning of the bullet animation. Our animate() can use that information to decide when to stop the bullet animation. This is how it could look:
def animate():
global bulletAnimStep
#animate bullet
if bulletAnimStep >= 0:
bulletAnimStep += 1
bullet.move(0, -5)
if bulletAnimStep >= 100:
#the bullet has gone far enough
bullet.undraw()
bulletAnimStep = -1
This question already has answers here:
How can I make a sprite move when key is held down
(6 answers)
Closed last month.
I just got a sprite moving around the window using "w,a,s,d", and i want to make this sprite "shoot" by pressing the space bar.
The problem i've got is that the sprite appears but doesn't move until i release the space bar, and i want the sprite shot to go forward until the end of the window, just by pressing the space bar, not by releasing it.
This is my main loop:
while pygame.event.poll().type != QUIT:
screen.blit(background, (0, 0))
#"player" is the sprite moving around the window
player.move(width,height)
screen.blit(player.image, player.rect)
key = pygame.key.get_pressed()
if key[K_SPACE]:
xpos = player.rect.right
ypos = player.rect.top
shot_on_screen = True
if shot_on_screen:
xpos += 1
#"kame" is the sprite i want to move forward
screen.blit(shot.kame, (xpos, ypos))
else:
shot.x = player.rect.right
shot.y = player.rect.top
shot_on_screen = False
pygame.display.update()
I'm new at this python-pygame world, i've checked a lot of manuals and documentation before asking though, hope you can help, thanks.
You are setting xpos to the player most right position on every loop when the K_SPACE is pressed. You shouldn't do that. Try removing that line.
if key[K_SPACE]:
ypos = player.rect.top
shot_on_screen = True
Also, I don't know if you are checking if the shot is on the screen somewhere else on the code, but the code you posted will not set it to false.
if shot_on_screen:
xpos += 1
#"kame" is the sprite i want to move forward
screen.blit(shot.kame, (xpos, ypos))
else:
shot.x = player.rect.right
shot.y = player.rect.top
shot_on_screen = False # won't work. It is already False.