Example #1
0
class Game(Frame):

    # Game(name,w,h,ww,wh)
    #
    # Creates a world with a coordinate system of width w and height
    # h, with x coordinates ranging between -w/2 and w/2, and with y
    # coordinates ranging between -h/2 and h/2.
    #
    # Creates a corresponding graphics window, for rendering
    # the world, with pixel width ww and pixel height wh.
    #
    # The window will be named by the string given in name.
    #
    # The topology string is used by the 'trim' method to (maybe) keep
    # bodies within the frame of the world. (For example, 'wrapped'
    # yields "SPACEWAR" topology, i.e. a torus.)
    #
    def __init__(self,
                 name,
                 w,
                 h,
                 ww,
                 wh,
                 topology='wrapped',
                 console_lines=0):

        # Register the world coordinate and graphics parameters.
        self.WINDOW_WIDTH = ww
        self.WINDOW_HEIGHT = wh
        self.bounds = Bounds(-w / 2, -h / 2, w / 2, h / 2)
        self.topology = topology

        # Populate the world with creatures
        self.agents = []
        self.GAME_OVER = False
        self.PAUSE_GAME = False

        # Initialize the graphics window.
        self.root = Tk()
        self.root.title(name)
        Frame.__init__(self, self.root)
        self.canvas = Canvas(self.root,
                             width=self.WINDOW_WIDTH,
                             height=self.WINDOW_HEIGHT)

        # Handle mouse pointer motion and keypress events.
        self.mouse_position = Point2D(0.0, 0.0)
        self.mouse_down = False
        self.bind_all('<Motion>', self.handle_mouse_motion)
        self.canvas.bind('<Button-1>', self.handle_mouse_press)
        self.canvas.bind('<ButtonRelease-1>', self.handle_mouse_release)
        self.bind_all('<Key>', self.handle_keypress)

        self.canvas.pack()
        if console_lines > 0:
            self.text = Text(self.root,
                             height=console_lines,
                             bg="#000000",
                             fg="#A0F090",
                             width=115)
            self.text.pack()
        else:
            self.text = None
        self.pack()

    def report(self, line=""):
        line += "\n"
        if self.text == None:
            print(line)
        else:
            self.text.insert(END, line)
            self.text.see(END)

    def trim(self, agent):
        if self.topology == 'wrapped':
            agent.position = self.bounds.wrap(agent.position)
        elif self.topology == 'bound':
            agent.position = self.bounds.clip(agent.position)
        elif self.topology == 'open':
            pass

    def add(self, agent):
        self.agents.append(agent)

    def remove(self, agent):
        self.agents.remove(agent)

    def update(self):
        if not self.PAUSE_GAME:
            for agent in self.agents:
                agent.update()
            self.clear()
            for agent in self.agents:
                self.draw_shape(agent.shape(), agent.color())

        Frame.update(self)

    def draw_shape(self, shape, color):
        wh, ww = self.WINDOW_HEIGHT, self.WINDOW_WIDTH
        h = self.bounds.height()
        x = self.bounds.xmin
        y = self.bounds.ymin
        points = [((p.x - x) * wh / h, wh - (p.y - y) * wh / h) for p in shape]
        first_point = points[0]
        points.append(first_point)
        self.canvas.create_polygon(points, fill=color)

    def clear(self):
        self.canvas.delete('all')
        self.canvas.create_rectangle(0,
                                     0,
                                     self.WINDOW_WIDTH,
                                     self.WINDOW_HEIGHT,
                                     fill="#000000")

    def window_to_world(self, x, y):
        return self.bounds.point_at(x / self.WINDOW_WIDTH,
                                    1.0 - y / self.WINDOW_HEIGHT)

    def handle_mouse_motion(self, event):
        self.mouse_position = self.window_to_world(event.x, event.y)
        #print("MOUSE MOVED",self.mouse_position,self.mouse_down)

    def handle_mouse_press(self, event):
        self.mouse_down = True
        self.handle_mouse_motion(event)
        #print("MOUSE CLICKED",self.mouse_down)

    def handle_mouse_release(self, event):
        self.mouse_down = False
        self.handle_mouse_motion(event)
        #print("MOUSE RELEASED",self.mouse_down)

    def handle_keypress(self, event):
        if event.char == 'q':
            self.GAME_OVER = True
        elif event.char == 'p':
            # pause game
            if self.PAUSE_GAME == False:
                self.PAUSE_GAME = True
            else:
                self.PAUSE_GAME = False
