Pygame: How to ignore collisions - pygame

Okay I am making a 2D scroller game with pygame but want to be able to control when to take collisions into consideration. For example, after my player collides and dies he respawns straight away in the middle of the screen, the problem is that there is often another collision object close by which kills the player instantly. What I want is some small time period in which the player is immured to collisions allowing it to move away to safety first then carry on playing ad normal. I was thinking maybe placing the respawns in a dummy sprite group then over time remove and add it to another group that has collisions. I don't really know.

When the player dies, I would set a variable with the number of frames you want it to be invulnerable for. When you do your collision detection, you can check if the player has any frames of invulnerability left, and only handle collisions when there are no frames left.
def kill_player(player):
# handle moving the player after death, anything else you need to do
# set player invulnerability to 30 frames
player_invulnerable_frames = 30
if environment_rect.collides(player_rect) and player_invulnerable_frames = 0:
# perform collision response stuff here
In your game loop, or maybe an update function, you can decrease the number of invulnerability frames if it is currently greater than zero
while(running):
# your game loop stuff
if player_invulnerable_frames > 0:
player_invulnerable_frames -= 1

Related

How do I iterate through a number of sprites frame by frame when i move my character to the right?

I have never made a html5 game before and i made some sprites for a simple crossing game. I would like to make my character use a array of four different sprite frames when moving to the right and then cycle through till the last one until i stop moving, where by it then reverses the loop and cycles back to the original sprite frame.
I would like to have that function for both left and right movement. I want the same function but with sprites facing the opposite way when moving left.
If my character collides with a enemy sprite i want the fifth sprite frame for each direction to trigger and stay the sprite when game over. It is a game over sprite which two exist, one for each direction the player was moving when they collided with the enemy. total sprites for player is 10, five for each direction of which four are used each way unless a collision happens where the fifth of the particular direction is triggered.
The enemy sprites consist of only two frames that cycle over and over infinitly until the game is over.
The last frame is for the goal which is a static frame which does not change.
How can I make this work?
I am new so i have no idea if or how exactly I should build a array to cycle through the images for each direction or if i should do some for loop or if loop or for eachloop?
To get a cycling index from an incrementing number, use the modulo operator:
sprite_index = step_number % 4
then sprite_index will be 0,1,2,3,0,1,2,3,0,1,2,3,... as step_number increases like 0,1,2,3,4,5,6,7,8,9,10,11...
Don't use a loop because you will already have a loop for moving the characters and so on anyway. An extra loop inside that will stop the main loop while it runs.

AS3 landing smoothly under affect of Gravity

