How to add acceleration to my character in pygame? - python

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).

Related

How do I make my rocket go back to its position when hitting the border?

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

need help finding solution to deciding turns for tic-tac-toe

I'm working on a tic tac toe game in processing.
I can't figure out how to make a way to have X and O swap to vaguely imitate swapping turns I have seen someone did it like the code below but for some reason, I either get an error or it just doesn't work when I hook it up to my preexisting code.
I should have Elaborated more I plan (attempt) to use the Minimax algorithm to make this game unwinnable
print("Begin")
global top_left, top_middle, top_right
global middle_left, center, middle_right
global bottem_left, bottem_middle, bottem_right
#these are the variables used to check if someone has put their move their already
#0 = empty
#1 = Circle
#2 = X
top_left = 0
top_middle = 0
top_right = 0
middle_left = 0
center = 0
middle_right = 0
bottem_left = 0
bottem_middle = 0
bottem_right = 0
#code for changing turns
turn = 1
def turn_changer():
global turn
if turn == 1:
turn = 2
else:
turn = 1
#board setup
def setup():
size(600,600)
#this hurt my brain trying to fully understand
#lines dividing board
def draw():
for y in range(3):
for x in range(3):
rect(200*x,200*y,200,200)
#hope this is not what geomtry is like
#top left ellipse
if top_left == 1:
ellipse(100,100,150,150)
#top left X
elif top_left == 2:
line(0,0,200,200)
line(200,0,0,200)
#top middle ellipse
if top_middle == 1:
ellipse(300,100,150,150)
#top middle X
elif top_middle == 2:
line(200,0,400,200)
line(400,0,200,200)
#top right ellipse
if top_right == 1:
ellipse(500,100,150,150)
#top right X
elif top_right == 2:
line(400,0,600,200)
line(600,0,400,200)
#middle left ellipse
if middle_left == 1:
ellipse(100,300,150,150)
#middle left X
elif middle_left == 2:
line(0,200,200,400)
line(200,200,0,400)
#middle ellipse
if center == 1:
ellipse(300,300,150,150)
#middle X
elif center == 2:
line(200,200,400,400)
line(400,200,200,400)
#middle right ellipse
if middle_right == 1:
ellipse(500,300,150,150)
#middle right X
elif middle_right == 2:
line(400,200,600,400)
line(600,200,400,400)
#bottem left ellipse
if bottem_left == 1:
ellipse(100,500,150,150)
#bottem left X
elif bottem_left == 2:
line(0,400,200,600)
line(200,400,0,600)
#bottem middle ellipse
if bottem_middle == 1:
ellipse(300,500,150,150)
#bottem middle X
elif bottem_middle == 2:
line(200,400,400,600)
line(400,400,200,600)
#bottem right ellipse
if bottem_right == 1:
ellipse (500,500,150,150)
#bottem right Xw
elif bottem_right == 2:
line(400,400,600,600)
line(600,400,400,600)
#dectects the quardnates where the mouse clicked and prints them
def mousePressed():
println( (mouseX, mouseY) )
#top left square hitbox
if (mouseX > 0 and mouseX < 200) and (mouseY > 0 and mouseY < 200):
top_left =+ turn
turn_changer()
print("top left")
#top middle square hitbox
elif (mouseX > 200 and mouseX < 400) and (mouseY > 0 and mouseY < 200):
top_middle = turn
turn_changer()
print(turn)
print("top middle")
#top right square hitbox
elif (mouseX > 400 and mouseX < 600) and (mouseY > 0 and mouseY < 200):
top_right = turn
turn_changer()
print("top right")
#middle left square hitbox
elif (mouseX > 0 and mouseX < 200) and (mouseY > 200 and mouseY < 400):
middle_left = turn
turn_changer()
print("middle left")
#center square hitbox
elif (mouseX > 200 and mouseX < 400) and (mouseY > 200 and mouseY < 400):
center = turn
turn_changer()
print("middle")
#middle right square hitbox
elif (mouseX > 400 and mouseX < 600) and (mouseY > 200 and mouseY < 400):
middle_right = turn
turn_changer()
print("middle right")
#bottem left square hitbox
elif (mouseX > 0 and mouseX < 200) and (mouseY > 400 and mouseY < 600):
bottem_left = turn
turn_changer()
print("bottem left")
#bottem middle square hitbox
elif (mouseX > 200 and mouseX < 400) and (mouseY > 400 and mouseY < 600):
bottem_middle = turn
turn_changer()
print("bottem middle")
#bottem right square hitbox
elif (mouseX > 400 and mouseX < 600) and (mouseY > 400 and mouseY < 600):
bottem_right = turn
turn_changer()
print("bottem right")
I respect that you're learning on your own, and so I took some time to learn python's basics to give you something to think about. I'm not a python buff (yet), so I may have done some misguided manipulations somewhere (so if a better coder than me is reading this and spots something awful, let me know), but I believe that this is mostly good stuff.
I used class since I tend to think in OOP (and so will you after a while). Instead of seeing a grid with X and O, I see the game like this:
One game is an object.
A Game manages:
A Grid (which is an object, too).
Who's turn it is (and when it's the AI turn, how the AI should play).
When the game ends.
A grid manages:
9 Cases (which are objects, too).
A Case manages:
It draws itself (so... it's coordinates and stuff).
If there's a X or O on it.
If it's been clicked
I fully realize that objects are a huge bump in the learning curve when you start programming, but I'm insisting here because I've seen A LOT of hardcoding in your code, and it's the kind of stuff which will cause you problems when you scale up your projects.
Hardcoding, like how you check which case have been clicked, isn't inherently bad, but it makes everything more difficult. It's part of the things you sometimes learn "the hard way", so here's my advice: when you ninja-code something (short code snippets which are written quickly and won't be part of something bigger), it's not great but it does the job. In any other context, it must be motivated by some specific need to be a good practice, and even there it can be avoided most of the time.
Here's commented code based on what I just wrote. I didn't do the whole tic-tac-toe game, just up to the part where it switch turns between the players or the player/AI (I put a boolean up there that let you switch between human opponent and AI opponent). What is missing is mostly the AI logic (I put a temporary one where it selects the first case it finds) and the victory conditions.
The boolean is currently in "player vs player" mode. Change it to True to let the AI take over the O side.
# Player 1 (X) is human and play first
# Player 2 (O) is cpu
# You can change this boolean to play hotseat with a human if you want:
_AIPlayer = False
# Game own a grid, count turns and do any other game-specific concepts
# One "game of tic-tac-toe" would equal one of this object
class Game:
def __init__(self):
self.Grid = Grid(self) # creating the grid we'll use
self.TurnCount = 0 # first turn is turn number zero
def Render(self):
# when you draw the game, in fact it asks it's grid to draw itself
self.Grid.Render()
def Play(self):
# if it's the CPU's turn, let him play, else the game will wait for the player before going forward
# if there is no cpu player, the mouse can be used by player two
# the difference is that the cpu will do it's turn as a consequence of the player's turn
# and then add +1 to the turn count, while player 2 is exactly like player one but with O instead of X
# the game will check X and O to see who win, not a player class (but it could have been designed that way if needed)
if self.GetCurrentPlayer() == "O" and _AIPlayer:
self.AITurn()
def GetCurrentPlayer(self):
# return which's player is currently playing
if self.TurnCount % 2 == 0:
return "X"
else:
return "O"
def AITurn(self):
# this is a dumb placeholder
# your AI logic will be used here
# for now it just put a O on the first available case
print("AI turn")
for c in self.Grid.Cases:
if c.XO == "":
c.XO = self.GetCurrentPlayer()
break
self.TurnCount += 1
# Grid class is the whole grid
class Grid:
def __init__(self, game):
# the grid knows the game. I could use the global variable instead, but I dislike
# this kind of spaghetti. It would have worked, though.
# It's usually best to make everything you can dynamic, i.e. not hardcoded.
# It's easier to maintain and fix bugs that way, and you can upscale more easily too
# for an example, I could use this code to run several tic-tac-toe games in the
# same window at the same time with only a few modifications
self.Game = game
self.Cases = []
for i in range(3):
for j in range(3):
self.Cases.append(GridCase(i, j))
def Render(self):
# when you draw the grid, in fact it ask it's cases to draw themselves
for c in self.Cases:
c.Render()
def CaseClicked(self, xPos, yPos):
# this checks which case was clicked when it's a player
# since we don't care about the case's coordinated, we ask them if they have been clicked instead
for c in self.Cases:
if c.Clicked(xPos, yPos, self.Game.GetCurrentPlayer()):
self.Game.TurnCount += 1
return
# GridCase is each instance of 1 case in the grid
class GridCase:
def __init__(self, gridX, gridY):
# gridX and gridY are useful to know which case is part of which line
self.gridX = gridX
self.gridY = gridY
# I hardcoded the case's width and height, but you could totally make them dynamic
# and decide "on the fly" how big the grid will be. And it would still work.
self.w = 200 # width
self.h = 200 # height
# these coordinates are in pixels, and are useful to draw the case and for hit detection
self.x = self.w * gridX # x coordinate of the case
self.y = self.h * gridY # y coordinate of the case
# the "content" of the case
self.XO = "" # X or O as a character (it could be anything, I choose to stick to these)
def Render(self):
# the lines positions are dynamic: they'll be calculated from the case's perspective
# every case top left corner is in fact: (self.x, self.y)
rect(self.x, self.y, self.w, self.h)
# if the case has content, it'll be drawn at the same time than the case
if self.XO == "X":
line(self.x , self.y, self.x+self.w, self.y+self.h)
line(self.x, self.y+self.h, self.x+self.w, self.y)
elif self.XO == "O":
ellipse(self.x+(self.w/2),self.y+(self.h/2), self.w*0.75, self.h*0.75)
def SetXO(self, XO):
self.XO = XO
def Clicked(self, xPos, yPos, car):
# if the case is free and the click was inside it's boundaries, then attribute it to the current player
# the return True to tell that a sign was just placed
if self.XO == "" and xPos > self.x and xPos < self.x + self.w and yPos > self.y and yPos < self.y + self.h:
self.XO = car
return True
return False
# globals
_game = Game()
def setup():
size(600,600)
def draw():
# background wipes the screen "clean" (here it paints it black)
# then we can draw the current state of the grid
# here we could do without but I wanted you to know about it
background(0)
# draw the grid, then let the players do their thing
_game.Render()
# here you should check for game end conditions (victory or draw)
_game.Play()
def mouseClicked():
# listeing to mouse clicks
_game.Grid.CaseClicked(mouseX, mouseY)
You should copy and paste this code in a Processing.py IDE and try it. Fiddle around and read the comments. You can learn a lot here if you try. If you have questions, ask away in the comments with my handle and I'll come back and give you a hand.
And... have fun!
When the button is pressed check if the turn is equal to 1 or 2 and with that u tell the program to display an cross or a circle instead of making a function to change that value
Hope this helps!
There are SO MANY WAYS you could do this...
You can flip a variable (kinda like you just showed). Since there are only two players, I would probably flip a boolean instead: myBoolean = !myBoolean after every turn.
You can count the turns and use the modulo operator. Then you both know which turn it is right now AND the total number of turns for the current game. Let's say that you have a global TurnCount variable. If you do TurnCount % 2 the result will either be 0 or 1, making it a surefire way to know which turn it is. This operator is really useful and you should remember it either way!
If there are no difference in the gameplay between player 1 and 2 except for their X and O, you can flip between the character 'X' and the character 'O' instead of 1 and 2 like in your code snippet. This variable can be used to show visually which symbol will placed or straight up to place one symbol or the other. Simple and efficient.
So it mostly depends on how ninja you code will be. If you're doing a "simpel hot seat" where players takes turn clicking with the same mouse, method 3 is great. If you want to show "statistics" after the game, method 2 will work nicely. Method 1 will work too, but it's more rough, even if it's simple. You can add more code if you need tailored advice.
Have fun!
Set the variable 'turn' as a global (outside of the 'turn_changer' function / making sure this code is only ran once, not every time your game loops).
Run your game logic, with the player (X or O) being determined by the value of 'turn'.
After the player makes their move call 'turn_changer' so the turn changes.
Repeat.
Using the code you provided, I added this:
def game():
print (turn)
turn_changer()
print (turn)
turn_changer()
print (turn)
if __name__ == "__main__":
game()
and the turn_changer() function seems to work correctly

