3
votes

I'm in the process of making a simple game in pygame. Its looking to be a platformer RPG. But that is neither final or relevant per this question. So far i have very little functionality in the game. Its just a skeleton at this point if that. My question is kind of two fold:

  • Whats the best (in terms of performance and flexibility) way to add gravity to classes in pygame?
  • What are the best practices for adding gravity in general? For example, do you just simply do a "if keyPressed == k_W then subtract 2pixels per tick from player-y for 20 ticks" or something with velocity in the up or negative-y direction?

I've seen other posts on adding gravity to games after the fact, where adding it really wasn't thought about during initial development. I want to add it in as early as possible so instead of adding gravity to other things, i can add other things to gravity. I'm going to continue to read up on this, so if you prefer to point me in the direction of some online resources, I'd much appreciate that as well!

2

2 Answers

0
votes

Quick dislaimer: I do not know multiple ways to incorporate gravity, so I can not say which is "best". But, if you're fighting the performance battle in Python, you've probably fighting the wrong battle.

For gravity, you can use a vector system. Say a character jumps off the ground and has initial velocity of [5, -15] (negative y because positive y is down!), you can move your character's rect by this velocity every frame to simulate movement. To throw gravity into this, you need to add 9.8 to your y velocity component value every second. So 1 second in, the velocity will be about [5, -5]. This will have your character slow to a stop, and begin moving down.

For key pressed movement, I recommend using booleans. An example, upon pressing k_U , a variable that says you are moving up becomes True. Then, if this variable is True, you move him, say, [0, -5]. Upon keyup, set variable to false. Do this for north/east/south/west, and then you have a movement system in 4 directions, that moves you while you hold the key down.

0
votes

I used the 1/2 mg^2 equation in this code, which has a snow like effect:

import math, sys, random, time
import pygame, inputbox
from pygame.locals import *

class flake:

    def __init__(self, xpos, ypos, mass, color, drift):
        self.xpos = xpos
        self.ypos = ypos
        self.mass = mass
        self.rect = pygame.Rect(xpos, ypos, 2, 2)
        self.checked = False
        self.color = color
        self.drift = drift

size = width, height = 510, 700

BLACK = (0,0,0)
WHITE = (255, 255, 255)
GREY = (128,128,128)
DARKGREY = (169,169,169)
SILVER = (192,192,192)
LIGHTGREY = (211,211,211)
LIGHTESTGREY = (220,220,220)

pygame.init()     

screen = pygame.display.set_mode(size)
background = pygame.Surface(screen.get_size())
background = background.convert()
background.fill(BLACK)

def init():

    global theSnow, snowColours, clock, startrange

    theSnow = []
    snowColours = []

    snowColours.append(WHITE)
    snowColours.append(GREY)
    snowColours.append(DARKGREY)
    snowColours.append(SILVER)
    snowColours.append(LIGHTGREY)
    snowColours.append(LIGHTESTGREY)

    for c in range(2000):
        mass = 0.0
        mass = float(random.randint(1,8) / 100.0)
        xpos = random.randint(0,width)
        ypos = random.randint(0,5)
        ypos = -ypos
        drift = ypos/10.0

        colour = snowColours[random.randint(0,5)]

        f = flake(xpos, ypos, mass, colour, drift)
        theSnow.append(f)       
        print "flake x = " + str(f.xpos) + "   y = " + str(f.ypos) + "   mass = " + str(f.mass)             

    startrange = 200
    clock = pygame.time.Clock() 

def run():

    global theSnow, clock
    global startrange

    newrange = 0

    while True:
        events = pygame.event.get()
        for event in events:
            if event.type == pygame.QUIT:
                sys.exit()
        keys=pygame.key.get_pressed()

        if keys[K_q]:
            return

        g = 3

        for count in range(startrange):

            yinc = 0.0
            yuncertainty = float(random.randint(1,5)/10.0)
            yinc = float(0.5 * theSnow[count].mass * (g*g)) + yuncertainty
            theSnow[count].ypos += yinc

            xuncertainty = random.randint(1,10)
            if xuncertainty > 4:
                theSnow[count].xpos += theSnow[count].drift
            else:
                theSnow[count].xpos -= theSnow[count].drift

            theSnow[count].rect = pygame.Rect(theSnow[count].xpos, theSnow[count].ypos, 2,2)

            if not theSnow[count].checked:
                if theSnow[count].ypos > 30:
                    for c in range(newrange, startrange):
                        print " c= " + str(c)
                        theSnow[c].checked = True

                    if startrange < 2000:
                        startrange += 100
                        newrange = startrange - 100
                        print " newrange = " + str(newrange)
                        print " startrange = " + str(startrange)

        update()
        pygame.time.wait(10)
    #clock.tick(10)

def update():

    global theSnow, startrange
    background.fill(BLACK)

    for count in range(startrange):
        pygame.draw.rect(background, theSnow[count].color, theSnow[count].rect)

    screen.blit(background, (0, 0))
    pygame.display.flip()


if __name__ == "__main__":
    init()
    run()