diff --git a/data/images/entities/partner.png b/data/images/entities/partner.png new file mode 100644 index 0000000..6323690 Binary files /dev/null and b/data/images/entities/partner.png differ diff --git a/data/maps/map_1.csv b/data/maps/map_1.csv index b984a72..79d7ac1 100644 --- a/data/maps/map_1.csv +++ b/data/maps/map_1.csv @@ -4,16 +4,16 @@ 2,1,1,1,1,1,1,1,1,1,1,1,1,1,2 2,1,1,1,1,1,1,1,1,1,1,1,1,1,2 2,1,1,1,1,1,1,1,1,1,1,1,1,1,2 +2,1,1,1,1,2,2,2,1,1,1,1,1,1,2 +2,1,1,1,1,2,1,1,1,1,1,1,1,1,2 +2,1,1,1,1,2,1,1,1,1,1,1,1,1,2 2,1,1,1,1,1,1,1,1,1,1,1,1,1,2 2,1,1,1,1,1,1,1,1,1,1,1,1,1,2 -2,1,1,1,1,1,1,1,1,1,1,1,1,1,2 -2,1,1,1,1,1,1,1,1,1,1,1,1,1,2 -2,1,1,1,1,1,1,1,1,1,1,1,1,1,2 -2,1,1,1,1,1,1,1,1,1,1,1,1,1,2 -2,1,1,1,1,1,1,1,1,1,1,1,1,1,2 -2,1,1,1,1,1,1,1,1,1,1,1,1,1,2 -2,1,1,1,1,1,1,1,1,1,1,1,1,1,2 -2,1,1,1,1,1,1,1,1,1,1,1,1,1,2 +2,1,1,1,1,3,1,1,1,1,1,1,1,1,2 +2,1,1,1,1,3,1,1,1,1,1,1,1,1,2 +2,1,1,1,3,3,1,1,1,1,1,1,1,1,2 +2,1,1,1,1,3,1,1,1,1,1,1,1,1,2 +2,1,1,1,1,3,1,1,1,1,1,1,1,1,2 2,1,1,1,1,1,1,1,1,1,1,1,1,1,2 2,1,1,1,1,1,1,1,1,1,1,1,1,1,2 2,1,1,1,1,1,1,1,1,1,1,1,1,1,2 diff --git a/game.py b/game.py index f9f0261..1564405 100644 --- a/game.py +++ b/game.py @@ -1,7 +1,7 @@ import pygame import numpy as np from scripts.tiles import Tilemap -from scripts.entities import Entity +from scripts.entities import Entity, Partner, GroupEntities from scripts.utils import load_image, load_images, to_isometric_pixel from scripts.camera import Camera @@ -20,39 +20,46 @@ class Game: self.clock = pygame.time.Clock() self.player = Entity(self, 'player', (64., 64.), (28, 42)) + self.partner = Partner(self, (80.,80.), (28,42)) + self.entities = GroupEntities(self, [self.player, self.partner]) self.assets = { 'player' : load_image('entities/player.png'), + 'partner': load_image('entities/partner.png'), #'grass' : load_images('tiles/grass/'), #'stone' : load_images('tiles/stone/') 'iso' : load_images('tiles/iso/') } self.tilemap = Tilemap(self, (64,32), 'map_1.csv') self.camera = Camera(self) + def render(self): + self.display.fill('white') + self.tilemap.render(self.display, offset = self.camera.scroll) + self.entities.render(self.display, offset = self.camera.scroll) + #self.player.render(self.display, offset = self.camera.scroll) + #self.partner.render(self.display, offset = self.camera.scroll) + self.screen.blit(pygame.transform.scale(self.display,self.screen.get_size()), (0,0)) + pygame.display.update() def run(self): self.status = True while self.status: - self.display.fill('white') delta = np.array([0.0,0.0]) for event in pygame.event.get(): if event.type == pygame.QUIT: self.status = False keys = pygame.key.get_pressed() if keys[pygame.K_LEFT]: - delta[0] -= 5 + delta += np.array([-5,5]) if keys[pygame.K_RIGHT]: - delta[0] += 5 + delta += np.array([5,-5]) if keys[pygame.K_UP]: - delta[1] -= 5 + delta += np.array([-5,-5]) if keys[pygame.K_DOWN]: - delta[1] += 5 - #print(self.tilemap.physics_rects_around(self.player.pos)) - print(self.player.pos) + delta += np.array([5,5]) + self.camera.update() self.player.update(self.tilemap, delta) - self.tilemap.render(self.display, offset = self.camera.scroll) - self.player.render(self.display, offset = self.camera.scroll) - self.screen.blit(pygame.transform.scale(self.display,self.screen.get_size()), (0,0)) - pygame.display.update() + self.partner.update() + self.render() self.clock.tick(60) pygame.quit() diff --git a/scripts/entities.py b/scripts/entities.py index 24bb303..aa70a9e 100644 --- a/scripts/entities.py +++ b/scripts/entities.py @@ -33,3 +33,45 @@ class Entity: surface.blit(self.game.assets[self.type], to_isometric_pixel(self.pos-np.array([48,80]))*np.array([1,0.5])-offset) def rect(self): return pygame.Rect(self.pos, self.size) + +class Partner(Entity): + def __init__(self, game, pos, size): + super().__init__(game, 'partner', pos, size) + self.player = game.player #player a cui รจ linkato + def update(self): + R = 50 + player_pos = self.player.pos + if np.linalg.norm(player_pos-self.pos) <= R: + return + a = np.stack([player_pos, self.pos]) + if np.linalg.det(a) == 0: + line_coeffs = np.append(np.linalg.lstsq(a,np.array([[0.0],[0.0]]),rcond=None)[0],0) + else: + line_coeffs = np.append(np.linalg.lstsq(a,np.array([[1.0],[1.0]]),rcond=None)[0],1) + if np.abs(line_coeffs[1])<1e-7: + P3 = np.array([self.pos[0], player_pos[1] + R]) #np.sqrt(R ** 2 - (x - player_pos[0]) ** 2) + P4 = np.array([self.pos[0], player_pos[1] - R]) + theta = 0 + delta = 0 + else: + m = - line_coeffs[0] / line_coeffs[1] + theta = np.arctan(m) + delta = R * np.array([np.cos(theta),np.sin(theta)]) + P3 = player_pos + delta + P4 = player_pos - delta + P = (P3 if (np.linalg.norm(P3-self.pos) < np.linalg.norm(P4-self.pos)) else P4) + #super().update(tilemap, P - self.pos) #nice idea but sometimes gets blocked and needs to tp to the player + self.pos = P + +class GroupEntities: + def __init__(self, game, entities): + self.game = game + self.entities = entities #sorted(entities, key=(lambda x: x.pos[1])) + def add_entity(self, entity): + self.entities.append(entity) + #def update() + def render(self, surface, offset=np.array([0.,0.])): + self.entities.sort(key = (lambda x: x.pos[1])) + for entity in self.entities: + entity.render(surface, offset) + diff --git a/scripts/utils.py b/scripts/utils.py index f30cf1a..42ca966 100644 --- a/scripts/utils.py +++ b/scripts/utils.py @@ -37,3 +37,25 @@ def to_isometric_pixel(coord): a = np.array([[1,-1],[1,1]]) a = 0.5 * a return np.squeeze(np.matmul(a,coord[:,np.newaxis])) + +class Animation: + def __init__(self, images, img_dur=5, loop=True): + self.images = images + self.img_duration = img_dur + self.loop = loop + self.done = False + self.frame = 0 #in the sense of gameframe, not current frame of the animation + + def copy(self): + return Animation(self.images, self.img_duration, self.loop) + + def update(self): + if self.loop: + self.frame = (self.frame + 1) % (self.img_duration * len(self.images)) + else: + self.frame = min(self.frame + 1, self.img_duration * len(self.images) - 1) + if self.frame >= self.img_duration * len(self.images) - 1: + self.done = True + def img(self): + return self.images[int(self.frame / self.img_duration)] +