<file_sep>#smishra2
from cmu_112_graphics import *
from tkinter import *
import random
from PIL import Image
import math

class SplashScreenMode(Mode):
    def redrawAll(mode,canvas):
        font='Helvetica 26 bold'
        canvas.create_text(mode.width/2,mode.height/10,text='This is a game',font=font)
    def keyPressed(mode,event):
        if event.key=='Enter':
            mode.app.setActiveMode(mode.app.gameMode)
        elif event.key=='h':
            mode.app.setActiveMode(mode.app.helpMode)
        elif event.key=='g':
            mode.app.setActiveMode(mode.app.objectivesMode)
class Player(object):
    def __init__(self,mode):
        self.mode=mode
        self.x=self.mode.app.width//2
        self.y=self.mode.app.height-50
    def move(self,direction):
        if direction=='Left':
            self.x+=0
        elif direction=='Right':
            self.x+=10
        elif direction=='Up':
            self.y-=10
        elif direction=='Down':
            self.y+=10
        if (self.y < self.mode.scrollY + self.mode.scrollMargin):
            self.mode.scrollY = self.y - self.mode.scrollMargin
        if (self.y > self.mode.scrollY + self.mode.height - self.mode.scrollMargin):
            self.mode.scrollY = self.y - self.mode.height + self.mode.scrollMargin
        if (self.x < self.mode.scrollX + self.mode.scrollMargin):
            self.mode.scrollX = self.x - self.mode.scrollMargin
        if (self.x > self.mode.scrollX + self.mode.width - self.mode.scrollMargin):
            self.mode.scrollX = self.x - self.mode.width + self.mode.scrollMargin
        self.mode.spriteCounter=(1 + self.mode.spriteCounter) % len(self.mode.sprites)
    def draw(self,canvas):
        self.mode.sprite=self.mode.sprites[self.mode.spriteCounter]
        canvas.create_image(self.x-self.r, self.y-self.r, image=ImageTk.PhotoImage(self.mode.sprite))
class GoodMonster(object):
    def __init__(self,mode):
        self.mode=mode
        self.monsters=[]
        self.score=0
        for _ in range(30):
            self.monsters.append((random.randint(0,mode.app.width-mode.margin),random.randint(0,mode.app.height-mode.margin)))
    def __hash__(self):
        return hash(self.monsters)
    def move(self,direction,jumpDir):
        if direction=='Right':
            self.x+=10
        elif direction=='Left':
            self.x-=10
        elif direction=='Up':
            self.y-=10
        elif direction=='Down':
            self.y+=10
    def draw(self,canvas,mode):
        for x,y in self.monsters:
            if abs(self.mode.player.x-x)>5 and abs(self.mode.player.y-y)>5:
                canvas.create_oval(x-10-self.mode.scrollX,y-10-self.mode.scrollY,x+10-self.mode.scrollX,y+10-self.mode.scrollY,fill=random.choice(['blue','green']))
            else:
                self.monsters.remove((x,y))
                self.score+=1
class BadMonster(GoodMonster):
    def draw(self,canvas,mode,dx,dy):
        for x,y in self.monsters:
            canvas.create_oval(x-dx-10-self.mode.scrollX,y-dy+10-self.mode.scrollY,x+dx+10-self.mode.scrollX,y+dy+10-self.mode.scrollY,fill=random.choice(['red','orange']))
    def delete(self,mode,delx,dely):
        for x,y in self.monsters:
            if delx<x+1 or delx>x-1 or dely<y+1 or dely>y-1:
                self.monsters.remove((x,y))