Player moves correct speed across the screen, walk cycle is too fast, hoping for suggestions to do it properly

I'm jumping around tutorials trying to successfully complete my first game. I was taking a heavy object oriented approach for managing resources, but I felt that was clouding my understanding a bit, so I restarted. I currently have my character moving smoothly across the screen at a speed I like, my problem is my "walk cycle" of three images goes way to fast, and I get a persistence of vision effect on my little chicken's legs. I need to slow it down, so far I was able to achieve a desired effect by popping in a call to the clock after each decision loop, but I am worried that will slow down the entire game logic, as I am not sure if calling clock more than once is "freezing" my game update in time while the character decides to move. I had considered maybe making some type of equation comparing the time on the clock to the time on the clock before, to slow down the walk cycle key frames. Any help or suggestions, is there an easier method? Thanks a bunch.
import pygame, sys
from pygame.locals import *
pygame.init()
#Contstants
BLACK = (0, 0, 0)
SCREENWIDTH = 300
SCREENHEIGHT = 300
game_running = True
clock = pygame.time.Clock()
#variables
current = 0
class Player(object):
def __init__(self):
self.avatar_front = pygame.image.load("chicken_front.png")
self.avatar_back = pygame.image.load("chicken_back.png")
self.avatar_right = pygame.image.load("chicken_right_stand.png")
self.avatar_left = pygame.image.load("chicken_left_stand.png")
self.avatar_left_walk = pygame.image.load("chicken_left_walk1.png")
self.avatar_left_walk2 = pygame.image.load("chicken_left_walk2.png")
self.avatar_right = pygame.image.load("chicken_right_stand.png")
self.avatar_right_walk = pygame.image.load("chicken_right_walk1.png")
self.avatar_right_walk2 = pygame.image.load("chicken_right_walk2.png")
self.position = [0, 0]
self.current_direction = self.avatar_front
#SetUp
myScreen = pygame.display.set_mode((SCREENWIDTH, SCREENHEIGHT))
pygame.display.set_caption("Chicken Rush!")
pygame.display.set_icon(pygame.image.load("chicken_front.png"))
myPlayer = Player()
while game_running:
myScreen.fill(BLACK)
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
#RIGHT HERE DETERMINES WHICH IMAGE TO DISPLAY FOR WALKING LEFT->This is the part I need to # slow down
keys_pressed = pygame.key.get_pressed()
if keys_pressed[K_LEFT] and myPlayer.position[0] >= 0:
if current == 0:
myPlayer.current_direction = myPlayer.avatar_left
current += 1
elif current == 1:
myPlayer.current_direction = myPlayer.avatar_left_walk
current += 1
elif current == 2:
myPlayer.current_direction = myPlayer.avatar_left_walk2
current = 0
myPlayer.position[0] -= 3
if keys_pressed[K_RIGHT] and myPlayer.position[0] < SCREENWIDTH - 32:
myPlayer.position[0] += 3
if keys_pressed[K_UP] and myPlayer.position[1] >= 0:
myPlayer.position[1] -= 3
if keys_pressed[K_DOWN] and myPlayer.position[1] < SCREENHEIGHT - 35:
myPlayer.position[1] += 3
myScreen.blit(myPlayer.current_direction, (myPlayer.position[0], myPlayer.position[1]))
pygame.display.update()
clock.tick(28)
It seems like you could use a longer interval to slow down the image transitions. Keep in mind you'll need to play with the value of imageTransitionSpeed to get it to your liking, but something like this should help slow the transition down:
#RIGHT HERE DETERMINES WHICH IMAGE TO DISPLAY FOR WALKING LEFT->This is the part I need to # slow down
imageTransitionSpeed = 10
keys_pressed = pygame.key.get_pressed()
if keys_pressed[K_LEFT] and myPlayer.position[0] >= 0:
if current == 0:
myPlayer.current_direction = myPlayer.avatar_left
current += 1
elif current == imageTransitionSpeed:
myPlayer.current_direction = myPlayer.avatar_left_walk
current += 1
elif current == (imageTransitionSpeed * 2):
myPlayer.current_direction = myPlayer.avatar_left_walk2
current = 0
else:
current += 1
myPlayer.position[0] -= 3
if keys_pressed[K_RIGHT] and myPlayer.position[0] < SCREENWIDTH - 32:
myPlayer.position[0] += 3
if keys_pressed[K_UP] and myPlayer.position[1] >= 0:
myPlayer.position[1] -= 3
if keys_pressed[K_DOWN] and myPlayer.position[1] < SCREENHEIGHT - 35:
myPlayer.position[1] += 3
myScreen.blit(myPlayer.current_direction, (myPlayer.position[0], myPlayer.position[1]))
pygame.display.update()
clock.tick(28)

