photo1photo2 I'm making a game using pygame where the user controls a player using the mouse. To shoot you left click. I need a way of creating a basic sprite and make it drop from the top of the screen at an increasing rate
I have tried doing this, but when I spawn a sprite in a loop, it just spawns so rapidly that the user would not have time to shoot all of them.
Have tried inserting a time.sleep function, but that just slows the game down completely.
Any ideas on how to go about this would be much appreciated.
Thanks
I'm not familiar with pygame, but I'm assuming there is some sort of game loop or tick that happens every frame. If that is the case, you could use a persistent variable to keep track of the next spawn time, and write an updateSpawn() method that spawns the sprite when it is ready. Something like this:
def updateSpawn():
if currentTime > nextSpawnTime:
# Make the spawn rate faster
timeBetweenSpawns -= SPAWNRATE_SPEEDUP
# Update the next spawn time
nextSpawnTime = currentTime + timeBetweenSpawns
# Spawn the sprite
spawnSprite()
Related
I'm learning OpenCV and I decided to make a snake game using it. It's almost done but there is a slight problem that seems simple but I couldn't find a solution.
while True:
move()
cv2.imshow('Snake Game', frame)
cv2.waitKey(250)
It's supposed to wait 250 miliseconds before the next frame but key presses break the waiting so game speeds up when I hold down a key. How can I make it ignore the keyboard events and only use time?
I would be very surprised if waitKey didn't stop the waiting after key presses. In fact the name itself suggest that. So basically it's like calling a function called max and then expect the minimum.
From your code and what you've described, you're using waitKey for two reasons:
waiting for some fixed time. That means you're using it to synchronize your game loop.
using it (maybe) to handle key presses for user interaction with the game.
In my opinion, first thing to do is to stop waiting and just keep showing frames continuously as soon as it is ready. And for synchronization you just need to save time for each frame printing. And using that time you update after user interaction or deciding how to process frame or ... One place to help you in that is to look at how game loops are implemented.Take a look here : https://gamedev.stackexchange.com/questions/651/how-should-i-write-a-main-game-loop
I am working on a basic simulation in pyglet, which I need to re-run and visualise multiple times. The simulation adjusts the focus "f" of a lens until it reaches the desired location (see gif here https://imgur.com/Ui06B1c). I have put an instance of the simulation inside a for loop along with a pyglet.app.run() loop running inside it also, so that it can be reset and run for 10 episodes.
num_episodes=10
for i in range(num_episodes):
update_rate=1/59
simulation=PivotPointSimulation()
pyglet.clock.schedule_interval(update, update_rate)
pyglet.app.run()
I need to make an instance of the "simulation" so that the draw and update methods can be called by pyglet.app.run(). By making a new instance each loop, I can also reset the variables when the simulation starts again. I terminate the simulation when the focus "f" of the lens reaches the desired position with pyglet.app.exit().
The problem is each time the for loop iterates, the framerate of my pyglet application speeds up (see gif for example https://imgur.com/Ui06B1c). I have checked if the update_rate is changing and it is staying the same. Peculiarly enough, when I use spyders stop button to stop the code, and run the simulation again with "play" the framerate of the simulation also gets faster and faster each time I hit stop and play.
I am wondering if there is a way to properly terminate an app, so that each time it runs again it is reset fully? I am unsure if pyglet.app.exit() is resetting everything properly. But I am not sure how the app is speeding up, since pyglet.clock.schedule_interval(update, update_rate) should update at a constant update rate.
I have tried playing around with Vsync settings (setting from false to true) and it hasn't helped. I have also tried using pyglet.clock.set_fps_limit(60) to no avail. So I am not sure what is going on here.
Has anyone encountered this problem before?
Every time you call pyglet.clock.schedule_interval(update, update_rate), it adds the callback to be called at the rate.
So at the end of your loop of 10, you have the same callback scheduled ten times.
One way to prevent this is to unschedule the function before so that it isn't scheduled a second time:
num_episodes=10
for i in range(num_episodes):
update_rate=1/59
simulation=PivotPointSimulation()
pyglet.clock.unschedule(update)
pyglet.clock.schedule_interval(update, update_rate)
pyglet.app.run()
I want to draw a line, but not instantaneously as it usually appears with DrawLine(). I want it to be fast, but just slow enough that you can tell it's being drawn.
I've tried testing a for loop that draws a line a pixel at a time with a sleep of .05 seconds, but it doesn't seem to draw any of it until the for loop ends at which point it draws it all, instantly. I figured this had to do with it not getting drawing actions through the mainloop, so I used CallAfter on the drawline, that didn't work, either.
It seems like there should be a way to simply tell drawline to draw it over the course of x seconds or send it through an animation object in which you can specify # of frames, etc. Not really sure where to look. Any suggestions?
The issue is that time.sleep(...) will also block GUI as the for loop itself. wx.Yield should normally signal "GUI, I have halted the time-consuming process, do whatever you nned to do NOW". But by experience, this basically never works (I have not found out yet why).
So instead of using sleep you could use wx.CallLater (Link to wxPython Phoenix docs) which is like wx.CallAfter, but a delay can be specified. By calling it at the end of the inner for loop drawing the line part draw events should not pile up.
You will probably want to draw a series of lines. That would likely be the easiest. I would probably use a wx.Timer. It runs in it's own main loop. You can set up the timer to fire every so often, say every 0.5 second. When it fires, it can call your draw method, which will draw the next line. You can read more about timers here:
http://wiki.wxpython.org/Timer
http://www.blog.pythonlibrary.org/2009/08/25/wxpython-using-wx-timers/
http://www.wxpython.org/docs/api/wx.Timer-class.html
I'm using the pygame function pygame.time.delay() to make pygame freeze while presenting some pictures or text, and I want to play a sound at the same time.
The problem, I think, is that in order for pygame mixer to work the main loop must be running, so putting the system on wait it also stops the mixer.
Any easy way to solve this problem? thanks
pygame.time.delay() is a bad idea for waiting while presenting things, it not only will prevent you from playing music it can also freeze your screen (blank screen).
You should process events and update the display although you have static image.
Some alternatives are:
Use a counter in your loop to know how long you should keep the same image in the screen.
Use a timer to receive a User Event that will notify you that you need to change the current state.
I recently startet getting into pyglet and rabbyt from pygame, but I have hit something of a brick wall.
I created a basic example where one Sprite (of the type found in pyglet.sprite.Sprite) is displayed at 60 frames per second. The problem is that this simple program is using up 50% of the CPU time somehow. I repeated the experiment with the sprite type found in the rabbyt library with the same result.
I decided to render 1000, then 10 000 sprites at 60 frames per second, and to my surprise the CPU usage stays at 50%. The only thing is that moving or animating a sprite results in slight stuttering.
Lastly, I tried running at 360 frames per second. Same result, 50% usage.
Here is the sample code:
import pyglet
import rabbyt
def on_draw(dt):
window.clear()
spr.render()
global window
window = pyglet.window.Window(800, 600)
spr = rabbyt.Sprite('ship.png')
spr.x = 100
spr.y = 100
pyglet.clock.schedule_interval(on_draw, 1.0/60.0)
if __name__ == '__main__':
pyglet.app.run()
I am using a Core 2 Duo with an ATI HD 3500 card.
Any advice/ideas are appreciated.
Be aware that the default pyglet event handler will fire an 'on_draw' event every time it clears the event queue.
http://www.pyglet.org/doc/programming_guide/the_application_event_loop.html
The pyglet application event loop dispatches window events (such as for mouse and keyboard input) as they occur and dispatches the on_draw event to each window after every iteration through the loop.
This means that any event can trigger a redraw.
So if you're moving the mouse about or doing anything that fires events, you will get massive slow down as it begins to trigger render calls.
This also caused problems because I was doing my own render calls, so I would get the two buffers fighting which created a 'ghost' effect on the screen. Took me a while to realise this was the cause.
I monkey patched the event loop to not do this.
https://github.com/adamlwgriffiths/PyGLy/blob/master/pygly/monkey_patch.py
Be aware that this patched event loop will no longer render on it's own, you must manually flip the buffers or trigger an 'on_draw' event.
It might be the case that, although you've hooked in at 60fps, but the internal render loop is ticking at the maximum possible rate.
I dislike code that takes away control, hence my patch lets me decide when render events occur.
Hmm.. You might want to know the fps at which the game runs, if it helps:
cldis = pyglet.clock.ClockDisplay()
Then add this to your on_draw function:
cldis.draw()
it draws the current fps at the bottomleft corner of the screen in a semi-transparent color.
I know that in Pygame there is the built-in called "Clock". You can put a limit on how many times the game loops per second using the tick method. In my example I have put a limit of 30 FPS. This prevents your CPU being on constant demand.
clock = pygame.time.Clock()
While 1:
clock.tick(30) # Puts a limit of 30 frames per second on the loop
In pyglet there appears to be something similar:
pyglet.clock.schedule_interval(on_draw, 1.0/60.0)
clock.set_fps_limit(60)
Hope that helps!
edit: documentation on fps limit: http://pyglet.org/doc/api/pyglet.clock-module.html#set_fps_limit