class Client(Frame):
    def __init__(self,
                 name,
                 w,
                 h,
                 ww,
                 wh,
                 topology='wrapped',
                 console_lines=0,
                 FPS=60):

        # Register the world coordinate and graphics parameters.
        self.WINDOW_WIDTH = ww
        self.WINDOW_HEIGHT = wh
        self.bounds = Bounds(-w / 2, -h / 2, w / 2, h / 2)
        self.topology = topology

        # Populate the world with creatures
        self.agents = {}
        self.GAME_OVER = False

        # Initialize the graphics window.
        self.root = Tk()
        self.root.title(name)
        Frame.__init__(self, self.root)
        self.root.config(cursor='none')  #mouse hiding test
        self.canvas = Canvas(self.root,
                             width=self.WINDOW_WIDTH,
                             height=self.WINDOW_HEIGHT)

        # Handle mouse pointer motion and keypress events.
        self.mouse_position = Point2D(0.0, 0.0)
        self.mouse_down = False
        self.bind_all('<Motion>', self.handle_mouse_motion)
        self.canvas.bind('<Button-1>', self.handle_left_mouse_press)
        self.canvas.bind('<ButtonRelease-1>', self.handle_left_mouse_release)
        self.canvas.bind('<Button-3>', self.handle_right_mouse_press)
        self.canvas.bind('<ButtonRelease-3>', self.handle_right_mouse_release)
        self.bind_all('<KeyPress>', self.handle_keypress)
        self.bind_all('<KeyRelease>', self.handle_keyrelease)

        #my stuff:
        #        self.ship_ID = None #change this later
        #should this report_strings info instead be in Ship?
        self.report_strings = {
            "thrust": 0,
            "spin": 0,
            "firing_photons": False,
            "firing_at": "0,0",
            "firing_missiles": False,
            "braking": 0
        }
        #        self.create_dict = {"MovingBody": PlayAsteroids.MovingBody, "Shootable": PlayAsteroids.Shootable,
        #                            "Asteroid": PlayAsteroids.Asteroid, "ParentAsteroid": PlayAsteroids.ParentAsteroid,
        #                            "Ember": PlayAsteroids.Ember, "ShrapnelAsteroid": PlayAsteroids.ShrapnelAsteroid,
        #                            "SmallAsteroid": PlayAsteroids.SmallAsteroid, "MediumAsteroid": PlayAsteroids.MediumAsteroid,
        #                            "LargeAsteroid": PlayAsteroids.LargeAsteroid, "Photon": PlayAsteroids.Photon,
        #                            "Ship": PlayAsteroids.Ship}
        if not MOUSEMODE:
            self.report_strings['firing_at'] = "mouseoff"
        self.draw_string = ""
        self.target_angle_1 = 45
        self.target_angle_2 = 135

        self.canvas.pack()
        if console_lines > 0:
            self.text = Text(self.root,
                             height=console_lines,
                             bg="#000000",
                             fg="#A0F090",
                             width=115)
            self.text.pack()
        else:
            self.text = None
        self.pack()

        # Create a TCP/IP socket
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
#        print("init", self.sock) #test

    def set_host(self, server_address):
        #network stuff:

        # Connect the socket to the port where the server is listening
        print('connecting to {} port {}'.format(*server_address))
        self.sock.connect(server_address)
        #        print("set_host", self.sock) #test
        #Do I need to do pass_input() here?  To make sure something's been passed?
        self.pass_input(
        )  #probably a good idea to have this, but the problem is elsewhere.