Add collision detection to sprite, pyGame

bassically im trying to add collision detection to the sprite below, using the following:
self.rect = bounds_rect
collide = pygame.sprite.spritecollide(self, wall_list, False)
if collide:
# yes
print("collide")
However it seems that when the collide is triggered it continuously prints 'collide' over and over when instead i want them to simply not be able to walk through the object, any help?
def update(self, time_passed):
""" Update the creep.
time_passed:
The time passed (in ms) since the previous update.
"""
if self.state == Creep.ALIVE:
# Maybe it's time to change the direction ?
#
self._change_direction(time_passed)
# Make the creep point in the correct direction.
# Since our direction vector is in screen coordinates
# (i.e. right bottom is 1, 1), and rotate() rotates
# counter-clockwise, the angle must be inverted to
# work correctly.
#
self.image = pygame.transform.rotate(
self.base_image, -self.direction.angle)
# Compute and apply the displacement to the position
# vector. The displacement is a vector, having the angle
# of self.direction (which is normalized to not affect
# the magnitude of the displacement)
#
displacement = vec2d(
self.direction.x * self.speed * time_passed,
self.direction.y * self.speed * time_passed)
self.pos += displacement
# When the image is rotated, its size is changed.
# We must take the size into account for detecting
# collisions with the walls.
#
self.image_w, self.image_h = self.image.get_size()
global bounds_rect
bounds_rect = self.field.inflate(
-self.image_w, -self.image_h)
if self.pos.x < bounds_rect.left:
self.pos.x = bounds_rect.left
self.direction.x *= -1
elif self.pos.x > bounds_rect.right:
self.pos.x = bounds_rect.right
self.direction.x *= -1
elif self.pos.y < bounds_rect.top:
self.pos.y = bounds_rect.top
self.direction.y *= -1
elif self.pos.y > bounds_rect.bottom:
self.pos.y = bounds_rect.bottom
self.direction.y *= -1
self.rect = bounds_rect
collide = pygame.sprite.spritecollide(self, wall_list, False)
if collide:
# yes
print("collide")
elif self.state == Creep.EXPLODING:
if self.explode_animation.active:
self.explode_animation.update(time_passed)
else:
self.state = Creep.DEAD
self.kill()
elif self.state == Creep.DEAD:
pass
#------------------ PRIVATE PARTS ------------------#
# States the creep can be in.
#
# ALIVE: The creep is roaming around the screen
# EXPLODING:
# The creep is now exploding, just a moment before dying.
# DEAD: The creep is dead and inactive
#
(ALIVE, EXPLODING, DEAD) = range(3)
_counter = 0
def _change_direction(self, time_passed):
""" Turn by 45 degrees in a random direction once per
0.4 to 0.5 seconds.
"""
self._counter += time_passed
if self._counter > randint(400, 500):
self.direction.rotate(45 * randint(-1, 1))
self._counter = 0
def _point_is_inside(self, point):
""" Is the point (given as a vec2d) inside our creep's
body?
"""
img_point = point - vec2d(
int(self.pos.x - self.image_w / 2),
int(self.pos.y - self.image_h / 2))
try:
pix = self.image.get_at(img_point)
return pix[3] > 0
except IndexError:
return False
def _decrease_health(self, n):
""" Decrease my health by n (or to 0, if it's currently
less than n)
"""
self.health = max(0, self.health - n)
if self.health == 0:
self._explode()
def _explode(self):
""" Starts the explosion animation that ends the Creep's
life.
"""
self.state = Creep.EXPLODING
pos = ( self.pos.x - self.explosion_images[0].get_width() / 2,
self.pos.y - self.explosion_images[0].get_height() / 2)
self.explode_animation = SimpleAnimation(
self.screen, pos, self.explosion_images,
100, 300)
global remainingCreeps
remainingCreeps-=1
if remainingCreeps == 0:
print("all dead")
A check for collision is only a check to see if two rectangular sprites have a common area.
There isn't a built in collision that unables player input during collision. You have to write that yourself.
You should probably want to change the player coordinates when a collision takes place. An example:
Let's say we play mario. When the state of mario is JUMPING check for collision. Somewhere we will store the speed of mario in the y axis. When the collision returns True, with any of the blocks, we now set the speed to 0, and the y to the top/bottom of a block. If it will be the bottom, we still keep JUMPING, so it can fall back to the ground.
My tip for the creeper is to have some oldx and oldy value, to return to when the collision takes place. That way the creeper will never go into a wall. Another approach would be to simply change the direction when a collision takes place, but that may not always work.

Pygame collision between player and block

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.

Categories

Resources