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.