I'm attempting a to make a fighting game with multiple platforms. I've successfully made the controls, movement, (double)jumping, and gravity parts of the game.
The issue is, when a player jumps, upon reaching the ground, they seem to go a bit deeper than they should on the platform (they should land and stay on the surface of the platform). This is more visible when the player double jumps.
I know why this happens; it's because sometimes hitTestObject takes a while to react when objects come in too quickly.
So, the first thing I thought of is to make the player's foot's y axis equal to the y axis of the top of the platform he lands on.
Though, that solution resulted in a rather jerky landing.
My question is: Is there a way to make the player to land smoothly on the top surface of the platform?
Some things I've tried:
-Raising FPS, it just made the same effect happen, but more quickly.
-Decreasing the speed at which the player falls, but that makes the game less fun, so I've crossed it out.
And here's my relevant code:
stage.addEventListener(Event.ENTER_FRAME, loop);
var jumpConstant:Number = 30;
var gravityConstant:Number = 1.8;
function loop(e:Event):void //happens
{
if(player.leg1.foreleg1.foot1.hitTestObject(platforms.ground)||player.leg2.foreleg2.foot2.hitTestObject(platforms.ground)) //if either of the player's legs are colliding with the platform [ps: nested movieclips]
{
player.ySpeed = 0; //the player stops going downwards
player.y = platforms.y; //the player's y becomes the platform's y. don't worry, it puts the player in the right place, just not smoothly.
if (player.b_up) //if Up control button (W or Up Arrow) is being pressed
{
player.ySpeed = -player.jumpConstant; //make the player jump
}
else //if the player isn't colliding with the platform
{
player.ySpeed += player.gravityConstant; //the player is affected by gravity and is pulled downwards
}
Link to the game if you wanna try it out to see the jerky effect:
http://www.fastswf.com/-64Ux3I
The problem is that you are only checking for a collision at increments of ySpeed. Since y speed increases during a fall by 1.8 per step, you are quickly looking at collision checks spaced widely apart. If you want pixel precise collision checks, you need to check for collision at 1px increments. This means if y speed is 10, you need 10 collision checks during one loop update. Use a for loop within your loop function to accomplish this.
Why don't you set hitTestObject y coordinates a bit above the ground so the sinking into the ground will actually make it touch the ground now.

Actionscript 3 - lock the code from restarting while it loops

I am making a boardgames in flash, with a background with moving objects.
It goes on repeat, so they dont stop on the last frame, which in this case is 60 frames. Only problem is, the actionscript code which has its own layer, and exists on frame 1, resets every time it starts over again, logically enough. But then I loose all the data I´ve gained over the time of 60 frames.
Is there a way I can make the actionscript code unbound from the objects loop?
Cheers
On the last frame of your animation, add a bit of AS3 code to force skipping frame 1:
gotoAndPlay ( 2 );
When the playhead reaches the last frame, this line will execute and your animation will restart at frame #2, skipping the code on frame #1.

Draggable object with multiple boundaries

I have my player dragged around the stage. If the player hits any object(All perfect rectangles) that I lay out in a movieclip, I'd like the player to hit a wall and stop moving. What's the most efficient way to write this?
Do I loop through all the points the player can't hit?
There are built in methods for hit testing, you loop through all the objects you want to hit test against (make each it's own sprite or hit test the entire sprite that contains all the parts against the object depending on what kinds of info you want to have. You may also want to rig up your own custom Sprite that has hit regions for the left right top and bottom to determine which edge the player has hit.
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/display/DisplayObject.html#hitTestObject()
Multiple hittest AS3

Best practices: ENTER_FRAME vs. Timer

I'm creating a Flash game which is based on the old Pacman and I'm not sure which is the best way to control the animation.
As I understand it these type of games were originally dependent on a game loop which ran faster or slower depending on the CPU, which is why I imagine that the most similar to use would be the ENTER_FRAME event.
This however presents the problem of having to have a specific frame rate and changing it later is out of the question, not to mention being limited to very few different "speeds" (see below). An example could be that the sprite has to move 12 pixels before the next move is determined. If the speed is then 4 pixels per frame, the math is quite simple:
[...]
public var stepCount:uint = 0;
[...]
function enterFrameHandler(e:Event):void
{
if(stepCount==0) {
//Some code to evaluate next move. Let's say it evaluates to MOVE RIGHT
}
if(MOVE_RIGHT)
{
x += 4;
}
stepCount++;
if(stepCount > 2)
{
stepCount = 0; //Now ready to evaluate direction again.
}
}
This all works fine, but let's say that I want the sprite to move 5 pixels per frame. Then the number of frames before making the next evaluation would not compute. The stepSize would have to be a multiple of 12, which limits the different possible speeds (1,2,3,4 and 6 pixels per frame).
This is why I attempted to base the movement on a Timer instead, which I also managed to get to work, but the movement was somewhat erratic and it seemed like the Timer was using far more memory than the ENTER_FRAME event. Instead of an even movement the Timer made the sprite slow down and speed up and slow down again.
Another possible solution could be the Tween class, but it seems extravagant.
Does anyone have experience with what works best in other games?
Morten Twellmann
You have several separate issues here. Your first question is, should you execute your game loop in a frame event or a timer event? The answer is easy - you should do it in a frame event. The reason is that regardless of how you move your characters, the screen is updated precisely once per frame. So any time you're calling your game loop more than once per frame you're wasting CPU, and any time you call it less than once per frame, you're sacrificing visual quality. So this one is easy, don't bother with timer events at all.
The next question is whether your game's movement should be tied to frames or miliseconds, and the answer is that it depends on the game. Ask yourself this: suppose that some user is playing your game, and their spaceship (or whatever) is flying along at a given speed. Suddenly, the user's anti-virus package does something heavy, and the CPU spike causes Flash to stop updating for one second. Once the spike is over, do you want the spaceship to continue moving from where it was when the spike started? Or do you want it to jump forwards to where it would be if it had continued moving during the spike? If you want the former, you should tie your movement to frames; if you want the latter, you should tie it to miliseconds. But which one is best depends on how you want your game to work.
The final question is, how exactly should you move the characters in your game? Based on what you wrote, I'd do it as follows. For frame-based movement (i.e. the first approach described earlier):
// the ship moves 25 pixels per second
var shipSpeed:Number = 25;
// the number of seconds per frame, based on the published framerate
var frameTime:Number = 1 / stage.frameRate;
// game loop called each frame:
function gameLoop() {
// ...
playerShip.x += shipSpeed * frameTime;
// ....
}
This way, the ship's movement on screen is constant, regardless of what framerate you publish your SWF at. Using a higher framerate simply makes the movement smoother. Likewise, to tie your movement to time instead of frames, simply change "frameTime" in the code above to refer to the time elapsed since the previous frame, as described in Allan's answer.
Yes frame rates will vary depending on CPU amongst other things. Therefore you need to take this into account with your game loop. What I like to do is get the time difference between the current frame and the old frame and use that value in my calculations. So if it happens that there is a delay the larger difference value will then make up for the fact less frames ran.
var _previousTime:Number;
//gameLoop is the function called on ENTER_FRAME
public function gameLoop(e:Event):void
{
var currentTime:Number = getTimer();
var difference:Number = currentTime - _previousTime;
_previousTime = currentTime;
//use difference variable with calculations involving movement
}