Jump to content


Check out our Community Blogs

Register and join over 40,000 other developers!


Recent Status Updates

View All Updates

Photo
- - - - -

Tkinter bouncy ball with full control over direction

python tkinter game

  • Please log in to reply
No replies to this topic

#1 DanielTan

DanielTan

    CC Regular

  • Member
  • PipPipPip
  • 25 posts

Posted 07 August 2013 - 06:16 AM

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:

Attached File  bounceeverywhere.py   3.3KB   363 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.


  • 0





Also tagged with one or more of these keywords: python, tkinter, game