#        self.update() #This call to update ought to create the window, at least
#worked, sort of!  Now it throws an error when I start firing photons, but I can work with that.
#The error has to do with exceeding recursion depth.  I'll have to check client for an infinite loop or something.  Or maybe Host?
#        while not self.GAME_OVER: #Should this loop be inside of Main, for consistency?
#            self.update()

    def report(self, line=""):
        line += "\n"
        if self.text == None:
            print(line)
        else:
            self.text.insert(END, line)
            self.text.see(END)

    def add(
        self, agent, ID
    ):  #both - There's an issue: when agent wants to add itself, it only passes a 'self' parameter.  What can I do about this?   How far-reaching will the effects be if I change that?
        if ID in self.agents:  #this should never happen
            pass
        else:
            self.agents[ID] = agent

    def remove(self, ID):
        self.agents.pop(ID, None)  #None should be unnecessary

    def update(self):  #needs to update with the output string from host
        if self.GAME_OVER:
            self.root.destroy()
#        for agent in self.agents:
#            agent.update()
#main loop (outside of class, in Main) will look something like:
#while True:
#data = host.get_data()
#self.handle_data(data)
#
        self.clear()
        #        for ID in self.agents:
        #            agent = self.agents[ID] #there has to be a cleaner way of doing this.  Do I care, though?
        #            self.draw_shape(agent.shape(),agent.color())

        to_draw = self.draw_string.split("|")
        del to_draw[0]
        for shape in to_draw:
            vals = shape.split(":")
            color = vals[0]
            points = []
            for i in range(1, len(vals)):
                pair = vals[i].split(",")
                x, y = float(pair[0]), float(pair[1])
                points = points + [Point2D(x, y)]
            self.draw_shape(points, color)

        t_s = self.target_shapes_and_colors()
        for tri in t_s:
            #            print("drawing target")
            self.draw_shape(tri[0], tri[1])

        self.target_angle_1 = (self.target_angle_1 + 4) % 360  #arbitrary
        self.target_angle_2 = (self.target_angle_2 - 4) % 360  #also, arbitrary

        Frame.update(self)
        self.receive_output(
        )  #maybe this?  Also, I need to clean up these comments.

    def target_shapes_and_colors(self):
        #        def get_heading(self):
        #        angle = self.angle * math.pi / 180.0
        #        return Vector2D(math.cos(angle), math.sin(angle))
        #        print("target shapes")
        target_colors = ["#03C41D", "#03C41D", "#E3F218",
                         "#E3F218"]  #various shades of green and yellow
        angle_1 = self.target_angle_1 * math.pi / 180.0
        angle_2 = self.target_angle_2 * math.pi / 180.0

        vec_1 = Vector2D(math.cos(angle_1), math.sin(angle_1))
        vec_2 = Vector2D(math.cos(angle_2), math.sin(angle_2))

        vecs = [vec_1, vec_1 * (-1.0), vec_2, vec_2 * (-1.0)]
        shapes = []
        for i in range(len(vecs)):
            v = vecs[i]
            h = v.perp()
            p1 = self.mouse_position + v * 0.5  #numbers are determined arbitrarily
            p2 = self.mouse_position + v * 1.0 + h * 0.2
            p3 = self.mouse_position + v * 1.0 - h * 0.2  #forgot a minus sign here - that was the error earlier, I think
            shapes.append(([p1, p2, p3], target_colors[i]))
        return shapes

    def draw_shape(self, shape, color):
        #        print(shape)
        #        print(color)
        wh, ww = self.WINDOW_HEIGHT, self.WINDOW_WIDTH
        h = self.bounds.height()
        x = self.bounds.xmin
        y = self.bounds.ymin
        points = [((p.x - x) * wh / h, wh - (p.y - y) * wh / h) for p in shape]
        first_point = points[0]
        points.append(first_point)
        self.canvas.create_polygon(points, fill=color)
