Right, in my previous tutorial
http://forum.codecal...all-snake-game/,
I wrote some code for a ball snake game. Problem is, in that game, there's only eight directions. Now then, let's get greedy and make it go any way we want.
Also, we will use parametric functions do make paths for our sprites, which in this case, for simplicity, will be simple geometric shapes.
I got this idea to use vectors from a website for java programming (forgot what it was though), and it proved useful for games like these, where you need every direction possible. The thing was, it did not hurt to have some understanding of physics and maths.
Besides, it's easier to write maths in python.
Here's the code first:
bounceeverywhere.py 3.3KB
590 downloads
I will just copy paste the outer shell of the interface here, to save some time.
from tkinter import * from random import* from math import * '''New game to illustrate the use of tkinter to make a game that can handle collisions. ''' class game: def __init__(self): self.root=Tk() self.RUN=False self.frame=Frame(bg="black") self.frame.pack(); self.canvas=Canvas(self.frame, bg="black",width=300,height=300) self.canvas.pack() self.clock=Label(self.frame, bg="black", fg="white") self.clock.pack() self.points=Label(self.frame, bg="black", fg="white") self.points.pack() self.button=Button(self.frame, bg="black", fg="white", text="Click to start" ,command=self.start) self.button.pack() self.root.mainloop() def start(self): self.time=0 self.RUN=True self.foodX=[] self.foodY=[] self.trapX=[] self.trapY=[] self.powerupX=[[],[]] self.powerupY=[[],[]] self.TEXT="Welcome to tkinter" self.point=0 self.x=100 self.y=100 self.xa=200 self.ya=100 self.tempx=0 self.tempy=0 self.size=3 self.canvas.bind("<ButtonPress-1>", self.onMClick) self.run() def run(self): if self.RUN is True: self.time+=1 #Here's where the ball circles round and round self.xa+=25*sin((pi/3)*self.time) self.ya+=25*cos((pi/3)*self.time) self.clock['text']="TIME:" + str(self.time//100) self.points['text']="Points gathered: " + str(self.point) self.move(10*self.size,2) self.paint() self.root.after(10, self.run) def end(self): self.RUN=False self.canvas.unbind("<ButtonPress-1>") def paint(self): self.canvas.delete(ALL) self.canvas.create_text(100,100, text=self.TEXT, fill="green") if self.time//100<=60: if 10*self.size >0: self.TEXT="Welcome to tkinter" ball=self.canvas.create_oval(self.x-10*self.size,self.y-10*self.size,self.x+10*self.size,self.y+10*self.size, fill="white") hey=self.canvas.create_oval(self.xa-10,self.ya-10,self.xa+10,self.ya+10, fill="white") def move(self, b,speed): #movement handler def onMClick(self,event): #mouseclick events app=game()
The outer shell of the interface is covered in that link above, so let's continue with the juicier parts. We want the ball to move where we click.
FIrst, we should have the mouseclick update the direction vector, which is a vector, of length one.
def onMClick(self,event): #using unit vectors here X=event.x-self.x Y=event.y-self.y self.tempx=X/((X**2 + Y**2)**(0.5)) self.tempy=Y/((X**2 + Y**2)**(0.5)) print(self.tempx, self.tempy)
once again, i allow the event handler to handle the direction, and another function to handle movements and collisions.
def move(self, b,speed): if self.tempy and self.y-b>0 and self.y+b<300: self.y+=speed*self.tempy elif self.tempy<=0 and self.y-b<=0 : self.tempy*=-1 self.y+=speed*self.tempy elif self.tempy>0 and self.y+b>=300: self.tempy*=-1 self.y+=speed*self.tempy if self.tempx and self.x-b>0 and self.x+b<300: self.x+=speed*self.tempx elif self.tempx<=0 and self.x-b<=0 : self.tempx*=-1 self.x+=speed*self.tempx elif self.tempx>0 and self.x+b>=300: self.tempx*=-1 self.x+=speed*self.tempx
The good thing about vectors is that just by multiplying it by negative one, you reverse the direction.
There! add this to the outer shell and you're done.
Also, you might notice that there is a rotating circle.
from this:
def run(self): if self.RUN is True: self.time+=1 #Here's where the ball circles round and round self.xa+=25*sin((pi/3)*self.time) self.ya+=25*cos((pi/3)*self.time) self.clock['text']="TIME:" + str(self.time//100) self.points['text']="Points gathered: " + str(self.point) self.move(10*self.size,2) self.paint() self.root.after(10, self.run)
Where the sin and cos are both parametric equations of a circle.
And voila, your ball will move anywhere you want it and it will bounce off walls.