So I have a problem with pygame. I am running Python 3.5-32 bit with Pygame 1.9ish on two Windows 10 computers. On the modern highspeed i7, if I try to run my code at 60fps, it runs stable and at consistent speed. However, if I run it on my Core2Duo which is a bit older, it runs stable at 60FPS... for about 15 seconds, before dropping down to 45 and stuttering. However, if I increase FPS to 120 on the Core2Duo it runs consistently and fine. But running with it set around 60 or 70, the FPS suddenly drops after 15 seconds.
I can't seem to explain why this is. I've already switched to using clock.tick_busy_loop(60) instead of clock.tick(60) because that was unreliable on all computers.
Any pointers? I don't see why it runs fine and stable on one machine, and loses speed after 15 seconds on the other.
#! /usr/bin/env python
"""
Modified from example by Sean J. McKiernan 'Mekire'
"""
import os
import sys
import random
import math
import ctypes #to fix stupid Windows fullscreen issue
import pygame as pg
CAPTION = "Drag the Red Square"
SCREEN_WIDTH=1920
SCREEN_HEIGHT=1020
SCREEN_SIZE = (SCREEN_WIDTH,SCREEN_HEIGHT)
GRAVITY=0.1
PI=math.pi
class Planet(object):
"""
A class to represent our lovable purple planets.
"""
def __init__(self):
"""
DEPRECATED: The argument pos corresponds to the center of our rectangle.
"""
self.xPos=random.randint(0,SCREEN_WIDTH)
self.yPos=random.randint(0,SCREEN_HEIGHT)
self.densityFloat=random.uniform(1,2)
self.radiusFloat=random.uniform(25,100)
self.massFloat=GRAVITY*2.0*(self.radiusFloat**2)*self.densityFloat
self.text, self.text_rect = self.setup_font()
self.radius=int(self.radiusFloat)
self.planetSurface=pg.Surface((SCREEN_WIDTH,SCREEN_HEIGHT))
#self.planetSurface.set_colorkey((0,0,0), pg.RLEACCEL)
self.planetSurface.fill((255,0,0))
self.circleDude, self.circleDude_rect=self.setup_circle()
self.newX=0
self.displacement=0
self.playerSpeed=0.005
def setup_font(self):
font = pg.font.SysFont('timesnewroman',30)
message = "x-position: " + str(self.xPos) + " radiusFloat: " + str(round(self.radiusFloat,3))
label = font.render(message,True, pg.Color("white"))
label_rect = label.get_rect()
return label, label_rect
def setup_circle(self):
circle = pg.Surface((self.radius*2,self.radius*2))
circle_rect = circle.get_rect()
circle.fill((255,255,0))
pg.draw.circle(circle, pg.Color("white"), (self.radius,self.radius),self.radius, 0)
circle.set_colorkey((0,0,0), pg.RLEACCEL)
return circle, circle_rect
def draw(self, surface, fpsMillis):
"""
Blit image and text to the target surface.
"""
timedelta=fpsMillis/1000.0
localfont = pg.font.SysFont('timesnewroman',30)
fontobj=localfont.render(str(timedelta),True,pg.Color("red"))
#surface.blit(self.text,(0,0))
#surface.blit(self.planetSurface,(0,0))
surface.blit(fontobj,(500,500))
#surface.blit(self.circleDude,(self.newX,self.yPos))
self.circleDude_rect.center = self.newX, self.yPos
self.circleDude_rect.center=(self.newX,self.yPos)
#self.newX += 50*timedelta
class App(object):
"""
A class to manage our event, game loop, and overall program flow.
"""
def __init__(self):
"""
Get a reference to the screen (created in main); define necessary
attributes; and create our player (draggable rect).
"""
self.screen = pg.display.get_surface()
self.screen_rect = self.screen.get_rect()
self.clock = pg.time.Clock()
self.fps = 120
self.done = False
self.keys = pg.key.get_pressed()
self.planetOne = Planet()
self.frameMilliseconds = 1
def event_loop(self):
"""
This is the event loop for the whole program.
Regardless of the complexity of a program, there should never be a need
to have more than one event loop.
"""
for event in pg.event.get():
if event.type == pg.QUIT or self.keys[pg.K_ESCAPE]:
self.done = True
elif event.type == pg.MOUSEBUTTONDOWN and event.button == 1:
self.player.check_click(event.pos)
elif event.type == pg.MOUSEBUTTONUP and event.button == 1:
self.player.click = False
elif event.type in (pg.KEYUP, pg.KEYDOWN):
self.keys = pg.key.get_pressed()
def render(self):
"""
All drawing should be found here.
This is the only place that pygame.display.update() should be found.
"""
self.screen.fill(pg.Color("black"))
self.planetOne.draw(self.screen,self.frameMilliseconds)
pg.display.update()
def main_loop(self):
"""
This is the game loop for the entire program.
Like the event_loop, there should not be more than one game_loop.
"""
while not self.done:
self.event_loop()
self.render()
self.frameMilliseconds=self.clock.tick_busy_loop(self.fps)
def main():
"""
Prepare our environment, create a display, and start the program.
"""
os.environ['SDL_VIDEO_CENTERED'] = '1'
pg.init() #run init routines. duh.
pg.display.set_caption(CAPTION) #Set window caption to something dank, homie
ctypes.windll.user32.SetProcessDPIAware() #STUPID windows is a pain in the ainairse - dpi scaling wrecks python
pg.display.set_mode((SCREEN_WIDTH,SCREEN_HEIGHT),pg.FULLSCREEN) #Set display mood, wait, I mean mode. Mode.
App().main_loop() #get into main loop.
pg.quit() #quit pygame library, because that's a requirement apparently.
sys.exit() #quit code.
if __name__ == "__main__":
main()