So, my snake makes a continuous movement, but if I press any key it goes back in time and lags back and forward. Here is a video: https://youtu.be/KCesu5bGiS8
My guess would be to update the key input faster, but when I do that everything updates faster, so the snake goes faster etc.
Code (as requested in text form) here:
import pyglet import random pyglet.resource.path = ["resources"] pyglet.resource.reindex() # sets the resource path class Snake_Window(pyglet.window.Window): a = 0 dtx = 160 dty = 200 # sets the basic direction and snake body x and y def __init__(self): super(Snake_Window, self).__init__(width=1280, height=720) # sets resolution and inherits self.key_handler = pyglet.window.key.KeyStateHandler() self.push_handlers(self.key_handler) # sets keys self.set_caption("Wild Snake") # gives it a name self.background_image = pyglet.resource.image("background.png") self.food_image = pyglet.resource.image("food.png") self.snake_head_image = pyglet.resource.image("snake_head.png") self.snake_body_image = pyglet.resource.image("snake_body.png") # makes images usable self.center_image(self.food_image) self.center_image(self.snake_head_image) self.center_image(self.snake_body_image) # centers the images using center_image self.snake_head = pyglet.sprite.Sprite(img=self.snake_head_image, x=200, y=200) self.snake_head.scale = 0.1 self.snake_head.rotation = 270 # sets snake_head as a image on screen self.snake_body = pyglet.sprite.Sprite(img=self.snake_body_image, x=self.dtx, y=self.dty) self.snake_body.scale = 0.1 self.snake_body.rotation = 90 # sets snake_body as a image on screen self.background = pyglet.sprite.Sprite(img=self.background_image, x=0, y=0) # sets background as a image on screen self.food = [] # sets food pyglet.clock.schedule_interval(self.game_tick, 0.1) def center_image(self, image): # sets the center of the image to the actual center image.anchor_x = image.width / 2 image.anchor_y = image.height / 2 def update_snake_head(self): # makes the snake head go and sets the x and y for the body if self.a == 0: self.snake_head.x += 40 self.dtx = self.snake_head.x - 40 self.dty = self.snake_head.y elif self.a == 1: self.snake_head.x -= 40 self.dtx = self.snake_head.x + 40 self.dty = self.snake_head.y elif self.a == 2: self.snake_head.y += 40 self.dty = self.snake_head.y - 40 self.dtx = self.snake_head.x elif self.a == 3: self.snake_head.y -= 40 self.dty = self.snake_head.y + 40 self.dtx = self.snake_head.x def update_snake_body(self, dtx, dty): # makes the snakes body go self.snake_body.x = dtx self.snake_body.y = dty def game_tick(self, dt): # updates snakes head, snakes body, key presses and sets the background self.update_snake_head() self.update_snake_body(self.dtx, self.dty) self.draw_elements() self.key_press() print(dt) def draw_elements(self): # draws everything in window self.clear() self.background.draw() self.snake_head.draw() self.snake_body.draw() def key_press(self): # sets direction of snake upon key press and rotates his head accordingly if self.key_handler[pyglet.window.key.RIGHT]: if self.a == 1: pass else: self.a = 0 self.snake_head.rotation = 270 elif self.key_handler[pyglet.window.key.LEFT]: if self.a == 0: pass else: self.a = 1 self.snake_head.rotation = 90 elif self.key_handler[pyglet.window.key.UP]: if self.a == 3: pass else: self.a = 2 self.snake_head.rotation = 180 elif self.key_handler[pyglet.window.key.DOWN]: if self.a == 2: pass else: self.a = 3 self.snake_head.rotation = 0 game_window = Snake_Window() pyglet.app.run()
Advertisement
Answer
Converting all my comments into a answer instead. It won’t solve your problem completely. But due to lack of time, I’ll leave something useful at least that almost solves it.
The reason for these are a couple. One of them is that you use a scheduler to render stuff instead of using the built-in on_draw
event. Can’t say for sure, but a good guess is that the graphical buffer gets updated/flipped automatically in on_draw
while you’re doing your drawing and stuff in a side-chained render function. So moving all the rendering stuff into on_draw
makes sense.
Another issue is that you don’t trigger on the actual key press, but instead you need to time the key press to each tick in the scheduler you got going – which you also have mushed into the rendering function. Essentially you’re doing eventhandling+rendering+updating+IO in one cluster*** of a function, heh. Instead, you should rely on on_key_press
for keyboard events.
Lastly, you’re doing math operations all over the place – any of which might be half way done when you’re doing the actual rendering. That’s why you might get ghosting or odd artifacts (some things aren’t completely done updating positions etc).
But here is a almost working example of a few steps taken to get closer to what you want. If no one else (including you) haven’t solved this by a few days I’ll go ahead and re-write most of your code and point you in a few good directions (batches being one of them).
import pyglet import random pyglet.resource.path = ["resources"] pyglet.resource.reindex() # sets the resource path class Snake_Window(pyglet.window.Window): a = 0 dtx = 160 dty = 200 # sets the basic direction and snake body x and y def __init__(self): super(Snake_Window, self).__init__(width=1280, height=720) # sets resolution and inherits self.key_handler = pyglet.window.key.KeyStateHandler() self.push_handlers(self.key_handler) # sets keys self.set_caption("Wild Snake") # gives it a name self.background_image = pyglet.resource.image("background.png") self.food_image = pyglet.resource.image("food.png") self.snake_head_image = pyglet.resource.image("snake_head.png") self.snake_body_image = pyglet.resource.image("snake_body.png") # makes images usable self.center_image(self.food_image) self.center_image(self.snake_head_image) self.center_image(self.snake_body_image) # centers the images using center_image self.snake_head = pyglet.sprite.Sprite(img=self.snake_head_image, x=200, y=200) self.snake_head.rotation = 270 # sets snake_head as a image on screen self.snake_body = pyglet.sprite.Sprite(img=self.snake_body_image, x=self.dtx, y=self.dty) self.snake_body.scale = 0.1 self.snake_body.rotation = 90 # sets snake_body as a image on screen self.background = pyglet.sprite.Sprite(img=self.background_image, x=0, y=0) # sets background as a image on screen self.food = [] # sets food pyglet.clock.schedule_interval(self.game_tick, 0.1) def on_draw(self): self.draw_elements() def center_image(self, image): # sets the center of the image to the actual center image.anchor_x = image.width / 2 image.anchor_y = image.height / 2 def update_snake_head(self): # makes the snake head go and sets the x and y for the body if self.a == 0: self.snake_head.x += 40 self.dtx = self.snake_head.x - 40 self.dty = self.snake_head.y elif self.a == 1: self.snake_head.x -= 40 self.dtx = self.snake_head.x + 40 self.dty = self.snake_head.y elif self.a == 2: self.snake_head.y += 40 self.dty = self.snake_head.y - 40 self.dtx = self.snake_head.x elif self.a == 3: self.snake_head.y -= 40 self.dty = self.snake_head.y + 40 self.dtx = self.snake_head.x def update_snake_body(self, dtx, dty): # makes the snakes body go self.snake_body.x = dtx self.snake_body.y = dty def game_tick(self, dt): # updates snakes head, snakes body, key presses and sets the background self.update_snake_head() self.update_snake_body(self.dtx, self.dty) def draw_elements(self): # draws everything in window self.clear() self.background.draw() print('Head:', self.snake_head.x, self.snake_head.y, {0:'Right', 1:'Left', 2: 'Up', 3:'Down'}[self.a]) self.snake_head.draw() self.snake_body.draw() self.flip() def on_key_press(self, symbol, modifier): # sets direction of snake upon key press and rotates his head accordingly if symbol == pyglet.window.key.ESCAPE: pyglet.app.exit() if symbol == pyglet.window.key.SPACE: print('Here') if symbol == pyglet.window.key.RIGHT: if self.a == 1: pass else: self.a = 0 self.snake_head.rotation = 270 elif symbol == pyglet.window.key.LEFT: if self.a == 0: pass else: self.a = 1 self.snake_head.rotation = 90 elif symbol == pyglet.window.key.UP: if self.a == 3: pass else: self.a = 2 self.snake_head.rotation = 180 elif symbol == pyglet.window.key.DOWN: if self.a == 2: pass else: self.a = 3 self.snake_head.rotation = 0 game_window = Snake_Window() pyglet.app.run()
I’ll leave you not only with this ish-working code, but a good advice.
Stop asking so many questions, and start learn ways to debug why things are happening the way they do. You’re shooting in the dark right now, asking questions hoping someone will solve the problems for you so you can focus on the fun stuff – which is the game development itself.
But what you’ll have a lot of use for later in life – is finding ways to debug, probe, understand and pinpoint why things are or aren’t happening the way you want.
Put some print("moo")
here and there, print some values, add logging/debugging all over the place until you get wiser. It’s not always efficient, but it got me to this point with your code.