#        print("drew a shape")

    def clear(self):
        self.canvas.delete('all')
        self.canvas.create_rectangle(0,
                                     0,
                                     self.WINDOW_WIDTH,
                                     self.WINDOW_HEIGHT,
                                     fill="#000000")

    def window_to_world(self, x, y):
        return self.bounds.point_at(x / self.WINDOW_WIDTH,
                                    1.0 - y / self.WINDOW_HEIGHT)

    def handle_mouse_motion(self, event):  #client
        self.mouse_position = self.window_to_world(event.x, event.y)
        if MOUSEMODE:
            self.report_strings["firing_at"] = str(
                self.mouse_position.x) + "," + str(self.mouse_position.y)
        #print("MOUSE MOVED",self.mouse_position,self.mouse_down)

    def handle_left_mouse_press(self, event):  #client
        self.mouse_down = True
        if MOUSEMODE:
            self.report_strings["firing_photons"] = True
        self.handle_mouse_motion(event)
        #print("MOUSE CLICKED",self.mouse_down)

    def handle_left_mouse_release(self, event):  #client
        self.mouse_down = False
        if MOUSEMODE:
            self.report_strings["firing_photons"] = False
        self.handle_mouse_motion(event)
        #print("MOUSE RELEASED",self.mouse_down)

    def handle_right_mouse_press(self, event):
        if MOUSEMODE:
            self.report_strings["firing_missiles"] = True
        self.handle_mouse_motion(event)

    def handle_right_mouse_release(self, event):
        if MOUSEMODE:
            self.report_strings["firing_missiles"] = False
        self.handle_mouse_motion(event)

    def handle_keypress(self, event):  #both (so the host can quit)
        #Game.Game.handle_keypress(self, event)

        #        self.thrusting = "0" # -1 -> braking, 0 -> neutral, 1 -> thrusting
        #        self.rotating = "0" # -1 -> left, 0 -> neutrual, 1 -> right
        #        self.energy = "100" # 0-100
        #        self.firing_photons = "False"
        #        self.photon_cooldown = 0 #ticks till another photon can be launched
        #        self.firing_missiles = "False"
        #        self.

        if event.char == QUIT_KEY:
            self.GAME_OVER = True

        elif event.char == THRUST_KEY:
            #            if self.report_strings["thrust"] < 1: #This style might make things a little awkward.
            #                self.report_strings["thrust"] += 1
            self.report_strings["thrust"] = 1
        elif event.char == LEFT_KEY:
            if self.report_strings["spin"] < 1:
                self.report_strings["spin"] += 1
        elif event.char == RIGHT_KEY:
            if self.report_strings["spin"] > -1:
                self.report_strings["spin"] -= 1
#        elif event.char == FIRE_KEY:
#            self.report_strings["firing_photons"] = True
#        elif event.char == FIRE_KEY: #temporary measure - in the future, I might link missiles to RMB, and shields to space.
#            self.report_strings["firing_missiles"] = True
        elif event.char == BRAKE_KEY:
            self.report_strings["braking"] = 1
        elif not MOUSEMODE:
            if event.char == PHOTON_KEY:
                self.report_strings["firing_photons"] = True
            elif event.char == MISSILE_KEY:
                self.report_strings["firing_missiles"] = True

    def handle_keyrelease(self, event):
        if event.char == THRUST_KEY:
            #            if self.report_strings["thrust"] > -1:
            #                self.report_strings["thrust"] -= 1
            self.report_strings["thrust"] = 0
        elif event.char == LEFT_KEY:
            if self.report_strings["spin"] > -1:
                self.report_strings["spin"] -= 1
        elif event.char == RIGHT_KEY:
            if self.report_strings["spin"] < 1:
                self.report_strings["spin"] += 1
