I am using Cocos2d v3 with Chipmunk for physics in my game. My game has a ball that falls down onto a platform with a trap door in it. The platform and the doors are static objects so they will not fall down from the balls velocity or from gravity. The player is in control of opening the trap door, so if the ball is set to rest on the platform or doors it will eventually fall asleep. Once the ball is set to sleeping, when the trap door is opened it won't recognize that an object is no longer under the ball so the ball won't move.
Right now I have a function being called every 0.2 seconds to check on the ball. If it is asleep it sets its velocity to (0, 0) which wakes the ball up. The only problem is that this way reduces the frame rate of the game from 60 to 40-50. (I can have up to 30 different balls in the level at once which slows it down that much)
Is there an easy way to keep the ball from falling asleep or to wake it up when the trap door opens? Or is there a way to keep my trap doors dynamic and not static but not have them move when the ball collides with it.
If you need to wake up the body you can try use the activate method of the ChipmunkBody which is used internally by CCPhysicsBody.
I haven't tried this, just found this option by looking into code of cocos2d. Here is some pseudo-code, that might do the trick:
#import "CCPhysics+ObjectiveChipmunk.h"
//Let's pretend this method is called when you open your trap door
-(void)openTrap
{
// Get the body of your ball somehow
CCPhysicsBody *ballBody = ...
// Get the body property of CCPhysicsBody,
// (which is only available if you import the header at the top)
// this will return a ChipmunkBody body, which has an
// activate function to wake up your ball
[ballBody.body activate];
}
Related
My hero sprite is on a physics sprite. If the player (user) doesn't move the hero for 2 seconds while touching the sprite I want to end the game. In the update method I am checking to see if the two sprites are touching for longer than 2 seconds and if true run "game over" action. This is the code
if( TWO SPRITES ARE TOUCHING && USER ISN"T TOUCHING THE SCREEN ){
[_hero runAction:[CCActionSequence actions:[CCActionDelay actionWithDuration:2.0f],
_gameOverAction,
nil]];
}
The end game action runs even if the user is holding down. Basically if you don't touch the screen to move the sprite the game should end. Any suggestions?
In your current code as soon as two sprites are touching and the user isn't touching the screen it will quick off the action. It will happen in 2 seconds no matter what as it is never cancelled.
What you need to do instead is keep a variable of the time it last happened and check to see if 2 seconds have passed since then in your update loop. If it has then you can call the game over method.
I am working on a platformer game using cocos2d with box2d in which i have ground body that must continuously move to left and right, but doesn't fall when player jumps onto it. I am not able to do so, my body falls when player jump onto it. Provide me some link or code to do so.
I think the best solution is to move the sprite for the platform, not the platform itsef.
Instead of creating a small platform for the jumping, create a rectangle that extends across the entire pit.
Only move the sprite over the region that you want the player to jump on to (i.e. move it left and right so the player knows the "safe" area to jump).
Use the b2ContactListener to detect the collision between the rectangle and the player. If they are in contact and the player is over the moving sprite, then don't do anything different.
If they are in contact and the player is NOT over the moving sprite, disable the collisions response in the PreSolve event of the b2Contact listener and for the entire time the player is in contact with it. The player should fall through to the pit below.
You could also use a sensor body for the moving platform to give you a better "contact mechanism" than just the sprite. So if the player is in contact with the "platform sensor" and the "rectangle across the pit", don't do anything in the PreSolve event. Otherwise, if they are only in contact with the "rectangle across the pit", let them drop through it.
Does this work?
Here is a part of SDL2 code
SDL main function
int main(int argc,char *argv[])
{
...
...
bool quit=false;
SDL_Event e;
while(!quit) ///First while (say)
{
while(SDL_PollEvent(&e)) ///Second while (say)
{
if(e.type==SDL_QUIT)
{
quit=true;
}
handleEvent(e) ;///Function for executing certain event
}
...
SDL_RenderPresent((SDL_Renderer)renderer);
}
}
My question is,what does this SDL_PollEvent() actually do ,and suppose an event occur does the execution goes out of the second while() and call the SDL_RenderPresent() or it waits for all the events to take poll and then SDL_RenderPresent() is called , i am totally confused ?
The above is a very common single thread event loop:
Basically the application is constantly inside the outer while loop. To get the smoothest user experience we try to keep this loop under 17ms (for a 60 frames a sec rate)
Every 'frame' starts by responding to all the events that are waiting in the queue (the inner while):
while(SDL_PollEvent(&e)) ///Second while (say)
{
if(e.type==SDL_QUIT)
{
quit=true;
}
handleEvent(e) ;///Function for executing certain event
}
Events are notifications from the operating system that something happened. It might be that the window is closing SDL_QUIT or that the mouse was moved.
You must respond to these events for the application to be responsive. Usually the response is to change the state of the application.
For example we might see a left-mouse is down event we might find what is "under" the mouse button and indicate that it is now selected. This is normally just finding the object and calling a function that will change its state. All that changes is the boolean value that indicates the object is now selected.
Maybe moving the mouse needs to change the point of view of the next frame so we will update the vector that stores the direction we are looking at. So we update the vector in memory.
You may have long stretches where the event queue is empty and the application does not have any events to handle. And there might be flurries of activity (for instance the user moving the mouse) where you will get lots of events to respond to.
SDL_PollEvent will not "wait" for events. If there is an event in the queue you will get the information. If there is no event it will return false.
Handling events should be done quickly (remember we have to be finished in 17ms) don't worry it is quite a lot of time on a PC.
Once you are done with all the events and out of the inner loop you are ready to move on to updating the world and rendering.
At this point you will normally do stuff like AI. Calling physics engine. For instance you might iterate over the objects and change their position based on their velocity.
The next step is to actually do the drawing.
SDL_RenderClear(renderer);
...
SDL_RenderPresent((SDL_Renderer)renderer);
The first call will clear the screen. You then go and based on the state of different objects do the rendering. For instance maybe because we changed the object state to selected we will now draw a glowing border around it.
Your final call is for SDL_RenderPresent(renderer) to present the new screen to the user
If you are using Vsync (quite common) then this final call will hide a small wait time to synch the screen update with the graphics card capabilities. This will produce a smoother graphics. Assuming a 60Hz refresh rate (60 frames per second) and assuming you are running under 16.6 ms in your frame rendering logic the app will wait the remaining time.
Now the application is ready to go back to the start of the loop and check if there are any events in SDL_PollEvent. Since the entire loop typically only takes a few milliseconds the application will always feel responsive.
I'm developing an Endless Scroller type of game and I need help with ways to spawn enemies. I have two background images that repeat over and over. I spawn the enemy just above the screen then schedule an update to move the position down.
The current way I'm spawning the enemies at the start is just scheduling a selector every 8 seconds, then based on the score, I unschedule the selector and reschedule it again for 6 seconds etc. My character doesnt shoot you just have to navigate around the enemies so the quickest I can have the selector scheduled is 3 seconds otherwise there isnt enough of a gap to get around them.
I'm only new to programming and cocos2d so I'm not to sure how expensive the unschedule and schedule will be.
So basically my question is, Is there a better way of spawning the enemies? keeping in mind that there always has to be a path to survive?
Your options are to either use the ccScheduler, or implement your own via a timer in update(). Something along the lines of if nextWaveTime > timeBetweenWaves. I would recommend using the scheduler in Cocos2D because I'm sure it has some optimizations built in by some very smart people. Also, scheduling is 'a drop in the bucket' compared to the cost of draw calls. Be sure to reuse the enemies if at all possible. When active enemies go off the screen, don't remove them but instead place them back at the desired 'enter screen' point.
I'm working on a two player iOS game that is similar to checkers. I'm using cocos2d to create this game.
I want a think time of .5 seconds between when the player's move renders and when the computer's move renders to simulate think time.
The flow of the game is controlled using NSNotification events and looks like this...
Player (computer or human) submits a move -> The board adds the new sprite -> The game controller updates the current player and asks them to submit a move.
I've tried adding usleep(500000) at the end of the board update or the beginning of the game update. What ends up happening is the sprites added in the board update, for the human player, don't show up until after the computer player has submitted his move. So the game waits 500 milliseconds and then updates with both moves.
Is there a way to force the CCLayer to update its child sprites before the usleep, or is there just a better way of adding this think time?
Thanks
if you schedule for receiving an update in your controller, you could slip time in the update:(ccTime)dt function.
in your .h
float _slipTime;
in your .m
// with other declaratives
static float THINK_TIME=.5f;
// last line before the stall
_slipTime=0.f;
[self schedule:#selector(pauseForThink:)];
-(void) pauseForThink:(ccTime) dt {
_slipTime+=dt;
if(_slipTime>THINK_TIME) {
[self unschedule:#selector(pauseForThink:)];
// trigger here whatever you wanted to accomplish after
// the think pause.
}
}
ok, this is simple, but will prevent the main loop from being blocked (this is what happens with your sleep). When running at 60 FPS, the pauseForThink method will be called about 30 times, and cocos will have 30 draw cycles during the pause.