44If Python and Arcade are installed, this example can be run from the command line with:
55python -m arcade.examples.hex_map
66"""
7+
8+ import math
9+ from operator import add
10+
11+ from pyglet .math import Vec2
12+
713import arcade
8- from arcade import TileMap
14+ from arcade import hexagon
915
1016WINDOW_WIDTH = 1280
1117WINDOW_HEIGHT = 720
@@ -21,7 +27,7 @@ def __init__(self):
2127 super ().__init__ ()
2228
2329 # Variable to hold our Tiled Map
24- self .tile_map : TileMap
30+ self .tile_map : arcade . TileMap
2531
2632 # Replacing all of our SpriteLists with a Scene variable
2733 self .scene : arcade .Scene
@@ -32,14 +38,45 @@ def __init__(self):
3238 # A variable to store our gui camera object
3339 self .gui_camera : arcade .camera .Camera2D
3440
35-
36- # If you have sprite lists, you should create them here,
37- # and set them to None
41+ # Initialize the mouse_pan variable
42+ self .mouse_pan = False
3843
3944 def reset (self ):
4045 """Reset the game to the initial state."""
41- # Do changes needed to restart the game here if you want to support that
42- pass
46+ # Do changes needed to restart the game here
47+
48+ # Tiled always uses pointy orientations
49+ orientation = hexagon .pointy_orientation
50+ #
51+ hex_size_x = 120 / math .sqrt (3 )
52+ hex_size_y = 140 / 2
53+ map_origin = Vec2 (0 , 0 )
54+
55+ hex_layout = hexagon .Layout (
56+ orientation = orientation ,
57+ size = Vec2 (hex_size_x , hex_size_y ),
58+ origin = map_origin ,
59+ )
60+
61+ # Load our TileMap
62+ self .tile_map = arcade .load_tilemap (
63+ ":resources:tiled_maps/hex_map.tmj" ,
64+ hex_layout = hex_layout ,
65+ use_spatial_hash = True ,
66+ )
67+
68+ # Create our Scene Based on the TileMap
69+ self .scene = arcade .Scene .from_tilemap (self .tile_map ) # type: ignore[arg-type]
70+
71+ # Initialize our camera, setting a viewport the size of our window.
72+ self .camera = arcade .camera .Camera2D ()
73+ self .camera .zoom = 0.5
74+
75+ # Initialize our gui camera, initial settings are the same as our world camera.
76+ self .gui_camera = arcade .camera .Camera2D ()
77+
78+ # Set the background color to a nice red
79+ self .background_color = arcade .color .BLACK
4380
4481 def on_draw (self ):
4582 """
@@ -50,6 +87,9 @@ def on_draw(self):
5087 # the screen to the background color, and erase what we drew last frame.
5188 self .clear ()
5289
90+ with self .camera .activate ():
91+ self .scene .draw ()
92+
5393 # Call draw() on all your sprite lists below
5494
5595 def on_update (self , delta_time ):
@@ -79,23 +119,62 @@ def on_mouse_motion(self, x, y, delta_x, delta_y):
79119 """
80120 Called whenever the mouse moves.
81121 """
82- pass
122+ if self .mouse_pan :
123+ # If the middle mouse button is pressed, we want to pan the camera
124+ # by the amount of pixels the mouse moved, divided by the zoom level
125+ # to keep the panning speed consistent regardless of zoom level.
126+ # The camera position is updated by adding the delta_x and delta_y
127+ # values to the current camera position, divided by the zoom level.
128+ # This is done using the add function from the operator module to
129+ # add the delta_x and delta_y values to the current camera position.
130+ self .camera .position = tuple (
131+ map (
132+ add ,
133+ self .camera .position ,
134+ (- delta_x * 1 / self .camera .zoom , - delta_y * 1 / self .camera .zoom ),
135+ )
136+ )
137+ return
83138
84139 def on_mouse_press (self , x , y , button , key_modifiers ):
85140 """
86141 Called when the user presses a mouse button.
87142 """
88- pass
143+ if button == arcade .MOUSE_BUTTON_MIDDLE :
144+ self .mouse_pan = True
145+ return
89146
90147 def on_mouse_release (self , x , y , button , key_modifiers ):
91148 """
92149 Called when a user releases a mouse button.
93150 """
94- pass
151+ if button == arcade .MOUSE_BUTTON_MIDDLE :
152+ self .mouse_pan = False
153+ return
154+
155+ def on_mouse_scroll (self , x : int , y : int , scroll_x : int , scroll_y : int ) -> None :
156+ """Called whenever the mouse scrolls."""
157+ # If the mouse wheel is scrolled, we want to zoom the camera in or out
158+ # by the amount of scroll_y. The zoom level is adjusted by adding the
159+ # scroll_y value multiplied by a zoom factor (0.1 in this case) to the
160+ # current zoom level. This allows for smooth zooming in and out of the
161+ # camera view.
162+
163+ self .camera .zoom += scroll_y * 0.1
164+
165+ # The zoom level is clamped to a minimum of 0.1 to prevent the camera
166+ # from zooming out too far.
167+ if self .camera .zoom < 0.1 :
168+ self .camera .zoom = 0.1
169+
170+ # The zoom level is clamped to a maximum of 10 to prevent the camera
171+ # from zooming in too far.
172+ if self .camera .zoom > 2 :
173+ self .camera .zoom = 2
95174
96175
97176def main ():
98- """ Main function """
177+ """Main function"""
99178 # Create a window class. This is what actually shows up on screen
100179 window = arcade .Window (WINDOW_WIDTH , WINDOW_HEIGHT , WINDOW_TITLE )
101180
@@ -105,10 +184,12 @@ def main():
105184 # Show GameView on screen
106185 window .show_view (game )
107186
187+ # Reset the game to the initial state
188+ game .reset ()
189+
108190 # Start the arcade game loop
109191 arcade .run ()
110192
111193
112-
113194if __name__ == "__main__" :
114195 main ()
0 commit comments