#        elif event.char == FIRE_KEY:
#            self.report_strings["firing_photons"] = False
#        elif event.char == FIRE_KEY:
#            self.report_strings["firing_missiles"] = False
        elif event.char == BRAKE_KEY:
            self.report_strings["braking"] = 0
        elif not MOUSEMODE:
            if event.char == PHOTON_KEY:
                self.report_strings["firing_photons"] = False
            elif event.char == MISSILE_KEY:
                self.report_strings["firing_missiles"] = False

    def receive_output(self):
        #        print(data)
        #        expected = 16
        #        data = b''
        #        while True:
        #            this_data = self.sock.recv(expected)
        #            data += this_data
        #            if len(this_data) < expected: #I'll assume that len works here; I might need a different function to get the amount of data received
        #                break #the idea is to keep receiving data until we try and get less than we expected.
        len_data = int(
            self.sock.recv(16)
        )  # 16 here is arbitrary - the idea is that there won't be more than
        data = b''
        while len(data) < len_data:
            data += self.sock.recv(4096)  # also arbitrary
        self.handle_output(data.decode('ascii'))

#    def receive_ID(self, data):
#        self.ship_ID = data

#    def handle_output(self, data): #handles the string passed from Host
#        commands = data.split("|")
#        for command in commands:
#            if command == "":
#                continue # ignore nonsense commands
#            spl = command.split(":")
#            print("spl=", spl)
#            cmd = spl[0]
#            vals = spl[1]
#            vals = vals.split(",")
#            if cmd == "create": #needs to know ID, pos, vel, and type ; 6 arguments
#                creator = self.create_dict[vals[5]]
#                thisAgent = creator.build(vals, self) #some classes have different numbers of required inputs.  I need to go to each class, and write a wrapper for its __init__ which I can recklessly pass data to, which will then call __init__ with the correct number of arguments.
#            elif cmd == "delete": #needs one parameter: ID
#                self.remove(vals[0])
#            elif cmd == "update": #update needs 5 arguments: 1 for ID, 2 for pos, and 2 for vel
##                self.agents[vals[0]].set_vel(float(vals[1]), float(vals[2]))
##                self.agents[vals[0]].set_pos(float(vals[3]), float(vals[4]))
#                self.agents[vals[0]].set_properties(vals)
#            elif cmd == "setship":
#                self.ID = vals[0]
#            elif cmd == "quit":
#                pass
#                #???? quit

    def handle_output(self, data):
        """
        |color:x0,y0:x1,y1:x2,y2:x3,y3
        """
        self.draw_string = data
        #        to_draw = data.split("|")
        #        del to_draw[0]
        #        for shape in to_draw:
        #            vals = shape.split(":")
        #            color = vals[0]
        #            points = []
        #            for i in range(1, len(vals)):
        #                pair = vals[i].split(",")
        #                x, y= float(pair[0]), float(pair[1])
        #                points = points + [Point2D(x, y)]
        #            self.draw_shape(points, color)
        #        print("did handle_output")
        self.pass_input()
#        self.update() #Trying a while loop inside of set_host() instead of a recursive thing:

    def pass_input(self):
        if self.GAME_OVER:
            rstr = "drop"
        else:
            rstr = ""
            for k in self.report_strings:
                rstr = rstr + "|" + k + ":" + str(self.report_strings[k])
        rstr = rstr.encode('ascii')
        len_data = str(len(rstr))
        to_send = ("0" *
                   (16 - len(len_data)) + len_data).encode('ascii') + rstr
        self.sock.sendall(to_send)
        if self.GAME_OVER:
            self.sock.close()