class GameMode(Mode):
    def appStarted(mode):
        mode.margin=10
        mode.scrollMargin=50
        mode.player=Player(mode)
        mode.scrollX=0
        mode.scrollY=20
        mode.url='https://www.shutterstock.com/image-vector/game-kits-adventure-character-sprite-man-510472759'
        mode.spritestrip=mode.loadImage(mode.url)
        mode.sprites=[]
        mode.spriteCounter=0
        for i in range(8):
            mode.sprite=mode.spritestrip.crop((30+80*i, 50, 80+85*i, 150))
            mode.sprites.append(mode.sprite)
        mode.app.timerDelay=50
    def timerFired(mode):
        mode.dx+=random.randint(0,mode.app.width//500)
        mode.dy+=random.randint(0,mode.app.height//500)
    def keyPressed(mode,event):
        mode.player.move(event.key)
    def redrawAll(mode,canvas):
        mode.player.draw(canvas)
        mode.goodMonster.draw(canvas,mode)
        mode.badMonster.draw(canvas,mode,mode.dx,mode.dy)
        canvas.create_text(mode.width//2,50,text=mode.goodMonster.score,font='Arial 26 bold')
    def mousePressed(mode,event):
        mode.badMonster.delete(mode,event.x,event.y)
        mode.pressed+=1
        if mode.pressed>2:
            mode.app.setActiveMode(mode.app.endGame)
class HelpMode(Mode):
    def redrawAll(mode,canvas):
        font='Arial 18 bold'
        canvas.create_text(mode.width/2,mode.height/10,text='This is the help screen')
class ObjectiveMode(Mode):
    def redrawAll(mode,canvas):
        font='Arial 18 bold'
        canvas.create_text(mode.width/2,mode.height/10,text='The objective of this game')
class EndGame(Mode):
    def redrawAll(mode,canvas):
        canvas.create_text(mode.width//2,mode.height//2,text='You lost. Press R to start again.')        
class MyModalApp(ModalApp):
    def appStarted(app):
        app.gameMode=GameMode()
        app.splashScreenMode=SplashScreenMode()
        app.endGame=EndGame()
        app.objectiveMode=ObjectiveMode()
        app.setActiveMode(app.splashScreenMode)
app = MyModalApp(width=500,height=500)
class MyApp(App):
    def appStarted(self): 
        self.messages = ['appStarted']
        self.points=[]
        self.shape='hello'
        self.angle=0
        
    def appStopped(self):
        self.messages.append('appStopped')
        print('appStopped!')

    def keyPressed(self, event):
        if event.key=='l':
            self.points=[]

    def keyReleased(self, event):
        self.messages.append('keyReleased: ' + event.key)

    def mousePressed(self, event):
        self.messages.append(f'mousePressed at {(event.x, event.y)}')

    def mouseReleased(self, event):
        self.messages.append(f'mouseReleased at {(event.x, event.y)}')

    def mouseMoved(self, event):
        self.points.append((event.x,event.y))
        listOfAngles=[]
        for i in range(1,len(self.points)-1):
            point1,point2,point3=self.points[i-1],self.points[i],self.points[i+1]
            x1,y1=point1
            x2,y2=point2
            x3,y3=point3
            dotProduct=((x1-x2)*(x3-x2))+((y2-y1)*(y3-y2))
            magnitudeX=(((x1-x2)**2)+((y2-y1)**2))**0.5
            magnitudeY=(((x2-x3)**2)+((y3-y2)**2))**0.5
            radAngle=math.acos(dotProduct/(magnitudeX*magnitudeY))
            angle=math.degrees(radAngle)
            if angle<100 and angle>55:
                listOfAngles.append(angle)
            self.angle=angle
        if len(listOfAngles)==3: self.shape='triangle'
        elif len(listOfAngles)==4: self.shape='square'
        elif len(listOfAngles)==0: self.shape='circle'
        
    def mouseDragged(self, event):
        self.messages.append(f'mouseDragged at {(event.x, event.y)}')

    def sizeChanged(self):
        self.messages.append(f'sizeChanged to {(self.width, self.height)}')

    def shape(self):
        listOfAngles=[]
        for i in range(1,len(self.points)-1):
            point1,point2,point3=self.points[i-1],self.points[i],self.points[i+1]
            x=(point1,point2)
            y=(point2,point3)
            dotProduct=(point1*point2)+(point2*point3)
            magnitudeX=((point1**2)+(point2**2))**0.5
            magnitudeY=((point2**2)+(point3**2))**0.5
            angle=math.acos(dotProduct/(magnitudeX*magnitudeY))
            if angle<120 and angle>45:
                listOfAngles.append(angle)
        if len(listOfAngles)==3: self.shape='triangle'
        elif len(listOfAngles)==4: self.shape='square'
        elif len(listOfAngles)==0: self.shape='circle'
        return self.shape
    def magnitude(point1,point2):
        x1,y1=point1
        x2,y2=point2
        return ((x2-x1)**2 + (y2-y1)**2)**0.5

    def redrawAll(self, canvas):
        font = 'Arial 20 bold'
        canvas.create_text(self.width/2,  30, text=self.shape, font=font)
        canvas.create_text(self.width/2,  50, text=self.angle, font=font)
        n = min(10, len(self.messages))
        i0 = len(self.messages)-n
        for i in range(len(self.points)):
            x,y=self.points[i]
            canvas.create_oval(x-5,y-5,x+5,y+5,fill='black')
MyApp(width=600, height=600)

