Posts: 18 Threads: 1 Joined: Oct 2017 Reputation: 0 Likes received: 0 Nov-13-2017, 07:23 PM (This post was last modified: Nov-13-2017, 07:38 PM by hammza. Edited 1 time in total.) (Nov-13-2017, 01:46 PM)heiner55 Wrote: This needs big changes. A class for the ship and a class for the bullet. Each class take care of the position x and y and has a draw/update function. Then you need a function which is called every 1/100s. This function calls all updates functions from your ship and from many bullets. You should google for ping pong. If you understand ping pong, you can also code your game. See https://gist.github.com/calebrob6/4022622 Thank for your advice (Nov-13-2017, 05:16 PM)Windspar Wrote: here an example import tkinter as tk
SCREEN = 600, 400
class Bullet:
def __init__(self, canvas, x, y, tk_fill, movement):
self.bullet = canvas.create_oval(x -3 , y - 3, x + 3, y + 3, fill=tk_fill)
self.movement = movement
def move(self, canvas):
canvas.move(self.bullet, self.movement[0], self.movement[1])
class App(tk.Frame):
def __init__(self, master):
# put canvas in frame so you can have other goodies
tk.Frame.__init__(self, master)
self.pack()
self.canvas = tk.Canvas(self, width=SCREEN[0], height=SCREEN[1])
self.canvas.pack()
self.bullets = []# store bullets
self.tick_loop() # start the tick loop
self.ship = self.create_ship(300, 370, "blue")
master.bind("<Left>", self.go_left)
master.bind("<Right>", self.go_right)
master.bind("<Up>", self.go_up)
master.bind("<Down>", self.go_down)
master.bind("<space>", self.space_key)
def create_ship(self, x, y, tk_fill):
return self.canvas.create_polygon(x, y, x - 20, y + 30, x + 20, y + 30, fill=tk_fill)
def tick_loop(self):
remove_list =
for enum, bullet in enumerate(self.bullets):
if self.canvas.coords(bullet.bullet)[1] < 0:
remove_list.append(enum)
self.canvas.delete(bullet.bullet)
else:
bullet.move(self.canvas)
for index in remove_list:
self.bullets.pop(index)
# framerate per seconds 1000/30 = 30 frames roughly
self.after(int(1000/30), self.tick_loop)
def go_left(self, event):
self.canvas.move(self.ship, -5, 0)
self.canvas.update()
def go_right(self, event):
self.canvas.move(self.ship, 5, 0)
self.canvas.update()
def go_up(self, event):
self.canvas.move(self.ship, 0, -5)
self.canvas.update()
def go_down(self, event):
self.canvas.move(self.ship, 0, 5)
self.canvas.update()
def space_key(self, event=0):
# only want the first two coords
x, y = self.canvas.coords(self.ship)[:2]
# just having shoot straight up
self.bullets.append(Bullet(self.canvas, x, y, "blue", (0, -10)))
def main():
root = tk.Tk()
app = App(root)
app.mainloop()
if __name__ == '__main__':
main() Don't like how keypress working but here it is. Would be easier in pygame or pysfml. fix poping bug. popping bug so far has no effect on above good. Just added little more stuff. import tkinter as tk
SCREEN = 600, 400
class Bullet:
def __init__(self, canvas, x, y, tk_fill, movement):
self.bullet = canvas.create_oval(x -3 , y - 3, x + 3, y + 3, fill=tk_fill)
self.movement = movement
def move(self, canvas):
canvas.move(self.bullet, self.movement[0], self.movement[1])
class App(tk.Frame):
def __init__(self, master):
# put canvas in frame so you can have other goodies
tk.Frame.__init__(self, master)
self.pack()
self.canvas = tk.Canvas(self, width=SCREEN[0], height=SCREEN[1])
self.canvas.pack()
self.bullets = [] # store bullets
self.tick_loop() # start the tick loop
self.ship = self.create_ship(300, 370, "blue")
master.bind("<Left>", self.go_left)
master.bind("<Right>", self.go_right)
master.bind("<Up>", self.go_up)
master.bind("<Down>", self.go_down)
master.bind("<space>", self.space_key)
master.bind("<b>", self.go_b)
master.bind("<v>", self.go_v)
def create_ship(self, x, y, tk_fill):
return self.canvas.create_polygon(x, y, x - 20, y + 30, x + 20, y + 30, fill=tk_fill)
def tick_loop(self):
remove_list = []
for enum, bullet in enumerate(self.bullets):
coords = self.canvas.coords(bullet.bullet)
if coords[1] < 0 or coords[0] < 0 or coords[2] > SCREEN[0]:
remove_list.append(enum)
self.canvas.delete(bullet.bullet)
else:
bullet.move(self.canvas)
# fix poping bug
for enum, index in enumerate(remove_list):
self.bullets.pop(index - enum)
# framerate per seconds 1000/30 = 30 frames roughly
self.after(int(1000/30), self.tick_loop)
def go_left(self, event):
self.canvas.move(self.ship, -5, 0)
self.canvas.update()
def go_right(self, event):
self.canvas.move(self.ship, 5, 0)
self.canvas.update()
def go_up(self, event):
self.canvas.move(self.ship, 0, -5)
self.canvas.update()
def go_down(self, event):
self.canvas.move(self.ship, 0, 5)
self.canvas.update()
def space_key(self, event=0):
# only want the first two coords
x, y = self.canvas.coords(self.ship)[:2]
# just having shoot straight up
self.bullets.append(Bullet(self.canvas, x, y, "blue", (0, -10)))
# spread shooting
def go_b(self, event):
# only want the first two coords
x, y = self.canvas.coords(self.ship)[:2]
#up
self.bullets.append(Bullet(self.canvas, x, y, "red", (0, -8)))
#left
self.bullets.append(Bullet(self.canvas, x, y, "red", (-8, 0)))
#right
self.bullets.append(Bullet(self.canvas, x, y, "red", (8, 0)))
# triple shoot striaght up
def go_v(self, event):
# only want the first two coords
x, y = self.canvas.coords(self.ship)[:2]
#up
self.bullets.append(Bullet(self.canvas, x, y, "green", (0, -5)))
self.bullets.append(Bullet(self.canvas, x - 50, y, "green", (0, -5)))
self.bullets.append(Bullet(self.canvas, x + 50, y, "green", (0, -5)))
def main():
root = tk.Tk()
app = App(root)
app.mainloop()
if __name__ == '__main__':
main() That's a great help from you, thank you very much for the codes Please can you tell me where did learned all this, or do you know any tutorials or books that help begginers to reach this advanced levels. (Nov-13-2017, 01:01 PM)metulburr Wrote: Quote:What i want is how to make it shoot like (space invaders), I don't know how to use coords, and I didn't found any good tutorial or explanation. Thats because no one uses tkinter to make games. There is a better library to handle that kind of software and it called pygame. In fact, we have a tutorial on how to make a ship shoot like space invaders on this forum. Tkinter is a GUI library mainly for building window form apps. Thank you for your advice I know about pygame, but I don't want to use it I want to learn how to use pure python with less libraries, just the important ones like tkinter canvas and built in functions. I want to learn how to make games just like old style was, with functions. Posts: 3,117 Threads: 205 Joined: Sep 2016 Reputation: 70 Likes received: 790 Nov-13-2017, 08:52 PM (This post was last modified: Nov-13-2017, 08:53 PM by metulburr. Edited 1 time in total.) Quote:I want to learn how to use pure python with less libraries You are actually not using pure python as tkinter is not apart of the standard library. Only Windows comes packaged with tkinter and you can even opt out of installing it in the python installer. Linux you have to install it like any other 3rd party lib. If you compile python on windows, tkinter is not apart of it. The first paragraph briefly explains this https://docs.python.org/3.6/library/tkinter.html So you are already using a 3rd party module. Its just the build you installed, already has that 3rd party library with it. Posts: 217 Threads: 11 Joined: Oct 2016 Reputation: 9 Likes received: 28 Nov-13-2017, 09:11 PM (This post was last modified: Nov-13-2017, 09:37 PM by Windspar. Edited 2 times in total.) Quote:I want to learn how to make games just like old style was, with functions. Almost all program language have some type of structures. Python and old style is not going to work. Python has built in polymorph. Almost all python is object base. An modern programming helps reduce size of code. Take classes. Add a namespace to object and create many different objects quickly. Methods are just function wrap in a class. You always could check out assembly code for old programming. linux nasm assembly example Quote:; nasm hello asm ; nasm -f elf hello.asm ; ld -m elf_i386 hello.o -o hello SECTION .data msg db 'Hello World!', 0Ah msg2 db 'Hello, brave new world!', 0Ah SECTION .text global _start _start: mov edx, 13 mov ecx, msg mov ebx, 1 ; stdout mov eax, 4 ; system write int 80h mov ebx, msg2 mov eax, ebx ; count char in string nextchar: cmp byte [eax], 0 jz finished inc eax jmp nextchar finished: sub eax, ebx mov edx, eax mov ecx, msg2 mov ebx, 1 ; stdout mov eax, 4 ; system write int 80h ; exit call mov ebx, 0 mov eax, 1 int 80h in python print("Hello World!")
print("Hello, brave new world!") Quote:Please can you tell me where did learned all this, or do you know any tutorials or books that help begginers to reach this advanced levels. I learn by making little programs. Testing one thing to death. learn by runtime errors. using print(dir(on object)) to see there variables and methods and builtins read docs and code There is no magic formula to making programs. nothing but commands and pushing and altering numbers around. strings are nothing but numbers. I don't call this advance stuff. Just basic python. 99 percent of computer problems exists between chair and keyboard. Posts: 303 Threads: 2 Joined: Nov 2016 Reputation: 14 Likes received: 15 Posts: 217 Threads: 11 Joined: Oct 2016 Reputation: 9 Likes received: 28 Found no solution to tkinter annoying keypress. Just compare tkinter vs pysfml. Here pysfml example. I would recommend pygame because of better docs. from sfml import sf
class Bullet:
def __init__(self, x, y, color, movement):
self.bullet = sf.CircleShape(3, 18)
self.bullet.position = x, y
self.bullet.fill_color = color
self.movement = movement
def move(self, speed):
vector = (self.movement[0] * speed + self.bullet.position.x,
self.movement[1] * speed + self.bullet.position.y)
self.bullet.position = vector
class App:
def __init__(self):
self.window = sf.RenderWindow(sf.VideoMode(600, 400), "Invaders")
self.bullets = []
self.create_ship(300, 370, sf.Color(0,0,200))
def create_ship(self, x, y, color):
self.ship = sf.ConvexShape(3)
self.ship.set_point(0, (0, 0))
self.ship.set_point(1, (-20, 30))
self.ship.set_point(2, ( 20, 30))
self.ship.fill_color = color
self.ship.position = x, y
def loop(self):
clock = sf.Clock()
bullet_clock = sf.Clock()
while self.window.is_open:
for event in self.window.events:
if event.type == sf.Event.CLOSED:
self.window.close()
elif event.type == sf.Event.KEY_PRESSED:
if sf.Keyboard.is_key_pressed(sf.Keyboard.ESCAPE):
self.window.close()
# create bullets
if sf.Keyboard.is_key_pressed(sf.Keyboard.SPACE):
# keeps bullet at steady intervals
if bullet_clock.elapsed_time.milliseconds > 300:
bullet_clock.restart()
vector = self.ship.position
self.bullets.append(Bullet(vector.x, vector.y, sf.Color(0,0,200), (0,-2)))
# movement, speed keeps movement steady
speed = 100 * clock.elapsed_time.seconds
if sf.Keyboard.is_key_pressed(sf.Keyboard.LEFT):
self.ship.move((-speed, 0))
elif sf.Keyboard.is_key_pressed(sf.Keyboard.RIGHT):
self.ship.move((speed, 0))
elif sf.Keyboard.is_key_pressed(sf.Keyboard.UP):
self.ship.move((0, -speed))
elif sf.Keyboard.is_key_pressed(sf.Keyboard.DOWN):
self.ship.move((0, speed))
self.window.clear()
# draw bullets
bullet_remove = []
for enum, bullet in enumerate(self.bullets):
if bullet.bullet.position.y < 0:
bullet_remove.append(enum)
else:
bullet.move(speed)
self.window.draw(bullet.bullet)
for enum, index in enumerate(bullet_remove):
self.bullets.pop(index - enum)
self.window.draw(self.ship)
self.window.display()
clock.restart()
sf.sleep(sf.milliseconds(5))
def main():
app = App()
app.loop()
if __name__ == '__main__':
main() 99 percent of computer problems exists between chair and keyboard. Posts: 217 Threads: 11 Joined: Oct 2016 Reputation: 9 Likes received: 28 here a pygame example import pygame
pygame.init()
SCREEN = 600, 400
class Bullet:
def __init__(self, x, y, color, movement):
self.position = [x - movement[0], y - movement[1]]
self.color = color
self.movement = movement
def blit(self, surface):
self.position[0] += self.movement[0]
self.position[1] += self.movement[1]
position = int(self.position[0]), int(self.position[1])
pygame.draw.circle(surface, self.color, position, 3)
class Ship:
def __init__(self, x, y, color, pointlist):
self.position = [x, y]
self.pointlist = pointlist
self.color = color
def move(self, x, y):
self.position[0] += x
self.position[1] += y
def blit(self, surface):
points = []
for point in self.pointlist:
points.append((self.position[0] + point[0], self.position[1] + point[1]))
pygame.draw.polygon(surface, self.color, points)
class Pauser:
def __init__(self, length):
self.length = length
self.last_tick = 0
def elaspe(self, ticks):
if ticks > self.last_tick + self.length:
self.last_tick = ticks
return True
return False
class App:
def __init__(self):
pygame.display.set_caption("Invaders")
# create are screen. Your main surface
self.screen = pygame.display.set_mode(SCREEN)
# create a clock for framerate control
self.clock = pygame.time.Clock()
self.bullets = []
self.bullets_pauser = Pauser(300)
self.ship = Ship(300, 370, (0,0,200), ((0,0), (-20,30), (20,30)))
def loop(self):
running = True
self.ticks = 0
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
running = False
last_ticks = self.ticks
self.ticks = pygame.time.get_ticks()
speed = (self.ticks - last_ticks) * 0.05
# grab all keys return True if pressed
key_press = pygame.key.get_pressed()
# creaate bullets
if key_press[pygame.K_SPACE]:
# shoot bullets in intervals
if self.bullets_pauser.elaspe(self.ticks):
x, y = self.ship.position
self.bullets.append(Bullet(x, y, (0,0,200), (0,-10)))
# ship movement
ship_speed = speed * 3
if key_press[pygame.K_LEFT]:
self.ship.move(-ship_speed, 0)
elif key_press[pygame.K_RIGHT]:
self.ship.move(ship_speed, 0)
elif key_press[pygame.K_UP]:
self.ship.move(0, -ship_speed)
elif key_press[pygame.K_DOWN]:
self.ship.move(0, ship_speed)
# clear screen
self.screen.fill((0,0,0))
# blits bullets
remove_list = []
for enum, bullet in enumerate(self.bullets):
if bullet.position[1] < 0:
remove_list.append(enum)
else:
bullet.blit(self.screen)
for enum, index in enumerate(remove_list):
self.bullets.pop(index - enum)
self.ship.blit(self.screen)
pygame.display.flip()
# frame per seconds
self.clock.tick(30)
def main():
app = App()
app.loop()
pygame.quit()
if __name__ == '__main__':
main() 99 percent of computer problems exists between chair and keyboard. Posts: 3,117 Threads: 205 Joined: Sep 2016 Reputation: 70 Likes received: 790 Nov-14-2017, 09:23 PM (This post was last modified: Nov-14-2017, 09:24 PM by metulburr. Edited 1 time in total.) if you remove the elif, to have all if, you can do two angles at the same time making it more "natural" feeling (Nov-14-2017, 08:40 PM)Windspar Wrote: here a pygame example import pygame
pygame.init()
SCREEN = 600, 400
class Bullet:
def __init__(self, x, y, color, movement):
self.position = [x - movement[0], y - movement[1]]
self.color = color
self.movement = movement
def blit(self, surface):
self.position[0] += self.movement[0]
self.position[1] += self.movement[1]
position = int(self.position[0]), int(self.position[1])
pygame.draw.circle(surface, self.color, position, 3)
class Ship:
def __init__(self, x, y, color, pointlist):
self.position = [x, y]
self.pointlist = pointlist
self.color = color
def move(self, x, y):
self.position[0] += x
self.position[1] += y
def blit(self, surface):
points = []
for point in self.pointlist:
points.append((self.position[0] + point[0], self.position[1] + point[1]))
pygame.draw.polygon(surface, self.color, points)
class Pauser:
def __init__(self, length):
self.length = length
self.last_tick = 0
def elaspe(self, ticks):
if ticks > self.last_tick + self.length:
self.last_tick = ticks
return True
return False
class App:
def __init__(self):
pygame.display.set_caption("Invaders")
# create are screen. Your main surface
self.screen = pygame.display.set_mode(SCREEN)
# create a clock for framerate control
self.clock = pygame.time.Clock()
self.bullets = []
self.bullets_pauser = Pauser(300)
self.ship = Ship(300, 370, (0,0,200), ((0,0), (-20,30), (20,30)))
def loop(self):
running = True
self.ticks = 0
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
running = False
last_ticks = self.ticks
self.ticks = pygame.time.get_ticks()
speed = (self.ticks - last_ticks) * 0.05
# grab all keys return True if pressed
key_press = pygame.key.get_pressed()
# creaate bullets
if key_press[pygame.K_SPACE]:
# shoot bullets in intervals
if self.bullets_pauser.elaspe(self.ticks):
x, y = self.ship.position
self.bullets.append(Bullet(x, y, (0,0,200), (0,-10)))
# ship movement
ship_speed = speed * 3
if key_press[pygame.K_LEFT]:
self.ship.move(-ship_speed, 0)
if key_press[pygame.K_RIGHT]:
self.ship.move(ship_speed, 0)
if key_press[pygame.K_UP]:
self.ship.move(0, -ship_speed)
if key_press[pygame.K_DOWN]:
self.ship.move(0, ship_speed)
# clear screen
self.screen.fill((0,0,0))
# blits bullets
remove_list = []
for enum, bullet in enumerate(self.bullets):
if bullet.position[1] < 0:
remove_list.append(enum)
else:
bullet.blit(self.screen)
for enum, index in enumerate(remove_list):
self.bullets.pop(index - enum)
self.ship.blit(self.screen)
pygame.display.flip()
# frame per seconds
self.clock.tick(30)
def main():
app = App()
app.loop()
pygame.quit()
if __name__ == '__main__':
main() Posts: 217 Threads: 11 Joined: Oct 2016 Reputation: 9 Likes received: 28 @metulburr yeah for some reason i thought showing how it works in tkinter would be better. Instead showing what possible with pygame and pysfml. Still looking for a way to do it in tkinter. If there one. Unless it a linux side problem. @hammza Hope this help to show you has basic this is. Added more comments. Anything you think is still advanced let me know. I show you how basic it is. import tkinter as tk
# this makes a tuple (600, 400). tuples can be index
SCREEN = 600, 400
# Object
class Bullet:
# movement takes a tuple (x, y)
def __init__(self, canvas, x, y, tk_fill, movement):
self.bullet = canvas.create_oval(x -3 , y - 3, x + 3, y + 3, fill=tk_fill)
self.movement = movement
#object method. self refers to object
def move(self, canvas):
canvas.move(self.bullet, self.movement[0], self.movement[1])
class App(tk.Frame):
def __init__(self, master):
# put canvas in frame so you can have other goodies
# this is from inheriting tk.Frame and calls __init__.
# so the App gains all variables and methods from tk.Frame
tk.Frame.__init__(self, master)
self.pack()
# self.canvas is an object variable
self.canvas = tk.Canvas(self, width=SCREEN[0], height=SCREEN[1])
self.canvas.pack()
# just a python list
self.bullets = [] # store bullets
# calls method. App.tick_loop(object)
self.tick_loop() # start the tick loop
# calls method. object.ship = App.create_ship(object, 300, 370, "blue")
self.ship = self.create_ship(300, 370, "blue")
master.bind("<Left>", self.go_left)
master.bind("<Right>", self.go_right)
master.bind("<Up>", self.go_up)
master.bind("<Down>", self.go_down)
master.bind("<space>", self.space_key)
master.bind("<b>", self.go_b)
master.bind("<v>", self.go_v)
def create_ship(self, x, y, tk_fill):
return self.canvas.create_polygon(x, y, x - 20, y + 30, x + 20, y + 30, fill=tk_fill)
def tick_loop(self):
remove_list = []
# upacking iterable [(0, object(Bullet)), (1, object(Bullet)), etc]
for enum, bullet in enumerate(self.bullets):
coords = self.canvas.coords(bullet.bullet)
if coords[1] < 0 or coords[0] < 0 or coords[2] > SCREEN[0]:
remove_list.append(enum)
self.canvas.delete(bullet.bullet)
else:
bullet.move(self.canvas)
# fix popping bug
for enum, index in enumerate(remove_list):
self.bullets.pop(index - enum)
# framerate per seconds 1000/30 = 30 frames roughly
self.after(int(1000/30), self.tick_loop)
def go_left(self, event):
self.canvas.move(self.ship, -5, 0)
self.canvas.update()
def go_right(self, event):
self.canvas.move(self.ship, 5, 0)
self.canvas.update()
def go_up(self, event):
self.canvas.move(self.ship, 0, -5)
self.canvas.update()
def go_down(self, event):
self.canvas.move(self.ship, 0, 5)
self.canvas.update()
def space_key(self, event=0):
# only want the first two coords
x, y = self.canvas.coords(self.ship)[:2]
# just having shoot straight up
self.bullets.append(Bullet(self.canvas, x, y, "blue", (0, -10)))
# spread shooting
def go_b(self, event):
# only want the first two coords
x, y = self.canvas.coords(self.ship)[:2]
#up
self.bullets.append(Bullet(self.canvas, x, y, "red", (0, -8)))
#left
self.bullets.append(Bullet(self.canvas, x, y, "red", (-8, 0)))
#right
self.bullets.append(Bullet(self.canvas, x, y, "red", (8, 0)))
# triple shoot striaght up
def go_v(self, event):
# only want the first two coords
x, y = self.canvas.coords(self.ship)[:2]
#up
self.bullets.append(Bullet(self.canvas, x, y, "green", (0, -5)))
self.bullets.append(Bullet(self.canvas, x - 50, y, "green", (0, -5)))
self.bullets.append(Bullet(self.canvas, x + 50, y, "green", (0, -5)))
def main():
root = tk.Tk()
app = App(root)
app.mainloop()
# __name__ only equals '__main__' if it is execute
# if import then it equals module name
if __name__ == '__main__':
main() 99 percent of computer problems exists between chair and keyboard. Posts: 217 Threads: 11 Joined: Oct 2016 Reputation: 9 Likes received: 28 Nov-18-2017, 02:50 AM (This post was last modified: Nov-18-2017, 02:54 AM by Windspar. Edited 1 time in total.) Okay figure out how to make tkinter keypress work smoothly. Enjoy! import tkinter as tk
# this makes a tuple (600, 400). tuples can be index
SCREEN = 600, 400
class Pauser:
def __init__(self, length):
self.length = length
self.last_tick = 0
def elaspe(self, ticks):
if ticks > self.last_tick + self.length:
self.last_tick = ticks
return True
return False
def update(self, ticks):
self.last_tick = ticks
# Object
class Bullet:
# movement takes a tuple (x, y)
def __init__(self, canvas, x, y, tk_fill, movement):
self.bullet = canvas.create_oval(x -3 , y - 3, x + 3, y + 3, fill=tk_fill)
self.movement = movement
#object method. self refers to object
def move(self, canvas):
canvas.move(self.bullet, self.movement[0], self.movement[1])
class App(tk.Frame):
def __init__(self, master):
# put canvas in frame so you can have other goodies
# this is from inheriting tk.Frame and calls __init__.
# so the App gains all variables and methods from tk.Frame
tk.Frame.__init__(self, master)
self.pack()
# self.canvas is an object variable
self.canvas = tk.Canvas(self, width=SCREEN[0], height=SCREEN[1])
self.canvas.pack()
# just a python list
self.bullets = # store bullets
# how fast a bullet can shoot
self.shoot_pauser = Pauser(12)
self.triple_pauser = Pauser(30)
self.spread_pauser = Pauser(25)
# storing keys to dict
self.keys_press = {}
# need to slow shooting
self.ticks = 0
# calls method. object.ship = App.create_ship(object, 300, 370, "blue")
self.ship = self.create_ship(300, 370, "blue")
self.speed = 5
# calls method. App.tick_loop(object)
self.tick_loop() # start the tick loop
print("Keys Press:", self.keys_press)
self.bind_all('<KeyPress>', self.go_press)
self.bind_all('<KeyRelease>', self.go_release)
def create_ship(self, x, y, tk_fill):
return self.canvas.create_polygon(x, y, x - 20, y + 30, x + 20, y + 30, fill=tk_fill)
def tick_loop(self):
remove_list =
# upacking iterable [(0, object(Bullet)), (1, object(Bullet)), etc]
for enum, bullet in enumerate(self.bullets):
coords = self.canvas.coords(bullet.bullet)
if coords[1] < 0 or coords[0] < 0 or coords[2] > SCREEN[0]:
remove_list.append(enum)
self.canvas.delete(bullet.bullet)
else:
bullet.move(self.canvas)
# NEW moving player
if self.keys_press.get('Left', False):
self.canvas.move(self.ship, -self.speed, 0)
if self.keys_press.get('Right', False):
self.canvas.move(self.ship, self.speed, 0)
if self.keys_press.get('Up', False):
self.canvas.move(self.ship, 0, -self.speed)
if self.keys_press.get('Down', False):
self.canvas.move(self.ship, 0, self.speed)
if self.keys_press.get('space', False):
if self.shoot_pauser.elaspe(self.ticks):
self.spread_pauser.update(self.ticks)
self.triple_pauser.update(self.ticks)
self.shoot()
if self.keys_press.get('b', False):
if self.spread_pauser.elaspe(self.ticks):
self.shoot_pauser.update(self.ticks)
self.triple_pauser.update(self.ticks)
self.spread_shot()
if self.keys_press.get('v', False):
if self.triple_pauser.elaspe(self.ticks):
self.shoot_pauser.update(self.ticks)
self.spread_pauser.update(self.ticks)
self.triple_shot()
# fix popping bug
for enum, index in enumerate(remove_list):
self.bullets.pop(index - enum)
# framerate per seconds 1000/30 = 30 frames roughly
self.ticks += 1
self.after(int(1000/30), self.tick_loop)
def go_press(self, event):
self.keys_press[event.keysym] = True
def go_release(self, event):
self.keys_press[event.keysym] = False
def shoot(self):
# only want the first two coords
x, y = self.canvas.coords(self.ship)[:2]
# just having shoot straight up
self.bullets.append(Bullet(self.canvas, x, y, "blue", (0, -10)))
# spread shooting
def spread_shot(self):
# only want the first two coords
x, y = self.canvas.coords(self.ship)[:2]
#up
self.bullets.append(Bullet(self.canvas, x, y, "red", (0, -8)))
#left
self.bullets.append(Bullet(self.canvas, x, y, "red", (-8, 0)))
#right
self.bullets.append(Bullet(self.canvas, x, y, "red", (8, 0)))
# triple shot striaght up
def triple_shot(self):
# only want the first two coords
x, y = self.canvas.coords(self.ship)[:2]
#up
self.bullets.append(Bullet(self.canvas, x, y, "green", (0, -5)))
self.bullets.append(Bullet(self.canvas, x - 50, y, "green", (0, -5)))
self.bullets.append(Bullet(self.canvas, x + 50, y, "green", (0, -5)))
def main():
root = tk.Tk()
app = App(root)
app.mainloop()
# __name__ only equals '__main__' if it is execute
# if import then it equals module name
if __name__ == '__main__':
main() 99 percent of computer problems exists between chair and keyboard. Posts: 18 Threads: 1 Joined: Oct 2017 Reputation: 0 Likes received: 0 Dec-06-2017, 01:13 PM (This post was last modified: Dec-06-2017, 01:19 PM by hammza. Edited 1 time in total.) (Nov-18-2017, 02:50 AM)Windspar Wrote: Okay figure out how to make tkinter keypress work smoothly. Enjoy! import tkinter as tk
# this makes a tuple (600, 400). tuples can be index
SCREEN = 600, 400
class Pauser:
def __init__(self, length):
self.length = length
self.last_tick = 0
def elaspe(self, ticks):
if ticks > self.last_tick + self.length:
self.last_tick = ticks
return True
return False
def update(self, ticks):
self.last_tick = ticks
# Object
class Bullet:
# movement takes a tuple (x, y)
def __init__(self, canvas, x, y, tk_fill, movement):
self.bullet = canvas.create_oval(x -3 , y - 3, x + 3, y + 3, fill=tk_fill)
self.movement = movement
#object method. self refers to object
def move(self, canvas):
canvas.move(self.bullet, self.movement[0], self.movement[1])
class App(tk.Frame):
def __init__(self, master):
# put canvas in frame so you can have other goodies
# this is from inheriting tk.Frame and calls __init__.
# so the App gains all variables and methods from tk.Frame
tk.Frame.__init__(self, master)
self.pack()
# self.canvas is an object variable
self.canvas = tk.Canvas(self, width=SCREEN[0], height=SCREEN[1])
self.canvas.pack()
# just a python list
self.bullets = # store bullets
# how fast a bullet can shoot
self.shoot_pauser = Pauser(12)
self.triple_pauser = Pauser(30)
self.spread_pauser = Pauser(25)
# storing keys to dict
self.keys_press = {}
# need to slow shooting
self.ticks = 0
# calls method. object.ship = App.create_ship(object, 300, 370, "blue")
self.ship = self.create_ship(300, 370, "blue")
self.speed = 5
# calls method. App.tick_loop(object)
self.tick_loop() # start the tick loop
print("Keys Press:", self.keys_press)
self.bind_all('<KeyPress>', self.go_press)
self.bind_all('<KeyRelease>', self.go_release)
def create_ship(self, x, y, tk_fill):
return self.canvas.create_polygon(x, y, x - 20, y + 30, x + 20, y + 30, fill=tk_fill)
def tick_loop(self):
remove_list =
# upacking iterable [(0, object(Bullet)), (1, object(Bullet)), etc]
for enum, bullet in enumerate(self.bullets):
coords = self.canvas.coords(bullet.bullet)
if coords[1] < 0 or coords[0] < 0 or coords[2] > SCREEN[0]:
remove_list.append(enum)
self.canvas.delete(bullet.bullet)
else:
bullet.move(self.canvas)
# NEW moving player
if self.keys_press.get('Left', False):
self.canvas.move(self.ship, -self.speed, 0)
if self.keys_press.get('Right', False):
self.canvas.move(self.ship, self.speed, 0)
if self.keys_press.get('Up', False):
self.canvas.move(self.ship, 0, -self.speed)
if self.keys_press.get('Down', False):
self.canvas.move(self.ship, 0, self.speed)
if self.keys_press.get('space', False):
if self.shoot_pauser.elaspe(self.ticks):
self.spread_pauser.update(self.ticks)
self.triple_pauser.update(self.ticks)
self.shoot()
if self.keys_press.get('b', False):
if self.spread_pauser.elaspe(self.ticks):
self.shoot_pauser.update(self.ticks)
self.triple_pauser.update(self.ticks)
self.spread_shot()
if self.keys_press.get('v', False):
if self.triple_pauser.elaspe(self.ticks):
self.shoot_pauser.update(self.ticks)
self.spread_pauser.update(self.ticks)
self.triple_shot()
# fix popping bug
for enum, index in enumerate(remove_list):
self.bullets.pop(index - enum)
# framerate per seconds 1000/30 = 30 frames roughly
self.ticks += 1
self.after(int(1000/30), self.tick_loop)
def go_press(self, event):
self.keys_press[event.keysym] = True
def go_release(self, event):
self.keys_press[event.keysym] = False
def shoot(self):
# only want the first two coords
x, y = self.canvas.coords(self.ship)[:2]
# just having shoot straight up
self.bullets.append(Bullet(self.canvas, x, y, "blue", (0, -10)))
# spread shooting
def spread_shot(self):
# only want the first two coords
x, y = self.canvas.coords(self.ship)[:2]
#up
self.bullets.append(Bullet(self.canvas, x, y, "red", (0, -8)))
#left
self.bullets.append(Bullet(self.canvas, x, y, "red", (-8, 0)))
#right
self.bullets.append(Bullet(self.canvas, x, y, "red", (8, 0)))
# triple shot striaght up
def triple_shot(self):
# only want the first two coords
x, y = self.canvas.coords(self.ship)[:2]
#up
self.bullets.append(Bullet(self.canvas, x, y, "green", (0, -5)))
self.bullets.append(Bullet(self.canvas, x - 50, y, "green", (0, -5)))
self.bullets.append(Bullet(self.canvas, x + 50, y, "green", (0, -5)))
def main():
root = tk.Tk()
app = App(root)
app.mainloop()
# __name__ only equals '__main__' if it is execute
# if import then it equals module name
if __name__ == '__main__':
main() Thank you very mush Windspar Iam sorry, I was busy last weeks The last code is just perfect, and exactly what I was looking for, just pure code without pygame or any game library. So making games with only tkinter and canvas is possible I hope I can reach your level programming man I worked on the background and the Land, but I don't know how to make it work simultaneously I think I should use threading but I didn't find a good tutorial explains it easily . I'll put the code sooner . |