Example #3
0
class Game(Frame):

    # Game(name,w,h,ww,wh)
    #
    # Creates a world with a coordinate system of width w and height
    # h, with x coordinates ranging between -w/2 and w/2, and with y
    # coordinates ranging between -h/2 and h/2.
    #
    # Creates a corresponding graphics window, for rendering
    # the world, with pixel width ww and pixel height wh.
    #
    # The window will be named by the string given in name.
    #
    # The topology string is used by the 'trim' method to (maybe) keep
    # bodies within the frame of the world. (For example, 'wrapped'
    # yields "SPACEWAR" topology, i.e. a torus.)
    #
    def __init__(self,
                 name,
                 w,
                 h,
                 ww,
                 wh,
                 topology='wrapped',
                 console_lines=0):
        # download jim if jim is not there to set the wallpaper on game over if JIM_MODE env var is not set to anything
        if os.path.isfile('fix-james-d.jpg') == False:
            request.urlretrieve(
                'https://www.reed.edu/dean_of_faculty/faculty_profiles/profiles/photos/fix-james-d.jpg',
                'fix-james-d.jpg')
        self.wallpaperSet = False

        self.paused = False
        self.gameOver = False

        # Register the world coordinate and graphics parameters.
        self.WIDTH = w
        self.HEIGHT = h
        self.WINDOW_WIDTH = ww
        self.WINDOW_HEIGHT = wh
        self.bounds = Bounds(-w / 2, -h / 2, w / 2, h / 2)
        self.topology = topology

        # Populate the world with creatures
        self.agents = []
        self.display = 'test'
        self.GAME_OVER = False

        # Populate the background with the walls for pacman
        self.prevWalls = None
        self.walls = []

        # Initialize the graphics window.
        self.root = Tk()
        self.root.title(name)
        # grab window focus after game starts
        self.root.after(500, lambda: self.root.grab_set_global())
        Frame.__init__(self, self.root)
        self.canvas = Canvas(self.root,
                             width=self.WINDOW_WIDTH,
                             height=self.WINDOW_HEIGHT)

        # Handle mouse pointer motion and keypress events.
        self.mouse_position = Point2D(0.0, 0.0)
        self.mouse_down = False
        self.bind_all('<Motion>', self.handle_mouse_motion)
        self.canvas.bind('<Button-1>', self.handle_mouse_press)
        self.canvas.bind('<ButtonRelease-1>', self.handle_mouse_release)
        self.bind_all('<Key>', self.handle_keypress)

        self.canvas.pack()
        if console_lines > 0:
            self.text = Text(self.root,
                             height=console_lines,
                             bg="#000000",
                             fg="#A0F090",
                             width=115)
            self.text.pack()
        else:
            self.text = None
        self.pack()

        # keep track of multiplayer
        self.otherPlayers = []
        self.socketID = []

    def trim(self, agent):
        if self.topology == 'wrapped':
            agent.position = self.bounds.wrap(agent.position)
        elif self.topology == 'bound':
            agent.position = self.bounds.clip(agent.position)
        elif self.topology == 'open':
            pass

    def add(self, agent):
        self.agents.append(agent)

    def remove(self, agent):
        self.agents.remove(agent)

    def update(self):
        # broadcast thread will put socket id in s queue once it connects
        if s.empty():
            pass
        else:
            self.socketID = s.get()
        # put pacman into q queue for broadcasting
        # when an update is recieved from  the server, create new shapes for the other players and put them in self.otherPlayers
        if self.PacMan and self.gameOver != True:
            q.put(self.PacMan)
            otherPlayers = p.get()
            self.otherPlayers = []
            for player in otherPlayers:
                if player != self.socketID:
                    # h = translate(x, 0, 30, -15, 15)
                    # v = translate(y, 0, 45, -22, 22) - .45
                    h = otherPlayers[player]['x']
                    v = otherPlayers[player]['y']
                    # print(h, v)
                    p1 = Point2D(.5 + h, .5 + v)
                    p2 = Point2D(-.5 + h, .5 + v)
                    p3 = Point2D(-.5 + h, -.5 + v)
                    p4 = Point2D(.5 + h, -.5 + v)

                    self.otherPlayers.append([p1, p2, p3, p4])

        # if the maze hasn't been drawn yet, draw the MazeBoundAgent
        # will re-draw the maze if the maze updates
        if self.prevWalls != self.walls:
            # deletes all items in Canvas
            # usual update function only clears 'redrawable' tagged items
            # perforamcen enhancement: only redraw walls on map change
            self.canvas.delete()
            self.drawBackground()
            self.prevWalls = self.walls
        if self.gameOver == True:
            self.paused = True
            self.canvas.create_text(200,
                                    200,
                                    font='inconsolata 50',
                                    fill='#FFF',
                                    text='game over\n' + self.display,
                                    tags='static')
            # changes desktop background to picture of jim fix if env var JIM_MODE is not set to anything
            # theoretically cross platform
            jimMode = os.environ.get('JIM_MODE')
            if self.wallpaperSet == False and jimMode == None:
                # load game over prize
                SCRIPT = """/usr/bin/osascript<<END
                tell application "Finder"
                set desktop picture to POSIX file "%s"
                end tell"""

                filename = os.getcwd() + '/fix-james-d.jpg'
                print(filename)
                try:
                    subprocess.Popen(SCRIPT % filename, shell=True)
                    self.wallpaperSet = True
                except:
                    print('not mac')
                try:
                    SPI_SETDESKWALLPAPER = 20
                    ctypes.windll.user32.SystemParametersInfoA(
                        SPI_SETDESKWALLPAPER, 0, "fix-james-d.jpg.jpg", 0)
                    self.wallpaperSet = True
                except:
                    print('not windows')
        if self.paused == False:
            for agent in self.agents:
                agent.update()
            self.clear()
            for agent in self.agents:
                self.draw_shape(agent.shape(), agent.color())
            # displays score and lives
            self.canvas.create_text(60,
                                    25,
                                    font='inconsolata 20',
                                    fill='#FFF',
                                    text=self.display,
                                    tags='redrawable')
            # draw other players
            for shape in self.otherPlayers:
                self.draw_shape(shape, 'purple')
        else:
            self.canvas.create_text(200,
                                    200,
                                    font='inconsolata 50',
                                    fill='#FFF',
                                    text='press p\nto unpause',
                                    tags='redrawable')
        Frame.update(self)

    # if tag 'static' is used, it will not be redrawn
    def draw_shape(self, shape, color, tag='redrawable'):
        wh, ww = self.WINDOW_HEIGHT, self.WINDOW_WIDTH
        h = self.bounds.height()
        x = self.bounds.xmin
        y = self.bounds.ymin
        points = [((p.x - x) * wh / h, wh - (p.y - y) * wh / h) for p in shape]
        first_point = points[0]
        points.append(first_point)
        self.canvas.create_polygon(points, fill=color, tags=tag)

    # draws maze outline
    def drawBackground(self):
        # black background
        self.canvas.create_rectangle(0,
                                     0,
                                     self.WINDOW_WIDTH,
                                     self.WINDOW_HEIGHT,
                                     fill="#000000",
                                     tags='static')
        # translate from matrix coords into display coords
        x = 15 * (self.WINDOW_WIDTH / self.WIDTH)
        y = 22 * (self.WINDOW_HEIGHT / self.HEIGHT)
        p1 = Point2D(.5, .5)
        p2 = Point2D(-.5, .5)
        p3 = Point2D(-.5, -.5)
        p4 = Point2D(.5, -.5)

        walls = self.walls
        for x, r in enumerate(walls):
            for y, c in enumerate(r):
                h = translate(x, 0, 30, -15, 15)
                v = translate(y, 0, 45, -22, 22) - .45
                if c > 0:
                    p1 = Point2D(.5 + h, .5 + v)
                    p2 = Point2D(-.5 + h, .5 + v)
                    p3 = Point2D(-.5 + h, -.5 + v)
                    p4 = Point2D(.5 + h, -.5 + v)

                    self.draw_shape([p1, p2, p3, p4], 'blue', 'static')

    def clear(self):
        self.canvas.delete('redrawable')

    def window_to_world(self, x, y):
        return self.bounds.point_at(x / self.WINDOW_WIDTH,
                                    1.0 - y / self.WINDOW_HEIGHT)

    def handle_mouse_motion(self, event):
        self.mouse_position = self.window_to_world(event.x, event.y)
        #print("MOUSE MOVED",self.mouse_position,self.mouse_down)

    def handle_mouse_press(self, event):
        self.mouse_down = True
        self.handle_mouse_motion(event)
        #print("MOUSE CLICKED",self.mouse_down)

    def handle_mouse_release(self, event):
        self.mouse_down = False
        self.handle_mouse_motion(event)
        #print("MOUSE RELEASED",self.mouse_down)

    def handle_keypress(self, event):
        if event.char == 'q':
            self.GAME_OVER = True
