Player goes a little bit under the ground after landing - python

Hi I am making a game and I have a problem. When player lands to the ground he goes a little bit under the ground, for example like this:
And I want someting like this:
Here is my gravity code:
if not player.player.collidelistall(MAPr) and player.yvel < 4:
player.yvel -= 0.3
if player.player.collidelistall(MAPr):
player.yvel = 0
player.y -= player.yvel
cy -= player.yvel
thanks!

Calculate the player's position as it would be if it had moved before the collision test. Only move the player if it doesn't collide. Set the player's position on the ground when you detect the collision:
player.y = cy - player.yvel
indices = player.player.collidelistall(MAPr)
if indices:
player.yvel = 0
for i in indices:
player.player.bottom = MAPr[i].top
cy = player.player.y
else:
cy -= player.yvel
if player.yvel < 4:
player.yvel -= 0.3
See collidelistall:
Returns a list of all the indices that contain rectangles that collide with the Rect

Related

How can i make my randomly moving object move in a specific angle in pygame

Full Code
self.VEL = 3
self.RAND = numpy.linspace(-self.VEL, +self.VEL, 100) # calculating value between -2 and 2, a total of 100 values
-----------------------------------------
if self.new_line:
self.deltax = random.choice(self.RAND)
self.deltay = random.choice(self.RAND)
self.new_line = False
self.move(self.deltax, self.deltay)
-----------------------------------------
def move(self, deltax, deltay):
self.x += deltax
self.y += deltay
I'm currently building an ant simulator in python with pygame. The ants start in the middle and move on from there randomly. The movement works like this. Every few milliseconds self.new_line is set to True. Then a new self.deltax and self.deltay are calculated. Now, as long as self.new_line is False my ant will move with self.x += deltax and self.y += deltay per iteration. When self.new_line is True again the ant will start a new line with new values for self.deltax and self.deltay. The values for deltax and deltay are between -2 and +2 meaning the ant could move in every angle.
Visualization
Questions:
However i want my ants only to move in a specific angle. Like This
How can i do this?
If you run the program with on ant you will see that the speed of the ant changes with new lines. How can make my ant to have one consistent speed?
How can i make my ant bounce of walls in a specific angle?
Thanks for your help.
These are multiple questions. The intent is to ask only one question. I will only answer 2 of them.
Use pygame.math.Vector2 and rotate() to generate a direction vector with constant length and angle in a specified range:
if self.new_line:
angle = random.randint(-45, 45)
direction_vector = pygame.math.Vector2(0, -self.VEL).rotate(angle)
self.deltax = direction_vector.x
self.deltay = direction_vector.y

Simple drag physics, acting differently when moving left or right [duplicate]

This question already has answers here:
Pygame doesn't let me use float for rect.move, but I need it
(2 answers)
How to draw a moving circle in Pygame with a small angle at a low speed and blinking?
(1 answer)
Closed 2 years ago.
My code is acting differently for negative velocities than it is positive ones
I'm trying to implement platformer physics, the player has velocity in the X direction, the velocity is increased or decreased when the user presses "A" or "D" respectively, or set to 0 when the player collides with a wall.
To simulate friction with the ground, the X Velocity of the player is multiplied with "self.drag" (a float less than 1)
I expected this code to reduce the players X Velocity, over time reducing it neglibly near to 0, without actually reversing the velocity (like subtracting a value would), this would stop the player sliding about uncontrollably when the user isn't imputing movement commands.
This works as intended when moving right, however when moving left it acts differently,
when moving to the left the player seems to continue floating for a while before coming to a stop.
Here's the code that takes player input, inside the player class, run each frame:
dx = 0
if pygame.key.get_pressed()[pygame.K_a]:
dx -= self.speed
if pygame.key.get_pressed()[pygame.K_d]:
dx += self.speed
# to slow down horizontal movement
self.vx *= self.drag
# Add change in velocity to total velocity
self.vx += dx
self.vy += dy
Maybe the concept works and I've implemented it incorrectly?
There's collision code that may be affecting the velocities in ways I haven't noticed?
Does this system work differently for positive and negative velocities?
Thanks!
Any help is much appreciated
The issue is caused, because pygame.Rect stores integral coordinates:
The coordinates for Rect objects are all integers. [...]
The fraction component of dx and dy is lost when you do:
self.Rect.x += dx
self.Rect.y += dy
You have to do the calculations with floating point accuracy. Add an x ​​and y attribute to the class. Increment the attributes in move and synchronize the Rect attribute:
class Player:
def __init__(self, color):
self.Rect = pygame.Rect([50, 50], [30, 50])
self.x = self.Rect.x
self.y = slef.Rect.y
# [...]
def move(self, dx, dy, platforms):
# Test for collisions with platforms
# handle movement on the X axis
self.x += dx
self.Rect.x = round(self.x)
for platform in platforms:
if self.Rect.colliderect(platform.Rect):
if dx > 0:
self.Rect.right = platform.Rect.left
if dx < 0:
self.Rect.left = platform.Rect.right
self.x = self.Rect.x
# Reset velocity when collision with wall
self.vx = 0
# handle movement on the Y axis
self.Rect.y += dy
self.Rect.y = round(self.y)
for platform in platforms:
if self.Rect.colliderect(platform.Rect):
if dy > 0:
self.Rect.bottom = platform.Rect.top
if dy < 0:
self.Rect.top = platform.Rect.bottom
self.y = self.Rect.y
# Reset velocity when collision with floor or roof
self.vy = 0
# return correctly collided rect to draw()
return self.Rect

