I am making a slot machine game in iphone. I am using cocos2d as its language. I am greatly disturb coding for the method that will animate score in the game. The animation looks like with the fps. Can you help me do it. Animating the score in cocos2d. Can you share sample code that looks like what i need now. Thanks in advance.
Here is how I do my score. it is not really animated, but if you want it to be like fps this will do it. Just call this method when your score changes.
in your init method:
// create and initialize the _scoreLabel
_scoreLabel = [CCLabel labelWithString:#" "
dimensions:CGSizeMake(labelSizes.width,labelSizes.height)
alignment:UITextAlignmentLeft
fontName:#"Helvetica"
fontSize:20.0];
_scoreLabel.color = ccc3(255,255,255);
_scoreLabel.position = ccp((labelSizes.width / 2), (winSize.height - (labelSizes.height / 2)));
[self addChild:_scoreLabel z:1];
This is the score update method:
-(void)updateScore {
[_scoreLabel setString:[NSString stringWithFormat:#"Score: %d / %d", _score, _scoreToWin]];
}
Then to update the score when the score changes call it like this:
// Then later to set the Score
[self updateScore];
I've done it in this way:
_odd = _odd + _stage*value;
[self schedule:#selector(pointAdder) interval:1.0/(3.0*_odd)];
and
- (void)pointAdder {
if (_odd==0) {
[self unschedule:#selector(pointAdder)];
return;
}
else {
int tmp = [_lblScore.string intValue];
[_lblScore setString:[NSString stringWithFormat:#"%i",tmp+1]];
_odd--;
}
}
Related
I am building SDL2 applications for macOS using C++. I need some "basic" scrolling for an app (like a web browser). I achieve that using the SDL_MouseWheel event, which gives me a fully functional "windows-like" scrolling. I am using a Macbook Pro and I want to bring the trackpad's functionality in.
Simply, I am asking for a better scrolling algorithm (Macbook's trackpad scrolling, inertial scrolling)
I know about the SDL_MultiGesture event, but I don't really know how to put things together to achieve the result I want.
I ran into the same issue, and it turns out that SDL opts out of momentum scroll events by turning off the AppleMomentumScrollSupported default in the user defaults system.
You can turn this back on in your application with the following bit of Objective-C++, and your SDL_MouseWheel events will become smoothed.
NSDictionary *appDefaults = [[NSDictionary alloc] initWithObjectsAndKeys:
[NSNumber numberWithBool:YES], #"AppleMomentumScrollSupported",
nil];
[[NSUserDefaults standardUserDefaults] registerDefaults:appDefaults];
[appDefaults release];
Okay, here's the answer to the problem.
First of all, you will have to do it manually.
I also assume that you know SDL2 and C++.
*Note: I'm doing scrolling only for Y-Axis (you can do it for both if you want).
Firstly we will need some variables:
int scrolling; // flag (scrolling or not)
int scroll_sensitivity = 40; // how fast we want to scroll
double scroll_Y = 0; // current scrolling amount (on Y-Axis)
double scroll_acceleration; // scrolling speed
double scroll_friction = 0.001; // how fast we decelerate
double scroll_prev_pos; // previous event's position
After that you will need to handle the SDL_MultiGesture event:
case SDL_MULTIGESTURE:{
if(event.mgesture.numFingers == 2){
if(scrolling == 0){
scrolling = 1;
scroll_prev_pos = event.mgesture.y;
} else{
double dy = event.mgesture.y - scroll_prev_pos;
scroll_acceleration = dy * 40;
scroll_prev_pos = event.mgesture.y;
scrolling = 1;
}
}
break;
}
Also, we need to stop scrolling on SDL_FingerDown event:
case SDL_FINGERDOWN:{
scrolling = 0;
break;
}
Next, we want to update scroll_Y (put it in your "update" function):
if(scrolling){
if(scroll_acceleration > 0) scroll_acceleration -= scroll_friction;
if(scroll_acceleration < 0) scroll_acceleration += scroll_friction;
if(abs(scroll_acceleration) < 0.0005) scroll_acceleration = 0;
scroll_Y += scroll_sensitivity * scroll_acceleration;
// Here you have to set your scrolling bounds i.e. if(scroll_Y < 0) scroll_Y = 0;
}
Finally, we want to render according to our scroll values:
SDL_Rect rect = {some_x, some_y + scroll_Y, some_w, some_h};
SDL_RenderCopy(renderer, some_texture, NULL, &rect);
This is it!
I have a fully working app with the above code, so I'm 100% sure that this works as supposed. If you have any problems (because it's not actual code, it's more like an algorithm) contact me. As I mentioned before, I assume that you already know good enough SDL and C++, so I believe that you are able to understand the implementation.
Also, I know that this solution can become better, so if you have anything to add / change, just say it!
Have a nice day!
For some reason, #Aleski's answer doesn't work anymore. The new way to hack this feature back on is:
[[NSUserDefaults standardUserDefaults] setBool: YES
forKey: #"AppleMomentumScrollSupported"];
I'v got trouble getting my sprite to appear on screen using my current method. I got multiple sprites on the screen already, but I'v added this new one in a different manner as I'm going to manipulate it later on (handling different interactions and such). But I don't see why it doesn't appear on the screen when I run the program. I'v tried changing the z order without luck, but that might be because the sprite wasn't added in the init method like the others so the z order doesn't affect it in comparison to the background and such created in the init method. Anyways, got any clue for why it won't draw on screen?
- (void) addMonster {
CCSprite * monster = [CCSprite spriteWithImageNamed:#"Ghost.png"];
// Determine where to spawn the monster along the Y axis
CGSize viewSize = [CCDirector sharedDirector].viewSize;
int minY = monster.contentSize.height / 2;
int maxY = viewSize.height - monster.contentSize.height/2;
int rangeY = maxY - minY;
int actualY = (arc4random() % rangeY) + minY;
// Create the monster slightly off-screen along the right edge,
// and along a random position along the Y axis as calculated above
monster.position = ccp(viewSize.width + monster.contentSize.width/2, actualY);
[self addChild:monster];
// Determine speed of the monster
int minDuration = 2.0;
int maxDuration = 4.0;
int rangeDuration = maxDuration - minDuration;
int actualDuration = (arc4random() % rangeDuration) + minDuration;
// Create the actions
CCActionMoveTo * actionMove = [CCActionMoveTo actionWithDuration:actualDuration
position:ccp(-monster.contentSize.width/2, actualY)];
CCActionCallBlock * actionMoveDone = [CCActionCallBlock actionWithBlock:^(CCNode *node) {
[monster removeFromParentAndCleanup:YES];
}];
[monster runAction:[CCActionSequence actions:actionMove, actionMoveDone, nil]];
}
//The call back function
-(void)gameLogic:(CCTime)dt {
[self addMonster];
}
- (id)init{
// Apple recommend assigning self with supers return value
self = [super init];
if (!self) return(nil);
if( (self = [super init]) ) {
self.userInteractionEnabled = YES;
//How often a new ghost gets produced
[self schedule:#selector(gameLogic:) interval:1.0];
//And some more code none relevant to this keeps going...
I am having the same problem.
The sprites i add do appear, but when i leave the scene and come back, they won't appear. As far as i know sprites needs to be added in the init method. When you add them at a later stage (in my case) they appear only once.
I am still looking for a solution to add the sprites at a later stage than the init method and appears more than once.
Maybe this answer helps you finding a solution.
I'm new to Cocos2D and I'm now trying ABC123 (downloaded from internet, created by kwigbo)
I wonder why it works all fine by the simulator, but while i'm using my iPad to test it.... problem comes up.. I tried for 2weeks but still cannot solve it... hope anyone can teach me?? Thanks a lot....
Originally the bubble will appear AFTER player memorized the word's locations, but when using iPad to run it... the bubble appear soon after started, player cannot remember the word locations for playing the game at all...
I've tried to change the delay part from delayTime = 1.5 to 4;:
#GameLayer.m
float delayTime = 4.0;
if(dataManager.currentlevel > 10) delayTime = 2.5;
[self runAction:[Sequence actions:[DelayTime actionWithDuration:delayTime], [CallFunc actionWithTarget:self selector:#selector(showBubbles)], nil]];
It delay in simulator but didn't change in iPad....
Is there any relationship with OrbSprite.m?
#OrbSprite.m's init:
Label *l = [[Label alloc] initWithString:#"" dimensions:CGSizeMake(50, 50) alignment:UITextAlignmentCenter fontName:#"Arial Rounded MT Bold" fontSize:45];
self.label = l;
[l release];
//[self initWithFile:#"bubble1.png"];
Animation *bub = [Animation animationWithName:#"bubble" delay:1.0f images:#"bubble1.png", #"bubble2.png", nil];
self.bubble = bub;
[bub release];
[self addAnimation:bubble];
Or should I do anything on this line?
- (void) showBubble
{
isBubble = YES;
[self setDisplayFrame:#"bubble" index:1];
self.scale = .1;
[self runAction:[Sequence actions: [ScaleTo actionWithDuration:.1 scale:0.1], [ScaleTo actionWithDuration:.1 scale:1], nil]];
[self removeChild:label cleanup:YES];
}
I have one question when infinite background scrolling is done, is the object remain fixed(like doodle in doodle jump, papy in papi jump) or these object really moves.Is only background move or both (background and object )move.plz someone help me.I am searching for this solution for 4/5 days,but can't get the solution.So plz someone help me. And if object does not move how to create such a illusion of object moving.
If you add the object to the same layer as the scrolling background, then it will scroll as the background scrolls.
If your looking for an effect like the hero in doodle jump, you may want to look at having two or more layers in a scene.
Layer 1: Scrolling Background Layer
Layer 2: Sprite layer
SomeScene.m
CCLayer *backgroundLayer = [[CCLayer alloc] init];
CCLayer *spriteLayer= [[CCLayer alloc] init];
[self addChild:backgroundLayer z:0];
[self addChild:spriteLayer z:1];
//Hero stays in one spot regardless of background scrolling.
CCSprite *squidHero = [[CCSprite alloc] initWithFile:#"squid.png"];
[spriteLayer addChild:squidHero];
If you want objects to scroll with the background add it to the background layer:
//Platform moves with background.
CCSprite *bouncePlatform= [[CCSprite alloc] initWithFile:#"bouncePlatform.png"];
[backgroundLayer addChild:bouncePlatform];
Another alternative is to use a CCFollow action. You would code as if the background is static (which it will be) and the player is moving (which it will be), but add a CCFollow action to the player. This essentially moves the camera so that it tracks your player.
You can also modify the classes so that you can get the CCFollow action to follow with an offset (i.e., so the player is not in the middle of the screen) as well as to have a smoothing effect to it, so that when the player moves, the follow action is not jerky. See the below code:
*NOTE I am using cocos2d-x, the c++ port. The methods are similar in cocos2d, and you should be able to modify these to fit the cocos2d syntax. Or search around -- I found these for cocos2d and then ported to c++.
//defines the action to constantly follow the player (in my case, "runner.p_sprite is the sprite pointing to the player)
FollowWithOffset* followAction = FollowWithOffset::create(runner.p_sprite, CCRectZero);
runAction(followAction);
And separately, I have copied the class definition for CCFollow to create my own class, CCFollowWithAction. This also has a smoothing effect (you can look this up more online) so that when the player moves, the actions are not jerky. I modified "initWithTarget," to take into account an offset, and "step," to add a smoothing action. You can see the modifications in the comments below.
bool FollowWithOffset::initWithTarget(CCNode *pFollowedNode, const CCRect& rect/* = CCRectZero*/)
{
CCAssert(pFollowedNode != NULL, "");
pFollowedNode->retain();
m_pobFollowedNode = pFollowedNode;
if (rect.equals(CCRectZero))
{
m_bBoundarySet = false;
}
else
{
m_bBoundarySet = true;
}
m_bBoundaryFullyCovered = false;
CCSize winSize = CCDirector::sharedDirector()->getWinSize();
m_obFullScreenSize = CCPointMake(winSize.width, winSize.height);
//m_obHalfScreenSize = ccpMult(m_obFullScreenSize, 0.5f);
m_obHalfScreenSize = CCPointMake(m_obFullScreenSize.x/2 + RUNNER_FOLLOW_OFFSET_X,
m_obFullScreenSize.y/2 + RUNNER_FOLLOW_OFFSET_Y);
if (m_bBoundarySet)
{
m_fLeftBoundary = -((rect.origin.x+rect.size.width) - m_obFullScreenSize.x);
m_fRightBoundary = -rect.origin.x ;
m_fTopBoundary = -rect.origin.y;
m_fBottomBoundary = -((rect.origin.y+rect.size.height) - m_obFullScreenSize.y);
if(m_fRightBoundary < m_fLeftBoundary)
{
// screen width is larger than world's boundary width
//set both in the middle of the world
m_fRightBoundary = m_fLeftBoundary = (m_fLeftBoundary + m_fRightBoundary) / 2;
}
if(m_fTopBoundary < m_fBottomBoundary)
{
// screen width is larger than world's boundary width
//set both in the middle of the world
m_fTopBoundary = m_fBottomBoundary = (m_fTopBoundary + m_fBottomBoundary) / 2;
}
if( (m_fTopBoundary == m_fBottomBoundary) && (m_fLeftBoundary == m_fRightBoundary) )
{
m_bBoundaryFullyCovered = true;
}
}
return true;
}
void FollowWithOffset::step(float dt)
{
CC_UNUSED_PARAM(dt);
if(m_bBoundarySet){
// whole map fits inside a single screen, no need to modify the position - unless map boundaries are increased
if(m_bBoundaryFullyCovered)
return;
CCPoint tempPos = ccpSub( m_obHalfScreenSize, m_pobFollowedNode->getPosition());
m_pTarget->setPosition(ccp(clampf(tempPos.x, m_fLeftBoundary, m_fRightBoundary),
clampf(tempPos.y, m_fBottomBoundary, m_fTopBoundary)));
}
else{
//custom written code to add in support for a smooth ccfollow action
CCPoint tempPos = ccpSub( m_obHalfScreenSize, m_pobFollowedNode->getPosition());
CCPoint moveVect = ccpMult(ccpSub(tempPos,m_pTarget->getPosition()),0.25); //0.25 is the smooth constant.
CCPoint newPos = ccpAdd(m_pTarget->getPosition(), moveVect);
m_pTarget->setPosition(newPos);
}
}
I've got a CCSprite with three animations: idle, walk and attack. I want to switch between idle and walk depending on whether or not the sprite is moving (if the joystick is beeing used). All of this works great.
For the attacking animation, I want it to run once, and then return to the previous animation when done (ex.: idle) how do I detect when the animation is done?
thanks,
Dave
Alright, so here's what i've done, and it works, although I have no clue if its the right or the best way:
1) store the current animation.
2) If the currentAnimation is attacking, do nothing.
3) when switching between animations, if the new animation is attacking, run a sequence on the sprite, the second action being a callback to a "onDoneAttacking"
4) in the callback, change the current animation
But this isn't veery smooth and it doesn't allow to attack very fast.
Here's what it looks like:
-(void) changeAnimation:(NSString*)name forTime:(int) times {
if(currentAnimation != #"attack" )
{
CCFiniteTimeAction *action = [CCAnimate actionWithAnimation:[self animationByName:name]];
CCRepeat *repeatAction = [CCRepeat actionWithAction:action times:1];
if(name == #"attack") {
id doneAttacking = [CCCallFunc actionWithTarget:self selector:#selector(onDoneAttacking)];
[self runAction:[CCSequence actionOne:repeatAction two:doneAttacking]];
}
else {
[self runAction:repeatAction];
}
currentAnimation = name;
}
}
-(void) onDoneAttacking {
currentAnimation = #"idle";
}