def endstep(self, game, state, frametime): player = self.get_player(game, state) # check if we are on the ground before moving (for walking over 1 unit walls) onground = True # first we move, ignoring walls self.x += self.hspeed * frametime # if we are in a wall now, we must move back if game.map.collision_mask.overlap(self.collision_mask, (int(self.x), int(self.y))): # but if we just walked onto a one-unit wall it's ok # but we had to be on the ground if onground and not game.map.collision_mask.overlap(self.collision_mask, (int(self.x), int(self.y - 6))): while game.map.collision_mask.overlap(self.collision_mask, (int(self.x), int(self.y))): self.y -= 1 # but sometimes we are so fast we will need to take two stairs at the same time elif onground and not game.map.collision_mask.overlap(self.collision_mask, (int(self.x), int(self.y - 12))) and game.map.collision_mask.overlap(self.collision_mask, (int(self.x - 6 * function.sign(self.hspeed)), int(self.y))): while game.map.collision_mask.overlap(self.collision_mask, (int(self.x), int(self.y))): self.y -= 1 else: self.x = math.floor(self.x) # move back to a whole pixel - TODO math.floor/math.ceil depending on direction # and if one pixel wasn't enough while game.map.collision_mask.overlap(self.collision_mask, (int(self.x), int(self.y))): self.x -= function.sign(self.hspeed) self.hspeed = 0 #downward stairscript with hspeed checks if onground and not game.map.collision_mask.overlap(self.collision_mask, (int(self.x), int(self.y + 6))): if game.map.collision_mask.overlap(self.collision_mask, (int(self.x), int(self.y + 7))): self.y += 6 elif game.map.collision_mask.overlap(self.collision_mask, (int(self.x), int(self.y + 13))): if (self.hspeed !=0): if game.map.collision_mask.overlap(self.collision_mask, (int(self.x + function.sign(self.hspeed)*-6), int(self.y + 7))) and not game.map.collision_mask.overlap(self.collision_mask, (int(self.x + 6), int(self.y + 1))): self.y += 12 # same stuff, but now vertically self.y += self.vspeed * frametime if game.map.collision_mask.overlap(self.collision_mask, (int(self.x), int(self.y))): self.y = float(int(self.y)) while game.map.collision_mask.overlap(self.collision_mask, (int(self.x), int(self.y))): self.y -= function.sign(self.vspeed) self.vspeed = 0 player.last_left = player.left; player.last_right = player.right;
def step(self, game, state, frametime): # FIXME: MAKE THIS WORK FOR NEGATIVE frametime! # GMK-GG2 tried to emulate basic acceleration and air resistance with two simple instructions: # [execute 30 times per second] # speed += 1 # speed *= 0.92 # Underneath is the same thing converted to work with frametime. # PS: If you ever have the chance, please bash whoever had the idea of a non-standard exponential function for a rocket in an 8-bit game on the head. Thank you. self.speed /= 30 n = 30 * frametime self.speed = (0.92**n) * self.speed + 0.92*((1 - (0.92**n))/(1 - 0.92)) self.speed *= 30 self.hspeed = math.cos(math.radians(self.direction)) * self.speed * function.sign(frametime) self.vspeed = math.sin(math.radians(self.direction)) * (-self.speed) * function.sign(frametime)
def step(self, game, state, frametime): player = self.get_player(game, state) # this is quite important, if hspeed / 20 drops below 1 self.animoffset will rapidly change and cause very fast moving legs (while we are moving very slow) if abs(self.hspeed) > 20: self.animoffset += frametime * abs(self.hspeed) / 20 self.animoffset %= 2 if abs(self.hspeed) == 0: self.animoffset =0 self.flip = not (player.aimdirection < 90 or player.aimdirection > 270) # if we are holding down movement keys, move if player.left: self.hspeed -= self.acceleration * frametime if player.right: self.hspeed += self.acceleration * frametime # Friction: if abs(self.hspeed) < 10: self.hspeed = 0 else: self.hspeed -= function.sign(self.hspeed) * min(abs(self.hspeed), 600 * frametime) if player.up: self.jump(game, state) # gravitational force self.vspeed += 300 * frametime # TODO: air resistance, not hard limit self.vspeed = min(800, self.vspeed) self.hspeed = min(self.max_speed, max(-self.max_speed, self.hspeed))
def endstep(self, game, state, frametime): player = self.get_player(state) # check if we are on the ground before moving (for walking over 1 unit walls) onground = True # first we move, ignoring walls self.x += self.hspeed * frametime # if we are in a wall now, we must move back if state.map.collision_mask.overlap(self.collision_mask, (int(round(self.x)), int(round(self.y)))): # but if we just walked onto a one-unit wall it's ok # but we had to be on the ground if onground and not state.map.collision_mask.overlap(self.collision_mask, (int(round(self.x)), int(round(self.y - 6)))): while state.map.collision_mask.overlap(self.collision_mask, (int(round(self.x)), int(round(self.y)))): self.y -= 1 # but sometimes we are so fast we will need to take two stairs at the same time elif onground and not state.map.collision_mask.overlap(self.collision_mask, (int(round(self.x)), int(round(self.y - 12)))) and state.map.collision_mask.overlap(self.collision_mask, (int(round(self.x - 6 * function.sign(self.hspeed))), int(round(self.y)))): while state.map.collision_mask.overlap(self.collision_mask, (int(round(self.x)), int(round(self.y)))): self.y -= 1 else: if self.hspeed < 0: self.x = math.floor(self.x) # move back to a whole pixel else: self.x = math.ceil(self.x) # and if one pixel wasn't enough while state.map.collision_mask.overlap(self.collision_mask, (int(round(self.x)), int(round(self.y)))): self.x -= function.sign(self.hspeed) * function.sign(frametime) self.hspeed = 0 # same stuff, but now vertically self.y += self.vspeed * frametime if state.map.collision_mask.overlap(self.collision_mask, (int(round(self.x)), int(round(self.y)))): self.y = float(round(self.y)) while state.map.collision_mask.overlap(self.collision_mask, (int(round(self.x)), int(round(self.y)))): self.y -= function.sign(self.vspeed) * function.sign(frametime) self.vspeed = 0 player.last_left = player.left player.last_right = player.right
def destroy(self, game, state, frametime): if not self.max_flight_time - self.flight_time < self.fade_time: for obj in state.entities.values(): if ( isinstance(obj, character.Character) and math.hypot(self.x - obj.x, self.y - obj.y) < self.blastradius ): # w and h are the width and height of the collision mask of the character w, h = obj.collision_mask.get_size() # x and y are here a vector from the rocket to the character x = self.x - obj.x y = self.y - obj.y # we try to find out the crosspoint of that vector with the collision rectangle f = w / (2 * x) if abs(f * y) < h / 2: # the vector crosses the rectangle at the sides x = function.sign(x) * w / 2 y *= f else: # the vector crosses the rectangle at the bottom or top f = h / (2 * y) x *= f y = function.sign(y) * h / 2 # x and y are now the positions of the point on the edge of the collision rectangle nearest to the rocket # now get the vector from the rocket to that point, and store it in x and y x = (obj.x + x) - self.x y = (obj.y + y) - self.y length = math.hypot(x, y) force = (1 - (length / self.blastradius)) * self.knockback obj.hspeed += force * (x / length) obj.vspeed += force * (y / length) super(Rocket, self).destroy(state)