How do I have circle bounce back up after gravity takes it down?

I have a ball and once it hits the floor, I want it to bounce back up to say half the original bounce, until it can't bounce anymore. I added a pass where the ball just stops at the bottom. How do I make it bounce back up?
kickoff_location = [WIDTH/2 - ball_size[0] / 2, 210]
gravity = 2
ball_bounce = False
if not(ball_bounce):
if kickoff_location[1] < player_one_pos[1] + (player_width / 2) + ball_size[0]:
kickoff_location[1] += gravity
elif kickoff_location[1] == player_one_pos[1] + (player_width / 2) + ball_size[0]:
kickoff_location[1] -= gravity / 2
pass
You need a speed vector for your ball, ie. vel = [0, 0] # [dX, dY]
You need simple gravity acceleration constant, ie. grav = 0.1
You need enviroment resistance constant, ie. resist = 0.8
You need mentioned elasticity factor, ie. elast = 0.5
Now, in every update cycle you:
update Y part of velocity by gravity: vel[1] += grav
update both velocity parts by resistance: vel[0] *= resist ; vel[1] *= resist
check for collisions, vertical and horizontal separately. If collision is vertical (floor/ceiling) reverse Y speed and modify it by elasticity: vel[1] = -vel[1] * elast. The same for horizontal collisions, but for X part of velocity.
update ball position by speed vector: ball_loc[0] += vel[0] ; ball_loc[1] += vel[1]
And tinker with constants to get realistic ball movement...

Problems with creating a UI and glRotatef()

I am making a minimal Doom-style FPS game engine using Python, PyGame and Legacy PyOpenGL. I hope that the player will be able to look around in four directions - forward, backwards, left and right - using glRotatef() by pressing the left and right arrow keys.
A few problems have arisen:
A gun (a cube with a texture applied that changes the texture coordinates depending on the direction the player is facing) that should always appear 0.5 units ahead of the camera in the corresponding x and z position depending on the angle glRotatef() sets it to face towards, is moving to a strange position if I move on the x axis and then look left unless I stand dead centre in the room. The cube also appears to be static when I move left and right even though I am supplying it the x value I obtained from glGetDoublev(), and when I move forward the gun appears to be scaling even though I never implemented such functionality.
When I call
if event.type == pygame.KEYDOWN: # key pressed events
if event.key == pygame.K_LEFT:
glRotatef(-90,0,1,0)
if direction == 0:
direction = 3
else:
direction -= 1
to look to the left of the room, I occasionally get moved inside the wall and this sometimes affects the gun's position further.
I've tried adding fixed x and z variables (x_steps and z_steps) that are incremented by 0.1 every time the player moves. I'm not particularly sure why that removes the "static gun" problem but it did. However, when I rotated the camera, the same problem (of the gun moving to a strange position) still occurred.
## pygame/opengl initialisation code
def main():
pygame.init()
display = (800,600)
global displaySurface
displaySurface = pygame.display.set_mode(display, DOUBLEBUF|OPENGL)
pygame.display.set_caption("Wolfenstein 4D")
glEnable(GL_TEXTURE_2D)
glEnable(GL_DEPTH_TEST)
gluPerspective(45, (display[0]/display[1]),0.1,50.0)
## game loop, obtaining x,y,z positions and looking around the room
def room1():
direction = 3 ## 3 = forward, 2 = left, 1 = backward, 0 = right
while True:
pos = glGetDoublev(GL_MODELVIEW_MATRIX)
x = pos[3][0]
y = pos[3][1]
z = pos[3][2]
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
if event.type == pygame.KEYDOWN: # key pressed events
if event.key == pygame.K_LEFT:
glRotatef(-90,0,1,0)
if direction == 0:
direction = 3
else:
direction -= 1
x_steps = 0
z_steps = 0
if event.key == pygame.K_RIGHT:
glRotatef(90,0,1,0)
if direction == 3:
direction = 0
else:
direction += 1
x_steps = 0
z_steps = 0
## movement code
spd = 0.1
keys = pygame.key.get_pressed()
if direction == 3:
if keys[pygame.K_a]:
glTranslatef(spd,0,0)
x_steps -= spd
if keys[pygame.K_d]:
glTranslatef(-spd,0,0)
x_steps += spd
if keys[pygame.K_w]:
glTranslatef(0,0,spd)
z_steps -= spd
if keys[pygame.K_s]:
glTranslatef(0,0,-spd)
z_steps += spd
if direction == 2:
if keys[pygame.K_a]:
glTranslatef(0,0,-spd)
x_steps += spd
if keys[pygame.K_d]:
glTranslatef(0,0,spd)
x_steps -= spd
if keys[pygame.K_w]:
glTranslatef(spd,0,0)
z_steps -= spd
if keys[pygame.K_s]:
glTranslatef(-spd,0,0)
z_steps += spd
## gun drawing code in game loop
if direction == 3:
loadTexture("gun1.png")
drawHUDGun(x,-0.1,z-0.5,3,0.1,0.1,0.1)
if direction == 2:
loadTexture("gun.png")
drawHUDGun(z-0.5,-0.1,x+0.5,2,0.1,0.1,0.1)
## gun drawing function
def drawHUDGun(x,y,z,angle,width,height,depth=0.5,color = ((1,1,1))):
vertices = (
(width+x,-height+y,-depth+z),
(width+x,height+y,-depth+z),
(-width+x,height+y,-depth+z),
(-width+x,-height+y,-depth+z),
(width+x,-height+y,depth+z),
(width+x,height+y,depth+z),
(-width+x,-height+y,depth+z),
(-width+x,height+y,depth+z)
)
glEnable(GL_BLEND)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
glBegin(GL_QUADS)
if angle == 3:
j = 0
if angle == 2:
j = 8
i = 0
for surface in surfaces:
i += 1
for vertex in surface:
glColor4f(1,1,1,1)
setTexCoord(0, texCoords, j)
if angle == 3:
if i >= 0 and i < 4:
if j < 4:
j += 1
if angle == 2:
if i == 2:
if j < 12:
j += 1
glVertex3fv(vertices[vertex])
glEnd()
glDisable(GL_BLEND)
glBegin(GL_LINES)
for edge in edges:
glColor3fv((0,1,0))
for vertex in edge:
glVertex3fv(vertices[vertex])
glEnd()
## implementation of the functions
main()
room1()
I expect the gun to appear 0.5 units ahead of the player in any direction regardless of where they are in the room, but the gun is often out of view due to being assigned incorrect x or z co-ordinates.
In legacy OpenGL there exists different current matrices. The current matrix which is affected by matrix operations can be chosen by glMatrixMode. Each matrix is organized on a stack. Matrices can be pushed and popped by glPushMatrix/glPopMatrix.
The projection matrix should be placed set to the projection matrix stack, the view and model transformations to the modelview matrix stack:
// choose projection matrix stack
glMatrixMode(GL_PROJECTION)
gluPerspective(45, (display[0]/display[1]),0.1,50.0)
// choose modelview matrix stack, for the following matrix operations
glMatrixMode(GL_MODELVIEW)
The gun should be placed in a first person view ("in front of you"). The esiest wy to achieve this is to draw the gun in viewspace, this means you've to cancel all the previous transformations to the modelview matrix. The matrix can be replace with the identity matrix by glLoadIdentity.
Save the modelview matrix onto the stack, set the identity matrix, draw the gun and finally restore the modelview matrix.e.g:
glPushMatrix()
glLoadIdentity()
drawHUDGun(x,-0.1,z-0.5,3,0.1,0.1,0.1)
glPopMatrix()

