Related
I'm making a 3d platformer game in ursina and finishing level 1. But I can't get the Player to touch the portal and move to the next level. Also, I'm using my own player controller for some smoother jumping so I can't use intersect. I'll show you my code and the player code:
main.py File:
from ursina import *
from ursina import curve
from player import Player
from ursina.prefabs.sky import Sky
from ursina.shaders import lit_with_shadows_shader
app = Ursina(borderless=False)
window.exit_button.enabled = True
window.cog_button.enabled = True
window.fps_counter.enabled = False
window.exit_button.text = ''
window.exit_button.color = color.gray
window.exit_button.texture = "sword"
window.cog_menu.enabled = False
window.title = 'Urono'
window.icon = 'duh.png'
Sky()
player = Player("cube", (0, 10, 0), "box")
player.SPEED = 3
player.jump_height = 0.5
ground = Entity(model='cube', texture='assets/hrllohrllo', collider='mesh', position=(
0, 0, 0), scale=(7, 2, 7), shader=lit_with_shadows_shader)
FPC_POS = player.position
background = Audio(
'audio/urono-cheerbeat-background',
loop=True,
autoplay=True
)
quM = Audio(
'audio/quit',
loop=False,
autoplay=False
)
grappler = Entity(parent=camera.ui, model='assets/grappler.obj', position=(0.8, -0.4, 0), scale=(0.25, 0.25, 0.25),
color=color.red, texture="white_cube", rotation=(-10, -10, -10), shader=lit_with_shadows_shader, on_click=camera.shake)
lava = Entity(parent=scene, model = "plane", texture = "white_cube", position = (0, -100, 0), scale = (10000, 1, 10000), color = color.orange, collider = "plane")
class Grapple(Button):
def __init__(self, position=(0, 0, 0)):
super().__init__(
parent=scene,
model="cube",
texture="assets/grappler_texture",
collider="box",
position=position,
shader=lit_with_shadows_shader,
scale=(10, 10, 10)
)
self.player = player
def update(self):
self.on_click = Func(self.player.animate_position,
self.position, duration=0.5, curve=curve.linear)
ray = raycast(self.player.position, self.player.forward,
distance=0.5, ignore=[player, ])
if ray.entity == self:
self.player.y += 2
class Portal(Entity):
def __init__(self, position=(0, 0, 0)):
super().__init__(
parent=scene,
model="assets/portal.obj",
scale=(2, 4, 2),
texture="portal_texture",
collider="box",
position=position,
shader=lit_with_shadows_shader
)
self.player = player
def update(self):
if hit.entity == self.player:
level2()
class Platform(Entity):
def __init__(self, position=(0, 0, 0)):
super().__init__(
parent=scene,
model="cube",
scale=(7, 2, 7),
texture="grappler_texture",
collider="box",
position=position,
shader=lit_with_shadows_shader
)
FPC_POS_text = Text("", scale=2, x=0.2, y=0.2)
QUIT_WARN_text = Text("", scale=2, x=0.2, y=0.2)
def level1():
Platform(Vec3(1, -1, -27.2754))
Platform(Vec3(0.0640625, 0.00125, -53.2754))
Platform(Vec3(0.169236, 14.3008, -33.3041))
Platform(Vec3(-0.886462, 7.42754, -73.0878))
Platform(Vec3(-1.10773, 12.6191, -90.2041))
Platform(Vec3(-1.3286, 19.5097, -107.289))
Platform(Vec3(-1.55644, 25.4606, -124.914))
Platform(Vec3(-2.07368, 25.0602, -164.926))
Platform(Vec3(-4.56876, 24.3813, -206.787))
Platform(Vec3(-6.55665, 36.2641, -210.516))
Platform(Vec3(-5.2145, 24.7415, -232.169))
Platform(Vec3(-8.12956, 19.0883, -313.253))
Grapple(Vec3(-7.73628, 24.0123, -262.297))
Platform(Vec3(-8.12433, 26.1495, -245.986))
Platform(Vec3(6.65358, 20.0725, -312.287))
Platform(Vec3(25.9705, 20.3887, -312.661))
Platform(Vec3(44.783, 20.6966, -313.026))
Platform(Vec3(63.9781, 21.0108, -313.399))
Platform(Vec3(106.336, 21.7041, -314.22))
Platform(Vec3(127.271, 22.0467, -314.626))
Platform(Vec3(140.357, 27.1054, -314.879))
Platform(Vec3(155.502, 31.5333, -315.172))
Platform(Vec3(183.088, 32.3551, -313.688))
Platform(Vec3(207.893, 32.8512, -313.688))
Platform(Vec3(272.206, 34.1376, -313.688))
Platform(Vec3(286.402, 40.7493, -313.687))
Platform(Vec3(279.467, 45.2291, -298.974))
Platform(Vec3(276.644, 47.8035, -247.383))
Platform(Vec3(275.481, 47.0466, -206.259))
Portal(Vec3(275.486, 52.046, -206.386))
Platform(Vec3(280.947, 52.4222, -273.657))
Platform(Vec3(-1.45974, 25.976, -178.793))
Platform(Vec3(-2.1425, 25.0246, -178.681))
Platform(Vec3(-1.51808, 25.5806, -140.103))
Platform(Vec3(-2.0098, 26.0397, -150))
Platform(Vec3(-2.38591, 26.2334, -191.67))
Grapple(Vec3(91.2361, 32.216, -313.007))
Platform(Vec3(-9.097, 32.2579, -280.842))
Platform(Vec3(279.779, 52.2863, -288.757))
Platform(Vec3(277.064, 51.1692, -255.344))
Grapple(Vec3(274.925, 56.6227, -223.522))
Platform(Vec3(251.518, 40.172, -314.807))
Platform(Vec3(234.105, 33.5976, -314.413))
Platform(Vec3(225.337, 34.8861, -314.214))
Platform(Vec3(215.52, 33.2659, -316.504))
level1()
def level2():
Platform(Vec3(1, -1, -27.2754))
Platform(Vec3(0.0640625, 0.00125, -53.2754))
def update():
if held_keys['i']:
FPC_POS_text.text = f"{player.position}"
else:
FPC_POS_text.text = ' '
if held_keys['escape']:
if not quM.playing:
quM.play()
QUIT_WARN_text.text = 'Press "q" to quit'
else:
QUIT_WARN_text.text = ' '
if held_keys['q']:
quit()
PointLight(parent=camera, color=color.white, position=(0, 10, -1.5))
AmbientLight(color=color.rgba(100, 100, 100, 0.1))
AmbientLight(parent=lava, color = color.white, position = (0, -50, 0))
app.run()
Then The player File:
from ursina import *
import math
def sign(x): return -1 if x < 0 else (1 if x > 0 else 0)
class Player(Entity):
def __init__(self, model, position, collider, scale=(1, 1, 1), SPEED=3, velocity=(0, 0, 0), MAXJUMP=1, gravity=1, controls="wasd", **kwargs):
super().__init__(
model="cube",
position=position,
scale=(1, 1, 1),
visible_self=False
)
self.collider = BoxCollider(
self, center=Vec3(0, 1, 0), size=Vec3(1, 2, 1))
mouse.locked = True
camera.parent = self
camera.position = (0, 2, 0)
camera.rotation = (0, 0, 0)
camera.fov = 100
self.velocity_x, self.velocity_y, self.velocity_z = velocity
self.SPEED = SPEED
self.MAXJUMP = MAXJUMP
self.jump_count = 0
self.gravity = gravity
self.jump_height = 0.3
self.slope = 40
self.controls = controls
self.sensibility = 70
self.crosshair = Entity(model="quad", color=color.red, parent=camera, position=(
0, 0, 1), scale=(0.01, 0.01, 0.01))
for key, value in kwargs.items():
try:
setattr(self, key, value)
except:
print(key, value)
def jump(self):
self.velocity_y = self.jump_height * 40
self.jump_count += 1
def update(self):
y_movement = self.velocity_y * time.dt
direction = (0, sign(y_movement), 0)
yRay = boxcast(origin=self.world_position, direction=direction,
distance=self.scale_y/2+abs(y_movement), ignore=[self, ])
if yRay.hit:
move = False
self.jump_count = 0
self.velocity_y = 0
else:
self.y += y_movement
self.velocity_y -= self.gravity * time.dt * 25
x_movement = (self.forward[0]*held_keys[self.controls[0]] +
self.left[0]*held_keys[self.controls[1]] +
self.back[0]*held_keys[self.controls[2]] +
self.right[0]*held_keys[self.controls[3]]) * time.dt*6 * self.SPEED
z_movement = (self.forward[2]*held_keys[self.controls[0]] +
self.left[2]*held_keys[self.controls[1]] +
self.back[2]*held_keys[self.controls[2]] +
self.right[2]*held_keys[self.controls[3]]) * time.dt*6 * self.SPEED
if x_movement != 0:
direction = (sign(x_movement), 0, 0)
xRay = boxcast(origin=self.world_position, direction=direction,
distance=self.scale_x/2+abs(x_movement), ignore=[self, ], thickness=(1, 1))
if not xRay.hit:
self.x += x_movement
else:
TopXRay = raycast(origin=self.world_position-(0, self.scale_y/2-.1, 0),
direction=direction, distance=self.scale_x /
2+math.tan(math.radians(self.slope))*.1,
ignore=[self, ])
if not TopXRay.hit:
self.x += x_movement
HeightRay = raycast(origin=self.world_position+(sign(x_movement)*self.scale_x/2, -self.scale_y/2, 0),
direction=(0, 1, 0), ignore=[self, ])
if HeightRay.hit:
self.y += HeightRay.distance
if z_movement != 0:
direction = (0, 0, sign(z_movement))
zRay = boxcast(origin=self.world_position, direction=direction,
distance=self.scale_z/2+abs(z_movement), ignore=[self, ], thickness=(1, 1))
if not zRay.hit:
self.z += z_movement
else:
TopZRay = raycast(origin=self.world_position-(0, self.scale_y/2-.1, 0),
direction=direction, distance=self.scale_z /
2+math.tan(math.radians(self.slope))*.1,
ignore=[self, ])
if not TopZRay.hit:
self.z += z_movement
HeightRay = raycast(origin=self.world_position+(0, -self.scale_y/2, sign(z_movement)*self.scale_z/2),
direction=(0, 1, 0), ignore=[self, ])
if HeightRay.hit:
self.y += HeightRay.distance
camera.rotation_x -= mouse.velocity[1] * self.sensibility
self.rotation_y += mouse.velocity[0] * self.sensibility
camera.rotation_x = min(max(-80, camera.rotation_x), 80)
def input(self, key):
if key == 'space':
if self.jump_count < self.MAXJUMP:
self.jump()
There's no intersecton variable, and I don't know what to do.
Credit to Mandaw for the player.
I'm trying to create a function that tells me if two canvas objects(in my code, rec and block) touch each other in Tkinter. I tried to do so with the information of their coordinates but it doesn't seem to work. Can you please help me?
The function will be used in snake which I'm creating in the code below, so don't ask my why the code is so long.
The function is in the line 119, same_poz
This is my code:
from tkinter import *
import time
import random
import threading
root = Tk()
root.title('Snake')
x, y = 484, 484
recX, recY = x // 2, y // 2
recW, recH = recX + 22, recY + 22
randoms = []
for i in range(484):
if i % 11 == 0:
randoms.append(i)
blockX, blockY = random.choice(randoms), random.choice(randoms)
blockW, blockH = blockX + 22, blockY + 22
c = Canvas(root, bg='black', width=x, height=y)
c.pack()
class Snake(threading.Thread):
def __init__(self, c, x, y, recX, recY, recW, recH, blockX, blockY, blockW, blockH):
super(Snake, self).__init__()
self.c = c
self.x = x
self.y = y
self.recX = recX
self.recY = recY
self.recW = recW
self.recH = recH
self.blockW = blockW
self.blockH = blockH
self.rec = c.create_rectangle(recX, recY, recW, recH, fill='red', outline='white')
self.blockX = blockX
self.blockY = blockY
self.block = c.create_rectangle(blockX, blockY, blockW, blockH, fill='green',
outline='white')
self.moving_right = False
self.moving_left = False
self.moving_up = False
self.moving_down = False
self.moving = False
def movingright(self):
self.moving_right = True
self.moving_left = False
self.moving_up = False
self.moving_down = False
self.moving = True
c.move(self.rec, 11, 0)
self.after4 = root.after(150, self.movingright)
def movingleft(self):
self.moving_left = True
self.moving_left = False
self.moving_up = False
self.moving_down = False
self.moving = True
c.move(self.rec, -11, 0)
self.after3 = root.after(150, self.movingleft)
def movingup(self):
self.moving_up = True
self.moving_right = False
self.moving_left = False
self.moving_up = False
self.moving = True
c.move(self.rec, 0, -11)
self.after = root.after(150, self.movingup)
def movingdown(self):
self.moving_down = True
self.moving_right = False
self.moving_left = False
self.moving_down = False
self.moving = True
c.move(self.rec, 0, 11)
self.after2 = root.after(150, self.movingdown)
def stop(self):
self.moving_right = False
self.moving_left = False
self.moving_up = False
self.moving_down = False
self.moving = False
try:
root.after_cancel(self.after)
except AttributeError:
pass
try:
root.after_cancel(self.after2)
except AttributeError:
pass
try:
root.after_cancel(self.after3)
except AttributeError:
pass
try:
root.after_cancel(self.after4)
except AttributeError:
pass
def move(self, n):
if n.keysym == 'Up':
self.stop()
self.movingup()
if n.keysym == 'Down':
self.stop()
self.movingdown()
if n.keysym == 'Right':
self.stop()
self.movingright()
if n.keysym == 'Left':
self.stop()
self.movingleft()
def same_poz(self):
if self.blockY == self.recY:
self.helpY = random.randint(10, self.y - self.blockY)
self.c.move(self.block, 0, self.helpY)
if self.blockX == self.recY:
self.helpX = random.randint(10, self.x - self.blockX)
self.c.move(self.block, 0, self.helpX)
if self.blockW == self.recW:
self.helpW = random.randint(10, self.x - self.blockW)
self.c.move(self.block, 0, self.helpW)
if self.blockH == self.recH:
self.helpH = random.randint(10, self.y - self.blockH)
self.c.move(self.block, 0, helpH)
cube = Snake(c, x, y, recX, recY, recW, recH, blockX, blockY, blockW, blockH)
cube.start()
cube.c.bind_all('<Key>', cube.move, cube.stop)
cube.c.bind_all('<Key>', cube.moving_left, cube.moving_right)
cube.c.bind_all('<Key', cube.moving_up, cube.moving_down)
cube.c.bind(cube.same_poz)
root.mainloop()
There are way too many problems with your code, with what you provided. I do not know why you are programming using Tkinter when you are still lacking the basics of Python. (Don't mean to sound harsh)
I do not know why you decided to inherit from threading.Thread when
you do not have any use for anything Thread provides in that
class.
Way too many instance parameters which you have no use for at all, and too many instance parameters that you have to change every single time.
Not using elif and instead using if constantly.
If you are using a thread to handle Tkinter changes outside of mainloop, there is no need to use .after since it basically does that.
Tkinter has dedicated bindings for every single key, including combinations of keys. There is no need to catch every single key event.
Use if __name__ == '__main__': if you are working with a single script, for testing it.
Some reading material on Tkinter - http://effbot.org/tkinterbook/
Here is a minimal rework of the code, that is working.
import time
import random
import threading
from tkinter import *
MOVINGUP = 'u'
MOVINGDOWN = 'd'
MOVINGLEFT = 'l'
MOVINGRIGHT = 'r'
NOTMOVING = '0'
class Snake:
def __init__(self, root, recX, recY, recW, recH, blockX, blockY, blockW, blockH):
self.root = root
self.c = Canvas(root, bg='black', width=x, height=y)
self.c.pack()
self.rec = self.c.create_rectangle(recX, recY, recW, recH, fill='red', outline='white')
self.block = self.c.create_rectangle(blockX, blockY, blockW, blockH, fill='green', outline='white')
self.direction = NOTMOVING
self.root.bind('<Up>', lambda e: self.moveset(MOVINGUP))
self.root.bind('<Down>', lambda e: self.moveset(MOVINGDOWN))
self.root.bind('<Left>', lambda e: self.moveset(MOVINGLEFT))
self.root.bind('<Right>', lambda e: self.moveset(MOVINGRIGHT))
def moveset(self, direction):
self.direction = direction
def movement(self):
if self.direction == MOVINGUP:
self.c.move(self.rec, 0, -11)
elif self.direction == MOVINGDOWN:
self.c.move(self.rec, 0, 11)
elif self.direction == MOVINGLEFT:
self.c.move(self.rec, -11, 0)
elif self.direction == MOVINGRIGHT:
self.c.move(self.rec, 11, 0)
self.same_poz()
def run(self):
while True:
time.sleep(0.15)
self.movement()
def same_poz(self):
# Snake (x0, y0, x1, y1)
snakepos = self.c.bbox(self.rec)
# Food block (x0, y0, x1, y1)
food = self.c.bbox(self.block)
# If direction matters, if not then possible to only use self.hit in a single condition.
if self.direction == MOVINGRIGHT and self.hit(snakepos, food):
print('Caught the food moving right.')
elif self.direction == MOVINGLEFT and self.hit(snakepos, food):
print('Caught the food moving left.')
elif self.direction == MOVINGUP and self.hit(snakepos, food):
print('Caught the food moving up.')
elif self.direction == MOVINGDOWN and self.hit(snakepos, food):
print('Caught the food moving down.')
def hit(self, snakepos, food):
"""
Recieves coordinates of food block and snake block and returns if they collide.
:param snakepos: Tuple containing (x0, y0, x1, y1) of the snake.
:param food: Tuple containing (x0, y0, x1, y1) of the food block.
:return: Boolean whether they collide
"""
snakex = (snakepos[0], snakepos[2])
snakey = (snakepos[1], snakepos[3])
foodx = (food[0], food[2])
foody = (food[1], food[3])
# Returns True if any of the snake x cooridnates are between the food x coordinates, or both x coordinates match.
if any((foodx[0] < xcoord < foodx[1] for xcoord in snakex)) or foodx == snakex:
# Returns True if any of the snake y cooridnates are between the food y coordinates, or both y coordinates match.
return any((foody[0] < ycoord < foody[1] for ycoord in snakey)) or foody == snakey
return False
if __name__ == '__main__':
root = Tk()
root.title('Snake')
x, y = 484, 484
recX, recY = x // 2, y // 2
recW, recH = recX + 22, recY + 22
randoms = []
for i in range(484):
if i % 11 == 0:
randoms.append(i)
blockX, blockY = random.choice(randoms), random.choice(randoms)
blockW, blockH = blockX + 22, blockY + 22
snake = Snake(root, recX, recY, recW, recH, blockX, blockY, blockW, blockH)
threading.Thread(target=snake.run, daemon=True).start()
root.mainloop()
This question already has answers here:
How do I detect collision in pygame?
(5 answers)
How to detect collisions between two rectangular objects or images in pygame
(1 answer)
Closed 2 years ago.
I'm making a game environment for NEAT. The first two obstacles seem to collide with the players just fine, but none of the other obstacles do anything. The visuals won't work, but based on the size of the player list, yeah no it's not working. The collide class also wouldn't work before I started implementing NEAT, so there's that.
Anyway here's some (probably) irrelevant code:
import pygame
from pygame.locals import *
import random
import os
import neat
debugfun = 0
W = 300
H = 300
win = pygame.display.set_mode((W, H))
pygame.display.set_caption("bruv moment")
coords = [0, 60, 120, 180, 240]
class Player(object):
def __init__(self, x):
self.x = x
self.y = 600 - 60
self.width = 60
self.height = 60
self.pos = 0
self.left = False
self.right = False
def move(self):
if self.left:
self.pos -= 1
if self.right:
self.pos += 1
if self.pos < 0:
self.pos = 4
if self.pos > 4:
self.pos = 0
self.x = coords[self.pos]
class Block(object):
def __init__(self, pos, vel):
self.pos = pos
self.x = coords[self.pos]
self.y = -60
self.width = 60
self.height = 60
self.vel = vel
def move(self):
self.y += self.vel
def redraw_window():
pygame.draw.rect(win, (0, 0, 0), (0, 0, W, H))
for ob in obs:
pygame.draw.rect(win, (0, 255, 0), (ob.x, ob.y, ob.width, ob.height))
for ind in homies:
pygame.draw.rect(win, (255, 0, 0), (ind.x, ind.y, ind.width, ind.height))
pygame.display.update()
obs = []
homies = []
player_collision = False
ge = []
nets = []
And here's some relevant code:
def collide():
for ob in obs:
for x, ind in enumerate(homies):
if ind.y < ob.y + ob.height and ind.y + ind.height > ob.y and ind.x + ind.width > ob.x and ind.x < ob.x + ob.width:
ge[x].fitness -= 1
homies.pop(x)
nets.pop(x)
ge.pop(x)
def main(genomes, config):
speed = 30
pygame.time.set_timer(USEREVENT + 1, 550)
pygame.time.set_timer(USEREVENT + 2, 1000)
for _, g in genomes:
net = neat.nn.FeedForwardNetwork.create(g, config)
nets.append(net)
homies.append(Player(0))
g.fitness = 0
ge.append(g)
clock = pygame.time.Clock()
ran = True
while ran and len(homies) > 0:
clock.tick(27)
collide()
for x, ind in enumerate(homies):
ind.move()
ge[x].fitness += 0.1
try:
output = nets[x].activate((ind.x, abs(obs[0].x - ind.x)))
except IndexError:
output = 50
try:
if output in range(5, 25):
ind.left = True
else:
ind.left = False
if output > 25:
ind.right = True
else:
ind.right = False
except TypeError:
if output[0] in range(5, 25):
ind.left = True
else:
ind.left = False
if output[1] > 25:
ind.right = True
else:
ind.right = False
for ob in obs:
ob.move()
if ob.x > H:
obs.pop(obs.index(ob))
for event in pygame.event.get():
if event.type == pygame.QUIT:
ran = False
pygame.quit()
if event.type == USEREVENT+1:
if speed <= 200:
speed += 3
if event.type == USEREVENT+2:
for g in ge:
g.fitness += 0.5
if len(obs) == 0:
obs.append(Block(round(random.randint(0, 4)), speed))
print(len(homies))
print(len(obs))
redraw_window()
def run(config_file):
config = neat.config.Config(neat.DefaultGenome, neat.DefaultReproduction, neat.DefaultSpeciesSet,
neat.DefaultStagnation, config_path)
p = neat.Population(config)
p.add_reporter(neat.StdOutReporter(True))
stats = neat.StatisticsReporter()
p.add_reporter(stats)
winner = p.run(main, 50)
if __name__ == "__main__":
local_dir = os.path.dirname(__file__)
config_path = os.path.join(local_dir, "avoidpedofiles.txt")
run(config_path)
I am trying to build my first Platformer Game. So far, I have make moving left and right but unfortunately, I have encountered a error that I have not been able to fix when I implemented collisions and gravity. My player keeps on dissolving like spider man if it lands on the platform. The character is still existent, and lands on the platform, but unfortunately, he becomes invisible. There is no error message, and I suspect is has to do with the collision check.
hits = pygame.sprite.spritecollide(object, allPlatforms, False)
if hits:
object.rect.y = hits[0].rect.top + 1
object.vy = 0
print(object.rect.midbottom)
It prints out the Players location in the code, and the player is still existent and movable, but it just doesn't show. Is there something that I did that makes the character vanish?
import pygame
import random
WIDTH = 500
HEIGHT = 400
FPS = 30
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
playerImage = "blockBandit/BlockBandit.png"
class Player(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface((50, 50))
self.image = pygame.image.load(playerImage).convert()
self.rect = self.image.get_rect()
self.rect.center = (WIDTH / 2, HEIGHT / 2)
self.vx = 0
self.vy = 0
class Platform(pygame.sprite.Sprite):
def __init__(self, x, y, w, h):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.Surface((w, h))
self.image.fill(GREEN)
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
pygame.init()
pygame.mixer.init()
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Block Bandit")
clock = pygame.time.Clock()
allPlatforms = pygame.sprite.Group()
all_sprites = pygame.sprite.Group()
player = Player()
all_sprites.add(player)
p1 = Platform(0, HEIGHT - 40, WIDTH, 40)
all_sprites.add(p1)
allPlatforms.add(p1)
def moveCharacter(object):
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT]:
object.vx += -2
if keys[pygame.K_RIGHT]:
object.vx += 2
object.vx = object.vx * 0.9
if (abs(object.vx) < 1):
object.vx = 0
if (abs(object.vx) > 10):
if(object.vx < 0):
object.vx = -10
else:
object.vx = 10
object.vy = object.vy + 1
object.rect.x += object.vx
object.rect.y += object.vy
hits = pygame.sprite.spritecollide(object, allPlatforms, False)
if hits:
object.rect.y = hits[0].rect.top + 1
object.vy = 0
print(object.rect.midbottom)
running = True
while running:
clock.tick(FPS)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
moveCharacter(player)
#Update State
all_sprites.update()
#Render
screen.fill(BLACK)
all_sprites.draw(screen)
#screen.blit(player.icon, (20, 40))
pygame.display.flip()
pygame.quit()
Am I doing something wrong? Thanks!
The y attribute of the rect is the same as the top coordinate, so you're setting the top of the player sprite to the top of the platform sprite here object.rect.y = hits[0].rect.top + 1. And if the platform comes later in the sprite group, it will be blitted after the player and the player won't be visible.
Just change that line to object.rect.bottom = hits[0].rect.top + 1.
This question already has answers here:
How do I detect collision in pygame?
(5 answers)
How to detect collisions between two rectangular objects or images in pygame
(1 answer)
Closed 2 years ago.
It can collide properly on all sides and when i jump from the the ground onto the platform the player will land ontop of it and collide properly. However when i am standing on the platform and i jump and try to land on the platform again i fall straight through. Why does this happen?
Also if i hold down space bar then my sprite does not fall through the box and jumps ontop of it normally.
What it looks like: https://gyazo.com/6e0c9dfd15cdd99e72f14137fb5ef1cb
What it should look like: https://gyazo.com/bec5dc5a07d0d323b4d1cc8597eafb39
main.py
import pygame
from map import *
from char import *
pygame.init()
class game():
def __init__(self):
self.width = 1280
self.height = 720
self.gameRunning = True
self.clock = pygame.time.Clock()
self.FPS = 60
self.screen = pygame.display.set_mode((self.width, self.height))
self.loadMapData()
def update(self):
pygame.display.set_caption("{:.2f}".format(self.clock.get_fps()))
self.screen.fill(white)
self.screen.blit(self.map_img, (0,336))
playerGroup.draw(self.screen)
pygame.display.update()
def gameLoop(self):
self.clock.tick(self.FPS)
self.event()
player1.move()
self.update()
def event(self):
for event in pygame.event.get():
if event.type == pygame.QUIT:
self.gameRunning = False
def loadMapData(self):
self.map = TiledMap()
self.map_img = self.map.make_mapSurface()
for tile_object in self.map.gameMap.objects:
if tile_object.name == "Floor":
Collision(tile_object.x, tile_object.y + 336, tile_object.width, tile_object.height)
if tile_object.name == "Collision Box":
Platform(tile_object.x, tile_object.y + 336, tile_object.width, tile_object.height)
g = game()
player1 = player()
while g.gameRunning == True:
g.gameLoop()
map.py
import pygame
import pytmx
from char import *
pygame.init()
class TiledMap():
def __init__(self):
self.gameMap = pytmx.load_pygame("CollisionMap.tmx")
self.mapwidth = self.gameMap.tilewidth * self.gameMap.width
self.mapheight = self.gameMap.tileheight * self.gameMap.height
def renderMap(self, surface):
for layer in self.gameMap.visible_layers:
if isinstance(layer, pytmx.TiledTileLayer):
for x,y,gid in layer:
tile = self.gameMap.get_tile_image_by_gid(gid)
if tile:
surface.blit(tile, (x * self.gameMap.tilewidth, y * self.gameMap.tileheight))
def make_mapSurface(self):
mapSurface = pygame.Surface((self.mapwidth, self.mapheight), pygame.SRCALPHA)
self.renderMap(mapSurface)
return mapSurface
class Collision(pygame.sprite.Sprite):
def __init__(self, x, y, width, height):
self.groups = SolidGroup
pygame.sprite.Sprite.__init__(self, self.groups)
self.rect = pygame.Rect(x, y, width, height)
class Platform(pygame.sprite.Sprite):
def __init__(self, x, y, width, height):
self.groups = platformGroup
pygame.sprite.Sprite.__init__(self, self.groups)
self.rect = pygame.Rect(x, y, width, height)
char.py
import pygame
pygame.init()
black = (0, 0, 0)
white = (255, 255, 255)
red = (255, 0, 0)
green = (0, 255, 0)
blue = (0, 0, 255)
playerGroup = pygame.sprite.Group()
SolidGroup = pygame.sprite.Group()
platformGroup = pygame.sprite.Group()
class player(pygame.sprite.Sprite):
def __init__(self):
self.groups = playerGroup
pygame.sprite.Sprite.__init__(self, self.groups)
self.image = pygame.Surface((50, 50))
self.image.fill(blue)
self.rect = self.image.get_rect()
self.rect.center = (1280/2, 720/2)
self.position = pygame.math.Vector2(400, 300)
self.acceleration = pygame.math.Vector2(0, 0)
self.velocity = pygame.math.Vector2(0, 0)
self.friction = -0.18
self.falling = False
self.up = False
self.down = False
self.right = False
self.Left = False
def checkFalling(self):
self.rect.y += 1
if not pygame.sprite.spritecollideany(self, SolidGroup, False):
self.falling = True
if self.velocity.y < 0:
self.up = True
self.down = False
if self.velocity.y > 0:
self.up = False
self.down = True
else:
self.falling = False
self.up = False
self.down = False
self.rect.y -= 1
def move(self):
self.checkFalling()
if self.falling:
self.acceleration = pygame.math.Vector2(0, 0.5)
if not self.falling:
self.acceleration = pygame.math.Vector2(0, 0)
key = pygame.key.get_pressed()
if key[pygame.K_RIGHT]:
self.acceleration.x = 1
self.right = True
if key[pygame.K_LEFT]:
self.acceleration.x = -1
self.left = True
if key[pygame.K_SPACE]:
self.jump()
self.acceleration.x += self.velocity.x * self.friction
self.velocity += self.acceleration
if abs(self.velocity.x) < 0.1:
self.velocity.x = 0
self.position += self.velocity + 0.5 * self.acceleration
hitsPlatform = pygame.sprite.spritecollide(self, platformGroup, False)
if hitsPlatform:
if self.up:
self.position.y -= self.velocity.y - 0.5 * self.acceleration.y
self.velocity.y = 0
self.rect.midbottom = self.position
"""
Collision Code, not in function because of screen tearing and bouncy collisions
"""
hits = pygame.sprite.spritecollide(self, SolidGroup, False)
if hits:
self.position.y = hits[0].rect.top
self.velocity.y = 0
hitsPlatform = pygame.sprite.spritecollide(self, platformGroup, False)
if hitsPlatform:
if self.down and self.position.y <= 340:
self.position.y = hitsPlatform[0].rect.top
self.velocity.y = 0
if self.velocity.x > 0 and self.position.x + 64 < 239:
self.position.x -= self.velocity.x - 0.5 * self.acceleration.x
if self.velocity.x < 0 and self.position.x > 256:
self.position.x -= self.velocity.x - 0.5 * self.acceleration.x
self.rect.midbottom = self.position
def jump(self):
self.rect.y += 1
hits = pygame.sprite.spritecollide(self, SolidGroup, False)
hitsPlatform = pygame.sprite.spritecollide(self, platformGroup, False)
self.rect.y -= 1
if hits:
self.velocity.y = -15
if hitsPlatform:
self.velocity.y = -15