I want something like: if -finished drawn- : do somthing. What is the code for that ' finished drawn.
I want it because here is what happen (I'm using Tiled, but people say it is not Tiled fault, but still I will just put this here to be save than sorry heh, also detection collide code is at the end, but it work fine once the game properly draw everything so I guess collide code is not the problem):
run the game
screen black in a certain time, I assume it is loading here (like convert_alpha or other things, but not doing thing that could use for check collide_rect yet)
screen have every sprite like it support to be.
Now if before it loading I press Left (or any button that change position of player), this will happen:
run the game
2.1. press Left (let say keep press it until screen have sprite)
2.2. screen black in a certain time
- screen have every sprite, but sprite of player had been updated to new position, so the player will pass any obstacle that the game doesnt want it to pass.
So the problem is, the game still update player position, while the game still loading other things that make it think there is nothing for collide. I guess it is something like this: when loading a map, screen doesnt have any sprite yet, so the screen doesnt have any Rect. My code for collide check depend on Rect, so the game think that there is no collide, it doesnt stop player.
My resolve for this is, I create an atribute: moment_change_map for class Game, so everytime the game make a new map, and loading things when doing so, it will update that attribute: moment_change_map = pg.time.get_ticks(). And while the game loading things that doesnt use for check collide, the game will check:
`if pg.time.get_ticks() - moment_change_map > duration_save_to_update_position:
-update position-`
So only after a save certain time, that the game had finished loading everything used for that map (and things used for check collide), only then it will let the position got updated, and the game can check for collide like normal.
But I dont know how much is that 'duration_save_to_update_position' should be( it should be vari base on different map), and if that duration too long, the screen will draw the map long before draw obstacle on it, that would look kind of ugly to the game, also maybe there is better way to solve this that I dont know. And also maybe my guess about what happen is wrong.
Here is the code:
class Game:
...
load map
game_folder = path.dirname(__file__)
map_folder = path.join(game_folder, 'maps')
self.map = TiledMap(path.join(map_folder, self.curr_map ))
self.map_img = self.map.make_map()
self.map_rect = self.map_img.get_rect()
load obstacle on map:
for tile_object in self.map.tmxdata.objects:
if tile_object.name == 'player':
self.player = Player(self, tile_object.x, tile_object.y)
if tile_object.name == 'wall':
Wall(self, tile_object.x, tile_object.y,
tile_object.width, tile_object.height)
(I guess when use Tiled everyone do same steps so I dont need to write code for TiledMap here)
def update(self):
self.all_sprites.update()
class Wall and class Player are all have self.groups = game.all_sprites.
detecton collide:
def check_collide(sprite, group):
if vec(sprite.pos2) - vec(sprite.pos1) != vec(0, 0):
sprite.delta_pos = vec(sprite.pos2) - vec(sprite.pos1)
len = vec(sprite.delta_pos).length()
part = round(len)
if part == 0:
part = 1
b = False
b1 = False
for i in range(part + 1):
sprite.pos = vec(sprite.pos1) + vec(sprite.delta_pos.x / part * i, sprite.delta_pos.y / part * i)
sprite.hit_rect.centerx = vec(sprite.pos).x
sprite.rect.centerx = vec(sprite.pos).x
hit = pg.sprite.spritecollide(sprite, group, False, collide_hit_rect)
if hit:
if hit[0].rect.centerx > sprite.hit_rect.centerx:
sprite.hit_rect.centerx = hit[0].rect.left - sprite.hit_rect.width / 2
if hit[0].rect.centerx < sprite.hit_rect.centerx:
sprite.hit_rect.centerx = hit[0].rect.right + sprite.hit_rect.width / 2
sprite.pos.x = vec(sprite.hit_rect.center).x
sprite.rect.centerx = vec(sprite.pos).x
b1 = True
sprite.hit_rect.centery = vec(sprite.pos).y
sprite.rect.centery = vec(sprite.pos).y
hit = pg.sprite.spritecollide(sprite, group, False, collide_hit_rect)
if hit:
if hit[0].rect.centery > sprite.hit_rect.centery:
sprite.hit_rect.centery = hit[0].rect.top - sprite.hit_rect.height / 2
if hit[0].rect.centery < sprite.hit_rect.centery:
sprite.hit_rect.centery = hit[0].rect.bottom + sprite.hit_rect.height / 2
sprite.pos.y = vec(sprite.hit_rect.center).y
sprite.rect.centery = vec(sprite.pos).y
b = True
if b == True or b1 == True:
break
Basically if a sprite position got changed, I will break it down to each small vector and check after each small vector it will collide or not, this can prevent player 'teleport' pass obstacle when player vel become too large and player pos will get updated in one frame by a large amount pos += vel*dt. But it didnt do its job when map is loading so I guess the problem is at the time loading, there is nothing drawn to check collide for
draw code:
self.screen.blit(self.map_img, self.camera.apply_rect(self.map_rect))
for sprite in self.all_sprites:
self.screen.blit(sprite.image, self.camera.apply(sprite))
pg.display.flip()
loop game:
def run(self):
self.playing = True
while self.playing:
self.dt = self.clock.tick(FPS) / 1000 #0.016ms
self.events()
self.update()
self.draw()
To sum up: how will u solve that problem?