Python Turtle how to create collision

I am attempting to create pong using Turtle, however, I am having an issue with the collision system. I am using a basic pythagorean function for this, however, when the ball hits a bumber, it gets stuck at the bumper and starts shaking. I am not sure how to fix this problem. Here is the collision and bumper code.
turtle.register_shape('bar.gif')
lbump = turtle.Turtle()
lbump.color('white')
lbump.shape('bar.gif')
lbump.penup()
lbump.speed(0)
lbump.setposition(-285,0)
rbump = turtle.Turtle()
rbump.color('white')
rbump.shape('bar.gif')
rbump.penup()
rbump.speed(0)
rbump.setposition(285,0)
ball = turtle.Turtle()
ball.color('white')
ball.shape('circle')
ball.penup()
ball.speed(0)
ball.setposition(0,0)
ballspeedx = -5
ballspeedy = 0 #To test collison#
def isCollision(t1, t2):
distance = math.sqrt(math.pow(t1.xcor()-t2.xcor(),2)+math.pow(t1.ycor()-t2.ycor(),2))
if distance < 30:
return True
else:
return False
def ball_move():
while True:
global ballspeedy
global ballspeedx
x = ball.xcor() + ballspeedx
y = ball.ycor() + ballspeedy
if y > 285 or y < -285:
ballspeedy *= -1
if x < -295 or x > 295:
x = 0
y = 0
if isCollision(lbump, ball):
ballspeedx *= -1
if isCollision(rbump, ball):
ballspeedx *= -1
ball.setposition(x,y)
The reason it's likely this: when a collision is detected (isCollision returns True) and the sign of the x velocity is switched, the ball does not have the time to gain enough distance from the bumper until the next iteration of the loop. Hence, next iteration isCollision is still detecting a collision and changes again the sign of the velocity.
As a result, x velocity sign is switched each iteration from positive to negative and viceversa, and you see the shacking effect.
If I'm right, this edit is the simplest way that come to my mind to solve the issue:
if isCollision(lbump, ball):
ballspeedx = abs(ballspeedx)
if isCollision(rbump, ball):
ballspeedx = -1 * abs(ballspeedx)
Of course more elaborate solutions can be implemented.

Categories

Resources