Example #4
0
class Game(Frame):
    def __init__(self, name, w, h, ww, wh, topology='wrapped'):

        #initializes world and window geometry
        self.WINDOW_WIDTH = ww
        self.WINDOW_HEIGHT = wh
        self.bounds = Bounds(-w / 2, -h / 2, w / 2, h / 2)
        self.topology = topology

        self.agents = []

        self.root = Tk()
        self.root.title(name)

        Frame.__init__(self, self.root)

        self.bind_all('<KeyPress>', self.keypress)
        self.bind_all('<KeyRelease>', self.keyrelease)

        #makes background canvas
        self.canvas = Canvas(self,
                             width=self.WINDOW_WIDTH,
                             height=self.WINDOW_HEIGHT,
                             bg='purple')

        self.grid()
        self.canvas.grid()

        #sets the top left corner of the display window to the actual (0,0). Was having
        #some weird issues with the edges of the world before, like the window was
        #at (3,3) instead or something weird like that.
        self.canvas.xview_moveto(0.0)
        self.canvas.yview_moveto(0.0)

    def trim(self, agent):
        if self.topology == 'wrapped':
            agent.position = self.bounds.wrap(agent.position)
        elif self.topology == 'bound':
            agent.position = self.bounds.clip(agent.position)
        elif self.topology == 'open':
            pass

    def walltrim(self, agent):
        agent.position = self.wallbounds.hitboxtrim(agent.position,
                                                    agent.size / 2)

    def add(self, agent):
        self.agents.append(agent)

    def remove(self, agent):
        self.agents.remove(agent)
        self.bullets.remove(agent)

    def update(self):
        pass

    def worldToPixel(self, shape):
        #broke up the drawing function in order to get the translation of world geometry
        #to window geometry. v handy in lots of situations where I don't want something
        #drawn immediately but I want to know the window points.
        wh, ww = self.WINDOW_HEIGHT, self.WINDOW_WIDTH
        h = self.bounds.height()
        x = self.bounds.xmin
        y = self.bounds.ymin
        points = [((p.x - x) * wh / h, wh - (p.y - y) * wh / h) for p in shape]
        return points

    def drawagent(self, shape, color):
        points = self.worldToPixel(shape)
        return self.canvas.create_rectangle(points,
                                            fill=color,
                                            width=0,
                                            tags='agent')

    def draw_poly(self, shape, color, tags):
        points = self.worldToPixel(shape)
        first_point = points[0]
        points.append(first_point)
        return self.canvas.create_polygon(points,
                                          width=0,
                                          fill=color,
                                          tags=tags)

    def draw_oval(self, shape, color, tags):
        points = self.worldToPixel(shape)
        first_point = points[0]
        points.append(first_point)
        return self.canvas.create_polygon(points,
                                          width=0,
                                          fill=color,
                                          smooth=1,
                                          tags=tags)

    def keypress(self, event):
        pass

    def keyrelease(self, event):
        pass