1

Why when touching the ground my sprite starts increasing velocity, sorry far not so useful comments.

The velocity slowly increases while touching the floor, moving to left until it hits the wall and stops I think one of my velocity algorithms isnt working good, could you please help me out, to be noted: from character import Character from fuses import Fuses imports this:

import pygame

class Character(pygame.sprite.Sprite):
    def __init__(self, color, width, height):
        super().__init__()
        self.image = pygame.Surface([width, height])
        pygame.draw.rect(self.image, color, [0, 0, width, height])
        self.image = pygame.image.load("Fuses.png").convert_alpha()
        self.rect = self.image.get_rect()

and this

import pygame


class Fuses(pygame.sprite.Sprite):
    def __init__(self, color, width, height):
        super().__init__()
        self.image = pygame.Surface([width, height])
        pygame.draw.rect(self.image, color, [0, 0, width, height])
        self.image = pygame.image.load("Fuses.png").convert_alpha()
        self.rect = self.image.get_rect()
import ctypes
import random
import threading
import pygame
from character import Character
from fuses import Fuses
# starting game
pygame.init()
#initiates
if True:
    # initiating
    debug = True
    clock = pygame.time.Clock()
    user32 = ctypes.windll.user32
    screen_size = user32.GetSystemMetrics(0), user32.GetSystemMetrics(1)
    screen = pygame.display.set_mode(screen_size)
    screen_width, screen_height = screen_size
    font = pygame.font.SysFont('Comic Sans MS', 30)
    pygame.display.set_caption("Slingy")
    player = Character((0, 0, 0), 37, 63)
    player.rect.centerx = screen_width / 2
    player.rect.centery = screen_height / 2
    fuse = Fuses((0, 0, 0), 30, 40)
    fuse.rect.centerx = random.randint(21, screen_width - 21)
    fuse.rect.centery = random.randint(16, screen_height - 16)
    all_sprites_list = pygame.sprite.Group()
    all_sprites_list.add(fuse, player)
    fuse_count, velx, vely, click_count, debug_counter = 300, 0, 0, 0, 0
    carryOn = True
def update():
    # updates player position
    player.rect.centerx += velx
    player.rect.centery += vely

def collide():
    # check collision
    global fuse_count, velx, vely
    if fuse.rect.colliderect(player):
        print("Player has earnt 2 fuses")
        fuse_count += 2
        while fuse.rect.colliderect(player):
            fuse.rect.centerx = random.randint(21, screen_width - 21)
            fuse.rect.centery = random.randint(16, screen_height - 16)
    if player.rect.centerx < 37 / 2:
        player.rect.centerx = 37 / 2
        velx = velx * 0.85
    if player.rect.centerx > screen_width - 37 / 2:
        player.rect.centerx = screen_width - 37 / 2
        velx = velx * 0.85
    if player.rect.centery < 63 / 2:
        player.rect.centery = 63 / 2
        vely = vely * 0.90
    if player.rect.centery > screen_height - 63 / 2 + 1:
        player.rect.centery = screen_height - 63 / 2 + 1
        vely = vely * 0.90
        velx = velx * 0.85
def vel():
    # Slowly decreasing velocity
    global velx, vely
    if velx > 0.1:
        velx -= velx * 0.02 + 0.001
    if velx < 0.1:
        velx += velx * 0.02 + 0.001
    vely += abs(vely) / 50 + 0.3

def key():
    # gets input
    global click_count, fuse_count, velx, vely, carryOn
    mouseX, mouseY = pygame.mouse.get_pos()
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            carryOn = False
        if event.type == pygame.MOUSEBUTTONUP:
            click_count += 1
            print(f"Click count: {click_count} \nFuse count: {fuse_count}")
            if fuse_count > 0:
                fuse_count -= 1
                vely = 0
                velx += (mouseX - player.rect.centerx) * 0.05
                vely += (mouseY - player.rect.centery) * 0.05
            else:
                print("You are out of fuses")

def debugging():
    #prints velocities
    global debug_counter
    if debug_counter % 70 == 0:
        print(f"Velocity x: {velx} \nVelocity y: {vely}")
    debug_counter += 1

# Start of the game render
print(f"Starting... \nSprites: {all_sprites_list} \nClicks: {click_count} \n Fuses: {fuse_count}")
while carryOn:
    #game render
    clock.tick(70)
    velocity_t = threading.Thread(target=vel())
    collision_t = threading.Thread(target=collide())
    draw_t = threading.Thread(target=update())
    if debug:
        # print velocities
        debug_t = threading.Thread(target=debugging())
        debug_t.start()
    input_t = threading.Thread(target=key())
    input_t.start()
    input_t.join()
    collision_t.start()
    collision_t.join()
    velocity_t.start()
    velocity_t.join()
    draw_t.start()
    draw_t.join()
    textsurface = font.render("You have " + str(fuse_count) + " fuses", False, (0, 0, 0))
    screen.fill((255, 255, 255))
    screen.blit(textsurface, (0, 0))
    all_sprites_list.update()
    all_sprites_list.draw(screen)
    pygame.display.flip()
# quits the game
pygame.quit()
# game ended
Rabbid76
  • 202,892
  • 27
  • 131
  • 174
R0Best
  • 41
  • 6

1 Answers1

1

Since pygame.Rect is supposed to represent an area on the screen, a pygame.Rect object can only store integral data.

The coordinates for Rect objects are all integers. [...]

The fraction part of the coordinates gets lost when the new position of the object is assigned to the Rect object. This causes the object to move faster to the left than to the right.

If you want to store object positions with floating point accuracy, you have to store the location of the object in separate variables respectively attributes and to synchronize the pygame.Rect object. round the coordinates and assign it to the location (e.g. .topleft) of the rectangle:

class Character(pygame.sprite.Sprite):
    def __init__(self, color, width, height):
        super().__init__()
        self.image = pygame.Surface([width, height])
        pygame.draw.rect(self.image, color, [0, 0, width, height])
        self.image = pygame.image.load("Fuses.png").convert_alpha()
        self.rect = self.image.get_rect()
        self.x, self.y = self.rect.center

    def update(self):
        self.rect.center = round(self.x), round(self.y)
def update():
    # updates player position
    player.x += velx
    player.y += vely
    player.update()

def collide():
    # [...]

    if player.x < 37 / 2:
        player.x = 37 / 2
        velx = velx * 0.85
    if player.x > screen_width - 37 / 2:
        player.x = screen_width - 37 / 2
        velx = velx * 0.85
    if player.y < 63 / 2:
        player.y = 63 / 2
        vely = vely * 0.90
    if player.y > screen_height - 63 / 2 + 1:
        player.y = screen_height - 63 / 2 + 1
        vely = vely * 0.90
        velx = velx * 0.85
Rabbid76
  • 202,892
  • 27
  • 131
  • 174