Add: Set map rotation

This commit is contained in:
LmeSzinc 2023-08-06 22:19:10 +08:00
parent e41d5b4ae4
commit bfae03bc19
5 changed files with 137 additions and 0 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

View File

@ -33,6 +33,16 @@ JOYSTICK = ButtonWrapper(
button=(234, 546, 262, 574),
),
)
ROTATION_SWIPE_AREA = ButtonWrapper(
name='ROTATION_SWIPE_AREA',
share=Button(
file='./assets/share/map/control/ROTATION_SWIPE_AREA.png',
area=(264, 87, 990, 219),
search=(244, 67, 1010, 239),
color=(255, 255, 255),
button=(264, 87, 990, 219),
),
)
RUN_BUTTON = ButtonWrapper(
name='RUN_BUTTON',
share=Button(

View File

@ -0,0 +1,69 @@
from functools import cached_property
from module.base.timer import Timer
from module.logger import logger
from tasks.map.assets.assets_map_control import ROTATION_SWIPE_AREA
from tasks.map.control.joystick import MapControlJoystick
from tasks.map.minimap.minimap import Minimap
class MapControl(MapControlJoystick):
_rotation_swipe_interval = Timer(1.2, count=2)
@cached_property
def minimap(self) -> Minimap:
return Minimap()
def handle_rotation_set(self, target, threshold=15):
"""
Set rotation while running.
self.minimap.update_rotation() must be called first.
Args:
target: Target degree (0~360)
threshold:
Returns:
bool: If swiped rotation
"""
if self.minimap.is_rotation_near(target, threshold=threshold):
return False
if not self._rotation_swipe_interval.reached():
return False
logger.info(f'Rotation set: {target}')
diff = self.minimap.rotation_diff(target) * self.minimap.ROTATION_SWIPE_MULTIPLY
diff = min(diff, self.minimap.ROTATION_SWIPE_MAX_DISTANCE)
diff = max(diff, -self.minimap.ROTATION_SWIPE_MAX_DISTANCE)
self.device.swipe_vector((-diff, 0), box=ROTATION_SWIPE_AREA.area, duration=(0.2, 0.5))
self._rotation_swipe_interval.reset()
return True
def rotation_set(self, target, threshold=15, skip_first_screenshot=False):
"""
Set rotation while standing.
Args:
target: Target degree (0~360)
threshold:
skip_first_screenshot:
Returns:
bool: If swiped rotation
"""
while 1:
if skip_first_screenshot:
skip_first_screenshot = False
else:
self.device.screenshot()
self.minimap.update_rotation(self.device.image)
self.minimap.log_minimap()
# End
if self.minimap.is_rotation_near(target, threshold=threshold):
logger.info(f'Rotation is now at: {target}')
break
if self.handle_rotation_set(target, threshold=threshold):
continue

View File

@ -363,7 +363,9 @@ class Minimap(MapResource):
self.update_position(image)
self.update_direction(image)
self.update_rotation(image)
self.log_minimap()
def log_minimap(self):
# MiniMap P:(567.5, 862.8) (1.00x|0.439|0.157), D:303.8 (0.253), R:304 (0.846)
logger.info(
f'MiniMap '

View File

@ -43,6 +43,12 @@ class ResourceConst:
# Pad 600px, cause camera sight in game is larger than GIMAP
BIGMAP_BORDER_PAD = int(600 * BIGMAP_SEARCH_SCALE)
# Swipe 400px is about 85~90 degree
# <rotation_diff> * ROTATION_SWIPE_MULTIPLY = <distance_to_swipe>
ROTATION_SWIPE_MULTIPLY = 400 / 85
# Max distance in one swipe, limited in -600px~600px
ROTATION_SWIPE_MAX_DISTANCE = 600
def __init__(self):
# Usually to be 0.4~0.5
self.position_similarity = 0.
@ -50,6 +56,8 @@ class ResourceConst:
self.position_similarity_local = 0.
# Current position on GIMAP with an error of about 0.1 pixel
self.position: tuple[float, float] = (0, 0)
# Minimap scale factor, 1.0~1.25
self.position_scale = 1.0
# Usually > 0.3
# Warnings will be logged if similarity <= 0.8
@ -82,3 +90,51 @@ class ResourceConst:
file = self.filepath(file)
print(f'Save image: {file}')
Image.fromarray(image).save(file)
def position_diff(self, target):
"""
Args:
target: Target position (x, y)
Returns:
float: Distance to current position
"""
x1, y1 = self.position
x2, y2 = target
diff = ((x2 - x1) ** 2 + (y2 - y1) ** 2) ** 0.5
return diff
def is_position_near(self, target, threshold=5):
return self.position_diff(target) <= threshold
def direction_diff(self, target):
"""
Args:
target: Target degree (0~360)
Returns:
float: Diff to current direction (-180~180)
"""
diff = (self.direction - target) % 360
if diff > 180:
diff -= 360
return diff
def is_direction_near(self, target, threshold=15):
return abs(self.direction_diff(target)) <= threshold
def rotation_diff(self, target):
"""
Args:
target: Target degree (0~360)
Returns:
float: Diff to current rotation (-180~180)
"""
diff = (self.rotation - target) % 360
if diff > 180:
diff -= 360
return diff
def is_rotation_near(self, target, threshold=15):
return abs(self.rotation_diff(target)) <= threshold